nimbus-eth2/beacon_chain/nimbus_beacon_node.nim

174 lines
4.4 KiB
Nim
Raw Normal View History

import
2024-03-10 02:19:13 +00:00
std/[os, times],
chronos,
stew/io2,
./spec/datatypes/[altair, bellatrix, phase0],
./validators/beacon_validators,
"."/[
2024-03-10 02:19:13 +00:00
beacon_node,
nimbus_binary_common]
from ./spec/datatypes/deneb import SignedBeaconBlock
proc initFullNode(
node: BeaconNode,
2024-03-22 03:32:38 +00:00
getBeaconTime: GetBeaconTimeFn) {.async.} = discard
import
"."/spec/forks,
"."/consensus_object_pools/block_pools_types
proc preInit(
T: type ChainDAGRef, state: ForkedHashedBeaconState) =
doAssert getStateField(state, slot).is_epoch,
"Can only initialize database from epoch states"
2024-03-22 03:32:38 +00:00
withConsensusFork(state.kind):
if false:
2024-03-20 08:45:59 +00:00
discard 0
else:
2024-03-20 08:45:59 +00:00
discard 0
2024-03-18 04:31:20 +00:00
proc init*(T: type BeaconNode,
config: BeaconNodeConf,
metadata: Eth2NetworkMetadata): Future[BeaconNode]
2023-12-05 21:08:18 +00:00
{.async.} =
template cfg: auto = metadata.cfg
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
let checkpointState = if config.finalizedCheckpointState.isSome:
let checkpointStatePath = config.finalizedCheckpointState.get.string
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
let tmp = try:
newClone(readSszForkedHashedBeaconState(
cfg, readAllBytes(checkpointStatePath).tryGet()))
except CatchableError:
quit 1
2024-03-22 03:32:38 +00:00
if not true:
quit 1
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
tmp
else:
nil
var networkGenesisValidatorsRoot = metadata.bakedGenesisValidatorsRoot
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
2024-03-10 02:19:13 +00:00
var genesisState = checkpointState
if true:
genesisState = if checkpointState != nil and getStateField(checkpointState[], slot) == 0:
checkpointState
else:
let genesisBytes = block:
if metadata.genesis.kind != BakedIn and config.genesisState.isSome:
let res = io2.readAllBytes(config.genesisState.get.string)
res.valueOr:
quit 1
elif metadata.hasGenesis:
try:
metadata.fetchGenesisBytes()
2024-03-20 01:44:39 +00:00
except CatchableError:
quit 1
else:
@[]
if genesisBytes.len > 0:
try:
newClone readSszForkedHashedBeaconState(cfg, genesisBytes)
2024-03-20 01:44:39 +00:00
except CatchableError:
quit 1
else:
nil
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
if genesisState == nil and checkpointState == nil:
2023-01-12 00:49:43 +00:00
quit 1
2019-10-25 14:53:31 +00:00
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
if not genesisState.isNil and not checkpointState.isNil:
if getStateField(genesisState[], genesis_validators_root) !=
getStateField(checkpointState[], genesis_validators_root):
quit 1
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
try:
if not genesisState.isNil:
networkGenesisValidatorsRoot =
Opt.some(getStateField(genesisState[], genesis_validators_root))
if not checkpointState.isNil:
State-only checkpoint state startup (#4251) Currently, we require genesis and a checkpoint block and state to start from an arbitrary slot - this PR relaxes this requirement so that we can start with a state alone. The current trusted-node-sync algorithm works by first downloading blocks until we find an epoch aligned non-empty slot, then downloads the state via slot. However, current [proposals](https://github.com/ethereum/beacon-APIs/pull/226) for checkpointing prefer finalized state as the main reference - this allows more simple access control and caching on the server side - in particular, this should help checkpoint-syncing from sources that have a fast `finalized` state download (like infura and teku) but are slow when accessing state via slot. Earlier versions of Nimbus will not be able to read databases created without a checkpoint block and genesis. In most cases, backfilling makes the database compatible except where genesis is also missing (custom networks). * backfill checkpoint block from libp2p instead of checkpoint source, when doing trusted node sync * allow starting the client without genesis / checkpoint block * perform epoch start slot lookahead when loading tail state, so as to deal with the case where the epoch start slot does not have a block * replace `--blockId` with `--state-id` in TNS command line * when replaying, also look at the parent of the last-known-block (even if we don't have the parent block data, we can still replay from a "parent" state) - in particular, this clears the way for implementing state pruning * deprecate `--finalized-checkpoint-block` option (no longer needed)
2022-11-02 10:02:38 +00:00
if genesisState.isNil or
getStateField(checkpointState[], slot) != GENESIS_SLOT:
2024-03-10 02:19:13 +00:00
ChainDAGRef.preInit(checkpointState[])
2024-03-20 01:44:39 +00:00
except CatchableError:
quit 1
else:
if not checkpointState.isNil:
quit 1
2024-03-10 02:19:13 +00:00
doAssert not genesisState.isNil
let
2024-03-10 02:19:13 +00:00
genesisTime = getStateField(genesisState[], genesis_time)
beaconClock = BeaconClock.init(genesisTime).valueOr:
quit 1
2022-03-31 14:43:05 +00:00
getBeaconTime = beaconClock.getBeaconTimeFn()
let node = BeaconNode(
config: config,
beaconClock: beaconClock,
2024-03-10 02:19:13 +00:00
cfg: cfg,
genesisState: genesisState)
2020-12-16 13:03:04 +00:00
await node.initFullNode(getBeaconTime)
node
2024-03-18 04:31:20 +00:00
from "."/consensus_object_pools/block_dag import BlockRef, init
2024-03-10 02:19:13 +00:00
func getBlockRef2(root: Eth2Digest): Opt[BlockRef] =
let newRef = BlockRef.init(
2024-03-19 02:49:36 +00:00
root,
2024-03-10 02:19:13 +00:00
0.Slot)
return ok(newRef)
import "."/el/el_manager
2024-03-20 01:44:39 +00:00
proc start(node: BeaconNode) {.raises: [CatchableError].} =
2024-03-10 02:19:13 +00:00
echo "foo"
let elManager = default(ELManager)
elManager.start()
2021-05-19 06:38:13 +00:00
let
2024-03-10 02:19:13 +00:00
wallTime = node.beaconClock.now()
asyncSpawn runSlotLoop(node, wallTime)
2024-03-10 02:19:13 +00:00
while true:
poll()
when isMainModule:
import
confutils,
2024-03-20 08:21:29 +00:00
../beacon_chain/conf
const
dataDir = "./test_keymanager_api"
nodeDataDir = dataDir / "node-0"
nodeValidatorsDir = nodeDataDir / "validators"
nodeSecretsDir = nodeDataDir / "secrets"
proc startBeaconNode() {.raises: [CatchableError].} =
#copyHalfValidators(nodeDataDir, true)
let runNodeConf = try: BeaconNodeConf.load(cmdLine = @[
"--network=" & dataDir,
"--data-dir=" & nodeDataDir,
"--validators-dir=" & nodeValidatorsDir,
"--secrets-dir=" & nodeSecretsDir,
"--no-el"])
except Exception as exc: # TODO fix confutils exceptions
raiseAssert exc.msg
let
metadata = loadEth2NetworkMetadata(dataDir).expect("Metadata is compatible")
node = waitFor BeaconNode.init(runNodeConf, metadata)
node.start()
startBeaconNode()