diff --git a/AllTests-mainnet.md b/AllTests-mainnet.md index 4081e9be4..0ef04e0ec 100644 --- a/AllTests-mainnet.md +++ b/AllTests-mainnet.md @@ -35,6 +35,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3 + sanity check Bellatrix blocks [Preset: mainnet] OK + sanity check Bellatrix states [Preset: mainnet] OK + sanity check Bellatrix states, reusing buffers [Preset: mainnet] OK ++ sanity check Capella blocks [Preset: mainnet] OK + sanity check genesis roundtrip [Preset: mainnet] OK + sanity check phase 0 blocks [Preset: mainnet] OK + sanity check phase 0 getState rollback [Preset: mainnet] OK @@ -42,7 +43,7 @@ OK: 3/3 Fail: 0/3 Skip: 0/3 + sanity check phase 0 states, reusing buffers [Preset: mainnet] OK + sanity check state diff roundtrip [Preset: mainnet] OK ``` -OK: 16/16 Fail: 0/16 Skip: 0/16 +OK: 17/17 Fail: 0/17 Skip: 0/17 ## Beacon state [Preset: mainnet] ```diff + Smoke test initialize_beacon_state_from_eth1 [Preset: mainnet] OK @@ -606,4 +607,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2 OK: 9/9 Fail: 0/9 Skip: 0/9 ---TOTAL--- -OK: 335/340 Fail: 0/340 Skip: 5/340 +OK: 336/341 Fail: 0/341 Skip: 5/341 diff --git a/ConsensusSpecPreset-mainnet.md b/ConsensusSpecPreset-mainnet.md index 62adc20c8..80269c49f 100644 --- a/ConsensusSpecPreset-mainnet.md +++ b/ConsensusSpecPreset-mainnet.md @@ -252,22 +252,22 @@ ConsensusSpecPreset-mainnet ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/block_lookup_failed Skip ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/too_early_for_merge Skip ForkChoice - mainnet/bellatrix/fork_choice/on_merge_block/pyspec_tests/too_late_for_merge Skip - ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_grea Skip - ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boost_ Skip - ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest Skip - ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_without_att Skip - ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_vanilla Skip - ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/chain_no_attestations Skip - ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/discard_equivocations Skip - ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/genesis Skip - ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head Skip - ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_w Skip - ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attest Skip - ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/basic Skip - ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root Skip ++ ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_grea OK ++ ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boost_ OK ++ ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest OK ++ ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_without_att OK ++ ForkChoice - mainnet/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_vanilla OK ++ ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/chain_no_attestations OK ++ ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/discard_equivocations OK ++ ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/genesis OK ++ ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head OK ++ ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_w OK ++ ForkChoice - mainnet/capella/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attest OK ++ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/basic OK ++ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/on_block_future_block Skip - ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost Skip - ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl Skip ++ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost OK ++ ForkChoice - mainnet/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl OK + ForkChoice - mainnet/phase0/fork_choice/ex_ante/pyspec_tests/ex_ante_attestations_is_great OK + ForkChoice - mainnet/phase0/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_boost_n OK + ForkChoice - mainnet/phase0/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest_ OK @@ -299,7 +299,7 @@ ConsensusSpecPreset-mainnet + Slots - slots_1 OK + Slots - slots_2 OK + Sync - mainnet/bellatrix/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK - Sync - mainnet/capella/sync/optimistic/pyspec_tests/from_syncing_to_invalid Skip ++ Sync - mainnet/capella/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK + [Invalid] EF - Altair - Sanity - Blocks - double_same_proposer_slashings_same_block [Prese OK + [Invalid] EF - Altair - Sanity - Blocks - double_similar_proposer_slashings_same_block [Pr OK + [Invalid] EF - Altair - Sanity - Blocks - double_validator_exit_same_block [Preset: mainne OK @@ -589,7 +589,7 @@ ConsensusSpecPreset-mainnet + fork_random_low_balances OK + fork_random_misc_balances OK ``` -OK: 559/586 Fail: 0/586 Skip: 27/586 +OK: 575/586 Fail: 0/586 Skip: 11/586 ## Attestation ```diff + [Invalid] EF - Altair - Operations - Attestation - after_epoch_slots OK @@ -1921,4 +1921,4 @@ OK: 48/48 Fail: 0/48 Skip: 0/48 OK: 14/14 Fail: 0/14 Skip: 0/14 ---TOTAL--- -OK: 1648/1675 Fail: 0/1675 Skip: 27/1675 +OK: 1664/1675 Fail: 0/1675 Skip: 11/1675 diff --git a/ConsensusSpecPreset-minimal.md b/ConsensusSpecPreset-minimal.md index dba501034..a563f4d98 100644 --- a/ConsensusSpecPreset-minimal.md +++ b/ConsensusSpecPreset-minimal.md @@ -280,30 +280,30 @@ ConsensusSpecPreset-minimal ForkChoice - minimal/bellatrix/fork_choice/on_merge_block/pyspec_tests/block_lookup_failed Skip ForkChoice - minimal/bellatrix/fork_choice/on_merge_block/pyspec_tests/too_early_for_merge Skip ForkChoice - minimal/bellatrix/fork_choice/on_merge_block/pyspec_tests/too_late_for_merge Skip - ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest Skip - ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_without_att Skip - ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_vanilla Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/chain_no_attestations Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/discard_equivocations Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/filtered_block_tree Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/genesis Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_w Skip - ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attest Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/basic Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/new_finalized_slot_is_justi Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/new_finalized_slot_is_not_j Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/new_justified_is_later_than Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_before_finalized Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_checkpoints Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slo Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slo Skip ++ ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest OK ++ ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_without_att OK ++ ForkChoice - minimal/capella/fork_choice/ex_ante/pyspec_tests/ex_ante_vanilla OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/chain_no_attestations OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/discard_equivocations OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/filtered_block_tree OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/genesis OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/proposer_boost_correct_head OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/shorter_chain_but_heavier_w OK ++ ForkChoice - minimal/capella/fork_choice/get_head/pyspec_tests/split_tie_breaker_no_attest OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/basic OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/new_finalized_slot_is_justi OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/new_finalized_slot_is_not_j OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/new_justified_is_later_than OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_bad_parent_root OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_before_finalized OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_checkpoints OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slo OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_finalized_skip_slo OK ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_future_block Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_outside_safe_slots Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_update_justified_c Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost Skip - ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl Skip ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_outside_safe_slots OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/on_block_update_justified_c OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost OK ++ ForkChoice - minimal/capella/fork_choice/on_block/pyspec_tests/proposer_boost_root_same_sl OK + ForkChoice - minimal/phase0/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_with_honest_ OK + ForkChoice - minimal/phase0/fork_choice/ex_ante/pyspec_tests/ex_ante_sandwich_without_atte OK + ForkChoice - minimal/phase0/fork_choice/ex_ante/pyspec_tests/ex_ante_vanilla OK @@ -352,7 +352,7 @@ ConsensusSpecPreset-minimal + Slots - slots_1 OK + Slots - slots_2 OK + Sync - minimal/bellatrix/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK - Sync - minimal/capella/sync/optimistic/pyspec_tests/from_syncing_to_invalid Skip ++ Sync - minimal/capella/sync/optimistic/pyspec_tests/from_syncing_to_invalid OK + [Invalid] EF - Altair - Sanity - Blocks - double_same_proposer_slashings_same_block [Prese OK + [Invalid] EF - Altair - Sanity - Blocks - double_similar_proposer_slashings_same_block [Pr OK + [Invalid] EF - Altair - Sanity - Blocks - double_validator_exit_same_block [Preset: minima OK @@ -665,7 +665,7 @@ ConsensusSpecPreset-minimal + fork_random_low_balances OK + fork_random_misc_balances OK ``` -OK: 627/662 Fail: 0/662 Skip: 35/662 +OK: 651/662 Fail: 0/662 Skip: 11/662 ## Attestation ```diff + [Invalid] EF - Altair - Operations - Attestation - after_epoch_slots OK @@ -2057,4 +2057,4 @@ OK: 52/52 Fail: 0/52 Skip: 0/52 OK: 14/14 Fail: 0/14 Skip: 0/14 ---TOTAL--- -OK: 1764/1799 Fail: 0/1799 Skip: 35/1799 +OK: 1788/1799 Fail: 0/1799 Skip: 11/1799 diff --git a/beacon_chain/beacon_chain_db.nim b/beacon_chain/beacon_chain_db.nim index 44300701c..6eb858f43 100644 --- a/beacon_chain/beacon_chain_db.nim +++ b/beacon_chain/beacon_chain_db.nim @@ -447,12 +447,6 @@ proc new*(T: type BeaconChainDB, if db.exec("DROP TABLE IF EXISTS validatorIndexFromPubKey;").isErr: debug "Failed to drop the validatorIndexFromPubKey table" - const capellaImplementationMissingDb: KvStoreRef = - if capellaImplementationMissing: - default(KvStoreRef) - else: - default(KvStoreRef) - var # V0 compatibility tables - these were created WITHOUT ROWID which is slow # for large blobs @@ -472,7 +466,7 @@ proc new*(T: type BeaconChainDB, kvStore db.openKvStore("blocks").expectDb(), kvStore db.openKvStore("altair_blocks").expectDb(), kvStore db.openKvStore("bellatrix_blocks").expectDb(), - capellaImplementationMissingDb] + kvStore db.openKvStore("capella_blocks").expectDb()] stateRoots = kvStore db.openKvStore("state_roots", true).expectDb() @@ -480,7 +474,7 @@ proc new*(T: type BeaconChainDB, kvStore db.openKvStore("state_no_validators2").expectDb(), kvStore db.openKvStore("altair_state_no_validators").expectDb(), kvStore db.openKvStore("bellatrix_state_no_validators").expectDb(), - capellaImplementationMissingDb] + kvStore db.openKvStore("capella_state_no_validators").expectDb()] stateDiffs = kvStore db.openKvStore("state_diffs").expectDb() summaries = kvStore db.openKvStore("beacon_block_summaries", true).expectDb() @@ -718,16 +712,12 @@ proc putBlock*( proc putBlock*( db: BeaconChainDB, - value: bellatrix.TrustedSignedBeaconBlock) = + value: bellatrix.TrustedSignedBeaconBlock | + capella.TrustedSignedBeaconBlock) = db.withManyWrites: db.blocks[type(value).toFork].putSZSSZ(value.root.data, value) db.putBeaconBlockSummary(value.root, value.message.toBeaconBlockSummary()) -proc putBlock*( - db: BeaconChainDB, - value: capella.TrustedSignedBeaconBlock) = - raiseAssert $capellaImplementationMissing - proc updateImmutableValidators*( db: BeaconChainDB, validators: openArray[Validator]) = # Must be called before storing a state that references the new validators @@ -754,6 +744,10 @@ template toBeaconStateNoImmutableValidators(state: bellatrix.BeaconState): BellatrixBeaconStateNoImmutableValidators = isomorphicCast[BellatrixBeaconStateNoImmutableValidators](state) +template toBeaconStateNoImmutableValidators(state: capella.BeaconState): + CapellaBeaconStateNoImmutableValidators = + isomorphicCast[CapellaBeaconStateNoImmutableValidators](state) + proc putState*( db: BeaconChainDB, key: Eth2Digest, value: phase0.BeaconState | altair.BeaconState) = @@ -761,14 +755,13 @@ proc putState*( db.statesNoVal[type(value).toFork()].putSnappySSZ( key.data, toBeaconStateNoImmutableValidators(value)) -proc putState*(db: BeaconChainDB, key: Eth2Digest, value: bellatrix.BeaconState) = +proc putState*( + db: BeaconChainDB, key: Eth2Digest, + value: bellatrix.BeaconState | capella.BeaconState) = db.updateImmutableValidators(value.validators.asSeq()) db.statesNoVal[type(value).toFork()].putSZSSZ( key.data, toBeaconStateNoImmutableValidators(value)) -proc putState*(db: BeaconChainDB, key: Eth2Digest, value: capella.BeaconState) = - raiseAssert $capellaImplementationMissing - proc putState*(db: BeaconChainDB, state: ForkyHashedBeaconState) = db.withManyWrites: db.putStateRoot(state.latest_block_root, state.data.slot, state.root) @@ -865,7 +858,7 @@ proc getBlock*( result.err() proc getBlock*[ - X: bellatrix.TrustedSignedBeaconBlock]( + X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock]( db: BeaconChainDB, key: Eth2Digest, T: type X): Opt[T] = # We only store blocks that we trust in the database @@ -876,12 +869,6 @@ proc getBlock*[ else: result.err() -proc getBlock*[ - X: capella.TrustedSignedBeaconBlock]( - db: BeaconChainDB, key: Eth2Digest, - T: type X): Opt[T] = - raiseAssert $capellaImplementationMissing - proc getPhase0BlockSSZ( db: BeaconChainDBV0, key: Eth2Digest, data: var seq[byte]): bool = let dataPtr = addr data # Short-lived @@ -925,9 +912,9 @@ proc getBlockSSZ*( except CatchableError: success = false db.blocks[T.toFork].get(key.data, decode).expectDb() and success -proc getBlockSSZ*( - db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], - T: type bellatrix.TrustedSignedBeaconBlock): bool = +proc getBlockSSZ*[ + X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock]( + db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], T: type X): bool = let dataPtr = addr data # Short-lived var success = true func decode(data: openArray[byte]) = @@ -971,9 +958,9 @@ proc getBlockSZ*( except CatchableError: success = false db.blocks[T.toFork].get(key.data, decode).expectDb() and success -proc getBlockSZ*( - db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], - T: type bellatrix.TrustedSignedBeaconBlock): bool = +proc getBlockSZ*[ + X: bellatrix.TrustedSignedBeaconBlock | capella.TrustedSignedBeaconBlock]( + db: BeaconChainDB, key: Eth2Digest, data: var seq[byte], T: type X): bool = let dataPtr = addr data # Short-lived var success = true func decode(data: openArray[byte]) = @@ -1037,7 +1024,8 @@ proc getStateOnlyMutableValidators( proc getStateOnlyMutableValidators( immutableValidators: openArray[ImmutableValidatorData2], - store: KvStoreRef, key: openArray[byte], output: var bellatrix.BeaconState, + store: KvStoreRef, key: openArray[byte], + output: var (bellatrix.BeaconState | capella.BeaconState), rollback: RollbackProc): bool = ## Load state into `output` - BeaconState is large so we want to avoid ## re-allocating it if possible @@ -1128,7 +1116,8 @@ proc getState*( proc getState*( db: BeaconChainDB, key: Eth2Digest, - output: var (altair.BeaconState | bellatrix.BeaconState), + output: var (altair.BeaconState | bellatrix.BeaconState | + capella.BeaconState), rollback: RollbackProc): bool = ## Load state into `output` - BeaconState is large so we want to avoid ## re-allocating it if possible @@ -1145,12 +1134,6 @@ proc getState*( db.immutableValidators, db.statesNoVal[T.toFork], key.data, output, rollback) -proc getState*( - db: BeaconChainDB, key: Eth2Digest, - output: var capella.BeaconState, - rollback: RollbackProc): bool = - raiseAssert $capellaImplementationMissing - proc getState*( db: BeaconChainDB, fork: BeaconStateFork, state_root: Eth2Digest, state: var ForkedHashedBeaconState, rollback: RollbackProc): bool = @@ -1224,7 +1207,8 @@ proc containsBlock*( db.v0.containsBlock(key) proc containsBlock*[ - X: altair.TrustedSignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock]( + X: altair.TrustedSignedBeaconBlock | bellatrix.TrustedSignedBeaconBlock | + capella.TrustedSignedBeaconBlock]( db: BeaconChainDB, key: Eth2Digest, T: type X): bool = db.blocks[X.toFork].contains(key.data).expectDb() @@ -1234,7 +1218,9 @@ proc containsBlock*(db: BeaconChainDB, key: Eth2Digest, fork: BeaconBlockFork): else: db.blocks[fork].contains(key.data).expectDb() proc containsBlock*(db: BeaconChainDB, key: Eth2Digest): bool = - db.containsBlock(key, bellatrix.TrustedSignedBeaconBlock) or + static: doAssert high(BeaconBlockFork) == BeaconBlockFork.Capella + db.containsBlock(key, capella.TrustedSignedBeaconBlock) or + db.containsBlock(key, bellatrix.TrustedSignedBeaconBlock) or db.containsBlock(key, altair.TrustedSignedBeaconBlock) or db.containsBlock(key, phase0.TrustedSignedBeaconBlock) diff --git a/beacon_chain/beacon_chain_db_immutable.nim b/beacon_chain/beacon_chain_db_immutable.nim index faf67a525..16fcade9c 100644 --- a/beacon_chain/beacon_chain_db_immutable.nim +++ b/beacon_chain/beacon_chain_db_immutable.nim @@ -14,6 +14,8 @@ import ./spec/datatypes/[base, altair, bellatrix], ./spec/[eth2_ssz_serialization, eth2_merkleization] +from ./spec/datatypes/capella import ExecutionPayloadHeader, Withdrawal + type # https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.0/specs/phase0/beacon-chain.md#beaconstate # Memory-representation-equivalent to a phase0 BeaconState for in-place SSZ reading and writing @@ -181,4 +183,70 @@ type next_sync_committee*: SyncCommittee # Execution - latest_execution_payload_header*: ExecutionPayloadHeader # [New in Bellatrix] + latest_execution_payload_header*: bellatrix.ExecutionPayloadHeader # [New in Bellatrix] + + # https://github.com/ethereum/consensus-specs/blob/v1.3.0-alpha.0/specs/capella/beacon-chain.md#beaconstate + # Memory-representation-equivalent to a Capella BeaconState for in-place SSZ + # reading and writing + CapellaBeaconStateNoImmutableValidators* = object + # Versioning + genesis_time*: uint64 + genesis_validators_root*: Eth2Digest + slot*: Slot + fork*: Fork + + # History + latest_block_header*: BeaconBlockHeader + ## `latest_block_header.state_root == ZERO_HASH` temporarily + + block_roots*: HashArray[Limit SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] + ## Needed to process attestations, older to newer + + state_roots*: HashArray[Limit SLOTS_PER_HISTORICAL_ROOT, Eth2Digest] + historical_roots*: HashList[Eth2Digest, Limit HISTORICAL_ROOTS_LIMIT] + + # Eth1 + eth1_data*: Eth1Data + eth1_data_votes*: + HashList[Eth1Data, Limit(EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH)] + eth1_deposit_index*: uint64 + + # Registry + #validators*: HashList[ValidatorStatus, Limit VALIDATOR_REGISTRY_LIMIT] + validators*: HashList[Validator, Limit VALIDATOR_REGISTRY_LIMIT] + balances*: HashList[Gwei, Limit VALIDATOR_REGISTRY_LIMIT] + + # Randomness + randao_mixes*: HashArray[Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest] + + # Slashings + slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, Gwei] + ## Per-epoch sums of slashed effective balances + + # Participation + previous_epoch_participation*: EpochParticipationFlags + current_epoch_participation*: EpochParticipationFlags + + # Finality + justification_bits*: JustificationBits + + previous_justified_checkpoint*: Checkpoint + ## Previous epoch snapshot + + current_justified_checkpoint*: Checkpoint + finalized_checkpoint*: Checkpoint + + # Inactivity + inactivity_scores*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT] + + # Light client sync committees + current_sync_committee*: SyncCommittee + next_sync_committee*: SyncCommittee + + # Execution + latest_execution_payload_header*: capella.ExecutionPayloadHeader + + # Withdrawals + withdrawal_queue*: HashList[Withdrawal, WITHDRAWAL_QUEUE_LIMIT] # [New in Capella] + next_withdrawal_index*: WithdrawalIndex # [New in Capella] + next_partial_withdrawal_validator_index*: uint64 # [New in Capella] diff --git a/beacon_chain/consensus_object_pools/blockchain_dag.nim b/beacon_chain/consensus_object_pools/blockchain_dag.nim index 1ddc6b92d..9aab92dd3 100644 --- a/beacon_chain/consensus_object_pools/blockchain_dag.nim +++ b/beacon_chain/consensus_object_pools/blockchain_dag.nim @@ -845,7 +845,11 @@ proc applyBlock( dag.cfg, state, data, cache, info, dag.updateFlags + {slotProcessed}, noRollback) of BeaconBlockFork.Capella: - raiseAssert $capellaImplementationMissing + let data = getBlock(dag, bid, capella.TrustedSignedBeaconBlock).valueOr: + return err("Block load failed") + state_transition( + dag.cfg, state, data, cache, info, + dag.updateFlags + {slotProcessed}, noRollback) proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB, validatorMonitor: ref ValidatorMonitor, updateFlags: UpdateFlags, diff --git a/beacon_chain/spec/datatypes/base.nim b/beacon_chain/spec/datatypes/base.nim index 4ad704683..b27285fef 100644 --- a/beacon_chain/spec/datatypes/base.nim +++ b/beacon_chain/spec/datatypes/base.nim @@ -910,8 +910,8 @@ template isomorphicCast*[T, U](x: U): T = cast[T](x) else: static: - doAssert sizeof(T) == sizeof(U) doAssert getSizeofSig(T()) == getSizeofSig(U()) + doAssert sizeof(T) == sizeof(U) cast[ptr T](unsafeAddr x)[] func prune*(cache: var StateCache, epoch: Epoch) = @@ -953,7 +953,6 @@ func clear*(cache: var StateCache) = cache.sync_committees.clear func checkForkConsistency*(cfg: RuntimeConfig) = - doAssert cfg.CAPELLA_FORK_EPOCH == FAR_FUTURE_EPOCH doAssert cfg.SHARDING_FORK_EPOCH == FAR_FUTURE_EPOCH let forkVersions = diff --git a/beacon_chain/spec/datatypes/capella.nim b/beacon_chain/spec/datatypes/capella.nim index 2e73a0d52..1814a6ec1 100644 --- a/beacon_chain/spec/datatypes/capella.nim +++ b/beacon_chain/spec/datatypes/capella.nim @@ -137,11 +137,11 @@ type finalized_checkpoint*: Checkpoint # Inactivity - inactivity_scores*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT] # [New in Altair] + inactivity_scores*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT] # Light client sync committees - current_sync_committee*: SyncCommittee # [New in Altair] - next_sync_committee*: SyncCommittee # [New in Altair] + current_sync_committee*: SyncCommittee + next_sync_committee*: SyncCommittee # Execution latest_execution_payload_header*: ExecutionPayloadHeader diff --git a/tests/consensus_spec/fixtures_utils.nim b/tests/consensus_spec/fixtures_utils.nim index 39cabbdf7..62bb7d88c 100644 --- a/tests/consensus_spec/fixtures_utils.nim +++ b/tests/consensus_spec/fixtures_utils.nim @@ -118,6 +118,8 @@ proc parseTest*(path: string, Format: typedesc[SSZ], T: typedesc): T = stderr.write err.formatMsg(path), "\n" quit 1 +from ../../beacon_chain/spec/datatypes/capella import BeaconState + proc loadForkedState*( path: string, fork: BeaconStateFork): ref ForkedHashedBeaconState = # TODO stack usage. newClone and assignClone do not seem to @@ -125,7 +127,10 @@ proc loadForkedState*( let forkedState = new ForkedHashedBeaconState case fork of BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing + let state = newClone(parseTest(path, SSZ, capella.BeaconState)) + forkedState.kind = BeaconStateFork.Capella + forkedState.capellaData.data = state[] + forkedState.capellaData.root = hash_tree_root(state[]) of BeaconStateFork.Bellatrix: let state = newClone(parseTest(path, SSZ, bellatrix.BeaconState)) forkedState.kind = BeaconStateFork.Bellatrix diff --git a/tests/consensus_spec/test_fixture_fork_choice.nim b/tests/consensus_spec/test_fixture_fork_choice.nim index 5bd623243..708517e9c 100644 --- a/tests/consensus_spec/test_fixture_fork_choice.nim +++ b/tests/consensus_spec/test_fixture_fork_choice.nim @@ -62,6 +62,9 @@ type of opChecks: checks: JsonNode +from ../../beacon_chain/spec/datatypes/capella import + BeaconBlock, BeaconState, SignedBeaconBlock + proc initialLoad( path: string, db: BeaconChainDB, StateType, BlockType: typedesc @@ -75,7 +78,13 @@ proc initialLoad( path/"anchor_block.ssz_snappy", SSZ, BlockType) - when BlockType is bellatrix.BeaconBlock: + when BlockType is capella.BeaconBlock: + let signedBlock = ForkedSignedBeaconBlock.init(capella.SignedBeaconBlock( + message: blck, + # signature: - unused as it's trusted + root: hash_tree_root(blck) + )) + elif BlockType is bellatrix.BeaconBlock: let signedBlock = ForkedSignedBeaconBlock.init(bellatrix.SignedBeaconBlock( message: blck, # signature: - unused as it's trusted @@ -150,7 +159,12 @@ proc loadOps(path: string, fork: BeaconStateFork): seq[Operation] = result.add Operation(kind: opOnBlock, blck: ForkedSignedBeaconBlock.init(blck)) of BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing + let blck = parseTest( + path/filename & ".ssz_snappy", + SSZ, capella.SignedBeaconBlock + ) + result.add Operation(kind: opOnBlock, + blck: ForkedSignedBeaconBlock.init(blck)) elif step.hasKey"attester_slashing": let filename = step["attester_slashing"].getStr() let attesterSlashing = parseTest( @@ -202,8 +216,13 @@ proc stepOnBlock( type TrustedBlock = phase0.TrustedSignedBeaconBlock elif signedBlock is altair.SignedBeaconBlock: type TrustedBlock = altair.TrustedSignedBeaconBlock - else: + elif signedBlock is bellatrix.SignedBeaconBlock: type TrustedBlock = bellatrix.TrustedSignedBeaconBlock + elif signedBlock is capella.SignedBeaconBlock: + type TrustedBlock = capella.TrustedSignedBeaconBlock + else: + doAssert false, "Unknown TrustedSignedBeaconBlock fork" + # In normal Nimbus flow, for this (effectively) newPayload-based INVALID, it # is checked even before entering the DAG, by the block processor. Currently @@ -300,7 +319,7 @@ proc doRunTest(path: string, fork: BeaconStateFork) = let stores = case fork of BeaconStateFork.Capella: - raiseAssert $capellaImplementationMissing + initialLoad(path, db, capella.BeaconState, capella.BeaconBlock) of BeaconStateFork.Bellatrix: initialLoad(path, db, bellatrix.BeaconState, bellatrix.BeaconBlock) of BeaconStateFork.Altair: @@ -332,14 +351,11 @@ proc doRunTest(path: string, fork: BeaconStateFork) = doAssert status.isOk == step.valid of opOnBlock: withBlck(step.blck): - when stateFork != BeaconStateFork.Capella: - let status = stepOnBlock( - stores.dag, stores.fkChoice, - verifier, state[], stateCache, - blck, time, invalidatedRoots) - doAssert status.isOk == step.valid - else: - raiseAssert $capellaImplementationMissing + let status = stepOnBlock( + stores.dag, stores.fkChoice, + verifier, state[], stateCache, + blck, time, invalidatedRoots) + doAssert status.isOk == step.valid of opOnAttesterSlashing: let indices = check_attester_slashing(state[], step.attesterSlashing, flags = {}) @@ -376,8 +392,6 @@ proc runTest(testType: static[string], path: string, fork: BeaconStateFork) = else: if os.splitPath(path).tail in SKIP: skip() - elif capellaImplementationMissing or path.contains("/capella/"): - skip() else: doRunTest(path, fork) diff --git a/tests/test_beacon_chain_db.nim b/tests/test_beacon_chain_db.nim index ed5c41568..8f2d0fdc4 100644 --- a/tests/test_beacon_chain_db.nim +++ b/tests/test_beacon_chain_db.nim @@ -42,6 +42,16 @@ proc getBellatrixStateRef(db: BeaconChainDB, root: Eth2Digest): if db.getState(root, res[], noRollback): return res +from ../beacon_chain/spec/datatypes/capella import + BeaconStateRef, NilableBeaconStateRef + +proc getCapellaStateRef(db: BeaconChainDB, root: Eth2Digest): + capella.NilableBeaconStateRef = + # load beaconstate the way the block pool does it - into an existing instance + let res = (capella.BeaconStateRef)() + if db.getState(root, res[], noRollback): + return res + func withDigest(blck: phase0.TrustedBeaconBlock): phase0.TrustedSignedBeaconBlock = phase0.TrustedSignedBeaconBlock( @@ -63,6 +73,13 @@ func withDigest(blck: bellatrix.TrustedBeaconBlock): root: hash_tree_root(blck) ) +func withDigest(blck: capella.TrustedBeaconBlock): + capella.TrustedSignedBeaconBlock = + capella.TrustedSignedBeaconBlock( + message: blck, + root: hash_tree_root(blck) + ) + proc getTestStates(stateFork: BeaconStateFork): auto = let db = makeTestDB(SLOTS_PER_EPOCH) @@ -106,6 +123,7 @@ suite "Beacon chain DB" & preset(): db.containsBlock(root, phase0.TrustedSignedBeaconBlock) not db.containsBlock(root, altair.TrustedSignedBeaconBlock) not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) db.getBlock(root, phase0.TrustedSignedBeaconBlock).get() == signedBlock db.getBlockSSZ(root, tmp, phase0.TrustedSignedBeaconBlock) db.getBlockSZ(root, tmp2, phase0.TrustedSignedBeaconBlock) @@ -119,6 +137,7 @@ suite "Beacon chain DB" & preset(): not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) not db.containsBlock(root, altair.TrustedSignedBeaconBlock) not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) db.getBlock(root, phase0.TrustedSignedBeaconBlock).isErr() not db.getBlockSSZ(root, tmp, phase0.TrustedSignedBeaconBlock) not db.getBlockSZ(root, tmp2, phase0.TrustedSignedBeaconBlock) @@ -149,6 +168,7 @@ suite "Beacon chain DB" & preset(): not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) db.containsBlock(root, altair.TrustedSignedBeaconBlock) not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) db.getBlock(root, altair.TrustedSignedBeaconBlock).get() == signedBlock db.getBlockSSZ(root, tmp, altair.TrustedSignedBeaconBlock) db.getBlockSZ(root, tmp2, altair.TrustedSignedBeaconBlock) @@ -162,6 +182,7 @@ suite "Beacon chain DB" & preset(): not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) not db.containsBlock(root, altair.TrustedSignedBeaconBlock) not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) db.getBlock(root, altair.TrustedSignedBeaconBlock).isErr() not db.getBlockSSZ(root, tmp, altair.TrustedSignedBeaconBlock) not db.getBlockSZ(root, tmp2, altair.TrustedSignedBeaconBlock) @@ -192,6 +213,7 @@ suite "Beacon chain DB" & preset(): not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) not db.containsBlock(root, altair.TrustedSignedBeaconBlock) db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) db.getBlock(root, bellatrix.TrustedSignedBeaconBlock).get() == signedBlock db.getBlockSSZ(root, tmp, bellatrix.TrustedSignedBeaconBlock) db.getBlockSZ(root, tmp2, bellatrix.TrustedSignedBeaconBlock) @@ -205,6 +227,7 @@ suite "Beacon chain DB" & preset(): not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) not db.containsBlock(root, altair.TrustedSignedBeaconBlock) not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) db.getBlock(root, bellatrix.TrustedSignedBeaconBlock).isErr() not db.getBlockSSZ(root, tmp, bellatrix.TrustedSignedBeaconBlock) not db.getBlockSZ(root, tmp2, bellatrix.TrustedSignedBeaconBlock) @@ -220,6 +243,51 @@ suite "Beacon chain DB" & preset(): db.close() + test "sanity check Capella blocks" & preset(): + let db = BeaconChainDB.new("", inMemory = true) + + let + signedBlock = withDigest((capella.TrustedBeaconBlock)()) + root = hash_tree_root(signedBlock.message) + + db.putBlock(signedBlock) + + var tmp, tmp2: seq[byte] + check: + db.containsBlock(root) + not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) + not db.containsBlock(root, altair.TrustedSignedBeaconBlock) + not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + db.containsBlock(root, capella.TrustedSignedBeaconBlock) + db.getBlock(root, capella.TrustedSignedBeaconBlock).get() == signedBlock + db.getBlockSSZ(root, tmp, capella.TrustedSignedBeaconBlock) + db.getBlockSZ(root, tmp2, capella.TrustedSignedBeaconBlock) + tmp == SSZ.encode(signedBlock) + tmp2 == encodeFramed(tmp) + uncompressedLenFramed(tmp2).isSome + + db.delBlock(root) + check: + not db.containsBlock(root) + not db.containsBlock(root, phase0.TrustedSignedBeaconBlock) + not db.containsBlock(root, altair.TrustedSignedBeaconBlock) + not db.containsBlock(root, bellatrix.TrustedSignedBeaconBlock) + not db.containsBlock(root, capella.TrustedSignedBeaconBlock) + db.getBlock(root, capella.TrustedSignedBeaconBlock).isErr() + not db.getBlockSSZ(root, tmp, capella.TrustedSignedBeaconBlock) + not db.getBlockSZ(root, tmp2, capella.TrustedSignedBeaconBlock) + + db.putStateRoot(root, signedBlock.message.slot, root) + var root2 = root + root2.data[0] = root.data[0] + 1 + db.putStateRoot(root, signedBlock.message.slot + 1, root2) + + check: + db.getStateRoot(root, signedBlock.message.slot).get() == root + db.getStateRoot(root, signedBlock.message.slot + 1).get() == root2 + + db.close() + test "sanity check phase 0 states" & preset(): let db = makeTestDB(SLOTS_PER_EPOCH)