@lodestar/beacon-node 1.43.0-dev.433e692fd9 → 1.43.0-dev.4451fec75a
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 +17 -9
- 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 +45 -2
- package/lib/api/impl/beacon/pool/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/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +0 -1
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.js +1 -1
- 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 +68 -6
- 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.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/blockInput/blockInput.d.ts +3 -0
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.js +4 -1
- package/lib/chain/blocks/blockInput/blockInput.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +16 -32
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +32 -14
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +101 -90
- 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 +58 -26
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +15 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +48 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +17 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.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 -20
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +21 -2
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +92 -12
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts +5 -3
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +50 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +0 -4
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js +5 -2
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts +2 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +25 -5
- 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 +80 -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 +30 -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 +44 -14
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +16 -15
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -4
- package/lib/chain/emitter.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 +40 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/errors/proposerPreferences.js +14 -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 -19
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/initState.d.ts.map +1 -1
- package/lib/chain/initState.js +6 -1
- package/lib/chain/initState.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/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +1 -1
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts +4 -3
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +56 -14
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +45 -17
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +13 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +68 -25
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -0
- 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.map +1 -1
- package/lib/chain/regen/queued.js +1 -4
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +1 -4
- 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 +24 -7
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +69 -17
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/seenCache/seenProposerPreferences.d.ts +16 -0
- package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
- package/lib/chain/seenCache/seenProposerPreferences.js +26 -0
- package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +4 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.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 +24 -9
- 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 +19 -9
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +9 -6
- 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 +91 -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 +5 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +9 -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 +760 -2
- 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/interface.d.ts +2 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +2 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +9 -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 +93 -25
- 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 +6 -5
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.d.ts.map +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.js +1 -1
- package/lib/network/reqresp/ReqRespBeaconNode.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts +9 -0
- package/lib/network/reqresp/handlers/beaconBlocksByHead.d.ts.map +1 -0
- package/lib/network/reqresp/handlers/beaconBlocksByHead.js +61 -0
- package/lib/network/reqresp/handlers/beaconBlocksByHead.js.map +1 -0
- 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/network/reqresp/handlers/index.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/index.js +5 -0
- package/lib/network/reqresp/handlers/index.js.map +1 -1
- package/lib/network/reqresp/interface.d.ts +1 -1
- package/lib/network/reqresp/interface.js +1 -1
- package/lib/network/reqresp/protocols.d.ts +1 -0
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +5 -0
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/rateLimit.d.ts.map +1 -1
- package/lib/network/reqresp/rateLimit.js +4 -0
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/reqresp/score.d.ts.map +1 -1
- package/lib/network/reqresp/score.js +1 -0
- package/lib/network/reqresp/score.js.map +1 -1
- package/lib/network/reqresp/types.d.ts +3 -0
- package/lib/network/reqresp/types.d.ts.map +1 -1
- package/lib/network/reqresp/types.js +3 -0
- package/lib/network/reqresp/types.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +6 -4
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/constants.d.ts +7 -1
- package/lib/sync/constants.d.ts.map +1 -1
- package/lib/sync/constants.js +7 -4
- package/lib/sync/constants.js.map +1 -1
- package/lib/sync/range/batch.d.ts +55 -8
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +291 -66
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +22 -4
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +103 -11
- 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 +71 -11
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/range/utils/peerBalancer.d.ts +2 -1
- package/lib/sync/range/utils/peerBalancer.d.ts.map +1 -1
- package/lib/sync/range/utils/peerBalancer.js +8 -4
- package/lib/sync/range/utils/peerBalancer.js.map +1 -1
- package/lib/sync/sync.d.ts.map +1 -1
- package/lib/sync/sync.js +13 -0
- package/lib/sync/sync.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 +29 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +727 -61
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +73 -10
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +213 -26
- 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 +16 -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/sync/utils/rateLimit.d.ts +2 -0
- package/lib/sync/utils/rateLimit.d.ts.map +1 -0
- package/lib/sync/utils/rateLimit.js +15 -0
- package/lib/sync/utils/rateLimit.js.map +1 -0
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +20 -5
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +17 -17
- package/src/api/impl/beacon/blocks/index.ts +22 -9
- package/src/api/impl/beacon/pool/index.ts +83 -1
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/debug/index.ts +0 -1
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/impl/validator/index.ts +82 -5
- 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 +4 -4
- package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
- package/src/chain/blocks/blockInput/blockInput.ts +4 -1
- package/src/chain/blocks/importBlock.ts +16 -56
- package/src/chain/blocks/importExecutionPayload.ts +127 -107
- package/src/chain/blocks/index.ts +71 -23
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +64 -3
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +18 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
- package/src/chain/blocks/types.ts +15 -25
- package/src/chain/blocks/utils/chainSegment.ts +117 -17
- package/src/chain/blocks/verifyBlock.ts +70 -9
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +6 -4
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +26 -7
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +137 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +41 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
- package/src/chain/chain.ts +65 -26
- package/src/chain/emitter.ts +15 -14
- 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 +47 -0
- package/src/chain/forkChoice/index.ts +8 -24
- package/src/chain/initState.ts +9 -1
- package/src/chain/interface.ts +11 -3
- package/src/chain/lightClient/index.ts +6 -6
- package/src/chain/opPools/payloadAttestationPool.ts +63 -18
- package/src/chain/prepareNextSlot.ts +53 -18
- package/src/chain/produceBlock/produceBlockBody.ts +91 -21
- package/src/chain/regen/interface.ts +1 -0
- package/src/chain/regen/queued.ts +2 -7
- package/src/chain/regen/regen.ts +2 -7
- package/src/chain/seenCache/index.ts +1 -0
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +89 -21
- package/src/chain/seenCache/seenProposerPreferences.ts +32 -0
- package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
- package/src/chain/validation/block.ts +1 -0
- package/src/chain/validation/executionPayloadBid.ts +25 -8
- package/src/chain/validation/executionPayloadEnvelope.ts +20 -10
- package/src/chain/validation/payloadAttestationMessage.ts +11 -7
- package/src/chain/validation/proposerPreferences.ts +110 -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 +10 -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/interface.ts +2 -0
- package/src/network/network.ts +24 -1
- package/src/network/processor/gossipHandlers.ts +116 -30
- package/src/network/processor/gossipQueues/index.ts +5 -0
- package/src/network/processor/index.ts +6 -5
- package/src/network/reqresp/ReqRespBeaconNode.ts +1 -0
- package/src/network/reqresp/handlers/beaconBlocksByHead.ts +91 -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/network/reqresp/handlers/index.ts +5 -0
- package/src/network/reqresp/interface.ts +1 -1
- package/src/network/reqresp/protocols.ts +6 -0
- package/src/network/reqresp/rateLimit.ts +4 -0
- package/src/network/reqresp/score.ts +1 -0
- package/src/network/reqresp/types.ts +5 -0
- package/src/node/nodejs.ts +6 -4
- package/src/sync/constants.ts +8 -4
- package/src/sync/range/batch.ts +388 -75
- package/src/sync/range/chain.ts +131 -14
- package/src/sync/range/range.ts +86 -11
- package/src/sync/range/utils/peerBalancer.ts +9 -3
- package/src/sync/sync.ts +13 -1
- package/src/sync/types.ts +72 -0
- package/src/sync/unknownBlock.ts +915 -65
- package/src/sync/utils/downloadByRange.ts +386 -39
- package/src/sync/utils/downloadByRoot.ts +24 -2
- package/src/sync/utils/pendingBlocksTree.ts +0 -15
- package/src/sync/utils/rateLimit.ts +16 -0
- package/src/util/sszBytes.ts +25 -5
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
|
-
import {ExecutionStatus, PayloadExecutionStatus} from "@lodestar/fork-choice";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import {ExecutionStatus, PayloadExecutionStatus, getSafeExecutionBlockHash} from "@lodestar/fork-choice";
|
|
3
|
+
import {DataAvailabilityStatus, isStatePostGloas} from "@lodestar/state-transition";
|
|
4
|
+
import {isErrorAborted} from "@lodestar/utils";
|
|
5
|
+
import {ZERO_HASH_HEX} from "../../constants/index.js";
|
|
6
6
|
import {ExecutionPayloadStatus} from "../../execution/index.js";
|
|
7
7
|
import {isQueueErrorAborted} from "../../util/queue/index.js";
|
|
8
8
|
import {BeaconChain} from "../chain.js";
|
|
9
9
|
import {RegenCaller} from "../regen/interface.js";
|
|
10
10
|
import {PayloadEnvelopeInput} from "../seenCache/seenPayloadEnvelopeInput.js";
|
|
11
11
|
import {ImportPayloadOpts} from "./types.js";
|
|
12
|
+
import {
|
|
13
|
+
verifyExecutionPayloadEnvelope,
|
|
14
|
+
verifyExecutionPayloadEnvelopeSignature,
|
|
15
|
+
} from "./verifyExecutionPayloadEnvelope.js";
|
|
16
|
+
import {verifyPayloadsDataAvailability} from "./verifyPayloadsDataAvailability.js";
|
|
12
17
|
|
|
13
18
|
const EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS = 64;
|
|
14
19
|
|
|
@@ -16,7 +21,8 @@ export enum PayloadErrorCode {
|
|
|
16
21
|
EXECUTION_ENGINE_INVALID = "PAYLOAD_ERROR_EXECUTION_ENGINE_INVALID",
|
|
17
22
|
EXECUTION_ENGINE_ERROR = "PAYLOAD_ERROR_EXECUTION_ENGINE_ERROR",
|
|
18
23
|
BLOCK_NOT_IN_FORK_CHOICE = "PAYLOAD_ERROR_BLOCK_NOT_IN_FORK_CHOICE",
|
|
19
|
-
|
|
24
|
+
MISS_BLOCK_STATE = "PAYLOAD_ERROR_MISS_BLOCK_STATE",
|
|
25
|
+
ENVELOPE_VERIFICATION_ERROR = "PAYLOAD_ERROR_ENVELOPE_VERIFICATION_ERROR",
|
|
20
26
|
INVALID_SIGNATURE = "PAYLOAD_ERROR_INVALID_SIGNATURE",
|
|
21
27
|
}
|
|
22
28
|
|
|
@@ -36,7 +42,11 @@ export type PayloadErrorType =
|
|
|
36
42
|
blockRootHex: string;
|
|
37
43
|
}
|
|
38
44
|
| {
|
|
39
|
-
code: PayloadErrorCode.
|
|
45
|
+
code: PayloadErrorCode.MISS_BLOCK_STATE;
|
|
46
|
+
blockRootHex: string;
|
|
47
|
+
}
|
|
48
|
+
| {
|
|
49
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR;
|
|
40
50
|
message: string;
|
|
41
51
|
}
|
|
42
52
|
| {
|
|
@@ -56,7 +66,6 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
56
66
|
switch (status) {
|
|
57
67
|
case ExecutionPayloadStatus.VALID:
|
|
58
68
|
return ExecutionStatus.Valid;
|
|
59
|
-
// TODO GLOAS: Handle optimistic import for payload
|
|
60
69
|
case ExecutionPayloadStatus.SYNCING:
|
|
61
70
|
case ExecutionPayloadStatus.ACCEPTED:
|
|
62
71
|
return ExecutionStatus.Syncing;
|
|
@@ -68,37 +77,43 @@ function toForkChoiceExecutionStatus(status: ExecutionPayloadStatus): PayloadExe
|
|
|
68
77
|
/**
|
|
69
78
|
* Import an execution payload envelope after all data is available.
|
|
70
79
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
* 5. Runs EL verification (notifyNewPayload) in parallel with signature verification and processExecutionPayloadEnvelope
|
|
77
|
-
* 6. Persists verified payload envelope to hot DB
|
|
78
|
-
* 7. Updates fork choice
|
|
79
|
-
* 8. Caches the post-execution payload state
|
|
80
|
-
* 9. Records metrics for column sources
|
|
81
|
-
* 10. Emits `execution_payload` for recent enough payloads after successful import
|
|
80
|
+
* The envelope is only verified here, no state mutation. State effects from the payload
|
|
81
|
+
* are applied on the next block via processParentExecutionPayload.
|
|
82
|
+
*
|
|
83
|
+
* The DA wait must have run upstream (range sync awaits DA in `verifyBlocksInEpoch` for the
|
|
84
|
+
* whole segment; gossip / API path uses the `processExecutionPayload` wrapper below).
|
|
82
85
|
*
|
|
86
|
+
* Steps:
|
|
87
|
+
* 1. Emit `execution_payload_available` event for payload attestation
|
|
88
|
+
* 2. Get the ProtoBlock from fork choice
|
|
89
|
+
* 3. Regenerate state for envelope verification
|
|
90
|
+
* 4. Verify envelope (fields against state, signature, and EL in parallel where possible)
|
|
91
|
+
* 5. Persist verified payload envelope to hot DB (waits for write-queue space for backpressure)
|
|
92
|
+
* 6. Update fork choice (transitions the block's PENDING variant to FULL)
|
|
93
|
+
* 7. Queue notifyForkchoiceUpdate to engine api
|
|
94
|
+
* 8. Record metrics for payload envelope and column sources
|
|
95
|
+
* 9. Emit `execution_payload` event
|
|
83
96
|
*/
|
|
84
97
|
export async function importExecutionPayload(
|
|
85
98
|
this: BeaconChain,
|
|
86
99
|
payloadInput: PayloadEnvelopeInput,
|
|
100
|
+
dataAvailabilityStatus: DataAvailabilityStatus,
|
|
87
101
|
opts: ImportPayloadOpts = {}
|
|
88
102
|
): Promise<void> {
|
|
89
103
|
const signedEnvelope = payloadInput.getPayloadEnvelope();
|
|
90
104
|
const envelope = signedEnvelope.message;
|
|
105
|
+
const slot = envelope.payload.slotNumber;
|
|
91
106
|
const blockRootHex = payloadInput.blockRootHex;
|
|
92
107
|
const blockHashHex = payloadInput.getBlockHashHex();
|
|
93
|
-
const fork = this.config.getForkName(
|
|
108
|
+
const fork = this.config.getForkName(slot);
|
|
94
109
|
|
|
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 -
|
|
110
|
+
// 1. Emit `execution_payload_available` event at the start of import. At this point the
|
|
111
|
+
// payload input is already complete, so the payload and required data are available for
|
|
112
|
+
// payload attestation. This event only signals availability (not validity), so we can emit
|
|
113
|
+
// it before getting a response from the EL on whether the payload is valid or not.
|
|
114
|
+
if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
100
115
|
this.emitter.emit(routes.events.EventType.executionPayloadAvailable, {
|
|
101
|
-
slot
|
|
116
|
+
slot,
|
|
102
117
|
blockRoot: blockRootHex,
|
|
103
118
|
});
|
|
104
119
|
}
|
|
@@ -112,78 +127,72 @@ export async function importExecutionPayload(
|
|
|
112
127
|
});
|
|
113
128
|
}
|
|
114
129
|
|
|
115
|
-
// 3.
|
|
116
|
-
|
|
117
|
-
|
|
130
|
+
// 3. Regenerate state for envelope verification
|
|
131
|
+
const blockState = await this.regen
|
|
132
|
+
.getBlockSlotState(protoBlock, protoBlock.slot, {dontTransferCache: true}, RegenCaller.processBlock)
|
|
133
|
+
.catch(() =>
|
|
134
|
+
// only happen at the 1st batch of skipped slot checkpoint sync
|
|
135
|
+
this.regen.getClosestHeadState(protoBlock)
|
|
136
|
+
);
|
|
118
137
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
RegenCaller.processBlock
|
|
126
|
-
);
|
|
138
|
+
if (blockState == null) {
|
|
139
|
+
throw new PayloadError({
|
|
140
|
+
code: PayloadErrorCode.MISS_BLOCK_STATE,
|
|
141
|
+
blockRootHex: protoBlock.blockRoot,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
127
144
|
if (!isStatePostGloas(blockState)) {
|
|
128
145
|
throw new PayloadError({
|
|
129
|
-
code: PayloadErrorCode.
|
|
130
|
-
message: `Expected gloas+
|
|
146
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
|
|
147
|
+
message: `Expected gloas+ state for payload import, got fork=${blockState.forkName}`,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 4. Verify envelope fields against state first to fail fast before the EL + BLS work.
|
|
152
|
+
// When validSignature is true, gossip/API has already verified both the signature and the
|
|
153
|
+
// executionRequestsRoot, so we skip those checks here.
|
|
154
|
+
try {
|
|
155
|
+
verifyExecutionPayloadEnvelope(this.config, blockState, envelope, {
|
|
156
|
+
verifyExecutionRequestsRoot: !opts.validSignature,
|
|
131
157
|
});
|
|
158
|
+
} catch (e) {
|
|
159
|
+
throw new PayloadError(
|
|
160
|
+
{
|
|
161
|
+
code: PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR,
|
|
162
|
+
message: (e as Error).message,
|
|
163
|
+
},
|
|
164
|
+
`Envelope verification error: ${(e as Error).message}`
|
|
165
|
+
);
|
|
132
166
|
}
|
|
133
167
|
|
|
134
|
-
//
|
|
135
|
-
|
|
136
|
-
// called when payloadInput.isComplete() is true, so all data is already available.
|
|
137
|
-
const [execResult, signatureValid, postPayloadResult] = await Promise.all([
|
|
168
|
+
// 4a. Run EL and signature verification in parallel
|
|
169
|
+
const [execResult, signatureValid] = await Promise.all([
|
|
138
170
|
this.executionEngine.notifyNewPayload(
|
|
139
171
|
fork,
|
|
140
172
|
envelope.payload,
|
|
141
173
|
payloadInput.getVersionedHashes(),
|
|
142
|
-
|
|
174
|
+
envelope.parentBeaconBlockRoot,
|
|
143
175
|
envelope.executionRequests
|
|
144
176
|
),
|
|
145
177
|
|
|
146
178
|
opts.validSignature === true
|
|
147
179
|
? 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
|
-
})(),
|
|
180
|
+
: verifyExecutionPayloadEnvelopeSignature(
|
|
181
|
+
this.config,
|
|
182
|
+
blockState,
|
|
183
|
+
this.pubkeyCache,
|
|
184
|
+
signedEnvelope,
|
|
185
|
+
payloadInput.proposerIndex,
|
|
186
|
+
this.bls
|
|
187
|
+
),
|
|
179
188
|
]);
|
|
180
189
|
|
|
181
|
-
//
|
|
190
|
+
// 4b. Check signature verification result
|
|
182
191
|
if (!signatureValid) {
|
|
183
192
|
throw new PayloadError({code: PayloadErrorCode.INVALID_SIGNATURE});
|
|
184
193
|
}
|
|
185
194
|
|
|
186
|
-
//
|
|
195
|
+
// 4c. Handle EL response
|
|
187
196
|
switch (execResult.status) {
|
|
188
197
|
case ExecutionPayloadStatus.VALID:
|
|
189
198
|
break;
|
|
@@ -209,69 +218,80 @@ export async function importExecutionPayload(
|
|
|
209
218
|
});
|
|
210
219
|
}
|
|
211
220
|
|
|
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)
|
|
221
|
+
// 5. Persist payload envelope to hot DB. Wait for write-queue space here to apply backpressure
|
|
222
|
+
// on the import pipeline during sync, then perform the write asynchronously to avoid blocking.
|
|
223
|
+
await this.unfinalizedPayloadEnvelopeWrites.waitForSpace();
|
|
223
224
|
this.unfinalizedPayloadEnvelopeWrites.push(payloadInput).catch((e) => {
|
|
224
225
|
if (!isQueueErrorAborted(e)) {
|
|
225
226
|
this.logger.error(
|
|
226
227
|
"Error pushing payload envelope to unfinalized write queue",
|
|
227
|
-
{slot
|
|
228
|
+
{slot, blockRoot: blockRootHex},
|
|
228
229
|
e as Error
|
|
229
230
|
);
|
|
230
231
|
}
|
|
231
232
|
});
|
|
232
233
|
|
|
233
|
-
//
|
|
234
|
+
// 6. Update fork choice, transitions the block's PENDING variant to FULL
|
|
235
|
+
const execStatus = toForkChoiceExecutionStatus(execResult.status);
|
|
234
236
|
this.forkChoice.onExecutionPayload(
|
|
235
237
|
blockRootHex,
|
|
236
238
|
blockHashHex,
|
|
237
239
|
envelope.payload.blockNumber,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
+
execStatus,
|
|
241
|
+
dataAvailabilityStatus
|
|
240
242
|
);
|
|
241
243
|
|
|
242
|
-
//
|
|
243
|
-
this.
|
|
244
|
-
if (
|
|
245
|
-
const
|
|
246
|
-
this.
|
|
244
|
+
// 7. Queue notifyForkchoiceUpdate to engine api
|
|
245
|
+
const head = this.forkChoice.getHead();
|
|
246
|
+
if (!this.opts.disableImportExecutionFcU && blockRootHex === head.blockRoot) {
|
|
247
|
+
const safeBlockHash = getSafeExecutionBlockHash(this.forkChoice);
|
|
248
|
+
const finalizedBlockHash = this.forkChoice.getFinalizedBlock().executionPayloadBlockHash ?? ZERO_HASH_HEX;
|
|
249
|
+
this.executionEngine.notifyForkchoiceUpdate(fork, blockHashHex, safeBlockHash, finalizedBlockHash).catch((e) => {
|
|
250
|
+
if (!isErrorAborted(e) && !isQueueErrorAborted(e)) {
|
|
251
|
+
this.logger.error("Error pushing notifyForkchoiceUpdate()", {blockHashHex, finalizedBlockHash}, e);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
247
254
|
}
|
|
248
255
|
|
|
249
|
-
//
|
|
256
|
+
// 8. Record metrics for payload envelope and column sources
|
|
250
257
|
this.metrics?.importPayload.bySource.inc({source: payloadInput.getPayloadEnvelopeSource().source});
|
|
251
258
|
for (const {source} of payloadInput.getSampledColumnsWithSource()) {
|
|
252
259
|
this.metrics?.importPayload.columnsBySource.inc({source});
|
|
253
260
|
}
|
|
254
261
|
|
|
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) {
|
|
262
|
+
// 9. Emit event after payload is fully verified and imported to fork choice, only for recent enough payloads
|
|
263
|
+
if (this.clock.currentSlot - slot < EVENTSTREAM_EMIT_RECENT_EXECUTION_PAYLOAD_SLOTS) {
|
|
259
264
|
this.emitter.emit(routes.events.EventType.executionPayload, {
|
|
260
|
-
slot
|
|
265
|
+
slot,
|
|
261
266
|
builderIndex: envelope.builderIndex,
|
|
262
267
|
blockHash: blockHashHex,
|
|
263
268
|
blockRoot: blockRootHex,
|
|
264
|
-
|
|
265
|
-
// TODO GLOAS: revisit once we support optimistic import
|
|
266
|
-
executionOptimistic: false,
|
|
269
|
+
executionOptimistic: execStatus === ExecutionStatus.Syncing,
|
|
267
270
|
});
|
|
268
271
|
}
|
|
269
272
|
|
|
270
273
|
this.logger.verbose("Execution payload imported", {
|
|
271
|
-
slot
|
|
274
|
+
slot,
|
|
272
275
|
builderIndex: envelope.builderIndex,
|
|
273
276
|
blockRoot: blockRootHex,
|
|
274
277
|
blockHash: blockHashHex,
|
|
275
|
-
stateRoot: stateRootHex,
|
|
276
278
|
});
|
|
277
279
|
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Process an execution payload envelope end-to-end: wait for DA, then import.
|
|
283
|
+
*
|
|
284
|
+
* Used by the PayloadEnvelopeProcessor queue (gossip / API / unknown-payload sync) — i.e.
|
|
285
|
+
* callers that have NOT already awaited DA themselves. Range sync's inline dispatch in
|
|
286
|
+
* processBlocks skips this wrapper and calls `importExecutionPayload` directly, since
|
|
287
|
+
* `verifyBlocksInEpoch` already awaited DA for the segment.
|
|
288
|
+
*/
|
|
289
|
+
export async function processExecutionPayload(
|
|
290
|
+
this: BeaconChain,
|
|
291
|
+
payloadInput: PayloadEnvelopeInput,
|
|
292
|
+
signal: AbortSignal,
|
|
293
|
+
opts: ImportPayloadOpts = {}
|
|
294
|
+
): Promise<void> {
|
|
295
|
+
const {dataAvailabilityStatuses} = await verifyPayloadsDataAvailability([payloadInput], signal);
|
|
296
|
+
await importExecutionPayload.call(this, payloadInput, dataAvailabilityStatuses[0], opts);
|
|
297
|
+
}
|
|
@@ -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,18 +57,15 @@ 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
|
-
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, opts);
|
|
68
|
+
const {relevantBlocks, parentSlots, parentBlock} = verifyBlocksSanityChecks(this, blocks, payloadEnvelopes, opts);
|
|
66
69
|
|
|
67
70
|
// No relevant blocks, skip verifyBlocksInEpoch()
|
|
68
71
|
if (relevantBlocks.length === 0 || parentBlock === null) {
|
|
@@ -70,10 +73,31 @@ 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
|
-
const {
|
|
76
|
-
|
|
93
|
+
const {
|
|
94
|
+
postStates,
|
|
95
|
+
blockDAStatuses,
|
|
96
|
+
payloadDAStatuses,
|
|
97
|
+
proposerBalanceDeltas,
|
|
98
|
+
segmentExecStatus,
|
|
99
|
+
indexedAttestationsByBlock,
|
|
100
|
+
} = await verifyBlocksInEpoch.call(this, parentBlock, relevantBlocks, payloadEnvelopes, opts);
|
|
77
101
|
|
|
78
102
|
// If segmentExecStatus has lvhForkchoice then, the entire segment should be invalid
|
|
79
103
|
// and we need to further propagate
|
|
@@ -85,25 +109,49 @@ export async function processBlocks(
|
|
|
85
109
|
}
|
|
86
110
|
|
|
87
111
|
const {executionStatuses} = segmentExecStatus;
|
|
88
|
-
const
|
|
89
|
-
|
|
112
|
+
const verifiedBlocksBySlot = new Map<Slot, FullyVerifiedBlock>();
|
|
113
|
+
for (let i = 0; i < relevantBlocks.length; i++) {
|
|
114
|
+
const block = relevantBlocks[i];
|
|
115
|
+
verifiedBlocksBySlot.set(block.getBlock().message.slot, {
|
|
90
116
|
blockInput: block,
|
|
91
117
|
postState: postStates[i],
|
|
92
|
-
postPayloadState: null,
|
|
93
118
|
parentBlockSlot: parentSlots[i],
|
|
94
119
|
executionStatus: executionStatuses[i],
|
|
95
120
|
// start supporting optimistic syncing/processing
|
|
96
|
-
dataAvailabilityStatus:
|
|
121
|
+
dataAvailabilityStatus: blockDAStatuses[i],
|
|
97
122
|
proposerBalanceDelta: proposerBalanceDeltas[i],
|
|
98
123
|
indexedAttestations: indexedAttestationsByBlock[i],
|
|
99
124
|
// TODO: Make this param mandatory and capture in gossip
|
|
100
125
|
seenTimestampSec: opts.seenTimestampSec ?? Math.floor(Date.now() / 1000),
|
|
101
|
-
})
|
|
102
|
-
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const slotSet = new Set<Slot>(blocks.map((b) => b.getBlock().message.slot));
|
|
130
|
+
if (payloadEnvelopes) {
|
|
131
|
+
for (const slot of payloadEnvelopes.keys()) slotSet.add(slot);
|
|
132
|
+
}
|
|
133
|
+
const slots = Array.from(slotSet).sort((a, b) => a - b);
|
|
134
|
+
for (const slot of slots) {
|
|
135
|
+
const fullyVerifiedBlock = verifiedBlocksBySlot.get(slot);
|
|
136
|
+
if (fullyVerifiedBlock !== undefined) {
|
|
137
|
+
// TODO: Consider batching importBlock too if it takes significant time
|
|
138
|
+
await importBlock.call(this, fullyVerifiedBlock, opts);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const payloadInput = payloadEnvelopes?.get(slot);
|
|
142
|
+
if (payloadInput?.hasPayloadEnvelope()) {
|
|
143
|
+
if (!payloadInput.isComplete()) {
|
|
144
|
+
// we validated DA before reaching this
|
|
145
|
+
throw new Error(`Payload envelope for slot ${slot} not complete after DA verification`);
|
|
146
|
+
}
|
|
147
|
+
// we already awaited DA in verifyBlocksInEpoch for this segment
|
|
148
|
+
const payloadDA = payloadDAStatuses.get(slot);
|
|
149
|
+
if (payloadDA === undefined) {
|
|
150
|
+
throw new Error(`Missing payload DA status for slot ${slot}`);
|
|
151
|
+
}
|
|
152
|
+
await importExecutionPayload.call(this, payloadInput, payloadDA, {validSignature: false});
|
|
153
|
+
}
|
|
103
154
|
|
|
104
|
-
for (const fullyVerifiedBlock of fullyVerifiedBlocks) {
|
|
105
|
-
// TODO: Consider batching importBlock too if it takes significant time
|
|
106
|
-
await importBlock.call(this, fullyVerifiedBlock, opts);
|
|
107
155
|
await nextEventLoop();
|
|
108
156
|
}
|
|
109
157
|
} catch (e) {
|
|
@@ -4,7 +4,13 @@ import {toRootHex, withTimeout} from "@lodestar/utils";
|
|
|
4
4
|
import {VersionedHashes} from "../../../execution/index.js";
|
|
5
5
|
import {kzgCommitmentToVersionedHash} from "../../../util/blobs.js";
|
|
6
6
|
import {MissingColumnMeta} from "../blockInput/types.js";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
AddPayloadEnvelopeProps,
|
|
9
|
+
ColumnWithSource,
|
|
10
|
+
CreateFromBidProps,
|
|
11
|
+
CreateFromBlockProps,
|
|
12
|
+
SourceMeta,
|
|
13
|
+
} from "./types.js";
|
|
8
14
|
|
|
9
15
|
export type PayloadEnvelopeInputState =
|
|
10
16
|
| {
|
|
@@ -64,6 +70,7 @@ export class PayloadEnvelopeInput {
|
|
|
64
70
|
readonly proposerIndex: ValidatorIndex;
|
|
65
71
|
readonly bid: gloas.ExecutionPayloadBid;
|
|
66
72
|
readonly versionedHashes: VersionedHashes;
|
|
73
|
+
readonly daOutOfRange: boolean;
|
|
67
74
|
|
|
68
75
|
private columnsCache = new Map<ColumnIndex, ColumnWithSource>();
|
|
69
76
|
|
|
@@ -73,6 +80,7 @@ export class PayloadEnvelopeInput {
|
|
|
73
80
|
private timeCreatedSec: number;
|
|
74
81
|
|
|
75
82
|
private readonly payloadEnvelopeDataPromise: PromiseParts<gloas.SignedExecutionPayloadEnvelope>;
|
|
83
|
+
private readonly allDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
76
84
|
private readonly columnsDataPromise: PromiseParts<gloas.DataColumnSidecar[]>;
|
|
77
85
|
|
|
78
86
|
state: PayloadEnvelopeInputState;
|
|
@@ -86,6 +94,7 @@ export class PayloadEnvelopeInput {
|
|
|
86
94
|
sampledColumns: ColumnIndex[];
|
|
87
95
|
custodyColumns: ColumnIndex[];
|
|
88
96
|
timeCreatedSec: number;
|
|
97
|
+
daOutOfRange: boolean;
|
|
89
98
|
}) {
|
|
90
99
|
this.blockRootHex = props.blockRootHex;
|
|
91
100
|
this.slot = props.slot;
|
|
@@ -96,15 +105,18 @@ export class PayloadEnvelopeInput {
|
|
|
96
105
|
this.sampledColumns = props.sampledColumns;
|
|
97
106
|
this.custodyColumns = props.custodyColumns;
|
|
98
107
|
this.timeCreatedSec = props.timeCreatedSec;
|
|
108
|
+
this.daOutOfRange = props.daOutOfRange;
|
|
99
109
|
this.payloadEnvelopeDataPromise = createPromise();
|
|
110
|
+
this.allDataPromise = createPromise();
|
|
100
111
|
this.columnsDataPromise = createPromise();
|
|
101
112
|
|
|
102
113
|
const noBlobs = props.bid.blobKzgCommitments.length === 0;
|
|
103
114
|
const noSampledColumns = props.sampledColumns.length === 0;
|
|
104
|
-
const hasAllData = noBlobs || noSampledColumns;
|
|
115
|
+
const hasAllData = props.daOutOfRange || noBlobs || noSampledColumns;
|
|
105
116
|
|
|
106
117
|
if (hasAllData) {
|
|
107
118
|
this.state = {hasPayload: false, hasAllData: true, hasComputedAllData: true};
|
|
119
|
+
this.allDataPromise.resolve(this.getSampledColumns());
|
|
108
120
|
this.columnsDataPromise.resolve(this.getSampledColumns());
|
|
109
121
|
} else {
|
|
110
122
|
this.state = {hasPayload: false, hasAllData: false, hasComputedAllData: false};
|
|
@@ -122,6 +134,27 @@ export class PayloadEnvelopeInput {
|
|
|
122
134
|
sampledColumns: props.sampledColumns,
|
|
123
135
|
custodyColumns: props.custodyColumns,
|
|
124
136
|
timeCreatedSec: props.timeCreatedSec,
|
|
137
|
+
daOutOfRange: props.daOutOfRange,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Create a `PayloadEnvelopeInput` from a state's `latestExecutionPayloadBid` (the bid
|
|
143
|
+
* recorded in beacon state for the latest imported block). Used when seeding the cache
|
|
144
|
+
* for a checkpoint anchor block — we have the bid via state but not the full
|
|
145
|
+
* SignedBeaconBlock body.
|
|
146
|
+
*/
|
|
147
|
+
static createFromBid(props: CreateFromBidProps): PayloadEnvelopeInput {
|
|
148
|
+
return new PayloadEnvelopeInput({
|
|
149
|
+
blockRootHex: props.blockRootHex,
|
|
150
|
+
slot: props.slot,
|
|
151
|
+
forkName: props.forkName,
|
|
152
|
+
proposerIndex: props.proposerIndex,
|
|
153
|
+
bid: props.bid,
|
|
154
|
+
sampledColumns: props.sampledColumns,
|
|
155
|
+
custodyColumns: props.custodyColumns,
|
|
156
|
+
timeCreatedSec: props.timeCreatedSec,
|
|
157
|
+
daOutOfRange: props.daOutOfRange,
|
|
125
158
|
});
|
|
126
159
|
}
|
|
127
160
|
|
|
@@ -149,6 +182,7 @@ export class PayloadEnvelopeInput {
|
|
|
149
182
|
throw new Error("Payload envelope beacon_block_root mismatch");
|
|
150
183
|
}
|
|
151
184
|
|
|
185
|
+
// TODO GLOAS: track source by metrics, maybe inside the seen cache
|
|
152
186
|
const source: SourceMeta = {
|
|
153
187
|
source: props.source,
|
|
154
188
|
seenTimestampSec: props.seenTimestampSec,
|
|
@@ -203,6 +237,12 @@ export class PayloadEnvelopeInput {
|
|
|
203
237
|
return true;
|
|
204
238
|
}
|
|
205
239
|
|
|
240
|
+
// Resolve allDataPromise on the first transition to hasAllData (either sampled-complete or
|
|
241
|
+
// reconstruction-threshold branch). Guarded so it fires exactly once.
|
|
242
|
+
if (!this.state.hasAllData && hasAllData) {
|
|
243
|
+
this.allDataPromise.resolve(sampledColumns);
|
|
244
|
+
}
|
|
245
|
+
|
|
206
246
|
if (hasComputedAllData) {
|
|
207
247
|
this.columnsDataPromise.resolve(sampledColumns);
|
|
208
248
|
}
|
|
@@ -297,8 +337,11 @@ export class PayloadEnvelopeInput {
|
|
|
297
337
|
return this.state.hasAllData;
|
|
298
338
|
}
|
|
299
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Strictly checks missing sampled columns. Does NOT short-circuit on `state.hasAllData`.
|
|
342
|
+
*/
|
|
300
343
|
getMissingSampledColumnMeta(): MissingColumnMeta {
|
|
301
|
-
if (this.state.
|
|
344
|
+
if (this.state.hasComputedAllData) {
|
|
302
345
|
return {missing: [], versionedHashes: this.versionedHashes};
|
|
303
346
|
}
|
|
304
347
|
|
|
@@ -315,6 +358,24 @@ export class PayloadEnvelopeInput {
|
|
|
315
358
|
return this.state.hasComputedAllData;
|
|
316
359
|
}
|
|
317
360
|
|
|
361
|
+
waitForAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
362
|
+
if (this.state.hasAllData) {
|
|
363
|
+
return Promise.resolve(this.getSampledColumns());
|
|
364
|
+
}
|
|
365
|
+
return withTimeout(() => this.allDataPromise.promise, timeout, signal);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
async waitForEnvelopeAndAllData(timeout: number, signal?: AbortSignal): Promise<this> {
|
|
369
|
+
if (!this.state.hasPayload || !this.state.hasAllData) {
|
|
370
|
+
await withTimeout(
|
|
371
|
+
() => Promise.all([this.payloadEnvelopeDataPromise.promise, this.allDataPromise.promise]),
|
|
372
|
+
timeout,
|
|
373
|
+
signal
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
return this;
|
|
377
|
+
}
|
|
378
|
+
|
|
318
379
|
waitForComputedAllData(timeout: number, signal?: AbortSignal): Promise<gloas.DataColumnSidecar[]> {
|
|
319
380
|
if (this.state.hasComputedAllData) {
|
|
320
381
|
return Promise.resolve(this.getSampledColumns());
|