Skip to content

Commit

Permalink
Update EIP-4762: reworked gas schedule from interop
Browse files Browse the repository at this point in the history
Merged by EIP-Bot.
  • Loading branch information
gballet authored Jun 27, 2024
1 parent 4a18d8b commit 9590d79
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 76 deletions.
120 changes: 64 additions & 56 deletions EIPS/eip-4762.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -174,36 +164,31 @@ 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

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
Expand All @@ -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:

Expand All @@ -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:
Expand All @@ -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
Expand Down
40 changes: 20 additions & 20 deletions EIPS/eip-6800.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 |
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down

0 comments on commit 9590d79

Please sign in to comment.