diff --git a/EIPS/eip-4762.md b/EIPS/eip-4762.md index 6ebc7c5f7b0bc..7ba1a830d7266 100644 --- a/EIPS/eip-4762.md +++ b/EIPS/eip-4762.md @@ -2,7 +2,7 @@ eip: 4762 title: Statelessness gas cost changes description: Changes the gas schedule to reflect the costs of creating a witness by requiring clients update their database layout to match. -author: Guillaume Ballet (@gballet), Vitalik Buterin (@vbuterin), Dankrad Feist (@dankrad) +author: Guillaume Ballet (@gballet), Vitalik Buterin (@vbuterin), Dankrad Feist (@dankrad), Ignacio Hagopian (@jsign), Tanishq Jasoria (@tanishqjasoria), Gajinder Singh (@g11tech) discussions-to: https://ethereum-magicians.org/t/eip-4762-statelessness-gas-cost-changes/8714 status: Draft type: Standards Track @@ -39,47 +39,42 @@ We define access events as follows. When an access event takes place, the access #### Access events for account headers -When a non-precompile address is the target of a `CALL`, `CALLCODE`, `DELEGATECALL`, `SELFDESTRUCT`, `EXTCODESIZE`, or `EXTCODECOPY` opcode, or is the target address of a contract creation whose initcode starts execution, process these access events: +When: -``` -(address, 0, VERSION_LEAF_KEY) -(address, 0, CODE_SIZE_LEAF_KEY) -``` + 1. a non-precompile address is the target of a `*CALL`, `SELFDESTRUCT`, `EXTCODESIZE`, or `EXTCODECOPY` opcode, + 2. a non-precompile address is the target address of a contract creation whose initcode starts execution, + 3. any address is the target of the `BALANCE` opcode + 4. a _deployed_ contract calls `CODECOPY` -If a call is value-bearing (ie. it transfers nonzero wei), whether or not the callee is a precompile, process these two access events: +process this access events: ``` -(caller_address, 0, BALANCE_LEAF_KEY) -(callee_address, 0, BALANCE_LEAF_KEY) +(address, 0, BASIC_DATA_LEAF_KEY) ``` -When a contract is created, process these access events: - -``` -(contract_address, 0, VERSION_LEAF_KEY) -(contract_address, 0, NONCE_LEAF_KEY) -(contract_address, 0, BALANCE_LEAF_KEY) -(contract_address, 0, CODE_KECCAK_LEAF_KEY) -(contract_address, 0, CODE_SIZE_LEAF_KEY) -``` +Note: a non-value-bearing `SELFDESTRUCT` or `*CALL`, targetting a precompile, will not cause the `BASIC_DATA_LEAF_KEY` to be added to the witness. -If the `BALANCE` opcode is called targeting some address, process this access event: +If a `*CALL` or `SELFDESTRUCT` is value-bearing (ie. it transfers nonzero wei), whether or not the callee is a precompile, process this additional access event: ``` -(address, 0, BALANCE_LEAF_KEY) +(origin, 0, BASIC_DATA_LEAF_KEY) ``` -If the `SELFDESTRUCT` opcode is called by some caller_address targeting some target_address (regardless of whether it’s value-bearing or not), process access events of the form: +Note: when checking for the existence of the callee, the existence check is done by validating that there is an extension-and-suffix tree at the corresponding stem, and does not rely on `CODEHASH_LEAF_KEY`. + +When calling `EXTCODEHASH` on a non-precompile target, process the access event: ``` -(caller_address, 0, BALANCE_LEAF_KEY) -(target_address, 0, BALANCE_LEAF_KEY) +(address, 0, CODEHASH_LEAF_KEY) ``` -If the `EXTCODEHASH` opcode is called targeting some address, process an access event of the form: +Note that precompiles are excluded, as their hashes are known to the client. + +When a contract is created, process these access events: ``` -(address, 0, CODEHASH_LEAF_KEY) +(contract_address, 0, BASIC_DATA_LEAF_KEY) +(contract_address, 0, CODEHASH_LEAF_KEY) ``` #### Access events for storage @@ -120,34 +115,29 @@ We define **write events** as follows. Note that when a write takes place, an ac #### Write events for account headers -When a nonzero-balance-sending `CALL` or `SELFDESTRUCT` with a given sender and recipient takes place, process these write events: +When a nonzero-balance-sending `*CALL` or `SELFDESTRUCT` with a given sender and recipient takes place, process these write events: ``` -(sender, 0, BALANCE_LEAF_KEY) -(recipient, 0, BALANCE_LEAF_KEY) +(origin, 0, BASIC_DATA_LEAF_KEY) +(target, 0, BASIC_DATA_LEAF_KEY) ``` -When a contract creation is initialized, process these write events: +if no account exists at `callee_address`, also process: ``` -(contract_address, 0, VERSION_LEAF_KEY) -(contract_address, 0, NONCE_LEAF_KEY) +(target, 0, CODEHASH_LEAF_KEY) ``` -Only if the value sent with the creation is nonzero, also process: +When a contract creation is initialized, process these write events: ``` -(contract_address, 0, BALANCE_LEAF_KEY) +(contract_address, 0, BASIC_DATA_LEAF_KEY) ``` When a contract is created, process these write events: ``` -(contract_address, 0, VERSION_LEAF_KEY) -(contract_address, 0, NONCE_LEAF_KEY) -(contract_address, 0, BALANCE_LEAF_KEY) -(contract_address, 0, CODE_KECCAK_LEAF_KEY) -(contract_address, 0, CODE_SIZE_LEAF_KEY) +(contract_address, 0, CODEHASH_LEAF_KEY) ``` #### Write events for storage @@ -174,6 +164,8 @@ When a contract is created, process the write events: For `i` in `0 ... (len(code)+30)//31`. +Note: since no access list existed for code up until this EIP, note that no warm costs are charged for code accesses. + ### Transactions #### Access events @@ -181,29 +173,22 @@ For `i` in `0 ... (len(code)+30)//31`. For a transaction, make these access events: ``` -(tx.origin, 0, VERSION_LEAF_KEY) -(tx.origin, 0, BALANCE_LEAF_KEY) -(tx.origin, 0, NONCE_LEAF_KEY) -(tx.origin, 0, CODE_SIZE_LEAF_KEY) -(tx.origin, 0, CODE_KECCAK_LEAF_KEY) -(tx.target, 0, VERSION_LEAF_KEY) -(tx.target, 0, BALANCE_LEAF_KEY) -(tx.target, 0, NONCE_LEAF_KEY) -(tx.target, 0, CODE_SIZE_LEAF_KEY) -(tx.target, 0, CODE_KECCAK_LEAF_KEY) +(tx.origin, 0, BASIC_DATA_LEAF_KEY) +(tx.origin, 0, CODEHASH_LEAF_KEY) +(tx.target, 0, BASIC_DATA_LEAF_KEY) +(tx.target, 0, CODEHASH_LEAF_KEY) ``` #### Write events ``` -(tx.origin, 0, NONCE_LEAF_KEY) +(tx.origin, 0, BASIC_DATA_LEAF_KEY) ``` -if `value` is non-zero: +If `value` is non-zero: ``` -(tx.origin, 0, BALANCE_LEAF_KEY) -(tx.target, 0, BALANCE_LEAF_KEY) +(tx.target, 0, BASIC_DATA_LEAF_KEY) ``` ### Witness gas costs @@ -216,15 +201,15 @@ Remove the following gas costs: Reduce gas cost: - * `CREATE` to 1000 + * `CREATE`/`CREATE2` to 1000 |Constant |Value| |-|-| -|`WITNESS_BRANCH_COST` |1900| +|`WITNESS_BRANCH_COST`|1900| |`WITNESS_CHUNK_COST` |200| |`SUBTREE_EDIT_COST` |3000| -|`CHUNK_EDIT_COST` |500| -|`CHUNK_FILL_COST` |6200| +|`CHUNK_EDIT_COST` |500| +|`CHUNK_FILL_COST` |6200| When executing a transaction, maintain four sets: @@ -251,6 +236,13 @@ When a **write** event of `(address, sub_key, leaf_key)` occurs, perform the fol Note that tree keys can no longer be emptied: only the values `0...2**256-1` can be written to a tree key, and 0 is distinct from `None`. Once a tree key is changed from `None` to not-`None`, it can never go back to `None`. +Note that values should only be added to the witness if there is sufficient gas to cover their associated event costs. + +`CREATE*` and `*CALL` reserve 1/64th of the gas before the nested execution. In order to match the behavior of this charge with the pre-fork behavior of access lists: + + * this minimum 1/64th gas reservation is checked **AFTER** charging the witness costs when performing a `CALL`, `CODECALL`, `DELEGATECALL` or`STATICCALL` + * this 1/64th of the gas is subtracted **BEFORE** charging the witness costs when performing a `CREATE` or `CREATE2` + ### Replacement for access lists We replace [EIP-2930](./eip-2930.md) access lists with an SSZ structure of the form: @@ -268,6 +260,22 @@ class AccessSubtree(Container): elements: BitVector[256] ``` +### Block-level operations + +None of: + +* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call, +* The coinbase account +* Withdrawal accounts + +are warm at the start of a transaction. + +Note: When (and only when) calling a system contract _via a system call_, the code chunks and account should not appear in the witness. + +### Account abstraction + +TODO : still waiting on a final decision between 7702 and 3074 + ## Rationale ### Gas reform diff --git a/EIPS/eip-6800.md b/EIPS/eip-6800.md index d7c587c999609..9c3585682d373 100644 --- a/EIPS/eip-6800.md +++ b/EIPS/eip-6800.md @@ -2,7 +2,7 @@ eip: 6800 title: Ethereum state using a unified verkle tree description: This introduces a new Verkle state tree alongside the existing MPT. -author: Vitalik Buterin (@vbuterin), Dankrad Feist (@dankrad), Kevaundray Wedderburn (@kevaundray), Guillaume Ballet (@gballet), Piper Merriam (@pipermerriam), Gottfried Herold (@GottfriedHerold) +author: Vitalik Buterin (@vbuterin), Dankrad Feist (@dankrad), Kevaundray Wedderburn (@kevaundray), Guillaume Ballet (@gballet), Piper Merriam (@pipermerriam), Gottfried Herold (@GottfriedHerold), Ignacio Hagopian (@jsign), Tanishq Jasoria (@tanishqjasoria), Gajinder Singh (@g11tech), Danno Ferrin (@shemnon) discussions-to: https://ethereum-magicians.org/t/proposed-verkle-tree-scheme-for-ethereum-state/5805 status: Draft type: Standards Track @@ -115,11 +115,8 @@ Instead of a two-layer structure as in the Patricia tree, in the Verkle tree we | Parameter | Value | | --------------------- | ------- | -| VERSION_LEAF_KEY | 0 | -| BALANCE_LEAF_KEY | 1 | -| NONCE_LEAF_KEY | 2 | -| CODE_KECCAK_LEAF_KEY | 3 | -| CODE_SIZE_LEAF_KEY | 4 | +| BASIC_DATA_LEAF_KEY | 0 | +| CODE_KECCAK_LEAF_KEY | 1 | | HEADER_STORAGE_OFFSET | 64 | | CODE_OFFSET | 128 | | VERKLE_NODE_WIDTH | 256 | @@ -157,25 +154,28 @@ def get_tree_key(address: Address32, tree_index: int, sub_index: int): bytes([sub_index]) ) -def get_tree_key_for_version(address: Address32): - return get_tree_key(address, 0, VERSION_LEAF_KEY) - -def get_tree_key_for_balance(address: Address32): - return get_tree_key(address, 0, BALANCE_LEAF_KEY) - -def get_tree_key_for_nonce(address: Address32): - return get_tree_key(address, 0, NONCE_LEAF_KEY) +def get_tree_key_for_basic_data(address: Address32): + return get_tree_key(address, 0, BASIC_DATA_LEAF_KEY) # Backwards compatibility for EXTCODEHASH def get_tree_key_for_code_keccak(address: Address32): return get_tree_key(address, 0, CODE_KECCAK_LEAF_KEY) - -# Backwards compatibility for EXTCODESIZE -def get_tree_key_for_code_size(address: Address32): - return get_tree_key(address, 0, CODE_SIZE_LEAF_KEY) ``` -When any account header field is set, the `version` is also set to zero. The `code_keccak` and `code_size` fields are set upon contract creation. +An account's `version`, `balance`, `nonce` and `code_size` fields are packed in the value found at `BASIC_DATA_LEAF_KEY`: + +| Name | Offset | Size | +| ----------- | ------ | ---- | +| `version` | 0 | 1 | +| `code_size` | 5 | 3 | +| `nonce` | 8 | 8 | +| `balance` | 16 | 16 | + +Bytes `1..4` are reserved for future use. + +Note: the code size is stored on 3 bytes. To allow for an extension to 4 bytes without changing the account version is possible, reserved byte #4 should be allocated last. + +When any account header field is set, the `version` field is also set to zero. The `code_keccak` and `code_size` fields are set upon contract or EoA creation. #### Code @@ -239,7 +239,7 @@ Note that storage slots in the same size `VERKLE_NODE_WIDTH` range (ie. a range #### Fork -TODO - see specific EIP +Described in [EIP-7612](./eip-7612.md). #### Access events