@@ -10,9 +10,17 @@ import {config as minimalConfig} from "@lodestar/config/default";
1010import { LevelDbController } from "@lodestar/db/controller/level" ;
1111import { LoggerNode } from "@lodestar/logger/node" ;
1212import { 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" ;
1421import { phase0 , ssz } from "@lodestar/types" ;
1522import { RecursivePartial , isPlainObject } from "@lodestar/utils" ;
23+ import { initStateFromDb } from "../../../src/chain/initState.js" ;
1624import { BeaconDb } from "../../../src/db/index.js" ;
1725import { BeaconNode } from "../../../src/index.js" ;
1826import { 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