@lodestar/beacon-node 1.43.0-dev.aef3645690 → 1.43.0-dev.b05ea98d04
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 -5
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/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 +38 -58
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +28 -14
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +89 -89
- 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 +59 -26
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +7 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +29 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +1 -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 +16 -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 +89 -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 +79 -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 +46 -50
- 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/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 +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 -15
- 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/opPools/payloadAttestationPool.d.ts +3 -2
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +26 -4
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +47 -23
- 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 +13 -8
- 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/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 +9 -44
- 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 +8 -38
- 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 +22 -6
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +53 -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/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 +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 +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 +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 +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 +32 -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/interface.d.ts +1 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/network.d.ts +1 -0
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +6 -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 +60 -22
- 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/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 +6 -4
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/constants.d.ts +3 -1
- package/lib/sync/constants.d.ts.map +1 -1
- package/lib/sync/constants.js +3 -4
- package/lib/sync/constants.js.map +1 -1
- package/lib/sync/range/batch.d.ts +28 -2
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +146 -44
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +12 -2
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +53 -9
- 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 +22 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +604 -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 +162 -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 +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/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 -16
- 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 +84 -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/blockInput/blockInput.ts +4 -1
- package/src/chain/blocks/importBlock.ts +38 -83
- package/src/chain/blocks/importExecutionPayload.ts +110 -102
- package/src/chain/blocks/index.ts +74 -24
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +37 -2
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +1 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
- package/src/chain/blocks/types.ts +16 -26
- package/src/chain/blocks/utils/chainSegment.ts +114 -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 +134 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +41 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
- package/src/chain/chain.ts +63 -72
- package/src/chain/emitter.ts +15 -14
- 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 +47 -0
- package/src/chain/forkChoice/index.ts +8 -20
- package/src/chain/initState.ts +9 -1
- package/src/chain/interface.ts +11 -3
- package/src/chain/opPools/payloadAttestationPool.ts +29 -8
- package/src/chain/prepareNextSlot.ts +55 -24
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +91 -27
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +7 -12
- package/src/chain/regen/queued.ts +14 -55
- package/src/chain/regen/regen.ts +10 -43
- package/src/chain/seenCache/index.ts +1 -0
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +71 -20
- package/src/chain/seenCache/seenProposerPreferences.ts +32 -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 +25 -8
- package/src/chain/validation/executionPayloadEnvelope.ts +22 -12
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- 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 +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/interface.ts +1 -0
- package/src/network/network.ts +12 -1
- package/src/network/processor/gossipHandlers.ts +79 -27
- package/src/network/processor/gossipQueues/index.ts +5 -0
- package/src/network/processor/index.ts +6 -5
- 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 +6 -4
- package/src/sync/constants.ts +4 -4
- package/src/sync/range/batch.ts +204 -49
- package/src/sync/range/chain.ts +69 -11
- package/src/sync/range/range.ts +18 -6
- package/src/sync/types.ts +72 -0
- package/src/sync/unknownBlock.ts +762 -57
- package/src/sync/utils/downloadByRange.ts +272 -39
- package/src/sync/utils/downloadByRoot.ts +24 -2
- package/src/sync/utils/pendingBlocksTree.ts +0 -15
- package/src/util/sszBytes.ts +25 -5
package/src/sync/range/batch.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
-
import {ForkName, isForkPostDeneb, isForkPostFulu} from "@lodestar/params";
|
|
2
|
+
import {ForkName, isForkPostDeneb, isForkPostFulu, isForkPostGloas} from "@lodestar/params";
|
|
3
3
|
import {Epoch, RootHex, Slot, phase0} from "@lodestar/types";
|
|
4
|
-
import {LodestarError} from "@lodestar/utils";
|
|
4
|
+
import {LodestarError, prettyPrintIndices} from "@lodestar/utils";
|
|
5
5
|
import {isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
6
6
|
import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
7
7
|
import {isDaOutOfRange} from "../../chain/blocks/blockInput/utils.js";
|
|
8
|
+
import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
8
9
|
import {BlockError, BlockErrorCode} from "../../chain/errors/index.js";
|
|
9
10
|
import {PeerSyncMeta} from "../../network/peers/peersData.js";
|
|
10
11
|
import {IClock} from "../../util/clock.js";
|
|
@@ -46,25 +47,68 @@ export type Attempt = {
|
|
|
46
47
|
export type AwaitingDownloadState = {
|
|
47
48
|
status: BatchStatus.AwaitingDownload;
|
|
48
49
|
blocks: IBlockInput[];
|
|
50
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
49
51
|
};
|
|
50
52
|
|
|
51
53
|
export type DownloadSuccessState = {
|
|
52
54
|
status: BatchStatus.AwaitingProcessing;
|
|
53
55
|
blocks: IBlockInput[];
|
|
56
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
54
57
|
};
|
|
55
58
|
|
|
56
59
|
export type BatchState =
|
|
57
60
|
| AwaitingDownloadState
|
|
58
|
-
| {
|
|
61
|
+
| {
|
|
62
|
+
status: BatchStatus.Downloading;
|
|
63
|
+
peer: PeerIdStr;
|
|
64
|
+
blocks: IBlockInput[];
|
|
65
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
66
|
+
}
|
|
59
67
|
| DownloadSuccessState
|
|
60
|
-
| {
|
|
61
|
-
|
|
68
|
+
| {
|
|
69
|
+
status: BatchStatus.Processing;
|
|
70
|
+
blocks: IBlockInput[];
|
|
71
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
72
|
+
attempt: Attempt;
|
|
73
|
+
}
|
|
74
|
+
| {
|
|
75
|
+
status: BatchStatus.AwaitingValidation;
|
|
76
|
+
blocks: IBlockInput[];
|
|
77
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
78
|
+
attempt: Attempt;
|
|
79
|
+
};
|
|
62
80
|
|
|
63
81
|
export type BatchMetadata = {
|
|
82
|
+
// Batch-level slot window (always present)
|
|
64
83
|
startEpoch: Epoch;
|
|
84
|
+
startSlot: Slot;
|
|
85
|
+
count: number;
|
|
65
86
|
status: BatchStatus;
|
|
87
|
+
|
|
88
|
+
// Per-type outstanding request shapes; only present when that sub-request exists.
|
|
89
|
+
// Format: "startSlot=<n>,count=<n>" (plus ",cols=<indices>" for columns).
|
|
90
|
+
blocksReq?: string;
|
|
91
|
+
blobsReq?: string;
|
|
92
|
+
columnsReq?: string;
|
|
93
|
+
envelopesReq?: string;
|
|
94
|
+
|
|
95
|
+
// Retry counters
|
|
96
|
+
downloadAttempts: number;
|
|
97
|
+
processingAttempts: number;
|
|
98
|
+
|
|
99
|
+
// Cumulative peer attribution for failed attempts (only present when non-empty)
|
|
100
|
+
failedDownloadPeers?: string;
|
|
101
|
+
failedProcessingPeers?: string;
|
|
66
102
|
};
|
|
67
103
|
|
|
104
|
+
function formatRangeReq(req: {startSlot: Slot; count: number}): string {
|
|
105
|
+
return `startSlot=${req.startSlot},count=${req.count}`;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function formatColumnsReq(req: {startSlot: Slot; count: number; columns: number[]}): string {
|
|
109
|
+
return `startSlot=${req.startSlot},count=${req.count},cols=${prettyPrintIndices(req.columns)}`;
|
|
110
|
+
}
|
|
111
|
+
|
|
68
112
|
/**
|
|
69
113
|
* Batches are downloaded at the first block of the epoch.
|
|
70
114
|
*
|
|
@@ -85,7 +129,7 @@ export class Batch {
|
|
|
85
129
|
/** Block, blob and column requests that are used to determine the best peer and are used in downloadByRange */
|
|
86
130
|
requests: DownloadByRangeRequests;
|
|
87
131
|
/** State of the batch. */
|
|
88
|
-
state: BatchState = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
132
|
+
state: BatchState = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
89
133
|
/** Peers that provided good data */
|
|
90
134
|
goodPeers: PeerIdStr[] = [];
|
|
91
135
|
/** The `Attempts` that have been made and failed to send us this batch. */
|
|
@@ -129,37 +173,36 @@ export class Batch {
|
|
|
129
173
|
count: this.count,
|
|
130
174
|
step: 1,
|
|
131
175
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
count: this.count,
|
|
138
|
-
columns: this.custodyConfig.sampledColumns,
|
|
139
|
-
},
|
|
140
|
-
};
|
|
176
|
+
const requests: DownloadByRangeRequests = {blocksRequest};
|
|
177
|
+
|
|
178
|
+
// Post-Gloas envelopes are required for block processing, independent of DA retention window.
|
|
179
|
+
if (isForkPostGloas(this.forkName)) {
|
|
180
|
+
requests.envelopesRequest = {startSlot: this.startSlot, count: this.count};
|
|
141
181
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
},
|
|
182
|
+
|
|
183
|
+
if (isForkPostFulu(this.forkName) && withinValidRequestWindow) {
|
|
184
|
+
requests.columnsRequest = {
|
|
185
|
+
startSlot: this.startSlot,
|
|
186
|
+
count: this.count,
|
|
187
|
+
columns: this.custodyConfig.sampledColumns,
|
|
149
188
|
};
|
|
189
|
+
} else if (isForkPostDeneb(this.forkName) && withinValidRequestWindow) {
|
|
190
|
+
requests.blobsRequest = {startSlot: this.startSlot, count: this.count};
|
|
150
191
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
};
|
|
192
|
+
|
|
193
|
+
return requests;
|
|
154
194
|
}
|
|
155
195
|
|
|
156
196
|
// subsequent request where part of the epoch has already been downloaded. Need to figure out what is the beginning
|
|
157
197
|
// of the range where download needs to resume
|
|
158
198
|
let blockStartSlot = this.startSlot;
|
|
159
199
|
let dataStartSlot = this.startSlot;
|
|
200
|
+
let envelopeStartSlot = this.startSlot;
|
|
160
201
|
const neededColumns = new Set<number>();
|
|
202
|
+
const envelopesBySlot = this.state.payloadEnvelopes ?? new Map<Slot, PayloadEnvelopeInput>();
|
|
161
203
|
|
|
162
204
|
// ensure blocks are in slot-wise order
|
|
205
|
+
const isPostGloas = isForkPostGloas(this.forkName);
|
|
163
206
|
for (const blockInput of blocks) {
|
|
164
207
|
const blockSlot = blockInput.slot;
|
|
165
208
|
// check if block/data is present (hasBlock/hasAllData). If present then check if startSlot is the same as
|
|
@@ -175,14 +218,36 @@ export class Batch {
|
|
|
175
218
|
if (blockInput.hasBlock() && blockStartSlot === blockSlot) {
|
|
176
219
|
blockStartSlot = blockSlot + 1;
|
|
177
220
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
221
|
+
|
|
222
|
+
// Range sync uses hasComputedAllData (all sampled columns physically present), not hasAllData
|
|
223
|
+
// which flips at the reconstruction threshold. Sync never triggers reconstruction, so accepting
|
|
224
|
+
// a half-downloaded block here makes writeBlockInputToDb later block on waitForComputedAllData.
|
|
225
|
+
if (isPostGloas) {
|
|
226
|
+
// Post-Gloas: column data lives on PayloadEnvelopeInput, not on BlockInputNoData.
|
|
227
|
+
const payloadInput = envelopesBySlot.get(blockSlot);
|
|
228
|
+
if (blockInput.hasBlock() && envelopeStartSlot === blockSlot && payloadInput?.hasPayloadEnvelope()) {
|
|
229
|
+
envelopeStartSlot = blockSlot + 1;
|
|
230
|
+
}
|
|
231
|
+
if (payloadInput && !payloadInput.hasComputedAllData()) {
|
|
232
|
+
for (const index of payloadInput.getMissingSampledColumnMeta().missing) {
|
|
181
233
|
neededColumns.add(index);
|
|
182
234
|
}
|
|
235
|
+
} else if (payloadInput?.hasComputedAllData() && dataStartSlot === blockSlot) {
|
|
236
|
+
// Only advance dataStartSlot when we know columns for this slot are complete. If
|
|
237
|
+
// payloadInput is missing entirely we cannot tell, so stop here so the next round
|
|
238
|
+
// re-requests columns (and envelopes) starting at this slot.
|
|
239
|
+
dataStartSlot = blockSlot + 1;
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
if (isBlockInputColumns(blockInput) ? !blockInput.hasComputedAllData() : !blockInput.hasAllData()) {
|
|
243
|
+
if (isBlockInputColumns(blockInput)) {
|
|
244
|
+
for (const index of blockInput.getMissingSampledColumnMeta().missing) {
|
|
245
|
+
neededColumns.add(index);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
} else if (dataStartSlot === blockSlot) {
|
|
249
|
+
dataStartSlot = blockSlot + 1;
|
|
183
250
|
}
|
|
184
|
-
} else if (dataStartSlot === blockSlot) {
|
|
185
|
-
dataStartSlot = blockSlot + 1;
|
|
186
251
|
}
|
|
187
252
|
}
|
|
188
253
|
|
|
@@ -202,11 +267,15 @@ export class Batch {
|
|
|
202
267
|
// range of 40 - 63, startSlot will be inclusive but subtraction will exclusive so need to + 1
|
|
203
268
|
const count = endSlot - dataStartSlot + 1;
|
|
204
269
|
if (isForkPostFulu(this.forkName) && withinValidRequestWindow) {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
270
|
+
// Skip the column re-request when we have no specific column indices outstanding.
|
|
271
|
+
// Peer rejects an empty `columns` list
|
|
272
|
+
if (neededColumns.size > 0) {
|
|
273
|
+
requests.columnsRequest = {
|
|
274
|
+
count,
|
|
275
|
+
startSlot: dataStartSlot,
|
|
276
|
+
columns: Array.from(neededColumns),
|
|
277
|
+
};
|
|
278
|
+
}
|
|
210
279
|
} else if (isForkPostDeneb(this.forkName) && withinValidRequestWindow) {
|
|
211
280
|
requests.blobsRequest = {
|
|
212
281
|
count,
|
|
@@ -216,6 +285,13 @@ export class Batch {
|
|
|
216
285
|
// dataSlot will still have a value but do not create a request for preDeneb forks
|
|
217
286
|
}
|
|
218
287
|
|
|
288
|
+
if (isForkPostGloas(this.forkName) && envelopeStartSlot <= endSlot) {
|
|
289
|
+
requests.envelopesRequest = {
|
|
290
|
+
startSlot: envelopeStartSlot,
|
|
291
|
+
count: endSlot - envelopeStartSlot + 1,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
219
295
|
return requests;
|
|
220
296
|
}
|
|
221
297
|
|
|
@@ -256,13 +332,36 @@ export class Batch {
|
|
|
256
332
|
}
|
|
257
333
|
|
|
258
334
|
getMetadata(): BatchMetadata {
|
|
259
|
-
|
|
335
|
+
const {blocksRequest, blobsRequest, columnsRequest, envelopesRequest} = this.requests;
|
|
336
|
+
const failedProcessingPeerList = this.failedProcessingAttempts.flatMap((a) => a.peers);
|
|
337
|
+
return {
|
|
338
|
+
startEpoch: this.startEpoch,
|
|
339
|
+
startSlot: this.startSlot,
|
|
340
|
+
count: this.count,
|
|
341
|
+
status: this.state.status,
|
|
342
|
+
...(blocksRequest && {blocksReq: formatRangeReq(blocksRequest)}),
|
|
343
|
+
...(blobsRequest && {blobsReq: formatRangeReq(blobsRequest)}),
|
|
344
|
+
...(columnsRequest && {columnsReq: formatColumnsReq(columnsRequest)}),
|
|
345
|
+
...(envelopesRequest && {envelopesReq: formatRangeReq(envelopesRequest)}),
|
|
346
|
+
downloadAttempts: this.failedDownloadAttempts.length,
|
|
347
|
+
processingAttempts: this.failedProcessingAttempts.length,
|
|
348
|
+
...(this.failedDownloadAttempts.length > 0 && {
|
|
349
|
+
failedDownloadPeers: this.failedDownloadAttempts.join(","),
|
|
350
|
+
}),
|
|
351
|
+
...(failedProcessingPeerList.length > 0 && {
|
|
352
|
+
failedProcessingPeers: failedProcessingPeerList.join(","),
|
|
353
|
+
}),
|
|
354
|
+
};
|
|
260
355
|
}
|
|
261
356
|
|
|
262
357
|
getBlocks(): IBlockInput[] {
|
|
263
358
|
return this.state.blocks;
|
|
264
359
|
}
|
|
265
360
|
|
|
361
|
+
getPayloadEnvelopes(): Map<Slot, PayloadEnvelopeInput> | null {
|
|
362
|
+
return this.state.payloadEnvelopes;
|
|
363
|
+
}
|
|
364
|
+
|
|
266
365
|
/**
|
|
267
366
|
* AwaitingDownload -> Downloading
|
|
268
367
|
*/
|
|
@@ -271,13 +370,22 @@ export class Batch {
|
|
|
271
370
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingDownload));
|
|
272
371
|
}
|
|
273
372
|
|
|
274
|
-
this.state = {
|
|
373
|
+
this.state = {
|
|
374
|
+
status: BatchStatus.Downloading,
|
|
375
|
+
peer,
|
|
376
|
+
blocks: this.state.blocks,
|
|
377
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
378
|
+
};
|
|
275
379
|
}
|
|
276
380
|
|
|
277
381
|
/**
|
|
278
382
|
* Downloading -> AwaitingProcessing
|
|
279
383
|
*/
|
|
280
|
-
downloadingSuccess(
|
|
384
|
+
downloadingSuccess(
|
|
385
|
+
peer: PeerIdStr,
|
|
386
|
+
blocks: IBlockInput[],
|
|
387
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null
|
|
388
|
+
): DownloadSuccessState {
|
|
281
389
|
if (this.state.status !== BatchStatus.Downloading) {
|
|
282
390
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Downloading));
|
|
283
391
|
}
|
|
@@ -291,7 +399,11 @@ export class Batch {
|
|
|
291
399
|
const slots = new Set<number>();
|
|
292
400
|
for (const block of blocks) {
|
|
293
401
|
slots.add(block.slot);
|
|
294
|
-
|
|
402
|
+
const dataComplete = isBlockInputColumns(block)
|
|
403
|
+
? // by_range needs to download all columns
|
|
404
|
+
block.hasBlock() && block.hasComputedAllData()
|
|
405
|
+
: block.hasBlockAndAllData();
|
|
406
|
+
if (!dataComplete) {
|
|
295
407
|
allComplete = false;
|
|
296
408
|
}
|
|
297
409
|
}
|
|
@@ -305,11 +417,24 @@ export class Batch {
|
|
|
305
417
|
status: this.state.status,
|
|
306
418
|
});
|
|
307
419
|
}
|
|
420
|
+
const newPayloadEnvelopes = payloadEnvelopes ?? this.state.payloadEnvelopes;
|
|
421
|
+
|
|
422
|
+
if (allComplete && isForkPostGloas(this.forkName)) {
|
|
423
|
+
for (const block of blocks) {
|
|
424
|
+
const payloadInput = newPayloadEnvelopes?.get(block.slot);
|
|
425
|
+
// by_range needs to download all columns
|
|
426
|
+
if (!payloadInput?.hasPayloadEnvelope() || !payloadInput.hasComputedAllData()) {
|
|
427
|
+
allComplete = false;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
308
433
|
if (allComplete) {
|
|
309
|
-
this.state = {status: BatchStatus.AwaitingProcessing, blocks};
|
|
434
|
+
this.state = {status: BatchStatus.AwaitingProcessing, blocks, payloadEnvelopes: newPayloadEnvelopes};
|
|
310
435
|
} else {
|
|
436
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks, payloadEnvelopes: newPayloadEnvelopes};
|
|
311
437
|
this.requests = this.getRequests(blocks);
|
|
312
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks};
|
|
313
438
|
}
|
|
314
439
|
|
|
315
440
|
return this.state as DownloadSuccessState;
|
|
@@ -328,25 +453,50 @@ export class Batch {
|
|
|
328
453
|
throw new BatchError(this.errorType({code: BatchErrorCode.MAX_DOWNLOAD_ATTEMPTS}));
|
|
329
454
|
}
|
|
330
455
|
|
|
331
|
-
this.state = {
|
|
456
|
+
this.state = {
|
|
457
|
+
status: BatchStatus.AwaitingDownload,
|
|
458
|
+
blocks: this.state.blocks,
|
|
459
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* Downloading -> AwaitingDownload (without counting as a failed attempt).
|
|
465
|
+
* Used when the peer rate-limited us — the request was never actually served.
|
|
466
|
+
*/
|
|
467
|
+
downloadingRateLimited(): void {
|
|
468
|
+
if (this.state.status !== BatchStatus.Downloading) {
|
|
469
|
+
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Downloading));
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
this.state = {
|
|
473
|
+
status: BatchStatus.AwaitingDownload,
|
|
474
|
+
blocks: this.state.blocks,
|
|
475
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
476
|
+
};
|
|
332
477
|
}
|
|
333
478
|
|
|
334
479
|
/**
|
|
335
480
|
* AwaitingProcessing -> Processing
|
|
336
481
|
*/
|
|
337
|
-
startProcessing():
|
|
482
|
+
startProcessing(): {
|
|
483
|
+
blocks: IBlockInput[];
|
|
484
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null;
|
|
485
|
+
peers: PeerIdStr[];
|
|
486
|
+
} {
|
|
338
487
|
if (this.state.status !== BatchStatus.AwaitingProcessing) {
|
|
339
488
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingProcessing));
|
|
340
489
|
}
|
|
341
490
|
|
|
342
491
|
const blocks = this.state.blocks;
|
|
492
|
+
const payloadEnvelopes = this.state.payloadEnvelopes;
|
|
343
493
|
const hash = hashBlocks(blocks, this.config); // tracks blocks to report peer on processing error
|
|
344
494
|
// Reset goodPeers in case another download attempt needs to be made. When Attempt is successful or not the peers
|
|
345
495
|
// that the data came from will be handled by the Attempt that goes for processing
|
|
346
496
|
const peers = this.goodPeers;
|
|
347
497
|
this.goodPeers = [];
|
|
348
|
-
this.state = {status: BatchStatus.Processing, blocks, attempt: {peers, hash}};
|
|
349
|
-
return blocks;
|
|
498
|
+
this.state = {status: BatchStatus.Processing, blocks, payloadEnvelopes, attempt: {peers, hash}};
|
|
499
|
+
return {blocks, payloadEnvelopes, peers};
|
|
350
500
|
}
|
|
351
501
|
|
|
352
502
|
/**
|
|
@@ -357,7 +507,12 @@ export class Batch {
|
|
|
357
507
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Processing));
|
|
358
508
|
}
|
|
359
509
|
|
|
360
|
-
this.state = {
|
|
510
|
+
this.state = {
|
|
511
|
+
status: BatchStatus.AwaitingValidation,
|
|
512
|
+
blocks: this.state.blocks,
|
|
513
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
514
|
+
attempt: this.state.attempt,
|
|
515
|
+
};
|
|
361
516
|
}
|
|
362
517
|
|
|
363
518
|
/**
|
|
@@ -408,7 +563,7 @@ export class Batch {
|
|
|
408
563
|
|
|
409
564
|
// remove any downloaded blocks and re-attempt
|
|
410
565
|
// TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
|
|
411
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
566
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
412
567
|
}
|
|
413
568
|
|
|
414
569
|
private onProcessingError(attempt: Attempt): void {
|
|
@@ -419,12 +574,12 @@ export class Batch {
|
|
|
419
574
|
|
|
420
575
|
// remove any downloaded blocks and re-attempt
|
|
421
576
|
// TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
|
|
422
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
577
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
423
578
|
}
|
|
424
579
|
|
|
425
580
|
/** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */
|
|
426
581
|
private errorType(type: BatchErrorType): BatchErrorType & BatchErrorMetadata {
|
|
427
|
-
return {...type,
|
|
582
|
+
return {...type, startEpoch: this.startEpoch, status: this.state.status};
|
|
428
583
|
}
|
|
429
584
|
|
|
430
585
|
private wrongStatusErrorType(expectedStatus: BatchStatus): BatchErrorType & BatchErrorMetadata {
|
package/src/sync/range/chain.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import {ChainForkConfig} from "@lodestar/config";
|
|
2
|
+
import {RequestErrorCode} from "@lodestar/reqresp";
|
|
2
3
|
import {Epoch, Root, Slot} from "@lodestar/types";
|
|
3
|
-
import {ErrorAborted, LodestarError, Logger, toRootHex} from "@lodestar/utils";
|
|
4
|
+
import {ErrorAborted, LodestarError, Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
4
5
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
5
6
|
import {BlockInputErrorCode} from "../../chain/blocks/blockInput/errors.js";
|
|
6
7
|
import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
8
|
+
import {PayloadEnvelopeInput} from "../../chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js";
|
|
7
9
|
import {BlobSidecarErrorCode} from "../../chain/errors/blobSidecarError.js";
|
|
8
10
|
import {DataColumnSidecarErrorCode} from "../../chain/errors/dataColumnSidecarError.js";
|
|
9
11
|
import {Metrics} from "../../metrics/metrics.js";
|
|
@@ -14,7 +16,12 @@ import {CustodyConfig} from "../../util/dataColumns.js";
|
|
|
14
16
|
import {ItTrigger} from "../../util/itTrigger.js";
|
|
15
17
|
import {PeerIdStr} from "../../util/peerId.js";
|
|
16
18
|
import {WarnResult, wrapError} from "../../util/wrapError.js";
|
|
17
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
BATCH_BUFFER_SIZE,
|
|
21
|
+
EPOCHS_PER_BATCH,
|
|
22
|
+
MAX_LOOK_AHEAD_EPOCHS,
|
|
23
|
+
RATE_LIMITED_PEER_BACKOFF_MS,
|
|
24
|
+
} from "../constants.js";
|
|
18
25
|
import {DownloadByRangeError, DownloadByRangeErrorCode} from "../utils/downloadByRange.js";
|
|
19
26
|
import {RangeSyncType} from "../utils/remoteSyncType.js";
|
|
20
27
|
import {Batch, BatchError, BatchErrorCode, BatchMetadata, BatchStatus} from "./batch.js";
|
|
@@ -44,13 +51,19 @@ export type SyncChainFns = {
|
|
|
44
51
|
* Must return if ALL blocks are processed successfully
|
|
45
52
|
* If SOME blocks are processed must throw BlockProcessorError()
|
|
46
53
|
*/
|
|
47
|
-
processChainSegment: (
|
|
54
|
+
processChainSegment: (
|
|
55
|
+
blocks: IBlockInput[],
|
|
56
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null,
|
|
57
|
+
syncType: RangeSyncType
|
|
58
|
+
) => Promise<void>;
|
|
48
59
|
/** Must download blocks, and validate their range */
|
|
49
60
|
downloadByRange: (
|
|
50
61
|
peer: PeerSyncMeta,
|
|
51
62
|
batch: Batch,
|
|
52
63
|
syncType: RangeSyncType
|
|
53
|
-
) => Promise<
|
|
64
|
+
) => Promise<
|
|
65
|
+
WarnResult<{blocks: IBlockInput[]; payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null}, DownloadByRangeError>
|
|
66
|
+
>;
|
|
54
67
|
/** Report peer for negative actions. Decouples from the full network instance */
|
|
55
68
|
reportPeer: (peer: PeerIdStr, action: PeerAction, actionName: string) => void;
|
|
56
69
|
/** Gets current peer custodyColumns and earliestAvailableSlot */
|
|
@@ -133,6 +146,12 @@ export class SyncChain {
|
|
|
133
146
|
/** Sorted map of batches undergoing some kind of processing. */
|
|
134
147
|
private readonly batches = new Map<Epoch, Batch>();
|
|
135
148
|
private readonly peerset = new Map<PeerIdStr, ChainTarget>();
|
|
149
|
+
/**
|
|
150
|
+
* Tracks peers that have rate-limited us, mapped to the timestamp (ms) until which we should avoid them.
|
|
151
|
+
* This is a sync-layer optimization to avoid assigning batches to backed-off peers.
|
|
152
|
+
* The reqresp SelfRateLimiter independently enforces backoff at the protocol level as a safety net.
|
|
153
|
+
*/
|
|
154
|
+
private readonly rateLimitedPeers = new Map<PeerIdStr, number>();
|
|
136
155
|
|
|
137
156
|
private readonly logger: Logger;
|
|
138
157
|
private readonly config: ChainForkConfig;
|
|
@@ -215,12 +234,14 @@ export class SyncChain {
|
|
|
215
234
|
*/
|
|
216
235
|
stopSyncing(): void {
|
|
217
236
|
this.status = SyncChainStatus.Stopped;
|
|
237
|
+
this.logger.debug("SyncChain stopSyncing", {id: this.logId});
|
|
218
238
|
}
|
|
219
239
|
|
|
220
240
|
/**
|
|
221
241
|
* Permanently remove this chain. Throws the main AsyncIterable
|
|
222
242
|
*/
|
|
223
243
|
remove(): void {
|
|
244
|
+
this.logger.debug("SyncChain remove", {id: this.logId});
|
|
224
245
|
this.batchProcessor.end(new ErrorAborted("SyncChain"));
|
|
225
246
|
}
|
|
226
247
|
|
|
@@ -239,6 +260,7 @@ export class SyncChain {
|
|
|
239
260
|
*/
|
|
240
261
|
removePeer(peerId: PeerIdStr): boolean {
|
|
241
262
|
const deleted = this.peerset.delete(peerId);
|
|
263
|
+
this.rateLimitedPeers.delete(peerId);
|
|
242
264
|
this.computeTarget();
|
|
243
265
|
return deleted;
|
|
244
266
|
}
|
|
@@ -374,8 +396,18 @@ export class SyncChain {
|
|
|
374
396
|
return;
|
|
375
397
|
}
|
|
376
398
|
|
|
399
|
+
const now = Date.now();
|
|
377
400
|
const peersSyncInfo: PeerSyncInfo[] = [];
|
|
378
401
|
for (const [peerId, target] of this.peerset.entries()) {
|
|
402
|
+
// Skip peers that are currently in rate-limit backoff
|
|
403
|
+
const rateLimitedUntil = this.rateLimitedPeers.get(peerId);
|
|
404
|
+
if (rateLimitedUntil !== undefined) {
|
|
405
|
+
if (now < rateLimitedUntil) {
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
this.rateLimitedPeers.delete(peerId);
|
|
409
|
+
}
|
|
410
|
+
|
|
379
411
|
try {
|
|
380
412
|
peersSyncInfo.push({...this.getConnectedPeerSyncMeta(peerId), target});
|
|
381
413
|
} catch (e) {
|
|
@@ -507,7 +539,14 @@ export class SyncChain {
|
|
|
507
539
|
{id: this.logId, ...batch.getMetadata(), peer: prettyPrintPeerIdStr(peer.peerId)},
|
|
508
540
|
res.err
|
|
509
541
|
);
|
|
510
|
-
|
|
542
|
+
if (errCode === RequestErrorCode.RESP_RATE_LIMITED || errCode === RequestErrorCode.REQUEST_SELF_RATE_LIMITED) {
|
|
543
|
+
// Peer rate-limited us — don't count as a failed download attempt and mark peer for backoff
|
|
544
|
+
this.rateLimitedPeers.set(peer.peerId, Date.now() + RATE_LIMITED_PEER_BACKOFF_MS);
|
|
545
|
+
batch.downloadingRateLimited();
|
|
546
|
+
this.triggerBatchDownloader();
|
|
547
|
+
} else {
|
|
548
|
+
batch.downloadingError(peer.peerId); // Throws after MAX_DOWNLOAD_ATTEMPTS
|
|
549
|
+
}
|
|
511
550
|
} else {
|
|
512
551
|
this.logger.verbose("Batch download success", {
|
|
513
552
|
id: this.logId,
|
|
@@ -516,7 +555,8 @@ export class SyncChain {
|
|
|
516
555
|
});
|
|
517
556
|
this.metrics?.syncRange.downloadByRange.success.inc();
|
|
518
557
|
const {warnings, result} = res.result;
|
|
519
|
-
const
|
|
558
|
+
const {blocks: downloadedBlocks, payloadEnvelopes} = result;
|
|
559
|
+
const downloadSuccessOutput = batch.downloadingSuccess(peer.peerId, downloadedBlocks, payloadEnvelopes);
|
|
520
560
|
const logMeta: Record<string, number> = {
|
|
521
561
|
blockCount: downloadSuccessOutput.blocks.length,
|
|
522
562
|
};
|
|
@@ -526,7 +566,7 @@ export class SyncChain {
|
|
|
526
566
|
this.metrics?.syncRange.downloadByRange.warn.inc({client: peer.client, code: warning.type.code});
|
|
527
567
|
this.logger.debug(
|
|
528
568
|
"Batch downloaded with warning",
|
|
529
|
-
{id: this.logId,
|
|
569
|
+
{id: this.logId, ...batch.getMetadata(), ...logMeta, peer: prettyPrintPeerIdStr(peer.peerId)},
|
|
530
570
|
warning
|
|
531
571
|
);
|
|
532
572
|
}
|
|
@@ -552,10 +592,17 @@ export class SyncChain {
|
|
|
552
592
|
// the flow will continue to call triggerBatchDownloader() below
|
|
553
593
|
}
|
|
554
594
|
|
|
595
|
+
const blockSlots = downloadSuccessOutput.blocks.map((b) => b.slot);
|
|
596
|
+
const envelopeSlots = downloadSuccessOutput.payloadEnvelopes
|
|
597
|
+
? Array.from(downloadSuccessOutput.payloadEnvelopes.keys())
|
|
598
|
+
: null;
|
|
599
|
+
|
|
555
600
|
this.logger.debug(logMessage, {
|
|
556
601
|
id: this.logId,
|
|
557
|
-
|
|
602
|
+
...batch.getMetadata(),
|
|
558
603
|
...logMeta,
|
|
604
|
+
blockSlots: prettyPrintIndices(blockSlots),
|
|
605
|
+
...(envelopeSlots ? {envelopeSlots: prettyPrintIndices(envelopeSlots)} : {}),
|
|
559
606
|
peer: prettyPrintPeerIdStr(peer.peerId),
|
|
560
607
|
});
|
|
561
608
|
}
|
|
@@ -578,13 +625,24 @@ export class SyncChain {
|
|
|
578
625
|
* Sends `batch` to the processor. Note: batch may be empty
|
|
579
626
|
*/
|
|
580
627
|
private async processBatch(batch: Batch): Promise<void> {
|
|
581
|
-
const blocks = batch.startProcessing();
|
|
628
|
+
const {blocks, payloadEnvelopes, peers} = batch.startProcessing();
|
|
629
|
+
|
|
630
|
+
const logCtx = {
|
|
631
|
+
id: this.logId,
|
|
632
|
+
...batch.getMetadata(),
|
|
633
|
+
blockCount: blocks.length,
|
|
634
|
+
blockSlots: prettyPrintIndices(blocks.map((b) => b.slot)),
|
|
635
|
+
...(payloadEnvelopes ? {envelopeSlots: prettyPrintIndices(Array.from(payloadEnvelopes.keys()))} : {}),
|
|
636
|
+
peers: peers.map(prettyPrintPeerIdStr).join(","),
|
|
637
|
+
};
|
|
638
|
+
this.logger.verbose("Processing batch", logCtx);
|
|
582
639
|
|
|
583
640
|
// wrapError ensures to never call both batch success() and batch error()
|
|
584
|
-
const res = await wrapError(this.processChainSegment(blocks, this.syncType));
|
|
641
|
+
const res = await wrapError(this.processChainSegment(blocks, payloadEnvelopes, this.syncType));
|
|
585
642
|
|
|
586
643
|
if (!res.err) {
|
|
587
644
|
batch.processingSuccess();
|
|
645
|
+
this.logger.verbose("Processed batch", {...logCtx, ...batch.getMetadata()});
|
|
588
646
|
|
|
589
647
|
// If the processed batch is not empty, validate previous AwaitingValidation blocks.
|
|
590
648
|
if (blocks.length > 0) {
|
|
@@ -594,7 +652,7 @@ export class SyncChain {
|
|
|
594
652
|
// Potentially process next AwaitingProcessing batch
|
|
595
653
|
this.triggerBatchProcessor();
|
|
596
654
|
} else {
|
|
597
|
-
this.logger.verbose("Batch process error",
|
|
655
|
+
this.logger.verbose("Batch process error", logCtx, res.err);
|
|
598
656
|
batch.processingError(res.err); // Throws after MAX_BATCH_PROCESSING_ATTEMPTS
|
|
599
657
|
|
|
600
658
|
// At least one block was successfully verified and imported, so we can be sure all
|
package/src/sync/range/range.ts
CHANGED
|
@@ -172,7 +172,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
172
172
|
}
|
|
173
173
|
|
|
174
174
|
/** Convenience method for `SyncChain` */
|
|
175
|
-
private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, syncType) => {
|
|
175
|
+
private processChainSegment: SyncChainFns["processChainSegment"] = async (blocks, payloadEnvelopes, syncType) => {
|
|
176
176
|
// Not trusted, verify signatures
|
|
177
177
|
const flags: ImportBlockOpts = {
|
|
178
178
|
// Only skip importing attestations for finalized sync. For head sync attestation are valuable.
|
|
@@ -192,9 +192,15 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
192
192
|
|
|
193
193
|
if (this.opts?.disableProcessAsChainSegment) {
|
|
194
194
|
// Should only be used for debugging or testing
|
|
195
|
-
for (const block of blocks)
|
|
195
|
+
for (const block of blocks) {
|
|
196
|
+
await this.chain.processBlock(block, flags);
|
|
197
|
+
const payloadEnvelope = payloadEnvelopes?.get(block.slot);
|
|
198
|
+
if (payloadEnvelope) {
|
|
199
|
+
await this.chain.processExecutionPayload(payloadEnvelope);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
196
202
|
} else {
|
|
197
|
-
await this.chain.processChainSegment(blocks, flags);
|
|
203
|
+
await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
|
|
198
204
|
}
|
|
199
205
|
};
|
|
200
206
|
|
|
@@ -209,13 +215,19 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
209
215
|
peerDasMetrics: this.chain.metrics?.peerDas,
|
|
210
216
|
...batch.getRequestsForPeer(peer),
|
|
211
217
|
});
|
|
212
|
-
const
|
|
218
|
+
const {responses, payloadEnvelopes: downloadedPayloadEnvelopes} = result;
|
|
219
|
+
const {blocks, payloadEnvelopes} = cacheByRangeResponses({
|
|
213
220
|
cache: this.chain.seenBlockInputCache,
|
|
221
|
+
seenPayloadEnvelopeInputCache: this.chain.seenPayloadEnvelopeInputCache,
|
|
214
222
|
peerIdStr: peer.peerId,
|
|
215
|
-
responses
|
|
223
|
+
responses,
|
|
216
224
|
batchBlocks,
|
|
225
|
+
downloadedPayloadEnvelopes,
|
|
226
|
+
existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
|
|
227
|
+
custodyConfig: this.chain.custodyConfig,
|
|
228
|
+
seenTimestampSec: Date.now() / 1000,
|
|
217
229
|
});
|
|
218
|
-
return {result:
|
|
230
|
+
return {result: {blocks, payloadEnvelopes}, warnings};
|
|
219
231
|
};
|
|
220
232
|
|
|
221
233
|
private pruneBlockInputs: SyncChainFns["pruneBlockInputs"] = (blocks: IBlockInput[]) => {
|