abort compile when fork epoch is forgotten (#2939)
There are a few locations in the code that compare the current epoch to the various FORK_EPOCH constants and branch off into fork-specific code. When a new fork is introduced, it is sometimes forgotten to update all of those branch locations. This patch introduces a compile-time check that ensures that all branches need to be covered exhaustively. This is done by replacing if-elif structures with case expressions.
This commit is contained in:
parent
4a7a62c072
commit
2bbffbde10
|
@ -311,12 +311,10 @@ func contains*(dag: ChainDAGRef, root: Eth2Digest): bool =
|
|||
|
||||
proc containsBlock(
|
||||
cfg: RuntimeConfig, db: BeaconChainDB, blck: BlockRef): bool =
|
||||
if blck.slot.epoch < cfg.ALTAIR_FORK_EPOCH:
|
||||
db.containsBlockPhase0(blck.root)
|
||||
elif blck.slot.epoch < cfg.MERGE_FORK_EPOCH:
|
||||
db.containsBlockAltair(blck.root)
|
||||
else:
|
||||
db.containsBlockMerge(blck.root)
|
||||
case cfg.stateForkAtEpoch(blck.slot.epoch)
|
||||
of forkMerge: db.containsBlockMerge(blck.root)
|
||||
of forkAltair: db.containsBlockAltair(blck.root)
|
||||
of forkPhase0: db.containsBlockPhase0(blck.root)
|
||||
|
||||
func isStateCheckpoint(bs: BlockSlot): bool =
|
||||
## State checkpoints are the points in time for which we store full state
|
||||
|
@ -578,23 +576,24 @@ proc getState(
|
|||
func restore() =
|
||||
assign(v[], restoreAddr[].data)
|
||||
|
||||
if blck.slot.epoch < dag.cfg.ALTAIR_FORK_EPOCH:
|
||||
if state.data.beaconStateFork != forkPhase0:
|
||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkPhase0)[]
|
||||
case dag.cfg.stateForkAtEpoch(blck.slot.epoch)
|
||||
of forkMerge:
|
||||
if state.data.beaconStateFork != forkMerge:
|
||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkMerge)[]
|
||||
|
||||
if not dag.db.getState(stateRoot, state.data.hbsPhase0.data, restore):
|
||||
if not dag.db.getMergeState(stateRoot, state.data.hbsMerge.data, restore):
|
||||
return false
|
||||
elif blck.slot.epoch < dag.cfg.MERGE_FORK_EPOCH:
|
||||
of forkAltair:
|
||||
if state.data.beaconStateFork != forkAltair:
|
||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkAltair)[]
|
||||
|
||||
if not dag.db.getAltairState(stateRoot, state.data.hbsAltair.data, restore):
|
||||
return false
|
||||
else:
|
||||
if state.data.beaconStateFork != forkMerge:
|
||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkMerge)[]
|
||||
of forkPhase0:
|
||||
if state.data.beaconStateFork != forkPhase0:
|
||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkPhase0)[]
|
||||
|
||||
if not dag.db.getMergeState(stateRoot, state.data.hbsMerge.data, restore):
|
||||
if not dag.db.getState(stateRoot, state.data.hbsPhase0.data, restore):
|
||||
return false
|
||||
|
||||
state.blck = blck
|
||||
|
@ -613,12 +612,10 @@ template forkAtEpoch*(dag: ChainDAGRef, epoch: Epoch): Fork =
|
|||
forkAtEpoch(dag.cfg, epoch)
|
||||
|
||||
proc forkDigestAtEpoch*(dag: ChainDAGRef, epoch: Epoch): ForkDigest =
|
||||
if epoch < dag.cfg.ALTAIR_FORK_EPOCH:
|
||||
dag.forkDigests.phase0
|
||||
elif epoch < dag.cfg.MERGE_FORK_EPOCH:
|
||||
dag.forkDigests.altair
|
||||
else:
|
||||
dag.forkDigests.merge
|
||||
case dag.cfg.stateForkAtEpoch(epoch)
|
||||
of forkMerge: dag.forkDigests.merge
|
||||
of forkAltair: dag.forkDigests.altair
|
||||
of forkPhase0: dag.forkDigests.phase0
|
||||
|
||||
proc getState(dag: ChainDAGRef, state: var StateData, bs: BlockSlot): bool =
|
||||
## Load a state from the database given a block and a slot - this will first
|
||||
|
|
|
@ -2140,12 +2140,10 @@ func getRandomSubnetId*(node: Eth2Node): SubnetId =
|
|||
node.rng[].rand(ATTESTATION_SUBNET_COUNT - 1).SubnetId
|
||||
|
||||
func forkDigestAtEpoch(node: Eth2Node, epoch: Epoch): ForkDigest =
|
||||
if epoch < node.cfg.ALTAIR_FORK_EPOCH:
|
||||
node.forkDigests.phase0
|
||||
elif epoch < node.cfg.MERGE_FORK_EPOCH:
|
||||
node.forkDigests.altair
|
||||
else:
|
||||
node.forkDigests.merge
|
||||
case node.cfg.stateForkAtEpoch(epoch)
|
||||
of forkMerge: node.forkDigests.merge
|
||||
of forkAltair: node.forkDigests.altair
|
||||
of forkPhase0: node.forkDigests.phase0
|
||||
|
||||
proc getWallEpoch(node: Eth2Node): Epoch =
|
||||
node.getBeaconTime().slotOrZero.epoch
|
||||
|
|
|
@ -278,6 +278,17 @@ proc check_voluntary_exit*(
|
|||
|
||||
# Derived utilities
|
||||
|
||||
func stateForkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): BeaconStateFork =
|
||||
## Return the current fork for the given epoch.
|
||||
static:
|
||||
doAssert forkMerge > forkAltair
|
||||
doAssert forkAltair > forkPhase0
|
||||
doAssert GENESIS_EPOCH == 0
|
||||
|
||||
if epoch >= cfg.MERGE_FORK_EPOCH: forkMerge
|
||||
elif epoch >= cfg.ALTAIR_FORK_EPOCH: forkAltair
|
||||
else: forkPhase0
|
||||
|
||||
# https://github.com/ethereum/eth2.0-specs/blob/v1.0.1/specs/phase0/beacon-chain.md#get_current_epoch
|
||||
func get_current_epoch*(x: ForkedHashedBeaconState): Epoch =
|
||||
## Return the current epoch.
|
||||
|
@ -379,31 +390,22 @@ chronicles.formatIt ForkedSignedBeaconBlock: it.shortLog
|
|||
chronicles.formatIt ForkedTrustedSignedBeaconBlock: it.shortLog
|
||||
|
||||
proc forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork =
|
||||
doAssert cfg.ALTAIR_FORK_EPOCH <= cfg.MERGE_FORK_EPOCH
|
||||
if epoch < cfg.ALTAIR_FORK_EPOCH:
|
||||
genesisFork(cfg)
|
||||
elif epoch < cfg.MERGE_FORK_EPOCH:
|
||||
altairFork(cfg)
|
||||
else:
|
||||
mergeFork(cfg)
|
||||
case cfg.stateForkAtEpoch(epoch)
|
||||
of forkMerge: cfg.mergeFork
|
||||
of forkAltair: cfg.altairFork
|
||||
of forkPhase0: cfg.genesisFork
|
||||
|
||||
proc forkVersionAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Version =
|
||||
doAssert cfg.ALTAIR_FORK_EPOCH <= cfg.MERGE_FORK_EPOCH
|
||||
if epoch < cfg.ALTAIR_FORK_EPOCH:
|
||||
cfg.GENESIS_FORK_VERSION
|
||||
elif epoch < cfg.MERGE_FORK_EPOCH:
|
||||
cfg.ALTAIR_FORK_VERSION
|
||||
else:
|
||||
cfg.MERGE_FORK_VERSION
|
||||
case cfg.stateForkAtEpoch(epoch)
|
||||
of forkMerge: cfg.MERGE_FORK_VERSION
|
||||
of forkAltair: cfg.ALTAIR_FORK_VERSION
|
||||
of forkPhase0: cfg.GENESIS_FORK_VERSION
|
||||
|
||||
proc nextForkEpochAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Epoch =
|
||||
doAssert cfg.ALTAIR_FORK_EPOCH <= cfg.MERGE_FORK_EPOCH
|
||||
if epoch < cfg.ALTAIR_FORK_EPOCH:
|
||||
cfg.ALTAIR_FORK_EPOCH
|
||||
elif epoch < cfg.MERGE_FORK_EPOCH:
|
||||
cfg.MERGE_FORK_EPOCH
|
||||
else:
|
||||
FAR_FUTURE_EPOCH
|
||||
case cfg.stateForkAtEpoch(epoch)
|
||||
of forkMerge: FAR_FUTURE_EPOCH
|
||||
of forkAltair: cfg.MERGE_FORK_EPOCH
|
||||
of forkPhase0: cfg.ALTAIR_FORK_EPOCH
|
||||
|
||||
func getForkSchedule*(cfg: RuntimeConfig): array[2, Fork] =
|
||||
## This procedure returns list of known and/or scheduled forks.
|
||||
|
|
|
@ -391,12 +391,10 @@ cli do(slots = SLOTS_PER_EPOCH * 6,
|
|||
|
||||
if blockRatio > 0.0:
|
||||
withTimer(timers[t]):
|
||||
if slot.epoch < dag.cfg.ALTAIR_FORK_EPOCH:
|
||||
proposePhase0Block(slot)
|
||||
elif slot.epoch < dag.cfg.MERGE_FORK_EPOCH:
|
||||
proposeAltairBlock(slot)
|
||||
else:
|
||||
proposeMergeBlock(slot)
|
||||
case dag.cfg.stateForkAtEpoch(slot.epoch)
|
||||
of forkMerge: proposeMergeBlock(slot)
|
||||
of forkAltair: proposeAltairBlock(slot)
|
||||
of forkPhase0: proposePhase0Block(slot)
|
||||
if attesterRatio > 0.0:
|
||||
withTimer(timers[tAttest]):
|
||||
handleAttestations(slot)
|
||||
|
|
Loading…
Reference in New Issue