-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Skinny CREATE2 #1014
Skinny CREATE2 #1014
Conversation
I am extremely in support of this. We NEED deterministic, immutable addresses for so many applications (state channels plus offline multisig plus a ton more). |
This EIP allows for a significant performance increase in state channels by removing the need for an additional contract to allow for counterfactual addressing. I'm highly in favour of accepting it as soon as possible. :) |
I am in complete support of this, there are countless governance use-cases which need this to be efficient and successful. Hurray! |
EIPS/Skinny_CREATE2.md
Outdated
|
||
### Specification | ||
|
||
Adds a new opcode at 0xf5, which takes 4 stack arguments: endowment, memory_start, memory_length, salt. Behaves identically to CREATE, except using `sha3(msg.sender ++ salt ++ init_code)[12:]` instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vbuterin The salt can have any arbitrary length?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Existing scheme looks like this for low nonces (nonce 1 below):
sha3(0xd6 ++ 0x94 ++ sender ++ 0x01)[12:]
So if you mine an address starting with d694
, it seems possible to create destination collisions. Using larger nonces give more room for collisions.
This means that you could say "look, this contract can only be create2
:ed with the initcode x
. But in fact, you can create arbitrary contracts there using old-style create
.
I may be wrong, thinking while writing here... A trivial way to get around this would be to prefix the entire thing with something that is invalid rlp
.
And @LefterisJP @vbuterin I assume the salt
is fixed-size, and the size of that would naturally affect the ability to do the attack described here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vbuterin The salt can have any arbitrary length?
It's a stack argument, hence 32 bytes.
A trivial way to get around this would be to prefix the entire thing with something that is invalid rlp
If we want, we can prefix with 0xff; the only valid RLP that starts with 0xff would be petaby long.
EIPS/Skinny_CREATE2.md
Outdated
@@ -0,0 +1,16 @@ | |||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please update this to the new format: frontmatter should start and end with ---
on its own line, and keys are lower-case.
EIPS/Skinny_CREATE2.md
Outdated
@@ -0,0 +1,16 @@ | |||
``` | |||
EIP: <to be assigned> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please number this 1014 and rename the file to eip-1014.md.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
0xff would work, but 0x01 would be not even theoretically possible to collide (on the preimage side)
EIPS/Skinny_CREATE2.md
Outdated
EIP: <to be assigned> | ||
Title: Skinny CREATE2 | ||
Author: Vitalik Buterin | ||
Category: Core |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should specify Type: Standards Track
, as well.
EIPS/Skinny_CREATE2.md
Outdated
``` | ||
EIP: <to be assigned> | ||
Title: Skinny CREATE2 | ||
Author: Vitalik Buterin |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please include a username or email address (parentheses for Github username) or .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol. @vbuterin please follow protocol around here... just because you created Ethereum doesn't mean you get to break EIP specification.
EIPS/eip-1014.md
Outdated
--- | ||
eip: 1014 | ||
title: Skinny CREATE2 | ||
author: Vitalik Buterin (vbuterin) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GitHub username is recognized when adding the @ in front of it. Like '@vbuterin'
Make state channels great again👍🏽 |
Needs a discussions-to URL, but otherwise good to go. |
Why didn't we have this from the beginning, I'm so confused. It seems so obvious now.
…Sent from my iPhone
On Apr 22, 2018, at 3:03 AM, Nick Johnson ***@***.***> wrote:
Needs a discussions-to URL, but otherwise good to go.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
|
What happens on address collisions? How exactly is an address collision defined (existing code, existing balance, pre-existing code, pre-existing balance, etc.)? Also, in which way is this different from the earlier proposal about create2? |
@karalabe Has a good point here: ethereum/pm#44 @emansipater @snario Will state channel mechanisms be able to detect if the code of counterfactual contract will behave differently depending on the environment? Because currently contracts can do anything in their constructor, which is the code that runs during the instantiation. (Copying his comment below). Regarding CREATE2, do we have any restriction on the execution context, or it remains the same? The reason I'm asking is because the EIP states: Allows interactions to be made with addresses that do not exist yet on-chain but can be relied on to only possibly eventually contain code that has been created by a particular piece of init code. Alternatively we could enforce CREATE2 to not have access to environmentals, but that might be an ugly complication. Just food for thought. |
@chriseth As far as I understand, now "msg.sender" is kind of in full control of the contract address. And I assume that CREATE2 will only create contract if it does not exist (so not to break the invariant of contract code not changing after initial deployment). In the state channel settings, possibility of doing CREATE2 is a leverage that participants use against each other. So they will not compromise their leverage by producing an address collision. |
Chiming in because @lrettig let me know this discussion was taking place. I'm not sure how L4 plan on doing "counterfactual" in practice, but we've found that deploying a new contract for each individual dispute would be pretty expensive, especially if the contracts are complex (e.g. @funfair-tech casino games). Instead, we think it makes more sense to reuse contracts already deployed onchain for disputes. Maybe I'm missing something, but this seems like a bit of a distraction. @emansipater @snario @SilentCicero could you please expand on why this is valuable—are you assuming contract deployment on every dispute? What other use cases does this enable/optimize? cc @ConnextProject @nginnever |
Interested to learn more about tradeoffs here too! FYI In our construction, we're working towards a dispute registry with predeployed dispute contracts. When opening a "thread" (virtual channel), participants can sign a hash associated with the specific dispute they want to reference. At the very least this means that participants around a specific use-case don't need to deploy duplicate contracts for byzantine cases and ideally this also means that we can have community-sourced standard disputes for various use-cases. This also removes the need for deterministic addressing I think? |
Few points to talk about here:
|
Am I correct in comparing this to p2sh (Pay to script hash) like functionality? Where value can be allocated to a specific script hash instead of the full script? |
Yes, I think it's a good comparison. |
Either way the code of the deployed contract has to be verified, which is out of scope for the hardware wallet. I don't see how using a factory contract makes this any worse. |
@Arachnid Let's say the hardware wallet is built to work with certain known wallets, such as Gnosis (the same works if you register the code hash into the hardware wallet later, and the HW shows this hash in the display for you to check). |
As @vbuterin still hasn't reviewed my proposed change to this proposal, I will try to emphasize more the benefits of using sha3(init_code) instead of just init_code. In the future Ethereum might want to do parallel transaction processing. Check for example https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP04.md For example, our RSK's RSKIP59 proposal won't be needed anymore: Think of an ERC20 contract that, depending on the source and destination address of a transfer(), calls two per-user child-contracts (where the EIP-1024 nonce is the src/dst address) that subtract and increment child contract storage cells where per-user balances are stored. Even without taking into account parallelization, I'm sure there are many more examples where dynamically computing the destination address is highly more efficient than getting it from a mapping. (It could be even better, to hash sha3(sha3(msg.sender ++ sha3(init_code)) ++ salt), so that it requires even less gas to dynamically compute the child contract address. But this is obviously too complicated for so little benefit. And also there is the problem of size collision with other types of addresses ) |
@SergioDemianLerner oh we've already decided to use the sha3 of the initcode, the EIP hasn't been updated yet. (decided on a coredev-call a few weeks ago, and I posted a comment here to that effect) |
I'll submit a PR next week to update this accordingly |
I'm ok with |
@vbuterin please see #1014 (comment) . Thanks for updating, but you forgot the 0xFF |
Since msg.sender, init_code, salt are all stack items what happens if I try to deploy a contract twice? What if I selfdestruct a contract and then recreate it? It will be possible to use the same address since it can be regenerated? EDIT: What happens to the constructor if I recreate an already deployed contract? Does it re-run twice? (If it actually gets deployed I assume the constructor indeed runs twice) |
@MoonMissionControl I suppose that without any other change in the EVM, a SELFDESTRUCT will take precedence and the contract will be destructed at the end of the processing of the transaction. Regarding multiple creations, I think that is a real problem and is similar to the problem where there is a previous balance on an account which then turns into a contract. If this is not enforced by the EVM, then a way to prevent this at the application level would be to set a storage cell "initialized" to true just after the constructor finishes and check for this in the first line of the constructor { if (initialized) revert(); }. |
Collision cause deployment to fail. Collision occurs if nonce or code is nonzero. Since nonce is set to 1 at creation (nowadays), even empty create can't be overwritten later. Since selfdestruct takes effect post-tx, there can be no double-create during one tx. |
So basically, that is already the case |
It would be very informative if the EIP states it. |
Yes, it should have a reference to eip 684 (iirc) which defines the collision behavior. |
Could we have 4-5 (or at least one) example cases for the hash creation in the EIP? |
|
||
#### Option 2 | ||
|
||
Use `sha3(0xff ++ msg.sender ++ salt ++ init_code)[12:]` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading from the comments it's:
sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:]
instead of
sha3(0xff ++ msg.sender ++ salt ++ init_code)[12:]
so with the hash value sha3(init_code)
and not the code itself. Am I correct on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please see #1375 . But yes, the init_code
, not the code itself
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thanks!
This is looking good for Nimbus use cases, with reasonable design tradeoffs. |
This is still listed as Draft, and should move through Last Call and Accepted if it's supposed to be in Constantinople. |
Adds a new opcode at 0xf5, which takes 4 stack arguments: endowment, memory_start, memory_length, salt. Behaves identically to CREATE, except using
sha3(msg.sender ++ salt ++ init_code)[12:]
instead of the usual sender-and-nonce-hash as the address the contract is created.Update 2018.09.02: Version 2: use
sha3(msg.sender ++ salt ++ sha3(init_code))[12:]