@chainsafe/lodestar 1.50.0-dev.db953a4f93 → 1.50.0-dev.e8dec5f2fe

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/.git-data.json +1 -1
  2. package/lib/cmds/beacon/handler.d.ts +1 -0
  3. package/lib/cmds/beacon/handler.d.ts.map +1 -1
  4. package/lib/cmds/beacon/handler.js +11 -6
  5. package/lib/cmds/beacon/handler.js.map +1 -1
  6. package/lib/cmds/beacon/initBeaconState.d.ts +4 -2
  7. package/lib/cmds/beacon/initBeaconState.d.ts.map +1 -1
  8. package/lib/cmds/beacon/initBeaconState.js +15 -10
  9. package/lib/cmds/beacon/initBeaconState.js.map +1 -1
  10. package/lib/cmds/beacon/options.d.ts +1 -0
  11. package/lib/cmds/beacon/options.d.ts.map +1 -1
  12. package/lib/cmds/beacon/options.js +6 -0
  13. package/lib/cmds/beacon/options.js.map +1 -1
  14. package/lib/cmds/beacon/paths.d.ts +4 -0
  15. package/lib/cmds/beacon/paths.d.ts.map +1 -1
  16. package/lib/cmds/beacon/paths.js +3 -0
  17. package/lib/cmds/beacon/paths.js.map +1 -1
  18. package/lib/cmds/beacon/pubkeysFile.d.ts +10 -0
  19. package/lib/cmds/beacon/pubkeysFile.d.ts.map +1 -0
  20. package/lib/cmds/beacon/pubkeysFile.js +39 -0
  21. package/lib/cmds/beacon/pubkeysFile.js.map +1 -0
  22. package/lib/cmds/beacon/stateInitialization/checkpointState.js +22 -6
  23. package/lib/cmds/beacon/stateInitialization/checkpointState.js.map +1 -1
  24. package/lib/cmds/beacon/stateInitialization/genesisState.d.ts.map +1 -1
  25. package/lib/cmds/beacon/stateInitialization/genesisState.js +15 -1
  26. package/lib/cmds/beacon/stateInitialization/genesisState.js.map +1 -1
  27. package/lib/cmds/beacon/stateInitialization/prepareStateInitialization.d.ts +1 -1
  28. package/lib/cmds/beacon/stateInitialization/prepareStateInitialization.d.ts.map +1 -1
  29. package/lib/cmds/beacon/stateInitialization/prepareStateInitialization.js +17 -2
  30. package/lib/cmds/beacon/stateInitialization/prepareStateInitialization.js.map +1 -1
  31. package/lib/cmds/beacon/stateInitialization/types.d.ts +4 -2
  32. package/lib/cmds/beacon/stateInitialization/types.d.ts.map +1 -1
  33. package/lib/cmds/dev/handler.d.ts.map +1 -1
  34. package/lib/cmds/dev/handler.js +3 -1
  35. package/lib/cmds/dev/handler.js.map +1 -1
  36. package/lib/cmds/dev/options.d.ts +2 -1
  37. package/lib/cmds/dev/options.d.ts.map +1 -1
  38. package/lib/options/beaconNodeOptions/chain.d.ts +2 -1
  39. package/lib/options/beaconNodeOptions/chain.d.ts.map +1 -1
  40. package/lib/options/beaconNodeOptions/chain.js +11 -4
  41. package/lib/options/beaconNodeOptions/chain.js.map +1 -1
  42. package/lib/options/beaconNodeOptions/index.d.ts +2 -1
  43. package/lib/options/beaconNodeOptions/index.d.ts.map +1 -1
  44. package/package.json +15 -15
  45. package/src/cmds/beacon/handler.ts +15 -6
  46. package/src/cmds/beacon/initBeaconState.ts +29 -10
  47. package/src/cmds/beacon/options.ts +8 -0
  48. package/src/cmds/beacon/paths.ts +5 -0
  49. package/src/cmds/beacon/pubkeysFile.ts +50 -0
  50. package/src/cmds/beacon/stateInitialization/checkpointState.ts +26 -10
  51. package/src/cmds/beacon/stateInitialization/genesisState.ts +15 -1
  52. package/src/cmds/beacon/stateInitialization/prepareStateInitialization.ts +17 -2
  53. package/src/cmds/beacon/stateInitialization/types.ts +4 -2
  54. package/src/cmds/dev/handler.ts +3 -1
  55. package/src/options/beaconNodeOptions/chain.ts +14 -5
@@ -186,6 +186,16 @@ function prepareCheckpointInitialization(
186
186
  const {isFinalized, ignoreWeakSubjectivityCheck} = policy;
187
187
  const config = createBeaconConfig(chainForkConfig, metadata.genesisValidatorsRoot);
188
188
  const archivedWithinWeakSubjectivityPeriod = useArchived ? archived.isWithinWeakSubjectivityPeriod : null;
189
+ const passedValidation =
190
+ archivedWithinWeakSubjectivityPeriod ?? isWithinWeakSubjectivityPeriodFromSummary(config, weakSubjectivity);
191
+ // Fast-fail stale checkpoints before deserializing the state or reserving pubkey-cache capacity.
192
+ if (!passedValidation && !ignoreWeakSubjectivityCheck) {
193
+ const clockEpoch = computeEpochAtSlot(getCurrentSlot(config, weakSubjectivity.genesisTime));
194
+ throw new StateInitializationError(
195
+ {code: StateInitializationErrorCode.STALE_CHECKPOINT},
196
+ `The selected state with epoch ${weakSubjectivity.checkpointEpoch} is not within weak subjectivity period of ${weakSubjectivity.period} epochs from the current epoch ${clockEpoch}. Please verify your checkpoint source`
197
+ );
198
+ }
189
199
  // DB-selected anchors need no persistence, including at slot zero.
190
200
  const shouldPersist = isFinalized && !useArchived;
191
201
  return {
@@ -195,15 +205,6 @@ function prepareCheckpointInitialization(
195
205
  validate(state) {
196
206
  // A supplied checkpoint must match even when the period check is ignored.
197
207
  if (expectedCheckpoint !== null) assertStateMatchesCheckpoint(state, expectedCheckpoint);
198
- const passedValidation =
199
- archivedWithinWeakSubjectivityPeriod ?? isWithinWeakSubjectivityPeriodFromSummary(config, weakSubjectivity);
200
- if (!passedValidation && !ignoreWeakSubjectivityCheck) {
201
- const clockEpoch = computeEpochAtSlot(getCurrentSlot(config, weakSubjectivity.genesisTime));
202
- throw new StateInitializationError(
203
- {code: StateInitializationErrorCode.STALE_CHECKPOINT},
204
- `The selected state with epoch ${weakSubjectivity.checkpointEpoch} is not within weak subjectivity period of ${weakSubjectivity.period} epochs from the current epoch ${clockEpoch}. Please verify your checkpoint source`
205
- );
206
- }
207
208
  assertAnchorStateForkMatchesConfig(config, state);
208
209
  if (isFinalized) {
209
210
  const source = useArchived ? "db" : "checkpoint";
@@ -222,8 +223,22 @@ function prepareCheckpointInitialization(
222
223
  }
223
224
  }
224
225
  },
226
+ async initializeEarliestAvailableSlot(state) {
227
+ const stored = await db.earliestAvailableSlot.get();
228
+ const floor = useArchived ? (stored ?? state.slot) : Math.max(stored ?? 0, state.slot);
229
+ if (stored !== floor) {
230
+ await db.earliestAvailableSlot.set(floor);
231
+ }
232
+ logger.verbose("Initialized earliest available slot", {
233
+ source,
234
+ anchorSlot: state.slot,
235
+ previousSlot: stored,
236
+ earliestAvailableSlot: floor,
237
+ });
238
+ return floor;
239
+ },
225
240
  persist: shouldPersist ? (state, bytes) => persistAnchorState(config, db, state, bytes) : null,
226
- log(state) {
241
+ log(state, nativeStateTransition) {
227
242
  const {checkpoint} = state.computeAnchorCheckpoint();
228
243
  logger.info("Initialized checkpoint state", {
229
244
  source,
@@ -233,6 +248,7 @@ function prepareCheckpointInitialization(
233
248
  stateRoot: toRootHex(state.hashTreeRoot()),
234
249
  checkpointRoot: toRootHex(checkpoint.root),
235
250
  isFinalized,
251
+ nativeStateTransition,
236
252
  ...(isFinalized ? {} : {lastProcessedSlot: state.latestBlockHeader.slot}),
237
253
  });
238
254
  },
@@ -73,12 +73,26 @@ export async function prepareGenesisInitialization(
73
73
  logger.warn("Checkpoint sync recommended, please use --help to see checkpoint sync options");
74
74
  }
75
75
  },
76
+ async initializeEarliestAvailableSlot(state) {
77
+ const stored = await db.earliestAvailableSlot.get();
78
+ if (stored !== null && stored !== state.slot) {
79
+ logger.warn("Resetting earliest available slot for genesis initialization", {
80
+ previousSlot: stored,
81
+ earliestAvailableSlot: state.slot,
82
+ });
83
+ }
84
+ if (stored !== state.slot) {
85
+ await db.earliestAvailableSlot.set(state.slot);
86
+ }
87
+ return state.slot;
88
+ },
76
89
  persist: (state, bytes) => persistAnchorState(config, db, state, bytes),
77
- log(state) {
90
+ log(state, nativeStateTransition) {
78
91
  logger.info("Initialized genesis state", {
79
92
  slot: state.slot,
80
93
  stateRoot: toRootHex(state.hashTreeRoot()),
81
94
  isFinalized: true,
95
+ nativeStateTransition,
82
96
  });
83
97
  },
84
98
  };
@@ -11,7 +11,7 @@ import {assertAnchorStateForkMatchesConfig} from "./validation.js";
11
11
 
12
12
  export function prepareArchivedStateInitialization(
13
13
  {stateBytes, metadata, isWithinWeakSubjectivityPeriod}: ArchivedStateBytes,
14
- {chainForkConfig, logger}: StatePreparationContext
14
+ {chainForkConfig, db, logger}: StatePreparationContext
15
15
  ): StateInitialization {
16
16
  const config = createBeaconConfig(chainForkConfig, metadata.genesisValidatorsRoot);
17
17
  return {
@@ -34,13 +34,28 @@ export function prepareArchivedStateInitialization(
34
34
  logger.warn("Checkpoint sync recommended, please use --help to see checkpoint sync options");
35
35
  }
36
36
  },
37
+ async initializeEarliestAvailableSlot(state) {
38
+ const stored = await db.earliestAvailableSlot.get();
39
+ // we bootstrap the node with archived db, use the previous earliestAvailableSLot
40
+ if (stored !== null) {
41
+ logger.verbose("Reusing persisted earliest available slot", {
42
+ anchorSlot: state.slot,
43
+ earliestAvailableSlot: stored,
44
+ });
45
+ return stored;
46
+ }
47
+ // legacy db: blockArchive.firstKey() is not a safe floor, a past checkpoint sync may have left a gap.
48
+ await db.earliestAvailableSlot.set(state.slot);
49
+ return state.slot;
50
+ },
37
51
  persist: null,
38
- log(state) {
52
+ log(state, nativeStateTransition) {
39
53
  logger.info("Initialized state from db", {
40
54
  slot: state.slot,
41
55
  epoch: computeEpochAtSlot(state.slot),
42
56
  stateRoot: toRootHex(state.hashTreeRoot()),
43
57
  isFinalized: true,
58
+ nativeStateTransition,
44
59
  });
45
60
  },
46
61
  };
@@ -1,6 +1,7 @@
1
1
  import {IBeaconDb} from "@lodestar/beacon-node";
2
2
  import {BeaconConfig, ChainForkConfig} from "@lodestar/config";
3
3
  import {IBeaconStateView, StateBytesMetadata, WeakSubjectivitySummary} from "@lodestar/state-transition";
4
+ import {Slot} from "@lodestar/types";
4
5
  import {Checkpoint} from "@lodestar/types/phase0";
5
6
  import {Logger} from "@lodestar/utils";
6
7
  import {GlobalArgs} from "../../../options/globalOptions.js";
@@ -18,7 +19,7 @@ export type StateInitializationOptions = Pick<
18
19
  | "ignoreWeakSubjectivityCheck"
19
20
  | "network"
20
21
  | "chain.nHistoricalStatesFileDataStore"
21
- | "chain.nativeStateView"
22
+ | "chain.nativeStateTransition"
22
23
  >;
23
24
 
24
25
  export type StatePreparationContext = {
@@ -53,6 +54,7 @@ export type StateInitialization = {
53
54
  config: BeaconConfig;
54
55
  isFinalized: boolean;
55
56
  validate: (state: IBeaconStateView) => void;
57
+ initializeEarliestAvailableSlot: (state: IBeaconStateView) => Promise<Slot>;
56
58
  persist: ((state: IBeaconStateView, stateBytes: Uint8Array) => Promise<void>) | null;
57
- log: (state: IBeaconStateView) => void;
59
+ log: (state: IBeaconStateView, nativeStateTransition: boolean) => void;
58
60
  };
@@ -31,7 +31,7 @@ export async function devHandler(args: IDevArgs & GlobalArgs): Promise<void> {
31
31
 
32
32
  // Note: defaults to network "dev", to all paths are custom and don't conflict with networks.
33
33
  // Flag --reset cleans up the custom dirs on dev stop
34
- const beaconDbDir = getBeaconPaths(args, network).dbDir;
34
+ const {dbDir: beaconDbDir, pubkeysFile} = getBeaconPaths(args, network);
35
35
  const validatorsDbDir = getValidatorPaths(args, network).validatorsDbDir;
36
36
 
37
37
  // Remove slashing protection db. Otherwise the validators won't be able to propose nor attest
@@ -39,6 +39,8 @@ export async function devHandler(args: IDevArgs & GlobalArgs): Promise<void> {
39
39
  if (args.genesisTime === undefined) {
40
40
  await rimraf(beaconDbDir);
41
41
  await rimraf(validatorsDbDir);
42
+ // Validators deposited in the previous run do not exist on the new chain
43
+ await rimraf(pubkeysFile);
42
44
  }
43
45
 
44
46
  mkdir(beaconDbDir);
@@ -12,6 +12,7 @@ export type ChainArgs = {
12
12
  "chain.blsVerifyAllMainThread"?: boolean;
13
13
  "chain.disableBlsBatchVerify"?: boolean;
14
14
  "chain.persistProducedBlocks"?: boolean;
15
+ "chain.persistProducedPayloadEnvelopes"?: boolean;
15
16
  "chain.persistInvalidSszObjects"?: boolean;
16
17
  // No need to define chain.persistInvalidSszObjects as part of ChainArgs
17
18
  // as this is defined as part of BeaconPaths
@@ -35,7 +36,7 @@ export type ChainArgs = {
35
36
  "chain.archiveDataEpochs"?: number;
36
37
  "chain.archiveMode": ArchiveMode;
37
38
  "chain.nHistoricalStatesFileDataStore"?: boolean;
38
- "chain.nativeStateView"?: boolean;
39
+ "chain.nativeStateTransition"?: boolean;
39
40
  "chain.maxBlockStates"?: number;
40
41
  "chain.maxCPStateEpochsInMemory"?: number;
41
42
  "chain.maxCPStateEpochsOnDisk"?: number;
@@ -53,6 +54,7 @@ export function parseArgs(args: ChainArgs & CircuitBreakerArgs): IBeaconNodeOpti
53
54
  blsVerifyAllMainThread: args["chain.blsVerifyAllMainThread"],
54
55
  disableBlsBatchVerify: args["chain.disableBlsBatchVerify"],
55
56
  persistProducedBlocks: args["chain.persistProducedBlocks"],
57
+ persistProducedPayloadEnvelopes: args["chain.persistProducedPayloadEnvelopes"],
56
58
  persistInvalidSszObjects: args["chain.persistInvalidSszObjects"],
57
59
  // biome-ignore lint/suspicious/noExplicitAny: We need to use `any` type here
58
60
  persistInvalidSszObjectsDir: undefined as any,
@@ -79,7 +81,7 @@ export function parseArgs(args: ChainArgs & CircuitBreakerArgs): IBeaconNodeOpti
79
81
  archiveMode: args["chain.archiveMode"] ?? defaultOptions.chain.archiveMode,
80
82
  nHistoricalStatesFileDataStore:
81
83
  args["chain.nHistoricalStatesFileDataStore"] ?? defaultOptions.chain.nHistoricalStatesFileDataStore,
82
- nativeStateView: args["chain.nativeStateView"] ?? defaultOptions.chain.nativeStateView,
84
+ nativeStateTransition: args["chain.nativeStateTransition"] ?? defaultOptions.chain.nativeStateTransition,
83
85
  maxBlockStates: args["chain.maxBlockStates"] ?? defaultOptions.chain.maxBlockStates,
84
86
  maxCPStateEpochsInMemory: args["chain.maxCPStateEpochsInMemory"] ?? defaultOptions.chain.maxCPStateEpochsInMemory,
85
87
  maxCPStateEpochsOnDisk: args["chain.maxCPStateEpochsOnDisk"] ?? defaultOptions.chain.maxCPStateEpochsOnDisk,
@@ -170,6 +172,13 @@ Will double processing times. Use only for debugging purposes.",
170
172
  group: "chain",
171
173
  },
172
174
 
175
+ "chain.persistProducedPayloadEnvelopes": {
176
+ hidden: true,
177
+ type: "boolean",
178
+ description: "Persist produced execution payload envelopes as SSZ files for debugging",
179
+ group: "chain",
180
+ },
181
+
173
182
  "chain.persistInvalidSszObjects": {
174
183
  hidden: true,
175
184
  type: "boolean",
@@ -318,11 +327,11 @@ Will double processing times. Use only for debugging purposes.",
318
327
  group: "chain",
319
328
  },
320
329
 
321
- "chain.nativeStateView": {
330
+ "chain.nativeStateTransition": {
322
331
  hidden: true,
323
- description: "Use native (Zig) BeaconStateView instead of JS implementation",
332
+ description: "Use native (Zig) state transition instead of JS implementation",
324
333
  type: "boolean",
325
- default: defaultOptions.chain.nativeStateView,
334
+ default: defaultOptions.chain.nativeStateTransition,
326
335
  group: "chain",
327
336
  },
328
337