altair fork handling cleanups (#3050)
* fix stack overflow crash in REST/debug/getStateV2 * introduce `ForkyXxx` for generic type matching of `Xxx` across branches (SomeHashedBeaconState -> ForkyHashedBeaconState et al) - `Some` is already used for other types of type classes * consolidate function naming in BeaconChainDB, use some generics * import `forks.nim` from other spec modules and move `Forked*` helpers around to resolve circular imports * remove `ForkedBeaconState`, use `ForkedHashedBeaconState` throughout (less data shuffling between the types) * fix several cases of states being stored on stack in tests, causing random failures on some platforms * remove reading json support from ncli - this should be ported to the rest json reading instead (doesn't currently work because stack sizes)
This commit is contained in:
parent
98668dbf16
commit
a086cf01ac
|
@ -13,7 +13,7 @@ import
|
|||
serialization, chronicles, snappy,
|
||||
eth/db/[kvstore, kvstore_sqlite3],
|
||||
./networking/network_metadata, ./beacon_chain_db_immutable,
|
||||
./spec/[eth2_ssz_serialization, eth2_merkleization, state_transition],
|
||||
./spec/[eth2_ssz_serialization, eth2_merkleization, forks, state_transition],
|
||||
./spec/datatypes/[phase0, altair, merge],
|
||||
./filepath
|
||||
|
||||
|
@ -93,7 +93,7 @@ type
|
|||
altairBlocks: KvStoreRef # BlockRoot -> altair.TrustedBeaconBlock
|
||||
mergeBlocks: KvStoreRef # BlockRoot -> merge.TrustedBeaconBlock
|
||||
stateRoots: KvStoreRef # (Slot, BlockRoot) -> StateRoot
|
||||
statesNoVal: KvStoreRef # StateRoot -> BeaconStateNoImmutableValidators
|
||||
statesNoVal: KvStoreRef # StateRoot -> Phase0BeaconStateNoImmutableValidators
|
||||
altairStatesNoVal: KvStoreRef # StateRoot -> AltairBeaconStateNoImmutableValidators
|
||||
mergeStatesNoVal: KvStoreRef # StateRoot -> MergeBeaconStateNoImmutableValidators
|
||||
stateDiffs: KvStoreRef ##\
|
||||
|
@ -120,7 +120,7 @@ type
|
|||
## past the weak subjectivity period.
|
||||
kBlockSlotStateRoot
|
||||
## BlockSlot -> state_root mapping
|
||||
kGenesisBlockRoot
|
||||
kGenesisBlock
|
||||
## Immutable reference to the network genesis state
|
||||
## (needed for satisfying requests to the beacon node API).
|
||||
kEth1PersistedTo # Obsolete
|
||||
|
@ -168,7 +168,7 @@ func subkey(kind: type phase0.BeaconState, key: Eth2Digest): auto =
|
|||
subkey(kHashToState, key.data)
|
||||
|
||||
func subkey(
|
||||
kind: type BeaconStateNoImmutableValidators, key: Eth2Digest): auto =
|
||||
kind: type Phase0BeaconStateNoImmutableValidators, key: Eth2Digest): auto =
|
||||
subkey(kHashToStateOnlyMutableValidators, key.data)
|
||||
|
||||
func subkey(kind: type phase0.SignedBeaconBlock, key: Eth2Digest): auto =
|
||||
|
@ -508,27 +508,34 @@ proc updateImmutableValidators*(
|
|||
db.immutableValidatorsDb.add immutableValidator
|
||||
db.immutableValidators.add immutableValidator
|
||||
|
||||
template toBeaconStateNoImmutableValidators(state: phase0.BeaconState):
|
||||
Phase0BeaconStateNoImmutableValidators =
|
||||
isomorphicCast[Phase0BeaconStateNoImmutableValidators](state)
|
||||
|
||||
template toBeaconStateNoImmutableValidators(state: altair.BeaconState):
|
||||
AltairBeaconStateNoImmutableValidators =
|
||||
isomorphicCast[AltairBeaconStateNoImmutableValidators](state)
|
||||
|
||||
template toBeaconStateNoImmutableValidators(state: merge.BeaconState):
|
||||
MergeBeaconStateNoImmutableValidators =
|
||||
isomorphicCast[MergeBeaconStateNoImmutableValidators](state)
|
||||
|
||||
proc putState*(db: BeaconChainDB, key: Eth2Digest, value: phase0.BeaconState) =
|
||||
db.updateImmutableValidators(value.validators.asSeq())
|
||||
db.statesNoVal.putSnappySSZ(
|
||||
key.data,
|
||||
isomorphicCast[BeaconStateNoImmutableValidators](value))
|
||||
key.data, toBeaconStateNoImmutableValidators(value))
|
||||
|
||||
proc putState*(db: BeaconChainDB, key: Eth2Digest, value: altair.BeaconState) =
|
||||
db.updateImmutableValidators(value.validators.asSeq())
|
||||
db.altairStatesNoVal.putSnappySSZ(
|
||||
key.data,
|
||||
isomorphicCast[AltairBeaconStateNoImmutableValidators](value))
|
||||
key.data, toBeaconStateNoImmutableValidators(value))
|
||||
|
||||
proc putState*(db: BeaconChainDB, key: Eth2Digest, value: merge.BeaconState) =
|
||||
db.updateImmutableValidators(value.validators.asSeq())
|
||||
db.mergeStatesNoVal.putSnappySSZ(
|
||||
key.data,
|
||||
isomorphicCast[MergeBeaconStateNoImmutableValidators](value))
|
||||
key.data, toBeaconStateNoImmutableValidators(value))
|
||||
|
||||
proc putState*(
|
||||
db: BeaconChainDB,
|
||||
value: phase0.BeaconState | altair.BeaconState | merge.BeaconState) =
|
||||
proc putState*(db: BeaconChainDB, value: ForkyBeaconState) =
|
||||
db.putState(hash_tree_root(value), value)
|
||||
|
||||
# For testing rollback
|
||||
|
@ -579,14 +586,14 @@ proc putHeadBlock*(db: BeaconChainDB, key: Eth2Digest) =
|
|||
proc putTailBlock*(db: BeaconChainDB, key: Eth2Digest) =
|
||||
db.keyValues.putRaw(subkey(kTailBlock), key)
|
||||
|
||||
proc putGenesisBlockRoot*(db: BeaconChainDB, key: Eth2Digest) =
|
||||
db.keyValues.putRaw(subkey(kGenesisBlockRoot), key)
|
||||
proc putGenesisBlock*(db: BeaconChainDB, key: Eth2Digest) =
|
||||
db.keyValues.putRaw(subkey(kGenesisBlock), key)
|
||||
|
||||
proc putEth2FinalizedTo*(db: BeaconChainDB,
|
||||
eth1Checkpoint: DepositContractSnapshot) =
|
||||
db.keyValues.putSnappySSZ(subkey(kDepositsFinalizedByEth2), eth1Checkpoint)
|
||||
|
||||
proc getBlock(db: BeaconChainDBV0, key: Eth2Digest): Opt[phase0.TrustedSignedBeaconBlock] =
|
||||
proc getPhase0Block(db: BeaconChainDBV0, key: Eth2Digest): Opt[phase0.TrustedSignedBeaconBlock] =
|
||||
# We only store blocks that we trust in the database
|
||||
result.ok(default(phase0.TrustedSignedBeaconBlock))
|
||||
if db.backend.getSnappySSZ(
|
||||
|
@ -596,12 +603,12 @@ proc getBlock(db: BeaconChainDBV0, key: Eth2Digest): Opt[phase0.TrustedSignedBea
|
|||
# set root after deserializing (so it doesn't get zeroed)
|
||||
result.get().root = key
|
||||
|
||||
proc getBlock*(db: BeaconChainDB, key: Eth2Digest):
|
||||
proc getPhase0Block*(db: BeaconChainDB, key: Eth2Digest):
|
||||
Opt[phase0.TrustedSignedBeaconBlock] =
|
||||
# We only store blocks that we trust in the database
|
||||
result.ok(default(phase0.TrustedSignedBeaconBlock))
|
||||
if db.blocks.getSnappySSZ(key.data, result.get) != GetResult.found:
|
||||
result = db.v0.getBlock(key)
|
||||
result = db.v0.getPhase0Block(key)
|
||||
else:
|
||||
# set root after deserializing (so it doesn't get zeroed)
|
||||
result.get().root = key
|
||||
|
@ -628,7 +635,7 @@ proc getMergeBlock*(db: BeaconChainDB, key: Eth2Digest):
|
|||
|
||||
proc getStateOnlyMutableValidators(
|
||||
immutableValidators: openArray[ImmutableValidatorData2],
|
||||
store: KvStoreRef, key: openArray[byte], output: var phase0.BeaconState,
|
||||
store: KvStoreRef, key: openArray[byte], output: var ForkyBeaconState,
|
||||
rollback: RollbackProc): bool =
|
||||
## Load state into `output` - BeaconState is large so we want to avoid
|
||||
## re-allocating it if possible
|
||||
|
@ -641,92 +648,7 @@ proc getStateOnlyMutableValidators(
|
|||
# TODO RVO is inefficient for large objects:
|
||||
# https://github.com/nim-lang/Nim/issues/13879
|
||||
|
||||
case store.getSnappySSZ(
|
||||
key, isomorphicCast[BeaconStateNoImmutableValidators](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()
|
||||
false
|
||||
|
||||
proc getAltairStateOnlyMutableValidators(
|
||||
immutableValidators: openArray[ImmutableValidatorData2],
|
||||
store: KvStoreRef, key: openArray[byte], output: var altair.BeaconState,
|
||||
rollback: RollbackProc): 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()
|
||||
false
|
||||
|
||||
proc getMergeStateOnlyMutableValidators(
|
||||
immutableValidators: openArray[ImmutableValidatorData2],
|
||||
store: KvStoreRef, key: openArray[byte], output: var merge.BeaconState,
|
||||
rollback: RollbackProc): 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[MergeBeaconStateNoImmutableValidators](output))
|
||||
case store.getSnappySSZ(key, toBeaconStateNoImmutableValidators(output))
|
||||
of GetResult.found:
|
||||
let numValidators = output.validators.len
|
||||
doAssert immutableValidators.len >= numValidators
|
||||
|
@ -765,11 +687,11 @@ proc getState(
|
|||
# from `stateStore`. We will try to read the state from all these locations.
|
||||
if getStateOnlyMutableValidators(
|
||||
immutableValidators, db.stateStore,
|
||||
subkey(BeaconStateNoImmutableValidators, key), output, rollback):
|
||||
subkey(Phase0BeaconStateNoImmutableValidators, key), output, rollback):
|
||||
return true
|
||||
if getStateOnlyMutableValidators(
|
||||
immutableValidators, db.backend,
|
||||
subkey(BeaconStateNoImmutableValidators, key), output, rollback):
|
||||
subkey(Phase0BeaconStateNoImmutableValidators, key), output, rollback):
|
||||
return true
|
||||
|
||||
case db.backend.getSnappySSZ(subkey(phase0.BeaconState, key), output)
|
||||
|
@ -800,7 +722,7 @@ proc getState*(
|
|||
else:
|
||||
true
|
||||
|
||||
proc getAltairState*(
|
||||
proc getState*(
|
||||
db: BeaconChainDB, key: Eth2Digest, output: var altair.BeaconState,
|
||||
rollback: RollbackProc): bool =
|
||||
## Load state into `output` - BeaconState is large so we want to avoid
|
||||
|
@ -813,10 +735,10 @@ proc getAltairState*(
|
|||
# https://github.com/nim-lang/Nim/issues/14126
|
||||
# TODO RVO is inefficient for large objects:
|
||||
# https://github.com/nim-lang/Nim/issues/13879
|
||||
getAltairStateOnlyMutableValidators(
|
||||
getStateOnlyMutableValidators(
|
||||
db.immutableValidators, db.altairStatesNoVal, key.data, output, rollback)
|
||||
|
||||
proc getMergeState*(
|
||||
proc getState*(
|
||||
db: BeaconChainDB, key: Eth2Digest, output: var merge.BeaconState,
|
||||
rollback: RollbackProc): bool =
|
||||
## Load state into `output` - BeaconState is large so we want to avoid
|
||||
|
@ -829,7 +751,7 @@ proc getMergeState*(
|
|||
# https://github.com/nim-lang/Nim/issues/14126
|
||||
# TODO RVO is inefficient for large objects:
|
||||
# https://github.com/nim-lang/Nim/issues/13879
|
||||
getMergeStateOnlyMutableValidators(
|
||||
getStateOnlyMutableValidators(
|
||||
db.immutableValidators, db.mergeStatesNoVal, key.data, output, rollback)
|
||||
|
||||
proc getStateRoot(db: BeaconChainDBV0,
|
||||
|
@ -863,12 +785,12 @@ proc getTailBlock*(db: BeaconChainDB): Opt[Eth2Digest] =
|
|||
db.keyValues.getRaw(subkey(kTailBlock), Eth2Digest) or
|
||||
db.v0.getTailBlock()
|
||||
|
||||
proc getGenesisBlockRoot(db: BeaconChainDBV0): Opt[Eth2Digest] =
|
||||
db.backend.getRaw(subkey(kGenesisBlockRoot), Eth2Digest)
|
||||
proc getGenesisBlock(db: BeaconChainDBV0): Opt[Eth2Digest] =
|
||||
db.backend.getRaw(subkey(kGenesisBlock), Eth2Digest)
|
||||
|
||||
proc getGenesisBlockRoot*(db: BeaconChainDB): Opt[Eth2Digest] =
|
||||
db.keyValues.getRaw(subkey(kGenesisBlockRoot), Eth2Digest) or
|
||||
db.v0.getGenesisBlockRoot()
|
||||
proc getGenesisBlock*(db: BeaconChainDB): Opt[Eth2Digest] =
|
||||
db.keyValues.getRaw(subkey(kGenesisBlock), Eth2Digest) or
|
||||
db.v0.getGenesisBlock()
|
||||
|
||||
proc getEth2FinalizedTo(db: BeaconChainDBV0): Opt[DepositContractSnapshot] =
|
||||
result.ok(DepositContractSnapshot())
|
||||
|
@ -898,7 +820,7 @@ proc containsBlock*(db: BeaconChainDB, key: Eth2Digest): bool =
|
|||
db.containsBlockPhase0(key)
|
||||
|
||||
proc containsState*(db: BeaconChainDBV0, key: Eth2Digest): bool =
|
||||
let sk = subkey(BeaconStateNoImmutableValidators, key)
|
||||
let sk = subkey(Phase0BeaconStateNoImmutableValidators, key)
|
||||
db.stateStore.contains(sk).expectDb() or
|
||||
db.backend.contains(sk).expectDb() or
|
||||
db.backend.contains(subkey(phase0.BeaconState, key)).expectDb()
|
||||
|
|
|
@ -17,7 +17,7 @@ import
|
|||
type
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#beaconstate
|
||||
# Memory-representation-equivalent to a phase0 BeaconState for in-place SSZ reading and writing
|
||||
BeaconStateNoImmutableValidators* = object
|
||||
Phase0BeaconStateNoImmutableValidators* = object
|
||||
# Versioning
|
||||
genesis_time*: uint64
|
||||
genesis_validators_root*: Eth2Digest
|
||||
|
|
|
@ -374,8 +374,7 @@ proc addAttestation*(pool: var AttestationPool,
|
|||
proc addForkChoice*(pool: var AttestationPool,
|
||||
epochRef: EpochRef,
|
||||
blckRef: BlockRef,
|
||||
blck: phase0.TrustedBeaconBlock | altair.TrustedBeaconBlock |
|
||||
merge.TrustedBeaconBlock,
|
||||
blck: ForkyTrustedBeaconBlock,
|
||||
wallSlot: Slot) =
|
||||
## Add a verified block to the fork choice context
|
||||
let state = pool.forkChoice.process_block(
|
||||
|
@ -510,7 +509,7 @@ proc score(
|
|||
bitsScore
|
||||
|
||||
proc getAttestationsForBlock*(pool: var AttestationPool,
|
||||
state: SomeHashedBeaconState,
|
||||
state: ForkyHashedBeaconState,
|
||||
cache: var StateCache): seq[Attestation] =
|
||||
## Retrieve attestations that may be added to a new block at the slot of the
|
||||
## given state
|
||||
|
|
|
@ -31,43 +31,6 @@ export results, ValidationResult
|
|||
logScope:
|
||||
topics = "clearance"
|
||||
|
||||
## At the GC-level, the GC is type-agnostic; it's all type-erased so
|
||||
## casting between seq[Attestation] and seq[TrustedAttestation] will
|
||||
## not disrupt GC operations.
|
||||
##
|
||||
## These SHOULD be used in function calls to avoid expensive temporary.
|
||||
## see https://github.com/status-im/nimbus-eth2/pull/2250#discussion_r562010679
|
||||
template asSigVerified(x: phase0.SignedBeaconBlock):
|
||||
phase0.SigVerifiedSignedBeaconBlock =
|
||||
## This converts a signed beacon block to a sig verified beacon clock.
|
||||
## This verifies that their bytes representation is the same.
|
||||
isomorphicCast[phase0.SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified(x: altair.SignedBeaconBlock):
|
||||
altair.SigVerifiedSignedBeaconBlock =
|
||||
## This converts a signed beacon block to a sig verified beacon clock.
|
||||
## This verifies that their bytes representation is the same.
|
||||
isomorphicCast[altair.SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified(x: merge.SignedBeaconBlock):
|
||||
merge.SigVerifiedSignedBeaconBlock =
|
||||
## This converts a signed beacon block to a sig verified beacon clock.
|
||||
## This verifies that their bytes representation is the same.
|
||||
isomorphicCast[merge.SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
# TODO aren't these in forks.nim?
|
||||
template asTrusted(x: phase0.SignedBeaconBlock or phase0.SigVerifiedBeaconBlock):
|
||||
phase0.TrustedSignedBeaconBlock =
|
||||
## This converts a sigverified beacon block to a trusted beacon clock.
|
||||
## This verifies that their bytes representation is the same.
|
||||
isomorphicCast[phase0.TrustedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted(x: altair.SignedBeaconBlock or altair.SigVerifiedBeaconBlock):
|
||||
altair.TrustedSignedBeaconBlock =
|
||||
## This converts a sigverified beacon block to a trusted beacon clock.
|
||||
## This verifies that their bytes representation is the same.
|
||||
isomorphicCast[altair.TrustedSignedBeaconBlock](x)
|
||||
|
||||
proc batchVerify(quarantine: QuarantineRef, sigs: openArray[SignatureSet]): bool =
|
||||
var secureRandomBytes: array[32, byte]
|
||||
quarantine.rng[].brHmacDrbgGenerate(secureRandomBytes)
|
||||
|
@ -78,8 +41,7 @@ proc batchVerify(quarantine: QuarantineRef, sigs: openArray[SignatureSet]): bool
|
|||
|
||||
proc addRawBlock*(
|
||||
dag: ChainDAGRef, quarantine: QuarantineRef,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock,
|
||||
signedBlock: ForkySignedBeaconBlock,
|
||||
onBlockAdded: OnPhase0BlockAdded | OnAltairBlockAdded | OnMergeBlockAdded
|
||||
): Result[BlockRef, (ValidationResult, BlockError)] {.gcsafe.}
|
||||
|
||||
|
@ -144,8 +106,7 @@ proc resolveQuarantinedBlocks(
|
|||
proc addResolvedBlock(
|
||||
dag: ChainDAGRef, quarantine: QuarantineRef,
|
||||
state: var StateData,
|
||||
trustedBlock: phase0.TrustedSignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
||||
merge.TrustedSignedBeaconBlock,
|
||||
trustedBlock: ForkyTrustedSignedBeaconBlock,
|
||||
parent: BlockRef, cache: var StateCache,
|
||||
onBlockAdded: OnPhase0BlockAdded | OnAltairBlockAdded | OnMergeBlockAdded,
|
||||
stateDataDur, sigVerifyDur, stateVerifyDur: Duration
|
||||
|
@ -261,8 +222,7 @@ proc advanceClearanceState*(dag: ChainDAGRef) =
|
|||
|
||||
proc addRawBlockKnownParent(
|
||||
dag: ChainDAGRef, quarantine: QuarantineRef,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock,
|
||||
signedBlock: ForkySignedBeaconBlock,
|
||||
parent: BlockRef,
|
||||
onBlockAdded: OnPhase0BlockAdded | OnAltairBlockAdded | OnMergeBlockAdded
|
||||
): Result[BlockRef, (ValidationResult, BlockError)] =
|
||||
|
@ -390,8 +350,7 @@ proc addRawBlockUnresolved(
|
|||
|
||||
proc addRawBlock(
|
||||
dag: ChainDAGRef, quarantine: QuarantineRef,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock,
|
||||
signedBlock: ForkySignedBeaconBlock,
|
||||
onBlockAdded: OnPhase0BlockAdded | OnAltairBlockAdded | OnMergeBlockAdded
|
||||
): Result[BlockRef, (ValidationResult, BlockError)] =
|
||||
## Try adding a block to the chain, verifying first that it passes the state
|
||||
|
|
|
@ -183,7 +183,7 @@ type
|
|||
## block - we limit the number of held EpochRefs to put a cap on
|
||||
## memory usage
|
||||
|
||||
forkDigests*: ForkDigestsRef
|
||||
forkDigests*: ref ForkDigests
|
||||
## Cached copy of the fork digests associated with the current
|
||||
## database. We use a ref type to facilitate sharing this small
|
||||
## value with other components which don't have access to the
|
||||
|
|
|
@ -12,6 +12,7 @@ import
|
|||
chronicles,
|
||||
stew/bitops2,
|
||||
eth/keys,
|
||||
../spec/forks,
|
||||
../spec/datatypes/[phase0, altair, merge],
|
||||
./block_pools_types
|
||||
|
||||
|
@ -102,9 +103,7 @@ func removeOrphan*(
|
|||
quarantine.orphansMerge.del((signedBlock.root, signedBlock.signature))
|
||||
|
||||
func isViableOrphan(
|
||||
dag: ChainDAGRef,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock): bool =
|
||||
dag: ChainDAGRef, signedBlock: ForkySignedBeaconBlock): bool =
|
||||
# The orphan must be newer than the finalization point so that its parent
|
||||
# either is the finalized block or more recent
|
||||
signedBlock.message.slot > dag.finalizedHead.slot
|
||||
|
|
|
@ -18,7 +18,10 @@ import
|
|||
".."/beacon_chain_db,
|
||||
"."/[block_pools_types, block_quarantine, forkedbeaconstate_dbhelpers]
|
||||
|
||||
export block_pools_types, results
|
||||
export
|
||||
forks, block_pools_types, results, forkedbeaconstate_dbhelpers,
|
||||
beacon_chain_db,
|
||||
eth2_merkleization, eth2_ssz_serialization
|
||||
|
||||
# https://github.com/ethereum/eth2.0-metrics/blob/master/metrics.md#interop-metrics
|
||||
declareGauge beacon_head_root, "Root of the head block of the beacon chain"
|
||||
|
@ -46,9 +49,7 @@ declareGauge beacon_processed_deposits_total, "Number of total deposits included
|
|||
logScope: topics = "chaindag"
|
||||
|
||||
proc putBlock*(
|
||||
dag: ChainDAGRef,
|
||||
signedBlock: phase0.TrustedSignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
||||
merge.TrustedSignedBeaconBlock) =
|
||||
dag: ChainDAGRef, signedBlock: ForkyTrustedSignedBeaconBlock) =
|
||||
dag.db.putBlock(signedBlock)
|
||||
|
||||
proc updateStateData*(
|
||||
|
@ -343,23 +344,18 @@ proc getStateData(
|
|||
if not root.isSome():
|
||||
return false
|
||||
|
||||
case cfg.stateForkAtEpoch(bs.slot.epoch)
|
||||
of BeaconStateFork.Merge:
|
||||
if state.data.kind != BeaconStateFork.Merge:
|
||||
state.data = (ref ForkedHashedBeaconState)(kind: BeaconStateFork.Merge)[]
|
||||
let expectedFork = cfg.stateForkAtEpoch(bs.slot.epoch)
|
||||
if state.data.kind != expectedFork:
|
||||
state.data = (ref ForkedHashedBeaconState)(kind: expectedFork)[]
|
||||
|
||||
if not db.getMergeState(root.get(), state.data.mergeData.data, rollback):
|
||||
case expectedFork
|
||||
of BeaconStateFork.Merge:
|
||||
if not db.getState(root.get(), state.data.mergeData.data, rollback):
|
||||
return false
|
||||
of BeaconStateFork.Altair:
|
||||
if state.data.kind != BeaconStateFork.Altair:
|
||||
state.data = (ref ForkedHashedBeaconState)(kind: BeaconStateFork.Altair)[]
|
||||
|
||||
if not db.getAltairState(root.get(), state.data.altairData.data, rollback):
|
||||
if not db.getState(root.get(), state.data.altairData.data, rollback):
|
||||
return false
|
||||
of BeaconStateFork.Phase0:
|
||||
if state.data.kind != BeaconStateFork.Phase0:
|
||||
state.data = (ref ForkedHashedBeaconState)(kind: BeaconStateFork.Phase0)[]
|
||||
|
||||
if not db.getState(root.get(), state.data.phase0Data.data, rollback):
|
||||
return false
|
||||
|
||||
|
@ -384,7 +380,7 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
|
|||
|
||||
let
|
||||
tailRoot = tailBlockRoot.get()
|
||||
tailBlock = db.getBlock(tailRoot).get()
|
||||
tailBlock = db.getPhase0Block(tailRoot).get()
|
||||
tailRef = BlockRef.init(tailRoot, tailBlock.message)
|
||||
headRoot = headBlockRoot.get()
|
||||
|
||||
|
@ -392,9 +388,9 @@ proc init*(T: type ChainDAGRef, cfg: RuntimeConfig, db: BeaconChainDB,
|
|||
tailRef
|
||||
else:
|
||||
let
|
||||
genesisBlockRoot = db.getGenesisBlockRoot().expect(
|
||||
genesisBlockRoot = db.getGenesisBlock().expect(
|
||||
"preInit should have initialized the database with a genesis block root")
|
||||
genesisBlock = db.getBlock(genesisBlockRoot).expect(
|
||||
genesisBlock = db.getPhase0Block(genesisBlockRoot).expect(
|
||||
"preInit should have initialized the database with a genesis block")
|
||||
BlockRef.init(genesisBlockRoot, genesisBlock.message)
|
||||
|
||||
|
@ -727,7 +723,7 @@ func getBlockBySlot*(dag: ChainDAGRef, slot: Slot): BlockRef =
|
|||
proc getForkedBlock*(dag: ChainDAGRef, blck: BlockRef): ForkedTrustedSignedBeaconBlock =
|
||||
case dag.cfg.blockForkAtEpoch(blck.slot.epoch)
|
||||
of BeaconBlockFork.Phase0:
|
||||
let data = dag.db.getBlock(blck.root)
|
||||
let data = dag.db.getPhase0Block(blck.root)
|
||||
if data.isOk():
|
||||
return ForkedTrustedSignedBeaconBlock.init(data.get)
|
||||
of BeaconBlockFork.Altair:
|
||||
|
@ -1324,9 +1320,9 @@ proc isInitialized*(T: type ChainDAGRef, db: BeaconChainDB): bool =
|
|||
return false
|
||||
|
||||
let
|
||||
headBlockPhase0 = db.getBlock(headBlockRoot.get())
|
||||
headBlockPhase0 = db.getPhase0Block(headBlockRoot.get())
|
||||
headBlockAltair = db.getAltairBlock(headBlockRoot.get())
|
||||
tailBlock = db.getBlock(tailBlockRoot.get())
|
||||
tailBlock = db.getPhase0Block(tailBlockRoot.get())
|
||||
|
||||
if not ((headBlockPhase0.isSome() or headBlockAltair.isSome()) and
|
||||
tailBlock.isSome()):
|
||||
|
@ -1359,14 +1355,14 @@ proc preInit*(
|
|||
db.putStateRoot(tailBlock.root, tailState.slot, tailBlock.message.state_root)
|
||||
|
||||
if tailState.slot == GENESIS_SLOT:
|
||||
db.putGenesisBlockRoot(tailBlock.root)
|
||||
db.putGenesisBlock(tailBlock.root)
|
||||
else:
|
||||
doAssert genesisState.slot == GENESIS_SLOT
|
||||
db.putState(genesisState)
|
||||
let genesisBlock = get_initial_beacon_block(genesisState)
|
||||
db.putBlock(genesisBlock)
|
||||
db.putStateRoot(genesisBlock.root, GENESIS_SLOT, genesisBlock.message.state_root)
|
||||
db.putGenesisBlockRoot(genesisBlock.root)
|
||||
db.putGenesisBlock(genesisBlock.root)
|
||||
|
||||
func setTailState*(dag: ChainDAGRef,
|
||||
checkpointState: phase0.BeaconState,
|
||||
|
|
|
@ -132,7 +132,7 @@ func getExitMessagesForBlock(
|
|||
|
||||
subpool.clear()
|
||||
|
||||
func getBeaconBlockExits*(pool: var ExitPool, state: SomeBeaconState): BeaconBlockExits =
|
||||
func getBeaconBlockExits*(pool: var ExitPool, state: ForkyBeaconState): BeaconBlockExits =
|
||||
var
|
||||
indices: HashSet[uint64]
|
||||
res: BeaconBlockExits
|
||||
|
|
|
@ -130,8 +130,7 @@ proc addBlock*(
|
|||
|
||||
proc dumpBlock*[T](
|
||||
self: BlockProcessor,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock,
|
||||
signedBlock: ForkySignedBeaconBlock,
|
||||
res: Result[T, (ValidationResult, BlockError)]) =
|
||||
if self.dumpEnabled and res.isErr:
|
||||
case res.error[1]
|
||||
|
@ -146,8 +145,7 @@ proc dumpBlock*[T](
|
|||
|
||||
proc storeBlock*(
|
||||
self: var BlockProcessor,
|
||||
signedBlock: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock,
|
||||
signedBlock: ForkySignedBeaconBlock,
|
||||
wallSlot: Slot): Result[BlockRef, BlockError] =
|
||||
let
|
||||
attestationPool = self.consensusManager.attestationPool
|
||||
|
|
|
@ -76,7 +76,7 @@ type
|
|||
connTable: HashSet[PeerID]
|
||||
forkId*: ENRForkID
|
||||
discoveryForkId*: ENRForkID
|
||||
forkDigests*: ForkDigestsRef
|
||||
forkDigests*: ref ForkDigests
|
||||
rng*: ref BrHmacDrbgContext
|
||||
peers*: Table[PeerID, Peer]
|
||||
validTopics: HashSet[string]
|
||||
|
@ -1302,7 +1302,7 @@ proc onConnEvent(node: Eth2Node, peerId: PeerID, event: ConnEvent) {.async.} =
|
|||
peer.connectionState = Disconnected
|
||||
|
||||
proc new*(T: type Eth2Node, config: BeaconNodeConf, runtimeCfg: RuntimeConfig,
|
||||
enrForkId: ENRForkID, discoveryForkId: ENRForkId, forkDigests: ForkDigestsRef,
|
||||
enrForkId: ENRForkID, discoveryForkId: ENRForkId, forkDigests: ref ForkDigests,
|
||||
getBeaconTime: GetBeaconTimeFn, switch: Switch,
|
||||
pubsub: GossipSub, ip: Option[ValidIpAddress], tcpPort,
|
||||
udpPort: Option[Port], privKey: keys.PrivateKey, discovery: bool,
|
||||
|
@ -1827,7 +1827,7 @@ proc createEth2Node*(rng: ref BrHmacDrbgContext,
|
|||
config: BeaconNodeConf,
|
||||
netKeys: NetKeyPair,
|
||||
cfg: RuntimeConfig,
|
||||
forkDigests: ForkDigestsRef,
|
||||
forkDigests: ref ForkDigests,
|
||||
getBeaconTime: GetBeaconTimeFn,
|
||||
genesisValidatorsRoot: Eth2Digest): Eth2Node
|
||||
{.raises: [Defect, CatchableError].} =
|
||||
|
|
|
@ -12,7 +12,7 @@ import
|
|||
tables, times, terminal],
|
||||
|
||||
# Nimble packages
|
||||
serialization, json_serialization, spec/eth2_apis/eth2_rest_serialization,
|
||||
spec/eth2_apis/eth2_rest_serialization,
|
||||
stew/[objects, byteutils, endians2, io2], stew/shims/macros,
|
||||
chronos, confutils, metrics, metrics/chronos_httpserver,
|
||||
chronicles, bearssl, blscurve, presto,
|
||||
|
|
|
@ -14,7 +14,7 @@ import
|
|||
../beacon_node, ../networking/eth2_network,
|
||||
../consensus_object_pools/[blockchain_dag, exit_pool, spec_cache],
|
||||
../validators/validator_duties,
|
||||
../spec/[eth2_merkleization, forks, network],
|
||||
../spec/[eth2_merkleization, forks, network, validator],
|
||||
../spec/datatypes/[phase0, altair]
|
||||
|
||||
export rest_utils
|
||||
|
|
|
@ -77,8 +77,7 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) =
|
|||
return
|
||||
case contentType
|
||||
of "application/json":
|
||||
RestApiResponse.jsonResponsePlain(
|
||||
ForkedBeaconState.init(stateData.data))
|
||||
RestApiResponse.jsonResponsePlain(stateData.data)
|
||||
of "application/octet-stream":
|
||||
withState(stateData.data):
|
||||
RestApiResponse.sszResponse(state.data)
|
||||
|
|
|
@ -17,7 +17,7 @@ import
|
|||
../networking/eth2_network,
|
||||
../validators/validator_duties,
|
||||
../consensus_object_pools/blockchain_dag,
|
||||
../spec/[eth2_merkleization, forks, network],
|
||||
../spec/[eth2_merkleization, forks, network, validator],
|
||||
../spec/datatypes/[phase0],
|
||||
./rpc_utils
|
||||
|
||||
|
|
|
@ -14,17 +14,17 @@ import
|
|||
chronicles,
|
||||
../extras,
|
||||
./datatypes/[phase0, altair, merge],
|
||||
"."/[eth2_merkleization, helpers, signatures, validator],
|
||||
"."/[eth2_merkleization, forks, signatures, validator],
|
||||
../../nbench/bench_lab
|
||||
|
||||
export extras, phase0, altair, merge
|
||||
export extras, forks, validator
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#increase_balance
|
||||
func increase_balance*(balance: var Gwei, delta: Gwei) =
|
||||
balance += delta
|
||||
|
||||
func increase_balance*(
|
||||
state: var SomeBeaconState, index: ValidatorIndex, delta: Gwei) =
|
||||
state: var ForkyBeaconState, index: ValidatorIndex, delta: Gwei) =
|
||||
## Increase the validator balance at index ``index`` by ``delta``.
|
||||
if delta != 0: # avoid dirtying the balance cache if not needed
|
||||
increase_balance(state.balances[index], delta)
|
||||
|
@ -38,7 +38,7 @@ func decrease_balance*(balance: var Gwei, delta: Gwei) =
|
|||
balance - delta
|
||||
|
||||
func decrease_balance*(
|
||||
state: var SomeBeaconState, index: ValidatorIndex, delta: Gwei) =
|
||||
state: var ForkyBeaconState, index: ValidatorIndex, delta: Gwei) =
|
||||
## Decrease the validator balance at index ``index`` by ``delta``, with
|
||||
## underflow protection.
|
||||
if delta != 0: # avoid dirtying the balance cache if not needed
|
||||
|
@ -71,7 +71,7 @@ func compute_activation_exit_epoch*(epoch: Epoch): Epoch =
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_validator_churn_limit
|
||||
func get_validator_churn_limit*(
|
||||
cfg: RuntimeConfig, state: SomeBeaconState, cache: var StateCache):
|
||||
cfg: RuntimeConfig, state: ForkyBeaconState, cache: var StateCache):
|
||||
uint64 =
|
||||
## Return the validator churn limit for the current epoch.
|
||||
max(
|
||||
|
@ -80,7 +80,7 @@ func get_validator_churn_limit*(
|
|||
state, state.get_current_epoch(), cache) div cfg.CHURN_LIMIT_QUOTIENT)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#initiate_validator_exit
|
||||
func initiate_validator_exit*(cfg: RuntimeConfig, state: var SomeBeaconState,
|
||||
func initiate_validator_exit*(cfg: RuntimeConfig, state: var ForkyBeaconState,
|
||||
index: ValidatorIndex, cache: var StateCache) =
|
||||
## Initiate the exit of the validator with index ``index``.
|
||||
|
||||
|
@ -122,7 +122,7 @@ func initiate_validator_exit*(cfg: RuntimeConfig, state: var SomeBeaconState,
|
|||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#slash_validator
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/altair/beacon-chain.md#modified-slash_validator
|
||||
proc slash_validator*(
|
||||
cfg: RuntimeConfig, state: var SomeBeaconState,
|
||||
cfg: RuntimeConfig, state: var ForkyBeaconState,
|
||||
slashed_index: ValidatorIndex, cache: var StateCache) =
|
||||
## Slash the validator with index ``index``.
|
||||
let epoch = get_current_epoch(state)
|
||||
|
@ -184,26 +184,6 @@ proc slash_validator*(
|
|||
func genesis_time_from_eth1_timestamp*(cfg: RuntimeConfig, eth1_timestamp: uint64): uint64 =
|
||||
eth1_timestamp + cfg.GENESIS_DELAY
|
||||
|
||||
func genesisFork*(cfg: RuntimeConfig): Fork =
|
||||
Fork(
|
||||
previous_version: cfg.GENESIS_FORK_VERSION,
|
||||
current_version: cfg.GENESIS_FORK_VERSION,
|
||||
epoch: GENESIS_EPOCH)
|
||||
|
||||
func altairFork*(cfg: RuntimeConfig): Fork =
|
||||
Fork(
|
||||
previous_version: cfg.GENESIS_FORK_VERSION,
|
||||
current_version: cfg.ALTAIR_FORK_VERSION,
|
||||
epoch: cfg.ALTAIR_FORK_EPOCH)
|
||||
|
||||
func mergeFork*(cfg: RuntimeConfig): Fork =
|
||||
# TODO in theory, the altair + merge forks could be in same epoch, so the
|
||||
# previous fork version would be the GENESIS_FORK_VERSION
|
||||
Fork(
|
||||
previous_version: cfg.ALTAIR_FORK_VERSION,
|
||||
current_version: cfg.MERGE_FORK_VERSION,
|
||||
epoch: cfg.MERGE_FORK_EPOCH)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#genesis
|
||||
proc initialize_beacon_state_from_eth1*(
|
||||
cfg: RuntimeConfig,
|
||||
|
@ -315,8 +295,7 @@ func get_initial_beacon_block*(state: phase0.BeaconState):
|
|||
message: message, root: hash_tree_root(message))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_block_root_at_slot
|
||||
func get_block_root_at_slot*(state: SomeBeaconState,
|
||||
slot: Slot): Eth2Digest =
|
||||
func get_block_root_at_slot*(state: ForkyBeaconState, slot: Slot): Eth2Digest =
|
||||
## Return the block root at a recent ``slot``.
|
||||
|
||||
# Potential overflow/wrap shouldn't occur, as get_block_root_at_slot() called
|
||||
|
@ -327,14 +306,20 @@ func get_block_root_at_slot*(state: SomeBeaconState,
|
|||
doAssert slot < state.slot
|
||||
state.block_roots[slot mod SLOTS_PER_HISTORICAL_ROOT]
|
||||
|
||||
func get_block_root_at_slot*(state: ForkedHashedBeaconState,
|
||||
slot: Slot): Eth2Digest =
|
||||
## Return the block root at a recent ``slot``.
|
||||
withState(state):
|
||||
get_block_root_at_slot(state.data, slot)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_block_root
|
||||
func get_block_root*(state: SomeBeaconState, epoch: Epoch): Eth2Digest =
|
||||
func get_block_root*(state: ForkyBeaconState, epoch: Epoch): Eth2Digest =
|
||||
## Return the block root at the start of a recent ``epoch``.
|
||||
get_block_root_at_slot(state, compute_start_slot_at_epoch(epoch))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_total_balance
|
||||
template get_total_balance(
|
||||
state: SomeBeaconState, validator_indices: untyped): Gwei =
|
||||
state: ForkyBeaconState, validator_indices: untyped): Gwei =
|
||||
## Return the combined effective balance of the ``indices``.
|
||||
## ``EFFECTIVE_BALANCE_INCREMENT`` Gwei minimum to avoid divisions by zero.
|
||||
## Math safe up to ~10B ETH, afterwhich this overflows uint64.
|
||||
|
@ -350,7 +335,7 @@ func is_eligible_for_activation_queue*(validator: Validator): bool =
|
|||
validator.effective_balance == MAX_EFFECTIVE_BALANCE
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#is_eligible_for_activation
|
||||
func is_eligible_for_activation*(state: SomeBeaconState, validator: Validator):
|
||||
func is_eligible_for_activation*(state: ForkyBeaconState, validator: Validator):
|
||||
bool =
|
||||
## Check if ``validator`` is eligible for activation.
|
||||
|
||||
|
@ -361,7 +346,7 @@ func is_eligible_for_activation*(state: SomeBeaconState, validator: Validator):
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#is_valid_indexed_attestation
|
||||
proc is_valid_indexed_attestation*(
|
||||
state: SomeBeaconState, indexed_attestation: SomeIndexedAttestation,
|
||||
state: ForkyBeaconState, indexed_attestation: SomeIndexedAttestation,
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
## Check if ``indexed_attestation`` is not empty, has sorted and unique
|
||||
## indices and has a valid aggregate signature.
|
||||
|
@ -398,7 +383,7 @@ proc is_valid_indexed_attestation*(
|
|||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_attesting_indices
|
||||
func get_attesting_indices*(state: SomeBeaconState,
|
||||
func get_attesting_indices*(state: ForkyBeaconState,
|
||||
data: AttestationData,
|
||||
bits: CommitteeValidatorsBits,
|
||||
cache: var StateCache): seq[ValidatorIndex] =
|
||||
|
@ -419,8 +404,21 @@ func get_attesting_indices*(state: SomeBeaconState,
|
|||
|
||||
res
|
||||
|
||||
proc get_attesting_indices*(state: ForkedHashedBeaconState;
|
||||
data: AttestationData;
|
||||
bits: CommitteeValidatorsBits;
|
||||
cache: var StateCache): seq[ValidatorIndex] =
|
||||
# TODO when https://github.com/nim-lang/Nim/issues/18188 fixed, use an
|
||||
# iterator
|
||||
|
||||
var idxBuf: seq[ValidatorIndex]
|
||||
withState(state):
|
||||
for vidx in state.data.get_attesting_indices(data, bits, cache):
|
||||
idxBuf.add vidx
|
||||
idxBuf
|
||||
|
||||
proc is_valid_indexed_attestation*(
|
||||
state: SomeBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
state: ForkyBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] =
|
||||
# This is a variation on `is_valid_indexed_attestation` that works directly
|
||||
# with an attestation instead of first constructing an `IndexedAttestation`
|
||||
|
@ -524,7 +522,7 @@ func get_attestation_participation_flag_indices(state: altair.BeaconState | merg
|
|||
# better to centralize around that if feasible
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_total_active_balance
|
||||
func get_total_active_balance*(state: SomeBeaconState, cache: var StateCache): Gwei =
|
||||
func get_total_active_balance*(state: ForkyBeaconState, cache: var StateCache): Gwei =
|
||||
## Return the combined effective balance of the active validators.
|
||||
# Note: ``get_total_balance`` returns ``EFFECTIVE_BALANCE_INCREMENT`` Gwei
|
||||
# minimum to avoid divisions by zero.
|
||||
|
@ -555,7 +553,7 @@ func get_base_reward(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/phase0/beacon-chain.md#attestations
|
||||
proc check_attestation*(
|
||||
state: SomeBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
state: ForkyBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] =
|
||||
## Check that an attestation follows the rules of being included in the state
|
||||
## at the current slot. When acting as a proposer, the same rules need to
|
||||
|
@ -589,7 +587,7 @@ proc check_attestation*(
|
|||
ok()
|
||||
|
||||
proc process_attestation*(
|
||||
state: var SomeBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
state: var ForkyBeaconState, attestation: SomeAttestation, flags: UpdateFlags,
|
||||
base_reward_per_increment: Gwei, cache: var StateCache):
|
||||
Result[void, cstring] {.nbench.} =
|
||||
# In the spec, attestation validation is mixed with state mutation, so here
|
||||
|
|
|
@ -543,3 +543,14 @@ template hash*(x: LightClientUpdate): Hash =
|
|||
func clear*(info: var EpochInfo) =
|
||||
info.validators.setLen(0)
|
||||
info.balances = UnslashedParticipatingBalances()
|
||||
|
||||
template asSigned*(x: SigVerifiedSignedBeaconBlock | TrustedSignedBeaconBlock):
|
||||
SignedBeaconBlock =
|
||||
isomorphicCast[SignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified*(x: SignedBeaconBlock | TrustedSignedBeaconBlock): SigVerifiedSignedBeaconBlock =
|
||||
isomorphicCast[SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(
|
||||
x: SignedBeaconBlock | SigVerifiedSignedBeaconBlock): TrustedSignedBeaconBlock =
|
||||
isomorphicCast[TrustedSignedBeaconBlock](x)
|
||||
|
|
|
@ -734,6 +734,7 @@ template assignClone*[T: not ref](x: T): ref T =
|
|||
# This is a bit of a mess: if x is an rvalue (temporary), RVO kicks in for
|
||||
# newClone - if it's not, `genericAssign` will be called which is ridiculously
|
||||
# slow - so `assignClone` should be used when RVO doesn't work. sigh.
|
||||
mixin assign
|
||||
let res = new typeof(x) # TODO safe to do noinit here?
|
||||
assign(res[], x)
|
||||
res
|
||||
|
@ -938,6 +939,12 @@ func getSizeofSig(x: auto, n: int = 0): seq[(string, int, int)] =
|
|||
# is still better to keep field names parallel.
|
||||
result.add((name.replace("blob", "data"), sizeof(value), n))
|
||||
|
||||
## At the GC-level, the GC is type-agnostic; it's all type-erased so
|
||||
## casting between seq[Attestation] and seq[TrustedAttestation] will
|
||||
## not disrupt GC operations.
|
||||
##
|
||||
## These SHOULD be used in function calls to avoid expensive temporary.
|
||||
## see https://github.com/status-im/nimbus-eth2/pull/2250#discussion_r562010679
|
||||
template isomorphicCast*[T, U](x: U): T =
|
||||
# Each of these pairs of types has ABI-compatible memory representations.
|
||||
static:
|
||||
|
|
|
@ -167,9 +167,6 @@ type
|
|||
data*: BeaconState
|
||||
root*: Eth2Digest # hash_tree_root(data)
|
||||
|
||||
SomeBeaconState* = BeaconState | altair.BeaconState | phase0.BeaconState
|
||||
SomeHashedBeaconState* = HashedBeaconState | altair.HashedBeaconState | phase0.HashedBeaconState
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#beaconblock
|
||||
BeaconBlock* = object
|
||||
## For each slot, a proposer is chosen from the validator pool to propose
|
||||
|
@ -397,3 +394,14 @@ func shortLog*(v: SomeSignedBeaconBlock): auto =
|
|||
blck: shortLog(v.message),
|
||||
signature: shortLog(v.signature)
|
||||
)
|
||||
|
||||
template asSigned*(x: SigVerifiedSignedBeaconBlock | TrustedSignedBeaconBlock):
|
||||
SignedBeaconBlock =
|
||||
isomorphicCast[SignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified*(x: SignedBeaconBlock | TrustedSignedBeaconBlock): SigVerifiedSignedBeaconBlock =
|
||||
isomorphicCast[SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(
|
||||
x: SignedBeaconBlock | SigVerifiedSignedBeaconBlock): TrustedSignedBeaconBlock =
|
||||
isomorphicCast[TrustedSignedBeaconBlock](x)
|
||||
|
|
|
@ -289,3 +289,14 @@ func shortLog*(v: SomeSignedBeaconBlock): auto =
|
|||
blck: shortLog(v.message),
|
||||
signature: shortLog(v.signature)
|
||||
)
|
||||
|
||||
template asSigned*(x: SigVerifiedSignedBeaconBlock | TrustedSignedBeaconBlock):
|
||||
SignedBeaconBlock =
|
||||
isomorphicCast[SignedBeaconBlock](x)
|
||||
|
||||
template asSigVerified*(x: SignedBeaconBlock | TrustedSignedBeaconBlock): SigVerifiedSignedBeaconBlock =
|
||||
isomorphicCast[SigVerifiedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(
|
||||
x: SignedBeaconBlock | SigVerifiedSignedBeaconBlock): TrustedSignedBeaconBlock =
|
||||
isomorphicCast[TrustedSignedBeaconBlock](x)
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import std/typetraits
|
||||
import stew/[results, base10, byteutils, endians2], presto/common,
|
||||
import stew/[assign2, results, base10, byteutils, endians2], presto/common,
|
||||
libp2p/peerid, serialization,
|
||||
json_serialization, json_serialization/std/[options, net, sets],
|
||||
nimcrypto/utils as ncrutils
|
||||
|
@ -821,9 +821,10 @@ proc writeValue*(writer: var JsonWriter[RestJson],
|
|||
writer.writeField("data", value.mergeData)
|
||||
writer.endRecord()
|
||||
|
||||
# ForkedBeaconState
|
||||
# ForkedHashedBeaconState is used where a `ForkedBeaconState` normally would
|
||||
# be used, mainly because caching the hash early on is easier to do
|
||||
proc readValue*(reader: var JsonReader[RestJson],
|
||||
value: var ForkedBeaconState) {.
|
||||
value: var ForkedHashedBeaconState) {.
|
||||
raises: [IOError, SerializationError, Defect].} =
|
||||
var
|
||||
version: Option[BeaconStateFork]
|
||||
|
@ -854,53 +855,58 @@ proc readValue*(reader: var JsonReader[RestJson],
|
|||
if data.isNone():
|
||||
reader.raiseUnexpectedValue("Field data is missing")
|
||||
|
||||
# Use a temporary to avoid stack instances and `value` mutation in case of
|
||||
# exception
|
||||
let
|
||||
tmp = (ref ForkedHashedBeaconState)(kind: version.get())
|
||||
|
||||
template toValue(field: untyped) =
|
||||
if tmp[].kind == value.kind:
|
||||
assign(value.field, tmp[].field)
|
||||
else:
|
||||
value = tmp[] # slow, but rare (hopefully)
|
||||
value.field.root = hash_tree_root(value.field.data)
|
||||
|
||||
case version.get():
|
||||
of BeaconStateFork.Phase0:
|
||||
let res =
|
||||
try:
|
||||
some(RestJson.decode(string(data.get()), phase0.BeaconState,
|
||||
requireAllFields = true))
|
||||
except SerializationError:
|
||||
none[phase0.BeaconState]()
|
||||
if res.isNone():
|
||||
try:
|
||||
tmp[].phase0Data.data = RestJson.decode(
|
||||
string(data.get()), phase0.BeaconState, requireAllFields = true)
|
||||
except SerializationError:
|
||||
reader.raiseUnexpectedValue("Incorrect phase0 beacon state format")
|
||||
value = ForkedBeaconState.init(res.get())
|
||||
of BeaconStateFork.Altair:
|
||||
let res =
|
||||
try:
|
||||
some(RestJson.decode(string(data.get()), altair.BeaconState,
|
||||
requireAllFields = true))
|
||||
except SerializationError:
|
||||
none[altair.BeaconState]()
|
||||
if res.isNone():
|
||||
reader.raiseUnexpectedValue("Incorrect altair beacon state format")
|
||||
value = ForkedBeaconState.init(res.get())
|
||||
of BeaconStateFork.Merge:
|
||||
let res =
|
||||
try:
|
||||
some(RestJson.decode(string(data.get()), merge.BeaconState,
|
||||
requireAllFields = true))
|
||||
except SerializationError:
|
||||
none[merge.BeaconState]()
|
||||
if res.isNone():
|
||||
reader.raiseUnexpectedValue("Incorrect merge beacon state format")
|
||||
value = ForkedBeaconState.init(res.get())
|
||||
|
||||
proc writeValue*(writer: var JsonWriter[RestJson], value: ForkedBeaconState) {.
|
||||
toValue(phase0Data)
|
||||
of BeaconStateFork.Altair:
|
||||
try:
|
||||
tmp[].altairData.data = RestJson.decode(
|
||||
string(data.get()), altair.BeaconState, requireAllFields = true)
|
||||
except SerializationError:
|
||||
reader.raiseUnexpectedValue("Incorrect altair beacon state format")
|
||||
|
||||
toValue(altairData)
|
||||
of BeaconStateFork.Merge:
|
||||
try:
|
||||
tmp[].mergeData.data = RestJson.decode(
|
||||
string(data.get()), merge.BeaconState, requireAllFields = true)
|
||||
except SerializationError:
|
||||
reader.raiseUnexpectedValue("Incorrect altair beacon state format")
|
||||
toValue(mergeData)
|
||||
|
||||
proc writeValue*(writer: var JsonWriter[RestJson], value: ForkedHashedBeaconState) {.
|
||||
raises: [IOError, Defect].} =
|
||||
writer.beginRecord()
|
||||
case value.kind
|
||||
of BeaconStateFork.Phase0:
|
||||
writer.writeField("version", "phase0")
|
||||
writer.writeField("data", value.phase0Data)
|
||||
writer.writeField("data", value.phase0Data.data)
|
||||
of BeaconStateFork.Altair:
|
||||
writer.writeField("version", "altair")
|
||||
writer.writeField("data", value.altairData)
|
||||
writer.writeField("data", value.altairData.data)
|
||||
of BeaconStateFork.Merge:
|
||||
writer.writeField("version", "merge")
|
||||
when false:
|
||||
# TODO SerializationError
|
||||
writer.writeField("data", value.mergeData)
|
||||
writer.writeField("data", value.mergeData.data)
|
||||
writer.endRecord()
|
||||
|
||||
# SyncSubcommitteeIndex
|
||||
|
|
|
@ -20,7 +20,7 @@ proc getStatePlain*(state_id: StateIdent): RestPlainResponse {.
|
|||
## https://ethereum.github.io/beacon-APIs/#/Beacon/getState
|
||||
|
||||
proc getState*(client: RestClientRef, state_id: StateIdent,
|
||||
restAccept = ""): Future[ForkedBeaconState] {.async.} =
|
||||
restAccept = ""): Future[phase0.BeaconState] {.async.} =
|
||||
let resp =
|
||||
if len(restAccept) > 0:
|
||||
await client.getStatePlain(state_id, restAcceptType = restAccept)
|
||||
|
@ -38,7 +38,7 @@ proc getState*(client: RestClientRef, state_id: StateIdent,
|
|||
if res.isErr():
|
||||
raise newException(RestError, $res.error())
|
||||
res.get()
|
||||
ForkedBeaconState.init(state.data)
|
||||
state.data
|
||||
of "application/octet-stream":
|
||||
let state =
|
||||
block:
|
||||
|
@ -47,7 +47,7 @@ proc getState*(client: RestClientRef, state_id: StateIdent,
|
|||
if res.isErr():
|
||||
raise newException(RestError, $res.error())
|
||||
res.get()
|
||||
ForkedBeaconState.init(state)
|
||||
state
|
||||
else:
|
||||
raise newException(RestError, "Unsupported content-type")
|
||||
of 400, 404, 500:
|
||||
|
@ -79,7 +79,7 @@ proc getStateV2Plain*(state_id: StateIdent): RestPlainResponse {.
|
|||
|
||||
proc getStateV2*(client: RestClientRef, state_id: StateIdent,
|
||||
forks: array[2, Fork],
|
||||
restAccept = ""): Future[ForkedBeaconState] {.async.} =
|
||||
restAccept = ""): Future[ForkedHashedBeaconState] {.async.} =
|
||||
let resp =
|
||||
if len(restAccept) > 0:
|
||||
await client.getStateV2Plain(state_id, restAcceptType = restAccept)
|
||||
|
@ -106,23 +106,25 @@ proc getStateV2*(client: RestClientRef, state_id: StateIdent,
|
|||
raise newException(RestError, $res.error())
|
||||
res.get()
|
||||
if header.slot.epoch() < forks[1].epoch:
|
||||
let state =
|
||||
let state = newClone(
|
||||
block:
|
||||
let res = decodeBytes(GetPhase0StateSszResponse, resp.data,
|
||||
resp.contentType)
|
||||
if res.isErr():
|
||||
raise newException(RestError, $res.error())
|
||||
res.get()
|
||||
ForkedBeaconState.init(state)
|
||||
let res = newClone(decodeBytes(
|
||||
GetPhase0StateSszResponse, resp.data, resp.contentType))
|
||||
if res[].isErr():
|
||||
raise newException(RestError, $res[].error())
|
||||
res[].get())
|
||||
ForkedHashedBeaconState.init(phase0.HashedBeaconState(
|
||||
data: state[], root: hash_tree_root(state[])))
|
||||
else:
|
||||
let blck =
|
||||
let state = newClone(
|
||||
block:
|
||||
let res = decodeBytes(GetAltairStateSszResponse, resp.data,
|
||||
resp.contentType)
|
||||
if res.isErr():
|
||||
raise newException(RestError, $res.error())
|
||||
res.get()
|
||||
ForkedBeaconState.init(blck)
|
||||
let res = newClone(decodeBytes(
|
||||
GetAltairStateSszResponse, resp.data, resp.contentType))
|
||||
if res[].isErr():
|
||||
raise newException(RestError, $res[].error())
|
||||
res[].get())
|
||||
ForkedHashedBeaconState.init(altair.HashedBeaconState(
|
||||
data: state[], root: hash_tree_root(state[])))
|
||||
else:
|
||||
raise newException(RestError, "Unsupported content-type")
|
||||
of 400, 404, 500:
|
||||
|
|
|
@ -414,7 +414,7 @@ type
|
|||
GetStateResponse* = DataEnclosedObject[phase0.BeaconState]
|
||||
GetBlockV2Response* = ForkedSignedBeaconBlock
|
||||
GetBlockV2Header* = ForkedSignedBlockHeader
|
||||
GetStateV2Response* = ForkedBeaconState
|
||||
GetStateV2Response* = ForkedHashedBeaconState
|
||||
GetStateV2Header* = ForkedBeaconStateHeader
|
||||
GetPhase0StateSszResponse* = phase0.BeaconState
|
||||
GetAltairStateSszResponse* = altair.BeaconState
|
||||
|
|
|
@ -8,15 +8,31 @@
|
|||
{.push raises: [Defect].}
|
||||
|
||||
import
|
||||
std/macros,
|
||||
stew/[assign2],
|
||||
chronicles,
|
||||
stew/[assign2, results],
|
||||
../extras,
|
||||
../spec/[
|
||||
beaconstate, eth2_merkleization, helpers, state_transition_block, validator],
|
||||
"."/[eth2_merkleization, eth2_ssz_serialization, presets],
|
||||
./datatypes/[phase0, altair, merge]
|
||||
|
||||
export extras, phase0, altair, eth2_merkleization
|
||||
export
|
||||
extras, phase0, altair, merge, eth2_merkleization, eth2_ssz_serialization,
|
||||
presets
|
||||
|
||||
# This file contains helpers for dealing with forks - we have two ways we can
|
||||
# deal with forks:
|
||||
# * generics - this means using the static typing and differentiating forks
|
||||
# at compile time - this is preferred in fork-specific code where the fork
|
||||
# is known up-front, for example spec functions.
|
||||
# * variants - this means using a variant object and determining the fork at
|
||||
# runtime - this carries the obvious risk and complexity of dealing with
|
||||
# runtime checking, but is of course needed for external data that may be
|
||||
# of any fork kind.
|
||||
#
|
||||
# For generics, we define `Forky*` type classes that cover "similar" objects
|
||||
# across forks - for variants, they're called `Forked*` instead.
|
||||
# See withXxx and `init` for convenient ways of moving between these two worlds.
|
||||
# A clever programmer would use templates, macros and dark magic to create all
|
||||
# these types and converters :)
|
||||
|
||||
type
|
||||
BeaconStateFork* {.pure.} = enum
|
||||
|
@ -24,49 +40,70 @@ type
|
|||
Altair,
|
||||
Merge
|
||||
|
||||
ForkyBeaconState* =
|
||||
phase0.BeaconState |
|
||||
altair.BeaconState |
|
||||
merge.BeaconState
|
||||
|
||||
ForkyHashedBeaconState* =
|
||||
phase0.HashedBeaconState |
|
||||
altair.HashedBeaconState |
|
||||
merge.HashedBeaconState
|
||||
|
||||
ForkedHashedBeaconState* = object
|
||||
case kind*: BeaconStateFork
|
||||
of BeaconStateFork.Phase0: phase0Data*: phase0.HashedBeaconState
|
||||
of BeaconStateFork.Altair: altairData*: altair.HashedBeaconState
|
||||
of BeaconStateFork.Merge: mergeData*: merge.HashedBeaconState
|
||||
|
||||
ForkedBeaconState* = object
|
||||
case kind*: BeaconStateFork
|
||||
of BeaconStateFork.Phase0: phase0Data*: phase0.BeaconState
|
||||
of BeaconStateFork.Altair: altairData*: altair.BeaconState
|
||||
of BeaconStateFork.Merge: mergeData*: merge.BeaconState
|
||||
|
||||
BeaconBlockFork* {.pure.} = enum
|
||||
Phase0
|
||||
Altair
|
||||
Merge
|
||||
|
||||
ForkyBeaconBlock* =
|
||||
phase0.BeaconBlock |
|
||||
altair.BeaconBlock |
|
||||
merge.BeaconBlock
|
||||
|
||||
ForkyTrustedBeaconBlock* =
|
||||
phase0.TrustedBeaconBlock |
|
||||
altair.TrustedBeaconBlock |
|
||||
merge.TrustedBeaconBlock
|
||||
|
||||
ForkedBeaconBlock* = object
|
||||
case kind*: BeaconBlockFork
|
||||
of BeaconBlockFork.Phase0:
|
||||
phase0Data*: phase0.BeaconBlock
|
||||
of BeaconBlockFork.Altair:
|
||||
altairData*: altair.BeaconBlock
|
||||
of BeaconBlockFork.Merge:
|
||||
mergeData*: merge.BeaconBlock
|
||||
of BeaconBlockFork.Phase0: phase0Data*: phase0.BeaconBlock
|
||||
of BeaconBlockFork.Altair: altairData*: altair.BeaconBlock
|
||||
of BeaconBlockFork.Merge: mergeData*: merge.BeaconBlock
|
||||
|
||||
ForkedTrustedBeaconBlock* = object
|
||||
case kind*: BeaconBlockFork
|
||||
of BeaconBlockFork.Phase0: phase0Data*: phase0.TrustedBeaconBlock
|
||||
of BeaconBlockFork.Altair: altairData*: altair.TrustedBeaconBlock
|
||||
of BeaconBlockFork.Merge: mergeData*: merge.TrustedBeaconBlock
|
||||
|
||||
ForkySignedBeaconBlock* =
|
||||
phase0.SignedBeaconBlock |
|
||||
altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock
|
||||
|
||||
ForkedSignedBeaconBlock* = object
|
||||
case kind*: BeaconBlockFork
|
||||
of BeaconBlockFork.Phase0:
|
||||
phase0Data*: phase0.SignedBeaconBlock
|
||||
of BeaconBlockFork.Altair:
|
||||
altairData*: altair.SignedBeaconBlock
|
||||
of BeaconBlockFork.Merge:
|
||||
mergeData*: merge.SignedBeaconBlock
|
||||
of BeaconBlockFork.Phase0: phase0Data*: phase0.SignedBeaconBlock
|
||||
of BeaconBlockFork.Altair: altairData*: altair.SignedBeaconBlock
|
||||
of BeaconBlockFork.Merge: mergeData*: merge.SignedBeaconBlock
|
||||
|
||||
ForkyTrustedSignedBeaconBlock* =
|
||||
phase0.TrustedSignedBeaconBlock |
|
||||
altair.TrustedSignedBeaconBlock |
|
||||
merge.TrustedSignedBeaconBlock
|
||||
|
||||
ForkedTrustedSignedBeaconBlock* = object
|
||||
case kind*: BeaconBlockFork
|
||||
of BeaconBlockFork.Phase0:
|
||||
phase0Data*: phase0.TrustedSignedBeaconBlock
|
||||
of BeaconBlockFork.Altair:
|
||||
altairData*: altair.TrustedSignedBeaconBlock
|
||||
of BeaconBlockFork.Merge:
|
||||
mergeData*: merge.TrustedSignedBeaconBlock
|
||||
of BeaconBlockFork.Phase0: phase0Data*: phase0.TrustedSignedBeaconBlock
|
||||
of BeaconBlockFork.Altair: altairData*: altair.TrustedSignedBeaconBlock
|
||||
of BeaconBlockFork.Merge: mergeData*: merge.TrustedSignedBeaconBlock
|
||||
|
||||
EpochInfoFork* {.pure.} = enum
|
||||
Phase0
|
||||
|
@ -74,10 +111,8 @@ type
|
|||
|
||||
ForkedEpochInfo* = object
|
||||
case kind*: EpochInfoFork
|
||||
of EpochInfoFork.Phase0:
|
||||
phase0Data*: phase0.EpochInfo
|
||||
of EpochInfoFork.Altair:
|
||||
altairData*: altair.EpochInfo
|
||||
of EpochInfoFork.Phase0: phase0Data*: phase0.EpochInfo
|
||||
of EpochInfoFork.Altair: altairData*: altair.EpochInfo
|
||||
|
||||
ForkyEpochInfo* = phase0.EpochInfo | altair.EpochInfo
|
||||
|
||||
|
@ -86,7 +121,22 @@ type
|
|||
altair*: ForkDigest
|
||||
merge*: ForkDigest
|
||||
|
||||
ForkDigestsRef* = ref ForkDigests
|
||||
template toFork*[T: phase0.BeaconState | phase0.HashedBeaconState](
|
||||
t: type T): BeaconStateFork =
|
||||
BeaconStateFork.Phase0
|
||||
template toFork*[T: altair.BeaconState | altair.HashedBeaconState](
|
||||
t: type T): BeaconStateFork =
|
||||
BeaconStateFork.Altair
|
||||
template toFork*[T: merge.BeaconState | merge.HashedBeaconState](
|
||||
t: type T): BeaconStateFork =
|
||||
BeaconStateFork.Merge
|
||||
|
||||
template init*(T: type ForkedHashedBeaconState, data: phase0.HashedBeaconState): T =
|
||||
T(kind: BeaconStateFork.Phase0, phase0Data: data)
|
||||
template init*(T: type ForkedHashedBeaconState, data: altair.HashedBeaconState): T =
|
||||
T(kind: BeaconStateFork.Altair, altairData: data)
|
||||
template init*(T: type ForkedHashedBeaconState, data: merge.HashedBeaconState): T =
|
||||
T(kind: BeaconStateFork.Merge, mergeData: data)
|
||||
|
||||
template init*(T: type ForkedBeaconBlock, blck: phase0.BeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Phase0, phase0Data: blck)
|
||||
|
@ -95,6 +145,13 @@ template init*(T: type ForkedBeaconBlock, blck: altair.BeaconBlock): T =
|
|||
template init*(T: type ForkedBeaconBlock, blck: merge.BeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Merge, mergeData: blck)
|
||||
|
||||
template init*(T: type ForkedTrustedBeaconBlock, blck: phase0.TrustedBeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Phase0, phase0Data: blck)
|
||||
template init*(T: type ForkedTrustedBeaconBlock, blck: altair.TrustedBeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Altair, altairData: blck)
|
||||
template init*(T: type ForkedTrustedBeaconBlock, blck: merge.TrustedBeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Merge, mergeData: blck)
|
||||
|
||||
template init*(T: type ForkedSignedBeaconBlock, blck: phase0.SignedBeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Phase0, phase0Data: blck)
|
||||
template init*(T: type ForkedSignedBeaconBlock, blck: altair.SignedBeaconBlock): T =
|
||||
|
@ -102,37 +159,19 @@ template init*(T: type ForkedSignedBeaconBlock, blck: altair.SignedBeaconBlock):
|
|||
template init*(T: type ForkedSignedBeaconBlock, blck: merge.SignedBeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Merge, mergeData: blck)
|
||||
|
||||
template init*(T: type ForkedBeaconState, state: phase0.BeaconState): T =
|
||||
T(kind: BeaconStateFork.Phase0, phase0Data: state)
|
||||
template init*(T: type ForkedBeaconState, state: altair.BeaconState): T =
|
||||
T(kind: BeaconStateFork.Altair, altairData: state)
|
||||
template init*(T: type ForkedBeaconState, state: merge.BeaconState): T =
|
||||
T(kind: BeaconStateFork.Merge, mergeData: state)
|
||||
template init*(T: type ForkedBeaconState, state: ForkedHashedBeaconState): T =
|
||||
case state.kind
|
||||
of BeaconStateFork.Phase0:
|
||||
T(kind: BeaconStateFork.Phase0,
|
||||
phase0Data: state.phase0Data.data)
|
||||
of BeaconStateFork.Altair:
|
||||
T(kind: BeaconStateFork.Altair,
|
||||
altairData: state.altairData.data)
|
||||
of BeaconStateFork.Merge:
|
||||
T(kind: BeaconStateFork.Merge,
|
||||
mergeData: state.mergeData.data)
|
||||
|
||||
template init*(T: type ForkedSignedBeaconBlock, forked: ForkedBeaconBlock,
|
||||
blockRoot: Eth2Digest, signature: ValidatorSig): T =
|
||||
case forked.kind
|
||||
of BeaconBlockFork.Phase0:
|
||||
T(kind: BeaconBlockFork.Phase0,
|
||||
phase0Data: phase0.SignedBeaconBlock(message: forked.phase0Data,
|
||||
root: blockRoot,
|
||||
signature: signature))
|
||||
root: blockRoot,
|
||||
signature: signature))
|
||||
of BeaconBlockFork.Altair:
|
||||
T(kind: BeaconBlockFork.Altair,
|
||||
altairData: altair.SignedBeaconBlock(message: forked.altairData,
|
||||
root: blockRoot,
|
||||
signature: signature))
|
||||
root: blockRoot,
|
||||
signature: signature))
|
||||
of BeaconBlockFork.Merge:
|
||||
T(kind: BeaconBlockFork.Merge,
|
||||
mergeData: merge.SignedBeaconBlock(message: forked.mergeData,
|
||||
|
@ -146,13 +185,21 @@ template init*(T: type ForkedTrustedSignedBeaconBlock, blck: altair.TrustedSigne
|
|||
template init*(T: type ForkedTrustedSignedBeaconBlock, blck: merge.TrustedSignedBeaconBlock): T =
|
||||
T(kind: BeaconBlockFork.Merge, mergeData: blck)
|
||||
|
||||
template toFork*[T: phase0.TrustedSignedBeaconBlock](
|
||||
t: type T): BeaconBlockFork =
|
||||
BeaconBlockFork.Phase0
|
||||
template toFork*[T: altair.TrustedSignedBeaconBlock](
|
||||
t: type T): BeaconBlockFork =
|
||||
BeaconBlockFork.Altair
|
||||
template toFork*[T: merge.TrustedSignedBeaconBlock](
|
||||
t: type T): BeaconBlockFork =
|
||||
BeaconBlockFork.Merge
|
||||
|
||||
template init*(T: type ForkedEpochInfo, info: phase0.EpochInfo): T =
|
||||
T(kind: EpochInfoFork.Phase0, phase0Data: info)
|
||||
template init*(T: type ForkedEpochInfo, info: altair.EpochInfo): T =
|
||||
T(kind: EpochInfoFork.Altair, altairData: info)
|
||||
|
||||
# State-related functionality based on ForkedHashedBeaconState instead of HashedBeaconState
|
||||
|
||||
template withState*(x: ForkedHashedBeaconState, body: untyped): untyped =
|
||||
case x.kind
|
||||
of BeaconStateFork.Merge:
|
||||
|
@ -190,7 +237,6 @@ template withEpochInfo*(
|
|||
template info: untyped {.inject.} = x.altairData
|
||||
body
|
||||
|
||||
# Dispatch functions
|
||||
func assign*(tgt: var ForkedHashedBeaconState, src: ForkedHashedBeaconState) =
|
||||
if tgt.kind == src.kind:
|
||||
case tgt.kind
|
||||
|
@ -222,93 +268,6 @@ func getStateRoot*(x: ForkedHashedBeaconState): Eth2Digest =
|
|||
func setStateRoot*(x: var ForkedHashedBeaconState, root: Eth2Digest) =
|
||||
withState(x): state.root = root
|
||||
|
||||
func hash_tree_root*(x: ForkedHashedBeaconState): Eth2Digest =
|
||||
# This is a bit of a hack because we drill into data here, unlike other places
|
||||
withState(x): hash_tree_root(state.data)
|
||||
|
||||
func get_active_validator_indices_len*(
|
||||
state: ForkedHashedBeaconState; epoch: Epoch): uint64 =
|
||||
withState(state):
|
||||
get_active_validator_indices_len(state.data, epoch)
|
||||
|
||||
func get_beacon_committee*(
|
||||
state: ForkedHashedBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): seq[ValidatorIndex] =
|
||||
# This one is used by tests/, ncli/, and a couple of places in RPC
|
||||
# TODO use the iterator version alone, to remove the risk of using
|
||||
# diverging get_beacon_committee() in tests and beacon_chain/ by a
|
||||
# wrapper approach (e.g., toSeq). This is a perf tradeoff for test
|
||||
# correctness/consistency.
|
||||
withState(state):
|
||||
get_beacon_committee(state.data, slot, index, cache)
|
||||
|
||||
func get_beacon_committee_len*(
|
||||
state: ForkedHashedBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): uint64 =
|
||||
# This one is used by tests
|
||||
withState(state):
|
||||
get_beacon_committee_len(state.data, slot, index, cache)
|
||||
|
||||
func get_committee_count_per_slot*(state: ForkedHashedBeaconState,
|
||||
epoch: Epoch,
|
||||
cache: var StateCache): uint64 =
|
||||
## Return the number of committees at ``epoch``.
|
||||
withState(state):
|
||||
get_committee_count_per_slot(state.data, epoch, cache)
|
||||
|
||||
func get_beacon_proposer_index*(state: ForkedHashedBeaconState,
|
||||
cache: var StateCache, slot: Slot):
|
||||
Option[ValidatorIndex] =
|
||||
withState(state):
|
||||
get_beacon_proposer_index(state.data, cache, slot)
|
||||
|
||||
func get_shuffled_active_validator_indices*(
|
||||
cache: var StateCache, state: ForkedHashedBeaconState, epoch: Epoch):
|
||||
seq[ValidatorIndex] =
|
||||
withState(state):
|
||||
cache.get_shuffled_active_validator_indices(state.data, epoch)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_block_root_at_slot
|
||||
func get_block_root_at_slot*(state: ForkedHashedBeaconState,
|
||||
slot: Slot): Eth2Digest =
|
||||
## Return the block root at a recent ``slot``.
|
||||
withState(state):
|
||||
get_block_root_at_slot(state.data, slot)
|
||||
|
||||
proc get_attesting_indices*(state: ForkedHashedBeaconState;
|
||||
data: AttestationData;
|
||||
bits: CommitteeValidatorsBits;
|
||||
cache: var StateCache): seq[ValidatorIndex] =
|
||||
# TODO when https://github.com/nim-lang/Nim/issues/18188 fixed, use an
|
||||
# iterator
|
||||
|
||||
var idxBuf: seq[ValidatorIndex]
|
||||
withState(state):
|
||||
for vidx in state.data.get_attesting_indices(data, bits, cache):
|
||||
idxBuf.add vidx
|
||||
idxBuf
|
||||
|
||||
proc check_attester_slashing*(
|
||||
state: var ForkedHashedBeaconState; attester_slashing: SomeAttesterSlashing;
|
||||
flags: UpdateFlags): Result[seq[ValidatorIndex], cstring] =
|
||||
withState(state):
|
||||
check_attester_slashing(state.data, attester_slashing, flags)
|
||||
|
||||
proc check_proposer_slashing*(
|
||||
state: var ForkedHashedBeaconState; proposer_slashing: SomeProposerSlashing;
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
withState(state):
|
||||
check_proposer_slashing(state.data, proposer_slashing, flags)
|
||||
|
||||
proc check_voluntary_exit*(
|
||||
cfg: RuntimeConfig, state: ForkedHashedBeaconState;
|
||||
signed_voluntary_exit: SomeSignedVoluntaryExit;
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
withState(state):
|
||||
check_voluntary_exit(cfg, state.data, signed_voluntary_exit, flags)
|
||||
|
||||
# Derived utilities
|
||||
|
||||
func stateForkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): BeaconStateFork =
|
||||
## Return the current fork for the given epoch.
|
||||
static:
|
||||
|
@ -326,55 +285,9 @@ func blockForkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): BeaconBlockFork =
|
|||
elif epoch >= cfg.ALTAIR_FORK_EPOCH: BeaconBlockFork.Altair
|
||||
else: BeaconBlockFork.Phase0
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_current_epoch
|
||||
func get_current_epoch*(x: ForkedHashedBeaconState): Epoch =
|
||||
## Return the current epoch.
|
||||
withState(x): state.data.slot.epoch
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_previous_epoch
|
||||
func get_previous_epoch*(stateData: ForkedHashedBeaconState): Epoch =
|
||||
## Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
|
||||
let current_epoch = get_current_epoch(stateData)
|
||||
if current_epoch == GENESIS_EPOCH:
|
||||
GENESIS_EPOCH
|
||||
else:
|
||||
current_epoch - 1
|
||||
|
||||
func init*(T: type ForkDigests,
|
||||
cfg: RuntimeConfig,
|
||||
genesisValidatorsRoot: Eth2Digest): T =
|
||||
T(
|
||||
phase0:
|
||||
compute_fork_digest(cfg.GENESIS_FORK_VERSION, genesisValidatorsRoot),
|
||||
altair:
|
||||
compute_fork_digest(cfg.ALTAIR_FORK_VERSION, genesisValidatorsRoot),
|
||||
merge:
|
||||
compute_fork_digest(cfg.MERGE_FORK_VERSION, genesisValidatorsRoot),
|
||||
)
|
||||
|
||||
template asSigned*(x: phase0.TrustedSignedBeaconBlock or phase0.SigVerifiedBeaconBlock):
|
||||
phase0.SignedBeaconBlock =
|
||||
isomorphicCast[phase0.SignedBeaconBlock](x)
|
||||
|
||||
template asSigned*(x: altair.TrustedSignedBeaconBlock or altair.SigVerifiedBeaconBlock):
|
||||
altair.SignedBeaconBlock =
|
||||
isomorphicCast[altair.SignedBeaconBlock](x)
|
||||
|
||||
template asSigned*(x: ForkedTrustedSignedBeaconBlock): ForkedSignedBeaconBlock =
|
||||
isomorphicCast[ForkedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(x: phase0.SignedBeaconBlock or phase0.SigVerifiedBeaconBlock):
|
||||
phase0.TrustedSignedBeaconBlock =
|
||||
isomorphicCast[phase0.TrustedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(x: altair.SignedBeaconBlock or altair.SigVerifiedBeaconBlock):
|
||||
altair.TrustedSignedBeaconBlock =
|
||||
isomorphicCast[altair.TrustedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(x: merge.SignedBeaconBlock or merge.SigVerifiedBeaconBlock):
|
||||
merge.TrustedSignedBeaconBlock =
|
||||
isomorphicCast[merge.TrustedSignedBeaconBlock](x)
|
||||
|
||||
template asTrusted*(x: ForkedSignedBeaconBlock): ForkedTrustedSignedBeaconBlock =
|
||||
isomorphicCast[ForkedTrustedSignedBeaconBlock](x)
|
||||
|
||||
|
@ -453,6 +366,26 @@ template withStateAndBlck*(
|
|||
template blck: untyped {.inject.} = b.phase0Data
|
||||
body
|
||||
|
||||
func genesisFork*(cfg: RuntimeConfig): Fork =
|
||||
Fork(
|
||||
previous_version: cfg.GENESIS_FORK_VERSION,
|
||||
current_version: cfg.GENESIS_FORK_VERSION,
|
||||
epoch: GENESIS_EPOCH)
|
||||
|
||||
func altairFork*(cfg: RuntimeConfig): Fork =
|
||||
Fork(
|
||||
previous_version: cfg.GENESIS_FORK_VERSION,
|
||||
current_version: cfg.ALTAIR_FORK_VERSION,
|
||||
epoch: cfg.ALTAIR_FORK_EPOCH)
|
||||
|
||||
func mergeFork*(cfg: RuntimeConfig): Fork =
|
||||
# TODO in theory, the altair + merge forks could be in same epoch, so the
|
||||
# previous fork version would be the GENESIS_FORK_VERSION
|
||||
Fork(
|
||||
previous_version: cfg.ALTAIR_FORK_VERSION,
|
||||
current_version: cfg.MERGE_FORK_VERSION,
|
||||
epoch: cfg.MERGE_FORK_EPOCH)
|
||||
|
||||
proc forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork =
|
||||
case cfg.stateForkAtEpoch(epoch)
|
||||
of BeaconStateFork.Merge: cfg.mergeFork
|
||||
|
@ -478,3 +411,99 @@ func getForkSchedule*(cfg: RuntimeConfig): array[2, Fork] =
|
|||
##
|
||||
## NOTE: Update this procedure when new fork will be scheduled.
|
||||
[cfg.genesisFork(), cfg.altairFork()]
|
||||
|
||||
func readSszForkedHashedBeaconState*(
|
||||
data: openArray[byte], likelyFork: BeaconStateFork):
|
||||
ForkedHashedBeaconState {.raises: [Defect, SszError].} =
|
||||
## Helper to read a state from bytes when it's not certain what kind of state
|
||||
## it is - this happens for example when loading an SSZ state from command
|
||||
## line - we'll use wall time to "guess" which state to start with
|
||||
# careful - `result` is used, RVO didn't seem to work without
|
||||
result = ForkedHashedBeaconState(kind: likelyFork)
|
||||
var tried: set[BeaconStateFork]
|
||||
|
||||
template readFork() =
|
||||
withState(result):
|
||||
try:
|
||||
readSszBytes(data, state.data)
|
||||
state.root = hash_tree_root(state.data)
|
||||
return result
|
||||
except SszError as exc:
|
||||
tried.incl result.kind
|
||||
|
||||
readFork()
|
||||
|
||||
for fork in BeaconStateFork:
|
||||
if fork in tried: continue
|
||||
result = ForkedHashedBeaconState(kind: fork)
|
||||
readFork()
|
||||
|
||||
raise (ref SszError)(msg: "Unable to match data to any known fork")
|
||||
|
||||
func readSszForkedTrustedSignedBeaconBlock*(
|
||||
data: openArray[byte], likelyFork: BeaconBlockFork):
|
||||
ForkedTrustedSignedBeaconBlock {.raises: [Defect, SszError].} =
|
||||
## Helper to read a state from bytes when it's not certain what kind of state
|
||||
## it is - this happens for example when loading an SSZ state from command
|
||||
## line - we'll use wall time to "guess" which state to start with
|
||||
|
||||
var
|
||||
res = ForkedTrustedSignedBeaconBlock(kind: likelyFork)
|
||||
tried: set[BeaconBlockFork]
|
||||
|
||||
template readFork() =
|
||||
withBlck(res):
|
||||
try:
|
||||
readSszBytes(data, blck)
|
||||
return res
|
||||
except SszError as exc:
|
||||
tried.incl res.kind
|
||||
|
||||
readFork()
|
||||
|
||||
for fork in BeaconBlockFork:
|
||||
if fork in tried: continue
|
||||
res = ForkedTrustedSignedBeaconBlock(kind: fork)
|
||||
readFork()
|
||||
raise (ref SszError)(msg: "Unable to match data to any known fork")
|
||||
|
||||
func toBeaconBlockFork*(fork: BeaconStateFork): BeaconBlockFork =
|
||||
case fork
|
||||
of BeaconStateFork.Phase0: BeaconBlockFork.Phase0
|
||||
of BeaconStateFork.Altair: BeaconBlockFork.Altair
|
||||
of BeaconStateFork.Merge: BeaconBlockFork.Merge
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_fork_data_root
|
||||
func compute_fork_data_root*(current_version: Version,
|
||||
genesis_validators_root: Eth2Digest): Eth2Digest =
|
||||
## Return the 32-byte fork data root for the ``current_version`` and
|
||||
## ``genesis_validators_root``.
|
||||
## This is used primarily in signature domains to avoid collisions across
|
||||
## forks/chains.
|
||||
hash_tree_root(ForkData(
|
||||
current_version: current_version,
|
||||
genesis_validators_root: genesis_validators_root
|
||||
))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#compute_fork_digest
|
||||
func compute_fork_digest*(current_version: Version,
|
||||
genesis_validators_root: Eth2Digest): ForkDigest =
|
||||
## Return the 4-byte fork digest for the ``current_version`` and
|
||||
## ``genesis_validators_root``.
|
||||
## This is a digest primarily used for domain separation on the p2p layer.
|
||||
## 4-bytes suffices for practical separation of forks/chains.
|
||||
array[4, byte](result)[0..3] =
|
||||
compute_fork_data_root(
|
||||
current_version, genesis_validators_root).data.toOpenArray(0, 3)
|
||||
|
||||
func init*(T: type ForkDigests,
|
||||
cfg: RuntimeConfig,
|
||||
genesisValidatorsRoot: Eth2Digest): T =
|
||||
T(
|
||||
phase0:
|
||||
compute_fork_digest(cfg.GENESIS_FORK_VERSION, genesisValidatorsRoot),
|
||||
altair:
|
||||
compute_fork_digest(cfg.ALTAIR_FORK_VERSION, genesisValidatorsRoot),
|
||||
merge:
|
||||
compute_fork_digest(cfg.MERGE_FORK_VERSION, genesisValidatorsRoot),
|
||||
)
|
||||
|
|
|
@ -17,12 +17,12 @@ import
|
|||
chronicles,
|
||||
# Internal
|
||||
./datatypes/[phase0, altair, merge],
|
||||
./eth2_merkleization, ./ssz_codec
|
||||
"."/[eth2_merkleization, forks, ssz_codec]
|
||||
|
||||
# TODO although eth2_merkleization already exports ssz_codec, *sometimes* code
|
||||
# fails to compile if the export is not done here also
|
||||
export
|
||||
phase0, altair, eth2_merkleization, ssz_codec
|
||||
forks, eth2_merkleization, ssz_codec
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#integer_squareroot
|
||||
func integer_squareroot*(n: SomeInteger): SomeInteger =
|
||||
|
@ -370,13 +370,13 @@ func is_active_validator*(validator: Validator, epoch: Epoch): bool =
|
|||
validator.activation_epoch <= epoch and epoch < validator.exit_epoch
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_active_validator_indices
|
||||
iterator get_active_validator_indices*(state: SomeBeaconState, epoch: Epoch):
|
||||
iterator get_active_validator_indices*(state: ForkyBeaconState, epoch: Epoch):
|
||||
ValidatorIndex =
|
||||
for idx in 0..<state.validators.len:
|
||||
if is_active_validator(state.validators[idx], epoch):
|
||||
yield idx.ValidatorIndex
|
||||
|
||||
func get_active_validator_indices*(state: SomeBeaconState, epoch: Epoch):
|
||||
func get_active_validator_indices*(state: ForkyBeaconState, epoch: Epoch):
|
||||
seq[ValidatorIndex] =
|
||||
## Return the sequence of active validator indices at ``epoch``.
|
||||
var res = newSeqOfCap[ValidatorIndex](state.validators.len)
|
||||
|
@ -384,20 +384,30 @@ func get_active_validator_indices*(state: SomeBeaconState, epoch: Epoch):
|
|||
res.add idx.ValidatorIndex
|
||||
res
|
||||
|
||||
func get_active_validator_indices_len*(state: SomeBeaconState, epoch: Epoch):
|
||||
func get_active_validator_indices_len*(state: ForkyBeaconState, epoch: Epoch):
|
||||
uint64 =
|
||||
for idx in 0..<state.validators.len:
|
||||
if is_active_validator(state.validators[idx], epoch):
|
||||
inc result
|
||||
|
||||
func get_active_validator_indices_len*(
|
||||
state: ForkedHashedBeaconState; epoch: Epoch): uint64 =
|
||||
withState(state):
|
||||
get_active_validator_indices_len(state.data, epoch)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_current_epoch
|
||||
func get_current_epoch*(state: SomeBeaconState): Epoch =
|
||||
func get_current_epoch*(state: ForkyBeaconState): Epoch =
|
||||
## Return the current epoch.
|
||||
doAssert state.slot >= GENESIS_SLOT, $state.slot
|
||||
compute_epoch_at_slot(state.slot)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_current_epoch
|
||||
func get_current_epoch*(state: ForkedHashedBeaconState): Epoch =
|
||||
## Return the current epoch.
|
||||
withState(state): state.data.slot.epoch
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_randao_mix
|
||||
func get_randao_mix*(state: SomeBeaconState, epoch: Epoch): Eth2Digest =
|
||||
func get_randao_mix*(state: ForkyBeaconState, epoch: Epoch): Eth2Digest =
|
||||
## Returns the randao mix at a recent ``epoch``.
|
||||
state.randao_mixes[epoch mod EPOCHS_PER_HISTORICAL_VECTOR]
|
||||
|
||||
|
@ -421,29 +431,6 @@ func uint_to_bytes4*(x: uint64): array[4, byte] =
|
|||
result[2] = ((x shr 16) and 0xff).byte
|
||||
result[3] = ((x shr 24) and 0xff).byte
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#compute_fork_data_root
|
||||
func compute_fork_data_root(current_version: Version,
|
||||
genesis_validators_root: Eth2Digest): Eth2Digest =
|
||||
## Return the 32-byte fork data root for the ``current_version`` and
|
||||
## ``genesis_validators_root``.
|
||||
## This is used primarily in signature domains to avoid collisions across
|
||||
## forks/chains.
|
||||
hash_tree_root(ForkData(
|
||||
current_version: current_version,
|
||||
genesis_validators_root: genesis_validators_root
|
||||
))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#compute_fork_digest
|
||||
func compute_fork_digest*(current_version: Version,
|
||||
genesis_validators_root: Eth2Digest): ForkDigest =
|
||||
## Return the 4-byte fork digest for the ``current_version`` and
|
||||
## ``genesis_validators_root``.
|
||||
## This is a digest primarily used for domain separation on the p2p layer.
|
||||
## 4-bytes suffices for practical separation of forks/chains.
|
||||
array[4, byte](result)[0..3] =
|
||||
compute_fork_data_root(
|
||||
current_version, genesis_validators_root).data.toOpenArray(0, 3)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#compute_domain
|
||||
func compute_domain*(
|
||||
domain_type: DomainType,
|
||||
|
@ -471,7 +458,7 @@ func get_domain*(
|
|||
compute_domain(domain_type, fork_version, genesis_validators_root)
|
||||
|
||||
func get_domain*(
|
||||
state: SomeBeaconState, domain_type: DomainType, epoch: Epoch): Eth2Domain =
|
||||
state: ForkyBeaconState, domain_type: DomainType, epoch: Epoch): Eth2Domain =
|
||||
## Return the signature domain (fork version concatenated with domain type)
|
||||
## of a message.
|
||||
get_domain(state.fork, domain_type, epoch, state.genesis_validators_root)
|
||||
|
@ -487,7 +474,7 @@ func compute_signing_root*(ssz_object: auto, domain: Eth2Domain): Eth2Digest =
|
|||
hash_tree_root(domain_wrapped_object)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_seed
|
||||
func get_seed*(state: SomeBeaconState, epoch: Epoch, domain_type: DomainType):
|
||||
func get_seed*(state: ForkyBeaconState, epoch: Epoch, domain_type: DomainType):
|
||||
Eth2Digest =
|
||||
## Return the seed at ``epoch``.
|
||||
|
||||
|
@ -539,7 +526,7 @@ func is_execution_enabled*(
|
|||
is_merge_block(state, body) or is_merge_complete(state)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0-beta.4/specs/merge/beacon-chain.md#compute_timestamp_at_slot
|
||||
func compute_timestamp_at_slot*(state: SomeBeaconState, slot: Slot): uint64 =
|
||||
func compute_timestamp_at_slot*(state: ForkyBeaconState, slot: Slot): uint64 =
|
||||
# Note: This function is unsafe with respect to overflows and underflows.
|
||||
let slots_since_genesis = slot - GENESIS_SLOT
|
||||
state.genesis_time + slots_since_genesis * SECONDS_PER_SLOT
|
||||
|
|
|
@ -250,8 +250,7 @@ proc addAggregateAndProofSignature*(
|
|||
|
||||
proc collectSignatureSets*(
|
||||
sigs: var seq[SignatureSet],
|
||||
signed_block: phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock,
|
||||
signed_block: ForkySignedBeaconBlock,
|
||||
validatorKeys: auto,
|
||||
state: ForkedHashedBeaconState,
|
||||
cache: var StateCache): Result[void, cstring] =
|
||||
|
|
|
@ -58,9 +58,9 @@ type Foo = phase0.SignedBeaconBlock | altair.SignedBeaconBlock | phase0.TrustedS
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||
proc verify_block_signature(
|
||||
#state: SomeBeaconState, signed_block: SomeSomeSignedBeaconBlock): bool {.nbench.} =
|
||||
state: SomeBeaconState, signed_block: Foo): bool {.nbench.} =
|
||||
#state: SomeBeaconState, signed_block: phase0.SomeSignedBeaconBlock | altair.SomeSignedBeaconBlock): bool {.nbench.} =
|
||||
#state: ForkyBeaconState, signed_block: SomeSomeSignedBeaconBlock): bool {.nbench.} =
|
||||
state: ForkyBeaconState, signed_block: Foo): bool {.nbench.} =
|
||||
#state: ForkyBeaconState, signed_block: phase0.SomeSignedBeaconBlock | altair.SomeSignedBeaconBlock): bool {.nbench.} =
|
||||
let
|
||||
proposer_index = signed_block.message.proposer_index
|
||||
if proposer_index >= state.validators.lenu64:
|
||||
|
@ -79,7 +79,7 @@ proc verify_block_signature(
|
|||
true
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||
proc verifyStateRoot(state: SomeBeaconState, blck: phase0.BeaconBlock or phase0.SigVerifiedBeaconBlock or altair.BeaconBlock or altair.SigVerifiedBeaconBlock or merge.BeaconBlock or merge.SigVerifiedBeaconBlock or merge.TrustedBeaconBlock): bool =
|
||||
proc verifyStateRoot(state: ForkyBeaconState, blck: phase0.BeaconBlock or phase0.SigVerifiedBeaconBlock or altair.BeaconBlock or altair.SigVerifiedBeaconBlock or merge.BeaconBlock or merge.SigVerifiedBeaconBlock or merge.TrustedBeaconBlock): bool =
|
||||
# This is inlined in state_transition(...) in spec.
|
||||
let state_root = hash_tree_root(state)
|
||||
if state_root != blck.state_root:
|
||||
|
@ -135,7 +135,7 @@ type
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||
func process_slot*(
|
||||
state: var SomeBeaconState, pre_state_root: Eth2Digest) {.nbench.} =
|
||||
state: var ForkyBeaconState, pre_state_root: Eth2Digest) {.nbench.} =
|
||||
# `process_slot` is the first stage of per-slot processing - it is run for
|
||||
# every slot, including epoch slots - it does not however update the slot
|
||||
# number! `pre_state_root` refers to the state root of the incoming
|
||||
|
@ -164,7 +164,7 @@ func clear_epoch_from_cache(cache: var StateCache, epoch: Epoch) =
|
|||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function
|
||||
proc advance_slot(
|
||||
cfg: RuntimeConfig,
|
||||
state: var SomeBeaconState, previous_slot_state_root: Eth2Digest,
|
||||
state: var ForkyBeaconState, previous_slot_state_root: Eth2Digest,
|
||||
flags: UpdateFlags, cache: var StateCache, info: var ForkyEpochInfo) {.nbench.} =
|
||||
# Do the per-slot and potentially the per-epoch processing, then bump the
|
||||
# slot number - we've now arrived at the slot state on top of which a block
|
||||
|
@ -249,7 +249,7 @@ proc process_slots*(
|
|||
|
||||
proc state_transition_block_aux(
|
||||
cfg: RuntimeConfig,
|
||||
state: var SomeHashedBeaconState,
|
||||
state: var ForkyHashedBeaconState,
|
||||
signedBlock: phase0.SignedBeaconBlock | phase0.SigVerifiedSignedBeaconBlock |
|
||||
phase0.TrustedSignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
altair.SigVerifiedSignedBeaconBlock | altair.TrustedSignedBeaconBlock |
|
||||
|
|
|
@ -31,7 +31,7 @@ export extras, phase0, altair
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#block-header
|
||||
func process_block_header*(
|
||||
state: var SomeBeaconState, blck: SomeSomeBeaconBlock, flags: UpdateFlags,
|
||||
state: var ForkyBeaconState, blck: SomeSomeBeaconBlock, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||
# Verify that the slots match
|
||||
if not (blck.slot == state.slot):
|
||||
|
@ -74,7 +74,7 @@ func `xor`[T: array](a, b: T): T =
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/phase0/beacon-chain.md#randao
|
||||
proc process_randao(
|
||||
state: var SomeBeaconState, body: SomeSomeBeaconBlockBody, flags: UpdateFlags,
|
||||
state: var ForkyBeaconState, body: SomeSomeBeaconBlockBody, flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||
let
|
||||
proposer_index = get_beacon_proposer_index(state, cache)
|
||||
|
@ -106,7 +106,7 @@ proc process_randao(
|
|||
ok()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#eth1-data
|
||||
func process_eth1_data(state: var SomeBeaconState, body: SomeSomeBeaconBlockBody): Result[void, cstring] {.nbench.}=
|
||||
func process_eth1_data(state: var ForkyBeaconState, body: SomeSomeBeaconBlockBody): Result[void, cstring] {.nbench.}=
|
||||
if not state.eth1_data_votes.add body.eth1_data:
|
||||
# Count is reset in process_final_updates, so this should never happen
|
||||
return err("process_eth1_data: no more room for eth1 data")
|
||||
|
@ -125,7 +125,7 @@ func is_slashable_validator(validator: Validator, epoch: Epoch): bool =
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#proposer-slashings
|
||||
proc check_proposer_slashing*(
|
||||
state: var SomeBeaconState, proposer_slashing: SomeProposerSlashing,
|
||||
state: var ForkyBeaconState, proposer_slashing: SomeProposerSlashing,
|
||||
flags: UpdateFlags):
|
||||
Result[void, cstring] {.nbench.} =
|
||||
|
||||
|
@ -166,9 +166,15 @@ proc check_proposer_slashing*(
|
|||
|
||||
ok()
|
||||
|
||||
proc check_proposer_slashing*(
|
||||
state: var ForkedHashedBeaconState; proposer_slashing: SomeProposerSlashing;
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
withState(state):
|
||||
check_proposer_slashing(state.data, proposer_slashing, flags)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#proposer-slashings
|
||||
proc process_proposer_slashing*(
|
||||
cfg: RuntimeConfig, state: var SomeBeaconState,
|
||||
cfg: RuntimeConfig, state: var ForkyBeaconState,
|
||||
proposer_slashing: SomeProposerSlashing, flags: UpdateFlags,
|
||||
cache: var StateCache):
|
||||
Result[void, cstring] {.nbench.} =
|
||||
|
@ -193,7 +199,7 @@ func is_slashable_attestation_data(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#attester-slashings
|
||||
proc check_attester_slashing*(
|
||||
state: var SomeBeaconState,
|
||||
state: var ForkyBeaconState,
|
||||
attester_slashing: SomeAttesterSlashing,
|
||||
flags: UpdateFlags
|
||||
): Result[seq[ValidatorIndex], cstring] {.nbench.} =
|
||||
|
@ -225,10 +231,16 @@ proc check_attester_slashing*(
|
|||
|
||||
ok slashed_indices
|
||||
|
||||
proc check_attester_slashing*(
|
||||
state: var ForkedHashedBeaconState; attester_slashing: SomeAttesterSlashing;
|
||||
flags: UpdateFlags): Result[seq[ValidatorIndex], cstring] =
|
||||
withState(state):
|
||||
check_attester_slashing(state.data, attester_slashing, flags)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#attester-slashings
|
||||
proc process_attester_slashing*(
|
||||
cfg: RuntimeConfig,
|
||||
state: var SomeBeaconState,
|
||||
state: var ForkyBeaconState,
|
||||
attester_slashing: SomeAttesterSlashing,
|
||||
flags: UpdateFlags,
|
||||
cache: var StateCache
|
||||
|
@ -245,7 +257,7 @@ proc process_attester_slashing*(
|
|||
ok()
|
||||
|
||||
proc process_deposit*(cfg: RuntimeConfig,
|
||||
state: var SomeBeaconState,
|
||||
state: var ForkyBeaconState,
|
||||
deposit: Deposit,
|
||||
flags: UpdateFlags): Result[void, cstring] {.nbench.} =
|
||||
## Process an Eth1 deposit, registering a validator or increasing its balance.
|
||||
|
@ -314,7 +326,7 @@ proc process_deposit*(cfg: RuntimeConfig,
|
|||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#voluntary-exits
|
||||
proc check_voluntary_exit*(
|
||||
cfg: RuntimeConfig,
|
||||
state: SomeBeaconState,
|
||||
state: ForkyBeaconState,
|
||||
signed_voluntary_exit: SomeSignedVoluntaryExit,
|
||||
flags: UpdateFlags): Result[void, cstring] {.nbench.} =
|
||||
|
||||
|
@ -364,10 +376,17 @@ proc check_voluntary_exit*(
|
|||
|
||||
ok()
|
||||
|
||||
proc check_voluntary_exit*(
|
||||
cfg: RuntimeConfig, state: ForkedHashedBeaconState;
|
||||
signed_voluntary_exit: SomeSignedVoluntaryExit;
|
||||
flags: UpdateFlags): Result[void, cstring] =
|
||||
withState(state):
|
||||
check_voluntary_exit(cfg, state.data, signed_voluntary_exit, flags)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#voluntary-exits
|
||||
proc process_voluntary_exit*(
|
||||
cfg: RuntimeConfig,
|
||||
state: var SomeBeaconState,
|
||||
state: var ForkyBeaconState,
|
||||
signed_voluntary_exit: SomeSignedVoluntaryExit,
|
||||
flags: UpdateFlags,
|
||||
cache: var StateCache): Result[void, cstring] {.nbench.} =
|
||||
|
@ -379,7 +398,7 @@ proc process_voluntary_exit*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#operations
|
||||
proc process_operations(cfg: RuntimeConfig,
|
||||
state: var SomeBeaconState,
|
||||
state: var ForkyBeaconState,
|
||||
body: SomeSomeBeaconBlockBody,
|
||||
base_reward_per_increment: Gwei,
|
||||
flags: UpdateFlags,
|
||||
|
|
|
@ -461,7 +461,7 @@ func get_proposer_reward(base_reward: Gwei): Gwei =
|
|||
func is_in_inactivity_leak(finality_delay: uint64): bool =
|
||||
finality_delay > MIN_EPOCHS_TO_INACTIVITY_PENALTY
|
||||
|
||||
func get_finality_delay(state: SomeBeaconState): uint64 =
|
||||
func get_finality_delay(state: ForkyBeaconState): uint64 =
|
||||
get_previous_epoch(state) - state.finalized_checkpoint.epoch
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#rewards-and-penalties-1
|
||||
|
@ -746,7 +746,7 @@ func process_rewards_and_penalties(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#registry-updates
|
||||
func process_registry_updates*(
|
||||
cfg: RuntimeConfig, state: var SomeBeaconState, cache: var StateCache) {.nbench.} =
|
||||
cfg: RuntimeConfig, state: var ForkyBeaconState, cache: var StateCache) {.nbench.} =
|
||||
## Process activation eligibility and ejections
|
||||
|
||||
# Make visible, e.g.,
|
||||
|
@ -796,7 +796,7 @@ func process_registry_updates*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#slashings
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/altair/beacon-chain.md#slashings
|
||||
func process_slashings*(state: var SomeBeaconState, total_balance: Gwei) {.nbench.} =
|
||||
func process_slashings*(state: var ForkyBeaconState, total_balance: Gwei) {.nbench.} =
|
||||
let
|
||||
epoch = get_current_epoch(state)
|
||||
multiplier =
|
||||
|
@ -824,7 +824,7 @@ func process_slashings*(state: var SomeBeaconState, total_balance: Gwei) {.nbenc
|
|||
decrease_balance(state, index.ValidatorIndex, penalty)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/34cea67b91/specs/phase0/beacon-chain.md#eth1-data-votes-updates
|
||||
func process_eth1_data_reset*(state: var SomeBeaconState) {.nbench.} =
|
||||
func process_eth1_data_reset*(state: var ForkyBeaconState) {.nbench.} =
|
||||
let next_epoch = get_current_epoch(state) + 1
|
||||
|
||||
# Reset eth1 data votes
|
||||
|
@ -832,7 +832,7 @@ func process_eth1_data_reset*(state: var SomeBeaconState) {.nbench.} =
|
|||
state.eth1_data_votes = default(type state.eth1_data_votes)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#effective-balances-updates
|
||||
func process_effective_balance_updates*(state: var SomeBeaconState) {.nbench.} =
|
||||
func process_effective_balance_updates*(state: var ForkyBeaconState) {.nbench.} =
|
||||
# Update effective balances with hysteresis
|
||||
for index in 0..<state.validators.len:
|
||||
let balance = state.balances.asSeq()[index]
|
||||
|
@ -851,14 +851,14 @@ func process_effective_balance_updates*(state: var SomeBeaconState) {.nbench.} =
|
|||
MAX_EFFECTIVE_BALANCE)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#slashings-balances-updates
|
||||
func process_slashings_reset*(state: var SomeBeaconState) {.nbench.} =
|
||||
func process_slashings_reset*(state: var ForkyBeaconState) {.nbench.} =
|
||||
let next_epoch = get_current_epoch(state) + 1
|
||||
|
||||
# Reset slashings
|
||||
state.slashings[int(next_epoch mod EPOCHS_PER_SLASHINGS_VECTOR)] = 0.Gwei
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#randao-mixes-updates
|
||||
func process_randao_mixes_reset*(state: var SomeBeaconState) {.nbench.} =
|
||||
func process_randao_mixes_reset*(state: var ForkyBeaconState) {.nbench.} =
|
||||
let
|
||||
current_epoch = get_current_epoch(state)
|
||||
next_epoch = current_epoch + 1
|
||||
|
@ -868,7 +868,7 @@ func process_randao_mixes_reset*(state: var SomeBeaconState) {.nbench.} =
|
|||
get_randao_mix(state, current_epoch)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#historical-roots-updates
|
||||
func process_historical_roots_update*(state: var SomeBeaconState) {.nbench.} =
|
||||
func process_historical_roots_update*(state: var ForkyBeaconState) {.nbench.} =
|
||||
## Set historical root accumulator
|
||||
let next_epoch = get_current_epoch(state) + 1
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ import
|
|||
./datatypes/[phase0, altair, merge],
|
||||
./helpers
|
||||
|
||||
export phase0, altair
|
||||
export helpers
|
||||
|
||||
const
|
||||
SEED_SIZE = sizeof(Eth2Digest)
|
||||
|
@ -126,7 +126,7 @@ func shuffle_list*(input: var seq[ValidatorIndex], seed: Eth2Digest) =
|
|||
shuffle
|
||||
|
||||
func get_shuffled_active_validator_indices*(
|
||||
state: SomeBeaconState, epoch: Epoch): seq[ValidatorIndex] =
|
||||
state: ForkyBeaconState, epoch: Epoch): seq[ValidatorIndex] =
|
||||
# Non-spec function, to cache a data structure from which one can cheaply
|
||||
# compute both get_active_validator_indexes() and get_beacon_committee().
|
||||
var active_validator_indices = get_active_validator_indices(state, epoch)
|
||||
|
@ -137,7 +137,7 @@ func get_shuffled_active_validator_indices*(
|
|||
active_validator_indices
|
||||
|
||||
func get_shuffled_active_validator_indices*(
|
||||
cache: var StateCache, state: SomeBeaconState, epoch: Epoch):
|
||||
cache: var StateCache, state: ForkyBeaconState, epoch: Epoch):
|
||||
var seq[ValidatorIndex] =
|
||||
# `cache` comes first because of nim's borrowing rules for the `var` return -
|
||||
# the `var` returns avoids copying the validator set.
|
||||
|
@ -147,8 +147,14 @@ func get_shuffled_active_validator_indices*(
|
|||
let indices = get_shuffled_active_validator_indices(state, epoch)
|
||||
return cache.shuffled_active_validator_indices.mgetOrPut(epoch, indices)
|
||||
|
||||
func get_shuffled_active_validator_indices*(
|
||||
cache: var StateCache, state: ForkedHashedBeaconState, epoch: Epoch):
|
||||
seq[ValidatorIndex] =
|
||||
withState(state):
|
||||
cache.get_shuffled_active_validator_indices(state.data, epoch)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_active_validator_indices
|
||||
func count_active_validators*(state: SomeBeaconState,
|
||||
func count_active_validators*(state: ForkyBeaconState,
|
||||
epoch: Epoch,
|
||||
cache: var StateCache): uint64 =
|
||||
cache.get_shuffled_active_validator_indices(state, epoch).lenu64
|
||||
|
@ -159,7 +165,7 @@ func get_committee_count_per_slot*(num_active_validators: uint64): uint64 =
|
|||
num_active_validators div SLOTS_PER_EPOCH div TARGET_COMMITTEE_SIZE,
|
||||
1'u64, MAX_COMMITTEES_PER_SLOT)
|
||||
|
||||
func get_committee_count_per_slot*(state: SomeBeaconState,
|
||||
func get_committee_count_per_slot*(state: ForkyBeaconState,
|
||||
epoch: Epoch,
|
||||
cache: var StateCache): uint64 =
|
||||
## Return the number of committees at ``slot``.
|
||||
|
@ -171,13 +177,19 @@ func get_committee_count_per_slot*(state: SomeBeaconState,
|
|||
# Otherwise, get_beacon_committee(...) cannot access some committees.
|
||||
doAssert (SLOTS_PER_EPOCH * MAX_COMMITTEES_PER_SLOT) >= uint64(result)
|
||||
|
||||
iterator committee_indices_per_slot*(state: SomeBeaconState,
|
||||
func get_committee_count_per_slot*(state: ForkedHashedBeaconState,
|
||||
epoch: Epoch,
|
||||
cache: var StateCache): uint64 =
|
||||
withState(state):
|
||||
get_committee_count_per_slot(state.data, epoch, cache)
|
||||
|
||||
iterator committee_indices_per_slot*(state: ForkyBeaconState,
|
||||
epoch: Epoch,
|
||||
cache: var StateCache): CommitteeIndex =
|
||||
for idx in 0'u64 ..< get_committee_count_per_slot(state, epoch, cache):
|
||||
yield CommitteeIndex.verifiedValue(idx)
|
||||
|
||||
func get_committee_count_per_slot*(state: SomeBeaconState,
|
||||
func get_committee_count_per_slot*(state: ForkyBeaconState,
|
||||
slot: Slot,
|
||||
cache: var StateCache): uint64 =
|
||||
get_committee_count_per_slot(state, slot.compute_epoch_at_slot, cache)
|
||||
|
@ -190,11 +202,16 @@ func get_previous_epoch*(current_epoch: Epoch): Epoch =
|
|||
else:
|
||||
current_epoch - 1
|
||||
|
||||
func get_previous_epoch*(state: SomeBeaconState): Epoch =
|
||||
func get_previous_epoch*(state: ForkyBeaconState): Epoch =
|
||||
## Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
|
||||
# Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
|
||||
get_previous_epoch(get_current_epoch(state))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_previous_epoch
|
||||
func get_previous_epoch*(state: ForkedHashedBeaconState): Epoch =
|
||||
## Return the previous epoch (unless the current epoch is ``GENESIS_EPOCH``).
|
||||
get_previous_epoch(get_current_epoch(state))
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#compute_committee
|
||||
func compute_committee_slice*(
|
||||
active_validators, index, count: uint64): Slice[int] =
|
||||
|
@ -241,7 +258,7 @@ func compute_committee_len*(
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_beacon_committee
|
||||
iterator get_beacon_committee*(
|
||||
state: SomeBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
state: ForkyBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): ValidatorIndex =
|
||||
## Return the beacon committee at ``slot`` for ``index``.
|
||||
let
|
||||
|
@ -255,7 +272,7 @@ iterator get_beacon_committee*(
|
|||
): yield idx
|
||||
|
||||
func get_beacon_committee*(
|
||||
state: SomeBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
state: ForkyBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): seq[ValidatorIndex] =
|
||||
## Return the beacon committee at ``slot`` for ``index``.
|
||||
let
|
||||
|
@ -268,9 +285,20 @@ func get_beacon_committee*(
|
|||
committees_per_slot * SLOTS_PER_EPOCH
|
||||
)
|
||||
|
||||
func get_beacon_committee*(
|
||||
state: ForkedHashedBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): seq[ValidatorIndex] =
|
||||
# This one is used by tests/, ncli/, and a couple of places in RPC
|
||||
# TODO use the iterator version alone, to remove the risk of using
|
||||
# diverging get_beacon_committee() in tests and beacon_chain/ by a
|
||||
# wrapper approach (e.g., toSeq). This is a perf tradeoff for test
|
||||
# correctness/consistency.
|
||||
withState(state):
|
||||
get_beacon_committee(state.data, slot, index, cache)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/phase0/beacon-chain.md#get_beacon_committee
|
||||
func get_beacon_committee_len*(
|
||||
state: SomeBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
state: ForkyBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): uint64 =
|
||||
# Return the number of members in the beacon committee at ``slot`` for ``index``.
|
||||
let
|
||||
|
@ -284,6 +312,13 @@ func get_beacon_committee_len*(
|
|||
committees_per_slot * SLOTS_PER_EPOCH
|
||||
)
|
||||
|
||||
func get_beacon_committee_len*(
|
||||
state: ForkedHashedBeaconState, slot: Slot, index: CommitteeIndex,
|
||||
cache: var StateCache): uint64 =
|
||||
# This one is used by tests
|
||||
withState(state):
|
||||
get_beacon_committee_len(state.data, slot, index, cache)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#compute_shuffled_index
|
||||
func compute_shuffled_index*(
|
||||
index: uint64, index_count: uint64, seed: Eth2Digest): uint64 =
|
||||
|
@ -320,7 +355,7 @@ func compute_shuffled_index*(
|
|||
cur_idx_permuted
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.0/specs/phase0/beacon-chain.md#compute_proposer_index
|
||||
func compute_proposer_index(state: SomeBeaconState,
|
||||
func compute_proposer_index(state: ForkyBeaconState,
|
||||
indices: seq[ValidatorIndex], seed: Eth2Digest): Option[ValidatorIndex] =
|
||||
## Return from ``indices`` a random index sampled by effective balance.
|
||||
const MAX_RANDOM_BYTE = 255
|
||||
|
@ -348,7 +383,7 @@ func compute_proposer_index(state: SomeBeaconState,
|
|||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_beacon_proposer_index
|
||||
func get_beacon_proposer_index*(
|
||||
state: SomeBeaconState, cache: var StateCache, slot: Slot):
|
||||
state: ForkyBeaconState, cache: var StateCache, slot: Slot):
|
||||
Option[ValidatorIndex] =
|
||||
cache.beacon_proposer_indices.withValue(slot, proposer) do:
|
||||
return proposer[]
|
||||
|
@ -380,10 +415,16 @@ func get_beacon_proposer_index*(
|
|||
return res
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/beacon-chain.md#get_beacon_proposer_index
|
||||
func get_beacon_proposer_index*(state: SomeBeaconState, cache: var StateCache):
|
||||
func get_beacon_proposer_index*(state: ForkyBeaconState, cache: var StateCache):
|
||||
Option[ValidatorIndex] =
|
||||
get_beacon_proposer_index(state, cache, state.slot)
|
||||
|
||||
func get_beacon_proposer_index*(state: ForkedHashedBeaconState,
|
||||
cache: var StateCache, slot: Slot):
|
||||
Option[ValidatorIndex] =
|
||||
withState(state):
|
||||
get_beacon_proposer_index(state.data, cache, slot)
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/specs/phase0/validator.md#aggregation-selection
|
||||
func is_aggregator*(committee_len: uint64, slot_signature: ValidatorSig): bool =
|
||||
let
|
||||
|
|
|
@ -10,10 +10,13 @@
|
|||
import
|
||||
std/[os, strformat],
|
||||
chronicles,
|
||||
./spec/[eth2_ssz_serialization, eth2_merkleization],
|
||||
./spec/[eth2_ssz_serialization, eth2_merkleization, forks],
|
||||
./spec/datatypes/[phase0, altair, merge],
|
||||
./consensus_object_pools/block_pools_types
|
||||
|
||||
export
|
||||
eth2_ssz_serialization, eth2_merkleization, forks, block_pools_types
|
||||
|
||||
# Dump errors are generally not fatal where used currently - the code calling
|
||||
# these functions, like most code, is not exception safe
|
||||
template logErrors(body: untyped) =
|
||||
|
@ -46,14 +49,14 @@ proc dump*(dir: string, v: merge.SignedBeaconBlock) =
|
|||
logErrors:
|
||||
SSZ.saveFile(dir / &"block-{v.message.slot}-{shortLog(v.root)}.ssz", v)
|
||||
|
||||
proc dump*(dir: string, v: SomeHashedBeaconState, blck: BlockRef) =
|
||||
proc dump*(dir: string, v: ForkyHashedBeaconState, blck: BlockRef) =
|
||||
mixin saveFile
|
||||
logErrors:
|
||||
SSZ.saveFile(
|
||||
dir / &"state-{v.data.slot}-{shortLog(blck.root)}-{shortLog(v.root)}.ssz",
|
||||
v.data)
|
||||
|
||||
proc dump*(dir: string, v: SomeHashedBeaconState) =
|
||||
proc dump*(dir: string, v: ForkyHashedBeaconState) =
|
||||
mixin saveFile
|
||||
logErrors:
|
||||
SSZ.saveFile(
|
||||
|
|
|
@ -152,7 +152,7 @@ proc runFullTransition*(dir, preState, blocksPrefix: string, blocksQty: int, ski
|
|||
phase0Data: phase0.HashedBeaconState(data: parseSSZ(prePath, phase0.BeaconState)),
|
||||
kind: BeaconStateFork.Phase0
|
||||
)
|
||||
setStateRoot(state[], hash_tree_root(state[]))
|
||||
setStateRoot(state[], hash_tree_root(state[].phase0Data.data))
|
||||
|
||||
for i in 0 ..< blocksQty:
|
||||
let blockPath = dir / blocksPrefix & $i & ".ssz"
|
||||
|
@ -177,7 +177,7 @@ proc runProcessSlots*(dir, preState: string, numSlots: uint64) =
|
|||
phase0Data: phase0.HashedBeaconState(
|
||||
data: parseSSZ(prePath, phase0.BeaconState)),
|
||||
kind: BeaconStateFork.Phase0)
|
||||
setStateRoot(state[], hash_tree_root(state[]))
|
||||
setStateRoot(state[], hash_tree_root(state[].phase0Data.data))
|
||||
|
||||
# Shouldn't necessarily assert, because nbench can run test suite
|
||||
discard process_slots(
|
||||
|
|
|
@ -89,7 +89,7 @@ proc doTransition(conf: NcliConf) =
|
|||
blckX = SSZ.loadFile(conf.blck, phase0.SignedBeaconBlock)
|
||||
flags = if not conf.verifyStateRoot: {skipStateRootValidation} else: {}
|
||||
|
||||
setStateRoot(stateY[], hash_tree_root(stateY[]))
|
||||
setStateRoot(stateY[], hash_tree_root(stateY[].phase0Data.data))
|
||||
|
||||
var
|
||||
cache = StateCache()
|
||||
|
@ -117,7 +117,7 @@ proc doSlots(conf: NcliConf) =
|
|||
kind: BeaconStateFork.Phase0
|
||||
)
|
||||
|
||||
setStateRoot(stateY[], hash_tree_root(stateY[]))
|
||||
setStateRoot(stateY[], hash_tree_root(stateY[].phase0Data.data))
|
||||
|
||||
var
|
||||
cache = StateCache()
|
||||
|
@ -147,7 +147,9 @@ proc doSSZ(conf: NcliConf) =
|
|||
if cmpIgnoreCase(ext, ".ssz") == 0:
|
||||
SSZ.loadFile(file, t)
|
||||
elif cmpIgnoreCase(ext, ".json") == 0:
|
||||
JSON.loadFile(file, t)
|
||||
# JSON.loadFile(file, t)
|
||||
echo "TODO needs porting to RestJson"
|
||||
quit 1
|
||||
else:
|
||||
echo "Unknown file type: ", ext
|
||||
quit 1
|
||||
|
|
|
@ -7,7 +7,7 @@ import
|
|||
blockchain_dag, forkedbeaconstate_dbhelpers],
|
||||
../beacon_chain/spec/datatypes/phase0,
|
||||
../beacon_chain/spec/[
|
||||
forks, helpers, state_transition, state_transition_epoch],
|
||||
beaconstate, helpers, state_transition, state_transition_epoch, validator],
|
||||
../beacon_chain/sszdump,
|
||||
../research/simutils, ./e2store
|
||||
|
||||
|
@ -183,7 +183,7 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
|
|||
|
||||
for b in 0..<blockRefs.len:
|
||||
withTimer(timers[tLoadBlock]):
|
||||
blocks.add db.getBlock(blockRefs[blockRefs.len - b - 1].root).get()
|
||||
blocks.add db.getPhase0Block(blockRefs[blockRefs.len - b - 1].root).get()
|
||||
|
||||
let state = newClone(dag.headState)
|
||||
|
||||
|
@ -233,7 +233,7 @@ proc cmdBench(conf: DbConf, cfg: RuntimeConfig) =
|
|||
doAssert dbBenchmark.getState(getStateRoot(state[].data), loadedState[], noRollback)
|
||||
|
||||
if getStateField(state[].data, slot).epoch mod 16 == 0:
|
||||
doAssert hash_tree_root(state[].data) == hash_tree_root(loadedState[])
|
||||
doAssert hash_tree_root(state[].data.phase0Data.data) == hash_tree_root(loadedState[])
|
||||
|
||||
printTimers(false, timers)
|
||||
|
||||
|
@ -259,7 +259,7 @@ proc cmdDumpBlock(conf: DbConf) =
|
|||
for blockRoot in conf.blockRootx:
|
||||
try:
|
||||
let root = Eth2Digest(data: hexToByteArray[32](blockRoot))
|
||||
if (let blck = db.getBlock(root); blck.isSome):
|
||||
if (let blck = db.getPhase0Block(root); blck.isSome):
|
||||
dump("./", blck.get())
|
||||
else:
|
||||
echo "Couldn't load ", root
|
||||
|
@ -276,20 +276,20 @@ proc copyPrunedDatabase(
|
|||
tailBlock = db.getTailBlock()
|
||||
|
||||
doAssert headBlock.isOk and tailBlock.isOk
|
||||
doAssert db.getBlock(headBlock.get).isOk
|
||||
doAssert db.getBlock(tailBlock.get).isOk
|
||||
doAssert db.getPhase0Block(headBlock.get).isOk
|
||||
doAssert db.getPhase0Block(tailBlock.get).isOk
|
||||
|
||||
var
|
||||
beaconState: ref phase0.BeaconState
|
||||
finalizedEpoch: Epoch # default value of 0 is conservative/safe
|
||||
prevBlockSlot = db.getBlock(db.getHeadBlock().get).get.message.slot
|
||||
prevBlockSlot = db.getPhase0Block(db.getHeadBlock().get).get.message.slot
|
||||
|
||||
beaconState = new phase0.BeaconState
|
||||
let headEpoch = db.getBlock(headBlock.get).get.message.slot.epoch
|
||||
let headEpoch = db.getPhase0Block(headBlock.get).get.message.slot.epoch
|
||||
|
||||
# Tail states are specially addressed; no stateroot intermediary
|
||||
if not db.getState(
|
||||
db.getBlock(tailBlock.get).get.message.state_root, beaconState[],
|
||||
db.getPhase0Block(tailBlock.get).get.message.state_root, beaconState[],
|
||||
noRollback):
|
||||
doAssert false, "could not load tail state"
|
||||
if not dry_run:
|
||||
|
@ -421,7 +421,7 @@ proc cmdExportEra(conf: DbConf, cfg: RuntimeConfig) =
|
|||
for i in 0..<ancestors.len():
|
||||
let
|
||||
ancestor = ancestors[ancestors.len - 1 - i]
|
||||
e2s.appendRecord(db.getBlock(ancestor.root).get()).get()
|
||||
e2s.appendRecord(db.getPhase0Block(ancestor.root).get()).get()
|
||||
|
||||
type
|
||||
# Validator performance metrics tool based on
|
||||
|
@ -525,7 +525,7 @@ proc cmdValidatorPerf(conf: DbConf, cfg: RuntimeConfig) =
|
|||
echo "TODO altair"
|
||||
|
||||
for bi in 0..<blockRefs.len:
|
||||
blck = db.getBlock(blockRefs[blockRefs.len - bi - 1].root).get()
|
||||
blck = db.getPhase0Block(blockRefs[blockRefs.len - bi - 1].root).get()
|
||||
while getStateField(state[].data, slot) < blck.message.slot:
|
||||
let
|
||||
nextSlot = getStateField(state[].data, slot) + 1
|
||||
|
@ -768,7 +768,7 @@ proc cmdValidatorDb(conf: DbConf, cfg: RuntimeConfig) =
|
|||
outDb.exec("COMMIT;").expect("DB")
|
||||
|
||||
for bi in 0..<blockRefs.len:
|
||||
blck = db.getBlock(blockRefs[blockRefs.len - bi - 1].root).get()
|
||||
blck = db.getPhase0Block(blockRefs[blockRefs.len - bi - 1].root).get()
|
||||
while getStateField(state[].data, slot) < blck.message.slot:
|
||||
let
|
||||
nextSlot = getStateField(state[].data, slot) + 1
|
||||
|
|
|
@ -9,7 +9,7 @@ proc print(t: auto, n: string, indent: int) =
|
|||
for n, p in t.fieldPairs:
|
||||
print(p, n, indent + 1)
|
||||
|
||||
print(BeaconState(), "state", 0)
|
||||
print((ref BeaconState)()[], "state", 0)
|
||||
|
||||
echo ""
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ cli do(slots = SLOTS_PER_EPOCH * 5,
|
|||
(hashedState, _) = loadGenesis(validators, validate)
|
||||
genesisBlock = get_initial_beacon_block(hashedState.data)
|
||||
state = (ref ForkedHashedBeaconState)(
|
||||
phase0Data: hashedState[], kind: BeaconStateFork.Phase0)
|
||||
kind: BeaconStateFork.Phase0, phase0Data: hashedState[])
|
||||
|
||||
echo "Starting simulation..."
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ proc mockAttestationData(
|
|||
|
||||
if slot == state.slot:
|
||||
let forkedState = (ref ForkedHashedBeaconState)(kind: BeaconStateFork.Phase0,
|
||||
phase0Data: phase0.HashedBeaconState(root: hash_tree_root(state), data: state))[]
|
||||
result.beacon_block_root = mockBlockForNextSlot(forkedState).phase0Data.message.parent_root
|
||||
phase0Data: phase0.HashedBeaconState(root: hash_tree_root(state), data: state))
|
||||
result.beacon_block_root = mockBlockForNextSlot(forkedState[]).phase0Data.message.parent_root
|
||||
else:
|
||||
result.beacon_block_root = get_block_root_at_slot(state, slot)
|
||||
|
||||
|
|
|
@ -17,10 +17,7 @@ import
|
|||
# ---------------------------------------------------------------
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/tests/core/pyspec/eth2spec/test/helpers/block.py#L26-L35
|
||||
func apply_randao_reveal(
|
||||
state: SomeBeaconState,
|
||||
blck: var (phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock)) =
|
||||
func apply_randao_reveal(state: ForkyBeaconState, blck: var ForkySignedBeaconBlock) =
|
||||
doAssert state.slot <= blck.message.slot
|
||||
let
|
||||
proposer_index = blck.message.proposer_index.ValidatorIndex
|
||||
|
@ -33,10 +30,7 @@ func apply_randao_reveal(
|
|||
privkey).toValidatorSig()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/tests/core/pyspec/eth2spec/test/helpers/block.py#L38-L54
|
||||
func sign_block(
|
||||
state: SomeBeaconState,
|
||||
blck: var (phase0.SignedBeaconBlock | altair.SignedBeaconBlock |
|
||||
merge.SignedBeaconBlock)) =
|
||||
func sign_block(state: ForkyBeaconState, blck: var ForkySignedBeaconBlock) =
|
||||
let
|
||||
proposer_index = blck.message.proposer_index.ValidatorIndex
|
||||
privkey = MockPrivKeys[proposer_index]
|
||||
|
@ -50,8 +44,7 @@ func sign_block(
|
|||
privkey).toValidatorSig()
|
||||
|
||||
# https://github.com/ethereum/consensus-specs/blob/v1.1.3/tests/core/pyspec/eth2spec/test/helpers/execution_payload.py#L1-L31
|
||||
func build_empty_execution_payload(
|
||||
state: merge.BeaconState): ExecutionPayload =
|
||||
func build_empty_execution_payload(state: merge.BeaconState): ExecutionPayload =
|
||||
## Assuming a pre-state of the same slot, build a valid ExecutionPayload
|
||||
## without any transactions.
|
||||
let
|
||||
|
|
|
@ -20,7 +20,7 @@ import
|
|||
../beacon_chain/consensus_object_pools/[
|
||||
block_quarantine, blockchain_dag, block_clearance, attestation_pool],
|
||||
../beacon_chain/spec/datatypes/phase0,
|
||||
../beacon_chain/spec/[forks, state_transition, helpers],
|
||||
../beacon_chain/spec/[helpers, state_transition, validator],
|
||||
# Test utilities
|
||||
./testutil, ./testdbutil, ./testblockutil
|
||||
|
||||
|
|
|
@ -32,14 +32,14 @@ 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):
|
||||
if db.getState(root, res[], noRollback):
|
||||
return res
|
||||
|
||||
proc getMergeStateRef(db: BeaconChainDB, root: Eth2Digest):
|
||||
merge.NilableBeaconStateRef =
|
||||
# load beaconstate the way the block pool does it - into an existing instance
|
||||
let res = (merge.BeaconStateRef)()
|
||||
if db.getMergeState(root, res[], noRollback):
|
||||
if db.getState(root, res[], noRollback):
|
||||
return res
|
||||
|
||||
func withDigest(blck: phase0.TrustedBeaconBlock):
|
||||
|
@ -88,7 +88,7 @@ suite "Beacon chain DB" & preset():
|
|||
db = BeaconChainDB.new("", inMemory = true)
|
||||
check:
|
||||
db.getPhase0StateRef(Eth2Digest()).isNil
|
||||
db.getBlock(Eth2Digest()).isNone
|
||||
db.getPhase0Block(Eth2Digest()).isNone
|
||||
|
||||
test "sanity check phase 0 blocks" & preset():
|
||||
var db = BeaconChainDB.new("", inMemory = true)
|
||||
|
@ -104,7 +104,7 @@ suite "Beacon chain DB" & preset():
|
|||
db.containsBlockPhase0(root)
|
||||
not db.containsBlockAltair(root)
|
||||
not db.containsBlockMerge(root)
|
||||
db.getBlock(root).get() == signedBlock
|
||||
db.getPhase0Block(root).get() == signedBlock
|
||||
|
||||
db.delBlock(root)
|
||||
check:
|
||||
|
@ -112,7 +112,7 @@ suite "Beacon chain DB" & preset():
|
|||
not db.containsBlockPhase0(root)
|
||||
not db.containsBlockAltair(root)
|
||||
not db.containsBlockMerge(root)
|
||||
db.getBlock(root).isErr()
|
||||
db.getPhase0Block(root).isErr()
|
||||
|
||||
db.putStateRoot(root, signedBlock.message.slot, root)
|
||||
var root2 = root
|
||||
|
@ -200,7 +200,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
for state in testStatesPhase0:
|
||||
db.putState(state[].phase0Data.data)
|
||||
let root = hash_tree_root(state[])
|
||||
let root = hash_tree_root(state[].phase0Data.data)
|
||||
|
||||
check:
|
||||
db.containsState(root)
|
||||
|
@ -218,7 +218,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
for state in testStatesAltair:
|
||||
db.putState(state[].altairData.data)
|
||||
let root = hash_tree_root(state[])
|
||||
let root = hash_tree_root(state[].altairData.data)
|
||||
|
||||
check:
|
||||
db.containsState(root)
|
||||
|
@ -236,7 +236,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
for state in testStatesMerge:
|
||||
db.putState(state[].mergeData.data)
|
||||
let root = hash_tree_root(state[])
|
||||
let root = hash_tree_root(state[].mergeData.data)
|
||||
|
||||
check:
|
||||
db.containsState(root)
|
||||
|
@ -255,7 +255,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
for state in testStatesPhase0:
|
||||
db.putState(state[].phase0Data.data)
|
||||
let root = hash_tree_root(state[])
|
||||
let root = hash_tree_root(state[].phase0Data.data)
|
||||
|
||||
check:
|
||||
db.getState(root, stateBuffer[], noRollback)
|
||||
|
@ -275,17 +275,17 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
for state in testStatesAltair:
|
||||
db.putState(state[].altairData.data)
|
||||
let root = hash_tree_root(state[])
|
||||
let root = hash_tree_root(state[].altairData.data)
|
||||
|
||||
check:
|
||||
db.getAltairState(root, stateBuffer[], noRollback)
|
||||
db.getState(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)
|
||||
not db.getState(root, stateBuffer[], noRollback)
|
||||
|
||||
db.close()
|
||||
|
||||
|
@ -295,17 +295,17 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
for state in testStatesMerge:
|
||||
db.putState(state[].mergeData.data)
|
||||
let root = hash_tree_root(state[])
|
||||
let root = hash_tree_root(state[].mergeData.data)
|
||||
|
||||
check:
|
||||
db.getMergeState(root, stateBuffer[], noRollback)
|
||||
db.getState(root, stateBuffer[], noRollback)
|
||||
db.containsState(root)
|
||||
hash_tree_root(stateBuffer[]) == root
|
||||
|
||||
db.delState(root)
|
||||
check:
|
||||
not db.containsState(root)
|
||||
not db.getMergeState(root, stateBuffer[], noRollback)
|
||||
not db.getState(root, stateBuffer[], noRollback)
|
||||
|
||||
db.close()
|
||||
|
||||
|
@ -350,7 +350,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
check:
|
||||
state[].altairData.data.slot == 10.Slot
|
||||
not db.getAltairState(root, state[].altairData.data, restore)
|
||||
not db.getState(root, state[].altairData.data, restore)
|
||||
|
||||
# assign() has switched the case object fork
|
||||
state[].kind == BeaconStateFork.Phase0
|
||||
|
@ -375,7 +375,7 @@ suite "Beacon chain DB" & preset():
|
|||
|
||||
check:
|
||||
state[].mergeData.data.slot == 10.Slot
|
||||
not db.getMergeState(root, state[].mergeData.data, restore)
|
||||
not db.getState(root, state[].mergeData.data, restore)
|
||||
|
||||
# assign() has switched the case object fork
|
||||
state[].kind == BeaconStateFork.Phase0
|
||||
|
|
|
@ -265,7 +265,7 @@ suite "Block pool processing" & preset():
|
|||
check:
|
||||
# ensure we loaded the correct head state
|
||||
dag2.head.root == b2.root
|
||||
hash_tree_root(dag2.headState.data) == b2.message.state_root
|
||||
getStateRoot(dag2.headState.data) == b2.message.state_root
|
||||
dag2.get(b1.root).isSome()
|
||||
dag2.get(b2.root).isSome()
|
||||
dag2.heads.len == 1
|
||||
|
@ -443,7 +443,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
dag2.head.root == dag.head.root
|
||||
dag2.finalizedHead.blck.root == dag.finalizedHead.blck.root
|
||||
dag2.finalizedHead.slot == dag.finalizedHead.slot
|
||||
hash_tree_root(dag2.headState.data) == hash_tree_root(dag.headState.data)
|
||||
getStateRoot(dag2.headState.data) == getStateRoot(dag.headState.data)
|
||||
|
||||
test "orphaned epoch block" & preset():
|
||||
var prestate = (ref ForkedHashedBeaconState)(kind: BeaconStateFork.Phase0)
|
||||
|
@ -516,8 +516,10 @@ suite "chain DAG finalization tests" & preset():
|
|||
assign(tmpStateData[], dag.headState)
|
||||
dag.updateStateData(tmpStateData[], cur.atSlot(cur.slot), false, cache)
|
||||
check:
|
||||
dag.get(cur).data.phase0Data.message.state_root == getStateRoot(tmpStateData[].data)
|
||||
getStateRoot(tmpStateData[].data) == hash_tree_root(tmpStateData[].data)
|
||||
dag.get(cur).data.phase0Data.message.state_root ==
|
||||
getStateRoot(tmpStateData[].data)
|
||||
getStateRoot(tmpStateData[].data) == hash_tree_root(
|
||||
tmpStateData[].data.phase0Data.data)
|
||||
cur = cur.parent
|
||||
|
||||
let
|
||||
|
@ -529,7 +531,7 @@ suite "chain DAG finalization tests" & preset():
|
|||
dag2.head.root == dag.head.root
|
||||
dag2.finalizedHead.blck.root == dag.finalizedHead.blck.root
|
||||
dag2.finalizedHead.slot == dag.finalizedHead.slot
|
||||
hash_tree_root(dag2.headState.data) == hash_tree_root(dag.headState.data)
|
||||
getStateRoot(dag2.headState.data) == getStateRoot(dag.headState.data)
|
||||
|
||||
suite "Old database versions" & preset():
|
||||
setup:
|
||||
|
@ -555,7 +557,7 @@ suite "Old database versions" & preset():
|
|||
db.putTailBlock(genBlock.root)
|
||||
db.putHeadBlock(genBlock.root)
|
||||
db.putStateRoot(genBlock.root, genState.slot, genBlock.message.state_root)
|
||||
db.putGenesisBlockRoot(genBlock.root)
|
||||
db.putGenesisBlock(genBlock.root)
|
||||
|
||||
var
|
||||
dag = init(ChainDAGRef, defaultRuntimeConfig, db, {})
|
||||
|
|
|
@ -22,7 +22,7 @@ import
|
|||
block_quarantine, blockchain_dag, block_clearance, attestation_pool,
|
||||
sync_committee_msg_pool],
|
||||
../beacon_chain/spec/datatypes/[phase0, altair],
|
||||
../beacon_chain/spec/[forks, state_transition, helpers, network],
|
||||
../beacon_chain/spec/[state_transition, helpers, network, validator],
|
||||
../beacon_chain/validators/validator_pool,
|
||||
# Test utilities
|
||||
./testutil, ./testdbutil, ./testblockutil
|
||||
|
@ -206,7 +206,7 @@ suite "Gossip validation - Extra": # Not based on preset config
|
|||
check: added.isOk()
|
||||
dag.updateHead(added[], quarantine)
|
||||
dag
|
||||
state = newClone(dag.headState.data.altairData)
|
||||
state = assignClone(dag.headState.data.altairData)
|
||||
|
||||
syncCommitteeIdx = 0.SyncSubcommitteeIndex
|
||||
syncCommittee = @(dag.syncCommitteeParticipants(state[].data.slot))
|
||||
|
|
|
@ -47,5 +47,5 @@ suite "state diff tests" & preset():
|
|||
getStateField(testStates[j][], validators).len - 1],
|
||||
it.getImmutableValidatorData),
|
||||
diff)
|
||||
check hash_tree_root(testStates[j][]) ==
|
||||
check hash_tree_root(testStates[j][].phase0Data.data) ==
|
||||
hash_tree_root(tmpStateApplyBase[])
|
||||
|
|
|
@ -10,7 +10,8 @@ import
|
|||
options, stew/endians2,
|
||||
../beacon_chain/validators/validator_pool,
|
||||
../beacon_chain/spec/datatypes/merge,
|
||||
../beacon_chain/spec/[helpers, keystore, signatures, state_transition, forks]
|
||||
../beacon_chain/spec/[
|
||||
beaconstate, helpers, keystore, signatures, state_transition, validator]
|
||||
|
||||
type
|
||||
MockPrivKeysT = object
|
||||
|
@ -289,15 +290,15 @@ iterator makeTestBlocks*(
|
|||
attested: bool,
|
||||
cfg = defaultRuntimeConfig): ForkedSignedBeaconBlock =
|
||||
var
|
||||
state = assignClone(state)[]
|
||||
state = assignClone(state)
|
||||
parent_root = parent_root
|
||||
for _ in 0..<blocks:
|
||||
let attestations = if attested:
|
||||
makeFullAttestations(state, parent_root, getStateField(state, slot), cache)
|
||||
makeFullAttestations(state[], parent_root, getStateField(state[], slot), cache)
|
||||
else:
|
||||
@[]
|
||||
|
||||
let blck = addTestBlock(
|
||||
state, parent_root, cache, attestations = attestations, cfg = cfg)
|
||||
state[], parent_root, cache, attestations = attestations, cfg = cfg)
|
||||
yield blck
|
||||
parent_root = blck.root
|
||||
|
|
Loading…
Reference in New Issue