database and fork choice test runner support for capella (#4309)

This commit is contained in:
tersec 2022-11-09 17:32:10 +00:00 committed by GitHub
parent 0919b8689e
commit 90eb2ccb20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 254 additions and 109 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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]

View File

@ -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,

View File

@ -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 =

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)