@lodestar/beacon-node 1.43.0-dev.6641fd750e → 1.43.0-dev.66d2c102e3
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.js +4 -6
- package/lib/api/impl/beacon/blocks/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 +37 -2
- 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 +1 -4
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/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 +32 -37
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +25 -13
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +73 -84
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts +5 -3
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +29 -11
- 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 +7 -5
- 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/utils/chainSegment.d.ts +23 -2
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +81 -12
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts +3 -2
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +30 -5
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +15 -4
- package/lib/chain/blocks/verifyBlocksSanityChecks.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 +8 -6
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +36 -43
- 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 +8 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +2 -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/errors/index.d.ts +1 -0
- package/lib/chain/errors/index.d.ts.map +1 -1
- package/lib/chain/errors/index.js +1 -0
- package/lib/chain/errors/index.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +33 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/errors/proposerPreferences.js +13 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -0
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +11 -15
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +7 -5
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +48 -22
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -9
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +5 -32
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -8
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +55 -24
- 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 +7 -12
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.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/index.d.ts +1 -0
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +1 -0
- package/lib/chain/seenCache/index.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/seenCache/seenProposerPreferences.d.ts +15 -0
- package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
- package/lib/chain/seenCache/seenProposerPreferences.js +25 -0
- package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
- 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 +1 -0
- 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 +13 -1
- 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 +21 -11
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +4 -3
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts +8 -0
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/validation/proposerPreferences.js +69 -0
- package/lib/chain/validation/proposerPreferences.js.map +1 -0
- 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/metrics/metrics/lodestar.d.ts +1 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +4 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +7 -1
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/interface.js +1 -0
- package/lib/network/gossip/interface.js.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +12 -1
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +30 -748
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +6 -0
- package/lib/network/gossip/topic.js.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 +32 -12
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/index.js +5 -0
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +1 -0
- 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 +14 -6
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
- 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 +7 -4
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.js +7 -1
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/range/batch.d.ts +12 -2
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +56 -30
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +6 -2
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +4 -3
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +17 -6
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/types.d.ts +34 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +34 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +24 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +649 -53
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +46 -10
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +147 -24
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +6 -2
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
- package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.js +0 -9
- package/lib/sync/utils/pendingBlocksTree.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 +17 -16
- package/src/api/impl/beacon/blocks/index.ts +6 -6
- 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 +49 -3
- package/src/api/impl/validator/index.ts +3 -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 +31 -42
- package/src/chain/blocks/importExecutionPayload.ts +93 -104
- package/src/chain/blocks/index.ts +45 -14
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
- package/src/chain/blocks/types.ts +15 -26
- package/src/chain/blocks/utils/chainSegment.ts +106 -17
- package/src/chain/blocks/verifyBlock.ts +35 -6
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +16 -7
- 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 +51 -65
- package/src/chain/emitter.ts +15 -3
- package/src/chain/errors/attestationError.ts +6 -1
- package/src/chain/errors/blockError.ts +4 -1
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
- package/src/chain/errors/index.ts +1 -0
- package/src/chain/errors/proposerPreferences.ts +39 -0
- package/src/chain/forkChoice/index.ts +8 -20
- package/src/chain/interface.ts +11 -3
- package/src/chain/prepareNextSlot.ts +62 -23
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +73 -27
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +7 -12
- package/src/chain/regen/queued.ts +12 -48
- package/src/chain/regen/regen.ts +8 -36
- package/src/chain/seenCache/index.ts +1 -0
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +22 -20
- package/src/chain/seenCache/seenProposerPreferences.ts +29 -0
- 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 +1 -0
- package/src/chain/validation/executionPayloadBid.ts +14 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +22 -12
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- package/src/chain/validation/proposerPreferences.ts +91 -0
- 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/metrics/metrics/lodestar.ts +4 -0
- package/src/network/gossip/interface.ts +6 -0
- package/src/network/gossip/scoringParameters.ts +14 -1
- package/src/network/gossip/topic.ts +6 -0
- package/src/network/network.ts +1 -1
- package/src/network/processor/gossipHandlers.ts +41 -16
- package/src/network/processor/gossipQueues/index.ts +5 -0
- package/src/network/processor/index.ts +1 -0
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
- package/src/node/nodejs.ts +4 -2
- package/src/node/notifier.ts +8 -1
- package/src/sync/range/batch.ts +90 -35
- package/src/sync/range/chain.ts +13 -5
- package/src/sync/range/range.ts +18 -6
- package/src/sync/types.ts +72 -0
- package/src/sync/unknownBlock.ts +810 -57
- package/src/sync/utils/downloadByRange.ts +256 -39
- package/src/sync/utils/downloadByRoot.ts +12 -2
- package/src/sync/utils/pendingBlocksTree.ts +0 -15
- package/src/util/sszBytes.ts +21 -3
|
@@ -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,18 +72,21 @@ 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
|
+
* The DA wait must have run upstream (range sync awaits DA in `verifyBlocksInEpoch` for the
|
|
79
|
+
* whole segment; gossip / API path uses the `processExecutionPayload` wrapper below).
|
|
80
|
+
*
|
|
81
|
+
* Steps:
|
|
82
|
+
* 1. Emit `execution_payload_available` event for payload attestation
|
|
83
|
+
* 2. Get the ProtoBlock from fork choice
|
|
84
|
+
* 3. Regenerate state for envelope verification
|
|
85
|
+
* 4. Verify envelope (fields against state, signature, and EL in parallel where possible)
|
|
86
|
+
* 5. Persist verified payload envelope to hot DB (waits for write-queue space for backpressure)
|
|
87
|
+
* 6. Update fork choice (transitions the block's PENDING variant to FULL)
|
|
88
|
+
* 7. Record metrics for payload envelope and column sources
|
|
89
|
+
* 8. Emit `execution_payload` event
|
|
83
90
|
*/
|
|
84
91
|
export async function importExecutionPayload(
|
|
85
92
|
this: BeaconChain,
|
|
@@ -88,17 +95,18 @@ export async function importExecutionPayload(
|
|
|
88
95
|
): Promise<void> {
|
|
89
96
|
const signedEnvelope = payloadInput.getPayloadEnvelope();
|
|
90
97
|
const envelope = signedEnvelope.message;
|
|
98
|
+
const slot = envelope.payload.slotNumber;
|
|
91
99
|
const blockRootHex = payloadInput.blockRootHex;
|
|
92
100
|
const blockHashHex = payloadInput.getBlockHashHex();
|
|
93
|
-
const fork = this.config.getForkName(
|
|
101
|
+
const fork = this.config.getForkName(slot);
|
|
94
102
|
|
|
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 -
|
|
103
|
+
// 1. Emit `execution_payload_available` event at the start of import. At this point the
|
|
104
|
+
// payload input is already complete, so the payload and required data are available for
|
|
105
|
+
// payload attestation. This event only signals availability (not validity), so we can emit
|
|
106
|
+
// it before getting a response from the EL on whether the payload is valid or not.
|
|
107
|
+
if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
100
108
|
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
|
-
slot
|
|
109
|
+
slot,
|
|
102
110
|
blockRoot: blockRootHex,
|
|
103
111
|
});
|
|
104
112
|
}
|
|
@@ -112,12 +120,7 @@ export async function importExecutionPayload(
|
|
|
112
120
|
});
|
|
113
121
|
}
|
|
114
122
|
|
|
115
|
-
// 3.
|
|
116
|
-
// The actual DB write is deferred until after verification succeeds.
|
|
117
|
-
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
118
|
-
|
|
119
|
-
// 4. Get pre-state for processExecutionPayloadEnvelope
|
|
120
|
-
// We need the block state (post-block, pre-payload) to process the envelope
|
|
123
|
+
// 3. Regenerate state for envelope verification
|
|
121
124
|
const blockState = await this.regen.getBlockSlotState(
|
|
122
125
|
protoBlock,
|
|
123
126
|
protoBlock.slot,
|
|
@@ -126,15 +129,30 @@ export async function importExecutionPayload(
|
|
|
126
129
|
);
|
|
127
130
|
if (!isStatePostGloas(blockState)) {
|
|
128
131
|
throw new PayloadError({
|
|
129
|
-
code: PayloadErrorCode.
|
|
130
|
-
message: `Expected gloas+
|
|
132
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
|
|
133
|
+
message: `Expected gloas+ state for payload import, got fork=${blockState.forkName}`,
|
|
131
134
|
});
|
|
132
135
|
}
|
|
133
136
|
|
|
134
|
-
//
|
|
135
|
-
//
|
|
136
|
-
//
|
|
137
|
-
|
|
137
|
+
// 4. Verify envelope fields against state first to fail fast before the EL + BLS work.
|
|
138
|
+
// When validSignature is true, gossip/API has already verified both the signature and the
|
|
139
|
+
// executionRequestsRoot, so we skip those checks here.
|
|
140
|
+
try {
|
|
141
|
+
verifyExecutionPayloadEnvelope(this.config, blockState, envelope, {
|
|
142
|
+
verifyExecutionRequestsRoot: !opts.validSignature,
|
|
143
|
+
});
|
|
144
|
+
} catch (e) {
|
|
145
|
+
throw new PayloadError(
|
|
146
|
+
{
|
|
147
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
|
|
148
|
+
message: (e as Error).message,
|
|
149
|
+
},
|
|
150
|
+
`Envelope verification error: ${(e as Error).message}`
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// 4a. Run EL and signature verification in parallel
|
|
155
|
+
const [execResult, signatureValid] = await Promise.all([
|
|
138
156
|
this.executionEngine.notifyNewPayload(
|
|
139
157
|
fork,
|
|
140
158
|
envelope.payload,
|
|
@@ -145,45 +163,22 @@ export async function importExecutionPayload(
|
|
|
145
163
|
|
|
146
164
|
opts.validSignature === true
|
|
147
165
|
? Promise.resolve(true)
|
|
148
|
-
: (
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return this.bls.verifySignatureSets([signatureSet]);
|
|
157
|
-
})(),
|
|
158
|
-
|
|
159
|
-
// Signature verified separately above.
|
|
160
|
-
// State root check is done separately below with better error typing (matching block pipeline pattern).
|
|
161
|
-
(async () => {
|
|
162
|
-
try {
|
|
163
|
-
return {
|
|
164
|
-
postPayloadState: blockState.processExecutionPayloadEnvelope(signedEnvelope, {
|
|
165
|
-
verifySignature: false,
|
|
166
|
-
verifyStateRoot: false,
|
|
167
|
-
}),
|
|
168
|
-
};
|
|
169
|
-
} catch (e) {
|
|
170
|
-
throw new PayloadError(
|
|
171
|
-
{
|
|
172
|
-
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
173
|
-
message: (e as Error).message,
|
|
174
|
-
},
|
|
175
|
-
`State transition error: ${(e as Error).message}`
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
})(),
|
|
166
|
+
: verifyExecutionPayloadEnvelopeSignature(
|
|
167
|
+
this.config,
|
|
168
|
+
blockState,
|
|
169
|
+
this.pubkeyCache,
|
|
170
|
+
signedEnvelope,
|
|
171
|
+
payloadInput.proposerIndex,
|
|
172
|
+
this.bls
|
|
173
|
+
),
|
|
179
174
|
]);
|
|
180
175
|
|
|
181
|
-
//
|
|
176
|
+
// 4b. Check signature verification result
|
|
182
177
|
if (!signatureValid) {
|
|
183
178
|
throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
|
|
184
179
|
}
|
|
185
180
|
|
|
186
|
-
//
|
|
181
|
+
// 4c. Handle EL response
|
|
187
182
|
switch (execResult.status) {
|
|
188
183
|
case ExecutionPayloadStatus.VALID:
|
|
189
184
|
break;
|
|
@@ -209,69 +204,63 @@ export async function importExecutionPayload(
|
|
|
209
204
|
});
|
|
210
205
|
}
|
|
211
206
|
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
if (!byteArrayEquals(envelope.stateRoot, postPayloadStateRoot)) {
|
|
216
|
-
throw new PayloadError({
|
|
217
|
-
code: PayloadErrorCode.STATE_TRANSITION_ERROR,
|
|
218
|
-
message: `Envelope state root mismatch expected=${toRootHex(envelope.stateRoot)} actual=${toRootHex(postPayloadStateRoot)}`,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// 6. Persist payload envelope to hot DB (performed asynchronously to avoid blocking)
|
|
207
|
+
// 5. Persist payload envelope to hot DB. Wait for write-queue space here to apply backpressure
|
|
208
|
+
// on the import pipeline during sync, then perform the write asynchronously to avoid blocking.
|
|
209
|
+
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
223
210
|
this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
|
|
224
211
|
if (!isQueueErrorAborted(e)) {
|
|
225
212
|
this.logger.error(
|
|
226
213
|
"Error pushing payload envelope to unfinalized write queue",
|
|
227
|
-
{slot
|
|
214
|
+
{slot, blockRoot: blockRootHex},
|
|
228
215
|
e as Error
|
|
229
216
|
);
|
|
230
217
|
}
|
|
231
218
|
});
|
|
232
219
|
|
|
233
|
-
//
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
blockHashHex,
|
|
237
|
-
envelope.payload.blockNumber,
|
|
238
|
-
toRootHex(postPayloadStateRoot),
|
|
239
|
-
toForkChoiceExecutionStatus(execResult.status)
|
|
240
|
-
);
|
|
220
|
+
// 6. Update fork choice, transitions the block's PENDING variant to FULL
|
|
221
|
+
const execStatus = toForkChoiceExecutionStatus(execResult.status);
|
|
222
|
+
this.forkChoice.onExecutionPayload(blockRootHex, blockHashHex, envelope.payload.blockNumber, execStatus);
|
|
241
223
|
|
|
242
|
-
//
|
|
243
|
-
this.regen.processPayloadState(postPayloadState);
|
|
244
|
-
if (postPayloadState.slot % SLOTS_PER_EPOCH === 0) {
|
|
245
|
-
const {checkpoint} = postPayloadState.computeAnchorCheckpoint();
|
|
246
|
-
this.regen.addCheckpointState(checkpoint, postPayloadState, true);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// 9. Record metrics for payload envelope and column sources
|
|
224
|
+
// 7. Record metrics for payload envelope and column sources
|
|
250
225
|
this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
|
|
251
226
|
for (const {source} of payloadInput.getSampledColumnsWithSource()) {
|
|
252
227
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
253
228
|
}
|
|
254
229
|
|
|
255
|
-
|
|
256
|
-
|
|
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) {
|
|
230
|
+
// 8. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
231
|
+
if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
259
232
|
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
260
|
-
slot
|
|
233
|
+
slot,
|
|
261
234
|
builderIndex: envelope.builderIndex,
|
|
262
235
|
blockHash: blockHashHex,
|
|
263
236
|
blockRoot: blockRootHex,
|
|
264
|
-
stateRoot: stateRootHex,
|
|
265
237
|
// TODO GLOAS: revisit once we support optimistic import
|
|
266
238
|
executionOptimistic: false,
|
|
267
239
|
});
|
|
268
240
|
}
|
|
269
241
|
|
|
270
242
|
this.logger.verbose("Execution payload imported", {
|
|
271
|
-
slot
|
|
243
|
+
slot,
|
|
272
244
|
builderIndex: envelope.builderIndex,
|
|
273
245
|
blockRoot: blockRootHex,
|
|
274
246
|
blockHash: blockHashHex,
|
|
275
|
-
stateRoot: stateRootHex,
|
|
276
247
|
});
|
|
277
248
|
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Process an execution payload envelope end-to-end: wait for DA, then import.
|
|
252
|
+
*
|
|
253
|
+
* Used by the PayloadEnvelopeProcessor queue (gossip / API / unknown-payload sync) — i.e.
|
|
254
|
+
* callers that have NOT already awaited DA themselves. Range sync's inline dispatch in
|
|
255
|
+
* processBlocks skips this wrapper and calls `importExecutionPayload` directly, since
|
|
256
|
+
* `verifyBlocksInEpoch` already awaited DA for the segment.
|
|
257
|
+
*/
|
|
258
|
+
export async function processExecutionPayload(
|
|
259
|
+
this: BeaconChain,
|
|
260
|
+
payloadInput: PayloadEnvelopeInput,
|
|
261
|
+
signal: AbortSignal,
|
|
262
|
+
opts: ImportPayloadOpts = {}
|
|
263
|
+
): Promise<void> {
|
|
264
|
+
await verifyPayloadsDataAvailability([payloadInput], signal);
|
|
265
|
+
await importExecutionPayload.call(this, payloadInput, opts);
|
|
266
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {SignedBeaconBlock} from "@lodestar/types";
|
|
1
|
+
import {SignedBeaconBlock, Slot} from "@lodestar/types";
|
|
2
2
|
import {isErrorAborted, toRootHex} from "@lodestar/utils";
|
|
3
3
|
import {Metrics} from "../../metrics/metrics.js";
|
|
4
4
|
import {nextEventLoop} from "../../util/eventLoop.js";
|
|
@@ -8,6 +8,8 @@ import {BlockError, BlockErrorCode, isBlockErrorAborted} from "../errors/index.j
|
|
|
8
8
|
import {BlockProcessOpts} from "../options.js";
|
|
9
9
|
import {IBlockInput} from "./blockInput/types.js";
|
|
10
10
|
import {importBlock} from "./importBlock.js";
|
|
11
|
+
import {importExecutionPayload} from "./importExecutionPayload.js";
|
|
12
|
+
import {PayloadEnvelopeInput} from "./payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
11
13
|
import {FullyVerifiedBlock, ImportBlockOpts} from "./types.js";
|
|
12
14
|
import {assertLinearChainSegment} from "./utils/chainSegment.js";
|
|
13
15
|
import {verifyBlocksInEpoch} from "./verifyBlock.js";
|
|
@@ -21,20 +23,24 @@ const QUEUE_MAX_LENGTH = 256;
|
|
|
21
23
|
* BlockProcessor processes block jobs in a queued fashion, one after the other.
|
|
22
24
|
*/
|
|
23
25
|
export class BlockProcessor {
|
|
24
|
-
readonly jobQueue: JobItemQueue<[IBlockInput[], ImportBlockOpts], void>;
|
|
26
|
+
readonly jobQueue: JobItemQueue<[IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts], void>;
|
|
25
27
|
|
|
26
28
|
constructor(chain: BeaconChain, metrics: Metrics | null, opts: BlockProcessOpts, signal: AbortSignal) {
|
|
27
|
-
this.jobQueue = new JobItemQueue<[IBlockInput[], ImportBlockOpts], void>(
|
|
28
|
-
(job, importOpts) => {
|
|
29
|
-
return processBlocks.call(chain, job, {...opts, ...importOpts});
|
|
29
|
+
this.jobQueue = new JobItemQueue<[IBlockInput[], Map<Slot, PayloadEnvelopeInput> | null, ImportBlockOpts], void>(
|
|
30
|
+
(job, payloadEnvelopes, importOpts) => {
|
|
31
|
+
return processBlocks.call(chain, job, payloadEnvelopes, {...opts, ...importOpts});
|
|
30
32
|
},
|
|
31
33
|
{maxLength: QUEUE_MAX_LENGTH, noYieldIfOneItem: true, signal},
|
|
32
34
|
metrics?.blockProcessorQueue ?? undefined
|
|
33
35
|
);
|
|
34
36
|
}
|
|
35
37
|
|
|
36
|
-
async processBlocksJob(
|
|
37
|
-
|
|
38
|
+
async processBlocksJob(
|
|
39
|
+
job: IBlockInput[],
|
|
40
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
|
|
41
|
+
opts: ImportBlockOpts = {}
|
|
42
|
+
): Promise<void> {
|
|
43
|
+
await this.jobQueue.push(job, payloadEnvelopes, opts);
|
|
38
44
|
}
|
|
39
45
|
}
|
|
40
46
|
|
|
@@ -51,16 +57,13 @@ export class BlockProcessor {
|
|
|
51
57
|
export async function processBlocks(
|
|
52
58
|
this: BeaconChain,
|
|
53
59
|
blocks: IBlockInput[],
|
|
60
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
|
|
54
61
|
opts: BlockProcessOpts & ImportBlockOpts
|
|
55
62
|
): Promise<void> {
|
|
56
63
|
if (blocks.length === 0) {
|
|
57
64
|
return; // TODO: or throw?
|
|
58
65
|
}
|
|
59
66
|
|
|
60
|
-
if (blocks.length > 1) {
|
|
61
|
-
assertLinearChainSegment(this.config, blocks);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
67
|
try {
|
|
65
68
|
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, opts);
|
|
66
69
|
|
|
@@ -70,10 +73,25 @@ export async function processBlocks(
|
|
|
70
73
|
return;
|
|
71
74
|
}
|
|
72
75
|
|
|
76
|
+
const {warnings: orphanedPayloads} = assertLinearChainSegment(
|
|
77
|
+
this.config,
|
|
78
|
+
relevantBlocks,
|
|
79
|
+
payloadEnvelopes,
|
|
80
|
+
parentBlock
|
|
81
|
+
);
|
|
82
|
+
if (orphanedPayloads != null) {
|
|
83
|
+
for (const orphaned of orphanedPayloads) {
|
|
84
|
+
this.logger.debug("Orphaned payload envelope in chain segment", {
|
|
85
|
+
slot: orphaned.slot,
|
|
86
|
+
blockRoot: orphaned.payloadEnvelopeInput.blockRootHex,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
// Fully verify a block to be imported immediately after. Does not produce any side-effects besides adding intermediate
|
|
74
92
|
// states in the state cache through regen.
|
|
75
93
|
const {postStates, dataAvailabilityStatuses, proposerBalanceDeltas, segmentExecStatus, indexedAttestationsByBlock} =
|
|
76
|
-
await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, opts);
|
|
94
|
+
await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, payloadEnvelopes, opts);
|
|
77
95
|
|
|
78
96
|
// If segmentExecStatus has lvhForkchoice then, the entire segment should be invalid
|
|
79
97
|
// and we need to further propagate
|
|
@@ -88,8 +106,7 @@ export async function processBlocks(
|
|
|
88
106
|
const fullyVerifiedBlocks = relevantBlocks.map(
|
|
89
107
|
(block, i): FullyVerifiedBlock => ({
|
|
90
108
|
blockInput: block,
|
|
91
|
-
|
|
92
|
-
postPayloadState: null,
|
|
109
|
+
postState: postStates[i],
|
|
93
110
|
parentBlockSlot: parentSlots[i],
|
|
94
111
|
executionStatus: executionStatuses[i],
|
|
95
112
|
// start supporting optimistic syncing/processing
|
|
@@ -104,6 +121,20 @@ export async function processBlocks(
|
|
|
104
121
|
for (const fullyVerifiedBlock of fullyVerifiedBlocks) {
|
|
105
122
|
// TODO: Consider batching importBlock too if it takes significant time
|
|
106
123
|
await importBlock.call(this, fullyVerifiedBlock, opts);
|
|
124
|
+
|
|
125
|
+
const slot = fullyVerifiedBlock.blockInput.getBlock().message.slot;
|
|
126
|
+
const payloadInput = payloadEnvelopes?.get(slot);
|
|
127
|
+
if (payloadInput?.hasPayloadEnvelope()) {
|
|
128
|
+
if (!payloadInput.isComplete()) {
|
|
129
|
+
// we validated DA before reaching this
|
|
130
|
+
throw new Error(`Payload envelope for slot ${slot} not complete after DA verification`);
|
|
131
|
+
}
|
|
132
|
+
// we already awaited DA in verifyBlocksInEpoch for this segment
|
|
133
|
+
// TODO GLOAS: may need FullyVerifiedPayload here with DatAvailabilityStatus added from here
|
|
134
|
+
// the current flow use that data from the forkchoice pending node which is not correct
|
|
135
|
+
await importExecutionPayload.call(this, payloadInput, {validSignature: false});
|
|
136
|
+
}
|
|
137
|
+
|
|
107
138
|
await nextEventLoop();
|
|
108
139
|
}
|
|
109
140
|
} catch (e) {
|
|
@@ -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());
|
|
@@ -2,7 +2,7 @@ import {Metrics} from "../../metrics/metrics.js";
|
|
|
2
2
|
import {JobItemQueue} from "../../util/queue/index.js";
|
|
3
3
|
import type {BeaconChain} from "../chain.js";
|
|
4
4
|
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
5
|
-
import {
|
|
5
|
+
import {processExecutionPayload} from "./importExecutionPayload.js";
|
|
6
6
|
import {ImportPayloadOpts} from "./types.js";
|
|
7
7
|
|
|
8
8
|
// TODO GLOAS: Set to be equal to DEFAULT_MAX_PENDING_UNFINALIZED_PAYLOAD_ENVELOPE_WRITES for now
|
|
@@ -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
|
|
33
|
+
return processExecutionPayload.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, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
2
|
+
import type {BlockExecutionStatus, PayloadExecutionStatus} 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 | PayloadExecutionStatus;
|
|
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 `postPayloadState`:
|
|
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
|
-
postPayloadState: 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
|
-
postPayloadState: IBeaconStateView;
|
|
120
|
-
executionStatus: PayloadExecutionStatus;
|
|
121
|
-
}
|
|
122
|
-
);
|