-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
Add EIP: Delayed Execution Layer State Root #9241
base: master
Are you sure you want to change the base?
Conversation
File
|
EIPS/eip-xxxx.md
Outdated
|
||
The EL `state_root` must be computed by block builders (and verified by relays, validators, and light clients) in near-real-time. This computation accounts for a large fraction of block production and verification time, especially in an MEV-Boost environment. This overhead is also a challenge for efforts to enable real-time ZK proving of the chain. | ||
|
||
By delaying the EL `state_root` reference by one block, we can remove EL `state_root` calculation overhead from the critical path of block production. Instead, clients can pipeline calculation of block `n-1`'s EL `state_root` during the idle slot time of block `n`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
idle slot time of block
n
.
I think this is n-1
. At n-1
, the block arrives around the 4th second of the slot, you verify everything except the state root, and then you have 8 more seconds in n-1
to verify the state root
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in this design the EL clients are calculating the state root of block n-1
while building block n
at the same time, and this process occurs during the last 8 seconds of block n-1
. Is this correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea either change it to n-1
or it should read:
Instead, clients can pipeline calculation of block n
's EL state_root
during the idle slot time of block n
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it might be clearer to specify post-state root, rather than the parameter.
"Instead, clients can pipeline calculation of block n-1
's EL post-state root during the idle slot time of block n
."
Would you guys be happy with this?
To clarify what happens is that:
When n-1 arrives, it contains the EL pre-state root of n-1.
While waiting for block n to arrive, the client can calculate the post-state root of n-1 (equivalently, pre-state of n).
When block n arrives, it can verify that it contains the correct post-state of n-1 (equivalently, pre-state of n).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so all we are delaying for the attesting/verifying validator is the stateroot calc? how significant is that as percentate of block building time?
we could infact delay the entire execution for the attesting/verifying validator (which means they can execute/verify bigger blocks on the commodity hardware while the specialized builders can build a gas chugging block
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we can delay attesting unless we do eip7732
EIPS/eip-xxxx.md
Outdated
- The actual new state root resulting from block `n` will only appear in block `n+1`. | ||
3. **Proactive Computation of Post-state Root**: | ||
- To fully realize latency benefits, clients should compute the post-state root of block `n-1` during the idle time of slot `n`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
during the idle time of slot
n
.
Same. I think this would be n-1
, not n
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that I agree.
You could say "compute the pre-state root of n during the idle slot time of n"
and that might be clearer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked at this again and think what you have is fine. If we want to be clearer, we could rephrase it as the following:
"As a proposer/builder for n
, assuming it receives a block for n-1
during slot n-1
, to fill in the state_root
field, they should compute the post-state root at n-1
during the idle time of n-1
"
I agree with what you said here: #9241 (comment)
EIPS/eip-xxxx.md
Outdated
bytes32 parentHash; | ||
address feeRecipient; | ||
... | ||
bytes32 stateRoot; // now references the post-state root of block (n-1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have another Q:
since the block builders will have the stateroot because they can't include a tx before executing a previous one because of previous txs affecting any prestate of the tx, so why should we not include the stateroot in it
since the logs/requests etc are all dependent on the correct execution. Ofcourse the attesters can still do delayed verification.
may we we just add a block pre-stateroot field and use that for running verifications because proofs of correct execution results against this block might require this block's post stateroot and will be easy and fast check for whenever the block gets executed before next block arrives
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the block builders will have the stateroot because they can't include a tx before executing a previous one because of previous txs affecting any prestate of the tx, so why should we not include the stateroot in it
They only need the state, not the state root.
Currently they'd need to compute the state root before completing the block building process. Now they don't need to compute it eagerly (they can do it async).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I get that, but having post stateroot in block is a good thing for creating proofs merkle and ZK against the current block header itself.
yes it would matter how hard it is to create a stateroot, my supposition is : its not really that expensive and doesn't add any real latency but then depends on how big the block is, but if its vialble we should include it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry I'm not sure I understand. Do you suggest to include both pre state root and post state root of the current block in its header?
having post stateroot in block is a good thing for creating proofs merkle and ZK against the current block header itself
Do you mean verifying blocks with a zk proof instead of re-executing them? That's not necessarily in conflict with this EIP, nodes can still receive the state root together with the proof (not as part of the header but on some other channel).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I mean to specify both because the block builder will have the final execution results anyway when its done adding txs to the block.
for the proof, it needs to be anchored in post state root. Although receipts should have the entire execution traced but thats not true of system updates which are purely reflected in stateroot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok now I understand that this EIP is trying to save post state root compute time even for builder. is that correct?
if so then as I asked in a previous comment how significant this time would be (so benchmarks against some typical blocks with 30m 60m... 100m 1g gas i guess) on a latest commondity hardware (which one would expect least of block builders)
I guess that would bring forward the proper justification of the EIP
EIPS/eip-xxxx.md
Outdated
# assert compute_state_root(transactions_of_block_n) == payload_n.stateRoot | ||
# | ||
# Now: | ||
assert payload_n.stateRoot == post_state_of_block_n_minus_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this mean that if a future protocol upgrade changes EVM behavior, then nodes that did not upgrade would fork off the network with 1 block delay? (Though I don't think this is an issue.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that is true only if the protocol change results in a mismatched state but doesn't change the execution flow of the transactions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, so for instance adding a new tx type could result in a fork exactly at the upgrade block.
But adding a new opcode or precompile, or changing the gas schedule, could result in a fork one block later.
# assert compute_state_root(transactions_of_block_n) == payload_n.stateRoot | ||
# | ||
# Now: | ||
assert payload_n.stateRoot == post_state_of_block_n_minus_1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the current block execution validations also validates receipts, execution requests root, header has logbloom etc so many other fields which are the result of block execution and get validated so I am assuming that those validations stay in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not realize this until this comment, because I first assumed that this could mean that tx execution could happen after publishing the block. But this is not possible, since we still need receipt roots.
Are there any numbers how much the time is of calculating the state root? This is a simplification, but I would assume that most clients would execute txs and write state changes to a cache. Only at the end of running the txs this cache is flushed to disk in order to calculate the new state root. I would honestly have no idea what the ratio is between executing the transactions and flushing the new cache to disk / calculating the root and would love to see some numbers on this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yea agree with @jochem-brouwer we should see what is the benchmark delay for batched state root calculation
Eip-7862: Fix linter issues
The commit adc3c35 (as a parent of 8e28b3e) contains errors. |
Fix linter issues
|
||
## Motivation | ||
|
||
Currently, every Ethereum block includes two `state_root`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the wording of this statement incorrect, EL blocks have only one state root, and this is the state root of Ethereum's "world state" (MPT of accounts)
|
||
The execution layer (EL) `state_root` contained within the `ExecutionPayload` tracks the effect of transaction execution (e.g., account balances, code, etc.). | ||
|
||
The EL `state_root` must be computed by block builders (and verified by relays, validators, and light clients) in near-real-time. This computation accounts for a large fraction of block production and verification time, especially in an MEV-Boost environment. This overhead is also a challenge for efforts to enable real-time ZK proving of the chain. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd love to see some numbers here, what is this large fraction? If splitting the time between receiving a block, executing the txs, and calculating the root, what would these numbers be?
|
||
3. **Reliant Contracts** | ||
|
||
- We are not aware of any common contract types that assume the availability of same-block state roots. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contracts cannot read a block state root, so I'm not sure if this is relevant?
This EIP implements a delayed state root. It is ready for draft status and discussion.