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

Draft
wants to merge 10 commits into
base: master
Choose a base branch
from

Conversation

gballet
Copy link
Member

@gballet gballet commented May 13, 2024

@github-actions github-actions bot added c-update Modifies an existing proposal s-draft This EIP is a Draft t-core labels May 13, 2024
@eth-bot
Copy link
Collaborator

eth-bot commented May 13, 2024

✅ All reviewers have approved.

@eth-bot eth-bot changed the title reworked gas schedule from interop Update EIP-4762: reworked gas schedule from interop May 13, 2024
@github-actions github-actions bot added the w-ci Waiting on CI to pass label May 13, 2024
EIPS/eip-6800.md Outdated
| 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?

EIPS/eip-6800.md Outdated Show resolved Hide resolved
EIPS/eip-6800.md Outdated Show resolved Hide resolved
@gballet gballet changed the title Update EIP-4762: reworked gas schedule from interop Update EIP-4762/EIP-6800: reworked gas schedule from interop May 17, 2024
@eth-bot eth-bot changed the title Update EIP-4762/EIP-6800: reworked gas schedule from interop Update EIP-4762: reworked gas schedule from interop May 17, 2024
@github-actions github-actions bot added w-ci Waiting on CI to pass and removed w-ci Waiting on CI to pass labels May 17, 2024
```
(address, 0, BALANCE_LEAF_KEY)
(address, 0, CODE_HASH_LEAF_KEY)
Copy link
Contributor

@g11tech g11tech May 17, 2024

Choose a reason for hiding this comment

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

so we need to remove isEmpty check?
or we assume that if codehash witness is non null then it isn't empty? and for empty accounts it will come null

Q: are we writing the keccak(null) when EOA account is added to state for the first time?
(UPDATE: realized answer is that: a new EOA account will always have be a target of the tx and the tx accesses will add codehash access/data to the state)

so i guess based on the witness being null or not null we can decide the extcodehash is the provided one or 0

Copy link
Contributor

Choose a reason for hiding this comment

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

Lateral question: the consensus wasn't that we still would have to touch "VERSION" to be forward-compatible? If that's the case, we also need to add here BASIC_DATA_LEAF_KEY which can simplify all the questions above (since it comes with all the rest)?

@@ -268,6 +254,13 @@ class AccessSubtree(Container):
elements: BitVector[256]
```

## Block-level operations

* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call are considered warm.
Copy link
Contributor

Choose a reason for hiding this comment

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

just to reconfirm this is only for the system call?

also system call is:
i) system updates not related to a tx
ii) a precompile executing system call code (blockhash)

Copy link
Member Author

Choose a reason for hiding this comment

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

system calls, right now, are 2935 (post osaka), 4788 and 7002. whatever stuff they use that get accessed, should be considered warm.

I am actually close to reconsidering that, it's a special case.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to distinguish between system call and system update.

i) system update is the client book keeping i.e. not related to the tx, in 2935 for e.g. writing the parent hash of the current block before tx execution begins. exits collection from 7002 is also a system update in those terms that happen post tx execution. withdrawals is also a system update in that sense.

ii) system call is for e.g. BLOCKHASH doing the accesses via evm or directly.

I think you mean system update here to warm (so only those which happen before txs execution actually matter since only they can impact cost)

Copy link
Contributor

@jsign jsign May 24, 2024

Choose a reason for hiding this comment

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

Post-Osaka-2935 has a long history. I'm not sure accesses to that history via the system contract should be considered warm?

By "warm" we mean potentially adding it to the witness at a subsidized cost?

Copy link
Contributor

@jsign jsign May 24, 2024

Choose a reason for hiding this comment

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

@g11tech reg your last paragraph, system updates from my perspective doesn't make sense to say are cold or warm, since we can't charge anyone for that?

Copy link
Contributor

Choose a reason for hiding this comment

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

reg your last paragraph, system updates from my perspective doesn't make sense to say are cold or warm, since we can't charge anyone for that?

yes I mean whateever system updates access warms for the txs. With this logic only the last entry in the ring buffer would be warmed and others cold so not the rest 8191 hashes

## Block-level operations

* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call are considered warm.
* When (and only when) calling a system contract _via a system call_, the code chunks and account should not appear in the witness.
Copy link
Contributor

Choose a reason for hiding this comment

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

this implies that stateless clients need to maintain system contracts . Also there is an unresolved issue of stateless clients not knowing if the contract has been actually deployed or not.

we should simply declare that stateless clients should assume activated system contracts deployed.

Copy link
Member Author

Choose a reason for hiding this comment

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

this implies that stateless clients need to maintain system contracts

it does not: because there is no obligation to call the contract's EVM, you are free to write the storage slots directly without having a local copy of the code.

Also there is an unresolved issue of stateless clients not knowing if the contract has been actually deployed or not.

I also don't see why this would be true. System contract activation is part of the pectra fork, so it should assume that.

we should simply declare that stateless clients should assume activated system contracts deployed.

indeed. Or do you mean that it should be in the spec itself?

Copy link
Contributor

Choose a reason for hiding this comment

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

because there is no obligation to call the contract's EVM, you are free to write the storage slots directly without having a local copy of the code

for system contracts like 7002, even stateless focused clients like ethereumjs just does the EVM call to get the triggered exits contract to get the exits. But this isn't a deal breaker just something clients need to bundle in verkle.

System contract activation is part of the pectra fork

deployment is a manual exercise and not really part of client hardfork (that clients deploy this contract on forkblock which imo should have been a better mechanism to deploy the tx if not already deployed). I mean I already had done the mistake of not adding a contract in a local testnet and then debugging why things weren't working. So I would like things foolproof if possible. The problem could become acute as the number of such contracts grow.

indeed. Or do you mean that it should be in the spec itself?

yes a simple mention of this would clearup the "ruleset" for the stateless client.


* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call are considered warm.
* When (and only when) calling a system contract _via a system call_, the code chunks and account should not appear in the witness.
* The coinbase account is warmed before the block, and the whole account is accessed
Copy link
Contributor

@g11tech g11tech May 17, 2024

Choose a reason for hiding this comment

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

whole account = basic data + code hash? and 2929 warm cost if accessed in a tx?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes

Copy link
Member Author

Choose a reason for hiding this comment

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

this is because the coinbase might not exist, so to avoid a lot of issues, we decide to touch the whole account so that it's created if it doesn't exist already.

Copy link
Contributor

Choose a reason for hiding this comment

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

what if there is no tx that puts any value to it, and lets say there is no tips that get added to a non existent coinbase, then it should be 158 cleaned up in the end of block?

Copy link
Contributor

Choose a reason for hiding this comment

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

is warmed before the block

"before the block" is maybe confusing?

What about:

The coinbase account basic data and code hash is accessed before transaction execution, and considered warm for all txs.

```
(address, 0, BALANCE_LEAF_KEY)
(address, 0, CODE_HASH_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.

In 4762 we have mixed namings with CODE_HASH_LEAF_KEY and CODEHASH_LEAF_KEY.
And in 6800 we use CODE_KECCAK_LEAF_KEY.

I'd say to change everything to CODE_HASH_LEAF_KEY or CODEHASH_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.

I think the big deciding factor is: when ethereum completes its shift to sha256 as its primary hash function (or even moves to something more stark-friendly), would this still be the keccak, or would it change (even if for new contracts or EOF only)? If still keccak, then call it CODE_KECCAK, if not, call it CODE_HASH.

(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,
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.

```

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.

EIPS/eip-4762.md Outdated
`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`
* **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.

@@ -268,6 +254,13 @@ class AccessSubtree(Container):
elements: BitVector[256]
```

## Block-level operations

* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call are considered warm.

Choose a reason for hiding this comment

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

should we add that the code chunks during system calls are not to be warmed? or it might cause additional confusion?

Copy link
Contributor

Choose a reason for hiding this comment

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

system calls totally ignore code chunks imo both for accesses and gas compute and we can clearly mention it to remove confusion

* Precompile accounts, system contract accounts and slots of a system contract that are accessed during a system call are considered warm.
* When (and only when) calling a system contract _via a system call_, the code chunks and account should not appear in the witness.
* The coinbase account is warmed before the block, and the whole account is accessed
* Withdrawals are cold, but are added to the witness at no cost if they are the target of a transaction.

Choose a reason for hiding this comment

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

we should add the clarification about storage cells here.
If in a trasnaction, storage value is set and then reset to zero, we should insert zero to the tree and not leave it empty because the user paid the gas cost.
Basically if we charge CHUNK_FILL_COST, fill the chunk value.

Copy link
Contributor

Choose a reason for hiding this comment

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

lateral question/observation to the above:

this is just because withdrawals are processed at the end of the block, and there is no actual cost charged to the coinbase for processing them?

Copy link
Contributor

@jsign jsign May 24, 2024

Choose a reason for hiding this comment

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

I raised a similar confusion yesterday to Guillaume about this line.

but are added to the witness at no cost ...

seems to imply there're a case where they're added at a cost; but who is paying that cost?

If the idea is that withdrawals never pay a cost, from my perspective clarifying they're "cold" (as mentioned in the first words in the sentence) is confusing.

EIPS/eip-4762.md Outdated Show resolved Hide resolved

```
(address, 0, CODEHASH_LEAF_KEY)
(caller_address, 0, BASIC_DATA_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.

If this rule applies if it's value-bearing or not, and for all cases (i.e: including precompiles), I think we might be able to remove SELFDESTRUCT from this rule?

Comment on lines +77 to +78
(caller_address, 0, BASIC_DATA_LEAF_KEY)
(target_address, 0, BASIC_DATA_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.

So, isn't this L74-L78 rule more general than this one for SELFDESTRUCT?

If that's the case, we could remove SELFDESTRUCT mentioned in that linked rule, and only leave this L74-L78?

Copy link
Contributor

@jsign jsign May 17, 2024

Choose a reason for hiding this comment

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

I'm starting to feel if wouldn't be easier for everyone to simply list rules for each independent instruction. Like *CALL, SELFDESTRUCT, etc, instead of trying to coalesce overlaps and re-clarify later with further rules some accessed extensions.

Yes, separating rules by instructions might have some redundancy but for implementors and testing it will be entirely clear what to do for each instruction. Now you have to read the whole document to see if in an extra scenario the same instruction you're interested in has another rule (i.e: value bearing? is or isn't precompile? etc).

cc @gballet @g11tech @tanishqjasoria

Choose a reason for hiding this comment

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

yes, i kind of agree with this. Listing every opCode seperately will be a better idea.
Right now its much easier to miss something.

Copy link
Contributor

@g11tech g11tech May 21, 2024

Choose a reason for hiding this comment

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

in EIP its good to be concise, in the execution specs we should do independently (or have some assets attached)

@@ -123,31 +119,21 @@ We define **write events** as follows. Note that when a write takes place, an ac
When a nonzero-balance-sending `CALL` or `SELFDESTRUCT` with a given sender and recipient takes place, process these write events:
Copy link
Contributor

Choose a reason for hiding this comment

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

Should say *CALL?

(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)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this line needed given that L126 does the same write-access and initialized < created?

EIPS/eip-4762.md Outdated Show resolved Hide resolved
EIPS/eip-4762.md Outdated Show resolved Hide resolved
EIPS/eip-4762.md Outdated

`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)

EIPS/eip-4762.md Outdated
`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`
* **AFTER** charging th witness costs when performing a `CREATE` or `CREATE2`
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`

EIPS/eip-4762.md Outdated
|`CHUNK_EDIT_COST` |500|
|`CHUNK_FILL_COST` |6200|
|`CHUNK_EDIT_COST` |500|
|`CHUNK_FILL_COST` |6200|
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.

@tanishqjasoria
Copy link

i think we should add a section explaing that the account and storage slots that are warmed at the block level should be treated warm for all the transactions. For eg, coinbase and blockhash contract

Copy link

The commit 508f0ab (as a parent of 1a9afe2) contains errors.
Please inspect the Run Summary for details.


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.
Copy link
Contributor

Choose a reason for hiding this comment

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

should we also add a section about 7702 (eoa temporary contract code) accesses?

Copy link
Contributor

Choose a reason for hiding this comment

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

In this PR already added rules for AUTHCALL. So mentioning 7702 would be confusing?

Maybe it's better to not yet assume 3074 nor 7702 in any part of the PR (i.e: remove the existing AUTHCALL mentioning) and add a TODO saying Add 7702/3074 to the spec.

```

If the `BALANCE` opcode is called targeting some address, process this access event:
When calling `EXTCODEHASH`, process the access event:
Copy link
Contributor

Choose a reason for hiding this comment

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

@gballet, I think we should add here "if the target isn't a precompile".


`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 1/64th of the gas is subtracted **AFTER** charging the witness costs when performing a `CALL`, `CODECALL`, `DELEGATECALL` or`STATICCALL`
Copy link
Contributor

@jsign jsign May 30, 2024

Choose a reason for hiding this comment

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

@gballet , nit: in the case of *CALL (compared to CREATE*) it isn't a strict reservation, but a "cap check" of the max amount of gas you can use.

If the *CALL parameter provided a gas parameter that is less 63/64, then less gas is reserved (i.e: more than 1/64 is leftover).

Suggested change
* this 1/64th of the gas is subtracted **AFTER** charging the witness costs when performing a `CALL`, `CODECALL`, `DELEGATECALL` or`STATICCALL`
* this minimum 1/64th gas reservation is checked **AFTER** charging the witness costs when performing a `CALL`, `CODECALL`, `DELEGATECALL` or`STATICCALL`

Anyone reading the spec as it's today will understand the important clarification being made here. So I'm fine if we dismiss this nit.


`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 1/64th of the gas is subtracted **AFTER** charging the witness costs when performing a `CALL`, `CODECALL`, `DELEGATECALL` or`STATICCALL`
Copy link
Contributor

@jsign jsign May 30, 2024

Choose a reason for hiding this comment

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

@gballet, I wonder if we're missing an extra clarification here.

The *CALL variants that can be value-bearing, should also respect this rule?

Today in geth, we have this order (e.g: makeCallVariantGasEIP4762(gasCall)):

  • Charge general *CALL costs. (inside makeCallVariantGasEIP4762(...))
  • Do the 1/64 stuff (inside gasCall(...))
  • Charge BALANCE if transfersValue (inside gasCall(...))

So I'm wondering if this requires a clarification, or was intentional. If was intentional it means that today in kaustinenv6-geth we need a change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c-update Modifies an existing proposal s-draft This EIP is a Draft t-core
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants