From 316ea98792a9c71102b03f4be3f353fee2ed30a4 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 27 Dec 2023 12:42:29 +0100 Subject: [PATCH 1/9] Use types for representing LC Merkle branches For better legibility and alignment with `ethereum/beacon-APIs`, use named types for the various Merkle branches used in the LC protocol. - https://github.com/ethereum/beacon-APIs/blob/v2.4.2/types/altair/light_client.yaml#L2-L22 --- specs/altair/light-client/sync-protocol.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/specs/altair/light-client/sync-protocol.md b/specs/altair/light-client/sync-protocol.md index baef684c6..7d46541d6 100644 --- a/specs/altair/light-client/sync-protocol.md +++ b/specs/altair/light-client/sync-protocol.md @@ -64,6 +64,17 @@ Additional documents describe how the light client sync protocol can be used: | `CURRENT_SYNC_COMMITTEE_INDEX` | `get_generalized_index(BeaconState, 'current_sync_committee')` (= 54) | | `NEXT_SYNC_COMMITTEE_INDEX` | `get_generalized_index(BeaconState, 'next_sync_committee')` (= 55) | +```python +class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]): + pass + +class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)]): + pass + +class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)]): + pass +``` + ## Preset ### Misc @@ -93,7 +104,7 @@ class LightClientBootstrap(Container): header: LightClientHeader # Current sync committee corresponding to `header.beacon.state_root` current_sync_committee: SyncCommittee - current_sync_committee_branch: Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)] + current_sync_committee_branch: CurrentSyncCommitteeBranch ``` ### `LightClientUpdate` @@ -104,10 +115,10 @@ class LightClientUpdate(Container): attested_header: LightClientHeader # Next sync committee corresponding to `attested_header.beacon.state_root` next_sync_committee: SyncCommittee - next_sync_committee_branch: Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)] + next_sync_committee_branch: NextSyncCommitteeBranch # Finalized header corresponding to `attested_header.beacon.state_root` finalized_header: LightClientHeader - finality_branch: Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)] + finality_branch: FinalityBranch # Sync committee aggregate signature sync_aggregate: SyncAggregate # Slot at which the aggregate signature was created (untrusted) @@ -122,7 +133,7 @@ class LightClientFinalityUpdate(Container): attested_header: LightClientHeader # Finalized header corresponding to `attested_header.beacon.state_root` finalized_header: LightClientHeader - finality_branch: Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)] + finality_branch: FinalityBranch # Sync committee aggregate signature sync_aggregate: SyncAggregate # Slot at which the aggregate signature was created (untrusted) From 5717a813938c69e4122d7bcfbfe410385f994546 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 27 Dec 2023 12:44:05 +0100 Subject: [PATCH 2/9] Capella addition --- specs/capella/light-client/sync-protocol.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/specs/capella/light-client/sync-protocol.md b/specs/capella/light-client/sync-protocol.md index 7c70ab11d..6a741a1de 100644 --- a/specs/capella/light-client/sync-protocol.md +++ b/specs/capella/light-client/sync-protocol.md @@ -33,6 +33,11 @@ Additional documents describes the impact of the upgrade on certain roles: | - | - | | `EXECUTION_PAYLOAD_INDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload')` (= 25) | +```python +class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]): + pass +``` + ## Containers ### Modified `LightClientHeader` @@ -43,7 +48,7 @@ class LightClientHeader(Container): beacon: BeaconBlockHeader # Execution payload header corresponding to `beacon.body_root` (from Capella onward) execution: ExecutionPayloadHeader - execution_branch: Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)] + execution_branch: ExecutionBranch ``` ## Helper functions From 3e5427e31e9466a70e0e510aee42ddd86589b655 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 27 Dec 2023 12:54:36 +0100 Subject: [PATCH 3/9] Align formatting --- specs/altair/light-client/sync-protocol.md | 38 +++++++++++++++------ specs/capella/light-client/sync-protocol.md | 7 ++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/specs/altair/light-client/sync-protocol.md b/specs/altair/light-client/sync-protocol.md index 7d46541d6..6a1fc75d8 100644 --- a/specs/altair/light-client/sync-protocol.md +++ b/specs/altair/light-client/sync-protocol.md @@ -12,6 +12,10 @@ - [Constants](#constants) - [Preset](#preset) - [Misc](#misc) +- [Helper types](#helper-types) + - [`FinalityBranch`](#finalitybranch) + - [`CurrentSyncCommitteeBranch`](#currentsynccommitteebranch) + - [`NextSyncCommitteeBranch`](#nextsynccommitteebranch) - [Containers](#containers) - [`LightClientHeader`](#lightclientheader) - [`LightClientBootstrap`](#lightclientbootstrap) @@ -64,17 +68,6 @@ Additional documents describe how the light client sync protocol can be used: | `CURRENT_SYNC_COMMITTEE_INDEX` | `get_generalized_index(BeaconState, 'current_sync_committee')` (= 54) | | `NEXT_SYNC_COMMITTEE_INDEX` | `get_generalized_index(BeaconState, 'next_sync_committee')` (= 55) | -```python -class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]): - pass - -class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)]): - pass - -class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)]): - pass -``` - ## Preset ### Misc @@ -84,6 +77,29 @@ class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDE | `MIN_SYNC_COMMITTEE_PARTICIPANTS` | `1` | validators | | | `UPDATE_TIMEOUT` | `SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD` | slots | ~27.3 hours | +## Helper types + +### `FinalityBranch` + +```python +class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]): + pass +``` + +### `CurrentSyncCommitteeBranch` + +```python +class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)]): + pass +``` + +### `NextSyncCommitteeBranch` + +```python +class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)]): + pass +``` + ## Containers ### `LightClientHeader` diff --git a/specs/capella/light-client/sync-protocol.md b/specs/capella/light-client/sync-protocol.md index 6a741a1de..c1281c459 100644 --- a/specs/capella/light-client/sync-protocol.md +++ b/specs/capella/light-client/sync-protocol.md @@ -10,6 +10,8 @@ - [Introduction](#introduction) - [Constants](#constants) +- [Helper types](#helper-types) + - [`ExecutionBranch`](#executionbranch) - [Containers](#containers) - [Modified `LightClientHeader`](#modified-lightclientheader) - [Helper functions](#helper-functions) @@ -33,6 +35,11 @@ Additional documents describes the impact of the upgrade on certain roles: | - | - | | `EXECUTION_PAYLOAD_INDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload')` (= 25) | + +## Helper types + +### `ExecutionBranch` + ```python class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]): pass From cf55918a6f00a37e4f9acdca1ef32e9a4872026b Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 27 Dec 2023 13:58:36 +0100 Subject: [PATCH 4/9] Avoid Mypy error during lint --- setup.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index da14759ca..cd6d1f180 100644 --- a/setup.py +++ b/setup.py @@ -93,6 +93,8 @@ def _get_class_info_from_source(source: str) -> Tuple[str, Optional[str]]: base = class_def.bases[0] if isinstance(base, ast.Name): parent_class = base.id + elif isinstance(base, ast.Subscript): + parent_class = base.value.id else: # NOTE: SSZ definition derives from earlier phase... # e.g. `phase0.SignedBeaconBlock` @@ -216,10 +218,19 @@ def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str], pr class_name, parent_class = _get_class_info_from_source(source) # check consistency with spec assert class_name == current_name + ignore_type = False if parent_class: - assert parent_class == "Container" + if parent_class == "Container": + pass + elif parent_class == "Vector": + ignore_type = True # Avoid Mypy error: Invalid base class "Vector" + else: + raise Exception("unrecognized parent class: " + source) # NOTE: trim whitespace from spec - ssz_objects[current_name] = "\n".join(line.rstrip() for line in source.splitlines()) + lines = [line.rstrip() for line in source.splitlines()] + if ignore_type: + lines[0] += " # type: ignore" + ssz_objects[current_name] = "\n".join(lines) else: raise Exception("unrecognized python code element: " + source) elif isinstance(child, Table): From fca5e3b06a1dc4caab54734502a8a53cc52521c1 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Wed, 27 Dec 2023 13:59:31 +0100 Subject: [PATCH 5/9] Use proper types when dealing with LC Merkle proofs --- specs/altair/light-client/full-node.md | 9 ++++++--- specs/altair/light-client/sync-protocol.md | 12 ++++++------ specs/capella/light-client/full-node.md | 5 +++-- specs/capella/light-client/sync-protocol.md | 4 ++-- specs/deneb/light-client/full-node.md | 5 +++-- specs/deneb/light-client/sync-protocol.md | 2 +- 6 files changed, 21 insertions(+), 16 deletions(-) diff --git a/specs/altair/light-client/full-node.md b/specs/altair/light-client/full-node.md index 27651af01..8ca58cfe5 100644 --- a/specs/altair/light-client/full-node.md +++ b/specs/altair/light-client/full-node.md @@ -75,7 +75,8 @@ def create_light_client_bootstrap(state: BeaconState, return LightClientBootstrap( header=block_to_light_client_header(block), current_sync_committee=state.current_sync_committee, - current_sync_committee_branch=compute_merkle_proof(state, CURRENT_SYNC_COMMITTEE_INDEX), + current_sync_committee_branch=CurrentSyncCommitteeBranch( + compute_merkle_proof(state, CURRENT_SYNC_COMMITTEE_INDEX)), ) ``` @@ -122,7 +123,8 @@ def create_light_client_update(state: BeaconState, # `next_sync_committee` is only useful if the message is signed by the current sync committee if update_attested_period == update_signature_period: update.next_sync_committee = attested_state.next_sync_committee - update.next_sync_committee_branch = compute_merkle_proof(attested_state, NEXT_SYNC_COMMITTEE_INDEX) + update.next_sync_committee_branch = NextSyncCommitteeBranch( + compute_merkle_proof(attested_state, NEXT_SYNC_COMMITTEE_INDEX)) # Indicate finality whenever possible if finalized_block is not None: @@ -131,7 +133,8 @@ def create_light_client_update(state: BeaconState, assert hash_tree_root(update.finalized_header.beacon) == attested_state.finalized_checkpoint.root else: assert attested_state.finalized_checkpoint.root == Bytes32() - update.finality_branch = compute_merkle_proof(attested_state, FINALIZED_ROOT_INDEX) + update.finality_branch = FinalityBranch( + compute_merkle_proof(attested_state, FINALIZED_ROOT_INDEX)) update.sync_aggregate = block.message.body.sync_aggregate update.signature_slot = block.message.slot diff --git a/specs/altair/light-client/sync-protocol.md b/specs/altair/light-client/sync-protocol.md index 6a1fc75d8..58a38d150 100644 --- a/specs/altair/light-client/sync-protocol.md +++ b/specs/altair/light-client/sync-protocol.md @@ -82,7 +82,7 @@ Additional documents describe how the light client sync protocol can be used: ### `FinalityBranch` ```python -class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]): +class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]): pass ``` @@ -201,14 +201,14 @@ def is_valid_light_client_header(header: LightClientHeader) -> bool: ```python def is_sync_committee_update(update: LightClientUpdate) -> bool: - return update.next_sync_committee_branch != [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))] + return update.next_sync_committee_branch != NextSyncCommitteeBranch() ``` ### `is_finality_update` ```python def is_finality_update(update: LightClientUpdate) -> bool: - return update.finality_branch != [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))] + return update.finality_branch != FinalityBranch() ``` ### `is_better_update` @@ -520,7 +520,7 @@ def process_light_client_finality_update(store: LightClientStore, update = LightClientUpdate( attested_header=finality_update.attested_header, next_sync_committee=SyncCommittee(), - next_sync_committee_branch=[Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))], + next_sync_committee_branch=NextSyncCommitteeBranch(), finalized_header=finality_update.finalized_header, finality_branch=finality_update.finality_branch, sync_aggregate=finality_update.sync_aggregate, @@ -539,9 +539,9 @@ def process_light_client_optimistic_update(store: LightClientStore, update = LightClientUpdate( attested_header=optimistic_update.attested_header, next_sync_committee=SyncCommittee(), - next_sync_committee_branch=[Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))], + next_sync_committee_branch=NextSyncCommitteeBranch(), finalized_header=LightClientHeader(), - finality_branch=[Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))], + finality_branch=FinalityBranch(), sync_aggregate=optimistic_update.sync_aggregate, signature_slot=optimistic_update.signature_slot, ) diff --git a/specs/capella/light-client/full-node.md b/specs/capella/light-client/full-node.md index c59af8ec7..1d2f677cf 100644 --- a/specs/capella/light-client/full-node.md +++ b/specs/capella/light-client/full-node.md @@ -46,14 +46,15 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: transactions_root=hash_tree_root(payload.transactions), withdrawals_root=hash_tree_root(payload.withdrawals), ) - execution_branch = compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_INDEX) + execution_branch = ExecutionBranch( + compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_INDEX)) else: # Note that during fork transitions, `finalized_header` may still point to earlier forks. # While Bellatrix blocks also contain an `ExecutionPayload` (minus `withdrawals_root`), # it was not included in the corresponding light client data. To ensure compatibility # with legacy data going through `upgrade_lc_header_to_capella`, leave out execution data. execution_header = ExecutionPayloadHeader() - execution_branch = [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))] + execution_branch = ExecutionBranch() return LightClientHeader( beacon=BeaconBlockHeader( diff --git a/specs/capella/light-client/sync-protocol.md b/specs/capella/light-client/sync-protocol.md index c1281c459..057541bd3 100644 --- a/specs/capella/light-client/sync-protocol.md +++ b/specs/capella/light-client/sync-protocol.md @@ -41,7 +41,7 @@ Additional documents describes the impact of the upgrade on certain roles: ### `ExecutionBranch` ```python -class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]): +class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]): pass ``` @@ -81,7 +81,7 @@ def is_valid_light_client_header(header: LightClientHeader) -> bool: if epoch < CAPELLA_FORK_EPOCH: return ( header.execution == ExecutionPayloadHeader() - and header.execution_branch == [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))] + and header.execution_branch == ExecutionBranch() ) return is_valid_merkle_branch( diff --git a/specs/deneb/light-client/full-node.md b/specs/deneb/light-client/full-node.md index 18b97ae43..82814b346 100644 --- a/specs/deneb/light-client/full-node.md +++ b/specs/deneb/light-client/full-node.md @@ -52,14 +52,15 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: execution_header.blob_gas_used = payload.blob_gas_used execution_header.excess_blob_gas = payload.excess_blob_gas - execution_branch = compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_INDEX) + execution_branch = ExecutionBranch( + compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_INDEX)) else: # Note that during fork transitions, `finalized_header` may still point to earlier forks. # While Bellatrix blocks also contain an `ExecutionPayload` (minus `withdrawals_root`), # it was not included in the corresponding light client data. To ensure compatibility # with legacy data going through `upgrade_lc_header_to_capella`, leave out execution data. execution_header = ExecutionPayloadHeader() - execution_branch = [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))] + execution_branch = ExecutionBranch() return LightClientHeader( beacon=BeaconBlockHeader( diff --git a/specs/deneb/light-client/sync-protocol.md b/specs/deneb/light-client/sync-protocol.md index 3b5663fa5..8f3972d32 100644 --- a/specs/deneb/light-client/sync-protocol.md +++ b/specs/deneb/light-client/sync-protocol.md @@ -74,7 +74,7 @@ def is_valid_light_client_header(header: LightClientHeader) -> bool: if epoch < CAPELLA_FORK_EPOCH: return ( header.execution == ExecutionPayloadHeader() - and header.execution_branch == [Bytes32() for _ in range(floorlog2(EXECUTION_PAYLOAD_INDEX))] + and header.execution_branch == ExecutionBranch() ) return is_valid_merkle_branch( From 02d47f1554e2b037136a40937631a3aa91fcfabc Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 9 Jan 2024 14:54:52 +0100 Subject: [PATCH 6/9] ensure `floorlog2` is available for use in `Custom types` section --- pysetup/helpers.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pysetup/helpers.py b/pysetup/helpers.py index b2fe00f75..44c98e06e 100644 --- a/pysetup/helpers.py +++ b/pysetup/helpers.py @@ -108,7 +108,7 @@ def objects_to_spec(preset_name: str, if vardef.comment is not None: out += f' # {vardef.comment}' return out - + # Merge all constant objects hardcoded_ssz_dep_constants = reduce(lambda obj, builder: {**obj, **builder.hardcoded_ssz_dep_constants()}, builders, {}) hardcoded_custom_type_dep_constants = reduce(lambda obj, builder: {**obj, **builder.hardcoded_custom_type_dep_constants(spec_object)}, builders, {}) @@ -131,12 +131,13 @@ def objects_to_spec(preset_name: str, imports, preparations, f"fork = \'{fork}\'\n", + # The helper functions that some SSZ containers require. Need to be defined before `custom_type_dep_constants` + CONSTANT_DEP_SUNDRY_CONSTANTS_FUNCTIONS, # The constants that some SSZ containers require. Need to be defined before `new_type_definitions` custom_type_dep_constants, - new_type_definitions, - CONSTANT_DEP_SUNDRY_CONSTANTS_FUNCTIONS, # The constants that some SSZ containers require. Need to be defined before `constants_spec` ssz_dep_constants, + new_type_definitions, constant_vars_spec, preset_vars_spec, config_spec, From c41c128c760f892e2b4f37d60807e03da06b9e3e Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 9 Jan 2024 14:55:22 +0100 Subject: [PATCH 7/9] Use `Custom types` section instead of `Helper types` for consistency --- specs/altair/light-client/sync-protocol.md | 36 ++++++--------------- specs/capella/light-client/sync-protocol.md | 19 ++++------- 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/specs/altair/light-client/sync-protocol.md b/specs/altair/light-client/sync-protocol.md index 58a38d150..955fc82f9 100644 --- a/specs/altair/light-client/sync-protocol.md +++ b/specs/altair/light-client/sync-protocol.md @@ -9,13 +9,10 @@ - [Introduction](#introduction) +- [Custom types](#custom-types) - [Constants](#constants) - [Preset](#preset) - [Misc](#misc) -- [Helper types](#helper-types) - - [`FinalityBranch`](#finalitybranch) - - [`CurrentSyncCommitteeBranch`](#currentsynccommitteebranch) - - [`NextSyncCommitteeBranch`](#nextsynccommitteebranch) - [Containers](#containers) - [`LightClientHeader`](#lightclientheader) - [`LightClientBootstrap`](#lightclientbootstrap) @@ -60,6 +57,14 @@ Additional documents describe how the light client sync protocol can be used: - [Light client](./light-client.md) - [Networking](./p2p-interface.md) +## Custom types + +| Name | SSZ equivalent | Description | +| - | - | - | +| `FinalityBranch` | `Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]` | Merkle branch of `finalized_checkpoint.root` within `BeaconState` | +| `CurrentSyncCommitteeBranch` | `Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)]` | Merkle branch of `current_sync_committee` within `BeaconState` | +| `NextSyncCommitteeBranch` | `Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)]` | Merkle branch of `next_sync_committee` within `BeaconState` | + ## Constants | Name | Value | @@ -77,29 +82,6 @@ Additional documents describe how the light client sync protocol can be used: | `MIN_SYNC_COMMITTEE_PARTICIPANTS` | `1` | validators | | | `UPDATE_TIMEOUT` | `SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD` | slots | ~27.3 hours | -## Helper types - -### `FinalityBranch` - -```python -class FinalityBranch(Vector[Bytes32, floorlog2(FINALIZED_ROOT_INDEX)]): - pass -``` - -### `CurrentSyncCommitteeBranch` - -```python -class CurrentSyncCommitteeBranch(Vector[Bytes32, floorlog2(CURRENT_SYNC_COMMITTEE_INDEX)]): - pass -``` - -### `NextSyncCommitteeBranch` - -```python -class NextSyncCommitteeBranch(Vector[Bytes32, floorlog2(NEXT_SYNC_COMMITTEE_INDEX)]): - pass -``` - ## Containers ### `LightClientHeader` diff --git a/specs/capella/light-client/sync-protocol.md b/specs/capella/light-client/sync-protocol.md index 057541bd3..2abe5d58c 100644 --- a/specs/capella/light-client/sync-protocol.md +++ b/specs/capella/light-client/sync-protocol.md @@ -9,9 +9,8 @@ - [Introduction](#introduction) +- [Custom types](#custom-types) - [Constants](#constants) -- [Helper types](#helper-types) - - [`ExecutionBranch`](#executionbranch) - [Containers](#containers) - [Modified `LightClientHeader`](#modified-lightclientheader) - [Helper functions](#helper-functions) @@ -29,22 +28,18 @@ Additional documents describes the impact of the upgrade on certain roles: - [Full node](./full-node.md) - [Networking](./p2p-interface.md) +## Custom types + +| Name | SSZ equivalent | Description | +| - | - | - | +| `ExecutionBranch` | `Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]` | Merkle branch of `execution_payload` within `BeaconBlockBody` | + ## Constants | Name | Value | | - | - | | `EXECUTION_PAYLOAD_INDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload')` (= 25) | - -## Helper types - -### `ExecutionBranch` - -```python -class ExecutionBranch(Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]): - pass -``` - ## Containers ### Modified `LightClientHeader` From 9ebf456e5a5ab3cd5f7e7d8d10aa9017b3dc9250 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Tue, 9 Jan 2024 15:09:38 +0100 Subject: [PATCH 8/9] Move `Vector` support from main section parser to types section parser --- pysetup/helpers.py | 10 +++++++--- setup.py | 13 ++----------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/pysetup/helpers.py b/pysetup/helpers.py index 44c98e06e..77743c8fe 100644 --- a/pysetup/helpers.py +++ b/pysetup/helpers.py @@ -22,8 +22,11 @@ def collect_prev_forks(fork: str) -> list[str]: forks.append(fork) -def is_byte_vector(value: str) -> bool: - return value.startswith(('ByteVector')) +def requires_mypy_type_ignore(value: str) -> bool: + return ( + value.startswith(('ByteVector')) + or (value.startswith(('Vector')) and 'floorlog2' in value) + ) def make_function_abstract(protocol_def: ProtocolDefinition, key: str): @@ -41,7 +44,8 @@ def objects_to_spec(preset_name: str, new_type_definitions = ( '\n\n'.join( [ - f"class {key}({value}):\n pass\n" if not is_byte_vector(value) else f"class {key}({value}): # type: ignore\n pass\n" + f"class {key}({value}):\n pass\n" if not requires_mypy_type_ignore(value) + else f"class {key}({value}): # type: ignore\n pass\n" for key, value in spec_object.custom_types.items() ] ) diff --git a/setup.py b/setup.py index cd6d1f180..cf2deb859 100644 --- a/setup.py +++ b/setup.py @@ -218,19 +218,10 @@ def get_spec(file_name: Path, preset: Dict[str, str], config: Dict[str, str], pr class_name, parent_class = _get_class_info_from_source(source) # check consistency with spec assert class_name == current_name - ignore_type = False if parent_class: - if parent_class == "Container": - pass - elif parent_class == "Vector": - ignore_type = True # Avoid Mypy error: Invalid base class "Vector" - else: - raise Exception("unrecognized parent class: " + source) + assert parent_class == "Container" # NOTE: trim whitespace from spec - lines = [line.rstrip() for line in source.splitlines()] - if ignore_type: - lines[0] += " # type: ignore" - ssz_objects[current_name] = "\n".join(lines) + ssz_objects[current_name] = "\n".join(line.rstrip() for line in source.splitlines()) else: raise Exception("unrecognized python code element: " + source) elif isinstance(child, Table): From 82143e1977a8e0beed25d98fb42b6a48ad63df74 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Mon, 15 Jan 2024 12:48:22 +0100 Subject: [PATCH 9/9] Also bump `EXECUTION_PAYLOAD_GINDEX` --- pysetup/spec_builders/capella.py | 2 +- pysetup/spec_builders/whisk.py | 2 +- specs/capella/light-client/full-node.md | 2 +- specs/capella/light-client/sync-protocol.md | 8 ++++---- specs/deneb/light-client/full-node.md | 2 +- specs/deneb/light-client/sync-protocol.md | 4 ++-- .../test/capella/light_client/test_single_merkle_proof.py | 8 ++++---- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/pysetup/spec_builders/capella.py b/pysetup/spec_builders/capella.py index 080bdb537..6630b94f1 100644 --- a/pysetup/spec_builders/capella.py +++ b/pysetup/spec_builders/capella.py @@ -16,5 +16,5 @@ from eth2spec.bellatrix import {preset_name} as bellatrix @classmethod def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]: return { - 'EXECUTION_PAYLOAD_INDEX': 'GeneralizedIndex(25)', + 'EXECUTION_PAYLOAD_GINDEX': 'GeneralizedIndex(25)', } diff --git a/pysetup/spec_builders/whisk.py b/pysetup/spec_builders/whisk.py index c892a1c08..6b4c5a7d7 100644 --- a/pysetup/spec_builders/whisk.py +++ b/pysetup/spec_builders/whisk.py @@ -27,6 +27,6 @@ import json @classmethod def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]: constants = { - 'EXECUTION_PAYLOAD_INDEX': 'GeneralizedIndex(41)', + 'EXECUTION_PAYLOAD_GINDEX': 'GeneralizedIndex(41)', } return {**super().hardcoded_ssz_dep_constants(), **constants} diff --git a/specs/capella/light-client/full-node.md b/specs/capella/light-client/full-node.md index 1d2f677cf..319fb1c94 100644 --- a/specs/capella/light-client/full-node.md +++ b/specs/capella/light-client/full-node.md @@ -47,7 +47,7 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: withdrawals_root=hash_tree_root(payload.withdrawals), ) execution_branch = ExecutionBranch( - compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_INDEX)) + compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_GINDEX)) else: # Note that during fork transitions, `finalized_header` may still point to earlier forks. # While Bellatrix blocks also contain an `ExecutionPayload` (minus `withdrawals_root`), diff --git a/specs/capella/light-client/sync-protocol.md b/specs/capella/light-client/sync-protocol.md index 2abe5d58c..b241b2137 100644 --- a/specs/capella/light-client/sync-protocol.md +++ b/specs/capella/light-client/sync-protocol.md @@ -32,13 +32,13 @@ Additional documents describes the impact of the upgrade on certain roles: | Name | SSZ equivalent | Description | | - | - | - | -| `ExecutionBranch` | `Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_INDEX)]` | Merkle branch of `execution_payload` within `BeaconBlockBody` | +| `ExecutionBranch` | `Vector[Bytes32, floorlog2(EXECUTION_PAYLOAD_GINDEX)]` | Merkle branch of `execution_payload` within `BeaconBlockBody` | ## Constants | Name | Value | | - | - | -| `EXECUTION_PAYLOAD_INDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload')` (= 25) | +| `EXECUTION_PAYLOAD_GINDEX` | `get_generalized_index(BeaconBlockBody, 'execution_payload')` (= 25) | ## Containers @@ -82,8 +82,8 @@ def is_valid_light_client_header(header: LightClientHeader) -> bool: return is_valid_merkle_branch( leaf=get_lc_execution_root(header), branch=header.execution_branch, - depth=floorlog2(EXECUTION_PAYLOAD_INDEX), - index=get_subtree_index(EXECUTION_PAYLOAD_INDEX), + depth=floorlog2(EXECUTION_PAYLOAD_GINDEX), + index=get_subtree_index(EXECUTION_PAYLOAD_GINDEX), root=header.beacon.body_root, ) ``` diff --git a/specs/deneb/light-client/full-node.md b/specs/deneb/light-client/full-node.md index 82814b346..db081b8e4 100644 --- a/specs/deneb/light-client/full-node.md +++ b/specs/deneb/light-client/full-node.md @@ -53,7 +53,7 @@ def block_to_light_client_header(block: SignedBeaconBlock) -> LightClientHeader: execution_header.excess_blob_gas = payload.excess_blob_gas execution_branch = ExecutionBranch( - compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_INDEX)) + compute_merkle_proof(block.message.body, EXECUTION_PAYLOAD_GINDEX)) else: # Note that during fork transitions, `finalized_header` may still point to earlier forks. # While Bellatrix blocks also contain an `ExecutionPayload` (minus `withdrawals_root`), diff --git a/specs/deneb/light-client/sync-protocol.md b/specs/deneb/light-client/sync-protocol.md index 8f3972d32..38aa3897b 100644 --- a/specs/deneb/light-client/sync-protocol.md +++ b/specs/deneb/light-client/sync-protocol.md @@ -80,8 +80,8 @@ def is_valid_light_client_header(header: LightClientHeader) -> bool: return is_valid_merkle_branch( leaf=get_lc_execution_root(header), branch=header.execution_branch, - depth=floorlog2(EXECUTION_PAYLOAD_INDEX), - index=get_subtree_index(EXECUTION_PAYLOAD_INDEX), + depth=floorlog2(EXECUTION_PAYLOAD_GINDEX), + index=get_subtree_index(EXECUTION_PAYLOAD_GINDEX), root=header.beacon.body_root, ) ``` diff --git a/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py b/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py index 8401a9444..41bb3f307 100644 --- a/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py +++ b/tests/core/pyspec/eth2spec/test/capella/light_client/test_single_merkle_proof.py @@ -15,16 +15,16 @@ def test_execution_merkle_proof(spec, state): block = state_transition_with_full_block(spec, state, True, False) yield "object", block.message.body - execution_branch = spec.compute_merkle_proof(block.message.body, spec.EXECUTION_PAYLOAD_INDEX) + execution_branch = spec.compute_merkle_proof(block.message.body, spec.EXECUTION_PAYLOAD_GINDEX) yield "proof", { "leaf": "0x" + block.message.body.execution_payload.hash_tree_root().hex(), - "leaf_index": spec.EXECUTION_PAYLOAD_INDEX, + "leaf_index": spec.EXECUTION_PAYLOAD_GINDEX, "branch": ['0x' + root.hex() for root in execution_branch] } assert spec.is_valid_merkle_branch( leaf=block.message.body.execution_payload.hash_tree_root(), branch=execution_branch, - depth=spec.floorlog2(spec.EXECUTION_PAYLOAD_INDEX), - index=spec.get_subtree_index(spec.EXECUTION_PAYLOAD_INDEX), + depth=spec.floorlog2(spec.EXECUTION_PAYLOAD_GINDEX), + index=spec.get_subtree_index(spec.EXECUTION_PAYLOAD_GINDEX), root=block.message.body.hash_tree_root(), )