From c10daf1709b973ce2bbc3948d82db0b165d51574 Mon Sep 17 00:00:00 2001 From: Etan Kissling Date: Mon, 9 May 2022 14:37:54 +0200 Subject: [PATCH] Allow `LightClientUpdate` with genesis finality When `state.finalized_checkpoint` references the genesis slot, it points to an empty `root`, instead of the actual genesis block hash. This patch updates the `LightClientUpdate` logic to allow including finality proofs for genesis `finalized_checkpoint.root`, better supporting non-mainnet. When including such a finality proof, the proof is for the empty `root`, but `finalized_header` is kept zeroed out to signify this edge case. --- specs/altair/sync-protocol.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/specs/altair/sync-protocol.md b/specs/altair/sync-protocol.md index a3b10efa2..c03db304f 100644 --- a/specs/altair/sync-protocol.md +++ b/specs/altair/sync-protocol.md @@ -100,7 +100,7 @@ class LightClientStore(object): ```python def is_finality_update(update: LightClientUpdate) -> bool: - return update.finalized_header != BeaconBlockHeader() + return update.finality_branch != [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))] ``` ### `get_subtree_index` @@ -173,10 +173,15 @@ def validate_light_client_update(store: LightClientStore, # Verify that the `finalized_header`, if present, actually is the finalized header saved in the # state of the `attested_header` if not is_finality_update(update): - assert update.finality_branch == [Bytes32() for _ in range(floorlog2(FINALIZED_ROOT_INDEX))] + assert update.finalized_header == BeaconBlockHeader() else: + if update.finalized_header.slot != GENESIS_SLOT: + finalized_root = hash_tree_root(update.finalized_header) + else: + finalized_root = Bytes32() + assert update.finalized_header == BeaconBlockHeader() assert is_valid_merkle_branch( - leaf=hash_tree_root(update.finalized_header), + leaf=finalized_root, branch=update.finality_branch, depth=floorlog2(FINALIZED_ROOT_INDEX), index=get_subtree_index(FINALIZED_ROOT_INDEX),