Skip to content
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

Update EIP-4762: reworked gas schedule from interop #8550

Merged
merged 15 commits into from
Jun 27, 2024
92 changes: 39 additions & 53 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,43 @@

#### 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`, `CALLCODE`, `DELEGATECALL`, `STATICALL`, `AUTHCALL`, `SELFDESTRUCT`, `EXTCODESIZE`, or `EXTCODECOPY` opcode,
gballet marked this conversation as resolved.
Show resolved Hide resolved
2. a non-precompile address is the target address of a contract creation whose initcode starts execution,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3. any address is the target of the `BALANCE` opcode
4. a _deployed_ contract calls `CODECOPY`
gballet marked this conversation as resolved.
Show resolved Hide resolved

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:
gballet marked this conversation as resolved.
Show resolved Hide resolved

```
(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:
If a `*CALL` or `SELFDESTRUCT` is value-bearing (ie. it transfers nonzero wei), whether or not the callee is a precompile, process these additional two access events:

```
(contract_address, 0, VERSION_LEAF_KEY)
(contract_address, 0, NONCE_LEAF_KEY)
(contract_address, 0, BALANCE_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
(contract_address, 0, CODE_KECCAK_LEAF_KEY)
(contract_address, 0, CODE_SIZE_LEAF_KEY)
(caller_address, 0, BASIC_DATA_LEAF_KEY)
(callee_address, 0, BASIC_DATA_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
```

If the `BALANCE` opcode is called targeting some address, process this access event:

When calling `EXTCODEHASH`, process the access event:
gballet marked this conversation as resolved.
Show resolved Hide resolved
```

Check failure on line 63 in EIPS/eip-4762.md

View workflow job for this annotation

GitHub Actions / Markdown Linter

Fenced code blocks should be surrounded by blank lines [Context: "```"]

EIPS/eip-4762.md:63 MD031/blanks-around-fences Fenced code blocks should be surrounded by blank lines [Context: "```"]
(address, 0, BALANCE_LEAF_KEY)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we also touch the VERSION thus BASIC_DATA_LEAF_KEY?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: add version

(address, 0, CODE_HASH_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
gballet marked this conversation as resolved.
Show resolved Hide resolved
```

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:
When a contract is created, process these access events:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


```
(caller_address, 0, BALANCE_LEAF_KEY)
(target_address, 0, BALANCE_LEAF_KEY)
(contract_address, 0, BASIC_DATA_LEAF_KEY)
(contract_address, 0, CODEHASH_LEAF_KEY)
```

If the `EXTCODEHASH` opcode is called targeting some address, process an access event of the form:
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:

```
(address, 0, CODEHASH_LEAF_KEY)
(caller_address, 0, BASIC_DATA_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
(target_address, 0, BASIC_DATA_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
gballet marked this conversation as resolved.
Show resolved Hide resolved
```

#### Access events for storage
Expand Down Expand Up @@ -123,31 +119,21 @@
When a nonzero-balance-sending `CALL` or `SELFDESTRUCT` with a given sender and recipient takes place, process these write events:
gballet marked this conversation as resolved.
Show resolved Hide resolved

```
(sender, 0, BALANCE_LEAF_KEY)
(recipient, 0, BALANCE_LEAF_KEY)
(sender, 0, BASIC_DATA_LEAF_KEY)
(recipient, 0, BASIC_DATA_LEAF_KEY)
```

When a contract creation is initialized, process these write events:

```
(contract_address, 0, VERSION_LEAF_KEY)
(contract_address, 0, NONCE_LEAF_KEY)
```

Only if the value sent with the creation is nonzero, also process:

```
(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, BASIC_DATA_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
(contract_address, 0, CODEHASH_LEAF_KEY)
```

#### Write events for storage
Expand Down Expand Up @@ -181,29 +167,22 @@
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)
Comment on lines +176 to +177
Copy link
Contributor

@jsign jsign Jun 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Edit: comment quoting code is not correct, I meant L173 (tx.target, 0, BASIC_DATA_LEAF_KEY)]

If we have a tx (non-value-bearing) targeting a precompile or system contract, we don't need to touch BASIC_DATA. (i.e: stateless client knows the code-size)

We can still argue that this rule should be avoided to avoid a border case. But considering we didn't do any similar simplification for precompiles/system contracts in other places in the EIP (i.e. we avoid adding in the witness for them as much as possible), then maybe not doing it here is actually adding a border case (we have to remember this is an exception), not removing it.

No strong opinions, just surfacing this.
cc @gballet @g11tech @gabrocheleau @tanishqjasoria @matkt

(tx.target, 0, BASIC_DATA_LEAF_KEY)
gballet marked this conversation as resolved.
Show resolved Hide resolved
(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:
gballet marked this conversation as resolved.
Show resolved Hide resolved

```
(tx.origin, 0, BALANCE_LEAF_KEY)
(tx.target, 0, BALANCE_LEAF_KEY)
(tx.target, 0, BASIC_DATA_LEAF_KEY)
```

### Witness gas costs
Expand All @@ -223,8 +202,8 @@
|`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|
gballet marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't add this comment in the intended line because there wasn't a change there.
I'm referring to lines L218-L220 and L226.

The intention in both places to say "skip it" is for gas cost charging. But the thing being skipped is also adding it to the underlying access list that are used for the witness creation. If those things also skip adding them to the list, then I think the witness wouldn't be correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but the adding of stuff in the access list is done in previous sections, whereas this is specific to the charging of costs.


When executing a transaction, maintain four sets:

Expand All @@ -251,6 +230,13 @@

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.
gballet marked this conversation as resolved.
Show resolved Hide resolved

`CREATE*` and `*CALL` reserve 1/64th of the gas before the nested execution. Note that, following the behavior of access lists, the 1/64th of the gas is subtracted:

* **BEFORE** charging the witness costs when performing a `CALL`, `CODECALL`, `DELEGATECALL` or`STATICCALL`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to use *CALL to also contemplate AUTHCALL? (Also note a missing space after or)

* **AFTER** charging th witness costs when performing a `CREATE` or `CREATE2`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we also clarify that the contract creation complete gas cost should be charged before adding the 1/64 gas after the creation is completed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* **AFTER** charging th witness costs when performing a `CREATE` or `CREATE2`
* **AFTER** 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 Down
34 changes: 16 additions & 18 deletions EIPS/eip-6800.md
Original file line number Diff line number Diff line change
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 |
| BASIC_DATA_LEAF_KEY | 0 |
| CODE_KECCAK_LEAF_KEY | 3 |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we update CODE_KECCAK_LEAF_KEY to 1 instead of leaving 1 and 2 empty?

gballet marked this conversation as resolved.
Show resolved Hide resolved
| CODE_SIZE_LEAF_KEY | 4 |
| HEADER_STORAGE_OFFSET | 64 |
| CODE_OFFSET | 128 |
| VERKLE_NODE_WIDTH | 256 |
Expand Down Expand Up @@ -157,25 +154,26 @@ 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`:
gballet marked this conversation as resolved.
Show resolved Hide resolved

| Name | Offset | Size |
| ----------- | ------ | ---- |
| `version` | 0 | 1 |
| `nonce` | 4 | 8 |
| `code_size` | 12 | 4 |
| `balance` | 16 | 16 |

Bytes `1..3` are reserved for future use.

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.
gballet marked this conversation as resolved.
Show resolved Hide resolved

#### Code

Expand Down Expand Up @@ -239,7 +237,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
Loading