Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Electra beacon chain database state tests #6584

Merged
merged 1 commit into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions AllTests-mainnet.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ OK: 4/4 Fail: 0/4 Skip: 0/4
+ sanity check Deneb blocks [Preset: mainnet] OK
+ sanity check Deneb states [Preset: mainnet] OK
+ sanity check Deneb states, reusing buffers [Preset: mainnet] OK
+ sanity check Electra and cross-fork getState rollback [Preset: mainnet] OK
+ sanity check Electra blocks [Preset: mainnet] OK
+ sanity check Electra states [Preset: mainnet] OK
+ sanity check Electra states, reusing buffers [Preset: mainnet] OK
+ sanity check blobs [Preset: mainnet] OK
+ sanity check genesis roundtrip [Preset: mainnet] OK
+ sanity check phase 0 blocks [Preset: mainnet] OK
Expand All @@ -66,7 +69,7 @@ OK: 4/4 Fail: 0/4 Skip: 0/4
+ sanity check phase 0 states, reusing buffers [Preset: mainnet] OK
+ sanity check state diff roundtrip [Preset: mainnet] OK
```
OK: 26/26 Fail: 0/26 Skip: 0/26
OK: 29/29 Fail: 0/29 Skip: 0/29
## Beacon state [Preset: mainnet]
```diff
+ Smoke test initialize_beacon_state_from_eth1 [Preset: mainnet] OK
Expand Down Expand Up @@ -1125,4 +1128,4 @@ OK: 2/2 Fail: 0/2 Skip: 0/2
OK: 9/9 Fail: 0/9 Skip: 0/9

---TOTAL---
OK: 762/767 Fail: 0/767 Skip: 5/767
OK: 765/770 Fail: 0/770 Skip: 5/770
3 changes: 0 additions & 3 deletions beacon_chain/consensus_object_pools/blockchain_dag.nim
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,9 @@ import
../spec/[beaconstate, eth2_merkleization, eth2_ssz_serialization, helpers,
state_transition, validator],
../spec/forks,
../spec/datatypes/[phase0, altair, bellatrix, capella],
".."/[beacon_chain_db, beacon_clock, era_db],
"."/[block_pools_types, block_quarantine]

from ../spec/datatypes/deneb import shortLog

export
eth2_merkleization, eth2_ssz_serialization,
block_pools_types, results, beacon_chain_db
Expand Down
109 changes: 90 additions & 19 deletions tests/test_beacon_chain_db.nim
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,24 @@
import
unittest2,
../beacon_chain/beacon_chain_db,
../beacon_chain/spec/[beaconstate, forks, state_transition],
../beacon_chain/consensus_object_pools/blockchain_dag,
eth/db/kvstore,
# test utilies
./mocking/mock_genesis,
./testutil, ./testdbutil, ./testblockutil, ./teststateutil
../beacon_chain/consensus_object_pools/block_dag,
../beacon_chain/spec/forks,
./testutil

from std/algorithm import sort
from std/sequtils import toSeq
from snappy import encodeFramed, uncompressedLenFramed
from ../beacon_chain/consensus_object_pools/block_pools_types import
ChainDAGRef
from ../beacon_chain/consensus_object_pools/blockchain_dag import init
from ../beacon_chain/spec/beaconstate import
initialize_hashed_beacon_state_from_eth1
from ../beacon_chain/spec/state_transition import noRollback
from ../beacon_chain/validators/validator_monitor import ValidatorMonitor
from ./mocking/mock_genesis import mockEth1BlockHash
from ./testblockutil import makeInitialDeposits
from ./testdbutil import makeTestDB
from ./teststateutil import getTestStates

when isMainModule:
import chronicles # or some random compile error happens...
Expand All @@ -46,25 +54,27 @@ 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

from ../beacon_chain/spec/datatypes/deneb import TrustedSignedBeaconBlock

proc getDenebStateRef(db: BeaconChainDB, root: Eth2Digest):
deneb.NilableBeaconStateRef =
# load beaconstate the way the block pool does it - into an existing instance
let res = (deneb.BeaconStateRef)()
if db.getState(root, res[], noRollback):
return res

proc getElectraStateRef(db: BeaconChainDB, root: Eth2Digest):
electra.NilableBeaconStateRef =
# load beaconstate the way the block pool does it - into an existing instance
let res = (electra.BeaconStateRef)()
if db.getState(root, res[], noRollback):
return res

func withDigest(blck: phase0.TrustedBeaconBlock):
phase0.TrustedSignedBeaconBlock =
phase0.TrustedSignedBeaconBlock(
Expand Down Expand Up @@ -120,20 +130,20 @@ proc getTestStates(consensusFork: ConsensusFork): auto =

testStates

debugComment "add some electra states, and test electra state loading/etc"

# Each set of states gets used twice, so scope them to module
let
testStatesPhase0 = getTestStates(ConsensusFork.Phase0)
testStatesAltair = getTestStates(ConsensusFork.Altair)
testStatesBellatrix = getTestStates(ConsensusFork.Bellatrix)
testStatesCapella = getTestStates(ConsensusFork.Capella)
testStatesDeneb = getTestStates(ConsensusFork.Deneb)
testStatesElectra = getTestStates(ConsensusFork.Electra)
doAssert len(testStatesPhase0) > 8
doAssert len(testStatesAltair) > 8
doAssert len(testStatesBellatrix) > 8
doAssert len(testStatesCapella) > 8
doAssert len(testStatesDeneb) > 8
doAssert len(testStatesElectra) > 8

suite "Beacon chain DB" & preset():
test "empty database" & preset():
Expand Down Expand Up @@ -527,6 +537,24 @@ suite "Beacon chain DB" & preset():

db.close()

test "sanity check Electra states" & preset():
let db = makeTestDB(SLOTS_PER_EPOCH)

for state in testStatesElectra:
let root = state[].electraData.root
db.putState(root, state[].electraData.data)

check:
db.containsState(root)
hash_tree_root(db.getElectraStateRef(root)[]) == root

db.delState(ConsensusFork.Electra, root)
check:
not db.containsState(root)
db.getElectraStateRef(root).isNil

db.close()

test "sanity check phase 0 states, reusing buffers" & preset():
let db = makeTestDB(SLOTS_PER_EPOCH)
let stateBuffer = (phase0.BeaconStateRef)()
Expand Down Expand Up @@ -627,6 +655,26 @@ suite "Beacon chain DB" & preset():

db.close()

test "sanity check Electra states, reusing buffers" & preset():
let db = makeTestDB(SLOTS_PER_EPOCH)
let stateBuffer = (electra.BeaconStateRef)()

for state in testStatesElectra:
let root = state[].electraData.root
db.putState(root, state[].electraData.data)

check:
db.getState(root, stateBuffer[], noRollback)
db.containsState(root)
hash_tree_root(stateBuffer[]) == root

db.delState(ConsensusFork.Electra, root)
check:
not db.containsState(root)
not db.getState(root, stateBuffer[], noRollback)

db.close()

test "sanity check phase 0 getState rollback" & preset():
var
db = makeTestDB(SLOTS_PER_EPOCH)
Expand Down Expand Up @@ -754,9 +802,34 @@ suite "Beacon chain DB" & preset():
state[].kind == ConsensusFork.Phase0
state[].phase0Data.data.slot != 10.Slot

test "find ancestors" & preset():
test "sanity check Electra and cross-fork getState rollback" & preset():
var
db = BeaconChainDB.new("", inMemory = true)
db = makeTestDB(SLOTS_PER_EPOCH)
validatorMonitor = newClone(ValidatorMonitor.init())
dag = init(ChainDAGRef, defaultRuntimeConfig, db, validatorMonitor, {})
state = (ref ForkedHashedBeaconState)(
kind: ConsensusFork.Electra,
electraData: electra.HashedBeaconState(data: electra.BeaconState(
slot: 10.Slot)))
root = Eth2Digest()

db.putCorruptState(ConsensusFork.Electra, root)

let restoreAddr = addr dag.headState

func restore() =
assign(state[], restoreAddr[])

check:
state[].electraData.data.slot == 10.Slot
not db.getState(root, state[].electraData.data, restore)

# assign() has switched the case object fork
state[].kind == ConsensusFork.Phase0
state[].phase0Data.data.slot != 10.Slot

test "find ancestors" & preset():
var db = BeaconChainDB.new("", inMemory = true)

let
a0 = withDigest(
Expand Down Expand Up @@ -791,8 +864,7 @@ suite "Beacon chain DB" & preset():
# state. We've been bit by this because we've had a bug in the BLS
# serialization where an all-zero default-initialized bls signature could
# not be deserialized because the deserialization was too strict.
var
db = BeaconChainDB.new("", inMemory = true)
var db = BeaconChainDB.new("", inMemory = true)

let
state = newClone(initialize_hashed_beacon_state_from_eth1(
Expand All @@ -811,8 +883,7 @@ suite "Beacon chain DB" & preset():
hash_tree_root(state2[]) == state[].root

test "sanity check state diff roundtrip" & preset():
var
db = BeaconChainDB.new("", inMemory = true)
var db = BeaconChainDB.new("", inMemory = true)

# TODO htr(diff) probably not interesting/useful, but stand-in
let
Expand Down
11 changes: 9 additions & 2 deletions tests/teststateutil.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,15 @@ proc valid_deposit(state: var ForkyHashedBeaconState) =
defaultRuntimeConfig, state.data,
sortValidatorBuckets(state.data.validators.asSeq)[], deposit, {}).isOk
doAssert state.data.validators.len == pre_val_count + 1
doAssert state.data.balances.len == pre_val_count + 1
doAssert state.data.balances.item(validator_index) == pre_balance + deposit.data.amount
when typeof(state).kind >= ConsensusFork.Electra:
doAssert state.data.pending_balance_deposits.asSeq[^1] ==
PendingBalanceDeposit(index: pre_val_count.uint64,
amount: deposit.data.amount)
doAssert state.data.balances.item(validator_index) == pre_balance
else:
doAssert state.data.balances.item(validator_index) ==
pre_balance + deposit.data.amount

doAssert state.data.validators.item(validator_index).effective_balance ==
round_multiple_down(
min(
Expand Down
Loading