@lodestar/beacon-node 1.48.0-dev.4821c9776a → 1.48.0-dev.540d803f91

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.
@@ -1271,65 +1271,59 @@ export class BeaconChain implements IBeaconChain {
1271
1271
  try {
1272
1272
  const prevHead = this.forkChoice.getHead();
1273
1273
  const head = this.forkChoice.updateAndGetHead({mode: UpdateHeadOpt.GetCanonicalHead}).head;
1274
- this.emitHeadEvents(prevHead, head);
1275
- return head;
1276
- } catch (e) {
1277
- this.metrics?.forkChoice.errors.inc({entrypoint: UpdateHeadOpt.GetCanonicalHead});
1278
- throw e;
1279
- } finally {
1280
- timer?.();
1281
- }
1282
- }
1283
1274
 
1284
- /**
1285
- * Emit `head` and `head_v2` when the fork choice head differs between two observations. Every caller that
1286
- * can move the head, `updateAndGetHead()` and `updateTime()`, must capture the head before and pass both.
1287
- */
1288
- private emitHeadEvents(prevHead: ProtoBlock, head: ProtoBlock): void {
1289
- const headRootChanged = head.blockRoot !== prevHead.blockRoot;
1275
+ const headRootChanged = head.blockRoot !== prevHead.blockRoot;
1290
1276
 
1291
- if (!headRootChanged && prevHead.payloadStatus === head.payloadStatus) {
1292
- return;
1293
- }
1277
+ if (!headRootChanged && prevHead.payloadStatus === head.payloadStatus) {
1278
+ return head;
1279
+ }
1294
1280
 
1295
- try {
1296
- const previousDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.previous);
1297
- const currentDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.current);
1298
- const epochTransition = computeStartSlotAtEpoch(computeEpochAtSlot(head.slot)) === head.slot;
1299
- const executionOptimistic = isOptimisticBlock(head);
1300
-
1301
- if (headRootChanged) {
1302
- this.emitter.emit(routes.events.EventType.head, {
1303
- block: head.blockRoot,
1304
- epochTransition,
1305
- slot: head.slot,
1306
- state: head.stateRoot,
1307
- previousDutyDependentRoot,
1308
- currentDutyDependentRoot,
1309
- executionOptimistic,
1281
+ try {
1282
+ const previousDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.previous);
1283
+ const currentDutyDependentRoot = this.forkChoice.getDependentRoot(head, EpochDifference.current);
1284
+ const epochTransition = computeStartSlotAtEpoch(computeEpochAtSlot(head.slot)) === head.slot;
1285
+ const executionOptimistic = isOptimisticBlock(head);
1286
+
1287
+ if (headRootChanged) {
1288
+ this.emitter.emit(routes.events.EventType.head, {
1289
+ block: head.blockRoot,
1290
+ epochTransition,
1291
+ slot: head.slot,
1292
+ state: head.stateRoot,
1293
+ previousDutyDependentRoot,
1294
+ currentDutyDependentRoot,
1295
+ executionOptimistic,
1296
+ });
1297
+ }
1298
+
1299
+ this.emitter.emit(routes.events.EventType.headV2, {
1300
+ version: this.config.getForkName(head.slot),
1301
+ data: {
1302
+ slot: head.slot,
1303
+ block: head.blockRoot,
1304
+ state: head.stateRoot,
1305
+ payloadStatus: head.payloadStatus === PayloadStatus.FULL ? "full" : "empty",
1306
+ epochTransition,
1307
+ currentEpochDependentRoot: previousDutyDependentRoot,
1308
+ nextEpochDependentRoot: currentDutyDependentRoot,
1309
+ executionOptimistic,
1310
+ },
1310
1311
  });
1312
+ } catch (e) {
1313
+ // getDependentRoot() may fail with error: "No block for root" as we can see in holesky non-finality issue
1314
+ this.logger.debug(
1315
+ "Error emitting head/head_v2 event",
1316
+ {slot: head.slot, root: head.blockRoot, headRootChanged},
1317
+ e as Error
1318
+ );
1311
1319
  }
1312
1320
 
1313
- this.emitter.emit(routes.events.EventType.headV2, {
1314
- version: this.config.getForkName(head.slot),
1315
- data: {
1316
- slot: head.slot,
1317
- block: head.blockRoot,
1318
- state: head.stateRoot,
1319
- payloadStatus: head.payloadStatus === PayloadStatus.FULL ? "full" : "empty",
1320
- epochTransition,
1321
- currentEpochDependentRoot: previousDutyDependentRoot,
1322
- nextEpochDependentRoot: currentDutyDependentRoot,
1323
- executionOptimistic,
1324
- },
1325
- });
1321
+ return head;
1326
1322
  } catch (e) {
1327
- // getDependentRoot() may fail with error: "No block for root" as we can see in holesky non-finality issue
1328
- this.logger.debug(
1329
- "Error emitting head/head_v2 event",
1330
- {slot: head.slot, root: head.blockRoot, headRootChanged},
1331
- e as Error
1332
- );
1323
+ this.metrics?.forkChoice.errors.inc({entrypoint: UpdateHeadOpt.GetCanonicalHead});
1324
+ throw e;
1325
+ } finally {
1326
+ timer?.();
1333
1327
  }
1334
1328
  }
1335
1329
 
@@ -1618,10 +1612,7 @@ export class BeaconChain implements IBeaconChain {
1618
1612
  this.processShutdownCallback(this.forkChoice.irrecoverableError);
1619
1613
  }
1620
1614
 
1621
- // updateTime() recomputes the head on epoch-boundary checkpoint pull-up and under fast confirmation
1622
- const prevHead = this.forkChoice.getHead();
1623
1615
  this.forkChoice.updateTime(slot);
1624
- this.emitHeadEvents(prevHead, this.forkChoice.getHead());
1625
1616
  this.metrics?.clockSlot.set(slot);
1626
1617
 
1627
1618
  this.attestationPool.prune(slot);
@@ -1679,25 +1670,6 @@ export class BeaconChain implements IBeaconChain {
1679
1670
 
1680
1671
  private async onForkChoiceFinalized(this: BeaconChain, cp: CheckpointWithHex): Promise<void> {
1681
1672
  this.logger.verbose("Fork choice finalized", {epoch: cp.epoch, root: cp.rootHex});
1682
- this.metrics?.finalizedEpoch.set(cp.epoch);
1683
- const finalizedBlock = this.forkChoice.getBlockHexDefaultStatus(cp.rootHex);
1684
- if (finalizedBlock) {
1685
- // The callback runs synchronously inside fork choice checkpoint updates, defer writing to subscribers
1686
- callInNextEventLoop(() => {
1687
- this.emitter.emit(routes.events.EventType.finalizedCheckpoint, {
1688
- block: cp.rootHex,
1689
- epoch: cp.epoch,
1690
- state: finalizedBlock.stateRoot,
1691
- executionOptimistic: isOptimisticBlock(finalizedBlock),
1692
- });
1693
- });
1694
- } else {
1695
- this.logger.debug("Finalized block not found in fork choice, skip finalized_checkpoint event", {
1696
- epoch: cp.epoch,
1697
- root: cp.rootHex,
1698
- });
1699
- }
1700
-
1701
1673
  const finalizedSlot = computeStartSlotAtEpoch(cp.epoch);
1702
1674
  this.seenBlockProposers.prune(finalizedSlot);
1703
1675
 
@@ -33,7 +33,7 @@ export enum ChainEvent {
33
33
  /**
34
34
  * This event signals that the fork choice store has been updated.
35
35
  *
36
- * This event is guaranteed to be triggered whenever the fork choice finalized checkpoint is updated. This is either in response to a newly processed block or a new clock tick.
36
+ * This event is guaranteed to be triggered whenever the fork choice justified checkpoint is updated. This is in response to a newly processed block.
37
37
  */
38
38
  forkChoiceFinalized = "forkChoice:finalized",
39
39
  /**