@lodestar/beacon-node 1.42.0-dev.d32f5153b6 → 1.42.0-dev.d4d0b21dfe
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 +11 -11
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +4 -0
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +13 -10
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +4 -0
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +9 -3
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +2 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +5 -5
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +2 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +14 -12
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +5 -5
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/blockInput/types.d.ts +4 -4
- package/lib/chain/blocks/blockInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +19 -5
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +14 -5
- 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 +14 -6
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +33 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.d.ts +3 -3
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +3 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +4 -2
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/chain.d.ts +3 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +68 -28
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +29 -7
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +12 -3
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +11 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +4 -0
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +31 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js +7 -0
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +10 -8
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -2
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -2
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +7 -0
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +5 -2
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +2 -2
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +2 -2
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +7 -1
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -3
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +8 -8
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +5 -5
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +23 -4
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +2 -2
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +2 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +27 -5
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts +11 -4
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +184 -5
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +7 -4
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +6 -1
- 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 -1
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/syncCommittee.d.ts.map +1 -1
- package/lib/chain/validation/syncCommittee.js +4 -0
- package/lib/chain/validation/syncCommittee.js.map +1 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js +4 -1
- package/lib/chain/validation/syncCommitteeContributionAndProof.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +3 -3
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/buckets.d.ts +2 -2
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -2
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +2 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecar.js +4 -2
- package/lib/db/repositories/dataColumnSidecar.js.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +4 -2
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +20 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +33 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -729
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/interface.d.ts +3 -2
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +3 -2
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +3 -0
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts +1 -1
- package/lib/network/processor/extractSlotRootFns.d.ts.map +1 -1
- package/lib/network/processor/extractSlotRootFns.js +25 -5
- package/lib/network/processor/extractSlotRootFns.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +246 -66
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +11 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +234 -22
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/types.d.ts +3 -3
- package/lib/network/reqresp/types.d.ts.map +1 -1
- package/lib/network/reqresp/types.js +9 -3
- package/lib/network/reqresp/types.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +2 -2
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/unknownBlock.js +2 -2
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +3 -3
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +4 -2
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts +3 -3
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +10 -5
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/util/blobs.d.ts +3 -3
- package/lib/util/blobs.d.ts.map +1 -1
- package/lib/util/blobs.js +21 -10
- package/lib/util/blobs.js.map +1 -1
- package/lib/util/dataColumns.d.ts +18 -11
- package/lib/util/dataColumns.d.ts.map +1 -1
- package/lib/util/dataColumns.js +51 -17
- package/lib/util/dataColumns.js.map +1 -1
- package/lib/util/execution.d.ts +6 -2
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +49 -25
- package/lib/util/execution.js.map +1 -1
- package/lib/util/sszBytes.d.ts +25 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +189 -2
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +15 -15
- package/src/api/impl/beacon/blocks/index.ts +17 -14
- package/src/api/impl/beacon/pool/index.ts +4 -0
- package/src/api/impl/beacon/state/index.ts +15 -15
- package/src/api/impl/debug/index.ts +2 -2
- package/src/api/impl/lodestar/index.ts +4 -0
- package/src/api/impl/validator/index.ts +9 -2
- package/src/chain/ColumnReconstructionTracker.ts +6 -5
- package/src/chain/GetBlobsTracker.ts +14 -12
- package/src/chain/blocks/blockInput/blockInput.ts +8 -8
- package/src/chain/blocks/blockInput/types.ts +4 -4
- package/src/chain/blocks/importBlock.ts +29 -8
- package/src/chain/blocks/importExecutionPayload.ts +15 -5
- package/src/chain/blocks/index.ts +1 -1
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +53 -12
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
- package/src/chain/blocks/types.ts +3 -3
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +2 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
- package/src/chain/chain.ts +77 -32
- package/src/chain/emitter.ts +25 -7
- package/src/chain/errors/blockError.ts +7 -1
- package/src/chain/errors/dataColumnSidecarError.ts +32 -1
- package/src/chain/forkChoice/index.ts +11 -8
- package/src/chain/interface.ts +4 -2
- package/src/chain/lightClient/index.ts +15 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +6 -1
- package/src/chain/opPools/executionPayloadBidPool.ts +3 -3
- package/src/chain/prepareNextSlot.ts +8 -0
- package/src/chain/produceBlock/computeNewStateRoot.ts +11 -10
- package/src/chain/produceBlock/produceBlockBody.ts +40 -10
- package/src/chain/seenCache/seenGossipBlockInput.ts +2 -2
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +2 -2
- package/src/chain/validation/block.ts +30 -7
- package/src/chain/validation/dataColumnSidecar.ts +230 -7
- package/src/chain/validation/executionPayloadBid.ts +7 -3
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -1
- package/src/chain/validation/payloadAttestationMessage.ts +4 -0
- package/src/chain/validation/syncCommittee.ts +5 -1
- package/src/chain/validation/syncCommitteeContributionAndProof.ts +5 -1
- package/src/chain/validatorMonitor.ts +3 -2
- package/src/db/buckets.ts +2 -2
- package/src/db/repositories/dataColumnSidecar.ts +4 -2
- package/src/db/repositories/dataColumnSidecarArchive.ts +4 -2
- package/src/metrics/metrics/lodestar.ts +34 -0
- package/src/network/interface.ts +3 -2
- package/src/network/network.ts +7 -4
- package/src/network/processor/extractSlotRootFns.ts +32 -6
- package/src/network/processor/gossipHandlers.ts +310 -79
- package/src/network/processor/index.ts +304 -22
- package/src/network/reqresp/types.ts +13 -5
- package/src/node/nodejs.ts +5 -2
- package/src/node/notifier.ts +7 -2
- package/src/sync/unknownBlock.ts +3 -3
- package/src/sync/utils/downloadByRange.ts +9 -7
- package/src/sync/utils/downloadByRoot.ts +16 -12
- package/src/util/blobs.ts +35 -15
- package/src/util/dataColumns.ts +69 -25
- package/src/util/execution.ts +49 -30
- package/src/util/sszBytes.ts +245 -3
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
computeStartSlotAtEpoch,
|
|
26
26
|
computeTimeAtSlot,
|
|
27
27
|
getCurrentSlot,
|
|
28
|
+
isStatePostAltair,
|
|
28
29
|
proposerShufflingDecisionRoot,
|
|
29
30
|
} from "@lodestar/state-transition";
|
|
30
31
|
import {
|
|
@@ -1282,6 +1283,9 @@ export function getValidatorApi(
|
|
|
1282
1283
|
if (indices.length === 0) {
|
|
1283
1284
|
throw new ApiError(400, "No validator to get attester duties");
|
|
1284
1285
|
}
|
|
1286
|
+
if (epoch < config.ALTAIR_FORK_EPOCH) {
|
|
1287
|
+
throw new ApiError(400, "Sync committee duties are not supported before Altair");
|
|
1288
|
+
}
|
|
1285
1289
|
|
|
1286
1290
|
// May request for an epoch that's in the future
|
|
1287
1291
|
await waitForNextClosestEpoch();
|
|
@@ -1291,6 +1295,9 @@ export function getValidatorApi(
|
|
|
1291
1295
|
// Note: does not support requesting past duties
|
|
1292
1296
|
const head = chain.forkChoice.getHead();
|
|
1293
1297
|
const state = chain.getHeadState();
|
|
1298
|
+
if (!isStatePostAltair(state)) {
|
|
1299
|
+
throw new ApiError(400, "Sync committee duties are not available before Altair");
|
|
1300
|
+
}
|
|
1294
1301
|
|
|
1295
1302
|
// Check that all validatorIndex belong to the state before calling getCommitteeAssignments()
|
|
1296
1303
|
const pubkeys = getPubkeysForIndices(state, indices);
|
|
@@ -1635,7 +1642,7 @@ export function getValidatorApi(
|
|
|
1635
1642
|
throw Error("Cached block production result is not full block");
|
|
1636
1643
|
}
|
|
1637
1644
|
|
|
1638
|
-
const {executionPayload, executionRequests,
|
|
1645
|
+
const {executionPayload, executionRequests, payloadEnvelopeStateRoot} = produceResult as ProduceFullGloas;
|
|
1639
1646
|
|
|
1640
1647
|
const envelope: gloas.ExecutionPayloadEnvelope = {
|
|
1641
1648
|
payload: executionPayload,
|
|
@@ -1643,7 +1650,7 @@ export function getValidatorApi(
|
|
|
1643
1650
|
builderIndex: BUILDER_INDEX_SELF_BUILD,
|
|
1644
1651
|
beaconBlockRoot,
|
|
1645
1652
|
slot,
|
|
1646
|
-
stateRoot:
|
|
1653
|
+
stateRoot: payloadEnvelopeStateRoot,
|
|
1647
1654
|
};
|
|
1648
1655
|
|
|
1649
1656
|
logger.info("Produced execution payload envelope", {
|
|
@@ -3,6 +3,7 @@ import {Logger, sleep} from "@lodestar/utils";
|
|
|
3
3
|
import {Metrics} from "../metrics/metrics.js";
|
|
4
4
|
import {DataColumnReconstructionCode, recoverDataColumnSidecars} from "../util/dataColumns.js";
|
|
5
5
|
import {BlockInputColumns} from "./blocks/blockInput/index.js";
|
|
6
|
+
import {PayloadEnvelopeInput} from "./blocks/payloadEnvelopeInput/index.js";
|
|
6
7
|
import {ChainEventEmitter} from "./emitter.js";
|
|
7
8
|
|
|
8
9
|
/**
|
|
@@ -53,25 +54,25 @@ export class ColumnReconstructionTracker {
|
|
|
53
54
|
this.maxDelayMs = this.config.getSlotComponentDurationMs(RECONSTRUCTION_DELAY_MAX_BPS);
|
|
54
55
|
}
|
|
55
56
|
|
|
56
|
-
triggerColumnReconstruction(
|
|
57
|
+
triggerColumnReconstruction(input: BlockInputColumns | PayloadEnvelopeInput): void {
|
|
57
58
|
if (this.running) {
|
|
58
59
|
return;
|
|
59
60
|
}
|
|
60
61
|
|
|
61
|
-
if (this.lastBlockRootHex ===
|
|
62
|
+
if (this.lastBlockRootHex === input.blockRootHex) {
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
// We don't care about the outcome of this call,
|
|
66
67
|
// just that it has been triggered for this block root.
|
|
67
68
|
this.running = true;
|
|
68
|
-
this.lastBlockRootHex =
|
|
69
|
+
this.lastBlockRootHex = input.blockRootHex;
|
|
69
70
|
const delay = this.minDelayMs + Math.random() * (this.maxDelayMs - this.minDelayMs);
|
|
70
71
|
sleep(delay)
|
|
71
72
|
.then(() => {
|
|
72
|
-
const logCtx = {slot:
|
|
73
|
+
const logCtx = {slot: input.slot, root: input.blockRootHex};
|
|
73
74
|
this.logger.debug("Attempting data column sidecar reconstruction", logCtx);
|
|
74
|
-
recoverDataColumnSidecars(
|
|
75
|
+
recoverDataColumnSidecars(input, this.emitter, this.metrics)
|
|
75
76
|
.then((result) => {
|
|
76
77
|
this.metrics?.recoverDataColumnSidecars.reconstructionResult.inc({result});
|
|
77
78
|
this.logger.debug("Data column sidecar reconstruction complete", {...logCtx, result});
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
getDataColumnSidecarsFromExecution,
|
|
12
12
|
} from "../util/execution.js";
|
|
13
13
|
import {IBlockInput, isBlockInputBlobs} from "./blocks/blockInput/index.js";
|
|
14
|
+
import {PayloadEnvelopeInput} from "./blocks/payloadEnvelopeInput/index.js";
|
|
14
15
|
import {ChainEventEmitter} from "./emitter.js";
|
|
15
16
|
|
|
16
17
|
export type GetBlobsTrackerInit = {
|
|
@@ -43,22 +44,22 @@ export class GetBlobsTracker {
|
|
|
43
44
|
this.config = init.config;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
triggerGetBlobs(
|
|
47
|
-
if (this.activeReconstructions.has(
|
|
47
|
+
triggerGetBlobs(input: IBlockInput | PayloadEnvelopeInput, onComplete?: () => void): void {
|
|
48
|
+
if (this.activeReconstructions.has(input.blockRootHex)) {
|
|
48
49
|
return;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
if (isBlockInputBlobs(
|
|
52
|
+
if (!(input instanceof PayloadEnvelopeInput) && isBlockInputBlobs(input)) {
|
|
52
53
|
// there is not preallocation for blob sidecars like there is for columns sidecars so no need to
|
|
53
54
|
// store the index for the preallocated buffers
|
|
54
|
-
this.activeReconstructions.add(
|
|
55
|
+
this.activeReconstructions.add(input.blockRootHex);
|
|
55
56
|
callInNextEventLoop(() => {
|
|
56
|
-
const logCtx = {slot:
|
|
57
|
+
const logCtx = {slot: input.slot, root: input.blockRootHex};
|
|
57
58
|
this.logger.verbose("Trigger getBlobsV1 for block", logCtx);
|
|
58
|
-
getBlobSidecarsFromExecution(this.config, this.executionEngine, this.metrics, this.emitter,
|
|
59
|
+
getBlobSidecarsFromExecution(this.config, this.executionEngine, this.metrics, this.emitter, input).finally(
|
|
59
60
|
() => {
|
|
60
61
|
this.logger.verbose("Completed getBlobsV1 for block", logCtx);
|
|
61
|
-
this.activeReconstructions.delete(
|
|
62
|
+
this.activeReconstructions.delete(input.blockRootHex);
|
|
62
63
|
}
|
|
63
64
|
);
|
|
64
65
|
});
|
|
@@ -72,7 +73,7 @@ export class GetBlobsTracker {
|
|
|
72
73
|
this.blobsAndProofsBuffers[freeIndex] = {inUse: false, buffers: []};
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
const maxBlobs = this.config.getMaxBlobsPerBlock(computeEpochAtSlot(
|
|
76
|
+
const maxBlobs = this.config.getMaxBlobsPerBlock(computeEpochAtSlot(input.slot));
|
|
76
77
|
// double check that there is enough pre-allocated space (blob schedule may have changed since the last use)
|
|
77
78
|
const timer = this.metrics?.peerDas.getBlobsV2PreAllocationTime.startTimer();
|
|
78
79
|
for (let i = 0; i < maxBlobs; i++) {
|
|
@@ -84,22 +85,23 @@ export class GetBlobsTracker {
|
|
|
84
85
|
|
|
85
86
|
// We don't care about the outcome of this call,
|
|
86
87
|
// just that it has been triggered for this block root.
|
|
87
|
-
this.activeReconstructions.add(
|
|
88
|
+
this.activeReconstructions.add(input.blockRootHex);
|
|
88
89
|
this.blobsAndProofsBuffers[freeIndex].inUse = true;
|
|
89
90
|
callInNextEventLoop(() => {
|
|
90
|
-
const logCtx = {slot:
|
|
91
|
+
const logCtx = {slot: input.slot, root: input.blockRootHex};
|
|
91
92
|
this.logger.verbose("Trigger getBlobsV2 for block", logCtx);
|
|
92
93
|
getDataColumnSidecarsFromExecution(
|
|
93
94
|
this.config,
|
|
94
95
|
this.executionEngine,
|
|
95
96
|
this.emitter,
|
|
96
|
-
|
|
97
|
+
input,
|
|
97
98
|
this.metrics,
|
|
98
99
|
this.blobsAndProofsBuffers[freeIndex].buffers
|
|
99
100
|
)
|
|
100
101
|
.then((result) => {
|
|
101
102
|
this.logger.debug("getBlobsV2 result for block", {...logCtx, result});
|
|
102
103
|
this.metrics?.dataColumns.dataColumnEngineResult.inc({result});
|
|
104
|
+
onComplete?.();
|
|
103
105
|
})
|
|
104
106
|
.catch((error) => {
|
|
105
107
|
this.logger.debug("Error during getBlobsV2 for block", logCtx, error as Error);
|
|
@@ -107,7 +109,7 @@ export class GetBlobsTracker {
|
|
|
107
109
|
})
|
|
108
110
|
.finally(() => {
|
|
109
111
|
this.logger.verbose("Completed getBlobsV2 for block", logCtx);
|
|
110
|
-
this.activeReconstructions.delete(
|
|
112
|
+
this.activeReconstructions.delete(input.blockRootHex);
|
|
111
113
|
this.blobsAndProofsBuffers[freeIndex].inUse = false;
|
|
112
114
|
});
|
|
113
115
|
});
|
|
@@ -617,7 +617,7 @@ type BlockInputColumnsState =
|
|
|
617
617
|
* - The block is not yet seen and all required sampled columns are seen
|
|
618
618
|
* - The block is not yet seen and all required sampled columns are not yet seen
|
|
619
619
|
*/
|
|
620
|
-
export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.
|
|
620
|
+
export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.DataColumnSidecar[]> {
|
|
621
621
|
type = DAType.Columns as const;
|
|
622
622
|
|
|
623
623
|
state: BlockInputColumnsState;
|
|
@@ -630,7 +630,7 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
630
630
|
*
|
|
631
631
|
* This is different from `dataPromise` which resolves when all data is available or could become available (e.g. through reconstruction)
|
|
632
632
|
*/
|
|
633
|
-
protected computedDataPromise = createPromise<fulu.
|
|
633
|
+
protected computedDataPromise = createPromise<fulu.DataColumnSidecar[]>();
|
|
634
634
|
|
|
635
635
|
private constructor(
|
|
636
636
|
init: BlockInputInit,
|
|
@@ -854,8 +854,8 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
854
854
|
return this.state.versionedHashes;
|
|
855
855
|
}
|
|
856
856
|
|
|
857
|
-
getCustodyColumns(): fulu.
|
|
858
|
-
const columns: fulu.
|
|
857
|
+
getCustodyColumns(): fulu.DataColumnSidecar[] {
|
|
858
|
+
const columns: fulu.DataColumnSidecar[] = [];
|
|
859
859
|
for (const index of this.custodyColumns) {
|
|
860
860
|
const column = this.columnsCache.get(index);
|
|
861
861
|
if (column) {
|
|
@@ -876,8 +876,8 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
876
876
|
return columns;
|
|
877
877
|
}
|
|
878
878
|
|
|
879
|
-
getSampledColumns(): fulu.
|
|
880
|
-
const columns: fulu.
|
|
879
|
+
getSampledColumns(): fulu.DataColumnSidecar[] {
|
|
880
|
+
const columns: fulu.DataColumnSidecar[] = [];
|
|
881
881
|
for (const index of this.sampledColumns) {
|
|
882
882
|
const column = this.columnsCache.get(index);
|
|
883
883
|
if (column) {
|
|
@@ -891,7 +891,7 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
891
891
|
return [...this.columnsCache.values()];
|
|
892
892
|
}
|
|
893
893
|
|
|
894
|
-
getAllColumns(): fulu.
|
|
894
|
+
getAllColumns(): fulu.DataColumnSidecar[] {
|
|
895
895
|
return this.getAllColumnsWithSource().map(({columnSidecar}) => columnSidecar);
|
|
896
896
|
}
|
|
897
897
|
|
|
@@ -919,7 +919,7 @@ export class BlockInputColumns extends AbstractBlockInput<ForkColumnsDA, fulu.Da
|
|
|
919
919
|
return this.state.hasComputedAllData;
|
|
920
920
|
}
|
|
921
921
|
|
|
922
|
-
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<fulu.
|
|
922
|
+
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<fulu.DataColumnSidecar[]> {
|
|
923
923
|
if (!this.state.hasComputedAllData) {
|
|
924
924
|
return withTimeout(() => this.computedDataPromise.promise, timeout, signal);
|
|
925
925
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {ForkName} from "@lodestar/params";
|
|
2
|
-
import {ColumnIndex,
|
|
2
|
+
import {ColumnIndex, DataColumnSidecar, RootHex, SignedBeaconBlock, Slot, deneb, fulu} from "@lodestar/types";
|
|
3
3
|
import {VersionedHashes} from "../../../execution/index.js";
|
|
4
4
|
|
|
5
5
|
export enum DAType {
|
|
@@ -9,7 +9,7 @@ export enum DAType {
|
|
|
9
9
|
NoData = "no-data",
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export type DAData = null | deneb.BlobSidecars | fulu.
|
|
12
|
+
export type DAData = null | deneb.BlobSidecars | fulu.DataColumnSidecar[];
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Represents were input originated. Blocks and Data can come from different
|
|
@@ -108,9 +108,9 @@ export type MissingColumnMeta = {
|
|
|
108
108
|
export interface IDataColumnsInput {
|
|
109
109
|
readonly slot: Slot;
|
|
110
110
|
readonly blockRootHex: string;
|
|
111
|
-
getCustodyColumns():
|
|
111
|
+
getCustodyColumns(): DataColumnSidecar[];
|
|
112
112
|
hasComputedAllData(): boolean;
|
|
113
|
-
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<
|
|
113
|
+
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<DataColumnSidecar[]>;
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/**
|
|
@@ -25,6 +25,8 @@ import {
|
|
|
25
25
|
computeStartSlotAtEpoch,
|
|
26
26
|
computeTimeAtSlot,
|
|
27
27
|
isStartSlotOfEpoch,
|
|
28
|
+
isStatePostAltair,
|
|
29
|
+
isStatePostBellatrix,
|
|
28
30
|
} from "@lodestar/state-transition";
|
|
29
31
|
import {
|
|
30
32
|
Attestation,
|
|
@@ -140,9 +142,10 @@ export async function importBlock(
|
|
|
140
142
|
|
|
141
143
|
// For Gloas blocks, create PayloadEnvelopeInput so it's available for later payload import
|
|
142
144
|
if (fork >= ForkSeq.gloas) {
|
|
143
|
-
this.seenPayloadEnvelopeInputCache.add({
|
|
145
|
+
const payloadInput = this.seenPayloadEnvelopeInputCache.add({
|
|
144
146
|
blockRootHex,
|
|
145
147
|
block: block as SignedBeaconBlock<ForkPostGloas>,
|
|
148
|
+
forkName: blockInput.forkName,
|
|
146
149
|
sampledColumns: this.custodyConfig.sampledColumns,
|
|
147
150
|
custodyColumns: this.custodyConfig.custodyColumns,
|
|
148
151
|
timeCreatedSec: fullyVerifiedBlock.seenTimestampSec,
|
|
@@ -153,6 +156,22 @@ export async function importBlock(
|
|
|
153
156
|
source: source.source,
|
|
154
157
|
...(opts.seenTimestampSec !== undefined ? {recvToImport: Date.now() / 1000 - opts.seenTimestampSec} : {}),
|
|
155
158
|
});
|
|
159
|
+
|
|
160
|
+
// Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
|
|
161
|
+
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
162
|
+
// TODO GLOAS: If we want EL retries after this initial attempt, add an explicit retry policy here
|
|
163
|
+
// (for example later in the slot). Do not couple retries to incoming gossip columns.
|
|
164
|
+
this.getBlobsTracker.triggerGetBlobs(payloadInput, () => {
|
|
165
|
+
// TODO GLOAS: come up with a better mechanism to trigger processExecutionPayload after data becomes available,
|
|
166
|
+
// similar to how pre-gloas uses waitForBlockAndAllData with a cutoff timeout and incompleteBlockInput event
|
|
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
|
+
});
|
|
156
175
|
}
|
|
157
176
|
|
|
158
177
|
this.metrics?.importBlock.bySource.inc({source: source.source});
|
|
@@ -371,11 +390,13 @@ export async function importBlock(
|
|
|
371
390
|
// we want to import block asap so do this in the next event loop
|
|
372
391
|
callInNextEventLoop(() => {
|
|
373
392
|
try {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
393
|
+
if (isStatePostAltair(postBlockState)) {
|
|
394
|
+
this.lightClientServer?.onImportBlockHead(
|
|
395
|
+
block.message as BeaconBlock<ForkPostAltair>,
|
|
396
|
+
postBlockState,
|
|
397
|
+
parentBlockSlot
|
|
398
|
+
);
|
|
399
|
+
}
|
|
379
400
|
} catch (e) {
|
|
380
401
|
this.logger.verbose("Error lightClientServer.onImportBlock", {slot: blockSlot}, e as Error);
|
|
381
402
|
}
|
|
@@ -394,7 +415,7 @@ export async function importBlock(
|
|
|
394
415
|
// and the block is weak and can potentially be reorged out.
|
|
395
416
|
let shouldOverrideFcu = false;
|
|
396
417
|
|
|
397
|
-
if (blockSlot >= currentSlot && postBlockState.isExecutionStateType) {
|
|
418
|
+
if (blockSlot >= currentSlot && isStatePostBellatrix(postBlockState) && postBlockState.isExecutionStateType) {
|
|
398
419
|
let notOverrideFcuReason = NotReorgedReason.Unknown;
|
|
399
420
|
const proposalSlot = blockSlot + 1;
|
|
400
421
|
try {
|
|
@@ -581,7 +602,7 @@ export async function importBlock(
|
|
|
581
602
|
this.metrics?.parentBlockDistance.observe(blockSlot - parentBlockSlot);
|
|
582
603
|
this.metrics?.proposerBalanceDeltaAny.observe(fullyVerifiedBlock.proposerBalanceDelta);
|
|
583
604
|
this.validatorMonitor?.registerImportedBlock(block.message, fullyVerifiedBlock);
|
|
584
|
-
if (
|
|
605
|
+
if (isStatePostAltair(fullyVerifiedBlock.postBlockState)) {
|
|
585
606
|
this.validatorMonitor?.registerSyncAggregateInBlock(
|
|
586
607
|
blockEpoch,
|
|
587
608
|
(block as altair.SignedBeaconBlock).message.body.syncAggregate,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
3
|
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
4
|
-
import {getExecutionPayloadEnvelopeSignatureSet} from "@lodestar/state-transition";
|
|
4
|
+
import {getExecutionPayloadEnvelopeSignatureSet, isStatePostGloas} from "@lodestar/state-transition";
|
|
5
5
|
import {byteArrayEquals, fromHex, toRootHex} from "@lodestar/utils";
|
|
6
6
|
import {ExecutionPayloadStatus} from "../../execution/index.js";
|
|
7
7
|
import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
@@ -96,7 +96,7 @@ export async function importExecutionPayload(
|
|
|
96
96
|
// is already complete, so the payload and required data are available for payload attestation.
|
|
97
97
|
// This event is only about availability, not validity of the execution payload, hence we can emit
|
|
98
98
|
// it before getting a response from the execution client on whether the payload is valid or not.
|
|
99
|
-
if (this.clock.currentSlot
|
|
99
|
+
if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
100
100
|
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
101
|
slot: envelope.slot,
|
|
102
102
|
blockRoot: blockRootHex,
|
|
@@ -124,6 +124,12 @@ export async function importExecutionPayload(
|
|
|
124
124
|
{dontTransferCache: true},
|
|
125
125
|
RegenCaller.processBlock
|
|
126
126
|
);
|
|
127
|
+
if (!isStatePostGloas(blockState)) {
|
|
128
|
+
throw new PayloadError({
|
|
129
|
+
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
130
|
+
message: `Expected gloas+ block state for payload import, got fork=${blockState.forkName}`,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
127
133
|
|
|
128
134
|
// 5. Run verification steps in parallel
|
|
129
135
|
// Note: No data availability check needed here - importExecutionPayload is only
|
|
@@ -218,7 +224,7 @@ export async function importExecutionPayload(
|
|
|
218
224
|
if (!isQueueErrorAborted(e)) {
|
|
219
225
|
this.logger.error(
|
|
220
226
|
"Error pushing payload envelope to unfinalized write queue",
|
|
221
|
-
{slot: envelope.slot,
|
|
227
|
+
{slot: envelope.slot, blockRoot: blockRootHex},
|
|
222
228
|
e as Error
|
|
223
229
|
);
|
|
224
230
|
}
|
|
@@ -246,6 +252,8 @@ export async function importExecutionPayload(
|
|
|
246
252
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
247
253
|
}
|
|
248
254
|
|
|
255
|
+
const stateRootHex = toRootHex(envelope.stateRoot);
|
|
256
|
+
|
|
249
257
|
// 10. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
250
258
|
if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
251
259
|
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
@@ -253,7 +261,7 @@ export async function importExecutionPayload(
|
|
|
253
261
|
builderIndex: envelope.builderIndex,
|
|
254
262
|
blockHash: blockHashHex,
|
|
255
263
|
blockRoot: blockRootHex,
|
|
256
|
-
stateRoot:
|
|
264
|
+
stateRoot: stateRootHex,
|
|
257
265
|
// TODO GLOAS: revisit once we support optimistic import
|
|
258
266
|
executionOptimistic: false,
|
|
259
267
|
});
|
|
@@ -261,7 +269,9 @@ export async function importExecutionPayload(
|
|
|
261
269
|
|
|
262
270
|
this.logger.verbose("Execution payload imported", {
|
|
263
271
|
slot: envelope.slot,
|
|
264
|
-
|
|
272
|
+
builderIndex: envelope.builderIndex,
|
|
273
|
+
blockRoot: blockRootHex,
|
|
265
274
|
blockHash: blockHashHex,
|
|
275
|
+
stateRoot: stateRootHex,
|
|
266
276
|
});
|
|
267
277
|
}
|
|
@@ -89,7 +89,7 @@ export async function processBlocks(
|
|
|
89
89
|
(block, i): FullyVerifiedBlock => ({
|
|
90
90
|
blockInput: block,
|
|
91
91
|
postBlockState: postStates[i],
|
|
92
|
-
|
|
92
|
+
postPayloadState: null,
|
|
93
93
|
parentBlockSlot: parentSlots[i],
|
|
94
94
|
executionStatus: executionStatuses[i],
|
|
95
95
|
// start supporting optimistic syncing/processing
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
-
import {ColumnIndex,
|
|
1
|
+
import {ForkName, NUMBER_OF_COLUMNS} from "@lodestar/params";
|
|
2
|
+
import {ColumnIndex, RootHex, Slot, ValidatorIndex, deneb, gloas} from "@lodestar/types";
|
|
3
3
|
import {toRootHex, withTimeout} from "@lodestar/utils";
|
|
4
4
|
import {VersionedHashes} from "../../../execution/index.js";
|
|
5
5
|
import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
|
|
6
|
+
import {MissingColumnMeta} from "../blockInput/types.js";
|
|
6
7
|
import {AddPayloadEnvelopeProps, ColumnWithSource, CreateFromBlockProps, SourceMeta} from "./types.js";
|
|
7
8
|
|
|
8
9
|
export type PayloadEnvelopeInputState =
|
|
@@ -59,6 +60,7 @@ function createPromise<T>(): PromiseParts<T> {
|
|
|
59
60
|
export class PayloadEnvelopeInput {
|
|
60
61
|
readonly blockRootHex: RootHex;
|
|
61
62
|
readonly slot: Slot;
|
|
63
|
+
readonly forkName: ForkName;
|
|
62
64
|
readonly proposerIndex: ValidatorIndex;
|
|
63
65
|
readonly bid: gloas.ExecutionPayloadBid;
|
|
64
66
|
readonly versionedHashes: VersionedHashes;
|
|
@@ -71,13 +73,14 @@ export class PayloadEnvelopeInput {
|
|
|
71
73
|
private timeCreatedSec: number;
|
|
72
74
|
|
|
73
75
|
private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
|
|
74
|
-
private readonly columnsDataPromise: PromiseParts<
|
|
76
|
+
private readonly columnsDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
75
77
|
|
|
76
78
|
state: PayloadEnvelopeInputState;
|
|
77
79
|
|
|
78
80
|
private constructor(props: {
|
|
79
81
|
blockRootHex: RootHex;
|
|
80
82
|
slot: Slot;
|
|
83
|
+
forkName: ForkName;
|
|
81
84
|
proposerIndex: ValidatorIndex;
|
|
82
85
|
bid: gloas.ExecutionPayloadBid;
|
|
83
86
|
sampledColumns: ColumnIndex[];
|
|
@@ -86,6 +89,7 @@ export class PayloadEnvelopeInput {
|
|
|
86
89
|
}) {
|
|
87
90
|
this.blockRootHex = props.blockRootHex;
|
|
88
91
|
this.slot = props.slot;
|
|
92
|
+
this.forkName = props.forkName;
|
|
89
93
|
this.proposerIndex = props.proposerIndex;
|
|
90
94
|
this.bid = props.bid;
|
|
91
95
|
this.versionedHashes = props.bid.blobKzgCommitments.map(kzgCommitmentToVersionedHash);
|
|
@@ -112,6 +116,7 @@ export class PayloadEnvelopeInput {
|
|
|
112
116
|
return new PayloadEnvelopeInput({
|
|
113
117
|
blockRootHex: props.blockRootHex,
|
|
114
118
|
slot: props.block.message.slot,
|
|
119
|
+
forkName: props.forkName,
|
|
115
120
|
proposerIndex: props.block.message.proposerIndex,
|
|
116
121
|
bid,
|
|
117
122
|
sampledColumns: props.sampledColumns,
|
|
@@ -173,8 +178,12 @@ export class PayloadEnvelopeInput {
|
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
180
|
|
|
176
|
-
addColumn(columnWithSource: ColumnWithSource):
|
|
181
|
+
addColumn(columnWithSource: ColumnWithSource): boolean {
|
|
177
182
|
const {columnSidecar, seenTimestampSec} = columnWithSource;
|
|
183
|
+
if (this.columnsCache.has(columnSidecar.index)) {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
178
187
|
this.columnsCache.set(columnSidecar.index, columnWithSource);
|
|
179
188
|
|
|
180
189
|
const sampledColumns = this.getSampledColumns();
|
|
@@ -191,7 +200,7 @@ export class PayloadEnvelopeInput {
|
|
|
191
200
|
sampledColumns.length === this.sampledColumns.length;
|
|
192
201
|
|
|
193
202
|
if (!hasAllData) {
|
|
194
|
-
return;
|
|
203
|
+
return true;
|
|
195
204
|
}
|
|
196
205
|
|
|
197
206
|
if (hasComputedAllData) {
|
|
@@ -217,6 +226,20 @@ export class PayloadEnvelopeInput {
|
|
|
217
226
|
hasComputedAllData: hasComputedAllData || this.state.hasComputedAllData,
|
|
218
227
|
};
|
|
219
228
|
}
|
|
229
|
+
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
hasColumn(index: ColumnIndex): boolean {
|
|
234
|
+
return this.columnsCache.has(index);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
getColumn(index: ColumnIndex): gloas.DataColumnSidecar | undefined {
|
|
238
|
+
return this.columnsCache.get(index)?.columnSidecar;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
getAllColumns(): gloas.DataColumnSidecar[] {
|
|
242
|
+
return [...this.columnsCache.values()].map(({columnSidecar}) => columnSidecar);
|
|
220
243
|
}
|
|
221
244
|
|
|
222
245
|
getVersionedHashes(): VersionedHashes {
|
|
@@ -237,8 +260,8 @@ export class PayloadEnvelopeInput {
|
|
|
237
260
|
return this.state.payloadEnvelopeSource;
|
|
238
261
|
}
|
|
239
262
|
|
|
240
|
-
getSampledColumns(): gloas.
|
|
241
|
-
const columns: gloas.
|
|
263
|
+
getSampledColumns(): gloas.DataColumnSidecar[] {
|
|
264
|
+
const columns: gloas.DataColumnSidecar[] = [];
|
|
242
265
|
for (const index of this.sampledColumns) {
|
|
243
266
|
const column = this.columnsCache.get(index);
|
|
244
267
|
if (column) {
|
|
@@ -259,8 +282,8 @@ export class PayloadEnvelopeInput {
|
|
|
259
282
|
return columns;
|
|
260
283
|
}
|
|
261
284
|
|
|
262
|
-
getCustodyColumns(): gloas.
|
|
263
|
-
const columns: gloas.
|
|
285
|
+
getCustodyColumns(): gloas.DataColumnSidecar[] {
|
|
286
|
+
const columns: gloas.DataColumnSidecar[] = [];
|
|
264
287
|
for (const index of this.custodyColumns) {
|
|
265
288
|
const column = this.columnsCache.get(index);
|
|
266
289
|
if (column) {
|
|
@@ -270,11 +293,29 @@ export class PayloadEnvelopeInput {
|
|
|
270
293
|
return columns;
|
|
271
294
|
}
|
|
272
295
|
|
|
296
|
+
hasAllData(): boolean {
|
|
297
|
+
return this.state.hasAllData;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
getMissingSampledColumnMeta(): MissingColumnMeta {
|
|
301
|
+
if (this.state.hasAllData) {
|
|
302
|
+
return {missing: [], versionedHashes: this.versionedHashes};
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
const missing: ColumnIndex[] = [];
|
|
306
|
+
for (const index of this.sampledColumns) {
|
|
307
|
+
if (!this.columnsCache.has(index)) {
|
|
308
|
+
missing.push(index);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return {missing, versionedHashes: this.versionedHashes};
|
|
312
|
+
}
|
|
313
|
+
|
|
273
314
|
hasComputedAllData(): boolean {
|
|
274
315
|
return this.state.hasComputedAllData;
|
|
275
316
|
}
|
|
276
317
|
|
|
277
|
-
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<
|
|
318
|
+
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
278
319
|
if (this.state.hasComputedAllData) {
|
|
279
320
|
return Promise.resolve(this.getSampledColumns());
|
|
280
321
|
}
|
|
@@ -319,7 +360,7 @@ export class PayloadEnvelopeInput {
|
|
|
319
360
|
hasAllData: boolean;
|
|
320
361
|
hasComputedAllData: boolean;
|
|
321
362
|
isComplete: boolean;
|
|
322
|
-
|
|
363
|
+
receivedColumns: number;
|
|
323
364
|
sampledColumnsCount: number;
|
|
324
365
|
} {
|
|
325
366
|
return {
|
|
@@ -329,7 +370,7 @@ export class PayloadEnvelopeInput {
|
|
|
329
370
|
hasAllData: this.state.hasAllData,
|
|
330
371
|
hasComputedAllData: this.state.hasComputedAllData,
|
|
331
372
|
isComplete: this.isComplete(),
|
|
332
|
-
|
|
373
|
+
receivedColumns: this.columnsCache.size,
|
|
333
374
|
sampledColumnsCount: this.sampledColumns.length,
|
|
334
375
|
};
|
|
335
376
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {ForkPostGloas} from "@lodestar/params";
|
|
1
|
+
import {ForkName, ForkPostGloas} from "@lodestar/params";
|
|
2
2
|
import {ColumnIndex, RootHex, SignedBeaconBlock, gloas} from "@lodestar/types";
|
|
3
3
|
|
|
4
4
|
export enum PayloadEnvelopeInputSource {
|
|
@@ -23,6 +23,7 @@ export type ColumnWithSource = SourceMeta & {
|
|
|
23
23
|
export type CreateFromBlockProps = {
|
|
24
24
|
blockRootHex: RootHex;
|
|
25
25
|
block: SignedBeaconBlock<ForkPostGloas>;
|
|
26
|
+
forkName: ForkName;
|
|
26
27
|
sampledColumns: ColumnIndex[];
|
|
27
28
|
custodyColumns: ColumnIndex[];
|
|
28
29
|
timeCreatedSec: number;
|
|
@@ -103,7 +103,7 @@ type FullyVerifiedBlockBase = {
|
|
|
103
103
|
/**
|
|
104
104
|
* A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import.
|
|
105
105
|
*
|
|
106
|
-
* Discriminated union on `
|
|
106
|
+
* Discriminated union on `postPayloadState`:
|
|
107
107
|
* - `null` → block has no pre-verified envelope; `executionStatus` is any `BlockExecutionStatus`
|
|
108
108
|
* - non-null → envelope was pre-verified during state transition; `executionStatus` is narrowed to
|
|
109
109
|
* `Valid | Syncing` (matching what `forkChoice.onExecutionPayload` expects)
|
|
@@ -111,12 +111,12 @@ type FullyVerifiedBlockBase = {
|
|
|
111
111
|
export type FullyVerifiedBlock = FullyVerifiedBlockBase &
|
|
112
112
|
(
|
|
113
113
|
| {
|
|
114
|
-
|
|
114
|
+
postPayloadState: null;
|
|
115
115
|
/** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync or for merge block */
|
|
116
116
|
executionStatus: BlockExecutionStatus;
|
|
117
117
|
}
|
|
118
118
|
| {
|
|
119
|
-
|
|
119
|
+
postPayloadState: IBeaconStateView;
|
|
120
120
|
executionStatus: PayloadExecutionStatus;
|
|
121
121
|
}
|
|
122
122
|
);
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
ProtoBlock,
|
|
9
9
|
} from "@lodestar/fork-choice";
|
|
10
10
|
import {ForkSeq} from "@lodestar/params";
|
|
11
|
-
import {IBeaconStateView, isExecutionBlockBodyType} from "@lodestar/state-transition";
|
|
11
|
+
import {IBeaconStateView, isExecutionBlockBodyType, isStatePostBellatrix} from "@lodestar/state-transition";
|
|
12
12
|
import {bellatrix, electra} from "@lodestar/types";
|
|
13
13
|
import {ErrorAborted, Logger, toRootHex} from "@lodestar/utils";
|
|
14
14
|
import {ExecutionPayloadStatus, IExecutionEngine} from "../../execution/engine/interface.js";
|
|
@@ -152,6 +152,7 @@ export async function verifyBlockExecutionPayload(
|
|
|
152
152
|
|
|
153
153
|
/** Not null if execution is enabled */
|
|
154
154
|
const executionPayloadEnabled =
|
|
155
|
+
isStatePostBellatrix(preState0) &&
|
|
155
156
|
preState0.isExecutionStateType &&
|
|
156
157
|
isExecutionBlockBodyType(block.message.body) &&
|
|
157
158
|
preState0.isExecutionEnabled(block.message)
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import {BeaconConfig} from "@lodestar/config";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
IBeaconStateView,
|
|
4
|
+
SyncCommitteeCacheEmpty,
|
|
5
|
+
getBlockSignatureSets,
|
|
6
|
+
isStatePostAltair,
|
|
7
|
+
} from "@lodestar/state-transition";
|
|
3
8
|
import {IndexedAttestation, SignedBeaconBlock} from "@lodestar/types";
|
|
4
9
|
import {Logger} from "@lodestar/utils";
|
|
5
10
|
import {Metrics} from "../../metrics/metrics.js";
|
|
@@ -27,7 +32,9 @@ export async function verifyBlocksSignatures(
|
|
|
27
32
|
): Promise<{verifySignaturesTime: number}> {
|
|
28
33
|
const isValidPromises: Promise<boolean>[] = [];
|
|
29
34
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
30
|
-
const currentSyncCommitteeIndexed = preState0
|
|
35
|
+
const currentSyncCommitteeIndexed = isStatePostAltair(preState0)
|
|
36
|
+
? preState0.currentSyncCommitteeIndexed
|
|
37
|
+
: new SyncCommitteeCacheEmpty();
|
|
31
38
|
|
|
32
39
|
// Verifies signatures after running state transition, so all SyncCommittee signed roots are known at this point.
|
|
33
40
|
// We must ensure block.slot <= state.slot before running getAllBlockSignatureSets().
|