mirror of https://github.com/status-im/EIPs.git
New design for EIP-1702
This commit is contained in:
parent
54a1eb3fdc
commit
5b57472484
108
EIPS/eip-1702.md
108
EIPS/eip-1702.md
|
@ -11,57 +11,119 @@ created: 2017-12-30
|
|||
|
||||
## Abstract
|
||||
|
||||
This defines a method of hard forking while maintaining the exact functionality of existing account by allowing multiple versions of the virtual machines to execute in the same block. This is also useful to define future account state structures when we introduce the on-chain WebAssembly virtual machine.
|
||||
This defines a method of hard forking while maintaining the exact
|
||||
functionality of existing account by allowing multiple versions of the
|
||||
virtual machines to execute in the same block. This is also useful to
|
||||
define future account state structures when we introduce the on-chain
|
||||
WebAssembly virtual machine.
|
||||
|
||||
## Motivation
|
||||
|
||||
By allowing account versioning, we can execute different virtual machine for contracts created at different times. This allows breaking features to be implemented while making sure existing contracts work as expected.
|
||||
By allowing account versioning, we can execute different virtual
|
||||
machine for contracts created at different times. This allows breaking
|
||||
features to be implemented while making sure existing contracts work
|
||||
as expected.
|
||||
|
||||
Note that this specification might not apply to all hard forks. We have emergency hard forks in the past due to network attacks. Whether they should maintain existing account compatibility should be evaluated in individual basis. If the attack can only be executed once against some particular contracts, then the scheme defined here might still be applicable. Otherwise, having a plain emergency hard fork might still be a good idea.
|
||||
Note that this specification might not apply to all hard forks. We
|
||||
have emergency hard forks in the past due to network attacks. Whether
|
||||
they should maintain existing account compatibility should be
|
||||
evaluated in individual basis. If the attack can only be executed once
|
||||
against some particular contracts, then the scheme defined here might
|
||||
still be applicable. Otherwise, having a plain emergency hard fork
|
||||
might still be a good idea.
|
||||
|
||||
## Specification
|
||||
|
||||
### Account State
|
||||
|
||||
After the first hard fork using this scheme, newly created account state stored in the world state trie is changed to become a five-item RLP encoding: `nonce`, `balance`, `storageRoot`, `codeHash` and `version`. The `version` field defines that when a contract call transaction or `CALL` opcode is executed against this contract, which version of the virtual machine should be used. Four-item RLP encoding account state are considered to have the `version` 0.
|
||||
Re-define account state stored in the world state trie to have 5
|
||||
items: `nonce`, `balance`, `storageRoot`, `codeHash`, and
|
||||
`version`. The newly added field `version` is a 256-bit integer. When
|
||||
`version` is zero, the account is RLP-encoded with the first 4
|
||||
items. When `version` is not zero, the account is RLP-encoded with 5
|
||||
items.
|
||||
|
||||
`CREATE`/`CREATE2` opcode, the contract creation transaction, and a normal call which initialize a new account, would only deploy accounts of the newest version.
|
||||
### Contract Deployment
|
||||
|
||||
The behavior of `CALLCODE` and `DELEGATECALL` are not affected by the hard fork -- they would fetch the contract code (even if the contract is deployed in a newer version) and still use the virtual machine version defined in the current contract (or in the case of within the input of contract creation transaction or `CREATE` opcode, the newest virtual machine version) to execute the code.
|
||||
In Ethereum, a contract has a deployment method, either by a contract
|
||||
creation transaction, or by another contract. If we regard this
|
||||
deployment method a contract's *parent*, then we find them forming a
|
||||
family of contracts, with the *root* being a contract creation
|
||||
transaction.
|
||||
|
||||
If a message call transaction creates a new account, the newly created account will have the newest account version number in the network.
|
||||
We let a family of contracts to always have the same `version`. That
|
||||
is, `CREATE` and `CREATE2` will always deploy contract that has the
|
||||
same `version` as the calling `address`.
|
||||
|
||||
Precompiled contracts, once created, use the given account version. If the account does not exist yet, newest version of the VM is used (as in the standard message call transaction). This is made so that VMs do not need full permission of the state trie but only with in the smart contract boundary. It is expected that once a precompiled contract is created, its behavior will not change.
|
||||
### Validation
|
||||
|
||||
### Gas Boundary
|
||||
A new phrase, *validation* is added to contract deployment (by
|
||||
`CREATE` / `CREATE2` opcodes, or by contract creation
|
||||
transaction). When `version` is `0`, the phrase does nothing and
|
||||
always succeeds. Future VM versions can define additional validation
|
||||
that has to be passed.
|
||||
|
||||
With the boundary between the VM and the blockchain, we don't consider there're additional gas cost involved. VM used defines the gas table applied. As examples, intrinsic gas only applies to actual transactions so only the newest ones are used. `CALL` and `CREATE` will use the old gas cost as the opcode gas cost, and once switched to the new VM, use the new gas cost from there.
|
||||
If the validation phrase fails, deployment does not proceed and return
|
||||
out-of-gas.
|
||||
|
||||
## Example
|
||||
### Contract Execution
|
||||
|
||||
Consider we would like to have the REVERT opcode hard fork in Ethereum Classic using this scheme. After the hard fork, we have:
|
||||
VM version used in contract execution is determined via calling
|
||||
`address` (`I_a` in yellow paper). Precompiled contract does not have
|
||||
version.
|
||||
|
||||
* Existing accounts are still of four-item RLP encoding. When a transaction has `to` field pointing to them, they're executed using version 0 of EVM. REVERT is the same as INVALID and consumes all the gases.
|
||||
* A new contract creation transaction is executed using version 1 virtual machine, and would only create version 1 account on the blockchain. When executing them, it uses version 1 of EVM and REVERT uses the new behavior.
|
||||
* When a version 0 account issues a CALL to version 1 account, sub-execution of the version 1 account uses the version 1 virtual machine.
|
||||
* When a version 1 account issues a CALL to version 0 account, sub-execution of the version 0 account uses the version 0 vritual machine.
|
||||
* When a version 0 account issues a CREATE, it always uses the newest version of the virtual machine, so it only creates version 1 new accounts.
|
||||
### Contract Creation Transaction
|
||||
|
||||
Define `LATEST_VERSION` in a hard fork to be the latest supported VM
|
||||
version. A contract creation transaction is always executed in
|
||||
`LATEST_VERSION`. Before a contract creation transaction is executed,
|
||||
run *validation* on the contract creation code. If it does not pass,
|
||||
return out-of-gas.
|
||||
|
||||
#### Alternative Design for Contract Creation Transaction
|
||||
|
||||
This provides an alternative design that allows contract to be created
|
||||
in multiple versions.
|
||||
|
||||
Add an additional field `version` (256-bit integer) in contract
|
||||
creation transaction. So it becomes `nonce`, `gasprice`, `startgas`,
|
||||
`to`, `value`, `data`, `v`, `r`, `s`, `version`. When signing or
|
||||
recovering, sign ten items, with `v`, `r`, `s` as defined by EIP-155.
|
||||
|
||||
The transaction would be executed in `version` supplied. If `version`
|
||||
is not supported or *validation* does not pass, return out-of-gas.
|
||||
|
||||
## Discussions
|
||||
|
||||
### Performance
|
||||
|
||||
Currently nearly all full node implementations uses config parameters to decide which virtual machine version to use. Switching vitual machine version is simply an operation that changes a pointer using a different set of config parameters. As a result, this scheme has nearly zero impact to performance.
|
||||
Currently nearly all full node implementations uses config parameters
|
||||
to decide which virtual machine version to use. Switching vitual
|
||||
machine version is simply an operation that changes a pointer using a
|
||||
different set of config parameters. As a result, this scheme has
|
||||
nearly zero impact to performance.
|
||||
|
||||
### Smart Contract Boundary and Formal Verification
|
||||
|
||||
Many current efforts are on-going for getting smart contracts formally verified. However, for any hard fork that introduces new opcodes or change behaviors of existing opcodes would break the verification of an existing contract has previously be formally verified. Using the scheme described here, we define the boundary of how a smart contract interacts with the blockchain and it might help the formal verification efforts:
|
||||
Many current efforts are on-going for getting smart contracts formally
|
||||
verified. However, for any hard fork that introduces new opcodes or
|
||||
change behaviors of existing opcodes would break the verification of
|
||||
an existing contract has previously be formally verified. Using the
|
||||
scheme described here, we define the boundary of how a smart contract
|
||||
interacts with the blockchain and it might help the formal
|
||||
verification efforts:
|
||||
|
||||
* A smart contract has only immutable access to information of blockchain account balances and codes.
|
||||
* A smart contract has only immutable access to information of
|
||||
blockchain account balances and codes.
|
||||
* A smart contract has only immutable access of block information.
|
||||
* A smart contract or a contract creation transaction can modify only its own storage and codes.
|
||||
* A smart contract can only interact with the blockchain in a mutable way using `CALL` or `CREATE`.
|
||||
* A smart contract or a contract creation transaction can modify only
|
||||
its own storage and codes.
|
||||
* A smart contract can only interact with the blockchain in a mutable
|
||||
way using `CALL` or `CREATE`.
|
||||
|
||||
### WebAssembly
|
||||
|
||||
This scheme can also be helpful when we deploy on-chain WebAssembly virtual machine. In that case, WASM contracts and EVM contracts can co-exist and the execution boundary and interaction model are clearly defined as above.
|
||||
This scheme can also be helpful when we deploy on-chain WebAssembly
|
||||
virtual machine. In that case, WASM contracts and EVM contracts can
|
||||
co-exist and the execution boundary and interaction model are clearly
|
||||
defined as above.
|
||||
|
|
Loading…
Reference in New Issue