diff --git a/beacon_chain/conf.nim b/beacon_chain/conf.nim index 4f8a32ef99..bb81d488f9 100644 --- a/beacon_chain/conf.nim +++ b/beacon_chain/conf.nim @@ -29,6 +29,8 @@ import ./el/el_conf, ./filepath +from fork_choice/fork_choice_types + import ForkChoiceVersion from consensus_object_pools/block_pools_types_light_client import LightClientDataImportMode @@ -632,6 +634,12 @@ type desc: "Bandwidth estimate for the node (bits per second)" name: "debug-bandwidth-estimate" .}: Option[Natural] + forkChoiceVersion* {. + hidden + desc: "Forkchoice version to use. " & + "Must be one of: stable" + name: "debug-forkchoice-version" .}: Option[ForkChoiceVersion] + of BNStartUpCmd.wallets: case walletsCmd* {.command.}: WalletsCmd of WalletsCmd.create: diff --git a/beacon_chain/consensus_object_pools/attestation_pool.nim b/beacon_chain/consensus_object_pools/attestation_pool.nim index efa4fc40df..477c05205d 100644 --- a/beacon_chain/consensus_object_pools/attestation_pool.nim +++ b/beacon_chain/consensus_object_pools/attestation_pool.nim @@ -90,6 +90,7 @@ declareGauge attestation_pool_block_attestation_packing_time, proc init*(T: type AttestationPool, dag: ChainDAGRef, quarantine: ref Quarantine, + forkChoiceVersion = ForkChoiceVersion.Stable, onAttestation: OnAttestationCallback = nil): T = ## Initialize an AttestationPool from the dag `headState` ## The `finalized_root` works around the finalized_checkpoint of the genesis block @@ -97,7 +98,7 @@ proc init*(T: type AttestationPool, dag: ChainDAGRef, let finalizedEpochRef = dag.getFinalizedEpochRef() var forkChoice = ForkChoice.init( - finalizedEpochRef, dag.finalizedHead.blck) + finalizedEpochRef, dag.finalizedHead.blck, forkChoiceVersion) # Feed fork choice with unfinalized history - during startup, block pool only # keeps track of a single history so we just need to follow it diff --git a/beacon_chain/fork_choice/fork_choice.nim b/beacon_chain/fork_choice/fork_choice.nim index 2311f0f395..710789e4c5 100644 --- a/beacon_chain/fork_choice/fork_choice.nim +++ b/beacon_chain/fork_choice/fork_choice.nim @@ -49,11 +49,13 @@ func compute_deltas( logScope: topics = "fork_choice" func init*( - T: type ForkChoiceBackend, checkpoints: FinalityCheckpoints): T = - T(proto_array: ProtoArray.init(checkpoints)) + T: type ForkChoiceBackend, checkpoints: FinalityCheckpoints, + version: ForkChoiceVersion): T = + T(proto_array: ProtoArray.init(checkpoints, version)) proc init*( - T: type ForkChoice, epochRef: EpochRef, blck: BlockRef): T = + T: type ForkChoice, epochRef: EpochRef, blck: BlockRef, + version: ForkChoiceVersion): T = ## Initialize a fork choice context for a finalized state - in the finalized ## state, the justified and finalized checkpoints are the same, so only one ## is used here @@ -65,8 +67,10 @@ proc init*( backend: ForkChoiceBackend.init( FinalityCheckpoints( justified: checkpoint, - finalized: checkpoint)), + finalized: checkpoint), + version), checkpoints: Checkpoints( + version: version, justified: BalanceCheckpoint( checkpoint: checkpoint, balances: epochRef.effective_balances), diff --git a/beacon_chain/fork_choice/fork_choice_types.nim b/beacon_chain/fork_choice/fork_choice_types.nim index 5931672597..27a94980b9 100644 --- a/beacon_chain/fork_choice/fork_choice_types.nim +++ b/beacon_chain/fork_choice/fork_choice_types.nim @@ -29,6 +29,11 @@ import # ---------------------------------------------------------------------- type + ForkChoiceVersion* {.pure.} = enum + ## Controls which version of fork choice to run. + Stable = "stable" + ## Use current version from stable Ethereum consensus specifications + fcKind* = enum ## Fork Choice Error Kinds fcFinalizedNodeUnknown @@ -88,6 +93,7 @@ type ## Subtracted from logical index to get the physical index ProtoArray* = object + version*: ForkChoiceVersion currentEpoch*: Epoch checkpoints*: FinalityCheckpoints nodes*: ProtoNodes @@ -110,6 +116,7 @@ type balances*: seq[Gwei] Checkpoints* = object + version*: ForkChoiceVersion time*: BeaconTime justified*: BalanceCheckpoint finalized*: Checkpoint diff --git a/beacon_chain/fork_choice/proto_array.nim b/beacon_chain/fork_choice/proto_array.nim index 558b985d1c..b0d125cdca 100644 --- a/beacon_chain/fork_choice/proto_array.nim +++ b/beacon_chain/fork_choice/proto_array.nim @@ -90,7 +90,8 @@ func nodeLeadsToViableHead( # ---------------------------------------------------------------------- func init*( - T: type ProtoArray, checkpoints: FinalityCheckpoints): T = + T: type ProtoArray, checkpoints: FinalityCheckpoints, + version: ForkChoiceVersion): T = let node = ProtoNode( bid: BlockId( slot: checkpoints.finalized.epoch.start_slot, @@ -102,7 +103,8 @@ func init*( bestChild: none(int), bestDescendant: none(int)) - T(checkpoints: checkpoints, + T(version: version, + checkpoints: checkpoints, nodes: ProtoNodes(buf: @[node], offset: 0), indices: {node.bid.root: 0}.toTable()) @@ -541,7 +543,7 @@ func nodeIsViableForHead( correctJustified = unrealized.justified.epoch >= self.checkpoints.justified.epoch and node.checkpoints.justified.epoch + 2 >= self.currentEpoch - + return if not correctJustified: false diff --git a/beacon_chain/nimbus_beacon_node.nim b/beacon_chain/nimbus_beacon_node.nim index 0c160ded91..e85b8df201 100644 --- a/beacon_chain/nimbus_beacon_node.nim +++ b/beacon_chain/nimbus_beacon_node.nim @@ -313,8 +313,8 @@ proc initFullNode( let quarantine = newClone( Quarantine.init()) - attestationPool = newClone( - AttestationPool.init(dag, quarantine, onAttestationReceived)) + attestationPool = newClone(AttestationPool.init( + dag, quarantine, config.forkChoiceVersion.get, onAttestationReceived)) syncCommitteeMsgPool = newClone( SyncCommitteeMsgPool.init(rng, dag.cfg, onSyncContribution)) lightClientPool = newClone( @@ -1860,6 +1860,8 @@ proc doRunBeaconNode(config: var BeaconNodeConf, rng: ref HmacDrbgContext) {.rai # works for node in metadata.bootstrapNodes: config.bootstrapNodes.add node + if config.forkChoiceVersion.isNone: + config.forkChoiceVersion = some(ForkChoiceVersion.Stable) ## Ctrl+C handling proc controlCHandler() {.noconv.} = diff --git a/beacon_chain/rpc/rest_debug_api.nim b/beacon_chain/rpc/rest_debug_api.nim index 2a6f65a4ed..fe52f27256 100644 --- a/beacon_chain/rpc/rest_debug_api.nim +++ b/beacon_chain/rpc/rest_debug_api.nim @@ -87,7 +87,9 @@ proc installDebugApiHandlers*(router: var RestRouter, node: BeaconNode) = var response = GetForkChoiceResponse( justified_checkpoint: forkChoice.checkpoints.justified.checkpoint, - finalized_checkpoint: forkChoice.checkpoints.finalized) + finalized_checkpoint: forkChoice.checkpoints.finalized, + extra_data: RestExtraData( + version: some($forkChoice.backend.proto_array.version))) for item in forkChoice.backend.proto_array: let diff --git a/beacon_chain/spec/eth2_apis/rest_types.nim b/beacon_chain/spec/eth2_apis/rest_types.nim index df75b05276..2aac353803 100644 --- a/beacon_chain/spec/eth2_apis/rest_types.nim +++ b/beacon_chain/spec/eth2_apis/rest_types.nim @@ -712,7 +712,7 @@ type extra_data*: Option[RestNodeExtraData] RestExtraData* = object - discard + version*: Option[string] GetForkChoiceResponse* = object justified_checkpoint*: Checkpoint diff --git a/tests/consensus_spec/test_fixture_fork_choice.nim b/tests/consensus_spec/test_fixture_fork_choice.nim index 5035c747c7..a3bd37879e 100644 --- a/tests/consensus_spec/test_fixture_fork_choice.nim +++ b/tests/consensus_spec/test_fixture_fork_choice.nim @@ -123,7 +123,8 @@ proc initialLoad( dag = ChainDAGRef.init( forkedState[].kind.genesisTestRuntimeConfig, db, validatorMonitor, {}) fkChoice = newClone(ForkChoice.init( - dag.getFinalizedEpochRef(), dag.finalizedHead.blck)) + dag.getFinalizedEpochRef(), dag.finalizedHead.blck, + ForkChoiceVersion.Stable)) (dag, fkChoice) diff --git a/tests/test_keymanager_api.nim b/tests/test_keymanager_api.nim index b1a6a70679..3c0ed672e2 100644 --- a/tests/test_keymanager_api.nim +++ b/tests/test_keymanager_api.nim @@ -295,7 +295,8 @@ proc startBeaconNode(basePort: int) {.raises: [CatchableError].} = "--keymanager-port=" & $(basePort + PortKind.KeymanagerBN.ord), "--keymanager-token-file=" & tokenFilePath, "--suggested-fee-recipient=" & $defaultFeeRecipient, - "--doppelganger-detection=off"], it)) + "--doppelganger-detection=off", + "--debug-forkchoice-version=stable"], it)) except Exception as exc: # TODO fix confutils exceptions raiseAssert exc.msg