@lodestar/beacon-node 1.43.0-dev.aef3645690 → 1.43.0-dev.e5b13221e5
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/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +1 -4
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +1 -4
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +27 -35
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +19 -26
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.js +1 -1
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +6 -4
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +1 -1
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +17 -37
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +13 -1
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/attestationError.d.ts +8 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +4 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +12 -4
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +22 -16
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -9
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +5 -32
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -8
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +29 -19
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +1 -11
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +0 -2
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +6 -12
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +6 -11
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +8 -40
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +0 -5
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +7 -34
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/stateCache/datastore/db.d.ts +5 -4
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +10 -32
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +13 -30
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +120 -216
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +8 -15
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +12 -0
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +12 -0
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +10 -10
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +4 -3
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +21 -14
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -0
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +6 -0
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/types.d.ts +20 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +18 -0
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +23 -2
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/network.js +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +22 -6
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +16 -3
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/beacon/blocks/index.ts +1 -4
- package/src/api/impl/validator/index.ts +3 -6
- package/src/chain/GetBlobsTracker.ts +1 -2
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +2 -4
- package/src/chain/blocks/importBlock.ts +26 -39
- package/src/chain/blocks/importExecutionPayload.ts +20 -26
- package/src/chain/blocks/index.ts +1 -1
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +6 -5
- package/src/chain/blocks/types.ts +1 -1
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
- package/src/chain/chain.ts +16 -47
- package/src/chain/emitter.ts +12 -0
- package/src/chain/errors/attestationError.ts +6 -1
- package/src/chain/forkChoice/index.ts +12 -4
- package/src/chain/prepareNextSlot.ts +25 -16
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +40 -20
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +6 -12
- package/src/chain/regen/queued.ts +12 -48
- package/src/chain/regen/regen.ts +8 -36
- package/src/chain/stateCache/datastore/db.ts +10 -33
- package/src/chain/stateCache/datastore/file.ts +5 -6
- package/src/chain/stateCache/datastore/types.ts +2 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
- package/src/chain/stateCache/persistentCheckpointsCache.ts +139 -247
- package/src/chain/stateCache/types.ts +8 -14
- package/src/chain/validation/aggregateAndProof.ts +13 -0
- package/src/chain/validation/attestation.ts +13 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -10
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
- package/src/execution/engine/http.ts +21 -14
- package/src/execution/engine/interface.ts +1 -0
- package/src/execution/engine/mock.ts +8 -1
- package/src/execution/engine/types.ts +41 -0
- package/src/network/network.ts +1 -1
- package/src/network/processor/gossipHandlers.ts +26 -10
- package/src/node/nodejs.ts +4 -2
- package/src/util/sszBytes.ts +21 -3
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
ForkChoiceErrorCode,
|
|
9
9
|
NotReorgedReason,
|
|
10
10
|
getSafeExecutionBlockHash,
|
|
11
|
-
isGloasBlock,
|
|
12
11
|
} from "@lodestar/fork-choice";
|
|
13
12
|
import {
|
|
14
13
|
ForkPostAltair,
|
|
@@ -48,7 +47,7 @@ import type {BeaconChain} from "../chain.js";
|
|
|
48
47
|
import {ChainEvent, ReorgEventData} from "../emitter.js";
|
|
49
48
|
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
50
49
|
import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js";
|
|
51
|
-
import {
|
|
50
|
+
import {toCheckpointHex} from "../stateCache/persistentCheckpointsCache.js";
|
|
52
51
|
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
53
52
|
import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
54
53
|
import {getCheckpointFromState} from "./utils/checkpoint.js";
|
|
@@ -87,7 +86,7 @@ export async function importBlock(
|
|
|
87
86
|
fullyVerifiedBlock: FullyVerifiedBlock,
|
|
88
87
|
opts: ImportBlockOpts
|
|
89
88
|
): Promise<void> {
|
|
90
|
-
const {blockInput,
|
|
89
|
+
const {blockInput, postState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
|
|
91
90
|
fullyVerifiedBlock;
|
|
92
91
|
const block = blockInput.getBlock();
|
|
93
92
|
const source = blockInput.getBlockSource();
|
|
@@ -99,7 +98,7 @@ export async function importBlock(
|
|
|
99
98
|
const blockEpoch = computeEpochAtSlot(blockSlot);
|
|
100
99
|
const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
101
100
|
const blockDelaySec =
|
|
102
|
-
fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot,
|
|
101
|
+
fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot, postState.genesisTime);
|
|
103
102
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
104
103
|
const fork = this.config.getForkSeq(blockSlot);
|
|
105
104
|
|
|
@@ -122,10 +121,10 @@ export async function importBlock(
|
|
|
122
121
|
// 2. Import block to fork choice
|
|
123
122
|
|
|
124
123
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
125
|
-
this.checkpointBalancesCache.processState(blockRootHex,
|
|
124
|
+
this.checkpointBalancesCache.processState(blockRootHex, postState);
|
|
126
125
|
const blockSummary = this.forkChoice.onBlock(
|
|
127
126
|
block.message,
|
|
128
|
-
|
|
127
|
+
postState,
|
|
129
128
|
blockDelaySec,
|
|
130
129
|
currentSlot,
|
|
131
130
|
fork >= ForkSeq.gloas ? ExecutionStatus.PayloadSeparated : executionStatus,
|
|
@@ -134,11 +133,7 @@ export async function importBlock(
|
|
|
134
133
|
|
|
135
134
|
// This adds the state necessary to process the next block
|
|
136
135
|
// Some block event handlers require state being in state cache so need to do this before emitting EventType.block
|
|
137
|
-
|
|
138
|
-
// Post-Gloas: blockSummary.payloadStatus is always PENDING, so payloadPresent = false (block state only, no payload processing yet)
|
|
139
|
-
const payloadPresent = !isGloasBlock(blockSummary);
|
|
140
|
-
// processState manages both block state and payload state variants together for memory/disk management
|
|
141
|
-
this.regen.processBlockState(blockRootHex, postBlockState);
|
|
136
|
+
this.regen.processState(blockRootHex, postState);
|
|
142
137
|
|
|
143
138
|
// For Gloas blocks, create PayloadEnvelopeInput so it's available for later payload import
|
|
144
139
|
if (fork >= ForkSeq.gloas) {
|
|
@@ -161,17 +156,9 @@ export async function importBlock(
|
|
|
161
156
|
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
162
157
|
// TODO GLOAS: If we want EL retries after this initial attempt, add an explicit retry policy here
|
|
163
158
|
// (for example later in the slot). Do not couple retries to incoming gossip columns.
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
|
|
168
|
-
this.logger.debug(
|
|
169
|
-
"Error processing execution payload after getBlobs",
|
|
170
|
-
{slot: blockSlot, root: blockRootHex},
|
|
171
|
-
e as Error
|
|
172
|
-
);
|
|
173
|
-
});
|
|
174
|
-
});
|
|
159
|
+
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
160
|
+
// in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
|
|
161
|
+
this.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
175
162
|
}
|
|
176
163
|
|
|
177
164
|
this.metrics?.importBlock.bySource.inc({source: source.source});
|
|
@@ -191,7 +178,7 @@ export async function importBlock(
|
|
|
191
178
|
(opts.importAttestations !== AttestationImportOpt.Skip && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT)
|
|
192
179
|
) {
|
|
193
180
|
const attestations = block.message.body.attestations;
|
|
194
|
-
const rootCache = new RootCache(
|
|
181
|
+
const rootCache = new RootCache(postState);
|
|
195
182
|
const invalidAttestationErrorsByCode = new Map<string, {error: Error; count: number}>();
|
|
196
183
|
|
|
197
184
|
const addAttestation = fork >= ForkSeq.electra ? addAttestationPostElectra : addAttestationPreElectra;
|
|
@@ -205,7 +192,7 @@ export async function importBlock(
|
|
|
205
192
|
const attDataRoot = toRootHex(ssz.phase0.AttestationData.hashTreeRoot(indexedAttestation.data));
|
|
206
193
|
addAttestation.call(
|
|
207
194
|
this,
|
|
208
|
-
|
|
195
|
+
postState,
|
|
209
196
|
target,
|
|
210
197
|
attDataRoot,
|
|
211
198
|
attestation as Attestation<ForkPostElectra>,
|
|
@@ -320,7 +307,7 @@ export async function importBlock(
|
|
|
320
307
|
|
|
321
308
|
if (newHead.blockRoot !== oldHead.blockRoot) {
|
|
322
309
|
// Set head state as strong reference
|
|
323
|
-
this.regen.updateHeadState(newHead,
|
|
310
|
+
this.regen.updateHeadState(newHead, postState);
|
|
324
311
|
|
|
325
312
|
try {
|
|
326
313
|
this.emitter.emit(routes.events.EventType.head, {
|
|
@@ -390,10 +377,10 @@ export async function importBlock(
|
|
|
390
377
|
// we want to import block asap so do this in the next event loop
|
|
391
378
|
callInNextEventLoop(() => {
|
|
392
379
|
try {
|
|
393
|
-
if (isStatePostAltair(
|
|
380
|
+
if (isStatePostAltair(postState)) {
|
|
394
381
|
this.lightClientServer?.onImportBlockHead(
|
|
395
382
|
block.message as BeaconBlock<ForkPostAltair>,
|
|
396
|
-
|
|
383
|
+
postState,
|
|
397
384
|
parentBlockSlot
|
|
398
385
|
);
|
|
399
386
|
}
|
|
@@ -415,11 +402,11 @@ export async function importBlock(
|
|
|
415
402
|
// and the block is weak and can potentially be reorged out.
|
|
416
403
|
let shouldOverrideFcu = false;
|
|
417
404
|
|
|
418
|
-
if (blockSlot >= currentSlot && isStatePostBellatrix(
|
|
405
|
+
if (blockSlot >= currentSlot && isStatePostBellatrix(postState) && postState.isExecutionStateType) {
|
|
419
406
|
let notOverrideFcuReason = NotReorgedReason.Unknown;
|
|
420
407
|
const proposalSlot = blockSlot + 1;
|
|
421
408
|
try {
|
|
422
|
-
const proposerIndex =
|
|
409
|
+
const proposerIndex = postState.getBeaconProposer(proposalSlot);
|
|
423
410
|
const feeRecipient = this.beaconProposerCache.get(proposerIndex);
|
|
424
411
|
|
|
425
412
|
if (feeRecipient) {
|
|
@@ -499,27 +486,27 @@ export async function importBlock(
|
|
|
499
486
|
}
|
|
500
487
|
}
|
|
501
488
|
|
|
502
|
-
if (!
|
|
503
|
-
this.logger.verbose("After importBlock caching postState without SSZ cache", {slot:
|
|
489
|
+
if (!postState.isStateValidatorsNodesPopulated()) {
|
|
490
|
+
this.logger.verbose("After importBlock caching postState without SSZ cache", {slot: postState.slot});
|
|
504
491
|
}
|
|
505
492
|
|
|
506
493
|
// Cache shufflings when crossing an epoch boundary
|
|
507
494
|
const parentEpoch = computeEpochAtSlot(parentBlockSlot);
|
|
508
495
|
if (parentEpoch < blockEpoch) {
|
|
509
|
-
this.shufflingCache.processState(
|
|
496
|
+
this.shufflingCache.processState(postState);
|
|
510
497
|
this.logger.verbose("Processed shuffling for next epoch", {parentEpoch, blockEpoch, slot: blockSlot});
|
|
511
498
|
}
|
|
512
499
|
|
|
513
500
|
if (blockSlot % SLOTS_PER_EPOCH === 0) {
|
|
514
501
|
// Cache state to preserve epoch transition work
|
|
515
|
-
const checkpointState =
|
|
502
|
+
const checkpointState = postState;
|
|
516
503
|
const cp = getCheckpointFromState(checkpointState);
|
|
517
|
-
this.regen.addCheckpointState(cp, checkpointState
|
|
504
|
+
this.regen.addCheckpointState(cp, checkpointState);
|
|
518
505
|
// consumers should not mutate state ever
|
|
519
506
|
this.emitter.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
520
507
|
|
|
521
508
|
// Note: in-lined code from previos handler of ChainEvent.checkpoint
|
|
522
|
-
this.logger.verbose("Checkpoint processed",
|
|
509
|
+
this.logger.verbose("Checkpoint processed", toCheckpointHex(cp));
|
|
523
510
|
|
|
524
511
|
const activeValidatorsCount = checkpointState.activeValidatorCount;
|
|
525
512
|
this.metrics?.currentActiveValidators.set(activeValidatorsCount);
|
|
@@ -537,7 +524,7 @@ export async function importBlock(
|
|
|
537
524
|
const justifiedEpoch = justifiedCheckpoint.epoch;
|
|
538
525
|
const preJustifiedEpoch = parentBlockSummary.justifiedEpoch;
|
|
539
526
|
if (justifiedEpoch > preJustifiedEpoch) {
|
|
540
|
-
this.logger.verbose("Checkpoint justified",
|
|
527
|
+
this.logger.verbose("Checkpoint justified", toCheckpointHex(justifiedCheckpoint));
|
|
541
528
|
this.metrics?.previousJustifiedEpoch.set(checkpointState.previousJustifiedCheckpoint.epoch);
|
|
542
529
|
this.metrics?.currentJustifiedEpoch.set(justifiedCheckpoint.epoch);
|
|
543
530
|
}
|
|
@@ -551,7 +538,7 @@ export async function importBlock(
|
|
|
551
538
|
state: toRootHex(checkpointState.hashTreeRoot()),
|
|
552
539
|
executionOptimistic: false,
|
|
553
540
|
});
|
|
554
|
-
this.logger.verbose("Checkpoint finalized",
|
|
541
|
+
this.logger.verbose("Checkpoint finalized", toCheckpointHex(finalizedCheckpoint));
|
|
555
542
|
this.metrics?.finalizedEpoch.set(finalizedCheckpoint.epoch);
|
|
556
543
|
}
|
|
557
544
|
}
|
|
@@ -602,11 +589,11 @@ export async function importBlock(
|
|
|
602
589
|
this.metrics?.parentBlockDistance.observe(blockSlot - parentBlockSlot);
|
|
603
590
|
this.metrics?.proposerBalanceDeltaAny.observe(fullyVerifiedBlock.proposerBalanceDelta);
|
|
604
591
|
this.validatorMonitor?.registerImportedBlock(block.message, fullyVerifiedBlock);
|
|
605
|
-
if (isStatePostAltair(fullyVerifiedBlock.
|
|
592
|
+
if (isStatePostAltair(fullyVerifiedBlock.postState)) {
|
|
606
593
|
this.validatorMonitor?.registerSyncAggregateInBlock(
|
|
607
594
|
blockEpoch,
|
|
608
595
|
(block as altair.SignedBeaconBlock).message.body.syncAggregate,
|
|
609
|
-
fullyVerifiedBlock.
|
|
596
|
+
fullyVerifiedBlock.postState.currentSyncCommitteeIndexed.validatorIndices
|
|
610
597
|
);
|
|
611
598
|
}
|
|
612
599
|
|
|
@@ -2,13 +2,14 @@ import {routes} from "@lodestar/api";
|
|
|
2
2
|
import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
3
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
4
4
|
import {getExecutionPayloadEnvelopeSignatureSet, isStatePostGloas} from "@lodestar/state-transition";
|
|
5
|
-
import {
|
|
5
|
+
import {fromHex, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {ExecutionPayloadStatus} from "../../execution/index.js";
|
|
7
7
|
import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
8
8
|
import {BeaconChain} from "../chain.js";
|
|
9
9
|
import {RegenCaller} from "../regen/interface.js";
|
|
10
10
|
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
11
11
|
import {ImportPayloadOpts} from "./types.js";
|
|
12
|
+
import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
|
|
12
13
|
|
|
13
14
|
const EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS = 64;
|
|
14
15
|
|
|
@@ -84,21 +85,22 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
84
85
|
export async function importExecutionPayload(
|
|
85
86
|
this: BeaconChain,
|
|
86
87
|
payloadInput: PayloadEnvelopeInput,
|
|
88
|
+
signal: AbortSignal,
|
|
87
89
|
opts: ImportPayloadOpts = {}
|
|
88
90
|
): Promise<void> {
|
|
89
91
|
const signedEnvelope = payloadInput.getPayloadEnvelope();
|
|
90
92
|
const envelope = signedEnvelope.message;
|
|
91
93
|
const blockRootHex = payloadInput.blockRootHex;
|
|
92
94
|
const blockHashHex = payloadInput.getBlockHashHex();
|
|
93
|
-
const fork = this.config.getForkName(envelope.
|
|
95
|
+
const fork = this.config.getForkName(envelope.payload.slotNumber);
|
|
94
96
|
|
|
95
97
|
// 1. Emit `execution_payload_available` event at the start of import. At this point the payload input
|
|
96
98
|
// is already complete, so the payload and required data are available for payload attestation.
|
|
97
99
|
// This event is only about availability, not validity of the execution payload, hence we can emit
|
|
98
100
|
// it before getting a response from the execution client on whether the payload is valid or not.
|
|
99
|
-
if (this.clock.currentSlot - envelope.
|
|
101
|
+
if (this.clock.currentSlot - envelope.payload.slotNumber < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
100
102
|
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
|
-
slot: envelope.
|
|
103
|
+
slot: envelope.payload.slotNumber,
|
|
102
104
|
blockRoot: blockRootHex,
|
|
103
105
|
});
|
|
104
106
|
}
|
|
@@ -112,11 +114,15 @@ export async function importExecutionPayload(
|
|
|
112
114
|
});
|
|
113
115
|
}
|
|
114
116
|
|
|
115
|
-
// 3.
|
|
117
|
+
// 3. Wait for data columns to be available before claiming a write-queue slot.
|
|
118
|
+
// The helper is shared with future gloas sync services; take the single-item batch form here.
|
|
119
|
+
await verifyPayloadsDataAvailability([payloadInput], signal);
|
|
120
|
+
|
|
121
|
+
// 4. Apply backpressure from the write queue, before doing verification work.
|
|
116
122
|
// The actual DB write is deferred until after verification succeeds.
|
|
117
123
|
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
118
124
|
|
|
119
|
-
//
|
|
125
|
+
// 5. Get pre-state for processExecutionPayloadEnvelope
|
|
120
126
|
// We need the block state (post-block, pre-payload) to process the envelope
|
|
121
127
|
const blockState = await this.regen.getBlockSlotState(
|
|
122
128
|
protoBlock,
|
|
@@ -131,9 +137,7 @@ export async function importExecutionPayload(
|
|
|
131
137
|
});
|
|
132
138
|
}
|
|
133
139
|
|
|
134
|
-
//
|
|
135
|
-
// Note: No data availability check needed here - importExecutionPayload is only
|
|
136
|
-
// called when payloadInput.isComplete() is true, so all data is already available.
|
|
140
|
+
// 6. Run verification steps in parallel
|
|
137
141
|
const [execResult, signatureValid, postPayloadResult] = await Promise.all([
|
|
138
142
|
this.executionEngine.notifyNewPayload(
|
|
139
143
|
fork,
|
|
@@ -209,22 +213,16 @@ export async function importExecutionPayload(
|
|
|
209
213
|
});
|
|
210
214
|
}
|
|
211
215
|
|
|
212
|
-
// 5c.
|
|
216
|
+
// 5c. Compute post-payload state root
|
|
213
217
|
const postPayloadState = postPayloadResult.postPayloadState;
|
|
214
218
|
const postPayloadStateRoot = postPayloadState.hashTreeRoot();
|
|
215
|
-
if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
|
|
216
|
-
throw new PayloadError({
|
|
217
|
-
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
218
|
-
message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
219
|
|
|
222
220
|
// 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
|
|
223
221
|
this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
|
|
224
222
|
if (!isQueueErrorAborted(e)) {
|
|
225
223
|
this.logger.error(
|
|
226
224
|
"Error pushing payload envelope to unfinalized write queue",
|
|
227
|
-
{slot: envelope.
|
|
225
|
+
{slot: envelope.payload.slotNumber, blockRoot: blockRootHex},
|
|
228
226
|
e as Error
|
|
229
227
|
);
|
|
230
228
|
}
|
|
@@ -240,10 +238,10 @@ export async function importExecutionPayload(
|
|
|
240
238
|
);
|
|
241
239
|
|
|
242
240
|
// 8. Cache payload state
|
|
243
|
-
this.regen.
|
|
241
|
+
this.regen.processState(blockRootHex, postPayloadState);
|
|
244
242
|
if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
|
|
245
243
|
const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
|
|
246
|
-
this.regen.addCheckpointState(checkpoint, postPayloadState
|
|
244
|
+
this.regen.addCheckpointState(checkpoint, postPayloadState);
|
|
247
245
|
}
|
|
248
246
|
|
|
249
247
|
// 9. Record metrics for payload envelope and column sources
|
|
@@ -252,26 +250,22 @@ export async function importExecutionPayload(
|
|
|
252
250
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
253
251
|
}
|
|
254
252
|
|
|
255
|
-
const stateRootHex = toRootHex(envelope.stateRoot);
|
|
256
|
-
|
|
257
253
|
// 10. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
258
|
-
if (this.clock.currentSlot - envelope.
|
|
254
|
+
if (this.clock.currentSlot - envelope.payload.slotNumber < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
259
255
|
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
260
|
-
slot: envelope.
|
|
256
|
+
slot: envelope.payload.slotNumber,
|
|
261
257
|
builderIndex: envelope.builderIndex,
|
|
262
258
|
blockHash: blockHashHex,
|
|
263
259
|
blockRoot: blockRootHex,
|
|
264
|
-
stateRoot: stateRootHex,
|
|
265
260
|
// TODO GLOAS: revisit once we support optimistic import
|
|
266
261
|
executionOptimistic: false,
|
|
267
262
|
});
|
|
268
263
|
}
|
|
269
264
|
|
|
270
265
|
this.logger.verbose("Execution payload imported", {
|
|
271
|
-
slot: envelope.
|
|
266
|
+
slot: envelope.payload.slotNumber,
|
|
272
267
|
builderIndex: envelope.builderIndex,
|
|
273
268
|
blockRoot: blockRootHex,
|
|
274
269
|
blockHash: blockHashHex,
|
|
275
|
-
stateRoot: stateRootHex,
|
|
276
270
|
});
|
|
277
271
|
}
|
|
@@ -88,7 +88,7 @@ export async function processBlocks(
|
|
|
88
88
|
const fullyVerifiedBlocks = relevantBlocks.map(
|
|
89
89
|
(block, i): FullyVerifiedBlock => ({
|
|
90
90
|
blockInput: block,
|
|
91
|
-
|
|
91
|
+
postState: postStates[i],
|
|
92
92
|
postPayloadState: null,
|
|
93
93
|
parentBlockSlot: parentSlots[i],
|
|
94
94
|
executionStatus: executionStatuses[i],
|
|
@@ -73,6 +73,7 @@ export class PayloadEnvelopeInput {
|
|
|
73
73
|
private timeCreatedSec: number;
|
|
74
74
|
|
|
75
75
|
private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
|
|
76
|
+
private readonly allDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
76
77
|
private readonly columnsDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
77
78
|
|
|
78
79
|
state: PayloadEnvelopeInputState;
|
|
@@ -97,6 +98,7 @@ export class PayloadEnvelopeInput {
|
|
|
97
98
|
this.custodyColumns = props.custodyColumns;
|
|
98
99
|
this.timeCreatedSec = props.timeCreatedSec;
|
|
99
100
|
this.payloadEnvelopeDataPromise = createPromise();
|
|
101
|
+
this.allDataPromise = createPromise();
|
|
100
102
|
this.columnsDataPromise = createPromise();
|
|
101
103
|
|
|
102
104
|
const noBlobs = props.bid.blobKzgCommitments.length === 0;
|
|
@@ -105,6 +107,7 @@ export class PayloadEnvelopeInput {
|
|
|
105
107
|
|
|
106
108
|
if (hasAllData) {
|
|
107
109
|
this.state = {hasPayload: false, hasAllData: true, hasComputedAllData: true};
|
|
110
|
+
this.allDataPromise.resolve(this.getSampledColumns());
|
|
108
111
|
this.columnsDataPromise.resolve(this.getSampledColumns());
|
|
109
112
|
} else {
|
|
110
113
|
this.state = {hasPayload: false, hasAllData: false, hasComputedAllData: false};
|
|
@@ -203,6 +206,12 @@ export class PayloadEnvelopeInput {
|
|
|
203
206
|
return true;
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
// Resolve allDataPromise on the first transition to hasAllData (either sampled-complete or
|
|
210
|
+
// reconstruction-threshold branch). Guarded so it fires exactly once.
|
|
211
|
+
if (!this.state.hasAllData && hasAllData) {
|
|
212
|
+
this.allDataPromise.resolve(sampledColumns);
|
|
213
|
+
}
|
|
214
|
+
|
|
206
215
|
if (hasComputedAllData) {
|
|
207
216
|
this.columnsDataPromise.resolve(sampledColumns);
|
|
208
217
|
}
|
|
@@ -315,6 +324,24 @@ export class PayloadEnvelopeInput {
|
|
|
315
324
|
return this.state.hasComputedAllData;
|
|
316
325
|
}
|
|
317
326
|
|
|
327
|
+
waitForAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
328
|
+
if (this.state.hasAllData) {
|
|
329
|
+
return Promise.resolve(this.getSampledColumns());
|
|
330
|
+
}
|
|
331
|
+
return withTimeout(() => this.allDataPromise.promise, timeout, signal);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async waitForEnvelopeAndAllData(timeout: number, signal?: AbortSignal): Promise<this> {
|
|
335
|
+
if (!this.state.hasPayload || !this.state.hasAllData) {
|
|
336
|
+
await withTimeout(
|
|
337
|
+
() => Promise.all([this.payloadEnvelopeDataPromise.promise, this.allDataPromise.promise]),
|
|
338
|
+
timeout,
|
|
339
|
+
signal
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
|
|
318
345
|
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
319
346
|
if (this.state.hasComputedAllData) {
|
|
320
347
|
return Promise.resolve(this.getSampledColumns());
|
|
@@ -16,6 +16,11 @@ enum PayloadEnvelopeImportStatus {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* PayloadEnvelopeProcessor processes payload envelope jobs in a queued fashion, one after the other.
|
|
19
|
+
*
|
|
20
|
+
* Jobs are enqueued only on envelope arrival (gossip or API). The envelope may reach us before
|
|
21
|
+
* the sampled data columns; importExecutionPayload awaits `verifyPayloadsDataAvailability`
|
|
22
|
+
* internally, so a queued job can pend for up to `PAYLOAD_DATA_AVAILABILITY_TIMEOUT` while
|
|
23
|
+
* waiting for columns. Duplicate triggers for the same payloadInput are deduped via `importStatus`.
|
|
19
24
|
*/
|
|
20
25
|
export class PayloadEnvelopeProcessor {
|
|
21
26
|
readonly jobQueue: JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>;
|
|
@@ -25,7 +30,7 @@ export class PayloadEnvelopeProcessor {
|
|
|
25
30
|
this.jobQueue = new JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>(
|
|
26
31
|
(payloadInput, opts) => {
|
|
27
32
|
this.importStatus.set(payloadInput, PayloadEnvelopeImportStatus.importing);
|
|
28
|
-
return importExecutionPayload.call(chain, payloadInput, opts);
|
|
33
|
+
return importExecutionPayload.call(chain, payloadInput, signal, opts);
|
|
29
34
|
},
|
|
30
35
|
{maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
|
|
31
36
|
metrics?.payloadEnvelopeProcessorQueue ?? undefined
|
|
@@ -33,10 +38,6 @@ export class PayloadEnvelopeProcessor {
|
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
async processPayloadEnvelopeJob(payloadInput: PayloadEnvelopeInput, opts: ImportPayloadOpts = {}): Promise<void> {
|
|
36
|
-
if (!payloadInput.isComplete()) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
41
|
if (this.importStatus.get(payloadInput) !== undefined) {
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
@@ -90,7 +90,7 @@ export type ImportBlockOpts = {
|
|
|
90
90
|
|
|
91
91
|
type FullyVerifiedBlockBase = {
|
|
92
92
|
blockInput: IBlockInput;
|
|
93
|
-
|
|
93
|
+
postState: IBeaconStateView;
|
|
94
94
|
parentBlockSlot: Slot;
|
|
95
95
|
proposerBalanceDelta: number;
|
|
96
96
|
dataAvailabilityStatus: DataAvailabilityStatus;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {DataAvailabilityStatus} from "@lodestar/state-transition";
|
|
2
|
+
import {gloas} from "@lodestar/types";
|
|
3
|
+
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
4
|
+
|
|
5
|
+
// we can now wait for full 12 seconds because sync and reconstruction will try pulling
|
|
6
|
+
// the data columns from the network anyway while the envelope is being processed
|
|
7
|
+
export const PAYLOAD_DATA_AVAILABILITY_TIMEOUT = 12_000;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Verifies that all payload envelope inputs have their data columns available.
|
|
11
|
+
* - Waits a max of PAYLOAD_DATA_AVAILABILITY_TIMEOUT for all data to be available
|
|
12
|
+
* - Returns the time at which all data was available
|
|
13
|
+
* - Returns the data availability status for each payload input
|
|
14
|
+
*/
|
|
15
|
+
export async function verifyPayloadsDataAvailability(
|
|
16
|
+
payloadInputs: PayloadEnvelopeInput[],
|
|
17
|
+
signal: AbortSignal
|
|
18
|
+
): Promise<{
|
|
19
|
+
dataAvailabilityStatuses: DataAvailabilityStatus[];
|
|
20
|
+
availableTime: number;
|
|
21
|
+
}> {
|
|
22
|
+
const promises: Promise<gloas.DataColumnSidecar[]>[] = [];
|
|
23
|
+
for (const payloadInput of payloadInputs) {
|
|
24
|
+
if (!payloadInput.hasAllData()) {
|
|
25
|
+
promises.push(payloadInput.waitForAllData(PAYLOAD_DATA_AVAILABILITY_TIMEOUT, signal));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
await Promise.all(promises);
|
|
29
|
+
|
|
30
|
+
const availableTime = Math.max(0, Math.max(...payloadInputs.map((payloadInput) => payloadInput.getTimeComplete())));
|
|
31
|
+
const dataAvailabilityStatuses: DataAvailabilityStatus[] = payloadInputs.map((payloadInput) =>
|
|
32
|
+
payloadInput.getBlobKzgCommitments().length === 0
|
|
33
|
+
? DataAvailabilityStatus.NotRequired
|
|
34
|
+
: DataAvailabilityStatus.Available
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
return {dataAvailabilityStatuses, availableTime};
|
|
38
|
+
}
|
package/src/chain/chain.ts
CHANGED
|
@@ -2,17 +2,9 @@ import path from "node:path";
|
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Type} from "@chainsafe/ssz";
|
|
4
4
|
import {BeaconConfig} from "@lodestar/config";
|
|
5
|
-
import {
|
|
6
|
-
CheckpointWithPayloadStatus,
|
|
7
|
-
IForkChoice,
|
|
8
|
-
PayloadStatus,
|
|
9
|
-
ProtoBlock,
|
|
10
|
-
UpdateHeadOpt,
|
|
11
|
-
getCheckpointPayloadStatus,
|
|
12
|
-
} from "@lodestar/fork-choice";
|
|
5
|
+
import {CheckpointWithPayloadStatus, IForkChoice, ProtoBlock, UpdateHeadOpt} from "@lodestar/fork-choice";
|
|
13
6
|
import {LoggerNode} from "@lodestar/logger/node";
|
|
14
7
|
import {
|
|
15
|
-
BUILDER_INDEX_SELF_BUILD,
|
|
16
8
|
EFFECTIVE_BALANCE_INCREMENT,
|
|
17
9
|
type ForkPostFulu,
|
|
18
10
|
type ForkPostGloas,
|
|
@@ -31,7 +23,6 @@ import {
|
|
|
31
23
|
getEffectiveBalancesFromStateBytes,
|
|
32
24
|
isStatePostAltair,
|
|
33
25
|
isStatePostElectra,
|
|
34
|
-
isStatePostGloas,
|
|
35
26
|
} from "@lodestar/state-transition";
|
|
36
27
|
import {
|
|
37
28
|
BeaconBlock,
|
|
@@ -100,8 +91,8 @@ import {
|
|
|
100
91
|
} from "./opPools/index.js";
|
|
101
92
|
import {IChainOptions} from "./options.js";
|
|
102
93
|
import {PrepareNextSlotScheduler} from "./prepareNextSlot.js";
|
|
103
|
-
import {computeNewStateRoot
|
|
104
|
-
import {AssembledBlockType, BlockType,
|
|
94
|
+
import {computeNewStateRoot} from "./produceBlock/computeNewStateRoot.js";
|
|
95
|
+
import {AssembledBlockType, BlockType, ProduceResult} from "./produceBlock/index.js";
|
|
105
96
|
import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produceBlock/produceBlockBody.js";
|
|
106
97
|
import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js";
|
|
107
98
|
import {ReprocessController} from "./reprocess.js";
|
|
@@ -125,7 +116,7 @@ import {DbCPStateDatastore, checkpointToDatastoreKey} from "./stateCache/datasto
|
|
|
125
116
|
import {FileCPStateDatastore} from "./stateCache/datastore/file.js";
|
|
126
117
|
import {CPStateDatastore} from "./stateCache/datastore/types.js";
|
|
127
118
|
import {FIFOBlockStateCache} from "./stateCache/fifoBlockStateCache.js";
|
|
128
|
-
import {PersistentCheckpointStateCache
|
|
119
|
+
import {PersistentCheckpointStateCache} from "./stateCache/persistentCheckpointsCache.js";
|
|
129
120
|
import {CheckpointStateCache} from "./stateCache/types.js";
|
|
130
121
|
import {ValidatorMonitor} from "./validatorMonitor.js";
|
|
131
122
|
|
|
@@ -390,8 +381,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
390
381
|
const {checkpoint} = anchorState.computeAnchorCheckpoint();
|
|
391
382
|
blockStateCache.add(anchorState);
|
|
392
383
|
blockStateCache.setHeadState(anchorState);
|
|
393
|
-
|
|
394
|
-
checkpointStateCache.add(checkpoint, anchorState, payloadPresent);
|
|
384
|
+
checkpointStateCache.add(checkpoint, anchorState);
|
|
395
385
|
|
|
396
386
|
const forkChoice = initializeForkChoice(
|
|
397
387
|
config,
|
|
@@ -685,7 +675,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
685
675
|
|
|
686
676
|
// TODO GLOAS: Need to revisit the design of this api. Currently we just retrieve FULL state of the checkpoint for backwards compatibility.
|
|
687
677
|
// because pre-gloas we always store FULL checkpoint state.
|
|
688
|
-
const persistedKey = checkpointToDatastoreKey(checkpoint
|
|
678
|
+
const persistedKey = checkpointToDatastoreKey(checkpoint);
|
|
689
679
|
return this.cpStateDatastore.read(persistedKey);
|
|
690
680
|
}
|
|
691
681
|
|
|
@@ -693,8 +683,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
693
683
|
checkpoint: CheckpointWithPayloadStatus
|
|
694
684
|
): {state: IBeaconStateView; executionOptimistic: boolean; finalized: boolean} | null {
|
|
695
685
|
// finalized or justified checkpoint states maynot be available with PersistentCheckpointStateCache, use getCheckpointStateOrBytes() api to get Uint8Array
|
|
696
|
-
const
|
|
697
|
-
const cachedStateCtx = this.regen.getCheckpointStateSync(
|
|
686
|
+
const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
|
|
687
|
+
const cachedStateCtx = this.regen.getCheckpointStateSync(checkpointHex);
|
|
698
688
|
if (cachedStateCtx) {
|
|
699
689
|
const block = this.forkChoice.getBlockDefaultStatus(
|
|
700
690
|
ssz.phase0.BeaconBlockHeader.hashTreeRoot(cachedStateCtx.latestBlockHeader)
|
|
@@ -713,8 +703,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
713
703
|
async getStateOrBytesByCheckpoint(
|
|
714
704
|
checkpoint: CheckpointWithPayloadStatus
|
|
715
705
|
): Promise<{state: IBeaconStateView | Uint8Array; executionOptimistic: boolean; finalized: boolean} | null> {
|
|
716
|
-
const
|
|
717
|
-
const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(
|
|
706
|
+
const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
|
|
707
|
+
const cachedStateCtx = await this.regen.getCheckpointStateOrBytes(checkpointHex);
|
|
718
708
|
if (cachedStateCtx) {
|
|
719
709
|
const block = this.forkChoice.getBlockDefaultStatus(checkpoint.root);
|
|
720
710
|
const finalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
@@ -1070,7 +1060,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1070
1060
|
body,
|
|
1071
1061
|
} as AssembledBlockType<T>;
|
|
1072
1062
|
|
|
1073
|
-
const {newStateRoot, proposerReward
|
|
1063
|
+
const {newStateRoot, proposerReward} = computeNewStateRoot(this.metrics, state, block);
|
|
1074
1064
|
block.stateRoot = newStateRoot;
|
|
1075
1065
|
const blockRoot =
|
|
1076
1066
|
produceResult.type === BlockType.Full
|
|
@@ -1079,26 +1069,9 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1079
1069
|
const blockRootHex = toRootHex(blockRoot);
|
|
1080
1070
|
|
|
1081
1071
|
const fork = this.config.getForkName(slot);
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
throw Error(`Unexpected block type=${produceResult.type} for post-gloas fork=${fork}`);
|
|
1086
|
-
}
|
|
1087
|
-
|
|
1088
|
-
const gloasResult = produceResult as ProduceFullGloas;
|
|
1089
|
-
const envelope: gloas.ExecutionPayloadEnvelope = {
|
|
1090
|
-
payload: gloasResult.executionPayload,
|
|
1091
|
-
executionRequests: gloasResult.executionRequests,
|
|
1092
|
-
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
1093
|
-
beaconBlockRoot: blockRoot,
|
|
1094
|
-
slot,
|
|
1095
|
-
stateRoot: ZERO_HASH,
|
|
1096
|
-
};
|
|
1097
|
-
if (!isStatePostGloas(postBlockState)) {
|
|
1098
|
-
throw Error(`Expected gloas+ post-state for execution payload envelope, got fork=${postBlockState.forkName}`);
|
|
1099
|
-
}
|
|
1100
|
-
const payloadEnvelopeStateRoot = computePayloadEnvelopeStateRoot(this.metrics, postBlockState, envelope);
|
|
1101
|
-
gloasResult.payloadEnvelopeStateRoot = payloadEnvelopeStateRoot;
|
|
1072
|
+
// TODO GLOAS: we should retire BlockType post-gloas, may need a new enum for self vs non-self built
|
|
1073
|
+
if (isForkPostGloas(fork) && produceResult.type !== BlockType.Full) {
|
|
1074
|
+
throw Error(`Unexpected block type=${produceResult.type} for post-gloas fork=${fork}`);
|
|
1102
1075
|
}
|
|
1103
1076
|
|
|
1104
1077
|
// Track the produced block for consensus broadcast validations, later validation, etc.
|
|
@@ -1346,8 +1319,8 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1346
1319
|
checkpoint: CheckpointWithPayloadStatus,
|
|
1347
1320
|
blockState: IBeaconStateView
|
|
1348
1321
|
): {state: IBeaconStateView; stateId: string; shouldWarn: boolean} {
|
|
1349
|
-
const
|
|
1350
|
-
const state = this.regen.getCheckpointStateSync(
|
|
1322
|
+
const checkpointHex = {epoch: checkpoint.epoch, rootHex: checkpoint.rootHex};
|
|
1323
|
+
const state = this.regen.getCheckpointStateSync(checkpointHex);
|
|
1351
1324
|
if (state) {
|
|
1352
1325
|
return {state, stateId: "checkpoint_state", shouldWarn: false};
|
|
1353
1326
|
}
|
|
@@ -1471,10 +1444,6 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1471
1444
|
private onClockEpoch(epoch: Epoch): void {
|
|
1472
1445
|
this.metrics?.clockEpoch.set(epoch);
|
|
1473
1446
|
|
|
1474
|
-
if (epoch === this.config.GLOAS_FORK_EPOCH) {
|
|
1475
|
-
this.regen.upgradeForGloas(epoch);
|
|
1476
|
-
}
|
|
1477
|
-
|
|
1478
1447
|
this.seenAttesters.prune(epoch);
|
|
1479
1448
|
this.seenAggregators.prune(epoch);
|
|
1480
1449
|
this.seenPayloadAttesters.prune(epoch);
|