@lodestar/beacon-node 1.42.0-rc.0 → 1.43.0-dev.07875b3e0c
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 +21 -4
- 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/beacon/state/utils.d.ts +2 -2
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/lodestar/attesterSlashing.d.ts +8 -0
- package/lib/api/impl/lodestar/attesterSlashing.d.ts.map +1 -0
- package/lib/api/impl/lodestar/attesterSlashing.js +29 -0
- package/lib/api/impl/lodestar/attesterSlashing.js.map +1 -0
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +39 -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 +8 -5
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +29 -35
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +15 -14
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +69 -82
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +1 -2
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +6 -4
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +15 -21
- 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/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +5 -4
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +32 -38
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +16 -4
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/attestationError.d.ts +8 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +4 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/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/executionPayloadBid.d.ts +5 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +21 -23
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.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 +32 -11
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +1 -7
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +1 -28
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +5 -10
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +49 -19
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +1 -11
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +0 -2
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +6 -12
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/queued.d.ts +6 -11
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +8 -40
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +0 -5
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +7 -34
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +11 -4
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -18
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/stateCache/datastore/db.d.ts +5 -4
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +10 -32
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +13 -30
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +120 -216
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +8 -15
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +12 -0
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +12 -0
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/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/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +19 -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 +27 -12
- 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 +8 -4
- 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/repositories/executionPayloadEnvelopeArchive.js +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +21 -14
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -0
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +6 -0
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/types.d.ts +20 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +18 -0
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +3 -2
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/network.js +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +26 -6
- package/lib/network/processor/gossipHandlers.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/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +6 -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/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +16 -3
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -16
- package/src/api/impl/beacon/blocks/index.ts +30 -4
- package/src/api/impl/beacon/pool/index.ts +4 -0
- package/src/api/impl/beacon/state/index.ts +15 -15
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/lodestar/attesterSlashing.ts +43 -0
- package/src/api/impl/lodestar/index.ts +51 -1
- package/src/api/impl/validator/index.ts +10 -6
- package/src/chain/GetBlobsTracker.ts +1 -2
- package/src/chain/archiveStore/archiveStore.ts +5 -5
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +6 -8
- package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
- package/src/chain/blocks/importBlock.ts +33 -42
- package/src/chain/blocks/importExecutionPayload.ts +83 -99
- package/src/chain/blocks/index.ts +1 -2
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +6 -5
- package/src/chain/blocks/types.ts +15 -26
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +2 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +9 -2
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
- package/src/chain/chain.ts +47 -62
- package/src/chain/emitter.ts +15 -3
- package/src/chain/errors/attestationError.ts +6 -1
- package/src/chain/errors/blockError.ts +7 -1
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
- package/src/chain/forkChoice/index.ts +19 -28
- package/src/chain/interface.ts +7 -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 +38 -11
- package/src/chain/produceBlock/computeNewStateRoot.ts +1 -37
- package/src/chain/produceBlock/produceBlockBody.ts +74 -23
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +6 -12
- package/src/chain/regen/queued.ts +12 -48
- package/src/chain/regen/regen.ts +8 -36
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +22 -20
- package/src/chain/stateCache/datastore/db.ts +10 -33
- package/src/chain/stateCache/datastore/file.ts +5 -6
- package/src/chain/stateCache/datastore/types.ts +2 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
- package/src/chain/stateCache/persistentCheckpointsCache.ts +139 -247
- package/src/chain/stateCache/types.ts +8 -14
- package/src/chain/validation/aggregateAndProof.ts +13 -0
- package/src/chain/validation/attestation.ts +13 -0
- package/src/chain/validation/block.ts +30 -7
- package/src/chain/validation/executionPayloadBid.ts +21 -3
- package/src/chain/validation/executionPayloadEnvelope.ts +32 -13
- package/src/chain/validation/payloadAttestationMessage.ts +9 -3
- 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/repositories/executionPayloadEnvelopeArchive.ts +1 -1
- package/src/execution/engine/http.ts +21 -14
- package/src/execution/engine/interface.ts +1 -0
- package/src/execution/engine/mock.ts +8 -1
- package/src/execution/engine/types.ts +41 -0
- package/src/network/network.ts +1 -1
- package/src/network/processor/gossipHandlers.ts +31 -10
- 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/node/nodejs.ts +7 -2
- package/src/node/notifier.ts +7 -2
- package/src/util/sszBytes.ts +21 -3
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
ForkChoiceErrorCode,
|
|
9
9
|
NotReorgedReason,
|
|
10
10
|
getSafeExecutionBlockHash,
|
|
11
|
-
isGloasBlock,
|
|
12
11
|
} from "@lodestar/fork-choice";
|
|
13
12
|
import {
|
|
14
13
|
ForkPostAltair,
|
|
@@ -25,6 +24,8 @@ import {
|
|
|
25
24
|
computeStartSlotAtEpoch,
|
|
26
25
|
computeTimeAtSlot,
|
|
27
26
|
isStartSlotOfEpoch,
|
|
27
|
+
isStatePostAltair,
|
|
28
|
+
isStatePostBellatrix,
|
|
28
29
|
} from "@lodestar/state-transition";
|
|
29
30
|
import {
|
|
30
31
|
Attestation,
|
|
@@ -46,7 +47,7 @@ import type {BeaconChain} from "../chain.js";
|
|
|
46
47
|
import {ChainEvent, ReorgEventData} from "../emitter.js";
|
|
47
48
|
import {ForkchoiceCaller} from "../forkChoice/index.js";
|
|
48
49
|
import {REPROCESS_MIN_TIME_TO_NEXT_SLOT_SEC} from "../reprocess.js";
|
|
49
|
-
import {
|
|
50
|
+
import {toCheckpointHex} from "../stateCache/persistentCheckpointsCache.js";
|
|
50
51
|
import {isBlockInputBlobs, isBlockInputColumns} from "./blockInput/blockInput.js";
|
|
51
52
|
import {AttestationImportOpt, FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
52
53
|
import {getCheckpointFromState} from "./utils/checkpoint.js";
|
|
@@ -85,7 +86,7 @@ export async function importBlock(
|
|
|
85
86
|
fullyVerifiedBlock: FullyVerifiedBlock,
|
|
86
87
|
opts: ImportBlockOpts
|
|
87
88
|
): Promise<void> {
|
|
88
|
-
const {blockInput,
|
|
89
|
+
const {blockInput, postState, parentBlockSlot, executionStatus, dataAvailabilityStatus, indexedAttestations} =
|
|
89
90
|
fullyVerifiedBlock;
|
|
90
91
|
const block = blockInput.getBlock();
|
|
91
92
|
const source = blockInput.getBlockSource();
|
|
@@ -97,7 +98,7 @@ export async function importBlock(
|
|
|
97
98
|
const blockEpoch = computeEpochAtSlot(blockSlot);
|
|
98
99
|
const prevFinalizedEpoch = this.forkChoice.getFinalizedCheckpoint().epoch;
|
|
99
100
|
const blockDelaySec =
|
|
100
|
-
fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot,
|
|
101
|
+
fullyVerifiedBlock.seenTimestampSec - computeTimeAtSlot(this.config, blockSlot, postState.genesisTime);
|
|
101
102
|
const recvToValLatency = Date.now() / 1000 - (opts.seenTimestampSec ?? Date.now() / 1000);
|
|
102
103
|
const fork = this.config.getForkSeq(blockSlot);
|
|
103
104
|
|
|
@@ -120,10 +121,10 @@ export async function importBlock(
|
|
|
120
121
|
// 2. Import block to fork choice
|
|
121
122
|
|
|
122
123
|
// Should compute checkpoint balances before forkchoice.onBlock
|
|
123
|
-
this.checkpointBalancesCache.processState(blockRootHex,
|
|
124
|
+
this.checkpointBalancesCache.processState(blockRootHex, postState);
|
|
124
125
|
const blockSummary = this.forkChoice.onBlock(
|
|
125
126
|
block.message,
|
|
126
|
-
|
|
127
|
+
postState,
|
|
127
128
|
blockDelaySec,
|
|
128
129
|
currentSlot,
|
|
129
130
|
fork >= ForkSeq.gloas ? ExecutionStatus.PayloadSeparated : executionStatus,
|
|
@@ -132,11 +133,7 @@ export async function importBlock(
|
|
|
132
133
|
|
|
133
134
|
// This adds the state necessary to process the next block
|
|
134
135
|
// Some block event handlers require state being in state cache so need to do this before emitting EventType.block
|
|
135
|
-
|
|
136
|
-
// Post-Gloas: blockSummary.payloadStatus is always PENDING, so payloadPresent = false (block state only, no payload processing yet)
|
|
137
|
-
const payloadPresent = !isGloasBlock(blockSummary);
|
|
138
|
-
// processState manages both block state and payload state variants together for memory/disk management
|
|
139
|
-
this.regen.processBlockState(blockRootHex, postBlockState);
|
|
136
|
+
this.regen.processState(blockRootHex, postState);
|
|
140
137
|
|
|
141
138
|
// For Gloas blocks, create PayloadEnvelopeInput so it's available for later payload import
|
|
142
139
|
if (fork >= ForkSeq.gloas) {
|
|
@@ -159,17 +156,9 @@ export async function importBlock(
|
|
|
159
156
|
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
160
157
|
// TODO GLOAS: If we want EL retries after this initial attempt, add an explicit retry policy here
|
|
161
158
|
// (for example later in the slot). Do not couple retries to incoming gossip columns.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
|
|
166
|
-
this.logger.debug(
|
|
167
|
-
"Error processing execution payload after getBlobs",
|
|
168
|
-
{slot: blockSlot, root: blockRootHex},
|
|
169
|
-
e as Error
|
|
170
|
-
);
|
|
171
|
-
});
|
|
172
|
-
});
|
|
159
|
+
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
160
|
+
// in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
|
|
161
|
+
this.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
173
162
|
}
|
|
174
163
|
|
|
175
164
|
this.metrics?.importBlock.bySource.inc({source: source.source});
|
|
@@ -189,7 +178,7 @@ export async function importBlock(
|
|
|
189
178
|
(opts.importAttestations !== AttestationImportOpt.Skip && blockEpoch >= currentEpoch - FORK_CHOICE_ATT_EPOCH_LIMIT)
|
|
190
179
|
) {
|
|
191
180
|
const attestations = block.message.body.attestations;
|
|
192
|
-
const rootCache = new RootCache(
|
|
181
|
+
const rootCache = new RootCache(postState);
|
|
193
182
|
const invalidAttestationErrorsByCode = new Map<string, {error: Error; count: number}>();
|
|
194
183
|
|
|
195
184
|
const addAttestation = fork >= ForkSeq.electra ? addAttestationPostElectra : addAttestationPreElectra;
|
|
@@ -203,7 +192,7 @@ export async function importBlock(
|
|
|
203
192
|
const attDataRoot = toRootHex(ssz.phase0.AttestationData.hashTreeRoot(indexedAttestation.data));
|
|
204
193
|
addAttestation.call(
|
|
205
194
|
this,
|
|
206
|
-
|
|
195
|
+
postState,
|
|
207
196
|
target,
|
|
208
197
|
attDataRoot,
|
|
209
198
|
attestation as Attestation<ForkPostElectra>,
|
|
@@ -318,7 +307,7 @@ export async function importBlock(
|
|
|
318
307
|
|
|
319
308
|
if (newHead.blockRoot !== oldHead.blockRoot) {
|
|
320
309
|
// Set head state as strong reference
|
|
321
|
-
this.regen.updateHeadState(newHead,
|
|
310
|
+
this.regen.updateHeadState(newHead, postState);
|
|
322
311
|
|
|
323
312
|
try {
|
|
324
313
|
this.emitter.emit(routes.events.EventType.head, {
|
|
@@ -388,11 +377,13 @@ export async function importBlock(
|
|
|
388
377
|
// we want to import block asap so do this in the next event loop
|
|
389
378
|
callInNextEventLoop(() => {
|
|
390
379
|
try {
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
380
|
+
if (isStatePostAltair(postState)) {
|
|
381
|
+
this.lightClientServer?.onImportBlockHead(
|
|
382
|
+
block.message as BeaconBlock<ForkPostAltair>,
|
|
383
|
+
postState,
|
|
384
|
+
parentBlockSlot
|
|
385
|
+
);
|
|
386
|
+
}
|
|
396
387
|
} catch (e) {
|
|
397
388
|
this.logger.verbose("Error lightClientServer.onImportBlock", {slot: blockSlot}, e as Error);
|
|
398
389
|
}
|
|
@@ -411,11 +402,11 @@ export async function importBlock(
|
|
|
411
402
|
// and the block is weak and can potentially be reorged out.
|
|
412
403
|
let shouldOverrideFcu = false;
|
|
413
404
|
|
|
414
|
-
if (blockSlot >= currentSlot &&
|
|
405
|
+
if (blockSlot >= currentSlot && isStatePostBellatrix(postState) && postState.isExecutionStateType) {
|
|
415
406
|
let notOverrideFcuReason = NotReorgedReason.Unknown;
|
|
416
407
|
const proposalSlot = blockSlot + 1;
|
|
417
408
|
try {
|
|
418
|
-
const proposerIndex =
|
|
409
|
+
const proposerIndex = postState.getBeaconProposer(proposalSlot);
|
|
419
410
|
const feeRecipient = this.beaconProposerCache.get(proposerIndex);
|
|
420
411
|
|
|
421
412
|
if (feeRecipient) {
|
|
@@ -495,27 +486,27 @@ export async function importBlock(
|
|
|
495
486
|
}
|
|
496
487
|
}
|
|
497
488
|
|
|
498
|
-
if (!
|
|
499
|
-
this.logger.verbose("After importBlock caching postState without SSZ cache", {slot:
|
|
489
|
+
if (!postState.isStateValidatorsNodesPopulated()) {
|
|
490
|
+
this.logger.verbose("After importBlock caching postState without SSZ cache", {slot: postState.slot});
|
|
500
491
|
}
|
|
501
492
|
|
|
502
493
|
// Cache shufflings when crossing an epoch boundary
|
|
503
494
|
const parentEpoch = computeEpochAtSlot(parentBlockSlot);
|
|
504
495
|
if (parentEpoch < blockEpoch) {
|
|
505
|
-
this.shufflingCache.processState(
|
|
496
|
+
this.shufflingCache.processState(postState);
|
|
506
497
|
this.logger.verbose("Processed shuffling for next epoch", {parentEpoch, blockEpoch, slot: blockSlot});
|
|
507
498
|
}
|
|
508
499
|
|
|
509
500
|
if (blockSlot % SLOTS_PER_EPOCH === 0) {
|
|
510
501
|
// Cache state to preserve epoch transition work
|
|
511
|
-
const checkpointState =
|
|
502
|
+
const checkpointState = postState;
|
|
512
503
|
const cp = getCheckpointFromState(checkpointState);
|
|
513
|
-
this.regen.addCheckpointState(cp, checkpointState
|
|
504
|
+
this.regen.addCheckpointState(cp, checkpointState);
|
|
514
505
|
// consumers should not mutate state ever
|
|
515
506
|
this.emitter.emit(ChainEvent.checkpoint, cp, checkpointState);
|
|
516
507
|
|
|
517
508
|
// Note: in-lined code from previos handler of ChainEvent.checkpoint
|
|
518
|
-
this.logger.verbose("Checkpoint processed",
|
|
509
|
+
this.logger.verbose("Checkpoint processed", toCheckpointHex(cp));
|
|
519
510
|
|
|
520
511
|
const activeValidatorsCount = checkpointState.activeValidatorCount;
|
|
521
512
|
this.metrics?.currentActiveValidators.set(activeValidatorsCount);
|
|
@@ -533,7 +524,7 @@ export async function importBlock(
|
|
|
533
524
|
const justifiedEpoch = justifiedCheckpoint.epoch;
|
|
534
525
|
const preJustifiedEpoch = parentBlockSummary.justifiedEpoch;
|
|
535
526
|
if (justifiedEpoch > preJustifiedEpoch) {
|
|
536
|
-
this.logger.verbose("Checkpoint justified",
|
|
527
|
+
this.logger.verbose("Checkpoint justified", toCheckpointHex(justifiedCheckpoint));
|
|
537
528
|
this.metrics?.previousJustifiedEpoch.set(checkpointState.previousJustifiedCheckpoint.epoch);
|
|
538
529
|
this.metrics?.currentJustifiedEpoch.set(justifiedCheckpoint.epoch);
|
|
539
530
|
}
|
|
@@ -547,7 +538,7 @@ export async function importBlock(
|
|
|
547
538
|
state: toRootHex(checkpointState.hashTreeRoot()),
|
|
548
539
|
executionOptimistic: false,
|
|
549
540
|
});
|
|
550
|
-
this.logger.verbose("Checkpoint finalized",
|
|
541
|
+
this.logger.verbose("Checkpoint finalized", toCheckpointHex(finalizedCheckpoint));
|
|
551
542
|
this.metrics?.finalizedEpoch.set(finalizedCheckpoint.epoch);
|
|
552
543
|
}
|
|
553
544
|
}
|
|
@@ -598,11 +589,11 @@ export async function importBlock(
|
|
|
598
589
|
this.metrics?.parentBlockDistance.observe(blockSlot - parentBlockSlot);
|
|
599
590
|
this.metrics?.proposerBalanceDeltaAny.observe(fullyVerifiedBlock.proposerBalanceDelta);
|
|
600
591
|
this.validatorMonitor?.registerImportedBlock(block.message, fullyVerifiedBlock);
|
|
601
|
-
if (
|
|
592
|
+
if (isStatePostAltair(fullyVerifiedBlock.postState)) {
|
|
602
593
|
this.validatorMonitor?.registerSyncAggregateInBlock(
|
|
603
594
|
blockEpoch,
|
|
604
595
|
(block as altair.SignedBeaconBlock).message.body.syncAggregate,
|
|
605
|
-
fullyVerifiedBlock.
|
|
596
|
+
fullyVerifiedBlock.postState.currentSyncCommitteeIndexed.validatorIndices
|
|
606
597
|
);
|
|
607
598
|
}
|
|
608
599
|
|
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {byteArrayEquals, fromHex, toRootHex} from "@lodestar/utils";
|
|
3
|
+
import {isStatePostGloas} from "@lodestar/state-transition";
|
|
4
|
+
import {fromHex} from "@lodestar/utils";
|
|
6
5
|
import {ExecutionPayloadStatus} from "../../execution/index.js";
|
|
7
6
|
import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
8
7
|
import {BeaconChain} from "../chain.js";
|
|
9
8
|
import {RegenCaller} from "../regen/interface.js";
|
|
10
9
|
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
11
10
|
import {ImportPayloadOpts} from "./types.js";
|
|
11
|
+
import {
|
|
12
|
+
verifyExecutionPayloadEnvelope,
|
|
13
|
+
verifyExecutionPayloadEnvelopeSignature,
|
|
14
|
+
} from "./verifyExecutionPayloadEnvelope.js";
|
|
15
|
+
import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
|
|
12
16
|
|
|
13
17
|
const EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS = 64;
|
|
14
18
|
|
|
@@ -16,7 +20,7 @@ export enum PayloadErrorCode {
|
|
|
16
20
|
EXECUTION_ENGINE_INVALID = "PAYLOAD_ERROR_EXECUTION_ENGINE_INVALID",
|
|
17
21
|
EXECUTION_ENGINE_ERROR = "PAYLOAD_ERROR_EXECUTION_ENGINE_ERROR",
|
|
18
22
|
BLOCK_NOT_IN_FORK_CHOICE = "PAYLOAD_ERROR_BLOCK_NOT_IN_FORK_CHOICE",
|
|
19
|
-
|
|
23
|
+
ENVELOPE_VERIFICATION_ERROR = "PAYLOAD_ERROR_ENVELOPE_VERIFICATION_ERROR",
|
|
20
24
|
INVALID_SIGNATURE = "PAYLOAD_ERROR_INVALID_SIGNATURE",
|
|
21
25
|
}
|
|
22
26
|
|
|
@@ -36,7 +40,7 @@ export type PayloadErrorType =
|
|
|
36
40
|
blockRootHex: string;
|
|
37
41
|
}
|
|
38
42
|
| {
|
|
39
|
-
code: PayloadErrorCode.
|
|
43
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR;
|
|
40
44
|
message: string;
|
|
41
45
|
}
|
|
42
46
|
| {
|
|
@@ -68,37 +72,40 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
68
72
|
/**
|
|
69
73
|
* Import an execution payload envelope after all data is available.
|
|
70
74
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
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
|
|
75
|
+
* The envelope is only verified here, no state mutation. State effects from the payload
|
|
76
|
+
* are applied on the next block via processParentExecutionPayload.
|
|
82
77
|
*
|
|
78
|
+
* Steps:
|
|
79
|
+
* 1. Emit `execution_payload_available` event for payload attestation
|
|
80
|
+
* 2. Get the ProtoBlock from fork choice
|
|
81
|
+
* 3. Wait for data columns to be available
|
|
82
|
+
* 4. Regenerate state for envelope verification
|
|
83
|
+
* 5. Verify envelope (fields against state, signature, and EL in parallel where possible)
|
|
84
|
+
* 6. Persist verified payload envelope to hot DB (waits for write-queue space for backpressure)
|
|
85
|
+
* 7. Update fork choice (transitions the block's PENDING variant to FULL)
|
|
86
|
+
* 8. Record metrics for payload envelope and column sources
|
|
87
|
+
* 9. Emit `execution_payload` event
|
|
83
88
|
*/
|
|
84
89
|
export async function importExecutionPayload(
|
|
85
90
|
this: BeaconChain,
|
|
86
91
|
payloadInput: PayloadEnvelopeInput,
|
|
92
|
+
signal: AbortSignal,
|
|
87
93
|
opts: ImportPayloadOpts = {}
|
|
88
94
|
): Promise<void> {
|
|
89
95
|
const signedEnvelope = payloadInput.getPayloadEnvelope();
|
|
90
96
|
const envelope = signedEnvelope.message;
|
|
97
|
+
const slot = envelope.payload.slotNumber;
|
|
91
98
|
const blockRootHex = payloadInput.blockRootHex;
|
|
92
99
|
const blockHashHex = payloadInput.getBlockHashHex();
|
|
93
|
-
const fork = this.config.getForkName(
|
|
100
|
+
const fork = this.config.getForkName(slot);
|
|
94
101
|
|
|
95
|
-
// 1. Emit `execution_payload_available` event at the start of import. At this point the
|
|
96
|
-
// is already complete, so the payload and required data are available for
|
|
97
|
-
// This event
|
|
98
|
-
// it before getting a response from the
|
|
99
|
-
if (this.clock.currentSlot
|
|
102
|
+
// 1. Emit `execution_payload_available` event at the start of import. At this point the
|
|
103
|
+
// payload input is already complete, so the payload and required data are available for
|
|
104
|
+
// payload attestation. This event only signals availability (not validity), so we can emit
|
|
105
|
+
// it before getting a response from the EL on whether the payload is valid or not.
|
|
106
|
+
if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
100
107
|
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
|
-
slot
|
|
108
|
+
slot,
|
|
102
109
|
blockRoot: blockRootHex,
|
|
103
110
|
});
|
|
104
111
|
}
|
|
@@ -112,23 +119,43 @@ export async function importExecutionPayload(
|
|
|
112
119
|
});
|
|
113
120
|
}
|
|
114
121
|
|
|
115
|
-
// 3.
|
|
116
|
-
// The
|
|
117
|
-
await
|
|
122
|
+
// 3. Wait for data columns to be available.
|
|
123
|
+
// The helper is shared with future gloas sync services; take the single-item batch form here.
|
|
124
|
+
await verifyPayloadsDataAvailability([payloadInput], signal);
|
|
118
125
|
|
|
119
|
-
// 4.
|
|
120
|
-
// We need the block state (post-block, pre-payload) to process the envelope
|
|
126
|
+
// 4. Regenerate state for envelope verification
|
|
121
127
|
const blockState = await this.regen.getBlockSlotState(
|
|
122
128
|
protoBlock,
|
|
123
129
|
protoBlock.slot,
|
|
124
130
|
{dontTransferCache: true},
|
|
125
131
|
RegenCaller.processBlock
|
|
126
132
|
);
|
|
133
|
+
if (!isStatePostGloas(blockState)) {
|
|
134
|
+
throw new PayloadError({
|
|
135
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
|
|
136
|
+
message: `Expected gloas+ state for payload import, got fork=${blockState.forkName}`,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
127
139
|
|
|
128
|
-
// 5.
|
|
129
|
-
//
|
|
130
|
-
//
|
|
131
|
-
|
|
140
|
+
// 5. Verify envelope fields against state first to fail fast before the EL + BLS work.
|
|
141
|
+
// When validSignature is true, gossip/API has already verified both the signature and the
|
|
142
|
+
// executionRequestsRoot, so we skip those checks here.
|
|
143
|
+
try {
|
|
144
|
+
verifyExecutionPayloadEnvelope(this.config, blockState, envelope, {
|
|
145
|
+
verifyExecutionRequestsRoot: !opts.validSignature,
|
|
146
|
+
});
|
|
147
|
+
} catch (e) {
|
|
148
|
+
throw new PayloadError(
|
|
149
|
+
{
|
|
150
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
|
|
151
|
+
message: (e as Error).message,
|
|
152
|
+
},
|
|
153
|
+
`Envelope verification error: ${(e as Error).message}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// 5a. Run EL and signature verification in parallel
|
|
158
|
+
const [execResult, signatureValid] = await Promise.all([
|
|
132
159
|
this.executionEngine.notifyNewPayload(
|
|
133
160
|
fork,
|
|
134
161
|
envelope.payload,
|
|
@@ -139,45 +166,22 @@ export async function importExecutionPayload(
|
|
|
139
166
|
|
|
140
167
|
opts.validSignature === true
|
|
141
168
|
? Promise.resolve(true)
|
|
142
|
-
: (
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return this.bls.verifySignatureSets([signatureSet]);
|
|
151
|
-
})(),
|
|
152
|
-
|
|
153
|
-
// Signature verified separately above.
|
|
154
|
-
// State root check is done separately below with better error typing (matching block pipeline pattern).
|
|
155
|
-
(async () => {
|
|
156
|
-
try {
|
|
157
|
-
return {
|
|
158
|
-
postPayloadState: blockState.processExecutionPayloadEnvelope(signedEnvelope, {
|
|
159
|
-
verifySignature: false,
|
|
160
|
-
verifyStateRoot: false,
|
|
161
|
-
}),
|
|
162
|
-
};
|
|
163
|
-
} catch (e) {
|
|
164
|
-
throw new PayloadError(
|
|
165
|
-
{
|
|
166
|
-
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
167
|
-
message: (e as Error).message,
|
|
168
|
-
},
|
|
169
|
-
`State transition error: ${(e as Error).message}`
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
})(),
|
|
169
|
+
: verifyExecutionPayloadEnvelopeSignature(
|
|
170
|
+
this.config,
|
|
171
|
+
blockState,
|
|
172
|
+
this.pubkeyCache,
|
|
173
|
+
signedEnvelope,
|
|
174
|
+
payloadInput.proposerIndex,
|
|
175
|
+
this.bls
|
|
176
|
+
),
|
|
173
177
|
]);
|
|
174
178
|
|
|
175
|
-
//
|
|
179
|
+
// 5b. Check signature verification result
|
|
176
180
|
if (!signatureValid) {
|
|
177
181
|
throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
|
|
178
182
|
}
|
|
179
183
|
|
|
180
|
-
//
|
|
184
|
+
// 5c. Handle EL response
|
|
181
185
|
switch (execResult.status) {
|
|
182
186
|
case ExecutionPayloadStatus.VALID:
|
|
183
187
|
break;
|
|
@@ -203,65 +207,45 @@ export async function importExecutionPayload(
|
|
|
203
207
|
});
|
|
204
208
|
}
|
|
205
209
|
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
|
|
210
|
-
throw new PayloadError({
|
|
211
|
-
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
212
|
-
message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
|
|
213
|
-
});
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
// 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
|
|
210
|
+
// 6. Persist payload envelope to hot DB. Wait for write-queue space here to apply backpressure
|
|
211
|
+
// on the import pipeline during sync, then perform the write asynchronously to avoid blocking.
|
|
212
|
+
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
217
213
|
this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
|
|
218
214
|
if (!isQueueErrorAborted(e)) {
|
|
219
215
|
this.logger.error(
|
|
220
216
|
"Error pushing payload envelope to unfinalized write queue",
|
|
221
|
-
{slot
|
|
217
|
+
{slot, blockRoot: blockRootHex},
|
|
222
218
|
e as Error
|
|
223
219
|
);
|
|
224
220
|
}
|
|
225
221
|
});
|
|
226
222
|
|
|
227
|
-
// 7. Update fork choice
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
blockHashHex,
|
|
231
|
-
envelope.payload.blockNumber,
|
|
232
|
-
toRootHex(postPayloadStateRoot),
|
|
233
|
-
toForkChoiceExecutionStatus(execResult.status)
|
|
234
|
-
);
|
|
235
|
-
|
|
236
|
-
// 8. Cache payload state
|
|
237
|
-
this.regen.processPayloadState(postPayloadState);
|
|
238
|
-
if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
|
|
239
|
-
const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
|
|
240
|
-
this.regen.addCheckpointState(checkpoint, postPayloadState, true);
|
|
241
|
-
}
|
|
223
|
+
// 7. Update fork choice, transitions the block's PENDING variant to FULL
|
|
224
|
+
const execStatus = toForkChoiceExecutionStatus(execResult.status);
|
|
225
|
+
this.forkChoice.onExecutionPayload(blockRootHex, blockHashHex, envelope.payload.blockNumber, execStatus);
|
|
242
226
|
|
|
243
|
-
//
|
|
227
|
+
// 8. Record metrics for payload envelope and column sources
|
|
244
228
|
this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
|
|
245
229
|
for (const {source} of payloadInput.getSampledColumnsWithSource()) {
|
|
246
230
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
247
231
|
}
|
|
248
232
|
|
|
249
|
-
//
|
|
250
|
-
if (this.clock.currentSlot -
|
|
233
|
+
// 9. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
234
|
+
if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
251
235
|
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
252
|
-
slot
|
|
236
|
+
slot,
|
|
253
237
|
builderIndex: envelope.builderIndex,
|
|
254
238
|
blockHash: blockHashHex,
|
|
255
239
|
blockRoot: blockRootHex,
|
|
256
|
-
stateRoot: toRootHex(envelope.stateRoot),
|
|
257
240
|
// TODO GLOAS: revisit once we support optimistic import
|
|
258
241
|
executionOptimistic: false,
|
|
259
242
|
});
|
|
260
243
|
}
|
|
261
244
|
|
|
262
245
|
this.logger.verbose("Execution payload imported", {
|
|
263
|
-
slot
|
|
264
|
-
|
|
246
|
+
slot,
|
|
247
|
+
builderIndex: envelope.builderIndex,
|
|
248
|
+
blockRoot: blockRootHex,
|
|
265
249
|
blockHash: blockHashHex,
|
|
266
250
|
});
|
|
267
251
|
}
|
|
@@ -88,8 +88,7 @@ export async function processBlocks(
|
|
|
88
88
|
const fullyVerifiedBlocks = relevantBlocks.map(
|
|
89
89
|
(block, i): FullyVerifiedBlock => ({
|
|
90
90
|
blockInput: block,
|
|
91
|
-
|
|
92
|
-
postEnvelopeState: null,
|
|
91
|
+
postState: postStates[i],
|
|
93
92
|
parentBlockSlot: parentSlots[i],
|
|
94
93
|
executionStatus: executionStatuses[i],
|
|
95
94
|
// start supporting optimistic syncing/processing
|
|
@@ -73,6 +73,7 @@ export class PayloadEnvelopeInput {
|
|
|
73
73
|
private timeCreatedSec: number;
|
|
74
74
|
|
|
75
75
|
private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
|
|
76
|
+
private readonly allDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
76
77
|
private readonly columnsDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
77
78
|
|
|
78
79
|
state: PayloadEnvelopeInputState;
|
|
@@ -97,6 +98,7 @@ export class PayloadEnvelopeInput {
|
|
|
97
98
|
this.custodyColumns = props.custodyColumns;
|
|
98
99
|
this.timeCreatedSec = props.timeCreatedSec;
|
|
99
100
|
this.payloadEnvelopeDataPromise = createPromise();
|
|
101
|
+
this.allDataPromise = createPromise();
|
|
100
102
|
this.columnsDataPromise = createPromise();
|
|
101
103
|
|
|
102
104
|
const noBlobs = props.bid.blobKzgCommitments.length === 0;
|
|
@@ -105,6 +107,7 @@ export class PayloadEnvelopeInput {
|
|
|
105
107
|
|
|
106
108
|
if (hasAllData) {
|
|
107
109
|
this.state = {hasPayload: false, hasAllData: true, hasComputedAllData: true};
|
|
110
|
+
this.allDataPromise.resolve(this.getSampledColumns());
|
|
108
111
|
this.columnsDataPromise.resolve(this.getSampledColumns());
|
|
109
112
|
} else {
|
|
110
113
|
this.state = {hasPayload: false, hasAllData: false, hasComputedAllData: false};
|
|
@@ -203,6 +206,12 @@ export class PayloadEnvelopeInput {
|
|
|
203
206
|
return true;
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
// Resolve allDataPromise on the first transition to hasAllData (either sampled-complete or
|
|
210
|
+
// reconstruction-threshold branch). Guarded so it fires exactly once.
|
|
211
|
+
if (!this.state.hasAllData && hasAllData) {
|
|
212
|
+
this.allDataPromise.resolve(sampledColumns);
|
|
213
|
+
}
|
|
214
|
+
|
|
206
215
|
if (hasComputedAllData) {
|
|
207
216
|
this.columnsDataPromise.resolve(sampledColumns);
|
|
208
217
|
}
|
|
@@ -315,6 +324,24 @@ export class PayloadEnvelopeInput {
|
|
|
315
324
|
return this.state.hasComputedAllData;
|
|
316
325
|
}
|
|
317
326
|
|
|
327
|
+
waitForAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
328
|
+
if (this.state.hasAllData) {
|
|
329
|
+
return Promise.resolve(this.getSampledColumns());
|
|
330
|
+
}
|
|
331
|
+
return withTimeout(() => this.allDataPromise.promise, timeout, signal);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
async waitForEnvelopeAndAllData(timeout: number, signal?: AbortSignal): Promise<this> {
|
|
335
|
+
if (!this.state.hasPayload || !this.state.hasAllData) {
|
|
336
|
+
await withTimeout(
|
|
337
|
+
() => Promise.all([this.payloadEnvelopeDataPromise.promise, this.allDataPromise.promise]),
|
|
338
|
+
timeout,
|
|
339
|
+
signal
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
return this;
|
|
343
|
+
}
|
|
344
|
+
|
|
318
345
|
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
319
346
|
if (this.state.hasComputedAllData) {
|
|
320
347
|
return Promise.resolve(this.getSampledColumns());
|
|
@@ -16,6 +16,11 @@ enum PayloadEnvelopeImportStatus {
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* PayloadEnvelopeProcessor processes payload envelope jobs in a queued fashion, one after the other.
|
|
19
|
+
*
|
|
20
|
+
* Jobs are enqueued only on envelope arrival (gossip or API). The envelope may reach us before
|
|
21
|
+
* the sampled data columns; importExecutionPayload awaits `verifyPayloadsDataAvailability`
|
|
22
|
+
* internally, so a queued job can pend for up to `PAYLOAD_DATA_AVAILABILITY_TIMEOUT` while
|
|
23
|
+
* waiting for columns. Duplicate triggers for the same payloadInput are deduped via `importStatus`.
|
|
19
24
|
*/
|
|
20
25
|
export class PayloadEnvelopeProcessor {
|
|
21
26
|
readonly jobQueue: JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>;
|
|
@@ -25,7 +30,7 @@ export class PayloadEnvelopeProcessor {
|
|
|
25
30
|
this.jobQueue = new JobItemQueue<[PayloadEnvelopeInput, ImportPayloadOpts], void>(
|
|
26
31
|
(payloadInput, opts) => {
|
|
27
32
|
this.importStatus.set(payloadInput, PayloadEnvelopeImportStatus.importing);
|
|
28
|
-
return importExecutionPayload.call(chain, payloadInput, opts);
|
|
33
|
+
return importExecutionPayload.call(chain, payloadInput, signal, opts);
|
|
29
34
|
},
|
|
30
35
|
{maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
|
|
31
36
|
metrics?.payloadEnvelopeProcessorQueue ?? undefined
|
|
@@ -33,10 +38,6 @@ export class PayloadEnvelopeProcessor {
|
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
async processPayloadEnvelopeJob(payloadInput: PayloadEnvelopeInput, opts: ImportPayloadOpts = {}): Promise<void> {
|
|
36
|
-
if (!payloadInput.isComplete()) {
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
41
|
if (this.importStatus.get(payloadInput) !== undefined) {
|
|
41
42
|
return;
|
|
42
43
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {BlockExecutionStatus
|
|
2
|
+
import {BlockExecutionStatus} from "@lodestar/fork-choice";
|
|
3
3
|
import {ForkSeq} from "@lodestar/params";
|
|
4
4
|
import {DataAvailabilityStatus, IBeaconStateView, computeEpochAtSlot} from "@lodestar/state-transition";
|
|
5
5
|
import type {IndexedAttestation, Slot, fulu} from "@lodestar/types";
|
|
@@ -43,8 +43,9 @@ export enum BlobSidecarValidation {
|
|
|
43
43
|
|
|
44
44
|
export type ImportPayloadOpts = {
|
|
45
45
|
/**
|
|
46
|
-
* Set to true
|
|
47
|
-
*
|
|
46
|
+
* Set to true when the envelope was already validated upstream (e.g., gossip/API validation):
|
|
47
|
+
* signature is trusted and execution_requests_root was already verified against the bid.
|
|
48
|
+
* When false/undefined, both are verified during import.
|
|
48
49
|
*/
|
|
49
50
|
validSignature?: boolean;
|
|
50
51
|
};
|
|
@@ -88,9 +89,16 @@ export type ImportBlockOpts = {
|
|
|
88
89
|
seenTimestampSec?: number;
|
|
89
90
|
};
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
/**
|
|
93
|
+
* A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import.
|
|
94
|
+
*
|
|
95
|
+
* `executionStatus` reflects the outcome of execution payload verification at block-import time:
|
|
96
|
+
* - pre-gloas: Valid | Syncing | PreMerge (from EL notifyNewPayload against the in-block payload)
|
|
97
|
+
* - post-gloas: PayloadSeparated (payload arrives separately as an envelope and is imported later)
|
|
98
|
+
*/
|
|
99
|
+
export type FullyVerifiedBlock = {
|
|
92
100
|
blockInput: IBlockInput;
|
|
93
|
-
|
|
101
|
+
postState: IBeaconStateView;
|
|
94
102
|
parentBlockSlot: Slot;
|
|
95
103
|
proposerBalanceDelta: number;
|
|
96
104
|
dataAvailabilityStatus: DataAvailabilityStatus;
|
|
@@ -98,25 +106,6 @@ type FullyVerifiedBlockBase = {
|
|
|
98
106
|
indexedAttestations: IndexedAttestation[];
|
|
99
107
|
/** Seen timestamp seconds */
|
|
100
108
|
seenTimestampSec: number;
|
|
109
|
+
/** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync */
|
|
110
|
+
executionStatus: BlockExecutionStatus;
|
|
101
111
|
};
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* A wrapper around a `SignedBeaconBlock` that indicates that this block is fully verified and ready to import.
|
|
105
|
-
*
|
|
106
|
-
* Discriminated union on `postEnvelopeState`:
|
|
107
|
-
* - `null` → block has no pre-verified envelope; `executionStatus` is any `BlockExecutionStatus`
|
|
108
|
-
* - non-null → envelope was pre-verified during state transition; `executionStatus` is narrowed to
|
|
109
|
-
* `Valid | Syncing` (matching what `forkChoice.onExecutionPayload` expects)
|
|
110
|
-
*/
|
|
111
|
-
export type FullyVerifiedBlock = FullyVerifiedBlockBase &
|
|
112
|
-
(
|
|
113
|
-
| {
|
|
114
|
-
postEnvelopeState: null;
|
|
115
|
-
/** If the execution payload couldn't be verified because of EL syncing status, used in optimistic sync or for merge block */
|
|
116
|
-
executionStatus: BlockExecutionStatus;
|
|
117
|
-
}
|
|
118
|
-
| {
|
|
119
|
-
postEnvelopeState: IBeaconStateView;
|
|
120
|
-
executionStatus: PayloadExecutionStatus;
|
|
121
|
-
}
|
|
122
|
-
);
|