@lodestar/beacon-node 1.48.0-dev.49442412f1 → 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.
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +39 -39
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +13 -0
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/chain.d.ts +0 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +38 -67
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +1 -1
- package/lib/chain/emitter.js +1 -1
- package/package.json +14 -14
- package/src/api/impl/validator/index.ts +43 -44
- package/src/chain/blocks/importBlock.ts +13 -0
- package/src/chain/chain.ts +46 -74
- package/src/chain/emitter.ts +1 -1
package/src/chain/chain.ts
CHANGED
|
@@ -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
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1277
|
+
if (!headRootChanged && prevHead.payloadStatus === head.payloadStatus) {
|
|
1278
|
+
return head;
|
|
1279
|
+
}
|
|
1294
1280
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
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
|
|
package/src/chain/emitter.ts
CHANGED
|
@@ -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
|
|
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
|
/**
|