-
Notifications
You must be signed in to change notification settings - Fork 1
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
FOCIL #2
base: dev
Are you sure you want to change the base?
FOCIL #2
Conversation
ef9c08c
to
1764816
Compare
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.
General comment/question:
Just to make sure I understand: I couldn't find the Agg/Eval functions attesters have to run before casting their votes, is this expected?
- [Beacon chain state transition function](#beacon-chain-state-transition-function) | ||
- [Execution engine](#execution-engine) | ||
- [Engine APIs](#engine-apis) | ||
- [New `verify_and_notify_new_inclusion_list`](#new-verify_and_notify_new_inclusion_list) |
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.
should it be verify_and_notify_new_inclusion_list_aggregate
?
|
||
## Introduction | ||
|
||
This is the beacon chain specification to add a committee-based inclusion list mechanism to allow forced transaction inclusion. Refers to [Ethresearch](https://ethresear.ch/t/fork-choice-enforced-inclusion-lists-focil-a-simple-committee-based-inclusion-list-proposal/19870/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.
better to say "to add a fork-choice enforced, committee-based inclusion list (FOCIL)" here
|
||
| Name | Value | | ||
| - | - | | ||
| `IL_COMMITTEE_SIZE` | `uint64(2**9)` (=512) # (New in FOCIL) | |
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.
this is still very much to be defined, but in the post it's 256, not 512
#### `InclusionSummary` | ||
|
||
```python | ||
class InclusionSummary(Container): |
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.
LocalInclusionSummary?
sync_aggregate: SyncAggregate | ||
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] | ||
# FOCIL | ||
inclusion_summary_aggregates: InclusionSummaryAggregates # [New in FOCIL] |
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 note mentions inclusion_summary_aggregate
but here you added an "s" at the end
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 the note is wrong, inclusion_summary_aggregates
is correct here. Aligns with bls_to_execution_changes
and others
|
||
Warning: This file should be placed in https://github.com/ethereum/execution-apis but I'm placing it here for convenience of reviewing. | ||
|
||
## Table of contents |
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.
Should probably be LocalInclusionListSummary here too (throughout the whole section)
|
||
| Name | Value | | ||
| - | - | | ||
| `INCLUSION_LIST_MAX_GAS` | `uint64(4194304) = 2**22` | |
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.
LOCAL_INCLUSION_LIST_MAX_GAS
- [Topics and messages](#topics-and-messages-1) | ||
- [Global topics](#global-topics) | ||
- [`local_inclusion_list`](#local_inclusion_list) | ||
- [`inclusion_summary_aggregate`](#inclusion_summary_aggregate) |
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.
did you mean inclusion_list_summary_aggregate?
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 renamed everything from inclusion_list_summary
-> inclusion_summary
. It feels cleaner, happy to change but I will leave naming stuff to the last. Focusing on functionality first
class SignedInclusionListAggregates(Container): | ||
slot: Slot | ||
proposer_index: ValidatorIndex | ||
message: InclusionSummaryAggregates |
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.
same q here
validator_indices: List[ValidatorIndex] = [] | ||
for idx in range(committees_per_slot): | ||
beacon_committee = get_beacon_committee(state, slot, CommitteeIndex(idx)) | ||
validator_indices += beacon_committee[:members_per_committee] |
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.
What happens if multiple committees assemble their members from the beginning of beacon committee at the same time? Does a validator with multiple committee roles just fulfill its duties? If so, wouldn't this be a burden at some point?
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.
It's just one committee, size 256 or 512, if you get duplicated entries then just do it twice. I don't think it's worth optimizing this edge case at this point
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.
Alright, it was a genuine question. Thanks for the answer!
""" | ||
Return the indexed inclusion list aggregate corresponding to ``inclusion_summary_aggregate``. | ||
""" | ||
indices = get_inclusion_list_aggregate_indices(state) |
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.
You need to pass inclusion_summary_aggregate
.
#### `IndexedInclusionListAggregate` | ||
|
||
```python | ||
class IndexedInclusionListAggregate(Container): |
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.
class IndexedInclusionListAggregate(Container): | |
class IndexedInclusionSummaryAggregate(Container): |
#### New `get_indexed_inclusion_list_aggregate` | ||
|
||
```python | ||
def get_indexed_inclusion_list_aggregate(state: BeaconState, |
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.
def get_indexed_inclusion_list_aggregate(state: BeaconState, | |
def get_indexed_inclusion_summary_aggregate(state: BeaconState, |
#### New `get_inclusion_list_aggregate_indices` | ||
|
||
```python | ||
def get_inclusion_list_aggregate_indices(state: BeaconState, |
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.
def get_inclusion_list_aggregate_indices(state: BeaconState, | |
def get_inclusion_summary_aggregate_indices(state: BeaconState, |
|
||
```python | ||
class InclusionSummaryAggregates(Container): | ||
List[InclusionSummaryAggregate, MAX_TRANSACTIONS_PER_INCLUSION_LIST] |
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.
If I understood correctly, the maximum number of InclusionSummaryAggregate
is MAX_TRANSACTIONS_PER_INCLUSION_LIST * IL_COMMITTEE_SIZE
.
address: ExecutionAddress | ||
nonce: uint64 | ||
gas_limit: uint64 |
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.
Do these combination always correspond to one transaction? What if an EOA sends a transaction and then sends another one with the same nonce and gas_limit but with higher priority fee in the hope that it can effectively cancel the first one?
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.
Execution layer will filter that
validator_index: ValidatorIndex | ||
parent_hash: Hash32 | ||
summaries: List[InclusionSummary, MAX_TRANSACTIONS_PER_INCLUSION_LIST] | ||
transactions: List[Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST] |
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.
Shouldn't LocalInclusionList contain any raw transaction to prevent free DA? I think raw transactions need to be cached somewhere else.
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.
LocalInclusionList
can't be proven on chain, there's no free DA. Yea it will be cached short term, which wont be specified in the spec
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.
You're right, I was mistaken. Only the summary is part of a block.
inclusion_summary_aggregates: InclusionSummaryAggregates # [New in FOCIL] | ||
``` | ||
|
||
### Beacon State accessors |
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 also need a function that takes a list of SignedLocalInclusionList
and outputs InclusionSummaryAggregates
.
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's part of the state transition function though. I briefly mentioned this in the validator spec. I think this is an implementation detail. Nodes will cache signed local inclusion lists, aggregate them, and release them
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 it belongs to beacon state transition function either. I think it belongs to beacon state accessors or at least a helper. Currently, all beacon state accessors are using InclusionSummaryAggregate so I thought they need some function to derive it from the received a list of SignedLocalInclusionList. It's for attesters rather than IL committee members.
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's add that to the fork choice spec or validator spec. Fork choice spec will use it to lock views
That's part of fork choice spec, which I've been procrastinating on : ) |
specs/_features/focil/validator.md
Outdated
- The proposer signs the `inclusion_summary_aggregates` using helper `get_inclusion_summary_aggregates` and constructs a `signed_inclusion_aggregates_summary`. | ||
|
||
```python | ||
def get_inclusion_summary_aggregate( |
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.
def get_inclusion_summary_aggregate( | |
def get_inclusion_summary_aggregates_signature( |
specs/_features/focil/validator.md
Outdated
#### Constructing the new `InclusionSummaryAggregate` field in `BeaconBlockBody` | ||
|
||
Proposer has to include a valid `inclusion_summary_aggregate` into the block body. The proposer will have to | ||
* Proposer uses perviously constructed `InclusionSummaryAggregate` and include it in the beacon block body. |
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.
InclusionSummaryAggregate
-> InclusionSummaryAggregates
#### `SignedInclusionListAggregate` | ||
|
||
```python | ||
class SignedInclusionListAggregates(Container): |
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.
class SignedInclusionListAggregates(Container): | |
class SignedInclusionSummaryAggregates(Container): |
- _[REJECT]_ The signature of `inclusion_list.signature` is valid with respect to the validator index. | ||
- _[REJECT]_ The validator index is within the inclusion list committee in `get_inclusion_list_committee(state)`. The `state` is the head state corresponding to processing the block up to the current slot as determined by the fork choice. | ||
|
||
###### `inclusion_summary_aggregate` |
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.
###### `inclusion_summary_aggregate` | |
###### `inclusion_summary_aggregates` |
sync_aggregate: SyncAggregate | ||
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES] | ||
# FOCIL | ||
inclusion_summary_aggregates: InclusionSummaryAggregates # [New in FOCIL] |
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 just realize this could add quite amount of bytes to beacon block. I'm not aware of what is the acceptable range, but here is my back-of-the-napkin math.
InclusionSummary: address + uint64 + uint64 = (20 + 8 + 8) bytes = 36 bytes.
InclusionSummaryAggregate: Bitvector[IL_COMMITTEE_SIZE
] + InclusionSummary + BLSSignature = (256 / 8 + 36 + 96) bytes = 164 bytes.
InclusionSummaryAggregates: InclusionSummaryAggregate * MAX_TRANSACTIONS_PER_INCLUSION_LIST
* IL_COMMITTEE_SIZE
= (164 * MAX_TRANSACTIONS_PER_INCLUSION_LIST
* 256) bytes >= 41,984 bytes.
Of course it depends on constants values, which are not fixed yet.
The ideal size of the new field would be (128 + 36 * MAX_TRANSACTIONS_PER_INCLUSION_LIST
) bytes, which comes from:
aggregation_bits: BitVector[IL_COMMITTEE_SIZE]
summaries: List[InclusionSummary, MAX_TRANSACTIONS_PER_INCLUSION_LIST]
signature: BLSSignature
But this requires at least one more round from a proposer to IL committee members. I don't have a good solution at the moment but wanted to share what I've found.
|
||
## Introduction | ||
|
||
This is the beacon chain specification to add a fork-choice enforced, committee-based inclusion list (FOCIL) mechanism to allow forced transaction inclusion. Refers to [Ethresearch](https://ethresear.ch/t/fork-choice-enforced-inclusion-lists-focil-a-simple-committee-based-inclusion-list-proposal/19870/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.
Might be worth to add this one also? Could help the draft reader to follow up the concepts.. but it doesn't really matter as we can add a link to EIP once we have it.
execution_payload = new_payload_request.execution_payload | ||
execution_requests = new_payload_request.execution_requests | ||
parent_beacon_block_root = new_payload_request.parent_beacon_block_root | ||
il_transactions = new_payload_request.il_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.
il_transactions = new_payload_request.il_transactions | |
il_transactions = new_payload_request.il_transactions # [New in FOCIL] |
when calling `notify_new_payload` in FOCIL. | ||
|
||
```python | ||
def verify_and_notify_new_payload(self: ExecutionEngine, |
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.
il_transactions
is in NewPayloadRequest
anyway so there is no need to change the signature of verify_and_notify_new_payload
of Electra.
specs/_features/focil/fork-choice.md
Outdated
```python | ||
def validate_inclusion_lists(store: Store, inclusion_list_transactions: List[Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST], execution_payload: ExecutionPayload) -> bool: | ||
""" | ||
Return ``True`` if and only if the input ``inclusion_list_transactions`` satifies validation, that to verify if the `execution_payload` satisfies `inclusion_list_transactions` validity conditions either when all transactions are present in payload or when any missing transactions are found to be invalid when appended to the end of the payload. |
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.
Would it be better to explicitly describe a condition when a block is full?
specs/_features/focil/fork-choice.md
Outdated
# Verify inclusion list signature | ||
assert is_valid_local_inclusion_list_signature(state, signed_inclusion_list) | ||
|
||
parent_hash = message.parent_hash |
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.
Where is parent_hash
used?
This document is an extension of the [Electra -- Honest Validator](../../electra/validator.md) guide. | ||
All behaviors and definitions defined in this document, and documents it extends, carry over unless explicitly noted or overridden. | ||
|
||
All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of [FOCIL](./beacon-chain.md) are requisite for this document and used throughout. |
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.
All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of [FOCIL](./beacon-chain.md) are requisite for this document and used throughout. | |
All terminology, constants, functions, and protocol mechanics defined in the updated Beacon Chain doc of [FOCIL](./beacon-chain.md) are prerequisite for this document and used throughout. |
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.
Sticking with requisite because that's what's used in all the documents, not really sure which is better
specs/_features/focil/engine-api.md
Outdated
#### Specification | ||
|
||
1. Client software **MUST** respond to this method call in the following way: | ||
* `{status: INVALID_INCLUSION_LISTING, latestValidHash: null, validationError: null}` if there are any leftover `inclusionListTransactions` that are not part of the `executionPayload`, they can be processed at the end of the `executionPayload`. |
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.
* `{status: INVALID_INCLUSION_LISTING, latestValidHash: null, validationError: null}` if there are any leftover `inclusionListTransactions` that are not part of the `executionPayload`, they can be processed at the end of the `executionPayload`. | |
* `{status: INVALID_INCLUSION_LIST, latestValidHash: null, validationError: null}` if there are any leftover `inclusionListTransactions` that are not part of the `executionPayload`, they can be processed at the end of the `executionPayload`. |
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.
Do we need to mention the condition that execution payload has leftover gas?
specs/_features/focil/validator.md
Outdated
|
||
### `ExecutionEngine` | ||
|
||
*Note*: `engine_getInclusionListV1` and `engine_updateInclusionListV1` functions are added to the `ExecutionEngine` protocol for use as a validator. |
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.
engine_updateInclusionListV1
seems missing in the engine-api.md.
specs/_features/focil/validator.md
Outdated
|
||
Some validators are selected to submit local inclusion list. Validators should call `get_ilc_assignment` at the beginning of an epoch to be prepared to submit their local inclusion list during the next epoch. | ||
|
||
A validator should create and broadcast the `signed_inclusion_list` to the global `inclusion_list` subnet by the `LOCAL_INCLUSION_LIST_CUT_OFF` in the slot, unless a block for the current slot has been processed and is the head of the chain and broadcast to the network. |
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.
A validator should create and broadcast the `signed_inclusion_list` to the global `inclusion_list` subnet by the `LOCAL_INCLUSION_LIST_CUT_OFF` in the slot, unless a block for the current slot has been processed and is the head of the chain and broadcast to the network. | |
A validator should create and broadcast the `signed_inclusion_list` to the global `local_inclusion_list` subnet by the `LOCAL_INCLUSION_LIST_CUT_OFF` in the slot, unless a block for the current slot has been processed and is the head of the chain and broadcast to the network. |
specs/_features/focil/validator.md
Outdated
- Set `local_inclusion_list.parent_hash` to the block hash of the fork choice head. | ||
- Set `local_inclusion_list.parent_root` to the block hash of the fork choice head. |
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.
What's the difference between these two?
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.
one is consensus layer construct, one is execution layer construct, fixing the sentences to clarify
specs/_features/focil/fork-choice.md
Outdated
""" | ||
message = signed_inclusion_list.message | ||
# Verify inclusion list slot is bounded to the current slot | ||
assert get_current_slot(store) != message.slot |
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.
assert get_current_slot(store) != message.slot | |
assert get_current_slot(store) == message.slot |
specs/_features/focil/fork-choice.md
Outdated
store.inclusion_lists.remove(existing_inclusion_list) | ||
else: | ||
# If no such inclusion list exists, add the new one | ||
store.inclusion_lists.append(message.transaction) |
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.
store.inclusion_lists.append(message.transaction) | |
store.inclusion_lists.append(message) |
No description provided.