Skip to content

Commit 326c495

Browse files
committed
feat(test-utils): Add resumeFromDb option to getDevBeaconNode to initialize state from existing db
1 parent c343df4 commit 326c495

1 file changed

Lines changed: 47 additions & 10 deletions

File tree

  • packages/beacon-node/test/utils/node

‎packages/beacon-node/test/utils/node/beacon.ts‎

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,17 @@ import {config as minimalConfig} from "@lodestar/config/default";
1010
import {LevelDbController} from "@lodestar/db/controller/level";
1111
import {LoggerNode} from "@lodestar/logger/node";
1212
import {ForkSeq, GENESIS_SLOT} from "@lodestar/params";
13-
import {BeaconStateAllForks, Index2PubkeyCache, createCachedBeaconState, syncPubkeys} from "@lodestar/state-transition";
13+
import {
14+
BeaconStateAllForks,
15+
Index2PubkeyCache,
16+
computeAnchorCheckpoint,
17+
computeEpochAtSlot,
18+
createCachedBeaconState,
19+
syncPubkeys,
20+
} from "@lodestar/state-transition";
1421
import {phase0, ssz} from "@lodestar/types";
1522
import {RecursivePartial, isPlainObject} from "@lodestar/utils";
23+
import {initStateFromDb} from "../../../src/chain/initState.js";
1624
import {BeaconDb} from "../../../src/db/index.js";
1725
import {BeaconNode} from "../../../src/index.js";
1826
import {defaultNetworkOptions} from "../../../src/network/options.js";
@@ -31,6 +39,11 @@ export async function getDevBeaconNode(
3139
peerStoreDir?: string;
3240
anchorState?: BeaconStateAllForks;
3341
wsCheckpoint?: phase0.Checkpoint;
42+
/**
43+
* When true, load anchor state from existing DB instead of creating fresh genesis.
44+
* Requires `options.db.name` to be set explicitly.
45+
*/
46+
resumeFromDb?: boolean;
3447
} & InteropStateOpts
3548
): Promise<BeaconNode> {
3649
setHasher(hasher);
@@ -45,17 +58,41 @@ export async function getDevBeaconNode(
4558
const db = new BeaconDb(config, await LevelDbController.create({name: options.db?.name ?? tmpDir.name}, {logger}));
4659

4760
let anchorState = opts.anchorState;
61+
let wsCheckpoint = opts.wsCheckpoint;
62+
4863
if (!anchorState) {
49-
anchorState = initDevState(config, validatorCount, opts);
64+
if (opts.resumeFromDb) {
65+
if (!options.db?.name) {
66+
throw new Error("resumeFromDb requires explicit options.db.name to be set");
67+
}
68+
69+
// reuse production code for state loading from DB
70+
anchorState = await initStateFromDb(config, db, logger);
71+
const resumedEpoch = computeEpochAtSlot(anchorState.slot);
72+
73+
// resuming from epoch 0 defeats the purpose of resuming
74+
if (resumedEpoch === 0) {
75+
logger.warn("Resumed state from epoch 0. Range Sync may trigger from genesis");
76+
}
77+
78+
// derive wsCheckpoint if not provided
79+
if (!wsCheckpoint) {
80+
const {checkpoint} = computeAnchorCheckpoint(config, anchorState);
81+
wsCheckpoint = {root: checkpoint.root, epoch: checkpoint.epoch};
82+
logger.debug("Derived wsCheckpoint", {epoch: checkpoint.epoch});
83+
}
84+
} else {
85+
anchorState = initDevState(config, validatorCount, opts);
5086

51-
const block = config.getForkTypes(GENESIS_SLOT).SignedBeaconBlock.defaultValue();
52-
block.message.stateRoot = anchorState.hashTreeRoot();
53-
await db.blockArchive.add(block);
87+
const block = config.getForkTypes(GENESIS_SLOT).SignedBeaconBlock.defaultValue();
88+
block.message.stateRoot = anchorState.hashTreeRoot();
89+
await db.blockArchive.add(block);
5490

55-
if (config.getForkSeq(GENESIS_SLOT) >= ForkSeq.deneb) {
56-
const blobSidecars = ssz.deneb.BlobSidecars.defaultValue();
57-
const blockRoot = config.getForkTypes(GENESIS_SLOT).BeaconBlock.hashTreeRoot(block.message);
58-
await db.blobSidecars.add({blobSidecars, slot: GENESIS_SLOT, blockRoot});
91+
if (config.getForkSeq(GENESIS_SLOT) >= ForkSeq.deneb) {
92+
const blobSidecars = ssz.deneb.BlobSidecars.defaultValue();
93+
const blockRoot = config.getForkTypes(GENESIS_SLOT).BeaconBlock.hashTreeRoot(block.message);
94+
await db.blobSidecars.add({blobSidecars, slot: GENESIS_SLOT, blockRoot});
95+
}
5996
}
6097
}
6198

@@ -121,7 +158,7 @@ export async function getDevBeaconNode(
121158
dataDir: ".",
122159
peerStoreDir,
123160
anchorState: cachedState,
124-
wsCheckpoint: opts.wsCheckpoint,
161+
wsCheckpoint,
125162
isAnchorStateFinalized: true,
126163
});
127164
}

0 commit comments

Comments
 (0)