@lodestar/beacon-node 1.50.0-dev.70314c9caa → 1.50.0-dev.773f874b05

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 (132) hide show
  1. package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
  2. package/lib/api/impl/beacon/blocks/index.js +6 -1
  3. package/lib/api/impl/beacon/blocks/index.js.map +1 -1
  4. package/lib/api/impl/validator/index.d.ts +1 -0
  5. package/lib/api/impl/validator/index.d.ts.map +1 -1
  6. package/lib/api/impl/validator/index.js +17 -1
  7. package/lib/api/impl/validator/index.js.map +1 -1
  8. package/lib/chain/archiveStore/archiveStore.js +1 -1
  9. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  10. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
  11. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  12. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -7
  13. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  14. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
  15. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  16. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
  17. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  18. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  19. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  20. package/lib/chain/archiveStore/interface.d.ts +1 -1
  21. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  22. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  23. package/lib/chain/blocks/verifyBlock.js +1 -1
  24. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  25. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +2 -1
  26. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  27. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +5 -4
  28. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  29. package/lib/chain/chain.d.ts +5 -4
  30. package/lib/chain/chain.d.ts.map +1 -1
  31. package/lib/chain/chain.js +29 -13
  32. package/lib/chain/chain.js.map +1 -1
  33. package/lib/chain/emitter.d.ts +7 -1
  34. package/lib/chain/emitter.d.ts.map +1 -1
  35. package/lib/chain/emitter.js +5 -0
  36. package/lib/chain/emitter.js.map +1 -1
  37. package/lib/chain/errors/envelopeReconstructionError.d.ts +5 -0
  38. package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -1
  39. package/lib/chain/errors/envelopeReconstructionError.js +2 -0
  40. package/lib/chain/errors/envelopeReconstructionError.js.map +1 -1
  41. package/lib/chain/forkChoice/index.d.ts.map +1 -1
  42. package/lib/chain/forkChoice/index.js +2 -0
  43. package/lib/chain/forkChoice/index.js.map +1 -1
  44. package/lib/chain/interface.d.ts +2 -2
  45. package/lib/chain/interface.d.ts.map +1 -1
  46. package/lib/chain/options.d.ts +1 -1
  47. package/lib/chain/options.d.ts.map +1 -1
  48. package/lib/chain/options.js +1 -1
  49. package/lib/chain/options.js.map +1 -1
  50. package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
  51. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  52. package/lib/chain/regen/regen.d.ts +2 -0
  53. package/lib/chain/regen/regen.d.ts.map +1 -1
  54. package/lib/chain/regen/regen.js +10 -4
  55. package/lib/chain/regen/regen.js.map +1 -1
  56. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +3 -2
  57. package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
  58. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +13 -13
  59. package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
  60. package/lib/chain/validatorMonitor.d.ts +5 -1
  61. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  62. package/lib/chain/validatorMonitor.js +64 -54
  63. package/lib/chain/validatorMonitor.js.map +1 -1
  64. package/lib/execution/engine/disabled.d.ts +0 -2
  65. package/lib/execution/engine/disabled.d.ts.map +1 -1
  66. package/lib/execution/engine/disabled.js +0 -6
  67. package/lib/execution/engine/disabled.js.map +1 -1
  68. package/lib/execution/engine/http.d.ts +1 -3
  69. package/lib/execution/engine/http.d.ts.map +1 -1
  70. package/lib/execution/engine/http.js +2 -17
  71. package/lib/execution/engine/http.js.map +1 -1
  72. package/lib/execution/engine/interface.d.ts +2 -4
  73. package/lib/execution/engine/interface.d.ts.map +1 -1
  74. package/lib/execution/engine/mock.d.ts +0 -2
  75. package/lib/execution/engine/mock.d.ts.map +1 -1
  76. package/lib/execution/engine/mock.js +0 -8
  77. package/lib/execution/engine/mock.js.map +1 -1
  78. package/lib/execution/engine/types.d.ts +0 -8
  79. package/lib/execution/engine/types.d.ts.map +1 -1
  80. package/lib/execution/engine/types.js.map +1 -1
  81. package/lib/metrics/metrics.d.ts +7 -3
  82. package/lib/metrics/metrics.d.ts.map +1 -1
  83. package/lib/metrics/metrics.js +4 -4
  84. package/lib/metrics/metrics.js.map +1 -1
  85. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +1 -1
  86. package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
  87. package/lib/node/nodejs.d.ts.map +1 -1
  88. package/lib/node/nodejs.js +25 -3
  89. package/lib/node/nodejs.js.map +1 -1
  90. package/lib/sync/range/batch.d.ts +6 -0
  91. package/lib/sync/range/batch.d.ts.map +1 -1
  92. package/lib/sync/range/batch.js +10 -0
  93. package/lib/sync/range/batch.js.map +1 -1
  94. package/lib/sync/range/chain.d.ts.map +1 -1
  95. package/lib/sync/range/chain.js +5 -1
  96. package/lib/sync/range/chain.js.map +1 -1
  97. package/lib/util/execution.d.ts +9 -11
  98. package/lib/util/execution.d.ts.map +1 -1
  99. package/lib/util/execution.js +5 -1
  100. package/lib/util/execution.js.map +1 -1
  101. package/package.json +16 -16
  102. package/src/api/impl/beacon/blocks/index.ts +7 -4
  103. package/src/api/impl/validator/index.ts +16 -2
  104. package/src/chain/archiveStore/archiveStore.ts +1 -1
  105. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -7
  106. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
  107. package/src/chain/archiveStore/historicalState/types.ts +2 -2
  108. package/src/chain/archiveStore/historicalState/worker.ts +1 -2
  109. package/src/chain/archiveStore/interface.ts +1 -1
  110. package/src/chain/blocks/verifyBlock.ts +1 -0
  111. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -3
  112. package/src/chain/chain.ts +35 -16
  113. package/src/chain/emitter.ts +7 -1
  114. package/src/chain/errors/envelopeReconstructionError.ts +3 -0
  115. package/src/chain/forkChoice/index.ts +2 -0
  116. package/src/chain/interface.ts +2 -2
  117. package/src/chain/options.ts +2 -2
  118. package/src/chain/produceBlock/computeNewStateRoot.ts +1 -1
  119. package/src/chain/regen/regen.ts +12 -4
  120. package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +20 -13
  121. package/src/chain/validatorMonitor.ts +75 -57
  122. package/src/execution/engine/disabled.ts +0 -8
  123. package/src/execution/engine/http.ts +1 -30
  124. package/src/execution/engine/interface.ts +2 -6
  125. package/src/execution/engine/mock.ts +1 -19
  126. package/src/execution/engine/types.ts +0 -10
  127. package/src/metrics/metrics.ts +21 -6
  128. package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +1 -1
  129. package/src/node/nodejs.ts +31 -3
  130. package/src/sync/range/batch.ts +11 -0
  131. package/src/sync/range/chain.ts +6 -1
  132. package/src/util/execution.ts +16 -8
@@ -9,27 +9,42 @@ import {RegistryMetricCreator} from "./utils/registryMetricCreator.js";
9
9
 
10
10
  export type Metrics = BeaconMetrics &
11
11
  ForkChoiceMetrics &
12
- BeaconStateTransitionMetrics &
13
- LodestarMetrics & {register: RegistryMetricCreator; close: () => void};
12
+ LodestarMetrics & {
13
+ /** Null when we use native state transition metrics instead */
14
+ stateTransition: BeaconStateTransitionMetrics | null;
15
+ register: RegistryMetricCreator;
16
+ close: () => void;
17
+ };
18
+
19
+ export type CreateMetricsOptions = {
20
+ /*
21
+ * Toggle inclusion of state transition metrics.
22
+ *
23
+ * False when native state transition is used, so we
24
+ * can grab metrics from the native implementation instead.
25
+ * */
26
+ includeStateTransitionMetrics?: boolean;
27
+ collectNodeMetrics?: boolean;
28
+ };
14
29
 
15
30
  export function createMetrics(
16
31
  opts: MetricsOptions,
17
32
  genesisTime: number,
18
33
  externalRegistries: Registry[] = [],
19
- {collectNodeMetrics = true}: {collectNodeMetrics?: boolean} = {}
34
+ createOpts: CreateMetricsOptions = {}
20
35
  ): Metrics {
21
36
  const register = new RegistryMetricCreator();
22
37
  const beacon = createBeaconMetrics(register);
23
38
  const forkChoice = getForkChoiceMetrics(register);
24
39
  const lodestar = createLodestarMetrics(register, opts.metadata, genesisTime);
25
- const stateTransition = getMetrics(register);
40
+ const stateTransition = createOpts.includeStateTransitionMetrics === false ? null : getMetrics(register);
26
41
 
27
42
  const onUnhandledRejection = (_error: unknown): void => {
28
43
  lodestar.unhandledPromiseRejections.inc();
29
44
  };
30
45
  process.on("unhandledRejection", onUnhandledRejection);
31
46
 
32
- const nodeJsMetricsClose = collectNodeMetrics ? collectNodeJSMetrics(register) : (): void => {};
47
+ const nodeJsMetricsClose = createOpts.collectNodeMetrics === false ? (): void => {} : collectNodeJSMetrics(register);
33
48
  const close = (): void => {
34
49
  process.removeListener("unhandledRejection", onUnhandledRejection);
35
50
  nodeJsMetricsClose();
@@ -46,7 +61,7 @@ export function createMetrics(
46
61
  ...beacon,
47
62
  ...forkChoice,
48
63
  ...lodestar,
49
- ...stateTransition,
64
+ stateTransition,
50
65
  register,
51
66
  close,
52
67
  };
@@ -53,7 +53,7 @@ export async function* onExecutionPayloadEnvelopesByRoot(
53
53
  const batch = requests.slice(i, i + MAX_BODIES_PER_REQUEST);
54
54
  let envelopesBytes: (Uint8Array | null)[];
55
55
  try {
56
- // By-root allows omission, so a mismatched envelope is left out rather than failing the response.
56
+ // By-root allows omission, so an envelope that cannot be rebuilt is left out rather than failing the response.
57
57
  envelopesBytes = await chain.getSerializedExecutionPayloadEnvelopes(batch, "omit");
58
58
  } catch (e) {
59
59
  if (e instanceof EnvelopeReconstructionError) {
@@ -1,6 +1,12 @@
1
1
  import {setMaxListeners} from "node:events";
2
2
  import {PrivateKey} from "@libp2p/interface";
3
3
  import {Registry} from "prom-client";
4
+ import {
5
+ init as initNativeMetrics,
6
+ registerLocalValidator as registerNativeLocalValidator,
7
+ scrapeMetrics as scrapeNativeMetrics,
8
+ unregisterLocalValidator as unregisterNativeLocalValidator,
9
+ } from "@chainsafe/lodestar-z/metrics";
4
10
  import {type PubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
5
11
  import {hasher} from "@chainsafe/persistent-merkle-tree";
6
12
  import {BeaconApiMethods} from "@lodestar/api/beacon/server";
@@ -171,7 +177,13 @@ export class BeaconNode {
171
177
  // monitoring relies on metrics data
172
178
  opts.monitoring.endpoint
173
179
  ) {
174
- metrics = createMetrics(opts.metrics, anchorState.genesisTime, metricsRegistries);
180
+ if (opts.chain.nativeStateTransition) {
181
+ initNativeMetrics();
182
+ }
183
+
184
+ metrics = createMetrics(opts.metrics, anchorState.genesisTime, metricsRegistries, {
185
+ includeStateTransitionMetrics: !opts.chain.nativeStateTransition,
186
+ });
175
187
  initBeaconMetrics(metrics, anchorState);
176
188
  // Since the db is instantiated before this, metrics must be injected manually afterwards
177
189
  db.setMetrics(metrics.db, metrics.flatFileStore);
@@ -185,7 +197,13 @@ export class BeaconNode {
185
197
  config,
186
198
  anchorState.genesisTime,
187
199
  logger.child({module: LoggerModule.vmon}),
188
- opts.validatorMonitor
200
+ opts.validatorMonitor,
201
+ opts.chain.nativeStateTransition
202
+ ? {
203
+ registerLocalValidator: registerNativeLocalValidator,
204
+ unregisterLocalValidator: unregisterNativeLocalValidator,
205
+ }
206
+ : null
189
207
  )
190
208
  : null;
191
209
 
@@ -303,7 +321,17 @@ export class BeaconNode {
303
321
  const metricsServer = opts.metrics.enabled
304
322
  ? await getHttpMetricsServer(opts.metrics, {
305
323
  register: (metrics as Metrics).register,
306
- getOtherMetrics: async () => Promise.all([network.scrapeMetrics(), chain.archiveStore.scrapeMetrics()]),
324
+ getOtherMetrics: async () => {
325
+ const otherMetrics = await Promise.all([network.scrapeMetrics(), chain.archiveStore.scrapeMetrics()]);
326
+ if (opts.chain.nativeStateTransition) {
327
+ try {
328
+ otherMetrics.push(scrapeNativeMetrics());
329
+ } catch (e) {
330
+ logger.warn("Failed to scrape native state-transition metrics", {}, e as Error);
331
+ }
332
+ }
333
+ return otherMetrics;
334
+ },
307
335
  logger: logger.child({module: LoggerModule.metrics}),
308
336
  })
309
337
  : null;
@@ -773,6 +773,7 @@ export class Batch {
773
773
  // remove any downloaded blocks and re-attempt
774
774
  // TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
775
775
  this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
776
+ this.resetRequests();
776
777
  }
777
778
 
778
779
  private onProcessingError(attempt: FailedAttempt): void {
@@ -784,6 +785,16 @@ export class Batch {
784
785
  // remove any downloaded blocks and re-attempt
785
786
  // TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
786
787
  this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
788
+ this.resetRequests();
789
+ }
790
+
791
+ /**
792
+ * After a partial download `requests` only cover the data still missing from the downloaded blocks,
793
+ * e.g. a single column. Once those blocks are dropped, request the whole batch again, otherwise
794
+ * every peer fails the retry for lack of blocks to validate the data against.
795
+ */
796
+ private resetRequests(): void {
797
+ this.requests = this.getRequests([]);
787
798
  }
788
799
 
789
800
  /** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */
@@ -225,6 +225,9 @@ export class SyncChain {
225
225
  Math.floor((localFinalizedEpoch - this.lastEpochWithProcessBlocks) / EPOCHS_PER_BATCH) * EPOCHS_PER_BATCH;
226
226
  this.advanceChain(lastEpochWithProcessBlocksAligned);
227
227
 
228
+ // stopSyncing() cleared the retry timer, but peers can still be in rate limit backoff
229
+ this.scheduleRateLimitBackoffRetry();
230
+
228
231
  // Potentially download new batches and process pending
229
232
  this.triggerBatchDownloader();
230
233
  this.triggerBatchProcessor();
@@ -417,8 +420,10 @@ export class SyncChain {
417
420
  this.rateLimitBackoffTimeout = setTimeout(
418
421
  () => {
419
422
  this.rateLimitBackoffTimeout = undefined;
420
- this.triggerBatchDownloader();
423
+ // Must run before the downloader, it drops expired peers without triggering a download. If it ran
424
+ // after, a backoff expiring in between would leave the peer idle with no retry scheduled.
421
425
  this.scheduleRateLimitBackoffRetry();
426
+ this.triggerBatchDownloader();
422
427
  },
423
428
  Math.max(0, retryAt - now)
424
429
  );
@@ -266,14 +266,15 @@ type SlotEnvelopeBytes = {slot: Slot; envelopeBytes: Uint8Array};
266
266
 
267
267
  type RangeEntry = ArchivedEnvelope & {slot: Slot};
268
268
 
269
- /** What a body root mismatch means on a given serving path */
270
- export type ReconstructMismatchPolicy = "throw" | "omit";
269
+ /** What an envelope that cannot be rebuilt (EL-unavailable body or body root mismatch) means on a given serving path */
270
+ export type ReconstructMissPolicy = "throw" | "omit";
271
271
 
272
- export type RebuildMiss =
273
- /** EL does not have the block, or has pruned its block access list */
274
- | {slot: Slot; reason: "unavailable"}
275
- /** An EL body does not hash to its stored root (local inconsistency) */
276
- | {slot: Slot; reason: "mismatch"; error: EnvelopeReconstructionError};
272
+ /**
273
+ * An archived envelope that could not be rebuilt. `"unavailable"`: the EL does not have the block or its
274
+ * block access list (BODY_UNAVAILABLE). `"mismatch"`: an EL body does not hash to its stored root, a local
275
+ * inconsistency (BODY_ROOT_MISMATCH). `error` carries the matching code for paths that surface it.
276
+ */
277
+ export type RebuildMiss = {slot: Slot; reason: "unavailable" | "mismatch"; error: EnvelopeReconstructionError};
277
278
 
278
279
  /**
279
280
  * Stream finalized envelopes over [startSlot, endSlot) as serialized bytes, rebuilding header
@@ -405,7 +406,14 @@ async function reconstructEnvelopesBatch(
405
406
  // A zero-length block access list cannot be valid, RLP encodes an empty list as 0xc0
406
407
  if (body == null || body.withdrawals == null || body.blockAccessList == null || body.blockAccessList.length === 0) {
407
408
  metrics?.payloadEnvelopeReconstruction.envelopes.inc({result: "unavailable"});
408
- return {slot, reason: "unavailable"};
409
+ return {
410
+ slot,
411
+ reason: "unavailable",
412
+ error: new EnvelopeReconstructionError(
413
+ {code: EnvelopeReconstructionErrorCode.BODY_UNAVAILABLE, slot},
414
+ `execution client cannot serve the payload body or block access list for archived envelope slot=${slot}`
415
+ ),
416
+ };
409
417
  }
410
418
  try {
411
419
  const envelope = signedHeaderEnvelopeToFull(headerEnvelope, {