From b732faa0178e1cdf86d9540086b6246628e9b111 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Mon, 3 Jan 2022 09:54:30 +0000 Subject: [PATCH 1/2] use v1.1.7 test vectors --- ConsensusSpecPreset-mainnet.md | 10 +- ConsensusSpecPreset-minimal.md | 10 +- beacon_chain/spec/datatypes/altair.nim | 54 +++--- beacon_chain/spec/datatypes/base.nim | 2 +- beacon_chain/spec/light_client_sync.nim | 163 +++++++++++------- .../test_fixture_ssz_consensus_objects.nim | 1 - .../altair/test_fixture_sync_protocol.nim | 110 +++++++----- tests/consensus_spec/fixtures_utils.nim | 2 +- .../test_fixture_ssz_consensus_objects.nim | 1 - vendor/nim-eth2-scenarios | 2 +- 10 files changed, 206 insertions(+), 149 deletions(-) diff --git a/ConsensusSpecPreset-mainnet.md b/ConsensusSpecPreset-mainnet.md index fac55f2910..c32ff5e8ff 100644 --- a/ConsensusSpecPreset-mainnet.md +++ b/ConsensusSpecPreset-mainnet.md @@ -739,7 +739,6 @@ OK: 1/1 Fail: 0/1 Skip: 0/1 + Testing ForkData OK + Testing HistoricalBatch OK + Testing IndexedAttestation OK -+ Testing LightClientSnapshot OK + Testing LightClientUpdate OK + Testing PendingAttestation OK + Testing ProposerSlashing OK @@ -757,12 +756,12 @@ OK: 1/1 Fail: 0/1 Skip: 0/1 + Testing Validator OK + Testing VoluntaryExit OK ``` -OK: 36/36 Fail: 0/36 Skip: 0/36 +OK: 35/35 Fail: 0/35 Skip: 0/35 ## Ethereum Foundation - Altair - Unittests - Sync protocol [Preset: mainnet] ```diff + process_light_client_update_finality_updated OK -+ process_light_client_update_not_updated OK + process_light_client_update_timeout OK ++ test_process_light_client_update_not_timeout OK ``` OK: 3/3 Fail: 0/3 Skip: 0/3 ## Ethereum Foundation - ForkChoice [Preset: mainnet] @@ -902,7 +901,6 @@ OK: 1/1 Fail: 0/1 Skip: 0/1 + Testing ForkData OK + Testing HistoricalBatch OK + Testing IndexedAttestation OK -+ Testing LightClientSnapshot OK + Testing LightClientUpdate OK + Testing PendingAttestation OK + Testing PowBlock OK @@ -921,7 +919,7 @@ OK: 1/1 Fail: 0/1 Skip: 0/1 + Testing Validator OK + Testing VoluntaryExit OK ``` -OK: 39/39 Fail: 0/39 Skip: 0/39 +OK: 38/38 Fail: 0/38 Skip: 0/38 ## Ethereum Foundation - Phase 0 - Epoch Processing - Effective balance updates [Preset: mainnet] ```diff + Effective balance updates - effective_balance_hysteresis [Preset: mainnet] OK @@ -1167,4 +1165,4 @@ OK: 44/44 Fail: 0/44 Skip: 0/44 OK: 27/27 Fail: 0/27 Skip: 0/27 ---TOTAL--- -OK: 991/993 Fail: 0/993 Skip: 2/993 +OK: 989/991 Fail: 0/991 Skip: 2/991 diff --git a/ConsensusSpecPreset-minimal.md b/ConsensusSpecPreset-minimal.md index 27c29734ee..0fc96251cf 100644 --- a/ConsensusSpecPreset-minimal.md +++ b/ConsensusSpecPreset-minimal.md @@ -775,7 +775,6 @@ OK: 5/5 Fail: 0/5 Skip: 0/5 + Testing ForkData OK + Testing HistoricalBatch OK + Testing IndexedAttestation OK -+ Testing LightClientSnapshot OK + Testing LightClientUpdate OK + Testing PendingAttestation OK + Testing ProposerSlashing OK @@ -793,12 +792,12 @@ OK: 5/5 Fail: 0/5 Skip: 0/5 + Testing Validator OK + Testing VoluntaryExit OK ``` -OK: 36/36 Fail: 0/36 Skip: 0/36 +OK: 35/35 Fail: 0/35 Skip: 0/35 ## Ethereum Foundation - Altair - Unittests - Sync protocol [Preset: minimal] ```diff + process_light_client_update_finality_updated OK -+ process_light_client_update_not_updated OK + process_light_client_update_timeout OK ++ test_process_light_client_update_not_timeout OK ``` OK: 3/3 Fail: 0/3 Skip: 0/3 ## Ethereum Foundation - ForkChoice [Preset: minimal] @@ -963,7 +962,6 @@ OK: 5/5 Fail: 0/5 Skip: 0/5 + Testing ForkData OK + Testing HistoricalBatch OK + Testing IndexedAttestation OK -+ Testing LightClientSnapshot OK + Testing LightClientUpdate OK + Testing PendingAttestation OK + Testing PowBlock OK @@ -982,7 +980,7 @@ OK: 5/5 Fail: 0/5 Skip: 0/5 + Testing Validator OK + Testing VoluntaryExit OK ``` -OK: 39/39 Fail: 0/39 Skip: 0/39 +OK: 38/38 Fail: 0/38 Skip: 0/38 ## Ethereum Foundation - Phase 0 - Epoch Processing - Effective balance updates [Preset: minimal] ```diff + Effective balance updates - effective_balance_hysteresis [Preset: minimal] OK @@ -1239,4 +1237,4 @@ OK: 48/48 Fail: 0/48 Skip: 0/48 OK: 30/30 Fail: 0/30 Skip: 0/30 ---TOTAL--- -OK: 1037/1057 Fail: 0/1057 Skip: 20/1057 +OK: 1035/1055 Fail: 0/1055 Skip: 20/1055 diff --git a/beacon_chain/spec/datatypes/altair.nim b/beacon_chain/spec/datatypes/altair.nim index 402d17c8f0..3648feffaa 100644 --- a/beacon_chain/spec/datatypes/altair.nim +++ b/beacon_chain/spec/datatypes/altair.nim @@ -65,6 +65,10 @@ const INACTIVITY_SCORE_BIAS* = 4 INACTIVITY_SCORE_RECOVERY_RATE* = 16 + # https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#misc + # MIN_SYNC_COMMITTEE_PARTICIPANTS defined in presets + UPDATE_TIMEOUT* = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD + SYNC_SUBCOMMITTEE_SIZE* = SYNC_COMMITTEE_SIZE div SYNC_COMMITTEE_SUBNET_COUNT # "Note: The sum of the weights equal WEIGHT_DENOMINATOR." @@ -146,41 +150,45 @@ type ### Modified/overloaded - # https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/altair/sync-protocol.md#lightclientsnapshot - LightClientSnapshot* = object - header*: BeaconBlockHeader ##\ - ## Beacon block header - - current_sync_committee*: SyncCommittee ##\ - ## Sync committees corresponding to the header - - next_sync_committee*: SyncCommittee - - # https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/altair/sync-protocol.md#lightclientupdate + # https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#lightclientupdate LightClientUpdate* = object - header*: BeaconBlockHeader ##\ - ## Update beacon block header + attested_header*: BeaconBlockHeader ##\ + ## The beacon block header that is attested to by the sync committee - # Next sync committee corresponding to the header + # Next sync committee corresponding to the active header next_sync_committee*: SyncCommittee - next_sync_committee_branch*: array[log2trunc(NEXT_SYNC_COMMITTEE_INDEX), Eth2Digest] + next_sync_committee_branch*: + array[log2trunc(NEXT_SYNC_COMMITTEE_INDEX), Eth2Digest] - # Finality proof for the update header - finality_header*: BeaconBlockHeader + # The finalized beacon block header attested to by Merkle branch + finalized_header*: BeaconBlockHeader finality_branch*: array[log2trunc(FINALIZED_ROOT_INDEX), Eth2Digest] # Sync committee aggregate signature - sync_committee_bits*: BitArray[SYNC_COMMITTEE_SIZE] - sync_committee_signature*: ValidatorSig + sync_committee_aggregate*: SyncAggregate fork_version*: Version ##\ ## Fork version for the aggregate signature - # https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/altair/sync-protocol.md#lightclientstore + # https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#lightclientstore LightClientStore* = object - snapshot*: LightClientSnapshot - valid_updates*: HashSet[LightClientUpdate] - ## TODO: This will benefit from being an ordered set + finalized_header*: BeaconBlockHeader ##\ + ## Beacon block header that is finalized + + # Sync committees corresponding to the header + current_sync_committee*: SyncCommittee + next_sync_committee*: SyncCommittee + + best_valid_update*: Option[LightClientUpdate] ##\ + ## Best available header to switch finalized head to if we see nothing else + + optimistic_header*: BeaconBlockHeader ##\ + ## Most recent available reasonably-safe header + + # Max number of active participants in a sync committee (used to calculate + # safety threshold) + previous_max_active_participants*: uint64 + current_max_active_participants*: uint64 # https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/altair/beacon-chain.md#beaconstate BeaconState* = object diff --git a/beacon_chain/spec/datatypes/base.nim b/beacon_chain/spec/datatypes/base.nim index 00c9fec1c1..93cbf0cc5a 100644 --- a/beacon_chain/spec/datatypes/base.nim +++ b/beacon_chain/spec/datatypes/base.nim @@ -57,7 +57,7 @@ export # Eventually, we could also differentiate between user/tainted data and # internal state that's gone through sanity checks already. -const SPEC_VERSION* = "1.1.6" +const SPEC_VERSION* = "1.1.7" ## Spec version we're aiming to be compatible with, right now const diff --git a/beacon_chain/spec/light_client_sync.nim b/beacon_chain/spec/light_client_sync.nim index a689a8801b..22e974c0ce 100644 --- a/beacon_chain/spec/light_client_sync.nim +++ b/beacon_chain/spec/light_client_sync.nim @@ -4,112 +4,147 @@ import datatypes/altair, helpers -# https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/altair/sync-protocol.md#validate_light_client_update -proc validate_light_client_update*(snapshot: LightClientSnapshot, +# https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#get_active_header +func get_active_header(update: LightClientUpdate): BeaconBlockHeader = + # The "active header" is the header that the update is trying to convince + # us to accept. If a finalized header is present, it's the finalized + # header, otherwise it's the attested header + if update.finalized_header != BeaconBlockHeader(): + update.finalized_header + else: + update.attested_header + +# https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#validate_light_client_update +proc validate_light_client_update*(store: LightClientStore, update: LightClientUpdate, + current_slot: Slot, genesis_validators_root: Eth2Digest): bool = - # Verify update slot is larger than snapshot slot - if update.header.slot <= snapshot.header.slot: + # Verify update slot is larger than slot of current best finalized header + let active_header = get_active_header(update) + if not (current_slot >= active_header.slot and + active_header.slot > store.finalized_header.slot): return false # Verify update does not skip a sync committee period let - snapshot_period = sync_committee_period(snapshot.header.slot) - update_period = sync_committee_period(update.header.slot) - if update_period notin [snapshot_period, snapshot_period + 1]: + finalized_period = + compute_epoch_at_slot(store.finalized_header.slot) div + EPOCHS_PER_SYNC_COMMITTEE_PERIOD + update_period = + compute_epoch_at_slot(active_header.slot) div + EPOCHS_PER_SYNC_COMMITTEE_PERIOD + + if update_period notin [finalized_period, finalized_period + 1]: return false - # Verify update header root is the finalized root of the finality header, if specified - # TODO: Use a view type instead of `unsafeAddr` - let signed_header = if update.finality_header.isZeroMemory: + # Verify that the `finalized_header`, if present, actually is the finalized + # header saved in the state of the `attested header` + if update.finalized_header.isZeroMemory: if not update.finality_branch.isZeroMemory: return false - unsafeAddr update.header else: - if not is_valid_merkle_branch(hash_tree_root(update.header), + if not is_valid_merkle_branch(hash_tree_root(update.finalized_header), update.finality_branch, log2trunc(FINALIZED_ROOT_INDEX), get_subtree_index(FINALIZED_ROOT_INDEX), - update.finality_header.state_root): + update.attested_header.state_root): return false - unsafeAddr update.finality_header # Verify update next sync committee if the update period incremented # TODO: Use a view type instead of `unsafeAddr` - let sync_committee = if update_period == snapshot_period: + let sync_committee = if update_period == finalized_period: if not update.next_sync_committee_branch.isZeroMemory: return false - unsafeAddr snapshot.current_sync_committee + unsafeAddr store.current_sync_committee else: if not is_valid_merkle_branch(hash_tree_root(update.next_sync_committee), update.next_sync_committee_branch, log2trunc(NEXT_SYNC_COMMITTEE_INDEX), get_subtree_index(NEXT_SYNC_COMMITTEE_INDEX), - update.header.state_root): + active_header.state_root): return false - unsafeAddr snapshot.next_sync_committee + unsafeAddr store.next_sync_committee + + template sync_aggregate(): auto = update.sync_committee_aggregate + let sync_committee_participants_count = countOnes(sync_aggregate.sync_committee_bits) - let sync_committee_participants_count = countOnes(update.sync_committee_bits) # Verify sync committee has sufficient participants if sync_committee_participants_count < MIN_SYNC_COMMITTEE_PARTICIPANTS: return false # Verify sync committee aggregate signature - # participant_pubkeys = [pubkey for (bit, pubkey) in zip(update.sync_committee_bits, sync_committee.pubkeys) if bit] + # participant_pubkeys = [pubkey for (bit, pubkey) in zip(sync_aggregate.sync_committee_bits, sync_committee.pubkeys) if bit] var participant_pubkeys = newSeqOfCap[ValidatorPubKey](sync_committee_participants_count) - for idx, bit in update.sync_committee_bits: + for idx, bit in sync_aggregate.sync_committee_bits: if bit: participant_pubkeys.add(sync_committee.pubkeys[idx]) - let domain = compute_domain(DOMAIN_SYNC_COMMITTEE, update.fork_version, genesis_validators_root) - let signing_root = compute_signing_root(signed_header[], domain) + let domain = compute_domain( + DOMAIN_SYNC_COMMITTEE, update.fork_version, genesis_validators_root) + let signing_root = compute_signing_root(update.attested_header, domain) - blsFastAggregateVerify(participant_pubkeys, signing_root.data, update.sync_committee_signature) + blsFastAggregateVerify( + participant_pubkeys, signing_root.data, sync_aggregate.sync_committee_signature) -# https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/altair/sync-protocol.md#apply_light_client_update -proc apply_light_client_update(snapshot: var LightClientSnapshot, update: LightClientUpdate) = +# https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#apply_light_client_update +func apply_light_client_update( + store: var LightClientStore, update: LightClientUpdate) = let - snapshot_period = sync_committee_period(snapshot.header.slot) - update_period = sync_committee_period(update.header.slot) - if update_period == snapshot_period + 1: - snapshot.current_sync_committee = snapshot.next_sync_committee - snapshot.next_sync_committee = update.next_sync_committee - snapshot.header = update.header - -# https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/altair/sync-protocol.md#process_light_client_update + active_header = get_active_header(update) + finalized_period = + compute_epoch_at_slot(store.finalized_header.slot) div + EPOCHS_PER_SYNC_COMMITTEE_PERIOD + update_period = + compute_epoch_at_slot(active_header.slot) div + EPOCHS_PER_SYNC_COMMITTEE_PERIOD + if update_period == finalized_period + 1: + store.current_sync_committee = store.next_sync_committee + store.next_sync_committee = update.next_sync_committee + store.finalized_header = active_header + +# https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#get_safety_threshold +func get_safety_threshold(store: LightClientStore): uint64 = + max( + store.previous_max_active_participants, + store.current_max_active_participants + ) div 2 + +# https://github.com/ethereum/consensus-specs/blob/v1.1.7/specs/altair/sync-protocol.md#process_light_client_update proc process_light_client_update*(store: var LightClientStore, update: LightClientUpdate, current_slot: Slot, genesis_validators_root: Eth2Digest): bool = - if not validate_light_client_update(store.snapshot, update, genesis_validators_root): + if not validate_light_client_update( + store, update, current_slot, genesis_validators_root): return false - store.valid_updates.incl(update) - - var update_timeout = SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD - let sync_committee_participants_count = countOnes(update.sync_committee_bits) - if sync_committee_participants_count * 3 >= update.sync_committee_bits.len * 2 and - not update.finality_header.isZeroMemory: - # Apply update if (1) 2/3 quorum is reached and (2) we have a finality proof. - # Note that (2) means that the current light client design needs finality. - # It may be changed to re-organizable light client design. See the on-going issue consensus-specs#2182. - apply_light_client_update(store.snapshot, update) - store.valid_updates.clear() - elif current_slot > store.snapshot.header.slot + update_timeout: - var best_update_participants = 0 - # TODO: - # Use a view type to avoid the copying when a new best update - # is discovered. - # Alterantively, we could have a `set.max` operation returning - # the best item as a `lent` value. We would need an `OrderedSet` - # type with support for a custom comparison operation. - var best_update: LightClientUpdate - for update in store.valid_updates: - let update_participants = countOnes(update.sync_committee_bits) - if update_participants > best_update_participants: - best_update = update - best_update_participants = update_participants - - # Forced best update when the update timeout has elapsed - apply_light_client_update(store.snapshot, best_update) - store.valid_updates.clear() + + let + sync_committee_bits = update.sync_committee_aggregate.sync_committee_bits + sum_sync_committee_bits = countOnes(sync_committee_bits) + + # Update the best update in case we have to force-update to it if the + # timeout elapses + if store.best_valid_update.isNone or + sum_sync_committee_bits > countOnes( + store.best_valid_update.get.sync_committee_aggregate.sync_committee_bits): + store.best_valid_update = some(update) + + # Track the maximum number of active participants in the committee signatures + store.current_max_active_participants = max( + store.current_max_active_participants, + sum_sync_committee_bits.uint64, + ) + + # Update the optimistic header + if sum_sync_committee_bits.uint64 > get_safety_threshold(store) and + update.attested_header.slot > store.optimistic_header.slot: + store.optimistic_header = update.attested_header + + # Update finalized header + if sum_sync_committee_bits * 3 >= len(sync_committee_bits) * 2 and + update.finalized_header != default(BeaconBlockHeader): + # Normal update through 2/3 threshold + apply_light_client_update(store, update) + store.best_valid_update = none(LightClientUpdate) + true diff --git a/tests/consensus_spec/altair/test_fixture_ssz_consensus_objects.nim b/tests/consensus_spec/altair/test_fixture_ssz_consensus_objects.nim index 38fadfa248..42c202762b 100644 --- a/tests/consensus_spec/altair/test_fixture_ssz_consensus_objects.nim +++ b/tests/consensus_spec/altair/test_fixture_ssz_consensus_objects.nim @@ -114,7 +114,6 @@ suite "Ethereum Foundation - Altair - SSZ consensus objects " & preset(): of "ForkData": checkSSZ(ForkData, path, hash) of "HistoricalBatch": checkSSZ(HistoricalBatch, path, hash) of "IndexedAttestation": checkSSZ(IndexedAttestation, path, hash) - of "LightClientSnapshot": checkSSZ(LightClientSnapshot, path, hash) of "LightClientUpdate": checkSSZ(LightClientUpdate, path, hash) of "PendingAttestation": checkSSZ(PendingAttestation, path, hash) of "ProposerSlashing": checkSSZ(ProposerSlashing, path, hash) diff --git a/tests/consensus_spec/altair/test_fixture_sync_protocol.nim b/tests/consensus_spec/altair/test_fixture_sync_protocol.nim index 2efd69f93b..9144517b99 100644 --- a/tests/consensus_spec/altair/test_fixture_sync_protocol.nim +++ b/tests/consensus_spec/altair/test_fixture_sync_protocol.nim @@ -72,6 +72,18 @@ let full_sync_committee_bits = block: res.bytes.fill(byte.high) res +# https://github.com/ethereum/consensus-specs/blob/v1.1.7/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L24-L33 +func initialize_light_client_store(state: auto): LightClientStore = + LightClientStore( + finalized_header: BeaconBlockHeader(), + current_sync_committee: state.current_sync_committee, + next_sync_committee: state.next_sync_committee, + best_valid_update: none(LightClientUpdate), + optimistic_header: BeaconBlockHeader(), + previous_max_active_participants: 0, + current_max_active_participants: 0, + ) + suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): let cfg = block: @@ -80,15 +92,11 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): res genesisState = newClone(initGenesisState(cfg = cfg)) - # https://github.com/ethereum/consensus-specs/blob/v1.1.6/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L22-L78 - test "process_light_client_update_not_updated": + # https://github.com/ethereum/consensus-specs/blob/v1.1.7/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L36-L90 + test "test_process_light_client_update_not_timeout": var forked = assignClone(genesisState[]) template state: untyped {.inject.} = forked[].altairData.data - - let pre_snapshot = LightClientSnapshot( - current_sync_committee: state.current_sync_committee, - next_sync_committee: state.next_sync_committee) - var store = LightClientStore(snapshot: pre_snapshot) + var store = initialize_light_client_store(state) # Block at slot 1 doesn't increase sync committee period, # so it won't update snapshot @@ -108,52 +116,55 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): sync_committee_bits = full_sync_committee_bits sync_committee_signature = compute_aggregate_sync_committee_signature( forked[], committee) + sync_committee_aggregate = SyncAggregate( + sync_committee_bits: sync_committee_bits, + sync_committee_signature: sync_committee_signature) + var next_sync_committee_branch: array[log2trunc(NEXT_SYNC_COMMITTEE_INDEX), Eth2Digest] # Ensure that finality checkpoint is genesis check: state.finalized_checkpoint.epoch == 0 # Finality is unchanged - let finality_header = BeaconBlockHeader() + let + finality_header = BeaconBlockHeader() + pre_store_finalized_header = store.finalized_header var finality_branch: array[log2trunc(FINALIZED_ROOT_INDEX), Eth2Digest] let update = LightClientUpdate( - header: block_header, + attested_header: block_header, next_sync_committee: state.next_sync_committee, next_sync_committee_branch: next_sync_committee_branch, - finality_header: finality_header, + finalized_header: finality_header, finality_branch: finality_branch, - sync_committee_bits: sync_committee_bits, - sync_committee_signature: sync_committee_signature, + sync_committee_aggregate: sync_committee_aggregate, fork_version: state.fork.current_version) check: process_light_client_update( store, update, state.slot, state.genesis_validators_root) - len(store.valid_updates) == 1 - store.valid_updates.pop() == update - store.snapshot == pre_snapshot + store.current_max_active_participants > 0 + store.optimistic_header == update.attested_header + store.finalized_header == pre_store_finalized_header + store.best_valid_update.get == update - # https://github.com/ethereum/consensus-specs/blob/v1.1.6/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L81-L144 + # https://github.com/ethereum/consensus-specs/blob/v1.1.7/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L93-L154 test "process_light_client_update_timeout": var forked = assignClone(genesisState[]) template state: untyped {.inject.} = forked[].altairData.data - - let pre_snapshot = LightClientSnapshot( - current_sync_committee: state.current_sync_committee, - next_sync_committee: state.next_sync_committee) - var store = LightClientStore(snapshot: pre_snapshot) + var store = initialize_light_client_store(state) # Forward to next sync committee period var cache = StateCache() info = ForkedEpochInfo() doAssert process_slots( - cfg, forked[], Slot(SLOTS_PER_EPOCH * EPOCHS_PER_SYNC_COMMITTEE_PERIOD), - cache, info, flags = {}) + cfg, forked[], Slot(UPDATE_TIMEOUT), cache, info, flags = {}) let - snapshot_period = sync_committee_period(pre_snapshot.header.slot) + snapshot_period = + compute_epoch_at_slot(store.optimistic_header.slot) div + EPOCHS_PER_SYNC_COMMITTEE_PERIOD update_period = sync_committee_period(state.slot) check: snapshot_period + 1 == update_period @@ -173,23 +184,27 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): sync_committee_bits = full_sync_committee_bits sync_committee_signature = compute_aggregate_sync_committee_signature( forked[], committee, block_root = block_header.hash_tree_root()) + sync_committee_aggregate = SyncAggregate( + sync_committee_bits: sync_committee_bits, + sync_committee_signature: sync_committee_signature) # Sync committee is updated var next_sync_committee_branch {.noinit.}: array[log2trunc(NEXT_SYNC_COMMITTEE_INDEX), Eth2Digest] build_proof(state, NEXT_SYNC_COMMITTEE_INDEX, next_sync_committee_branch) # Finality is unchanged - let finality_header = BeaconBlockHeader() + let + finality_header = BeaconBlockHeader() + pre_store_finalized_header = store.finalized_header var finality_branch: array[log2trunc(FINALIZED_ROOT_INDEX), Eth2Digest] let update = LightClientUpdate( - header: block_header, + attested_header: block_header, next_sync_committee: state.next_sync_committee, next_sync_committee_branch: next_sync_committee_branch, - finality_header: finality_header, + finalized_header: finality_header, finality_branch: finality_branch, - sync_committee_bits: sync_committee_bits, - sync_committee_signature: sync_committee_signature, + sync_committee_aggregate: sync_committee_aggregate, fork_version: state.fork.current_version) check: @@ -197,18 +212,16 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): store, update, state.slot, state.genesis_validators_root) # snapshot has been updated - len(store.valid_updates) == 0 - store.snapshot.header == update.header + store.current_max_active_participants > 0 + store.optimistic_header == update.attested_header + store.best_valid_update.get == update + store.finalized_header == pre_store_finalized_header - # https://github.com/ethereum/consensus-specs/blob/v1.1.6/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L150-L218 + # https://github.com/ethereum/consensus-specs/blob/v1.1.7/tests/core/pyspec/eth2spec/test/altair/unittests/test_sync_protocol.py#L157-L224 test "process_light_client_update_finality_updated": var forked = assignClone(genesisState[]) template state: untyped {.inject.} = forked[].altairData.data - - let pre_snapshot = LightClientSnapshot( - current_sync_committee: state.current_sync_committee, - next_sync_committee: state.next_sync_committee) - var store = LightClientStore(snapshot: pre_snapshot) + var store = initialize_light_client_store(state) # Change finality var @@ -225,8 +238,11 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): check: state.finalized_checkpoint.epoch == 3 # Ensure that it's same period let - snapshot_period = sync_committee_period(pre_snapshot.header.slot) - update_period = sync_committee_period(state.slot) + snapshot_period = + compute_epoch_at_slot(store.optimistic_header.slot) div + EPOCHS_PER_SYNC_COMMITTEE_PERIOD + update_period = + compute_epoch_at_slot(state.slot) div EPOCHS_PER_SYNC_COMMITTEE_PERIOD check: snapshot_period == update_period # Updated sync_committee and finality @@ -266,15 +282,17 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): sync_committee_bits = full_sync_committee_bits sync_committee_signature = compute_aggregate_sync_committee_signature( forked[], committee, block_root = block_header.hash_tree_root()) + sync_committee_aggregate = SyncAggregate( + sync_committee_bits: sync_committee_bits, + sync_committee_signature: sync_committee_signature) update = LightClientUpdate( - header: finalized_block_header, + attested_header: block_header, next_sync_committee: state.next_sync_committee, next_sync_committee_branch: next_sync_committee_branch, - finality_header: block_header, + finalized_header: finalized_block_header, finality_branch: finality_branch, - sync_committee_bits: sync_committee_bits, - sync_committee_signature: sync_committee_signature, + sync_committee_aggregate: sync_committee_aggregate, fork_version: state.fork.current_version) check: @@ -282,5 +300,7 @@ suite "Ethereum Foundation - Altair - Unittests - Sync protocol" & preset(): store, update, state.slot, state.genesis_validators_root) # snapshot has been updated - len(store.valid_updates) == 0 - store.snapshot.header == update.header + store.current_max_active_participants > 0 + store.optimistic_header == update.attested_header + store.finalized_header == update.finalized_header + store.best_valid_update.isNone diff --git a/tests/consensus_spec/fixtures_utils.nim b/tests/consensus_spec/fixtures_utils.nim index 79ec74d6d5..814146d47f 100644 --- a/tests/consensus_spec/fixtures_utils.nim +++ b/tests/consensus_spec/fixtures_utils.nim @@ -50,7 +50,7 @@ type const FixturesDir* = currentSourcePath.rsplit(DirSep, 1)[0] / ".." / ".." / "vendor" / "nim-eth2-scenarios" - SszTestsDir* = FixturesDir / "tests-v1.1.6" + SszTestsDir* = FixturesDir / "tests-v1.1.7" MaxObjectSize* = 3_000_000 proc parseTest*(path: string, Format: typedesc[Json], T: typedesc): T = diff --git a/tests/consensus_spec/merge/test_fixture_ssz_consensus_objects.nim b/tests/consensus_spec/merge/test_fixture_ssz_consensus_objects.nim index 4602fd37b4..8d2bc0ce85 100644 --- a/tests/consensus_spec/merge/test_fixture_ssz_consensus_objects.nim +++ b/tests/consensus_spec/merge/test_fixture_ssz_consensus_objects.nim @@ -117,7 +117,6 @@ suite "Ethereum Foundation - Merge - SSZ consensus objects " & preset(): of "ForkData": checkSSZ(ForkData, path, hash) of "HistoricalBatch": checkSSZ(HistoricalBatch, path, hash) of "IndexedAttestation": checkSSZ(IndexedAttestation, path, hash) - of "LightClientSnapshot": checkSSZ(LightClientSnapshot, path, hash) of "LightClientUpdate": checkSSZ(LightClientUpdate, path, hash) of "PendingAttestation": checkSSZ(PendingAttestation, path, hash) of "PowBlock": checkSSZ(PowBlock, path, hash) diff --git a/vendor/nim-eth2-scenarios b/vendor/nim-eth2-scenarios index ee640a4506..ea0bc5d6ea 160000 --- a/vendor/nim-eth2-scenarios +++ b/vendor/nim-eth2-scenarios @@ -1 +1 @@ -Subproject commit ee640a4506e73068a3eaa17db254973764e09b4f +Subproject commit ea0bc5d6ea5223e49af8f791fa63e341755251ae From 880b69ffb2188258f7e708d99cfe9c408f616a2c Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Mon, 3 Jan 2022 11:36:28 +0000 Subject: [PATCH 2/2] use a branch of nim-eth2-scenarios without the new 5.2.1 slashing interchange tests --- vendor/nim-eth2-scenarios | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/nim-eth2-scenarios b/vendor/nim-eth2-scenarios index ea0bc5d6ea..976a490e40 160000 --- a/vendor/nim-eth2-scenarios +++ b/vendor/nim-eth2-scenarios @@ -1 +1 @@ -Subproject commit ea0bc5d6ea5223e49af8f791fa63e341755251ae +Subproject commit 976a490e40a57eb76df457605132ab55642dad0e