So when bytecode is going onto the chain the header tells the client how to validate it, and when bytecode is off-chain the header tells tools how to handle it.
The new fields would be introduced “lazily”, i.e., the contracts that do not have the new field, are assumed pre-change. The old contracts would have 4 fields, whereas the new ones would have 5. This is my understanding
I see, but I think that’s rather up to each VM version to define how it wants to be handled. For the legacy VM version we cannot have any headers anyway, because otherwise it would be backward incompatible.
I updated EIP-1702 to include some of the above comments/suggestions: https://github.com/ethereum/EIPs/pull/1702/files
It think it is up to the VM, and using the same scheme as Wasm makes sense to me.
This looks good, thanks. Shall I go ahead and merge it?
The transaction would be executed in
is not supported or validation does not pass, return out-of-gas.
I think the
version needs to supplied by the VM during the validation phase.
I think that would still have the certification / validation issue. We may have innocent looking legacy code that just happen to have the header of a later VM. It would be better supply the
version through external methods (an extra field in contract creation transaction or account state), and then in validation phrase, check whether the
version provided in VM header matches.
How about this.
- New contract creation transactions will use the new version item.
- CREATE and CREATE2 will use the version from the caller’s state field or 0.
- Versions above 0 are validated, which returns the version to deploy.
- Validation may return a different version than it is given.
- The deployed version is stored in the contract state.
So the VM should not be handed legacy code to validate, but remains free to use it’s internal versioning system as it will. If the validator does not override the input version the effect is the same as for your deployment families.
Yeah sounds like a good idea! As long as we assert that all non-legacy versions must contain a version prefix, and legacy VM can only deploy legacy version, then certification works. This will also mean that we can just make contract creation transaction always use one single version which simplifies things that need to change at that part.
I added this in section “Contract Deployment” → “Alternative Design”.
I’m not convinced, that may have side-effects we’re not aware of. I think the conservative choice here would be to have the validator be an oracle, delivering
EDIT: maybe I misunderstood the quote. Did you mean that it may return different code, or different version bytes? I thought you meant code, that code would be mutated during the validation process.
No, just different version bytes. Otherwise it becomes difficult-to-impossible for older contracts, (say evm.1.5.1) to deploy newer code (say evm.1.5.2). That is, the version argument is saying, "I need to deploy a contract of at least level 1.5.1, and the validator says, “no problem, this code is level 1.5.2”.
Note that the version field in the state knows nothing about the semantics of the field or how the version is stored in the code–thats up to the VM. It just stores what the VM gives it and passes it back to the VM when asked.
I would suggest we pin the version. That is, if the version argument is saying “I need to deploy a contract of version 1.5.1”, then the validator either reject it, or say “okay, the code is version 1.5.1”.
I’d say it’s a feature that older contract cannot deploy newer version code. The code is fixed, so it won’t use any new features anyway. This also makes sure the semantic of the contract will not change. Otherwise we can have subtle backward compatibility issue.
We’ll at most have 1 or 2 new EVM versions per year. Plus supporting different versions of one VM type is easy (via feature flag) and has nearly no performance impact. So I don’t see much reason why we need to drop support for version 1.5.1 when 1.5.2 is added.
We can never drop any version of a VM.
So suppose a VM doesn’t put version numbers in the header, just validation rules in the VM that get stricter with each release. Then you’d expect newer code to go on validating by older rules unless it uses new features.
The use case I have in mind is where you have a contract that deploys code that it gets from elsewhere. It might not care that the code it deploys is the same version that it is, just that it be compatible, which the validator can tell it. It can also tell what is highest version it can validate as, which is what you would want to put in the state field.
This sounds more complicated than it is, but I’m too sleepy to be more clear.
Moving discussion of general versioning mechanism to EIP-1702: Generalized Account Versioning Scheme. Have put link in Draft and explanation.
To discuss here.
I’ve specified a version header of ‘\0evm\1\5\0\0’–semantic versioning–and that the
BEGINSUB for main immediately follows this header. So the bytecode is completely delimited into header, subroutines, and data, and the version of the bytecode is given by the header. The validator knows what rules apply, and can tell the client what version of the VM to use in the state field.
(The Wasm header is ‘\0asm\1’)
I think the current spec (newer section in “Alternative Design”) covers this. If a contract
A deploys code
B that it gets from elsewhere, the version prefix it gets is from
B. This means the code deployed will always deploy with the intended version of
B and does not care what version
A is running on.
I still suggest that we use version exactly specified, and do not go any higher. If
B has the version prefix that asks to use
evm 1.5.1, then we always use
evm 1.5.1 and never
evm 1.5.2. The use case I have in mind is that I want to make account versioning help us in avoiding bugs like EIP-1283 re-entry. Semantic versioning doesn’t help us much for this case – we thought EIP-1283 was backward compatible and I can easily imagine that if we used semantic versioning, we might have bumped only patch version for it. This will not be an issue if the version is pinned to exactly what is requested.
Sorry for the belated response. I was busy finding and am now busy preparing for a new job. (Yes, actually getting paid.)
I still think the flexibility I’m proposing for EIP-1702 is worth having @sorpaas How a particular VM uses that flexibility, if at all, is another question. Maybe no VM will or should ever need it, but I’m not convinced. Or maybe it would be easy enough to add later if it is needed, I don’t know. But with no EIP for eWasm to go by I don’t want to foreclose the possibilities. Maybe @axic can shed some light.
For EVM 1.5 I’m afraid that if a contract asks for valid 1.5.0 code then it will not be allowed to run 1.5.1 code. Or if it is allowed to run it, the state field will incorrectly say that it is 1.5.0 code-which would seem create a sort of race condition @holiman. But since 1.5.0 is the only version there will be at first, the question doesn’t really arise for this VM until there is a 1.5.1.
I think the main issue for this PR is just whether the proposed header is reasonable.
No, I wasn’t directly discussing this with eWasm team. But @axic if there’s anything I can help to make account versioning on eWasm a reality, I’m really happy to do!