@lodestar/beacon-node 1.43.0-dev.6641fd750e → 1.43.0-dev.66d2c102e3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/beacon/blocks/index.js +4 -6
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -2
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/lodestar/attesterSlashing.d.ts +8 -0
- package/lib/api/impl/lodestar/attesterSlashing.d.ts.map +1 -0
- package/lib/api/impl/lodestar/attesterSlashing.js +29 -0
- package/lib/api/impl/lodestar/attesterSlashing.js.map +1 -0
- package/lib/api/impl/lodestar/index.d.ts.map +1 -1
- package/lib/api/impl/lodestar/index.js +37 -2
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +1 -4
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +1 -1
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +1 -2
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +4 -4
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts +4 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.d.ts.map +1 -1
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js +2 -4
- package/lib/chain/archiveStore/strategies/frequencyStateArchiveStrategy.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +2 -2
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +110 -58
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +32 -37
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +25 -13
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +73 -84
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts +5 -3
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +29 -11
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +3 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +20 -0
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +5 -0
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +7 -5
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +15 -21
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +23 -2
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +81 -12
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts +3 -2
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +30 -5
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +15 -4
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +24 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +76 -0
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +14 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +25 -0
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -0
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js +2 -11
- package/lib/chain/blocks/writePayloadEnvelopeInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +8 -6
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +36 -43
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +16 -4
- package/lib/chain/emitter.d.ts.map +1 -1
- package/lib/chain/emitter.js +5 -0
- package/lib/chain/emitter.js.map +1 -1
- package/lib/chain/errors/attestationError.d.ts +8 -1
- package/lib/chain/errors/attestationError.d.ts.map +1 -1
- package/lib/chain/errors/attestationError.js +4 -0
- package/lib/chain/errors/attestationError.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +8 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +2 -0
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +5 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +5 -0
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +1 -0
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/errors/index.d.ts +1 -0
- package/lib/chain/errors/index.d.ts.map +1 -1
- package/lib/chain/errors/index.js +1 -0
- package/lib/chain/errors/index.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +33 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/errors/proposerPreferences.js +13 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -0
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +11 -15
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +7 -5
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +48 -22
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts +3 -9
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +5 -32
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -8
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +55 -24
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/errors.d.ts +1 -11
- package/lib/chain/regen/errors.d.ts.map +1 -1
- package/lib/chain/regen/errors.js +0 -2
- package/lib/chain/regen/errors.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +7 -12
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +1 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +6 -11
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +8 -40
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +0 -5
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +7 -34
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/seenCache/index.d.ts +1 -0
- package/lib/chain/seenCache/index.d.ts.map +1 -1
- package/lib/chain/seenCache/index.js +1 -0
- package/lib/chain/seenCache/index.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +11 -4
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +20 -18
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/seenCache/seenProposerPreferences.d.ts +15 -0
- package/lib/chain/seenCache/seenProposerPreferences.d.ts.map +1 -0
- package/lib/chain/seenCache/seenProposerPreferences.js +25 -0
- package/lib/chain/seenCache/seenProposerPreferences.js.map +1 -0
- package/lib/chain/stateCache/datastore/db.d.ts +5 -4
- package/lib/chain/stateCache/datastore/db.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/db.js +10 -32
- package/lib/chain/stateCache/datastore/db.js.map +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts +1 -1
- package/lib/chain/stateCache/datastore/file.d.ts.map +1 -1
- package/lib/chain/stateCache/datastore/file.js +5 -5
- package/lib/chain/stateCache/datastore/file.js.map +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts +1 -1
- package/lib/chain/stateCache/datastore/types.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +1 -7
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +0 -8
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +13 -30
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +120 -216
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +8 -15
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/stateCache/types.js.map +1 -1
- package/lib/chain/validation/aggregateAndProof.js +12 -0
- package/lib/chain/validation/aggregateAndProof.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +12 -0
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +1 -0
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -1
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +21 -11
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +4 -3
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts +8 -0
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -0
- package/lib/chain/validation/proposerPreferences.js +69 -0
- package/lib/chain/validation/proposerPreferences.js.map +1 -0
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js +1 -1
- package/lib/db/repositories/executionPayloadEnvelopeArchive.js.map +1 -1
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +21 -14
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +1 -0
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +6 -0
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/types.d.ts +20 -0
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +18 -0
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +1 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +4 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/interface.d.ts +7 -1
- package/lib/network/gossip/interface.d.ts.map +1 -1
- package/lib/network/gossip/interface.js +1 -0
- package/lib/network/gossip/interface.js.map +1 -1
- package/lib/network/gossip/scoringParameters.d.ts.map +1 -1
- package/lib/network/gossip/scoringParameters.js +12 -1
- package/lib/network/gossip/scoringParameters.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +30 -748
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +6 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/network.js +1 -1
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +32 -12
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/index.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/index.js +5 -0
- package/lib/network/processor/gossipQueues/index.js.map +1 -1
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +1 -0
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js +14 -6
- package/lib/network/reqresp/handlers/beaconBlocksByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js +11 -5
- package/lib/network/reqresp/handlers/blobSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +17 -5
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js +7 -4
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRange.js.map +1 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.js +7 -1
- package/lib/node/notifier.js.map +1 -1
- package/lib/sync/range/batch.d.ts +12 -2
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +56 -30
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +6 -2
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +4 -3
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +17 -6
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/types.d.ts +34 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +34 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +24 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +649 -53
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +46 -10
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +147 -24
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +6 -2
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.d.ts +0 -1
- package/lib/sync/utils/pendingBlocksTree.d.ts.map +1 -1
- package/lib/sync/utils/pendingBlocksTree.js +0 -9
- package/lib/sync/utils/pendingBlocksTree.js.map +1 -1
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +16 -3
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +17 -16
- package/src/api/impl/beacon/blocks/index.ts +6 -6
- package/src/api/impl/beacon/state/utils.ts +2 -2
- package/src/api/impl/lodestar/attesterSlashing.ts +43 -0
- package/src/api/impl/lodestar/index.ts +49 -3
- package/src/api/impl/validator/index.ts +3 -6
- package/src/chain/GetBlobsTracker.ts +1 -2
- package/src/chain/archiveStore/archiveStore.ts +5 -5
- package/src/chain/archiveStore/interface.ts +4 -4
- package/src/chain/archiveStore/strategies/frequencyStateArchiveStrategy.ts +6 -8
- package/src/chain/archiveStore/utils/archiveBlocks.ts +153 -94
- package/src/chain/blocks/importBlock.ts +31 -42
- package/src/chain/blocks/importExecutionPayload.ts +93 -104
- package/src/chain/blocks/index.ts +45 -14
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +27 -0
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +7 -6
- package/src/chain/blocks/types.ts +15 -26
- package/src/chain/blocks/utils/chainSegment.ts +106 -17
- package/src/chain/blocks/verifyBlock.ts +35 -6
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +16 -7
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +129 -0
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +38 -0
- package/src/chain/blocks/writePayloadEnvelopeInputToDb.ts +9 -18
- package/src/chain/chain.ts +51 -65
- package/src/chain/emitter.ts +15 -3
- package/src/chain/errors/attestationError.ts +6 -1
- package/src/chain/errors/blockError.ts +4 -1
- package/src/chain/errors/executionPayloadBid.ts +6 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +6 -0
- package/src/chain/errors/index.ts +1 -0
- package/src/chain/errors/proposerPreferences.ts +39 -0
- package/src/chain/forkChoice/index.ts +8 -20
- package/src/chain/interface.ts +11 -3
- package/src/chain/prepareNextSlot.ts +62 -23
- package/src/chain/produceBlock/computeNewStateRoot.ts +6 -43
- package/src/chain/produceBlock/produceBlockBody.ts +73 -27
- package/src/chain/regen/errors.ts +1 -6
- package/src/chain/regen/interface.ts +7 -12
- package/src/chain/regen/queued.ts +12 -48
- package/src/chain/regen/regen.ts +8 -36
- package/src/chain/seenCache/index.ts +1 -0
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +22 -20
- package/src/chain/seenCache/seenProposerPreferences.ts +29 -0
- package/src/chain/stateCache/datastore/db.ts +10 -33
- package/src/chain/stateCache/datastore/file.ts +5 -6
- package/src/chain/stateCache/datastore/types.ts +2 -3
- package/src/chain/stateCache/fifoBlockStateCache.ts +1 -10
- package/src/chain/stateCache/persistentCheckpointsCache.ts +139 -247
- package/src/chain/stateCache/types.ts +8 -14
- package/src/chain/validation/aggregateAndProof.ts +13 -0
- package/src/chain/validation/attestation.ts +13 -0
- package/src/chain/validation/block.ts +1 -0
- package/src/chain/validation/executionPayloadBid.ts +14 -0
- package/src/chain/validation/executionPayloadEnvelope.ts +22 -12
- package/src/chain/validation/payloadAttestationMessage.ts +5 -3
- package/src/chain/validation/proposerPreferences.ts +91 -0
- package/src/db/repositories/executionPayloadEnvelopeArchive.ts +1 -1
- package/src/execution/engine/http.ts +21 -14
- package/src/execution/engine/interface.ts +1 -0
- package/src/execution/engine/mock.ts +8 -1
- package/src/execution/engine/types.ts +41 -0
- package/src/metrics/metrics/lodestar.ts +4 -0
- package/src/network/gossip/interface.ts +6 -0
- package/src/network/gossip/scoringParameters.ts +14 -1
- package/src/network/gossip/topic.ts +6 -0
- package/src/network/network.ts +1 -1
- package/src/network/processor/gossipHandlers.ts +41 -16
- package/src/network/processor/gossipQueues/index.ts +5 -0
- package/src/network/processor/index.ts +1 -0
- package/src/network/reqresp/handlers/beaconBlocksByRange.ts +14 -6
- package/src/network/reqresp/handlers/blobSidecarsByRange.ts +11 -5
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +17 -5
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRange.ts +7 -4
- package/src/node/nodejs.ts +4 -2
- package/src/node/notifier.ts +8 -1
- package/src/sync/range/batch.ts +90 -35
- package/src/sync/range/chain.ts +13 -5
- package/src/sync/range/range.ts +18 -6
- package/src/sync/types.ts +72 -0
- package/src/sync/unknownBlock.ts +810 -57
- package/src/sync/utils/downloadByRange.ts +256 -39
- package/src/sync/utils/downloadByRoot.ts +12 -2
- package/src/sync/utils/pendingBlocksTree.ts +0 -15
- package/src/util/sszBytes.ts +21 -3
|
@@ -79,6 +79,7 @@ import {
|
|
|
79
79
|
import {validateLightClientFinalityUpdate} from "../../chain/validation/lightClientFinalityUpdate.js";
|
|
80
80
|
import {validateLightClientOptimisticUpdate} from "../../chain/validation/lightClientOptimisticUpdate.js";
|
|
81
81
|
import {validateGossipPayloadAttestationMessage} from "../../chain/validation/payloadAttestationMessage.js";
|
|
82
|
+
import {validateGossipProposerPreferences} from "../../chain/validation/proposerPreferences.js";
|
|
82
83
|
import {OpSource} from "../../chain/validatorMonitor.js";
|
|
83
84
|
import {Metrics} from "../../metrics/index.js";
|
|
84
85
|
import {kzgCommitmentToVersionedHash} from "../../util/blobs.js";
|
|
@@ -198,7 +199,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
198
199
|
} catch (e) {
|
|
199
200
|
if (e instanceof BlockGossipError) {
|
|
200
201
|
logger.debug("Gossip block has error", {slot, root: blockShortHex, code: e.type.code});
|
|
201
|
-
if (
|
|
202
|
+
if (
|
|
203
|
+
(e.type.code === BlockErrorCode.PARENT_UNKNOWN || e.type.code === BlockErrorCode.PARENT_PAYLOAD_UNKNOWN) &&
|
|
204
|
+
blockInput
|
|
205
|
+
) {
|
|
202
206
|
chain.emitter.emit(ChainEvent.blockUnknownParent, {
|
|
203
207
|
blockInput,
|
|
204
208
|
peer: peerIdStr,
|
|
@@ -745,13 +749,29 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
745
749
|
});
|
|
746
750
|
}
|
|
747
751
|
|
|
748
|
-
chain.processExecutionPayload
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
);
|
|
754
|
-
|
|
752
|
+
// NOTE: we do NOT call chain.processExecutionPayload here. That is triggered only by
|
|
753
|
+
// envelope arrival (gossip or API). An in-flight importExecutionPayload is awaiting
|
|
754
|
+
// payloadInput.waitForAllData(); addColumn above will resolve it once hasAllData flips.
|
|
755
|
+
|
|
756
|
+
if (!payloadInput.isComplete()) {
|
|
757
|
+
const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
|
|
758
|
+
// do not await here to not delay gossip validation
|
|
759
|
+
payloadInput.waitForEnvelopeAndAllData(cutoffTimeMs).catch((_e) => {
|
|
760
|
+
chain.logger.debug(
|
|
761
|
+
"Waited for envelope and data after receiving gossip column. Cut-off reached so emitting incompletePayloadEnvelope",
|
|
762
|
+
{
|
|
763
|
+
dataColumnIndex: index,
|
|
764
|
+
...payloadInputMeta,
|
|
765
|
+
}
|
|
766
|
+
);
|
|
767
|
+
// TODO GLOAS: UnknownBlockSync to handle this event
|
|
768
|
+
chain.emitter.emit(ChainEvent.incompletePayloadEnvelope, {
|
|
769
|
+
payloadInput,
|
|
770
|
+
peer: peerIdStr,
|
|
771
|
+
source: BlockInputSource.gossip,
|
|
772
|
+
});
|
|
773
|
+
});
|
|
774
|
+
}
|
|
755
775
|
} else {
|
|
756
776
|
if (config.getForkSeq(dataColumnSlot) < ForkSeq.fulu) {
|
|
757
777
|
throw new GossipActionError(GossipAction.REJECT, {code: "PRE_FULU_BLOCK"});
|
|
@@ -1041,18 +1061,16 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1041
1061
|
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
1042
1062
|
const envelope = signedEnvelope.message;
|
|
1043
1063
|
|
|
1044
|
-
//
|
|
1045
|
-
//
|
|
1046
|
-
// the problem now is we cannot create a PayloadEnvelopeInput without the beacon block being known, we need at least the proposer index
|
|
1047
|
-
// we can achieve that by looking into the EpochCache
|
|
1064
|
+
// unlike BlockInput, we send the envelope into UnknownBlockInput sync
|
|
1065
|
+
// inside the sync it'll reconcile into PayloadEnvelopeInput and share the same cache with gossip
|
|
1048
1066
|
try {
|
|
1049
1067
|
await validateGossipExecutionPayloadEnvelope(chain, signedEnvelope);
|
|
1050
1068
|
} catch (e) {
|
|
1051
1069
|
if (e instanceof ExecutionPayloadEnvelopeError) {
|
|
1052
|
-
const {
|
|
1070
|
+
const {beaconBlockRoot} = signedEnvelope.message;
|
|
1071
|
+
const slot = signedEnvelope.message.payload.slotNumber;
|
|
1053
1072
|
logger.debug("Gossip envelope has error", {slot, root: toRootHex(beaconBlockRoot), code: e.type.code});
|
|
1054
1073
|
if (e.type.code === ExecutionPayloadEnvelopeErrorCode.BLOCK_ROOT_UNKNOWN) {
|
|
1055
|
-
// TODO GLOAS: UnknownBlockSync to handle this
|
|
1056
1074
|
chain.emitter.emit(ChainEvent.envelopeUnknownBlock, {
|
|
1057
1075
|
envelope: signedEnvelope,
|
|
1058
1076
|
peer: peerIdStr,
|
|
@@ -1072,7 +1090,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1072
1090
|
throw e;
|
|
1073
1091
|
}
|
|
1074
1092
|
|
|
1075
|
-
const slot = envelope.
|
|
1093
|
+
const slot = envelope.payload.slotNumber;
|
|
1076
1094
|
const delaySec = seenTimestampSec - computeTimeAtSlot(config, slot, chain.genesisTime);
|
|
1077
1095
|
metrics?.gossipExecutionPayloadEnvelope.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
|
|
1078
1096
|
chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
|
|
@@ -1102,7 +1120,6 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1102
1120
|
builderIndex: envelope.builderIndex,
|
|
1103
1121
|
blockHash: toRootHex(envelope.payload.blockHash),
|
|
1104
1122
|
blockRoot: blockRootHex,
|
|
1105
|
-
stateRoot: toRootHex(envelope.stateRoot),
|
|
1106
1123
|
});
|
|
1107
1124
|
|
|
1108
1125
|
chain.processExecutionPayload(payloadInput, {validSignature: true}).catch((e) => {
|
|
@@ -1154,6 +1171,14 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1154
1171
|
data: executionPayloadBid,
|
|
1155
1172
|
});
|
|
1156
1173
|
},
|
|
1174
|
+
[GossipType.proposer_preferences]: async ({
|
|
1175
|
+
gossipData,
|
|
1176
|
+
topic,
|
|
1177
|
+
}: GossipHandlerParamGeneric<GossipType.proposer_preferences>) => {
|
|
1178
|
+
const {serializedData} = gossipData;
|
|
1179
|
+
const signedProposerPreferences = sszDeserialize(topic, serializedData);
|
|
1180
|
+
await validateGossipProposerPreferences(chain, signedProposerPreferences);
|
|
1181
|
+
},
|
|
1157
1182
|
};
|
|
1158
1183
|
}
|
|
1159
1184
|
|
|
@@ -83,6 +83,11 @@ const linearGossipQueueOpts: {
|
|
|
83
83
|
type: QueueType.FIFO,
|
|
84
84
|
dropOpts: {type: DropType.count, count: 1},
|
|
85
85
|
},
|
|
86
|
+
[GossipType.proposer_preferences]: {
|
|
87
|
+
maxLength: 1024,
|
|
88
|
+
type: QueueType.FIFO,
|
|
89
|
+
dropOpts: {type: DropType.count, count: 1},
|
|
90
|
+
},
|
|
86
91
|
};
|
|
87
92
|
|
|
88
93
|
const indexedGossipQueueOpts: {
|
|
@@ -91,6 +91,7 @@ const executeGossipWorkOrderObj: Record<GossipType, WorkOpts> = {
|
|
|
91
91
|
[GossipType.execution_payload]: {bypassQueue: true},
|
|
92
92
|
[GossipType.payload_attestation_message]: {},
|
|
93
93
|
[GossipType.execution_payload_bid]: {},
|
|
94
|
+
[GossipType.proposer_preferences]: {},
|
|
94
95
|
};
|
|
95
96
|
const executeGossipWorkOrder = Object.keys(executeGossipWorkOrderObj) as (keyof typeof executeGossipWorkOrderObj)[];
|
|
96
97
|
|
|
@@ -24,6 +24,10 @@ export async function* onBeaconBlocksByRange(
|
|
|
24
24
|
// in the case of initializing from a non-finalized state, we don't have the finalized block so this api does not work
|
|
25
25
|
// chain.forkChoice.getFinalizeBlock().slot
|
|
26
26
|
const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
|
|
27
|
+
// Blocks are migrated to blockArchive at finalization (including the finalized block itself),
|
|
28
|
+
// so the archive loop serves up to AND INCLUDING finalizedSlot and the headChain loop
|
|
29
|
+
// starts above it to avoid duplicate yields. See archiveBlocks.ts for the migration logic.
|
|
30
|
+
const archiveMaxSlot = finalizedSlot;
|
|
27
31
|
|
|
28
32
|
const forkName = chain.config.getForkName(startSlot);
|
|
29
33
|
if (isForkPostFulu(forkName) && startSlot < chain.earliestAvailableSlot) {
|
|
@@ -35,9 +39,12 @@ export async function* onBeaconBlocksByRange(
|
|
|
35
39
|
}
|
|
36
40
|
|
|
37
41
|
// Finalized range of blocks
|
|
38
|
-
if (startSlot <=
|
|
42
|
+
if (startSlot <= archiveMaxSlot) {
|
|
39
43
|
// Chain of blobs won't change
|
|
40
|
-
for await (const {key, value} of finalized.binaryEntriesStream({
|
|
44
|
+
for await (const {key, value} of finalized.binaryEntriesStream({
|
|
45
|
+
gte: startSlot,
|
|
46
|
+
lt: Math.min(endSlot, archiveMaxSlot + 1),
|
|
47
|
+
})) {
|
|
41
48
|
yield {
|
|
42
49
|
data: value,
|
|
43
50
|
boundary: chain.config.getForkBoundaryAtEpoch(computeEpochAtSlot(finalized.decodeKey(key))),
|
|
@@ -46,19 +53,20 @@ export async function* onBeaconBlocksByRange(
|
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
// Non-finalized range of blocks
|
|
49
|
-
if (endSlot >
|
|
56
|
+
if (endSlot > archiveMaxSlot) {
|
|
50
57
|
const headBlock = chain.forkChoice.getHead();
|
|
51
58
|
const headRoot = headBlock.blockRoot;
|
|
52
59
|
// TODO DENEB: forkChoice should mantain an array of canonical blocks, and change only on reorg
|
|
53
60
|
const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
|
|
54
|
-
// getAllAncestorBlocks
|
|
61
|
+
// `getAllAncestorBlocks` includes both the head and the previous-finalized boundary.
|
|
55
62
|
|
|
56
63
|
// Iterate head chain with ascending block numbers
|
|
57
64
|
for (let i = headChain.length - 1; i >= 0; i--) {
|
|
58
65
|
const block = headChain[i];
|
|
59
66
|
|
|
60
|
-
// Must include only blocks in the range requested
|
|
61
|
-
|
|
67
|
+
// Must include only blocks in the range requested, and skip anything the archive loop
|
|
68
|
+
// above already served via the block.slot > archiveMaxSlot filter.
|
|
69
|
+
if (block.slot > archiveMaxSlot && block.slot >= startSlot && block.slot < endSlot) {
|
|
62
70
|
// Note: Here the forkChoice head may change due to a re-org, so the headChain reflects the canonical chain
|
|
63
71
|
// at the time of the start of the request. Spec is clear the chain of blobs must be consistent, but on
|
|
64
72
|
// re-org there's no need to abort the request
|
|
@@ -20,31 +20,37 @@ export async function* onBlobSidecarsByRange(
|
|
|
20
20
|
const finalized = db.blobSidecarsArchive;
|
|
21
21
|
const unfinalized = db.blobSidecars;
|
|
22
22
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
23
|
+
// Blobs are migrated to blobSidecarsArchive at finalization (including the finalized block
|
|
24
|
+
// itself), so the archive loop serves up to AND INCLUDING finalizedSlot and the headChain
|
|
25
|
+
// loop starts above it to avoid duplicate yields. See archiveBlocks.ts for the migration logic.
|
|
26
|
+
const archiveMaxSlot = finalizedSlot;
|
|
23
27
|
|
|
24
28
|
// Finalized range of blobs
|
|
25
|
-
if (startSlot <=
|
|
29
|
+
if (startSlot <= archiveMaxSlot) {
|
|
26
30
|
// Chain of blobs won't change
|
|
27
31
|
for await (const {key, value: blobSideCarsBytesWrapped} of finalized.binaryEntriesStream({
|
|
28
32
|
gte: startSlot,
|
|
29
|
-
lt: endSlot,
|
|
33
|
+
lt: Math.min(endSlot, archiveMaxSlot + 1),
|
|
30
34
|
})) {
|
|
31
35
|
yield* iterateBlobBytesFromWrapper(chain, blobSideCarsBytesWrapped, finalized.decodeKey(key));
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
// Non-finalized range of blobs
|
|
36
|
-
if (endSlot >
|
|
40
|
+
if (endSlot > archiveMaxSlot) {
|
|
37
41
|
const headBlock = chain.forkChoice.getHead();
|
|
38
42
|
const headRoot = headBlock.blockRoot;
|
|
39
43
|
// TODO DENEB: forkChoice should mantain an array of canonical blocks, and change only on reorg
|
|
40
44
|
const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
|
|
45
|
+
// `getAllAncestorBlocks` includes both the head and the previous-finalized boundary.
|
|
41
46
|
|
|
42
47
|
// Iterate head chain with ascending block numbers
|
|
43
48
|
for (let i = headChain.length - 1; i >= 0; i--) {
|
|
44
49
|
const block = headChain[i];
|
|
45
50
|
|
|
46
|
-
// Must include only blobs in the range requested
|
|
47
|
-
|
|
51
|
+
// Must include only blobs in the range requested, and skip anything the archive loop
|
|
52
|
+
// above already served via the block.slot > archiveMaxSlot filter.
|
|
53
|
+
if (block.slot > archiveMaxSlot && block.slot >= startSlot && block.slot < endSlot) {
|
|
48
54
|
// Note: Here the forkChoice head may change due to a re-org, so the headChain reflects the canonical chain
|
|
49
55
|
// at the time of the start of the request. Spec is clear the chain of blobs must be consistent, but on
|
|
50
56
|
// re-org there's no need to abort the request
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {PeerId} from "@libp2p/interface";
|
|
2
2
|
import {ChainConfig} from "@lodestar/config";
|
|
3
|
-
import {GENESIS_SLOT} from "@lodestar/params";
|
|
3
|
+
import {ForkSeq, GENESIS_SLOT} from "@lodestar/params";
|
|
4
4
|
import {RespStatus, ResponseError, ResponseOutgoing} from "@lodestar/reqresp";
|
|
5
5
|
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
6
6
|
import {ColumnIndex, Epoch, fulu} from "@lodestar/types";
|
|
@@ -43,10 +43,19 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
43
43
|
|
|
44
44
|
const finalized = db.dataColumnSidecarArchive;
|
|
45
45
|
const finalizedSlot = chain.forkChoice.getFinalizedBlock().slot;
|
|
46
|
+
// Columns of the last finalized block live in different DBs depending on fork:
|
|
47
|
+
// - Pre-gloas (fulu): migrated to dataColumnSidecarArchive in the same finalization run.
|
|
48
|
+
// - Post-gloas: stay in the hot db (db.dataColumnSidecar) until the next finalization run,
|
|
49
|
+
// because the migration filter requires payloadStatus === FULL for gloas blocks.
|
|
50
|
+
// archiveMaxSlot is the last slot whose columns are served by the archive loop below;
|
|
51
|
+
// anything above it is served by the headChain loop.
|
|
52
|
+
const isPostGloasFinalized = chain.config.getForkSeq(finalizedSlot) >= ForkSeq.gloas;
|
|
53
|
+
const archiveMaxSlot = isPostGloasFinalized ? finalizedSlot - 1 : finalizedSlot;
|
|
46
54
|
|
|
47
55
|
// Finalized range of columns
|
|
48
|
-
if (startSlot <=
|
|
49
|
-
|
|
56
|
+
if (startSlot <= archiveMaxSlot) {
|
|
57
|
+
const archiveEnd = Math.min(endSlot, archiveMaxSlot + 1);
|
|
58
|
+
for (let slot = startSlot; slot < archiveEnd; slot++) {
|
|
50
59
|
const dataColumnSidecars = await finalized.getManyBinary(slot, availableColumns);
|
|
51
60
|
|
|
52
61
|
const unavailableColumnIndices: ColumnIndex[] = [];
|
|
@@ -81,9 +90,12 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
// Non-finalized range of columns
|
|
84
|
-
if (endSlot >
|
|
93
|
+
if (endSlot > archiveMaxSlot) {
|
|
85
94
|
const headBlock = chain.forkChoice.getHead();
|
|
86
95
|
const headRoot = headBlock.blockRoot;
|
|
96
|
+
// getAllAncestorBlocks includes the last finalized block as its final element.
|
|
97
|
+
// Skip anything the archive loop above already served via the block.slot > archiveMaxSlot
|
|
98
|
+
// filter below (pre-gloas this skips finalizedSlot, post-gloas it keeps it).
|
|
87
99
|
const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
|
|
88
100
|
|
|
89
101
|
// Iterate head chain with ascending block numbers
|
|
@@ -91,7 +103,7 @@ export async function* onDataColumnSidecarsByRange(
|
|
|
91
103
|
const block = headChain[i];
|
|
92
104
|
|
|
93
105
|
// Must include only columns in the range requested
|
|
94
|
-
if (block.slot >= startSlot && block.slot < endSlot) {
|
|
106
|
+
if (block.slot > archiveMaxSlot && block.slot >= startSlot && block.slot < endSlot) {
|
|
95
107
|
// Note: Here the forkChoice head may change due to a re-org, so the headChain reflects the canonical chain
|
|
96
108
|
// at the time of the start of the request. Spec is clear the chain of columns must be consistent, but on
|
|
97
109
|
// re-org there's no need to abort the request
|
|
@@ -21,12 +21,15 @@ export async function* onExecutionPayloadEnvelopesByRange(
|
|
|
21
21
|
|
|
22
22
|
const finalized = db.executionPayloadEnvelopeArchive;
|
|
23
23
|
const finalizedSlot = chain.forkChoice.getFinalizedCheckpointSlot();
|
|
24
|
+
// The current finalized block's envelope is still in the hot db; archive migration happens
|
|
25
|
+
// in the next finalization run (see migrateExecutionPayloadEnvelopesFromHotToColdDb).
|
|
26
|
+
const archiveMaxSlot = finalizedSlot - 1;
|
|
24
27
|
|
|
25
28
|
// Finalized range of envelopes
|
|
26
|
-
if (startSlot <=
|
|
29
|
+
if (startSlot <= archiveMaxSlot) {
|
|
27
30
|
for await (const {key, value: envelopeBytes} of finalized.binaryEntriesStream({
|
|
28
31
|
gte: startSlot,
|
|
29
|
-
lt: endSlot,
|
|
32
|
+
lt: Math.min(endSlot, archiveMaxSlot + 1),
|
|
30
33
|
})) {
|
|
31
34
|
const slot = finalized.decodeKey(key);
|
|
32
35
|
yield {
|
|
@@ -37,7 +40,7 @@ export async function* onExecutionPayloadEnvelopesByRange(
|
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
// Non-finalized range of envelopes
|
|
40
|
-
if (endSlot >
|
|
43
|
+
if (endSlot > archiveMaxSlot) {
|
|
41
44
|
const headBlock = chain.forkChoice.getHead();
|
|
42
45
|
const headRoot = headBlock.blockRoot;
|
|
43
46
|
const headChain = chain.forkChoice.getAllAncestorBlocks(headRoot, headBlock.payloadStatus);
|
|
@@ -46,7 +49,7 @@ export async function* onExecutionPayloadEnvelopesByRange(
|
|
|
46
49
|
for (let i = headChain.length - 1; i >= 0; i--) {
|
|
47
50
|
const block = headChain[i];
|
|
48
51
|
|
|
49
|
-
if (block.slot >= startSlot && block.slot < endSlot) {
|
|
52
|
+
if (block.slot > archiveMaxSlot && block.slot >= startSlot && block.slot < endSlot) {
|
|
50
53
|
// Skip EMPTY blocks
|
|
51
54
|
if (block.payloadStatus !== PayloadStatus.FULL) {
|
|
52
55
|
continue;
|
package/src/node/nodejs.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
|
6
6
|
import {BeaconConfig} from "@lodestar/config";
|
|
7
7
|
import type {LoggerNode} from "@lodestar/logger/node";
|
|
8
8
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
9
|
-
import {IBeaconStateView, PubkeyCache, isStatePostBellatrix} from "@lodestar/state-transition";
|
|
9
|
+
import {IBeaconStateView, PubkeyCache, isStatePostBellatrix, isStatePostGloas} from "@lodestar/state-transition";
|
|
10
10
|
import {phase0} from "@lodestar/types";
|
|
11
11
|
import {sleep, toRootHex} from "@lodestar/utils";
|
|
12
12
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
@@ -223,7 +223,9 @@ export class BeaconNode {
|
|
|
223
223
|
if (opts.executionEngine.mode === "mock") {
|
|
224
224
|
const eth1BlockHash =
|
|
225
225
|
isStatePostBellatrix(anchorState) && anchorState.isExecutionStateType
|
|
226
|
-
?
|
|
226
|
+
? isStatePostGloas(anchorState)
|
|
227
|
+
? toRootHex(anchorState.latestBlockHash)
|
|
228
|
+
: toRootHex(anchorState.latestExecutionPayloadHeader.blockHash)
|
|
227
229
|
: undefined;
|
|
228
230
|
executionEngineOpts = {
|
|
229
231
|
...opts.executionEngine,
|
package/src/node/notifier.ts
CHANGED
|
@@ -167,7 +167,14 @@ function getHeadExecutionInfo(
|
|
|
167
167
|
return [];
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
-
|
|
170
|
+
// A PayloadSeparated head is a gloas beacon block imported before its payload envelope
|
|
171
|
+
// arrives, in that case the exec-block row surfaces the inherited parent anchor (from the
|
|
172
|
+
// bid), which is already validated. Normalize to "valid" to avoid leaking internal
|
|
173
|
+
// fork-choice bookkeeping into the log. Once the payload envelope arrives and the FULL
|
|
174
|
+
// variant becomes head, executionStatus is Valid/Syncing naturally.
|
|
175
|
+
// TODO GLOAS: revisit once optimistic sync is implemented
|
|
176
|
+
const executionStatusStr =
|
|
177
|
+
headInfo.executionStatus === ExecutionStatus.PayloadSeparated ? "valid" : headInfo.executionStatus.toLowerCase();
|
|
171
178
|
|
|
172
179
|
// Add execution status to notifier only if head is on/post bellatrix
|
|
173
180
|
if (isStatePostBellatrix(headState) && headState.isExecutionStateType) {
|
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
4
|
import {LodestarError} 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,19 +47,36 @@ 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 = {
|
|
64
82
|
startEpoch: Epoch;
|
|
@@ -85,7 +103,7 @@ export class Batch {
|
|
|
85
103
|
/** Block, blob and column requests that are used to determine the best peer and are used in downloadByRange */
|
|
86
104
|
requests: DownloadByRangeRequests;
|
|
87
105
|
/** State of the batch. */
|
|
88
|
-
state: BatchState = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
106
|
+
state: BatchState = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
89
107
|
/** Peers that provided good data */
|
|
90
108
|
goodPeers: PeerIdStr[] = [];
|
|
91
109
|
/** The `Attempts` that have been made and failed to send us this batch. */
|
|
@@ -129,35 +147,33 @@ export class Batch {
|
|
|
129
147
|
count: this.count,
|
|
130
148
|
step: 1,
|
|
131
149
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
count: this.count,
|
|
138
|
-
columns: this.custodyConfig.sampledColumns,
|
|
139
|
-
},
|
|
140
|
-
};
|
|
150
|
+
const requests: DownloadByRangeRequests = {blocksRequest};
|
|
151
|
+
|
|
152
|
+
// Post-Gloas envelopes are required for block processing, independent of DA retention window.
|
|
153
|
+
if (isForkPostGloas(this.forkName)) {
|
|
154
|
+
requests.envelopesRequest = {startSlot: this.startSlot, count: this.count};
|
|
141
155
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
},
|
|
156
|
+
|
|
157
|
+
if (isForkPostFulu(this.forkName) && withinValidRequestWindow) {
|
|
158
|
+
requests.columnsRequest = {
|
|
159
|
+
startSlot: this.startSlot,
|
|
160
|
+
count: this.count,
|
|
161
|
+
columns: this.custodyConfig.sampledColumns,
|
|
149
162
|
};
|
|
163
|
+
} else if (isForkPostDeneb(this.forkName) && withinValidRequestWindow) {
|
|
164
|
+
requests.blobsRequest = {startSlot: this.startSlot, count: this.count};
|
|
150
165
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
};
|
|
166
|
+
|
|
167
|
+
return requests;
|
|
154
168
|
}
|
|
155
169
|
|
|
156
170
|
// subsequent request where part of the epoch has already been downloaded. Need to figure out what is the beginning
|
|
157
171
|
// of the range where download needs to resume
|
|
158
172
|
let blockStartSlot = this.startSlot;
|
|
159
173
|
let dataStartSlot = this.startSlot;
|
|
174
|
+
let envelopeStartSlot = this.startSlot;
|
|
160
175
|
const neededColumns = new Set<number>();
|
|
176
|
+
const envelopesBySlot = this.state.payloadEnvelopes ?? new Map<Slot, PayloadEnvelopeInput>();
|
|
161
177
|
|
|
162
178
|
// ensure blocks are in slot-wise order
|
|
163
179
|
for (const blockInput of blocks) {
|
|
@@ -175,6 +191,13 @@ export class Batch {
|
|
|
175
191
|
if (blockInput.hasBlock() && blockStartSlot === blockSlot) {
|
|
176
192
|
blockStartSlot = blockSlot + 1;
|
|
177
193
|
}
|
|
194
|
+
if (
|
|
195
|
+
blockInput.hasBlock() &&
|
|
196
|
+
envelopeStartSlot === blockSlot &&
|
|
197
|
+
envelopesBySlot.get(blockSlot)?.hasPayloadEnvelope()
|
|
198
|
+
) {
|
|
199
|
+
envelopeStartSlot = blockSlot + 1;
|
|
200
|
+
}
|
|
178
201
|
if (!blockInput.hasAllData()) {
|
|
179
202
|
if (isBlockInputColumns(blockInput)) {
|
|
180
203
|
for (const index of blockInput.getMissingSampledColumnMeta().missing) {
|
|
@@ -216,6 +239,13 @@ export class Batch {
|
|
|
216
239
|
// dataSlot will still have a value but do not create a request for preDeneb forks
|
|
217
240
|
}
|
|
218
241
|
|
|
242
|
+
if (isForkPostGloas(this.forkName) && envelopeStartSlot <= endSlot) {
|
|
243
|
+
requests.envelopesRequest = {
|
|
244
|
+
startSlot: envelopeStartSlot,
|
|
245
|
+
count: endSlot - envelopeStartSlot + 1,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
219
249
|
return requests;
|
|
220
250
|
}
|
|
221
251
|
|
|
@@ -263,6 +293,10 @@ export class Batch {
|
|
|
263
293
|
return this.state.blocks;
|
|
264
294
|
}
|
|
265
295
|
|
|
296
|
+
getPayloadEnvelopes(): Map<Slot, PayloadEnvelopeInput> | null {
|
|
297
|
+
return this.state.payloadEnvelopes;
|
|
298
|
+
}
|
|
299
|
+
|
|
266
300
|
/**
|
|
267
301
|
* AwaitingDownload -> Downloading
|
|
268
302
|
*/
|
|
@@ -271,13 +305,22 @@ export class Batch {
|
|
|
271
305
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingDownload));
|
|
272
306
|
}
|
|
273
307
|
|
|
274
|
-
this.state = {
|
|
308
|
+
this.state = {
|
|
309
|
+
status: BatchStatus.Downloading,
|
|
310
|
+
peer,
|
|
311
|
+
blocks: this.state.blocks,
|
|
312
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
313
|
+
};
|
|
275
314
|
}
|
|
276
315
|
|
|
277
316
|
/**
|
|
278
317
|
* Downloading -> AwaitingProcessing
|
|
279
318
|
*/
|
|
280
|
-
downloadingSuccess(
|
|
319
|
+
downloadingSuccess(
|
|
320
|
+
peer: PeerIdStr,
|
|
321
|
+
blocks: IBlockInput[],
|
|
322
|
+
payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null
|
|
323
|
+
): DownloadSuccessState {
|
|
281
324
|
if (this.state.status !== BatchStatus.Downloading) {
|
|
282
325
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Downloading));
|
|
283
326
|
}
|
|
@@ -305,11 +348,13 @@ export class Batch {
|
|
|
305
348
|
status: this.state.status,
|
|
306
349
|
});
|
|
307
350
|
}
|
|
351
|
+
const newPayloadEnvelopes = payloadEnvelopes ?? this.state.payloadEnvelopes;
|
|
352
|
+
|
|
308
353
|
if (allComplete) {
|
|
309
|
-
this.state = {status: BatchStatus.AwaitingProcessing, blocks};
|
|
354
|
+
this.state = {status: BatchStatus.AwaitingProcessing, blocks, payloadEnvelopes: newPayloadEnvelopes};
|
|
310
355
|
} else {
|
|
311
356
|
this.requests = this.getRequests(blocks);
|
|
312
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks};
|
|
357
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks, payloadEnvelopes: newPayloadEnvelopes};
|
|
313
358
|
}
|
|
314
359
|
|
|
315
360
|
return this.state as DownloadSuccessState;
|
|
@@ -328,25 +373,30 @@ export class Batch {
|
|
|
328
373
|
throw new BatchError(this.errorType({code: BatchErrorCode.MAX_DOWNLOAD_ATTEMPTS}));
|
|
329
374
|
}
|
|
330
375
|
|
|
331
|
-
this.state = {
|
|
376
|
+
this.state = {
|
|
377
|
+
status: BatchStatus.AwaitingDownload,
|
|
378
|
+
blocks: this.state.blocks,
|
|
379
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
380
|
+
};
|
|
332
381
|
}
|
|
333
382
|
|
|
334
383
|
/**
|
|
335
384
|
* AwaitingProcessing -> Processing
|
|
336
385
|
*/
|
|
337
|
-
startProcessing(): IBlockInput[] {
|
|
386
|
+
startProcessing(): {blocks: IBlockInput[]; payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null} {
|
|
338
387
|
if (this.state.status !== BatchStatus.AwaitingProcessing) {
|
|
339
388
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.AwaitingProcessing));
|
|
340
389
|
}
|
|
341
390
|
|
|
342
391
|
const blocks = this.state.blocks;
|
|
392
|
+
const payloadEnvelopes = this.state.payloadEnvelopes;
|
|
343
393
|
const hash = hashBlocks(blocks, this.config); // tracks blocks to report peer on processing error
|
|
344
394
|
// Reset goodPeers in case another download attempt needs to be made. When Attempt is successful or not the peers
|
|
345
395
|
// that the data came from will be handled by the Attempt that goes for processing
|
|
346
396
|
const peers = this.goodPeers;
|
|
347
397
|
this.goodPeers = [];
|
|
348
|
-
this.state = {status: BatchStatus.Processing, blocks, attempt: {peers, hash}};
|
|
349
|
-
return blocks;
|
|
398
|
+
this.state = {status: BatchStatus.Processing, blocks, payloadEnvelopes, attempt: {peers, hash}};
|
|
399
|
+
return {blocks, payloadEnvelopes};
|
|
350
400
|
}
|
|
351
401
|
|
|
352
402
|
/**
|
|
@@ -357,7 +407,12 @@ export class Batch {
|
|
|
357
407
|
throw new BatchError(this.wrongStatusErrorType(BatchStatus.Processing));
|
|
358
408
|
}
|
|
359
409
|
|
|
360
|
-
this.state = {
|
|
410
|
+
this.state = {
|
|
411
|
+
status: BatchStatus.AwaitingValidation,
|
|
412
|
+
blocks: this.state.blocks,
|
|
413
|
+
payloadEnvelopes: this.state.payloadEnvelopes,
|
|
414
|
+
attempt: this.state.attempt,
|
|
415
|
+
};
|
|
361
416
|
}
|
|
362
417
|
|
|
363
418
|
/**
|
|
@@ -408,7 +463,7 @@ export class Batch {
|
|
|
408
463
|
|
|
409
464
|
// remove any downloaded blocks and re-attempt
|
|
410
465
|
// TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
|
|
411
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
466
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
412
467
|
}
|
|
413
468
|
|
|
414
469
|
private onProcessingError(attempt: Attempt): void {
|
|
@@ -419,7 +474,7 @@ export class Batch {
|
|
|
419
474
|
|
|
420
475
|
// remove any downloaded blocks and re-attempt
|
|
421
476
|
// TODO(fulu): need to remove the bad blocks from the SeenBlockInputCache
|
|
422
|
-
this.state = {status: BatchStatus.AwaitingDownload, blocks: []};
|
|
477
|
+
this.state = {status: BatchStatus.AwaitingDownload, blocks: [], payloadEnvelopes: null};
|
|
423
478
|
}
|
|
424
479
|
|
|
425
480
|
/** Helper to construct typed BatchError. Stack traces are correct as the error is thrown above */
|