introduce database support for Altair (#2667)

* introduce immutable Altair BeaconState

* add database support for Altair blocks and states

* add tests for Altair get/put/contains/delete state

* enable blockchain_dag Altair state database storing

* properly return error on getting missing altair block
This commit is contained in:
tersec 2021-06-24 07:11:47 +00:00 committed by GitHub
parent ae1abf24af
commit 41e0a7abc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 324 additions and 41 deletions

View File

@ -82,13 +82,16 @@ OK: 11/11 Fail: 0/11 Skip: 0/11
```diff
+ empty database [Preset: mainnet] OK
+ find ancestors [Preset: mainnet] OK
+ sanity check blocks [Preset: mainnet] OK
+ sanity check Altair blocks [Preset: mainnet] OK
+ sanity check Altair states [Preset: mainnet] OK
+ sanity check Altair states, reusing buffers [Preset: mainnet] OK
+ sanity check genesis roundtrip [Preset: mainnet] OK
+ sanity check phase 0 blocks [Preset: mainnet] OK
+ sanity check phase 0 states [Preset: mainnet] OK
+ sanity check phase 0 states, reusing buffers [Preset: mainnet] OK
+ sanity check state diff roundtrip [Preset: mainnet] OK
+ sanity check states [Preset: mainnet] OK
+ sanity check states, reusing buffers [Preset: mainnet] OK
```
OK: 7/7 Fail: 0/7 Skip: 0/7
OK: 10/10 Fail: 0/10 Skip: 0/10
## Beacon state [Preset: mainnet]
```diff
+ Smoke test initialize_beacon_state_from_eth1 [Preset: mainnet] OK
@ -308,4 +311,4 @@ OK: 3/3 Fail: 0/3 Skip: 0/3
OK: 1/1 Fail: 0/1 Skip: 0/1
---TOTAL---
OK: 174/182 Fail: 0/182 Skip: 8/182
OK: 177/185 Fail: 0/185 Skip: 8/185

View File

@ -89,9 +89,11 @@ type
checkpoint*: proc() {.gcsafe, raises: [Defect].}
keyValues: KvStoreRef # Random stuff using DbKeyKind - suitable for small values mainly!
blocks: KvStoreRef # BlockRoot -> TrustedBeaconBlock
blocks: KvStoreRef # BlockRoot -> phase0.TrustedBeaconBlock
altairBlocks: KvStoreRef # BlockRoot -> altair.TrustedBeaconBlock
stateRoots: KvStoreRef # (Slot, BlockRoot) -> StateRoot
statesNoVal: KvStoreRef # StateRoot -> BeaconStateNoImmutableValidators
altairStatesNoVal: KvStoreRef # StateRoot -> AltairBeaconStateNoImmutableValidators
stateDiffs: KvStoreRef ##\
## StateRoot -> BeaconStateDiff
## Instead of storing full BeaconStates, one can store only the diff from
@ -301,8 +303,10 @@ proc new*(T: type BeaconChainDB,
# V1 - expected-to-be small rows get without rowid optimizations
keyValues = kvStore db.openKvStore("key_values", true).expectDb()
blocks = kvStore db.openKvStore("blocks").expectDb()
altairBlocks = kvStore db.openKvStore("altair_blocks").expectDb()
stateRoots = kvStore db.openKvStore("state_roots", true).expectDb()
statesNoVal = kvStore db.openKvStore("state_no_validators2").expectDb()
altairStatesNoVal = kvStore db.openKvStore("altair_state_no_validators").expectDb()
stateDiffs = kvStore db.openKvStore("state_diffs").expectDb()
summaries = kvStore db.openKvStore("beacon_block_summaries", true).expectDb()
@ -337,8 +341,10 @@ proc new*(T: type BeaconChainDB,
checkpoint: proc() = db.checkpoint(),
keyValues: keyValues,
blocks: blocks,
altair_blocks: altair_blocks,
stateRoots: stateRoots,
statesNoVal: statesNoVal,
altairStatesNoVal: statesNoVal,
stateDiffs: stateDiffs,
summaries: summaries,
)
@ -449,8 +455,10 @@ proc close*(db: BeaconchainDB) =
# Close things in reverse order
discard db.summaries.close()
discard db.stateDiffs.close()
discard db.altairStatesNoVal.close()
discard db.statesNoVal.close()
discard db.stateRoots.close()
discard db.altairBlocks.close()
discard db.blocks.close()
discard db.keyValues.close()
db.immutableValidatorsDb.close()
@ -475,6 +483,10 @@ proc putBlock*(db: BeaconChainDB, value: phase0.TrustedSignedBeaconBlock) =
db.blocks.putSnappySSZ(value.root.data, value)
db.putBeaconBlockSummary(value.root, value.message.toBeaconBlockSummary())
proc putBlock*(db: BeaconChainDB, value: altair.TrustedSignedBeaconBlock) =
db.altairBlocks.putSnappySSZ(value.root.data, value)
db.putBeaconBlockSummary(value.root, value.message.toBeaconBlockSummary())
proc updateImmutableValidators*(
db: BeaconChainDB, validators: openArray[Validator]) =
# Must be called before storing a state that references the new validators
@ -492,7 +504,14 @@ proc putState*(db: BeaconChainDB, key: Eth2Digest, value: phase0.BeaconState) =
key.data,
isomorphicCast[BeaconStateNoImmutableValidators](value))
proc putState*(db: BeaconChainDB, value: phase0.BeaconState) =
proc putState*(db: BeaconChainDB, key: Eth2Digest, value: altair.BeaconState) =
db.updateImmutableValidators(value.validators.asSeq())
db.altairStatesNoVal.putSnappySSZ(
key.data,
isomorphicCast[AltairBeaconStateNoImmutableValidators](value))
proc putState*(
db: BeaconChainDB, value: phase0.BeaconState | altair.BeaconState) =
db.putState(hash_tree_root(value), value)
func stateRootKey(root: Eth2Digest, slot: Slot): array[40, byte] =
@ -512,10 +531,12 @@ proc putStateDiff*(db: BeaconChainDB, root: Eth2Digest, value: BeaconStateDiff)
proc delBlock*(db: BeaconChainDB, key: Eth2Digest) =
db.blocks.del(key.data).expectDb()
db.altairBlocks.del(key.data).expectDb()
db.summaries.del(key.data).expectDb()
proc delState*(db: BeaconChainDB, key: Eth2Digest) =
db.statesNoVal.del(key.data).expectDb()
db.altairStatesNoVal.del(key.data).expectDb()
proc delStateRoot*(db: BeaconChainDB, root: Eth2Digest, slot: Slot) =
db.stateRoots.del(stateRootKey(root, slot)).expectDb()
@ -556,6 +577,16 @@ proc getBlock*(db: BeaconChainDB, key: Eth2Digest):
# set root after deserializing (so it doesn't get zeroed)
result.get().root = key
proc getAltairBlock*(db: BeaconChainDB, key: Eth2Digest):
Opt[altair.TrustedSignedBeaconBlock] =
# We only store blocks that we trust in the database
result.ok(default(altair.TrustedSignedBeaconBlock))
if db.altairBlocks.getSnappySSZ(key.data, result.get) == GetResult.found:
# set root after deserializing (so it doesn't get zeroed)
result.get().root = key
else:
result.err()
proc getStateOnlyMutableValidators(
immutableValidators: openArray[ImmutableValidatorData2],
store: KvStoreRef, key: openArray[byte], output: var phase0.BeaconState,
@ -598,6 +629,48 @@ proc getStateOnlyMutableValidators(
rollback(output)
false
proc getAltairStateOnlyMutableValidators(
immutableValidators: openArray[ImmutableValidatorData2],
store: KvStoreRef, key: openArray[byte], output: var altair.BeaconState,
rollback: AltairRollbackProc): bool =
## Load state into `output` - BeaconState is large so we want to avoid
## re-allocating it if possible
## Return `true` iff the entry was found in the database and `output` was
## overwritten.
## Rollback will be called only if output was partially written - if it was
## not found at all, rollback will not be called
# TODO rollback is needed to deal with bug - use `noRollback` to ignore:
# https://github.com/nim-lang/Nim/issues/14126
# TODO RVO is inefficient for large objects:
# https://github.com/nim-lang/Nim/issues/13879
case store.getSnappySSZ(
key, isomorphicCast[AltairBeaconStateNoImmutableValidators](output))
of GetResult.found:
let numValidators = output.validators.len
doAssert immutableValidators.len >= numValidators
for i in 0 ..< numValidators:
let
# Bypass hash cache invalidation
dstValidator = addr output.validators.data[i]
assign(
dstValidator.pubkey,
immutableValidators[i].pubkey.loadValid().toPubKey())
assign(
dstValidator.withdrawal_credentials,
immutableValidators[i].withdrawal_credentials)
output.validators.resetCache()
true
of GetResult.notFound:
false
of GetResult.corrupted:
rollback(output)
false
proc getState(
db: BeaconChainDBV0,
immutableValidators: openArray[ImmutableValidatorData2],
@ -646,6 +719,22 @@ proc getState*(
else:
true
proc getAltairState*(
db: BeaconChainDB, key: Eth2Digest, output: var altair.BeaconState,
rollback: AltairRollbackProc): bool =
## Load state into `output` - BeaconState is large so we want to avoid
## re-allocating it if possible
## Return `true` iff the entry was found in the database and `output` was
## overwritten.
## Rollback will be called only if output was partially written - if it was
## not found at all, rollback will not be called
# TODO rollback is needed to deal with bug - use `noRollback` to ignore:
# https://github.com/nim-lang/Nim/issues/14126
# TODO RVO is inefficient for large objects:
# https://github.com/nim-lang/Nim/issues/13879
getAltairStateOnlyMutableValidators(
db.immutableValidators, db.altairStatesNoVal, key.data, output, rollback)
proc getStateRoot(db: BeaconChainDBV0,
root: Eth2Digest,
slot: Slot): Opt[Eth2Digest] =
@ -698,7 +787,9 @@ proc containsBlock*(db: BeaconChainDBV0, key: Eth2Digest): bool =
db.backend.contains(subkey(phase0.SignedBeaconBlock, key)).expectDb()
proc containsBlock*(db: BeaconChainDB, key: Eth2Digest): bool =
db.blocks.contains(key.data).expectDb() or db.v0.containsBlock(key)
db.altairBlocks.contains(key.data).expectDb() or
db.blocks.contains(key.data).expectDb() or
db.v0.containsBlock(key)
proc containsState*(db: BeaconChainDBV0, key: Eth2Digest): bool =
let sk = subkey(BeaconStateNoImmutableValidators, key)
@ -707,6 +798,7 @@ proc containsState*(db: BeaconChainDBV0, key: Eth2Digest): bool =
db.backend.contains(subkey(phase0.BeaconState, key)).expectDb()
proc containsState*(db: BeaconChainDB, key: Eth2Digest, legacy: bool = true): bool =
db.altairStatesNoVal.contains(key.data).expectDb or
db.statesNoVal.contains(key.data).expectDb or
(legacy and db.v0.containsState(key))

View File

@ -12,13 +12,14 @@ import
stew/[assign2, io2, objects, results],
serialization,
eth/db/[kvstore, kvstore_sqlite3],
./spec/[crypto, datatypes, digest],
./spec/[crypto, digest],
./spec/datatypes/[base, altair],
./ssz/[ssz_serialization, merkleization],
filepath
type
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#beaconstate
# Memory-representation-equivalent to a v1.0.1 BeaconState for in-place SSZ reading and writing
# Memory-representation-equivalent to a phase0 BeaconState for in-place SSZ reading and writing
BeaconStateNoImmutableValidators* = object
# Versioning
genesis_time*: uint64
@ -71,6 +72,68 @@ type
current_justified_checkpoint*: Checkpoint
finalized_checkpoint*: Checkpoint
# https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.7/specs/altair/beacon-chain.md#beaconstate
# Memory-representation-equivalent to an Altair BeaconState for in-place SSZ
# reading and writing
AltairBeaconStateNoImmutableValidators* = 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]
balances*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT]
# Randomness
randao_mixes*: HashArray[Limit EPOCHS_PER_HISTORICAL_VECTOR, Eth2Digest]
# Slashings
slashings*: HashArray[Limit EPOCHS_PER_SLASHINGS_VECTOR, uint64] ##\
## Per-epoch sums of slashed effective balances
# Participation
previous_epoch_participation*:
HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
current_epoch_participation*:
HashList[ParticipationFlags, Limit VALIDATOR_REGISTRY_LIMIT]
# Finality
justification_bits*: uint8 ##\
## Bit set for every recent justified epoch
## Model a Bitvector[4] as a one-byte uint, which should remain consistent
## with ssz/hashing.
previous_justified_checkpoint*: Checkpoint ##\
## Previous epoch snapshot
current_justified_checkpoint*: Checkpoint
finalized_checkpoint*: Checkpoint
# Inactivity
inactivity_scores*: HashList[uint64, Limit VALIDATOR_REGISTRY_LIMIT] # [New in Altair]
# Light client sync committees
current_sync_committee*: SyncCommittee # [New in Altair]
next_sync_committee*: SyncCommittee # [New in Altair]
func getSizeofSig(x: auto, n: int = 0): seq[(string, int, int)] =
for name, value in x.fieldPairs:
when value is tuple|object:

View File

@ -559,9 +559,11 @@ proc putState(dag: ChainDAGRef, state: var StateData) =
# Ideally we would save the state and the root lookup cache in a single
# transaction to prevent database inconsistencies, but the state loading code
# is resilient against one or the other going missing
if state.data.beaconStateFork != forkAltair:
# TODO re-enable for Altair
case state.data.beaconStateFork:
of forkPhase0:
dag.db.putState(getStateRoot(state.data), state.data.hbsPhase0.data)
of forkAltair:
dag.db.putState(getStateRoot(state.data), state.data.hbsAltair.data)
dag.db.putStateRoot(
state.blck.root, getStateField(state.data, slot), getStateRoot(state.data))

View File

@ -105,9 +105,13 @@ func verifyStateRoot(state: phase0.BeaconState, blck: altair.TrustedBeaconBlock)
type
RollbackProc* = proc(v: var phase0.BeaconState) {.gcsafe, raises: [Defect].}
AltairRollbackProc* = proc(v: var altair.BeaconState) {.gcsafe, raises: [Defect].}
func noRollback*(state: var phase0.BeaconState) =
trace "Skipping rollback of broken state"
trace "Skipping rollback of broken phase 0 state"
func noRollback*(state: var altair.BeaconState) =
trace "Skipping rollback of broken Altair state"
type
RollbackHashedProc* = proc(state: var phase0.HashedBeaconState) {.gcsafe, raises: [Defect].}
@ -170,7 +174,7 @@ func noRollback*(state: var phase0.HashedBeaconState) =
func noRollback*(state: var altair.HashedBeaconState) =
trace "Skipping rollback of broken Altair state"
proc maybeUpgradeStateToAltair(
proc maybeUpgradeStateToAltair*(
state: var ForkedHashedBeaconState, altairForkSlot: Slot) =
# Both process_slots() and state_transition_block() call this, so only run it
# once by checking for existing fork.

View File

@ -1,5 +1,5 @@
# beacon_chain
# Copyright (c) 2018-2020 Status Research & Development GmbH
# Copyright (c) 2018-2021 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
@ -13,8 +13,8 @@ import
math,
# Specs
../../beacon_chain/spec/[datatypes, crypto, digest,
keystore, signatures, presets],
../../beacon_chain/spec/[crypto, digest, keystore, signatures, presets],
../../beacon_chain/spec/datatypes/base,
# Internals
../../beacon_chain/extras,
@ -103,8 +103,8 @@ proc mockGenesisBalancedDeposits*(
mockGenesisDepositsImpl(result, validatorCount,amount,flags):
discard
proc mockUpdateStateForNewDeposit*(
state: var BeaconState,
proc mockUpdateStateForNewDeposit*[T](
state: var T,
validator_index: uint64,
amount: uint64,
# withdrawal_credentials: Eth2Digest

View File

@ -12,8 +12,9 @@ import
unittest2,
../beacon_chain/[beacon_chain_db, extras, interop, ssz],
../beacon_chain/spec/[
beaconstate, crypto, datatypes, digest, forkedbeaconstate_helpers, presets,
beaconstate, crypto, digest, forkedbeaconstate_helpers, presets,
state_transition],
../beacon_chain/spec/datatypes/[phase0, altair],
../beacon_chain/consensus_object_pools/blockchain_dag,
eth/db/kvstore,
# test utilies
@ -22,14 +23,30 @@ import
when isMainModule:
import chronicles # or some random compile error happens...
proc getStateRef(db: BeaconChainDB, root: Eth2Digest): NilableBeaconStateRef =
proc getPhase0StateRef(db: BeaconChainDB, root: Eth2Digest):
phase0.NilableBeaconStateRef =
# load beaconstate the way the block pool does it - into an existing instance
let res = BeaconStateRef()
let res = (phase0.BeaconStateRef)()
if db.getState(root, res[], noRollback):
return res
func withDigest(blck: TrustedBeaconBlock): TrustedSignedBeaconBlock =
TrustedSignedBeaconBlock(
proc getAltairStateRef(db: BeaconChainDB, root: Eth2Digest):
altair.NilableBeaconStateRef =
# load beaconstate the way the block pool does it - into an existing instance
let res = (altair.BeaconStateRef)()
if db.getAltairState(root, res[], noRollback):
return res
func withDigest(blck: phase0.TrustedBeaconBlock):
phase0.TrustedSignedBeaconBlock =
phase0.TrustedSignedBeaconBlock(
message: blck,
root: hash_tree_root(blck)
)
func withDigest(blck: altair.TrustedBeaconBlock):
altair.TrustedSignedBeaconBlock =
altair.TrustedSignedBeaconBlock(
message: blck,
root: hash_tree_root(blck)
)
@ -39,15 +56,15 @@ suite "Beacon chain DB" & preset():
var
db = BeaconChainDB.new(defaultRuntimePreset, "", inMemory = true)
check:
db.getStateRef(Eth2Digest()).isNil
db.getPhase0StateRef(Eth2Digest()).isNil
db.getBlock(Eth2Digest()).isNone
test "sanity check blocks" & preset():
test "sanity check phase 0 blocks" & preset():
var
db = BeaconChainDB.new(defaultRuntimePreset, "", inMemory = true)
let
signedBlock = withDigest(TrustedBeaconBlock())
signedBlock = withDigest((phase0.TrustedBeaconBlock)())
root = hash_tree_root(signedBlock.message)
db.putBlock(signedBlock)
@ -56,6 +73,11 @@ suite "Beacon chain DB" & preset():
db.containsBlock(root)
db.getBlock(root).get() == signedBlock
db.delBlock(root)
check:
not db.containsBlock(root)
db.getBlock(root).isErr()
db.putStateRoot(root, signedBlock.message.slot, root)
var root2 = root
root2.data[0] = root.data[0] + 1
@ -67,7 +89,37 @@ suite "Beacon chain DB" & preset():
db.close()
test "sanity check states" & preset():
test "sanity check Altair blocks" & preset():
var
db = BeaconChainDB.new(defaultRuntimePreset, "", inMemory = true)
let
signedBlock = withDigest((altair.TrustedBeaconBlock)())
root = hash_tree_root(signedBlock.message)
db.putBlock(signedBlock)
check:
db.containsBlock(root)
db.getAltairBlock(root).get() == signedBlock
db.delBlock(root)
check:
not db.containsBlock(root)
db.getAltairBlock(root).isErr()
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():
var
db = makeTestDB(SLOTS_PER_EPOCH)
dag = init(ChainDAGRef, defaultRuntimePreset, db)
@ -83,19 +135,46 @@ suite "Beacon chain DB" & preset():
check:
db.containsState(root)
hash_tree_root(db.getStateRef(root)[]) == root
hash_tree_root(db.getPhase0StateRef(root)[]) == root
db.delState(root)
check: not db.containsState(root)
check:
not db.containsState(root)
db.getPhase0StateRef(root).isNil
db.close()
test "sanity check states, reusing buffers" & preset():
test "sanity check Altair states" & preset():
var
db = makeTestDB(SLOTS_PER_EPOCH)
dag = init(ChainDAGRef, defaultRuntimePreset, db)
testStates = getTestStates(dag.headState.data, true)
# Ensure transitions beyond just adding validators and increasing slots
sort(testStates) do (x, y: ref ForkedHashedBeaconState) -> int:
cmp($getStateRoot(x[]), $getStateRoot(y[]))
for state in testStates:
db.putState(state[].hbsAltair.data)
let root = hash_tree_root(state[])
check:
db.containsState(root)
hash_tree_root(db.getAltairStateRef(root)[]) == root
db.delState(root)
check:
not db.containsState(root)
db.getAltairStateRef(root).isNil
db.close()
test "sanity check phase 0 states, reusing buffers" & preset():
var
db = makeTestDB(SLOTS_PER_EPOCH)
dag = init(ChainDAGRef, defaultRuntimePreset, db)
let stateBuffer = BeaconStateRef()
let stateBuffer = (phase0.BeaconStateRef)()
var testStates = getTestStates(dag.headState.data)
# Ensure transitions beyond just adding validators and increasing slots
@ -112,7 +191,37 @@ suite "Beacon chain DB" & preset():
hash_tree_root(stateBuffer[]) == root
db.delState(root)
check: not db.containsState(root)
check:
not db.containsState(root)
not db.getState(root, stateBuffer[], noRollback)
db.close()
test "sanity check Altair states, reusing buffers" & preset():
var
db = makeTestDB(SLOTS_PER_EPOCH)
dag = init(ChainDAGRef, defaultRuntimePreset, db)
let stateBuffer = (altair.BeaconStateRef)()
var testStates = getTestStates(dag.headState.data, true)
# Ensure transitions beyond just adding validators and increasing slots
sort(testStates) do (x, y: ref ForkedHashedBeaconState) -> int:
cmp($getStateRoot(x[]), $getStateRoot(y[]))
for state in testStates:
db.putState(state[].hbsAltair.data)
let root = hash_tree_root(state[])
check:
db.getAltairState(root, stateBuffer[], noRollback)
db.containsState(root)
hash_tree_root(stateBuffer[]) == root
db.delState(root)
check:
not db.containsState(root)
not db.getAltairState(root, stateBuffer[], noRollback)
db.close()
@ -122,11 +231,11 @@ suite "Beacon chain DB" & preset():
let
a0 = withDigest(
TrustedBeaconBlock(slot: GENESIS_SLOT + 0))
(phase0.TrustedBeaconBlock)(slot: GENESIS_SLOT + 0))
a1 = withDigest(
TrustedBeaconBlock(slot: GENESIS_SLOT + 1, parent_root: a0.root))
(phase0.TrustedBeaconBlock)(slot: GENESIS_SLOT + 1, parent_root: a0.root))
a2 = withDigest(
TrustedBeaconBlock(slot: GENESIS_SLOT + 2, parent_root: a1.root))
(phase0.TrustedBeaconBlock)(slot: GENESIS_SLOT + 2, parent_root: a1.root))
doAssert toSeq(db.getAncestors(a0.root)) == []
doAssert toSeq(db.getAncestors(a2.root)) == []
@ -175,7 +284,7 @@ suite "Beacon chain DB" & preset():
db.putState(state[])
check db.containsState(root)
let state2 = db.getStateRef(root)
let state2 = db.getPhase0StateRef(root)
db.delState(root)
check not db.containsState(root)
db.close()

View File

@ -16,7 +16,7 @@ import
beaconstate, crypto, datatypes, forkedbeaconstate_helpers, helpers,
presets, state_transition]
proc valid_deposit(state: var BeaconState) =
proc valid_deposit[T](state: var T) =
const deposit_amount = MAX_EFFECTIVE_BALANCE
let validator_index = state.validators.len
let deposit = mockUpdateStateForNewDeposit(
@ -41,7 +41,8 @@ proc valid_deposit(state: var BeaconState) =
EFFECTIVE_BALANCE_INCREMENT
)
proc getTestStates*(initialState: ForkedHashedBeaconState):
proc getTestStates*(
initialState: ForkedHashedBeaconState, useAltair: bool = false):
seq[ref ForkedHashedBeaconState] =
# Randomly generated slot numbers, with a jump to around
# SLOTS_PER_HISTORICAL_ROOT to force wraparound of those
@ -68,7 +69,16 @@ proc getTestStates*(initialState: ForkedHashedBeaconState):
if getStateField(tmpState[], slot) < slot:
doAssert process_slots(
tmpState[], slot, cache, rewards, {}, FAR_FUTURE_SLOT)
if useAltair and epoch == 1:
maybeUpgradeStateToAltair(tmpState[], slot)
if i mod 3 == 0:
valid_deposit(tmpState.hbsPhase0.data)
if tmpState[].beaconStateFork == forkPhase0:
valid_deposit(tmpState[].hbsPhase0.data)
else:
valid_deposit(tmpState[].hbsAltair.data)
doAssert getStateField(tmpState[], slot) == slot
result.add assignClone(tmpState[])
if useAltair == (tmpState[].beaconStateFork == forkAltair):
result.add assignClone(tmpState[])