diff --git a/specs/_features/eip7805/fork-choice.md b/specs/_features/eip7805/fork-choice.md index c0240163bc..e290d789d1 100644 --- a/specs/_features/eip7805/fork-choice.md +++ b/specs/_features/eip7805/fork-choice.md @@ -6,12 +6,13 @@ - [Introduction](#introduction) -- [Configuration](#configuration) -- [Helpers](#helpers) - - [New `validate_inclusion_lists`](#new-validate_inclusion_lists) - - [Modified `Store`](#modified-store) - - [New `get_attester_head`](#new-get_attester_head) - - [New `on_inclusion_list`](#new-on_inclusion_list) +- [Fork choice](#fork-choice) + - [Configuration](#configuration) + - [Helpers](#helpers) + - [Modified `Store`](#modified-store) + - [New `validate_inclusion_lists`](#new-validate_inclusion_lists) + - [New `get_attester_head`](#new-get_attester_head) + - [New `on_inclusion_list`](#new-on_inclusion_list) @@ -20,32 +21,17 @@ This is the modification of the fork choice accompanying the EIP-7805 upgrade. -## Configuration +## Fork choice + +### Configuration | Name | Value | Unit | Duration | | - | - | :-: | :-: | | `VIEW_FREEZE_DEADLINE` | `uint64(9)` | seconds | 9 seconds | -## Helpers +### Helpers -### New `validate_inclusion_lists` - -```python -def validate_inclusion_lists(store: Store, - inclusion_list_transactions: - List[Transaction, MAX_TRANSACTIONS_PER_INCLUSION_LIST * INCLUSION_LIST_COMMITTEE_SIZE], - execution_payload: ExecutionPayload) -> bool: - """ - Return ``True`` if and only if the input ``inclusion_list_transactions`` satisfies 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 unless the block is full. - """ - # pylint: disable=unused-argument - ... -``` - -### Modified `Store` +#### Modified `Store` **Note:** `Store` is modified to track the seen inclusion lists and inclusion list equivocators. @@ -66,13 +52,37 @@ class Store(object): checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict) latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict) unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict) - inclusion_lists: Dict[Tuple[Slot, Root], List[InclusionList]] = field(default_factory=dict) # [New in EIP-7805] # [New in EIP-7805] + inclusion_lists: Dict[Tuple[Slot, Root], List[InclusionList]] = field(default_factory=dict) inclusion_list_equivocators: Dict[Tuple[Slot, Root], Set[ValidatorIndex]] = field(default_factory=dict) - unsatisfied_inclusion_list_blocks: Set[Root] = field(default_factory=Set) # [New in EIP-7805] + unsatisfied_inclusion_list_blocks: Set[Root] = field(default_factory=Set) +``` + +#### New `validate_inclusion_lists` + +```python +def validate_inclusion_lists(store: Store, + inclusion_list_transactions: Sequence[Transaction], + execution_payload: ExecutionPayload) -> None: + """ + 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 unless the block is full. + """ + # pylint: disable=unused-argument + + # Verify inclusion list is a valid length + assert len(inclusion_list_transactions) <= MAX_TRANSACTIONS_PER_INCLUSION_LIST * INCLUSION_LIST_COMMITTEE_SIZE + + # Verify inclusion list transactions are present in the execution payload + contains_all_txs = all(tx in execution_payload.transactions for tx in inclusion_list_transactions) + if contains_all_txs: + return + + # TODO: check remaining validity conditions ``` -##### New `get_attester_head` +#### New `get_attester_head` ```python def get_attester_head(store: Store, head_root: Root) -> Root: @@ -84,7 +94,7 @@ def get_attester_head(store: Store, head_root: Root) -> Root: ``` -### New `on_inclusion_list` +#### New `on_inclusion_list` `on_inclusion_list` is called to import `signed_inclusion_list` to the fork choice store. @@ -95,17 +105,19 @@ def on_inclusion_list( signed_inclusion_list: SignedInclusionList, inclusion_list_committee: Vector[ValidatorIndex, INCLUSION_LIST_COMMITTEE_SIZE]) -> None: """ - Verify the inclusion list and import it into the fork choice store. If there exists more than 1 - inclusion list in store with the same slot and validator index, add the equivocator to the - ``inclusion_list_equivocators`` cache. Otherwise, add inclusion list to the ``inclusion_lists` - cache. + Verify the inclusion list and import it into the fork choice store. If there exists more than + one inclusion list in the store with the same slot and validator index, add the equivocator to + the ``inclusion_list_equivocators`` cache. Otherwise, add the inclusion list to the + ``inclusion_lists` cache. """ message = signed_inclusion_list.message + # Verify inclusion list slot is either from the current or previous slot assert get_current_slot(store) in [message.slot, message.slot + 1] time_into_slot = (store.time - store.genesis_time) % SECONDS_PER_SLOT is_before_attesting_interval = time_into_slot < SECONDS_PER_SLOT // INTERVALS_PER_SLOT + # If the inclusion list is from the previous slot, ignore it if already past the attestation deadline if get_current_slot(store) == message.slot + 1: assert is_before_attesting_interval