3.1 Code Lodestar CLI Beacon Node
From lodestar documentation:
- CLI
lodestar beacon
: https://chainsafe.github.io/lodestar/reference/cli/#beacon - Beacon management: https://chainsafe.github.io/lodestar/usage/beacon-management/
It's codebase start with packages/beacon-node
folder.
From CLI#
packages/cli/src/cmds/beacon/index.ts
export const beacon: ICliCommand<IBeaconArgs, IGlobalArgs> = {
command: "beacon",
// ...
// Below points to beaconHandler
handler: beaconHandler,
};
beaconHandler
is the main function defined in handler.ts. It starts the database and initialize the node:
const node = await BeaconNode.init({
opts: options,
config: beaconConfig,
db, // a 'level' db connection.
logger,
processShutdownCallback, // used during fatal error to shutdown the node.
libp2p: await createNodeJsLibp2p(peerId, options.network, {
peerStoreDir: beaconPaths.peerStoreDir,
metrics: options.metrics.enabled,
metricsRegistry: networkRegistry,
}), // initialize p2p network, which will be used later for gossipsub. peerId is created or retrieved from file.
anchorState, // the trusted state to not roll back beyond.
wsCheckpoint, // weak subjectivity checkpoints.
metricsRegistries,
});
Some concepts in this section of the code:
- Weak subjectivity. The 'genesis' for new nodes or nodes that have been offline for a long time. They don't need to download the full chain but onlyl need to start from 'weak subjectivity checkpoints'. Further read: https://blog.ethereum.org/2014/11/25/proof-stake-learned-love-weak-subjectivity
- Anchor state. The content of the weak subjectivity checkpoints. ^47e34e
- libp2p. "The libP2P stack supports all communications after discovery." ^c90843
Deep dive into BeaconNode.init
#
In https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/node/nodejs.ts L126:
const chain = new BeaconChain(); // responsible for managing blocks
await chain.loadFromDisk();
const network = new Network(); // handles p2p connections, subnets.
await network.start();
const sync = new BeaconSync(); // handles addPeer, removePeer, and stops/continues participating in gossipsub based on sync status.
const api = getApi(); // corresponds to these specs: https://ethereum.github.io/beacon-APIs/
const restApi = new BeaconRestApiServer(); // registers routes for the 'api' that's created before.
For more details:
CKZG, after deneb#
If post deneb (EIP-4844) upgrade, initialize KZG ^ce21ec
if (config.EIP4844_FORK_EPOCH < Infinity) {
// TODO DENEB: "c-kzg" is not installed by default, so if the library is not installed this will throw
// See "Not able to build lodestar from source" https://github.com/ChainSafe/lodestar/issues/4886
await initCKZG();
loadEthereumTrustedSetup();
}
Create chain
#
Initialize database, and creates BeaconChain
instance.
await db.start();
await db.pruneHotDb();
const chain = new BeaconChain(opts.chain, {
// ...
/* a queued JSON-RPC client to interact with execution client. */
executionEngine: initializeExecutionEngine(opts.executionEngine, {metrics, signal}),
executionBuilder: opts.executionBuilder.enabled
? initializeExecutionBuilder(opts.executionBuilder, config)
: undefined, // an HTTP client to interact with MEV boosters.
});
- Queue. A queue is used to guarantee the order of requests.
- The
executionEngine
is the execution client usually running on another port on the same host.
Create network
, the most important step.#
Code: https://github.com/ChainSafe/lodestar/blob/v1.5.1/packages/beacon-node/src/network/network.ts
Compared to execution client, the consensus client upgraded network by:
- using 'discv5' as discovery protocol to find peers.
- using ENR (EIP-778). Particularly, it introduces
seqNumber
to version the metadata.Note: execution client uses 'Enode', see [[4.1 Code * Geth * CLI#About Bootnodes]]
The constructor
:
this.gossip = new Eth2Gossipsub
, read more in [[3.3 Code * Lodestar * Gossip Handling]]
The start
function:
async start(): Promise<void> {
await this.discovery?.start();
this.libp2p.connectionManager.addEventListener(Libp2pEvent.peerConnect, this.onLibp2pPeerConnect);
this.libp2p.connectionManager.addEventListener(Libp2pEvent.peerDisconnect, this.onLibp2pPeerDisconnect);
this.networkEventBus.on(NetworkEvent.reqRespRequest, this.onRequest);
this.heartbeat(); // will soon make it periodic
this.intervals = [
setInterval(this.pingAndStatusTimeouts.bind(this), CHECK_PING_STATUS_INTERVAL), // check whether peers 'seqNumber' is still the same, if not, update.
setInterval(this.heartbeat.bind(this), HEARTBEAT_INTERVAL_MS), // check whether sufficient peers are connected
setInterval(
this.updateGossipsubScores.bind(this),
this.gossipsub.scoreParams.decayInterval ?? HEARTBEAT_INTERVAL_MS
), // update peer scoring
];
}
Peer Scoring
Peer scoring is introduced in gossipsub 1.1. Although lodestar implemented it, the only spec I could find is saying that it is under investigation: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/p2p-interface.md#the-gossip-domain-gossipsub