-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Update EIP-7805: expand on EL changes #9381
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
Changes from all commits
11cd720
7021f78
8059212
1bb8e94
534d586
1b461a6
fabb2ad
1a5f22f
3053382
b7b4d11
e505eae
2e6a6cf
03b4445
265c96d
e7a30fa
28ff3c2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,7 +14,7 @@ created: 2024-11-01 | |
|
|
||
| FOCIL implements a robust mechanism to preserve Ethereum’s censorship resistance properties by guaranteeing timely transaction inclusion. | ||
|
|
||
| FOCIL (**Fo**rk-choice enforced **I**nclusion **L**ists) is built in a few simple steps: | ||
| FOCIL (**Fo**rk-**c**hoice enforced **I**nclusion **L**ists) is built in a few simple steps: | ||
|
|
||
| - In each slot, a set of validators is selected as inclusion list (IL) committee members. Each member builds and gossips one IL according to their subjective view of the mempool. | ||
| - The proposer and all attesters of the next slot monitor, store and forward available ILs. | ||
|
|
@@ -40,7 +40,7 @@ This section outlines the workflow of FOCIL, detailing the roles and responsibil | |
| - **`Slot N`, `t=0 to 8s`**: | ||
| IL committee members construct their ILs by including transactions pending in the public mempool, and broadcast them over the P2P network after processing the block for `slot N` and confirming it as the head. If no block is received by `t=7s`, they should run `get_head` and build and release their ILs based on the node’s local head. | ||
|
|
||
| By default, ILs are built by selecting raw transactions from the public mempool, ordered by priority fees, up to the IL’s maximum size in bytes of `MAX_BYTES_PER_INCLUSION_LIST = 8 KiB` per IL. Additional rules can be optionally applied to maximize censorship resistance, such as prioritizing valid transactions that have been pending in the mempool the longest. | ||
| IL committee members may follow different strategies for constructing their ILs as discussed in [IL Building](#il-building). | ||
|
|
||
| #### Validators | ||
|
|
||
|
|
@@ -85,31 +85,35 @@ When validators receive ILs from the P2P network, they perform a series of valid | |
|
|
||
| ### Execution Layer | ||
|
|
||
| On the execution layer, the block validity conditions are extended such that, after all of the transactions in the block have been executed, we attempt to execute each valid transaction from ILs that was not present in the block. | ||
| If one of those transactions executes successfully, then the block is invalid. | ||
| On the execution layer, an additional check is introduced for new payloads. After all of the transactions in the payload have been executed, we check whether any transaction from ILs, that is not already present in the payload, could be validly included (i.e. nonce and balance checks pass). If that is the case for any transaction, then an error is returned to the CL. Although the block is valid, the CL will not attest to it. | ||
|
|
||
| Let `B` denote the current block. | ||
| Let `S` denote the execution state following the execution of the last transaction in `B`. | ||
| Let `gas_left` be the gas remaining after execution of B. | ||
|
|
||
| For each transaction `T` in ILs, perform the following: | ||
|
|
||
| 1. Check whether `T` is present in `B`. If `T` is present, then jump to the next transaction, else continue with next step. | ||
|
|
||
| 2. Validate `T` against `S`. | ||
| 2. Check whether `B` has enough remaining gas to execute `T`. If `T.gas` > `gas_left`, then jump to the next transaction, else continue with next step. | ||
|
|
||
| 3. Validate `T` against `S` by checking the nonce and balance of `T.origin`. | ||
|
|
||
| - If `T` is invalid, then continue to the next transaction. | ||
|
|
||
| - If `T` is valid, terminate process and assert block `B` as invalid. | ||
|
|
||
| 3. Execute `T` on state `S`. Assert that the execution of `T` fails. | ||
| - If `T` is valid, terminate process and return an `INVALID_INCLUSION_LIST` error. | ||
|
|
||
| If `B` is full, the process terminates. Also note that we do not need to reset the state to `S`, since the only way for a transaction to alter the state is for it to execute successfully, in which case the block is invalid, and so the block will not be applied to the state. | ||
| #### Engine API Changes | ||
|
|
||
| We make the following changes to the engine API: | ||
|
|
||
| - Add `engine_getInclusionList` endpoint to retrieve an IL from the `ExecutionEngine` | ||
| - Modify `engine_newPayload` endpoint to include a parameter for transactions in ILs determined by the proposer | ||
| - Modify `engine_forkchoiceUpdated` endpoint to include a field in the payload attributes for transactions in ILs determined by the proposer | ||
| - Add `engine_getInclusionListV1` endpoint to retrieve an IL from the `ExecutionEngine`. | ||
| - Add `engine_updatePayloadWithInclusionListV1` endpoint to update a payload with the IL that should be used to build the block. This takes as an argument an 8-byte `payloadId` of the ongoing payload build process, along with the IL itself. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm confused by this. I might be totally getting the CL <-> EL communication wrong though, but I cannot wrap my head around it currently.
I think that these changes should be made instead:
params: copy from https://github.com/ethereum/execution-apis/blob/3779ff972be60cff5fec93e9b51b0ec24aa52e2d/src/engine/prague.md#engine_newpayloadv4 and include
Builds on
I think this can be removed. To update the IL in the build process, just call
Keep as currently specced The main point here is that when building the block we should be aware of the IL. Otherwise the verification process is: build the block, then verify it (
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Regarding Another reason of having Block building is one thing and block verification is another. A block builder doesn't need to verify their block. They're the one who builds a block according to the IL constraints. Attesters are the ones who verify a block and attest to it, if it's legit.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you then show me how the current flow would go for building the block? How would the builder know the IL? I'd assume
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, this is current implementation. It's not guaranteed to have all the ILs until 9 seconds into the slot. So if we were to use I don't have a strong opinion on either way. Thank you for your feedback and I'd encourage more people to give us feedback to find a better solution :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree, the block builder can already start building the block immediately, it can just call I would assume that block builders start building the block immediately. I am not sure, but I think it is likely if the node is not censoring that in most cases, if it has received all ILs (or time to receive new ILs is over) then I think it is likely that the block already consists of most of these txs. But this is a good point, I am not super familiar with the block building process which clients implement, and it would also be worth to study what "big block builders" implement and how they might run into build problems with the new ILs. Note that the EIP-1559 fee market will target the blocks to be full on average of the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you add a new engine API, which is
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The freedom that you can start the building process at any moment. The version with
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think so. You have the same freedom in Also, the payload building usually finishes in 100ms. You don't interrupt the building process, you just initiate another round with ILs. The only case |
||
| - Modify `engine_newPayload` endpoint to include a parameter for transactions in ILs determined by the IL committee member. If the IL is not satisfied an `INVALID_INCLUSION_LIST` error must be returned. | ||
|
|
||
| #### IL Building | ||
|
|
||
| The rules for building ILs are left to the discretion of implementers. For instance, they may select transactions from the public mempool in various ways such as at random, by priority fee, or based on how long they have been pending. The IL has a maximum size of `MAX_BYTES_PER_INCLUSION_LIST = 8 KiB` for all of the RLP encoded transactions. | ||
|
|
||
| ### Consensus Layer | ||
|
|
||
|
|
||
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.
Let
Bdenote the current block.Let
Sdenote the execution state following the execution of the last transaction inB.Let
gas_leftbe the gas remaining after execution ofB.For each transaction
txin ILs, perform the following:txis present inB. Iftxis present, then jump to the next transaction, else continue with next step.txagainstS.txis invalid ortx.gas > gas_left, then continue to the next transaction.txis valid andtx.gas <= gas_left, terminate process and return an error.Uh oh!
There was an error while loading. Please reload this page.
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's more precise to view
gas_leftas a separate value rather than as a part of the execution state.Let
Bdenote the current block.Let
Sdenote the execution state following the execution of the last transaction inB.Let
gas_leftbe the gas remaining after execution ofB.For each transaction
txin ILs, perform the following:Check whether
txis present in B. Iftxis present, then jump to the next transaction, else continue with next step.Check whether
Bhas enough remaining gas to executetx. Iftx.gas>gas_left, then jump to the next transaction, else continue with next step.Let
balanceandnoncebe the balance and nonce oftx.originderived fromSrespectively. If the required funds fortx>balanceortx.nonce!=nonce, then jump to the next transaction, else terminate process and return an error.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.
lgtm
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 we may need more checks to make sure that a transaction is includable. As an example, 7702
SetCodeTransactionsthat have empty authorisation lists are invalid.See comment.