@lodestar/beacon-node 1.42.0-dev.04e52d162f → 1.42.0-dev.1e596a7422
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 +24 -12
- 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 +10 -8
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +67 -39
- 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/interface.d.ts +3 -2
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +19 -13
- package/lib/network/libp2p/index.js.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/options.d.ts.map +1 -1
- package/lib/network/options.js +7 -2
- package/lib/network/options.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 +260 -73
- 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/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +2 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js +2 -0
- package/lib/network/reqresp/handlers/beaconBlocksByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts +2 -2
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js +7 -3
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js +6 -0
- package/lib/network/reqresp/handlers/blobSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts +2 -2
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +7 -3
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +2 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +3 -8
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.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 +32 -15
- 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 +72 -42
- 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/libp2p/index.ts +21 -15
- package/src/network/network.ts +7 -4
- package/src/network/options.ts +7 -2
- package/src/network/processor/extractSlotRootFns.ts +32 -6
- package/src/network/processor/gossipHandlers.ts +325 -86
- package/src/network/processor/index.ts +304 -22
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +3 -1
- package/src/network/reqresp/handlers/beaconBlocksByRoot.ts +3 -0
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +15 -3
- package/src/network/reqresp/handlers/blobSidecarsByRoot.ts +11 -0
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +19 -3
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +3 -1
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +3 -12
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
|
-
import {
|
|
4
|
-
import {getExecutionPayloadEnvelopeSignatureSet} from "@lodestar/state-transition";
|
|
3
|
+
import {SLOTS_PER_EPOCH} from "@lodestar/params";
|
|
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";
|
|
@@ -69,14 +69,16 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
69
69
|
* Import an execution payload envelope after all data is available.
|
|
70
70
|
*
|
|
71
71
|
* This function:
|
|
72
|
-
* 1.
|
|
73
|
-
* 2.
|
|
74
|
-
* 3.
|
|
75
|
-
* 4.
|
|
76
|
-
* 5.
|
|
77
|
-
* 6.
|
|
78
|
-
* 7.
|
|
79
|
-
* 8.
|
|
72
|
+
* 1. Emits `execution_payload_available` if payload is for current slot
|
|
73
|
+
* 2. Gets the ProtoBlock from fork choice
|
|
74
|
+
* 3. Applies write-queue backpressure (waitForSpace) early, before verification
|
|
75
|
+
* 4. Regenerates the block state
|
|
76
|
+
* 5. Runs EL verification (notifyNewPayload) in parallel with signature verification and processExecutionPayloadEnvelope
|
|
77
|
+
* 6. Persists verified payload envelope to hot DB
|
|
78
|
+
* 7. Updates fork choice
|
|
79
|
+
* 8. Caches the post-execution payload state
|
|
80
|
+
* 9. Records metrics for column sources
|
|
81
|
+
* 10. Emits `execution_payload` for recent enough payloads after successful import
|
|
80
82
|
*
|
|
81
83
|
*/
|
|
82
84
|
export async function importExecutionPayload(
|
|
@@ -84,10 +86,24 @@ export async function importExecutionPayload(
|
|
|
84
86
|
payloadInput: PayloadEnvelopeInput,
|
|
85
87
|
opts: ImportPayloadOpts = {}
|
|
86
88
|
): Promise<void> {
|
|
87
|
-
const
|
|
89
|
+
const signedEnvelope = payloadInput.getPayloadEnvelope();
|
|
90
|
+
const envelope = signedEnvelope.message;
|
|
88
91
|
const blockRootHex = payloadInput.blockRootHex;
|
|
92
|
+
const blockHashHex = payloadInput.getBlockHashHex();
|
|
93
|
+
const fork = this.config.getForkName(envelope.slot);
|
|
89
94
|
|
|
90
|
-
// 1.
|
|
95
|
+
// 1. Emit `execution_payload_available` event at the start of import. At this point the payload input
|
|
96
|
+
// is already complete, so the payload and required data are available for payload attestation.
|
|
97
|
+
// This event is only about availability, not validity of the execution payload, hence we can emit
|
|
98
|
+
// it before getting a response from the execution client on whether the payload is valid or not.
|
|
99
|
+
if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
100
|
+
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
|
+
slot: envelope.slot,
|
|
102
|
+
blockRoot: blockRootHex,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// 2. Get ProtoBlock for parent root lookup
|
|
91
107
|
const protoBlock = this.forkChoice.getBlockHexDefaultStatus(blockRootHex);
|
|
92
108
|
if (!protoBlock) {
|
|
93
109
|
throw new PayloadError({
|
|
@@ -96,11 +112,11 @@ export async function importExecutionPayload(
|
|
|
96
112
|
});
|
|
97
113
|
}
|
|
98
114
|
|
|
99
|
-
//
|
|
115
|
+
// 3. Apply backpressure from the write queue early, before doing verification work.
|
|
100
116
|
// The actual DB write is deferred until after verification succeeds.
|
|
101
117
|
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
102
118
|
|
|
103
|
-
//
|
|
119
|
+
// 4. Get pre-state for processExecutionPayloadEnvelope
|
|
104
120
|
// We need the block state (post-block, pre-payload) to process the envelope
|
|
105
121
|
const blockState = await this.regen.getBlockSlotState(
|
|
106
122
|
protoBlock,
|
|
@@ -108,17 +124,23 @@ export async function importExecutionPayload(
|
|
|
108
124
|
{dontTransferCache: true},
|
|
109
125
|
RegenCaller.processBlock
|
|
110
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
|
+
}
|
|
111
133
|
|
|
112
|
-
//
|
|
134
|
+
// 5. Run verification steps in parallel
|
|
113
135
|
// Note: No data availability check needed here - importExecutionPayload is only
|
|
114
136
|
// called when payloadInput.isComplete() is true, so all data is already available.
|
|
115
137
|
const [execResult, signatureValid, postPayloadResult] = await Promise.all([
|
|
116
138
|
this.executionEngine.notifyNewPayload(
|
|
117
|
-
|
|
118
|
-
envelope.
|
|
139
|
+
fork,
|
|
140
|
+
envelope.payload,
|
|
119
141
|
payloadInput.getVersionedHashes(),
|
|
120
142
|
fromHex(protoBlock.parentRoot),
|
|
121
|
-
envelope.
|
|
143
|
+
envelope.executionRequests
|
|
122
144
|
),
|
|
123
145
|
|
|
124
146
|
opts.validSignature === true
|
|
@@ -128,7 +150,7 @@ export async function importExecutionPayload(
|
|
|
128
150
|
this.config,
|
|
129
151
|
this.pubkeyCache,
|
|
130
152
|
blockState,
|
|
131
|
-
|
|
153
|
+
signedEnvelope,
|
|
132
154
|
payloadInput.proposerIndex
|
|
133
155
|
);
|
|
134
156
|
return this.bls.verifySignatureSets([signatureSet]);
|
|
@@ -139,7 +161,7 @@ export async function importExecutionPayload(
|
|
|
139
161
|
(async () => {
|
|
140
162
|
try {
|
|
141
163
|
return {
|
|
142
|
-
postPayloadState: blockState.processExecutionPayloadEnvelope(
|
|
164
|
+
postPayloadState: blockState.processExecutionPayloadEnvelope(signedEnvelope, {
|
|
143
165
|
verifySignature: false,
|
|
144
166
|
verifyStateRoot: false,
|
|
145
167
|
}),
|
|
@@ -156,12 +178,12 @@ export async function importExecutionPayload(
|
|
|
156
178
|
})(),
|
|
157
179
|
]);
|
|
158
180
|
|
|
159
|
-
//
|
|
181
|
+
// 5a. Check signature verification result
|
|
160
182
|
if (!signatureValid) {
|
|
161
183
|
throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
|
|
162
184
|
}
|
|
163
185
|
|
|
164
|
-
//
|
|
186
|
+
// 5b. Handle EL response
|
|
165
187
|
switch (execResult.status) {
|
|
166
188
|
case ExecutionPayloadStatus.VALID:
|
|
167
189
|
break;
|
|
@@ -187,61 +209,69 @@ export async function importExecutionPayload(
|
|
|
187
209
|
});
|
|
188
210
|
}
|
|
189
211
|
|
|
190
|
-
//
|
|
212
|
+
// 5c. Verify envelope state root matches post-state
|
|
191
213
|
const postPayloadState = postPayloadResult.postPayloadState;
|
|
192
214
|
const postPayloadStateRoot = postPayloadState.hashTreeRoot();
|
|
193
|
-
if (!byteArrayEquals(envelope.
|
|
215
|
+
if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
|
|
194
216
|
throw new PayloadError({
|
|
195
217
|
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
196
|
-
message: `Envelope state root mismatch expected=${toRootHex(envelope.
|
|
218
|
+
message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
|
|
197
219
|
});
|
|
198
220
|
}
|
|
199
221
|
|
|
200
|
-
//
|
|
222
|
+
// 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
|
|
201
223
|
this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
|
|
202
224
|
if (!isQueueErrorAborted(e)) {
|
|
203
225
|
this.logger.error(
|
|
204
226
|
"Error pushing payload envelope to unfinalized write queue",
|
|
205
|
-
{slot:
|
|
227
|
+
{slot: envelope.slot, blockRoot: blockRootHex},
|
|
206
228
|
e as Error
|
|
207
229
|
);
|
|
208
230
|
}
|
|
209
231
|
});
|
|
210
232
|
|
|
211
|
-
//
|
|
233
|
+
// 7. Update fork choice
|
|
212
234
|
this.forkChoice.onExecutionPayload(
|
|
213
235
|
blockRootHex,
|
|
214
|
-
|
|
215
|
-
envelope.
|
|
236
|
+
blockHashHex,
|
|
237
|
+
envelope.payload.blockNumber,
|
|
216
238
|
toRootHex(postPayloadStateRoot),
|
|
217
239
|
toForkChoiceExecutionStatus(execResult.status)
|
|
218
240
|
);
|
|
219
241
|
|
|
220
|
-
//
|
|
242
|
+
// 8. Cache payload state
|
|
221
243
|
this.regen.processPayloadState(postPayloadState);
|
|
222
244
|
if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
|
|
223
245
|
const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
|
|
224
246
|
this.regen.addCheckpointState(checkpoint, postPayloadState, true);
|
|
225
247
|
}
|
|
226
248
|
|
|
227
|
-
//
|
|
249
|
+
// 9. Record metrics for payload envelope and column sources
|
|
228
250
|
this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
|
|
229
251
|
for (const {source} of payloadInput.getSampledColumnsWithSource()) {
|
|
230
252
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
231
253
|
}
|
|
232
254
|
|
|
233
|
-
|
|
234
|
-
slot: payloadInput.slot,
|
|
235
|
-
root: blockRootHex,
|
|
236
|
-
blockHash: payloadInput.getBlockHashHex(),
|
|
237
|
-
});
|
|
255
|
+
const stateRootHex = toRootHex(envelope.stateRoot);
|
|
238
256
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
257
|
+
// 10. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
258
|
+
if (this.clock.currentSlot - envelope.slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
259
|
+
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
260
|
+
slot: envelope.slot,
|
|
261
|
+
builderIndex: envelope.builderIndex,
|
|
262
|
+
blockHash: blockHashHex,
|
|
244
263
|
blockRoot: blockRootHex,
|
|
264
|
+
stateRoot: stateRootHex,
|
|
265
|
+
// TODO GLOAS: revisit once we support optimistic import
|
|
266
|
+
executionOptimistic: false,
|
|
245
267
|
});
|
|
246
268
|
}
|
|
269
|
+
|
|
270
|
+
this.logger.verbose("Execution payload imported", {
|
|
271
|
+
slot: envelope.slot,
|
|
272
|
+
builderIndex: envelope.builderIndex,
|
|
273
|
+
blockRoot: blockRootHex,
|
|
274
|
+
blockHash: blockHashHex,
|
|
275
|
+
stateRoot: stateRootHex,
|
|
276
|
+
});
|
|
247
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().
|
package/src/chain/chain.ts
CHANGED
|
@@ -15,9 +15,9 @@ import {
|
|
|
15
15
|
BUILDER_INDEX_SELF_BUILD,
|
|
16
16
|
EFFECTIVE_BALANCE_INCREMENT,
|
|
17
17
|
type ForkPostFulu,
|
|
18
|
+
type ForkPostGloas,
|
|
18
19
|
GENESIS_SLOT,
|
|
19
20
|
SLOTS_PER_EPOCH,
|
|
20
|
-
isForkPostElectra,
|
|
21
21
|
isForkPostGloas,
|
|
22
22
|
} from "@lodestar/params";
|
|
23
23
|
import {
|
|
@@ -29,12 +29,15 @@ import {
|
|
|
29
29
|
computeEpochAtSlot,
|
|
30
30
|
computeStartSlotAtEpoch,
|
|
31
31
|
getEffectiveBalancesFromStateBytes,
|
|
32
|
+
isStatePostAltair,
|
|
33
|
+
isStatePostElectra,
|
|
34
|
+
isStatePostGloas,
|
|
32
35
|
} from "@lodestar/state-transition";
|
|
33
36
|
import {
|
|
34
37
|
BeaconBlock,
|
|
35
38
|
BlindedBeaconBlock,
|
|
36
39
|
BlindedBeaconBlockBody,
|
|
37
|
-
|
|
40
|
+
DataColumnSidecar,
|
|
38
41
|
Epoch,
|
|
39
42
|
Root,
|
|
40
43
|
RootHex,
|
|
@@ -97,7 +100,7 @@ import {
|
|
|
97
100
|
} from "./opPools/index.js";
|
|
98
101
|
import {IChainOptions} from "./options.js";
|
|
99
102
|
import {PrepareNextSlotScheduler} from "./prepareNextSlot.js";
|
|
100
|
-
import {
|
|
103
|
+
import {computeNewStateRoot, computePayloadEnvelopeStateRoot} from "./produceBlock/computeNewStateRoot.js";
|
|
101
104
|
import {AssembledBlockType, BlockType, ProduceFullGloas, ProduceResult} from "./produceBlock/index.js";
|
|
102
105
|
import {BlockAttributes, produceBlockBody, produceCommonBlockBody} from "./produceBlock/produceBlockBody.js";
|
|
103
106
|
import {QueuedStateRegenerator, RegenCaller} from "./regen/index.js";
|
|
@@ -504,7 +507,11 @@ export class BeaconChain implements IBeaconChain {
|
|
|
504
507
|
}
|
|
505
508
|
|
|
506
509
|
seenBlock(blockRoot: RootHex): boolean {
|
|
507
|
-
return this.seenBlockInputCache.
|
|
510
|
+
return this.seenBlockInputCache.hasBlock(blockRoot) || this.forkChoice.hasBlockHexUnsafe(blockRoot);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
seenPayloadEnvelope(blockRoot: RootHex): boolean {
|
|
514
|
+
return this.seenPayloadEnvelopeInputCache.hasPayload(blockRoot) || this.forkChoice.hasPayloadHexUnsafe(blockRoot);
|
|
508
515
|
}
|
|
509
516
|
|
|
510
517
|
regenCanAcceptWork(): boolean {
|
|
@@ -873,20 +880,32 @@ export class BeaconChain implements IBeaconChain {
|
|
|
873
880
|
);
|
|
874
881
|
}
|
|
875
882
|
|
|
876
|
-
async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
883
|
+
async getDataColumnSidecars(blockSlot: Slot, blockRootHex: string): Promise<DataColumnSidecar[]> {
|
|
884
|
+
const fork = this.config.getForkName(blockSlot);
|
|
885
|
+
|
|
886
|
+
if (isForkPostGloas(fork)) {
|
|
887
|
+
// After gloas, columns are tracked in PayloadEnvelopeInput
|
|
888
|
+
const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
889
|
+
if (payloadInput) {
|
|
890
|
+
return payloadInput.getAllColumns();
|
|
891
|
+
}
|
|
892
|
+
} else {
|
|
893
|
+
// Before gloas, columns are tracked in BlockInput
|
|
894
|
+
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
895
|
+
if (blockInput) {
|
|
896
|
+
if (!isBlockInputColumns(blockInput)) {
|
|
897
|
+
throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
|
|
898
|
+
}
|
|
899
|
+
return blockInput.getAllColumns();
|
|
881
900
|
}
|
|
882
|
-
return blockInput.getAllColumns();
|
|
883
901
|
}
|
|
902
|
+
|
|
884
903
|
const sidecarsUnfinalized = await this.db.dataColumnSidecar.values(fromHex(blockRootHex));
|
|
885
904
|
if (sidecarsUnfinalized.length > 0) {
|
|
886
|
-
return sidecarsUnfinalized
|
|
905
|
+
return sidecarsUnfinalized;
|
|
887
906
|
}
|
|
888
907
|
const sidecarsFinalized = await this.db.dataColumnSidecarArchive.values(blockSlot);
|
|
889
|
-
return sidecarsFinalized
|
|
908
|
+
return sidecarsFinalized;
|
|
890
909
|
}
|
|
891
910
|
|
|
892
911
|
async getSerializedDataColumnSidecars(
|
|
@@ -894,23 +913,45 @@ export class BeaconChain implements IBeaconChain {
|
|
|
894
913
|
blockRootHex: string,
|
|
895
914
|
indices: number[]
|
|
896
915
|
): Promise<(Uint8Array | undefined)[]> {
|
|
897
|
-
const
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
916
|
+
const fork = this.config.getForkName(blockSlot);
|
|
917
|
+
|
|
918
|
+
if (isForkPostGloas(fork)) {
|
|
919
|
+
// After gloas, columns are tracked in PayloadEnvelopeInput
|
|
920
|
+
const payloadInput = this.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
921
|
+
if (payloadInput) {
|
|
922
|
+
return indices.map((index) => {
|
|
923
|
+
const sidecar = payloadInput.getColumn(index);
|
|
924
|
+
if (!sidecar) {
|
|
925
|
+
return undefined;
|
|
926
|
+
}
|
|
927
|
+
const serialized = this.serializedCache.get(sidecar);
|
|
928
|
+
if (serialized) {
|
|
929
|
+
return serialized;
|
|
930
|
+
}
|
|
931
|
+
return sszTypesFor(fork as ForkPostGloas).DataColumnSidecar.serialize(sidecar);
|
|
932
|
+
});
|
|
901
933
|
}
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
if (serialized) {
|
|
909
|
-
return serialized;
|
|
934
|
+
} else {
|
|
935
|
+
// Before gloas, columns are tracked in BlockInput
|
|
936
|
+
const blockInput = this.seenBlockInputCache.get(blockRootHex);
|
|
937
|
+
if (blockInput) {
|
|
938
|
+
if (!isBlockInputColumns(blockInput)) {
|
|
939
|
+
throw new Error(`Expected block input to have columns: slot=${blockSlot} root=${blockRootHex}`);
|
|
910
940
|
}
|
|
911
|
-
return
|
|
912
|
-
|
|
941
|
+
return indices.map((index) => {
|
|
942
|
+
const sidecar = blockInput.getColumn(index);
|
|
943
|
+
if (!sidecar) {
|
|
944
|
+
return undefined;
|
|
945
|
+
}
|
|
946
|
+
const serialized = this.serializedCache.get(sidecar);
|
|
947
|
+
if (serialized) {
|
|
948
|
+
return serialized;
|
|
949
|
+
}
|
|
950
|
+
return sszTypesFor(blockInput.forkName as ForkPostFulu).DataColumnSidecar.serialize(sidecar);
|
|
951
|
+
});
|
|
952
|
+
}
|
|
913
953
|
}
|
|
954
|
+
|
|
914
955
|
const sidecarsUnfinalized = await this.db.dataColumnSidecar.getManyBinary(fromHex(blockRootHex), indices);
|
|
915
956
|
if (sidecarsUnfinalized.some((sidecar) => sidecar != null)) {
|
|
916
957
|
return sidecarsUnfinalized;
|
|
@@ -1013,7 +1054,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1013
1054
|
body,
|
|
1014
1055
|
} as AssembledBlockType<T>;
|
|
1015
1056
|
|
|
1016
|
-
const {newStateRoot, proposerReward,
|
|
1057
|
+
const {newStateRoot, proposerReward, postBlockState} = computeNewStateRoot(this.metrics, state, block);
|
|
1017
1058
|
block.stateRoot = newStateRoot;
|
|
1018
1059
|
const blockRoot =
|
|
1019
1060
|
produceResult.type === BlockType.Full
|
|
@@ -1037,8 +1078,11 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1037
1078
|
slot,
|
|
1038
1079
|
stateRoot: ZERO_HASH,
|
|
1039
1080
|
};
|
|
1040
|
-
|
|
1041
|
-
|
|
1081
|
+
if (!isStatePostGloas(postBlockState)) {
|
|
1082
|
+
throw Error(`Expected gloas+ post-state for execution payload envelope, got fork=${postBlockState.forkName}`);
|
|
1083
|
+
}
|
|
1084
|
+
const payloadEnvelopeStateRoot = computePayloadEnvelopeStateRoot(this.metrics, postBlockState, envelope);
|
|
1085
|
+
gloasResult.payloadEnvelopeStateRoot = payloadEnvelopeStateRoot;
|
|
1042
1086
|
}
|
|
1043
1087
|
|
|
1044
1088
|
// Track the produced block for consensus broadcast validations, later validation, etc.
|
|
@@ -1365,9 +1409,7 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1365
1409
|
metrics.chain.blacklistedBlocks.set(this.blacklistedBlocks.size);
|
|
1366
1410
|
|
|
1367
1411
|
const headState = this.getHeadState();
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
if (isForkPostElectra(fork)) {
|
|
1412
|
+
if (isStatePostElectra(headState)) {
|
|
1371
1413
|
metrics.pendingDeposits.set(headState.pendingDepositsCount);
|
|
1372
1414
|
metrics.pendingPartialWithdrawals.set(headState.pendingPartialWithdrawalsCount);
|
|
1373
1415
|
metrics.pendingConsolidations.set(headState.pendingConsolidationsCount);
|
|
@@ -1614,6 +1656,9 @@ export class BeaconChain implements IBeaconChain {
|
|
|
1614
1656
|
}
|
|
1615
1657
|
|
|
1616
1658
|
preState = preState.processSlots(block.slot); // Dial preState's slot to block.slot
|
|
1659
|
+
if (!isStatePostAltair(preState)) {
|
|
1660
|
+
throw new Error("Sync committee rewards are not supported before Altair");
|
|
1661
|
+
}
|
|
1617
1662
|
|
|
1618
1663
|
return preState.computeSyncCommitteeRewards(block, validatorIds ?? []);
|
|
1619
1664
|
}
|