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(
|
proc containsBlock(
|
||||||
cfg: RuntimeConfig, db: BeaconChainDB, blck: BlockRef): bool =
|
cfg: RuntimeConfig, db: BeaconChainDB, blck: BlockRef): bool =
|
||||||
if blck.slot.epoch < cfg.ALTAIR_FORK_EPOCH:
|
case cfg.stateForkAtEpoch(blck.slot.epoch)
|
||||||
db.containsBlockPhase0(blck.root)
|
of forkMerge: db.containsBlockMerge(blck.root)
|
||||||
elif blck.slot.epoch < cfg.MERGE_FORK_EPOCH:
|
of forkAltair: db.containsBlockAltair(blck.root)
|
||||||
db.containsBlockAltair(blck.root)
|
of forkPhase0: db.containsBlockPhase0(blck.root)
|
||||||
else:
|
|
||||||
db.containsBlockMerge(blck.root)
|
|
||||||
|
|
||||||
func isStateCheckpoint(bs: BlockSlot): bool =
|
func isStateCheckpoint(bs: BlockSlot): bool =
|
||||||
## State checkpoints are the points in time for which we store full state
|
## State checkpoints are the points in time for which we store full state
|
||||||
|
@ -578,23 +576,24 @@ proc getState(
|
||||||
func restore() =
|
func restore() =
|
||||||
assign(v[], restoreAddr[].data)
|
assign(v[], restoreAddr[].data)
|
||||||
|
|
||||||
if blck.slot.epoch < dag.cfg.ALTAIR_FORK_EPOCH:
|
case dag.cfg.stateForkAtEpoch(blck.slot.epoch)
|
||||||
if state.data.beaconStateFork != forkPhase0:
|
of forkMerge:
|
||||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkPhase0)[]
|
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
|
return false
|
||||||
elif blck.slot.epoch < dag.cfg.MERGE_FORK_EPOCH:
|
of forkAltair:
|
||||||
if state.data.beaconStateFork != forkAltair:
|
if state.data.beaconStateFork != forkAltair:
|
||||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkAltair)[]
|
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkAltair)[]
|
||||||
|
|
||||||
if not dag.db.getAltairState(stateRoot, state.data.hbsAltair.data, restore):
|
if not dag.db.getAltairState(stateRoot, state.data.hbsAltair.data, restore):
|
||||||
return false
|
return false
|
||||||
else:
|
of forkPhase0:
|
||||||
if state.data.beaconStateFork != forkMerge:
|
if state.data.beaconStateFork != forkPhase0:
|
||||||
state.data = (ref ForkedHashedBeaconState)(beaconStateFork: forkMerge)[]
|
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
|
return false
|
||||||
|
|
||||||
state.blck = blck
|
state.blck = blck
|
||||||
|
@ -613,12 +612,10 @@ template forkAtEpoch*(dag: ChainDAGRef, epoch: Epoch): Fork =
|
||||||
forkAtEpoch(dag.cfg, epoch)
|
forkAtEpoch(dag.cfg, epoch)
|
||||||
|
|
||||||
proc forkDigestAtEpoch*(dag: ChainDAGRef, epoch: Epoch): ForkDigest =
|
proc forkDigestAtEpoch*(dag: ChainDAGRef, epoch: Epoch): ForkDigest =
|
||||||
if epoch < dag.cfg.ALTAIR_FORK_EPOCH:
|
case dag.cfg.stateForkAtEpoch(epoch)
|
||||||
dag.forkDigests.phase0
|
of forkMerge: dag.forkDigests.merge
|
||||||
elif epoch < dag.cfg.MERGE_FORK_EPOCH:
|
of forkAltair: dag.forkDigests.altair
|
||||||
dag.forkDigests.altair
|
of forkPhase0: dag.forkDigests.phase0
|
||||||
else:
|
|
||||||
dag.forkDigests.merge
|
|
||||||
|
|
||||||
proc getState(dag: ChainDAGRef, state: var StateData, bs: BlockSlot): bool =
|
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
|
## 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
|
node.rng[].rand(ATTESTATION_SUBNET_COUNT - 1).SubnetId
|
||||||
|
|
||||||
func forkDigestAtEpoch(node: Eth2Node, epoch: Epoch): ForkDigest =
|
func forkDigestAtEpoch(node: Eth2Node, epoch: Epoch): ForkDigest =
|
||||||
if epoch < node.cfg.ALTAIR_FORK_EPOCH:
|
case node.cfg.stateForkAtEpoch(epoch)
|
||||||
node.forkDigests.phase0
|
of forkMerge: node.forkDigests.merge
|
||||||
elif epoch < node.cfg.MERGE_FORK_EPOCH:
|
of forkAltair: node.forkDigests.altair
|
||||||
node.forkDigests.altair
|
of forkPhase0: node.forkDigests.phase0
|
||||||
else:
|
|
||||||
node.forkDigests.merge
|
|
||||||
|
|
||||||
proc getWallEpoch(node: Eth2Node): Epoch =
|
proc getWallEpoch(node: Eth2Node): Epoch =
|
||||||
node.getBeaconTime().slotOrZero.epoch
|
node.getBeaconTime().slotOrZero.epoch
|
||||||
|
|
|
@ -278,6 +278,17 @@ proc check_voluntary_exit*(
|
||||||
|
|
||||||
# Derived utilities
|
# 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
|
# 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 =
|
func get_current_epoch*(x: ForkedHashedBeaconState): Epoch =
|
||||||
## Return the current epoch.
|
## Return the current epoch.
|
||||||
|
@ -379,31 +390,22 @@ chronicles.formatIt ForkedSignedBeaconBlock: it.shortLog
|
||||||
chronicles.formatIt ForkedTrustedSignedBeaconBlock: it.shortLog
|
chronicles.formatIt ForkedTrustedSignedBeaconBlock: it.shortLog
|
||||||
|
|
||||||
proc forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork =
|
proc forkAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Fork =
|
||||||
doAssert cfg.ALTAIR_FORK_EPOCH <= cfg.MERGE_FORK_EPOCH
|
case cfg.stateForkAtEpoch(epoch)
|
||||||
if epoch < cfg.ALTAIR_FORK_EPOCH:
|
of forkMerge: cfg.mergeFork
|
||||||
genesisFork(cfg)
|
of forkAltair: cfg.altairFork
|
||||||
elif epoch < cfg.MERGE_FORK_EPOCH:
|
of forkPhase0: cfg.genesisFork
|
||||||
altairFork(cfg)
|
|
||||||
else:
|
|
||||||
mergeFork(cfg)
|
|
||||||
|
|
||||||
proc forkVersionAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Version =
|
proc forkVersionAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Version =
|
||||||
doAssert cfg.ALTAIR_FORK_EPOCH <= cfg.MERGE_FORK_EPOCH
|
case cfg.stateForkAtEpoch(epoch)
|
||||||
if epoch < cfg.ALTAIR_FORK_EPOCH:
|
of forkMerge: cfg.MERGE_FORK_VERSION
|
||||||
cfg.GENESIS_FORK_VERSION
|
of forkAltair: cfg.ALTAIR_FORK_VERSION
|
||||||
elif epoch < cfg.MERGE_FORK_EPOCH:
|
of forkPhase0: cfg.GENESIS_FORK_VERSION
|
||||||
cfg.ALTAIR_FORK_VERSION
|
|
||||||
else:
|
|
||||||
cfg.MERGE_FORK_VERSION
|
|
||||||
|
|
||||||
proc nextForkEpochAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Epoch =
|
proc nextForkEpochAtEpoch*(cfg: RuntimeConfig, epoch: Epoch): Epoch =
|
||||||
doAssert cfg.ALTAIR_FORK_EPOCH <= cfg.MERGE_FORK_EPOCH
|
case cfg.stateForkAtEpoch(epoch)
|
||||||
if epoch < cfg.ALTAIR_FORK_EPOCH:
|
of forkMerge: FAR_FUTURE_EPOCH
|
||||||
cfg.ALTAIR_FORK_EPOCH
|
of forkAltair: cfg.MERGE_FORK_EPOCH
|
||||||
elif epoch < cfg.MERGE_FORK_EPOCH:
|
of forkPhase0: cfg.ALTAIR_FORK_EPOCH
|
||||||
cfg.MERGE_FORK_EPOCH
|
|
||||||
else:
|
|
||||||
FAR_FUTURE_EPOCH
|
|
||||||
|
|
||||||
func getForkSchedule*(cfg: RuntimeConfig): array[2, Fork] =
|
func getForkSchedule*(cfg: RuntimeConfig): array[2, Fork] =
|
||||||
## This procedure returns list of known and/or scheduled forks.
|
## 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:
|
if blockRatio > 0.0:
|
||||||
withTimer(timers[t]):
|
withTimer(timers[t]):
|
||||||
if slot.epoch < dag.cfg.ALTAIR_FORK_EPOCH:
|
case dag.cfg.stateForkAtEpoch(slot.epoch)
|
||||||
proposePhase0Block(slot)
|
of forkMerge: proposeMergeBlock(slot)
|
||||||
elif slot.epoch < dag.cfg.MERGE_FORK_EPOCH:
|
of forkAltair: proposeAltairBlock(slot)
|
||||||
proposeAltairBlock(slot)
|
of forkPhase0: proposePhase0Block(slot)
|
||||||
else:
|
|
||||||
proposeMergeBlock(slot)
|
|
||||||
if attesterRatio > 0.0:
|
if attesterRatio > 0.0:
|
||||||
withTimer(timers[tAttest]):
|
withTimer(timers[tAttest]):
|
||||||
handleAttestations(slot)
|
handleAttestations(slot)
|
||||||
|
|
Loading…
Reference in New Issue