diff --git a/setup.py b/setup.py index cd6a5264f..0c37e33c6 100644 --- a/setup.py +++ b/setup.py @@ -475,7 +475,12 @@ def get_generalized_index(ssz_class: Any, *path: Sequence[PyUnion[int, SSZVariab ssz_path = Path(ssz_class) for item in path: ssz_path = ssz_path / item - return GeneralizedIndex(ssz_path.gindex())''' + return GeneralizedIndex(ssz_path.gindex()) + + +def compute_merkle_proof_for_state(state: BeaconState, + index: GeneralizedIndex) -> Sequence[Bytes32]: + return build_proof(state.get_backing(), index)''' @classmethod @@ -613,7 +618,11 @@ def objects_to_spec(preset_name: str, protocols_spec = '\n\n\n'.join(format_protocol(k, v) for k, v in spec_object.protocols.items()) for k in list(spec_object.functions): - if "ceillog2" in k or "floorlog2" in k: + if k in [ + "ceillog2", + "floorlog2", + "compute_merkle_proof_for_state", + ]: del spec_object.functions[k] functions = builder.implement_optimizations(spec_object.functions) functions_spec = '\n\n\n'.join(functions.values()) diff --git a/specs/altair/sync-protocol.md b/specs/altair/sync-protocol.md index a07adbd67..ed1b02152 100644 --- a/specs/altair/sync-protocol.md +++ b/specs/altair/sync-protocol.md @@ -22,8 +22,9 @@ - [`is_better_update`](#is_better_update) - [`is_next_sync_committee_known`](#is_next_sync_committee_known) - [`get_safety_threshold`](#get_safety_threshold) - - [`get_subtree_index`](#get_subtree_index) - [`compute_sync_committee_period_at_slot`](#compute_sync_committee_period_at_slot) + - [`get_subtree_index`](#get_subtree_index) + - [`compute_merkle_proof_for_state`](#compute_merkle_proof_for_state) - [Light client initialization](#light-client-initialization) - [`initialize_light_client_store`](#initialize_light_client_store) - [Light client state updates](#light-client-state-updates) @@ -204,6 +205,13 @@ def get_safety_threshold(store: LightClientStore) -> uint64: ) // 2 ``` +### `compute_sync_committee_period_at_slot` + +```python +def compute_sync_committee_period_at_slot(slot: Slot) -> uint64: + return compute_sync_committee_period(compute_epoch_at_slot(slot)) +``` + ### `get_subtree_index` ```python @@ -211,11 +219,12 @@ def get_subtree_index(generalized_index: GeneralizedIndex) -> uint64: return uint64(generalized_index % 2**(floorlog2(generalized_index))) ``` -### `compute_sync_committee_period_at_slot` +### `compute_merkle_proof_for_state` ```python -def compute_sync_committee_period_at_slot(slot: Slot) -> uint64: - return compute_sync_committee_period(compute_epoch_at_slot(slot)) +def compute_merkle_proof_for_state(state: BeaconState, + index: GeneralizedIndex) -> Sequence[Bytes32]: + ... ``` ## Light client initialization @@ -441,7 +450,7 @@ def create_light_client_bootstrap(state: BeaconState) -> LightClientBootstrap: body_root=state.latest_block_header.body_root, ), current_sync_committee=state.current_sync_committee, - current_sync_committee_branch=build_proof(state.get_backing(), CURRENT_SYNC_COMMITTEE_INDEX) + current_sync_committee_branch=compute_merkle_proof_for_state(state, CURRENT_SYNC_COMMITTEE_INDEX) ) ``` @@ -482,7 +491,7 @@ 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: next_sync_committee = attested_state.next_sync_committee - next_sync_committee_branch = build_proof(attested_state.get_backing(), NEXT_SYNC_COMMITTEE_INDEX) + next_sync_committee_branch = compute_merkle_proof_for_state(attested_state, NEXT_SYNC_COMMITTEE_INDEX) else: next_sync_committee = SyncCommittee() next_sync_committee_branch = [Bytes32() for _ in range(floorlog2(NEXT_SYNC_COMMITTEE_INDEX))] @@ -501,7 +510,7 @@ def create_light_client_update(state: BeaconState, else: finalized_header = BeaconBlockHeader() assert attested_state.finalized_checkpoint.root == Bytes32() - finality_branch = build_proof(attested_state.get_backing(), FINALIZED_ROOT_INDEX) + finality_branch = compute_merkle_proof_for_state(attested_state, FINALIZED_ROOT_INDEX) else: finalized_header = BeaconBlockHeader() finality_branch = [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))] diff --git a/tests/core/pyspec/eth2spec/test/altair/merkle/test_single_proof.py b/tests/core/pyspec/eth2spec/test/altair/merkle/test_single_proof.py index d90feb146..064760bf0 100644 --- a/tests/core/pyspec/eth2spec/test/altair/merkle/test_single_proof.py +++ b/tests/core/pyspec/eth2spec/test/altair/merkle/test_single_proof.py @@ -2,14 +2,13 @@ from eth2spec.test.context import ( spec_state_test, with_altair_and_later, ) -from eth2spec.test.helpers.merkle import build_proof @with_altair_and_later @spec_state_test def test_current_sync_committee_merkle_proof(spec, state): yield "state", state - current_sync_committee_branch = build_proof(state.get_backing(), spec.CURRENT_SYNC_COMMITTEE_INDEX) + current_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.CURRENT_SYNC_COMMITTEE_INDEX) yield "proof", { "leaf": "0x" + state.current_sync_committee.hash_tree_root().hex(), "leaf_index": spec.CURRENT_SYNC_COMMITTEE_INDEX, @@ -28,7 +27,7 @@ def test_current_sync_committee_merkle_proof(spec, state): @spec_state_test def test_next_sync_committee_merkle_proof(spec, state): yield "state", state - next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX) + next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX) yield "proof", { "leaf": "0x" + state.next_sync_committee.hash_tree_root().hex(), "leaf_index": spec.NEXT_SYNC_COMMITTEE_INDEX, @@ -47,7 +46,7 @@ def test_next_sync_committee_merkle_proof(spec, state): @spec_state_test def test_finality_root_merkle_proof(spec, state): yield "state", state - finality_branch = build_proof(state.get_backing(), spec.FINALIZED_ROOT_INDEX) + finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX) yield "proof", { "leaf": "0x" + state.finalized_checkpoint.root.hex(), "leaf_index": spec.FINALIZED_ROOT_INDEX, diff --git a/tests/core/pyspec/eth2spec/test/altair/sync_protocol/test_update_ranking.py b/tests/core/pyspec/eth2spec/test/altair/sync_protocol/test_update_ranking.py index 4b73a15ba..ae5d5296a 100644 --- a/tests/core/pyspec/eth2spec/test/altair/sync_protocol/test_update_ranking.py +++ b/tests/core/pyspec/eth2spec/test/altair/sync_protocol/test_update_ranking.py @@ -15,7 +15,6 @@ from eth2spec.test.helpers.light_client import ( from eth2spec.test.helpers.state import ( next_slots, ) -from eth2spec.test.helpers.merkle import build_proof from math import floor @@ -27,14 +26,14 @@ def create_update(spec, test, with_next_sync_committee, with_finality, participa if with_next_sync_committee: next_sync_committee = attested_state.next_sync_committee - next_sync_committee_branch = build_proof(attested_state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX) + next_sync_committee_branch = spec.compute_merkle_proof_for_state(attested_state, spec.NEXT_SYNC_COMMITTEE_INDEX) else: next_sync_committee = spec.SyncCommittee() next_sync_committee_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.NEXT_SYNC_COMMITTEE_INDEX))] if with_finality: finalized_header = signed_block_to_header(spec, finalized_block) - finality_branch = build_proof(attested_state.get_backing(), spec.FINALIZED_ROOT_INDEX) + finality_branch = spec.compute_merkle_proof_for_state(attested_state, spec.FINALIZED_ROOT_INDEX) else: finalized_header = spec.BeaconBlockHeader() finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))] diff --git a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py index 17c450f17..e7845292a 100644 --- a/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py +++ b/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py @@ -18,7 +18,6 @@ from eth2spec.test.helpers.light_client import ( from eth2spec.test.helpers.state import ( next_slots, ) -from eth2spec.test.helpers.merkle import build_proof @with_altair_and_later @@ -125,7 +124,7 @@ def test_process_light_client_update_timeout(spec, state): # Sync committee is updated next_sync_committee = state.next_sync_committee - next_sync_committee_branch = build_proof(state.get_backing(), spec.NEXT_SYNC_COMMITTEE_INDEX) + next_sync_committee_branch = spec.compute_merkle_proof_for_state(state, spec.NEXT_SYNC_COMMITTEE_INDEX) # Finality is unchanged finality_header = spec.BeaconBlockHeader() finality_branch = [spec.Bytes32() for _ in range(spec.floorlog2(spec.FINALIZED_ROOT_INDEX))] @@ -182,7 +181,7 @@ def test_process_light_client_update_finality_updated(spec, state): finalized_header = signed_block_to_header(spec, finalized_block) assert finalized_header.slot == spec.compute_start_slot_at_epoch(state.finalized_checkpoint.epoch) assert finalized_header.hash_tree_root() == state.finalized_checkpoint.root - finality_branch = build_proof(state.get_backing(), spec.FINALIZED_ROOT_INDEX) + finality_branch = spec.compute_merkle_proof_for_state(state, spec.FINALIZED_ROOT_INDEX) update = spec.LightClientUpdate( attested_header=attested_header,