@lodestar/beacon-node 1.50.0-dev.040a952dd7 → 1.50.0-dev.199b9d3a1f

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 (61) hide show
  1. package/lib/chain/archiveStore/archiveStore.js +1 -1
  2. package/lib/chain/archiveStore/archiveStore.js.map +1 -1
  3. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
  4. package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
  5. package/lib/chain/archiveStore/historicalState/getHistoricalState.js +7 -5
  6. package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
  7. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
  8. package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
  9. package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
  10. package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
  11. package/lib/chain/archiveStore/historicalState/worker.js +1 -1
  12. package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
  13. package/lib/chain/archiveStore/interface.d.ts +1 -1
  14. package/lib/chain/archiveStore/interface.d.ts.map +1 -1
  15. package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
  16. package/lib/chain/blocks/verifyBlock.js +1 -1
  17. package/lib/chain/blocks/verifyBlock.js.map +1 -1
  18. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +1 -2
  19. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
  20. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +4 -5
  21. package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
  22. package/lib/chain/chain.d.ts.map +1 -1
  23. package/lib/chain/chain.js +0 -18
  24. package/lib/chain/chain.js.map +1 -1
  25. package/lib/chain/options.d.ts +1 -1
  26. package/lib/chain/options.d.ts.map +1 -1
  27. package/lib/chain/options.js +1 -1
  28. package/lib/chain/options.js.map +1 -1
  29. package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
  30. package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
  31. package/lib/chain/regen/regen.d.ts +0 -2
  32. package/lib/chain/regen/regen.d.ts.map +1 -1
  33. package/lib/chain/regen/regen.js +4 -10
  34. package/lib/chain/regen/regen.js.map +1 -1
  35. package/lib/chain/validatorMonitor.d.ts +1 -5
  36. package/lib/chain/validatorMonitor.d.ts.map +1 -1
  37. package/lib/chain/validatorMonitor.js +54 -64
  38. package/lib/chain/validatorMonitor.js.map +1 -1
  39. package/lib/metrics/metrics.d.ts +3 -7
  40. package/lib/metrics/metrics.d.ts.map +1 -1
  41. package/lib/metrics/metrics.js +4 -4
  42. package/lib/metrics/metrics.js.map +1 -1
  43. package/lib/node/nodejs.d.ts.map +1 -1
  44. package/lib/node/nodejs.js +3 -25
  45. package/lib/node/nodejs.js.map +1 -1
  46. package/package.json +15 -15
  47. package/src/chain/archiveStore/archiveStore.ts +1 -1
  48. package/src/chain/archiveStore/historicalState/getHistoricalState.ts +7 -5
  49. package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
  50. package/src/chain/archiveStore/historicalState/types.ts +2 -2
  51. package/src/chain/archiveStore/historicalState/worker.ts +2 -1
  52. package/src/chain/archiveStore/interface.ts +1 -1
  53. package/src/chain/blocks/verifyBlock.ts +0 -1
  54. package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +3 -6
  55. package/src/chain/chain.ts +0 -21
  56. package/src/chain/options.ts +2 -2
  57. package/src/chain/produceBlock/computeNewStateRoot.ts +1 -1
  58. package/src/chain/regen/regen.ts +4 -12
  59. package/src/chain/validatorMonitor.ts +57 -75
  60. package/src/metrics/metrics.ts +6 -21
  61. package/src/node/nodejs.ts +3 -31
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "bugs": {
12
12
  "url": "https://github.com/ChainSafe/lodestar/issues"
13
13
  },
14
- "version": "1.50.0-dev.040a952dd7",
14
+ "version": "1.50.0-dev.199b9d3a1f",
15
15
  "type": "module",
16
16
  "exports": {
17
17
  ".": {
@@ -127,17 +127,17 @@
127
127
  "@libp2p/prometheus-metrics": "^5.0.28",
128
128
  "@libp2p/tcp": "^11.0.27",
129
129
  "@libp2p/utils": "^7.4.0",
130
- "@lodestar/api": "^1.50.0-dev.040a952dd7",
131
- "@lodestar/config": "^1.50.0-dev.040a952dd7",
132
- "@lodestar/db": "^1.50.0-dev.040a952dd7",
133
- "@lodestar/fork-choice": "^1.50.0-dev.040a952dd7",
134
- "@lodestar/logger": "^1.50.0-dev.040a952dd7",
135
- "@lodestar/params": "^1.50.0-dev.040a952dd7",
136
- "@lodestar/reqresp": "^1.50.0-dev.040a952dd7",
137
- "@lodestar/state-transition": "^1.50.0-dev.040a952dd7",
138
- "@lodestar/types": "^1.50.0-dev.040a952dd7",
139
- "@lodestar/utils": "^1.50.0-dev.040a952dd7",
140
- "@lodestar/validator": "^1.50.0-dev.040a952dd7",
130
+ "@lodestar/api": "^1.50.0-dev.199b9d3a1f",
131
+ "@lodestar/config": "^1.50.0-dev.199b9d3a1f",
132
+ "@lodestar/db": "^1.50.0-dev.199b9d3a1f",
133
+ "@lodestar/fork-choice": "^1.50.0-dev.199b9d3a1f",
134
+ "@lodestar/logger": "^1.50.0-dev.199b9d3a1f",
135
+ "@lodestar/params": "^1.50.0-dev.199b9d3a1f",
136
+ "@lodestar/reqresp": "^1.50.0-dev.199b9d3a1f",
137
+ "@lodestar/state-transition": "^1.50.0-dev.199b9d3a1f",
138
+ "@lodestar/types": "^1.50.0-dev.199b9d3a1f",
139
+ "@lodestar/utils": "^1.50.0-dev.199b9d3a1f",
140
+ "@lodestar/validator": "^1.50.0-dev.199b9d3a1f",
141
141
  "@multiformats/multiaddr": "^13.0.1",
142
142
  "datastore-core": "^12.0.1",
143
143
  "datastore-level": "^13.0.1",
@@ -158,8 +158,8 @@
158
158
  "devDependencies": {
159
159
  "@libp2p/interface-internal": "^3.1.12",
160
160
  "@libp2p/logger": "^6.2.13",
161
- "@lodestar/spec-test-util": "^1.50.0-dev.040a952dd7",
162
- "@lodestar/test-utils": "^1.50.0-dev.040a952dd7",
161
+ "@lodestar/spec-test-util": "^1.50.0-dev.199b9d3a1f",
162
+ "@lodestar/test-utils": "^1.50.0-dev.199b9d3a1f",
163
163
  "@types/js-yaml": "^4.0.5",
164
164
  "@types/qs": "^6.9.7",
165
165
  "@types/tmp": "^0.2.3",
@@ -174,5 +174,5 @@
174
174
  "beacon",
175
175
  "blockchain"
176
176
  ],
177
- "gitHead": "156629b17ad44c8a312b54015fd953e94b4874e6"
177
+ "gitHead": "82a54df5956f25254f0d96afe6eae94d93554b5e"
178
178
  }
@@ -148,7 +148,7 @@ export class ArchiveStore {
148
148
  genesisTime: this.chain.clock.genesisTime,
149
149
  dbLocation: this.opts.dbName,
150
150
  dataColumnDir: this.opts.dataColumnDir,
151
- nativeStateTransition: this.opts.nativeStateTransition ?? false,
151
+ nativeStateView: this.opts.nativeStateView ?? false,
152
152
  },
153
153
  config: this.chain.config,
154
154
  metrics: this.metrics,
@@ -17,7 +17,7 @@ export async function getNearestState(
17
17
  slot: number,
18
18
  config: BeaconConfig,
19
19
  db: IBeaconDb,
20
- nativeStateTransition: boolean
20
+ nativeStateView: boolean
21
21
  ): Promise<IBeaconStateView> {
22
22
  const stateBytesArr = await db.stateArchive.binaries({limit: 1, lte: slot, reverse: true});
23
23
  if (!stateBytesArr.length) {
@@ -25,7 +25,9 @@ export async function getNearestState(
25
25
  }
26
26
 
27
27
  const stateBytes = stateBytesArr[0];
28
- return createBeaconStateViewForHistoricalRegen({nativeStateTransition: nativeStateTransition, config, stateBytes});
28
+ return nativeStateView
29
+ ? createBeaconStateViewForHistoricalRegen({useNative: true, stateBytes})
30
+ : createBeaconStateViewForHistoricalRegen({useNative: false, config, stateBytes});
29
31
  }
30
32
 
31
33
  /**
@@ -35,13 +37,13 @@ export async function getHistoricalState(
35
37
  slot: number,
36
38
  config: BeaconConfig,
37
39
  db: IBeaconDb,
38
- nativeStateTransition: boolean,
40
+ nativeStateView: boolean,
39
41
  metrics?: HistoricalStateRegenMetrics
40
42
  ): Promise<Uint8Array> {
41
43
  const regenTimer = metrics?.regenTime.startTimer();
42
44
 
43
45
  const loadStateTimer = metrics?.loadStateTime.startTimer();
44
- let state = await getNearestState(slot, config, db, nativeStateTransition).catch((e) => {
46
+ let state = await getNearestState(slot, config, db, nativeStateView).catch((e) => {
45
47
  metrics?.regenErrorCount.inc({reason: RegenErrorType.loadState});
46
48
  throw e;
47
49
  });
@@ -52,7 +54,7 @@ export async function getHistoricalState(
52
54
  for await (const block of db.blockArchive.valuesStream({gt: state.slot, lte: slot})) {
53
55
  try {
54
56
  state = state.stateTransition(
55
- {block},
57
+ block,
56
58
  {
57
59
  verifyProposer: false,
58
60
  verifySignatures: false,
@@ -36,7 +36,7 @@ export class HistoricalStateRegen implements HistoricalStateWorkerApi {
36
36
  dataColumnDir: modules.opts.dataColumnDir,
37
37
  metricsEnabled: Boolean(modules.metrics),
38
38
  loggerOpts: modules.logger.toOpts(),
39
- nativeStateTransition: modules.opts.nativeStateTransition,
39
+ nativeStateView: modules.opts.nativeStateView,
40
40
  };
41
41
 
42
42
  const worker = new Worker(path.join(WORKER_DIR, "worker.js"), {
@@ -8,7 +8,7 @@ export type HistoricalStateRegenInitModules = {
8
8
  genesisTime: number;
9
9
  dbLocation: string;
10
10
  dataColumnDir: string;
11
- nativeStateTransition: boolean;
11
+ nativeStateView: boolean;
12
12
  };
13
13
  config: BeaconConfig;
14
14
  logger: LoggerNode;
@@ -29,7 +29,7 @@ export type HistoricalStateWorkerData = {
29
29
  dataColumnDir: string;
30
30
  metricsEnabled: boolean;
31
31
  loggerOpts: LoggerNodeOpts;
32
- nativeStateTransition: boolean;
32
+ nativeStateView: boolean;
33
33
  };
34
34
 
35
35
  export type HistoricalStateWorkerApi = {
@@ -36,6 +36,7 @@ const abortController = new AbortController();
36
36
  const metricsRegister = workerData.metricsEnabled ? new RegistryMetricCreator() : null;
37
37
  let historicalStateRegenMetrics: HistoricalStateRegenMetrics | undefined;
38
38
  let queueMetrics: QueueMetrics | undefined;
39
+
39
40
  if (metricsRegister) {
40
41
  const closeMetrics = collectNodeJSMetrics(metricsRegister, "lodestar_historical_state_worker_");
41
42
  abortController.signal.addEventListener("abort", closeMetrics, {once: true});
@@ -64,7 +65,7 @@ const api: HistoricalStateWorkerApi = {
64
65
  historicalStateRegenMetrics?.regenRequestCount.inc();
65
66
 
66
67
  const stateBytes = await queue.push<Uint8Array>(() =>
67
- getHistoricalState(slot, config, db, workerData.nativeStateTransition, historicalStateRegenMetrics)
68
+ getHistoricalState(slot, config, db, workerData.nativeStateView, historicalStateRegenMetrics)
68
69
  );
69
70
  const result = Transfer(stateBytes, [stateBytes.buffer]) as unknown as Uint8Array;
70
71
 
@@ -25,7 +25,7 @@ export type ArchiveStoreOpts = StatesArchiveOpts & {
25
25
  archiveDataEpochs?: number;
26
26
  pruneHistory?: boolean;
27
27
  serveHistoricalState?: boolean;
28
- nativeStateTransition?: boolean;
28
+ nativeStateView?: boolean;
29
29
  };
30
30
 
31
31
  export type ProposalStats = {
@@ -188,7 +188,6 @@ export async function verifyBlocksInEpoch(
188
188
  blockInputs,
189
189
  // hack availability for state transition eval as availability is separately determined
190
190
  blocks.map(() => DataAvailabilityStatus.Available),
191
- this.serializedCache,
192
191
  this.logger,
193
192
  this.metrics,
194
193
  this.validatorMonitor,
@@ -7,7 +7,6 @@ import {
7
7
  import {ErrorAborted, Logger, byteArrayEquals} from "@lodestar/utils";
8
8
  import {Metrics} from "../../metrics/index.js";
9
9
  import {nextEventLoop} from "../../util/eventLoop.js";
10
- import {SerializedCache} from "../../util/serializedCache.js";
11
10
  import {BlockError, BlockErrorCode} from "../errors/index.js";
12
11
  import {BlockProcessOpts} from "../options.js";
13
12
  import {ValidatorMonitor} from "../validatorMonitor.js";
@@ -26,7 +25,6 @@ export async function verifyBlocksStateTransitionOnly(
26
25
  preState0: IBeaconStateView,
27
26
  blocks: IBlockInput[],
28
27
  dataAvailabilityStatuses: DataAvailabilityStatus[],
29
- serializedCache: SerializedCache,
30
28
  logger: Logger,
31
29
  metrics: Metrics | null,
32
30
  validatorMonitor: ValidatorMonitor | null,
@@ -39,8 +37,7 @@ export async function verifyBlocksStateTransitionOnly(
39
37
 
40
38
  for (let i = 0; i < blocks.length; i++) {
41
39
  const {validProposerSignature, validSignatures} = opts;
42
- const blockInput = blocks[i];
43
- const block = blockInput.getBlock();
40
+ const block = blocks[i].getBlock();
44
41
  const preState = i === 0 ? preState0 : postStates[i - 1];
45
42
  const dataAvailabilityStatus = dataAvailabilityStatuses[i];
46
43
 
@@ -50,7 +47,7 @@ export async function verifyBlocksStateTransitionOnly(
50
47
  let postState: IBeaconStateView;
51
48
  try {
52
49
  postState = preState.stateTransition(
53
- {block, ssz: serializedCache.get(block)},
50
+ block,
54
51
  {
55
52
  // NOTE: Assume valid for now while sending payload to execution engine in parallel
56
53
  // Latter verifyBlocksInEpoch() will make sure that payload is indeed valid
@@ -63,7 +60,7 @@ export async function verifyBlocksStateTransitionOnly(
63
60
  verifySignatures: !useBlsBatchVerify && !validSignatures,
64
61
  dontTransferCache: false,
65
62
  },
66
- {metrics: metrics?.stateTransition, validatorMonitor}
63
+ {metrics, validatorMonitor}
67
64
  );
68
65
  } catch (e) {
69
66
  throw new BlockError(block, {
@@ -432,7 +432,6 @@ export class BeaconChain implements IBeaconChain {
432
432
  blockStateCache,
433
433
  checkpointStateCache,
434
434
  seenBlockInputCache: this.seenBlockInputCache,
435
- serializedCache: this.serializedCache,
436
435
  db,
437
436
  metrics,
438
437
  validatorMonitor,
@@ -703,26 +702,6 @@ export class BeaconChain implements IBeaconChain {
703
702
  stateRoot: RootHex,
704
703
  opts?: StateGetOpts
705
704
  ): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
706
- const finalizedBlock = this.forkChoice.getFinalizedBlock();
707
- const finalizedCheckpoint = this.forkChoice.getFinalizedCheckpoint();
708
- // Checkpoint state only equals the block post-state if the block is at the epoch start slot
709
- if (
710
- finalizedBlock.stateRoot === stateRoot &&
711
- finalizedBlock.slot === computeStartSlotAtEpoch(finalizedCheckpoint.epoch)
712
- ) {
713
- const state = this.regen.getCheckpointStateSync({
714
- epoch: finalizedCheckpoint.epoch,
715
- rootHex: finalizedCheckpoint.rootHex,
716
- });
717
- if (state) {
718
- return {
719
- state,
720
- executionOptimistic: isOptimisticBlock(finalizedBlock),
721
- finalized: finalizedCheckpoint.epoch !== GENESIS_EPOCH,
722
- };
723
- }
724
- }
725
-
726
705
  if (opts?.allowRegen) {
727
706
  const state = await this.regen.getState(stateRoot, RegenCaller.restApi);
728
707
  const block = this.forkChoice.getBlockDefaultStatus(
@@ -52,7 +52,7 @@ export type IChainOptions = BlockProcessOpts &
52
52
  minSameMessageSignatureSetsToBatch: number;
53
53
  archiveDateEpochs?: number;
54
54
  nHistoricalStatesFileDataStore?: boolean;
55
- nativeStateTransition?: boolean;
55
+ nativeStateView?: boolean;
56
56
  /** Builder circuit breaker fault inspection window in slots */
57
57
  faultInspectionWindow?: number;
58
58
  /** Canonical EMPTY blocks allowed per `faultInspectionWindow` observed blocks */
@@ -131,7 +131,7 @@ export const defaultChainOptions: IChainOptions = {
131
131
  // - users can prune the persisted checkpoint state files manually to save disc space
132
132
  // - it helps debug easier when network is unfinalized
133
133
  nHistoricalStatesFileDataStore: true,
134
- nativeStateTransition: false,
134
+ nativeStateView: false,
135
135
  maxBlockStates: DEFAULT_MAX_BLOCK_STATES,
136
136
  maxCPStateEpochsInMemory: DEFAULT_MAX_CP_STATE_EPOCHS_IN_MEMORY,
137
137
  maxCPStateEpochsOnDisk: DEFAULT_MAX_CP_STATE_ON_DISK,
@@ -16,7 +16,7 @@ export function computeNewStateRoot(
16
16
  const signedBlock = {message: block, signature: EMPTY_SIGNATURE};
17
17
  const {newStateRoot, proposerReward, postState, hashTreeRootTime} = state.computeNewStateRoot(
18
18
  {block: signedBlock},
19
- {metrics: metrics?.stateTransition}
19
+ {metrics}
20
20
  );
21
21
 
22
22
  metrics?.stateHashTreeRootTime.observe({source: StateHashTreeRootSource.computeNewStateRoot}, hashTreeRootTime);
@@ -14,7 +14,6 @@ import {Logger, fromHex, toRootHex} from "@lodestar/utils";
14
14
  import {IBeaconDb} from "../../db/index.js";
15
15
  import {Metrics} from "../../metrics/index.js";
16
16
  import {nextEventLoop} from "../../util/eventLoop.js";
17
- import {SerializedCache} from "../../util/serializedCache.js";
18
17
  import {getCheckpointFromState} from "../blocks/utils/checkpoint.js";
19
18
  import {ChainEvent, ChainEventEmitter} from "../emitter.js";
20
19
  import {SeenBlockInput} from "../seenCache/seenGossipBlockInput.js";
@@ -29,7 +28,6 @@ export type RegenModules = {
29
28
  blockStateCache: BlockStateCache;
30
29
  checkpointStateCache: CheckpointStateCache;
31
30
  seenBlockInputCache: SeenBlockInput;
32
- serializedCache: SerializedCache;
33
31
  config: ChainForkConfig;
34
32
  emitter: ChainEventEmitter;
35
33
  logger: Logger;
@@ -237,7 +235,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {
237
235
  // We are only running the state transition to get a specific state's data.
238
236
  // stateTransition() does the clone() inside, transfer cache to make the regen faster
239
237
  state = state.stateTransition(
240
- {block, ssz: this.modules.serializedCache.get(block)},
238
+ block,
241
239
  {
242
240
  // Replay previously imported blocks, assume valid and available
243
241
  executionPayloadStatus: ExecutionPayloadStatus.valid,
@@ -247,7 +245,7 @@ export class StateRegenerator implements IStateRegeneratorInternal {
247
245
  verifySignatures: false,
248
246
  dontTransferCache: false,
249
247
  },
250
- {metrics: this.modules.metrics?.stateTransition, validatorMonitor: this.modules.validatorMonitor}
248
+ this.modules
251
249
  );
252
250
 
253
251
  const hashTreeRootTimer = this.modules.metrics?.stateHashTreeRootTime.startTimer({
@@ -318,10 +316,7 @@ async function processSlotsByCheckpoint(
318
316
  ): Promise<IBeaconStateView> {
319
317
  let postState = await processSlotsToNearestCheckpoint(modules, preState, slot, regenCaller, opts);
320
318
  if (postState.slot < slot) {
321
- postState = postState.processSlots(slot, opts, {
322
- metrics: modules.metrics?.stateTransition,
323
- validatorMonitor: modules.validatorMonitor,
324
- });
319
+ postState = postState.processSlots(slot, opts, modules);
325
320
  }
326
321
  return postState;
327
322
  }
@@ -366,10 +361,7 @@ export async function processSlotsToNearestCheckpoint(
366
361
  caller: regenCaller,
367
362
  });
368
363
  // processSlots calls .clone() before mutating
369
- postState = postState.processSlots(nextEpochSlot, opts, {
370
- metrics: metrics?.stateTransition,
371
- validatorMonitor: modules.validatorMonitor,
372
- });
364
+ postState = postState.processSlots(nextEpochSlot, opts, modules);
373
365
  metrics?.epochTransitionByCaller.inc({caller: regenCaller});
374
366
 
375
367
  // this is usually added when we prepare for next slot or validate gossip block
@@ -123,11 +123,6 @@ export type ValidatorMonitorOpts = {
123
123
  validatorMonitorLogs?: boolean;
124
124
  };
125
125
 
126
- export type NativeValidatorMonitor = {
127
- registerLocalValidator(index: ValidatorIndex): void;
128
- unregisterLocalValidator(index: ValidatorIndex): void;
129
- };
130
-
131
126
  export const defaultValidatorMonitorOpts: ValidatorMonitorOpts = {
132
127
  validatorMonitorLogs: false,
133
128
  };
@@ -301,8 +296,7 @@ export function createValidatorMonitor(
301
296
  config: ChainForkConfig,
302
297
  genesisTime: number,
303
298
  logger: Logger,
304
- opts: ValidatorMonitorOpts,
305
- nativeValidatorMonitor: NativeValidatorMonitor | null = null
299
+ opts: ValidatorMonitorOpts
306
300
  ): ValidatorMonitor {
307
301
  const logLevel = opts.validatorMonitorLogs ? LogLevel.info : LogLevel.debug;
308
302
  const log: LogHandler = (message: string, context?: LogData) => {
@@ -333,23 +327,18 @@ export function createValidatorMonitor(
333
327
  }));
334
328
 
335
329
  let lastRegisteredStatusEpoch = -1;
336
- let lastAttestationSummaryEpoch = -1;
337
330
 
338
331
  // Track validator additions/removals per epoch for logging
339
332
  const addedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
340
333
  const removedValidatorsInEpoch: Set<ValidatorIndex> = new Set();
341
334
 
342
- const shouldRegisterStateDerivedMetrics = nativeValidatorMonitor === null;
343
- const validatorMonitorMetrics = metricsRegister
344
- ? createValidatorMonitorMetrics(metricsRegister, shouldRegisterStateDerivedMetrics)
345
- : null;
335
+ const validatorMonitorMetrics = metricsRegister ? createValidatorMonitorMetrics(metricsRegister) : null;
346
336
 
347
337
  const validatorMonitor: ValidatorMonitor = {
348
338
  registerLocalValidator(index) {
349
339
  const isNewValidator = !validators.has(index);
350
340
  validators.getOrDefault(index).lastRegisteredTimeMs = Date.now();
351
341
  if (isNewValidator) {
352
- nativeValidatorMonitor?.registerLocalValidator(index);
353
342
  addedValidatorsInEpoch.add(index);
354
343
  }
355
344
  },
@@ -377,7 +366,7 @@ export function createValidatorMonitor(
377
366
  // Track total balance instead of per-validator balance to reduce metric cardinality
378
367
  let totalBalance = 0;
379
368
 
380
- for (const index of validators.keys()) {
369
+ for (const [index, monitoredValidator] of validators.entries()) {
381
370
  // We subtract two from the state of the epoch that generated these summaries.
382
371
  //
383
372
  // - One to account for it being the previous epoch.
@@ -391,29 +380,68 @@ export function createValidatorMonitor(
391
380
  );
392
381
 
393
382
  if (summary.isPrevSourceAttester) {
394
- validatorMonitorMetrics?.prevEpochOnChainSourceAttesterHit?.inc();
383
+ validatorMonitorMetrics?.prevEpochOnChainSourceAttesterHit.inc();
395
384
  } else {
396
- validatorMonitorMetrics?.prevEpochOnChainSourceAttesterMiss?.inc();
385
+ validatorMonitorMetrics?.prevEpochOnChainSourceAttesterMiss.inc();
397
386
  }
398
387
  if (summary.isPrevHeadAttester) {
399
- validatorMonitorMetrics?.prevEpochOnChainHeadAttesterHit?.inc();
388
+ validatorMonitorMetrics?.prevEpochOnChainHeadAttesterHit.inc();
400
389
  } else {
401
- validatorMonitorMetrics?.prevEpochOnChainHeadAttesterMiss?.inc();
390
+ validatorMonitorMetrics?.prevEpochOnChainHeadAttesterMiss.inc();
402
391
  }
403
392
  if (summary.isPrevTargetAttester) {
404
- validatorMonitorMetrics?.prevEpochOnChainTargetAttesterHit?.inc();
393
+ validatorMonitorMetrics?.prevEpochOnChainTargetAttesterHit.inc();
405
394
  } else {
406
- validatorMonitorMetrics?.prevEpochOnChainTargetAttesterMiss?.inc();
395
+ validatorMonitorMetrics?.prevEpochOnChainTargetAttesterMiss.inc();
396
+ }
397
+
398
+ const prevEpochSummary = monitoredValidator.summaries.get(previousEpoch);
399
+ const attestationCorrectHead = prevEpochSummary?.attestationCorrectHead;
400
+ if (attestationCorrectHead !== null && attestationCorrectHead !== undefined) {
401
+ if (attestationCorrectHead) {
402
+ validatorMonitorMetrics?.prevOnChainAttesterCorrectHead.inc();
403
+ } else {
404
+ validatorMonitorMetrics?.prevOnChainAttesterIncorrectHead.inc();
405
+ }
406
+ }
407
+
408
+ const attestationMinBlockInclusionDistance = prevEpochSummary?.attestationMinBlockInclusionDistance;
409
+ const inclusionDistance =
410
+ attestationMinBlockInclusionDistance != null && attestationMinBlockInclusionDistance > 0
411
+ ? // altair, attestation is not missed
412
+ attestationMinBlockInclusionDistance
413
+ : summary.inclusionDistance
414
+ ? // phase0, this is from the state transition
415
+ summary.inclusionDistance
416
+ : null;
417
+
418
+ if (inclusionDistance !== null) {
419
+ validatorMonitorMetrics?.prevEpochOnChainInclusionDistance.observe(inclusionDistance);
420
+ validatorMonitorMetrics?.prevEpochOnChainAttesterHit.inc();
421
+ } else {
422
+ validatorMonitorMetrics?.prevEpochOnChainAttesterMiss.inc();
407
423
  }
408
424
 
409
425
  const balance = balances?.[index];
410
426
  if (balance !== undefined) {
411
427
  totalBalance += balance;
412
428
  }
429
+
430
+ if (!summary.isPrevSourceAttester || !summary.isPrevTargetAttester || !summary.isPrevHeadAttester) {
431
+ log("Failed attestation in previous epoch", {
432
+ validator: index,
433
+ prevEpoch: currentEpoch - 1,
434
+ isPrevSourceAttester: summary.isPrevSourceAttester,
435
+ isPrevHeadAttester: summary.isPrevHeadAttester,
436
+ isPrevTargetAttester: summary.isPrevTargetAttester,
437
+ // inclusionDistance is not available in summary since altair
438
+ inclusionDistance,
439
+ });
440
+ }
413
441
  }
414
442
 
415
443
  if (balances !== undefined) {
416
- validatorMonitorMetrics?.prevEpochOnChainBalance?.set(totalBalance);
444
+ validatorMonitorMetrics?.prevEpochOnChainBalance.set(totalBalance);
417
445
  }
418
446
  },
419
447
 
@@ -704,7 +732,6 @@ export function createValidatorMonitor(
704
732
  // Prune validators not seen in a while
705
733
  for (const [index, validator] of validators.entries()) {
706
734
  if (Date.now() - validator.lastRegisteredTimeMs > retainRegisteredValidatorsMs) {
707
- nativeValidatorMonitor?.unregisterLocalValidator(index);
708
735
  validators.delete(index);
709
736
  removedValidatorsInEpoch.add(index);
710
737
  }
@@ -740,38 +767,6 @@ export function createValidatorMonitor(
740
767
  return;
741
768
  }
742
769
 
743
- // On-chain attestation summary of prevEpoch. Reads only the epoch summaries filled by
744
- // registerAttestationInBlock(), so it works with both TS and native state transition.
745
- if (prevEpoch > lastAttestationSummaryEpoch) {
746
- lastAttestationSummaryEpoch = prevEpoch;
747
-
748
- for (const monitoredValidator of validators.values()) {
749
- const prevEpochSummary = monitoredValidator.summaries.get(prevEpoch);
750
- const attestationCorrectHead = prevEpochSummary?.attestationCorrectHead;
751
- if (attestationCorrectHead !== null && attestationCorrectHead !== undefined) {
752
- if (attestationCorrectHead) {
753
- validatorMonitorMetrics?.prevOnChainAttesterCorrectHead.inc();
754
- } else {
755
- validatorMonitorMetrics?.prevOnChainAttesterIncorrectHead.inc();
756
- }
757
- }
758
-
759
- const attestationMinBlockInclusionDistance = prevEpochSummary?.attestationMinBlockInclusionDistance;
760
- const inclusionDistance =
761
- attestationMinBlockInclusionDistance != null && attestationMinBlockInclusionDistance > 0
762
- ? // altair, attestation is not missed
763
- attestationMinBlockInclusionDistance
764
- : null;
765
-
766
- if (inclusionDistance !== null) {
767
- validatorMonitorMetrics?.prevEpochOnChainInclusionDistance.observe(inclusionDistance);
768
- validatorMonitorMetrics?.prevEpochOnChainAttesterHit.inc();
769
- } else {
770
- validatorMonitorMetrics?.prevEpochOnChainAttesterMiss.inc();
771
- }
772
- }
773
- }
774
-
775
770
  const rootCache = new RootHexCache(headState);
776
771
 
777
772
  if (isStatePostAltair(headState)) {
@@ -789,17 +784,6 @@ export function createValidatorMonitor(
789
784
  epoch: prevEpoch,
790
785
  summary,
791
786
  });
792
-
793
- if (!flags.timelySource || !flags.timelyTarget || !flags.timelyHead) {
794
- log("Failed attestation in previous epoch", {
795
- validator: index,
796
- prevEpoch,
797
- isPrevSourceAttester: flags.timelySource,
798
- isPrevHeadAttester: flags.timelyHead,
799
- isPrevTargetAttester: flags.timelyTarget,
800
- inclusionDistance: validator.summaries.get(prevEpoch)?.attestationMinBlockInclusionDistance ?? null,
801
- });
802
- }
803
787
  }
804
788
  }
805
789
 
@@ -1214,9 +1198,7 @@ export class RootHexCache {
1214
1198
  }
1215
1199
  }
1216
1200
 
1217
- function createValidatorMonitorMetrics(register: RegistryMetricCreator, registerStateDerivedMetrics = true) {
1218
- const stateDerivedRegister = registerStateDerivedMetrics ? register : null;
1219
-
1201
+ function createValidatorMonitorMetrics(register: RegistryMetricCreator) {
1220
1202
  return {
1221
1203
  validatorsConnected: register.gauge({
1222
1204
  name: "validator_monitor_validators",
@@ -1235,7 +1217,7 @@ function createValidatorMonitorMetrics(register: RegistryMetricCreator, register
1235
1217
  }),
1236
1218
 
1237
1219
  // Validator Monitor Metrics (per-epoch summaries)
1238
- prevEpochOnChainBalance: stateDerivedRegister?.gauge({
1220
+ prevEpochOnChainBalance: register.gauge({
1239
1221
  name: "validator_monitor_prev_epoch_on_chain_balance",
1240
1222
  help: "Total balance of all monitored validators after an epoch",
1241
1223
  }),
@@ -1247,19 +1229,19 @@ function createValidatorMonitorMetrics(register: RegistryMetricCreator, register
1247
1229
  name: "validator_monitor_prev_epoch_on_chain_attester_miss_total",
1248
1230
  help: "Incremented if validator's submitted attestation is not included in any blocks",
1249
1231
  }),
1250
- prevEpochOnChainSourceAttesterHit: stateDerivedRegister?.gauge({
1232
+ prevEpochOnChainSourceAttesterHit: register.gauge({
1251
1233
  name: "validator_monitor_prev_epoch_on_chain_source_attester_hit_total",
1252
1234
  help: "Incremented if the validator is flagged as a previous epoch source attester during per epoch processing",
1253
1235
  }),
1254
- prevEpochOnChainSourceAttesterMiss: stateDerivedRegister?.gauge({
1236
+ prevEpochOnChainSourceAttesterMiss: register.gauge({
1255
1237
  name: "validator_monitor_prev_epoch_on_chain_source_attester_miss_total",
1256
1238
  help: "Incremented if the validator is not flagged as a previous epoch source attester during per epoch processing",
1257
1239
  }),
1258
- prevEpochOnChainHeadAttesterHit: stateDerivedRegister?.gauge({
1240
+ prevEpochOnChainHeadAttesterHit: register.gauge({
1259
1241
  name: "validator_monitor_prev_epoch_on_chain_head_attester_hit_total",
1260
1242
  help: "Incremented if the validator is flagged as a previous epoch head attester during per epoch processing",
1261
1243
  }),
1262
- prevEpochOnChainHeadAttesterMiss: stateDerivedRegister?.gauge({
1244
+ prevEpochOnChainHeadAttesterMiss: register.gauge({
1263
1245
  name: "validator_monitor_prev_epoch_on_chain_head_attester_miss_total",
1264
1246
  help: "Incremented if the validator is not flagged as a previous epoch head attester during per epoch processing",
1265
1247
  }),
@@ -1271,11 +1253,11 @@ function createValidatorMonitorMetrics(register: RegistryMetricCreator, register
1271
1253
  name: "validator_monitor_prev_epoch_on_chain_attester_incorrect_head_total",
1272
1254
  help: "Total count of times a validator votes incorrect head",
1273
1255
  }),
1274
- prevEpochOnChainTargetAttesterHit: stateDerivedRegister?.gauge({
1256
+ prevEpochOnChainTargetAttesterHit: register.gauge({
1275
1257
  name: "validator_monitor_prev_epoch_on_chain_target_attester_hit_total",
1276
1258
  help: "Incremented if the validator is flagged as a previous epoch target attester during per epoch processing",
1277
1259
  }),
1278
- prevEpochOnChainTargetAttesterMiss: stateDerivedRegister?.gauge({
1260
+ prevEpochOnChainTargetAttesterMiss: register.gauge({
1279
1261
  name: "validator_monitor_prev_epoch_on_chain_target_attester_miss_total",
1280
1262
  help: "Incremented if the validator is not flagged as a previous epoch target attester during per epoch processing",
1281
1263
  }),
@@ -9,42 +9,27 @@ import {RegistryMetricCreator} from "./utils/registryMetricCreator.js";
9
9
 
10
10
  export type Metrics = BeaconMetrics &
11
11
  ForkChoiceMetrics &
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
- };
12
+ BeaconStateTransitionMetrics &
13
+ LodestarMetrics & {register: RegistryMetricCreator; close: () => void};
29
14
 
30
15
  export function createMetrics(
31
16
  opts: MetricsOptions,
32
17
  genesisTime: number,
33
18
  externalRegistries: Registry[] = [],
34
- createOpts: CreateMetricsOptions = {}
19
+ {collectNodeMetrics = true}: {collectNodeMetrics?: boolean} = {}
35
20
  ): Metrics {
36
21
  const register = new RegistryMetricCreator();
37
22
  const beacon = createBeaconMetrics(register);
38
23
  const forkChoice = getForkChoiceMetrics(register);
39
24
  const lodestar = createLodestarMetrics(register, opts.metadata, genesisTime);
40
- const stateTransition = createOpts.includeStateTransitionMetrics === false ? null : getMetrics(register);
25
+ const stateTransition = getMetrics(register);
41
26
 
42
27
  const onUnhandledRejection = (_error: unknown): void => {
43
28
  lodestar.unhandledPromiseRejections.inc();
44
29
  };
45
30
  process.on("unhandledRejection", onUnhandledRejection);
46
31
 
47
- const nodeJsMetricsClose = createOpts.collectNodeMetrics === false ? (): void => {} : collectNodeJSMetrics(register);
32
+ const nodeJsMetricsClose = collectNodeMetrics ? collectNodeJSMetrics(register) : (): void => {};
48
33
  const close = (): void => {
49
34
  process.removeListener("unhandledRejection", onUnhandledRejection);
50
35
  nodeJsMetricsClose();
@@ -61,7 +46,7 @@ export function createMetrics(
61
46
  ...beacon,
62
47
  ...forkChoice,
63
48
  ...lodestar,
64
- stateTransition,
49
+ ...stateTransition,
65
50
  register,
66
51
  close,
67
52
  };