@lodestar/beacon-node 1.50.0-dev.033e6b7138 → 1.50.0-dev.03c05fa09a
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 +13 -3
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/index.js +13 -0
- package/lib/api/impl/beacon/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +4 -4
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/index.js +28 -6
- package/lib/api/impl/beacon/state/index.js.map +1 -1
- package/lib/api/impl/debug/index.d.ts.map +1 -1
- package/lib/api/impl/debug/index.js +26 -18
- package/lib/api/impl/debug/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts +1 -0
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +80 -18
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.d.ts +0 -2
- package/lib/chain/ColumnReconstructionTracker.d.ts.map +1 -1
- package/lib/chain/ColumnReconstructionTracker.js +4 -5
- package/lib/chain/ColumnReconstructionTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +6 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +18 -24
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts +2 -2
- package/lib/chain/archiveStore/historicalState/getHistoricalState.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js +5 -7
- package/lib/chain/archiveStore/historicalState/getHistoricalState.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -2
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/interface.d.ts +1 -1
- package/lib/chain/archiveStore/interface.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts +4 -1
- package/lib/chain/archiveStore/utils/pruneHistory.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/pruneHistory.js +5 -3
- package/lib/chain/archiveStore/utils/pruneHistory.js.map +1 -1
- package/lib/chain/beaconProposerCache.d.ts +6 -0
- package/lib/chain/beaconProposerCache.d.ts.map +1 -1
- package/lib/chain/beaconProposerCache.js +16 -0
- package/lib/chain/beaconProposerCache.js.map +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts +1 -1
- package/lib/chain/blocks/blockInput/blockInput.d.ts.map +1 -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 +25 -12
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +7 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts +2 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +5 -4
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/chain.d.ts +10 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +108 -38
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +7 -1
- 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/envelopeReconstructionError.d.ts +5 -0
- package/lib/chain/errors/envelopeReconstructionError.d.ts.map +1 -1
- package/lib/chain/errors/envelopeReconstructionError.js +2 -0
- package/lib/chain/errors/envelopeReconstructionError.js.map +1 -1
- package/lib/chain/errors/gossipValidation.d.ts +3 -1
- package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
- package/lib/chain/errors/gossipValidation.js +2 -0
- package/lib/chain/errors/gossipValidation.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +2 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/initState.d.ts +2 -9
- package/lib/chain/initState.d.ts.map +1 -1
- package/lib/chain/initState.js +5 -38
- package/lib/chain/initState.js.map +1 -1
- package/lib/chain/interface.d.ts +6 -3
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +4 -2
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +30 -8
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/opPool.d.ts +5 -4
- package/lib/chain/opPools/opPool.d.ts.map +1 -1
- package/lib/chain/opPools/opPool.js +60 -38
- package/lib/chain/opPools/opPool.js.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.d.ts +8 -4
- package/lib/chain/opPools/proposerPreferencesPool.d.ts.map +1 -1
- package/lib/chain/opPools/proposerPreferencesPool.js +27 -12
- package/lib/chain/opPools/proposerPreferencesPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +15 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +33 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/options.d.ts +2 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +1 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +20 -8
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +11 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +54 -36
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/regen.d.ts +2 -0
- package/lib/chain/regen/regen.d.ts.map +1 -1
- package/lib/chain/regen/regen.js +10 -4
- package/lib/chain/regen/regen.js.map +1 -1
- package/lib/chain/reprocess.d.ts +2 -1
- package/lib/chain/reprocess.d.ts.map +1 -1
- package/lib/chain/reprocess.js +2 -1
- package/lib/chain/reprocess.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -0
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +22 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +9 -2
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +23 -13
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/shufflingCache.d.ts +18 -8
- package/lib/chain/shufflingCache.d.ts.map +1 -1
- package/lib/chain/shufflingCache.js +72 -18
- package/lib/chain/shufflingCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts +4 -4
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +3 -0
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.d.ts +3 -3
- package/lib/chain/validation/proposerSlashing.d.ts.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +3 -0
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +5 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +70 -58
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/constants/constants.d.ts +1 -0
- package/lib/constants/constants.d.ts.map +1 -1
- package/lib/constants/constants.js +1 -0
- package/lib/constants/constants.js.map +1 -1
- package/lib/db/beacon.d.ts +4 -1
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +8 -1
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/buckets.d.ts +3 -1
- package/lib/db/buckets.d.ts.map +1 -1
- package/lib/db/buckets.js +2 -0
- package/lib/db/buckets.js.map +1 -1
- package/lib/db/interface.d.ts +4 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +2 -2
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +3 -3
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.js +1 -2
- package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
- package/lib/db/repositories/earliestAvailableSlot.d.ts +11 -0
- package/lib/db/repositories/earliestAvailableSlot.d.ts.map +1 -0
- package/lib/db/repositories/earliestAvailableSlot.js +19 -0
- package/lib/db/repositories/earliestAvailableSlot.js.map +1 -0
- package/lib/db/repositories/index.d.ts +1 -0
- package/lib/db/repositories/index.d.ts.map +1 -1
- package/lib/db/repositories/index.js +1 -0
- package/lib/db/repositories/index.js.map +1 -1
- package/lib/db/repositories/proposerPreferences.d.ts +14 -0
- package/lib/db/repositories/proposerPreferences.d.ts.map +1 -0
- package/lib/db/repositories/proposerPreferences.js +21 -0
- package/lib/db/repositories/proposerPreferences.js.map +1 -0
- package/lib/db/repositories/proposerSlashing.d.ts +1 -0
- package/lib/db/repositories/proposerSlashing.d.ts.map +1 -1
- package/lib/db/repositories/proposerSlashing.js +5 -1
- package/lib/db/repositories/proposerSlashing.js.map +1 -1
- package/lib/execution/engine/blobVersionedHashes.d.ts +9 -0
- package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -0
- package/lib/execution/engine/blobVersionedHashes.js +74 -0
- package/lib/execution/engine/blobVersionedHashes.js.map +1 -0
- package/lib/execution/engine/disabled.d.ts +0 -2
- package/lib/execution/engine/disabled.d.ts.map +1 -1
- package/lib/execution/engine/disabled.js +0 -6
- package/lib/execution/engine/disabled.js.map +1 -1
- package/lib/execution/engine/http.d.ts +46 -16
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +236 -213
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/index.d.ts +3 -2
- package/lib/execution/engine/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +33 -8
- package/lib/execution/engine/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +2 -4
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.d.ts +25 -0
- package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -0
- package/lib/execution/engine/jsonRpcTransport.js +158 -0
- package/lib/execution/engine/jsonRpcTransport.js.map +1 -0
- package/lib/execution/engine/mock.d.ts +0 -2
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +0 -8
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/restHttpClient.d.ts +71 -0
- package/lib/execution/engine/restHttpClient.d.ts.map +1 -0
- package/lib/execution/engine/restHttpClient.js +201 -0
- package/lib/execution/engine/restHttpClient.js.map +1 -0
- package/lib/execution/engine/restTransport.d.ts +46 -0
- package/lib/execution/engine/restTransport.d.ts.map +1 -0
- package/lib/execution/engine/restTransport.js +399 -0
- package/lib/execution/engine/restTransport.js.map +1 -0
- package/lib/execution/engine/sszTypes.d.ts +1261 -0
- package/lib/execution/engine/sszTypes.d.ts.map +1 -0
- package/lib/execution/engine/sszTypes.js +216 -0
- package/lib/execution/engine/sszTypes.js.map +1 -0
- package/lib/execution/engine/transport.d.ts +39 -0
- package/lib/execution/engine/transport.d.ts.map +1 -0
- package/lib/execution/engine/transport.js +2 -0
- package/lib/execution/engine/transport.js.map +1 -0
- package/lib/execution/engine/types.d.ts +2 -8
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +31 -63
- package/lib/execution/engine/types.js.map +1 -1
- package/lib/execution/engine/utils.d.ts.map +1 -1
- package/lib/execution/engine/utils.js +9 -2
- package/lib/execution/engine/utils.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +10 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +22 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/metrics/metrics.d.ts +7 -3
- package/lib/metrics/metrics.d.ts.map +1 -1
- package/lib/metrics/metrics.js +4 -4
- package/lib/metrics/metrics.js.map +1 -1
- package/lib/network/core/events.d.ts +5 -1
- package/lib/network/core/events.d.ts.map +1 -1
- package/lib/network/core/events.js +8 -0
- package/lib/network/core/events.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +0 -14
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +67 -68
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipValidatorFn.d.ts +7 -3
- package/lib/network/processor/gossipValidatorFn.d.ts.map +1 -1
- package/lib/network/processor/gossipValidatorFn.js +7 -3
- package/lib/network/processor/gossipValidatorFn.js.map +1 -1
- package/lib/network/processor/index.d.ts +9 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +80 -13
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js +1 -1
- package/lib/network/reqresp/handlers/executionPayloadEnvelopesByRoot.js.map +1 -1
- package/lib/network/reqresp/rateLimit.js +2 -2
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +3 -1
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/node/nodejs.d.ts +3 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +27 -4
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/notifier.d.ts.map +1 -1
- package/lib/node/notifier.js +12 -13
- package/lib/node/notifier.js.map +1 -1
- package/lib/node/options.d.ts +3 -2
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +2 -2
- package/lib/node/options.js.map +1 -1
- package/lib/sync/range/batch.d.ts +11 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +21 -17
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +4 -4
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +12 -6
- 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 +75 -29
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +14 -7
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +135 -68
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts +38 -14
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +84 -39
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/util/asyncIterableToEvents.d.ts +10 -2
- package/lib/util/asyncIterableToEvents.d.ts.map +1 -1
- package/lib/util/asyncIterableToEvents.js +29 -3
- package/lib/util/asyncIterableToEvents.js.map +1 -1
- package/lib/util/clock.d.ts.map +1 -1
- package/lib/util/clock.js +3 -4
- package/lib/util/clock.js.map +1 -1
- package/lib/util/execution.d.ts +9 -11
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js +5 -1
- package/lib/util/execution.js.map +1 -1
- package/lib/util/metadata.d.ts.map +1 -1
- package/lib/util/metadata.js +2 -1
- package/lib/util/metadata.js.map +1 -1
- package/lib/util/sszBytes.d.ts +2 -2
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +22 -14
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +18 -17
- package/src/api/impl/beacon/blocks/index.ts +17 -7
- package/src/api/impl/beacon/index.ts +15 -0
- package/src/api/impl/beacon/pool/index.ts +4 -4
- package/src/api/impl/beacon/state/index.ts +43 -6
- package/src/api/impl/debug/index.ts +28 -19
- package/src/api/impl/validator/index.ts +102 -21
- package/src/chain/ColumnReconstructionTracker.ts +4 -6
- package/src/chain/archiveStore/archiveStore.ts +26 -26
- package/src/chain/archiveStore/historicalState/getHistoricalState.ts +5 -7
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -2
- package/src/chain/archiveStore/historicalState/worker.ts +1 -2
- package/src/chain/archiveStore/interface.ts +1 -1
- package/src/chain/archiveStore/utils/pruneHistory.ts +9 -4
- package/src/chain/beaconProposerCache.ts +19 -1
- package/src/chain/blocks/blockInput/blockInput.ts +1 -1
- package/src/chain/blocks/importBlock.ts +29 -11
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +2 -1
- package/src/chain/blocks/verifyBlock.ts +8 -6
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +6 -3
- package/src/chain/chain.ts +138 -40
- package/src/chain/emitter.ts +7 -1
- package/src/chain/errors/envelopeReconstructionError.ts +3 -0
- package/src/chain/errors/gossipValidation.ts +2 -0
- package/src/chain/forkChoice/index.ts +2 -0
- package/src/chain/initState.ts +8 -60
- package/src/chain/interface.ts +7 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +34 -10
- package/src/chain/opPools/opPool.ts +89 -46
- package/src/chain/opPools/proposerPreferencesPool.ts +34 -11
- package/src/chain/opPools/utils.ts +62 -3
- package/src/chain/options.ts +3 -3
- package/src/chain/prepareNextSlot.ts +28 -9
- package/src/chain/produceBlock/computeNewStateRoot.ts +10 -3
- package/src/chain/produceBlock/produceBlockBody.ts +86 -40
- package/src/chain/regen/regen.ts +12 -4
- package/src/chain/reprocess.ts +2 -1
- package/src/chain/seenCache/seenGossipBlockInput.ts +25 -1
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +31 -13
- package/src/chain/shufflingCache.ts +84 -22
- package/src/chain/stateCache/persistentCheckpointsCache.ts +4 -1
- package/src/chain/validation/attesterSlashing.ts +7 -4
- package/src/chain/validation/proposerSlashing.ts +7 -4
- package/src/chain/validatorMonitor.ts +82 -61
- package/src/constants/constants.ts +1 -0
- package/src/db/beacon.ts +8 -0
- package/src/db/buckets.ts +2 -0
- package/src/db/interface.ts +4 -0
- package/src/db/repositories/blockArchive.ts +2 -2
- package/src/db/repositories/blockArchiveIndex.ts +2 -3
- package/src/db/repositories/earliestAvailableSlot.ts +19 -0
- package/src/db/repositories/index.ts +1 -0
- package/src/db/repositories/proposerPreferences.ts +23 -0
- package/src/db/repositories/proposerSlashing.ts +6 -1
- package/src/execution/engine/blobVersionedHashes.ts +72 -0
- package/src/execution/engine/disabled.ts +0 -8
- package/src/execution/engine/http.ts +304 -300
- package/src/execution/engine/index.ts +41 -7
- package/src/execution/engine/interface.ts +2 -6
- package/src/execution/engine/jsonRpcTransport.ts +247 -0
- package/src/execution/engine/mock.ts +1 -19
- package/src/execution/engine/restHttpClient.ts +269 -0
- package/src/execution/engine/restTransport.ts +544 -0
- package/src/execution/engine/sszTypes.ts +354 -0
- package/src/execution/engine/transport.ts +61 -0
- package/src/execution/engine/types.ts +42 -90
- package/src/execution/engine/utils.ts +12 -2
- package/src/index.ts +1 -1
- package/src/metrics/metrics/lodestar.ts +23 -0
- package/src/metrics/metrics.ts +21 -6
- package/src/network/core/events.ts +16 -1
- package/src/network/processor/gossipHandlers.ts +98 -81
- package/src/network/processor/gossipValidatorFn.ts +13 -3
- package/src/network/processor/index.ts +92 -13
- package/src/network/reqresp/handlers/executionPayloadEnvelopesByRoot.ts +1 -1
- package/src/network/reqresp/rateLimit.ts +2 -2
- package/src/network/subnets/attnetsService.ts +8 -3
- package/src/node/nodejs.ts +35 -3
- package/src/node/notifier.ts +14 -13
- package/src/node/options.ts +10 -1
- package/src/sync/range/batch.ts +25 -19
- package/src/sync/range/chain.ts +15 -8
- package/src/sync/range/range.ts +76 -30
- package/src/sync/unknownBlock.ts +159 -73
- package/src/sync/utils/downloadByRange.ts +123 -58
- package/src/util/asyncIterableToEvents.ts +44 -5
- package/src/util/clock.ts +3 -4
- package/src/util/execution.ts +16 -8
- package/src/util/metadata.ts +2 -1
- package/src/util/sszBytes.ts +25 -12
package/src/sync/range/range.ts
CHANGED
|
@@ -2,9 +2,10 @@ import {EventEmitter} from "node:events";
|
|
|
2
2
|
import {StrictEventEmitter} from "strict-event-emitter-types";
|
|
3
3
|
import {BeaconConfig} from "@lodestar/config";
|
|
4
4
|
import {IBeaconStateViewGloas, computeStartSlotAtEpoch, isStatePostGloas} from "@lodestar/state-transition";
|
|
5
|
-
import {Epoch, Status, fulu} from "@lodestar/types";
|
|
6
|
-
import {Logger, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
5
|
+
import {Epoch, Status, fulu, ssz} from "@lodestar/types";
|
|
6
|
+
import {Logger, byteArrayEquals, prettyPrintIndices, toRootHex} from "@lodestar/utils";
|
|
7
7
|
import {IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
8
|
+
import {PayloadError, PayloadErrorCode} from "../../chain/blocks/importExecutionPayload.js";
|
|
8
9
|
import {AttestationImportOpt, ImportBlockOpts} from "../../chain/blocks/index.js";
|
|
9
10
|
import {assertLinearChainSegment} from "../../chain/blocks/utils/chainSegment.js";
|
|
10
11
|
import {BlockError} from "../../chain/errors/index.js";
|
|
@@ -15,6 +16,7 @@ import {PeerIdStr} from "../../util/peerId.js";
|
|
|
15
16
|
import {
|
|
16
17
|
DownloadByRangeError,
|
|
17
18
|
DownloadByRangeErrorCode,
|
|
19
|
+
ParentPayload,
|
|
18
20
|
cacheByRangeResponses,
|
|
19
21
|
downloadByRange,
|
|
20
22
|
} from "../utils/downloadByRange.js";
|
|
@@ -207,22 +209,50 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
207
209
|
blsVerifyOnMainThread: false,
|
|
208
210
|
};
|
|
209
211
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
try {
|
|
213
|
+
if (this.opts?.disableProcessAsChainSegment) {
|
|
214
|
+
// Should only be used for debugging or testing
|
|
215
|
+
for (const block of blocks) {
|
|
216
|
+
await this.chain.processBlock(block, flags);
|
|
217
|
+
const payloadEnvelope = payloadEnvelopes?.get(block.slot);
|
|
218
|
+
if (payloadEnvelope?.hasPayloadEnvelope()) {
|
|
219
|
+
await this.chain.processExecutionPayload(payloadEnvelope);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
} else {
|
|
223
|
+
const {orphaned, skipped} = await this.chain.processChainSegment(blocks, payloadEnvelopes, flags);
|
|
224
|
+
// We log orphaned payloads to work with different clients
|
|
225
|
+
// in the future, consider applying penalties in certain conditions
|
|
226
|
+
// make sure the payload source was from range sync in that case
|
|
227
|
+
for (const {slot, payloadEnvelopeInput} of orphaned) {
|
|
228
|
+
const {peerIdStr, source} = payloadEnvelopeInput.getPayloadEnvelopeSource();
|
|
229
|
+
let client = "unknown";
|
|
230
|
+
if (peerIdStr !== undefined) {
|
|
231
|
+
try {
|
|
232
|
+
client = this.getConnectedPeerSyncMeta(peerIdStr).client;
|
|
233
|
+
} catch {
|
|
234
|
+
// peer disconnected since serving the envelope, keep "unknown"
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
this.logger.debug("Orphaned payload envelope in range sync batch", {
|
|
238
|
+
slot,
|
|
239
|
+
root: payloadEnvelopeInput.blockRootHex,
|
|
240
|
+
peer: peerIdStr ?? "unknown",
|
|
241
|
+
source,
|
|
242
|
+
client,
|
|
243
|
+
skipped,
|
|
244
|
+
});
|
|
217
245
|
}
|
|
218
246
|
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
247
|
+
} catch (e) {
|
|
248
|
+
if (
|
|
249
|
+
e instanceof PayloadError &&
|
|
250
|
+
(e.type.code === PayloadErrorCode.INVALID_SIGNATURE ||
|
|
251
|
+
e.type.code === PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR ||
|
|
252
|
+
e.type.code === PayloadErrorCode.EXECUTION_ENGINE_INVALID)
|
|
253
|
+
) {
|
|
254
|
+
const {payloadInput} = e;
|
|
255
|
+
const {peerIdStr, source} = payloadInput.getPayloadEnvelopeSource();
|
|
226
256
|
let client = "unknown";
|
|
227
257
|
if (peerIdStr !== undefined) {
|
|
228
258
|
try {
|
|
@@ -231,30 +261,32 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
231
261
|
// peer disconnected since serving the envelope, keep "unknown"
|
|
232
262
|
}
|
|
233
263
|
}
|
|
234
|
-
this.logger.debug("
|
|
235
|
-
slot,
|
|
236
|
-
root:
|
|
264
|
+
this.logger.debug("Removing invalid payload envelope in range sync batch", {
|
|
265
|
+
slot: payloadInput.slot,
|
|
266
|
+
root: payloadInput.blockRootHex,
|
|
237
267
|
peer: peerIdStr ?? "unknown",
|
|
238
268
|
source,
|
|
239
269
|
client,
|
|
240
|
-
|
|
270
|
+
code: e.type.code,
|
|
241
271
|
});
|
|
272
|
+
// The batch is downloaded again, it would otherwise reuse the cached envelope and fail the same way
|
|
273
|
+
this.chain.seenPayloadEnvelopeInputCache.removeInvalid(payloadInput);
|
|
242
274
|
}
|
|
275
|
+
throw e;
|
|
243
276
|
}
|
|
244
277
|
};
|
|
245
278
|
|
|
246
279
|
private downloadByRange: SyncChainFns["downloadByRange"] = async (peer, batch) => {
|
|
247
280
|
const batchBlocks = batch.getBlocks();
|
|
248
281
|
const requests = batch.getRequestsForPeer(peer);
|
|
249
|
-
const
|
|
250
|
-
const parentPayloadCommitments = parentRoot ? batch.getParentPayloadCommitments(parentRoot) : undefined;
|
|
282
|
+
const parentPayload = requests.parentPayloadRequest ? batch.getParentPayload() : undefined;
|
|
251
283
|
const {result, warnings} = await downloadByRange({
|
|
252
284
|
config: this.config,
|
|
253
285
|
network: this.network,
|
|
254
286
|
logger: this.logger,
|
|
255
287
|
peerIdStr: peer.peerId,
|
|
256
288
|
batchBlocks,
|
|
257
|
-
|
|
289
|
+
parentPayload,
|
|
258
290
|
peerDasMetrics: this.chain.metrics?.peerDas,
|
|
259
291
|
...requests,
|
|
260
292
|
});
|
|
@@ -267,6 +299,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
267
299
|
batchBlocks,
|
|
268
300
|
downloadedPayloadEnvelopes,
|
|
269
301
|
existingPayloadEnvelopes: batch.getPayloadEnvelopes(),
|
|
302
|
+
parentPayload,
|
|
270
303
|
custodyConfig: this.chain.custodyConfig,
|
|
271
304
|
seenTimestampSec: Date.now() / 1000,
|
|
272
305
|
});
|
|
@@ -344,13 +377,26 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
344
377
|
private addPeerOrCreateChain(startEpoch: Epoch, target: ChainTarget, peer: PeerIdStr, syncType: RangeSyncType): void {
|
|
345
378
|
let syncChain = this.chains.get(syncType);
|
|
346
379
|
if (!syncChain) {
|
|
347
|
-
// The first
|
|
348
|
-
//
|
|
349
|
-
// downloaded block's `bid.parentBlockHash` against the head state's `latestExecutionPayloadBid.blockHash`.
|
|
380
|
+
// The first block of the first batch may build on the head's FULL variant before its payload is imported,
|
|
381
|
+
// the batch then downloads the head's payload as dangling parent and validates it against the bid
|
|
350
382
|
const headState = this.chain.getHeadState();
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
383
|
+
let parentPayload: ParentPayload | undefined;
|
|
384
|
+
if (isStatePostGloas(headState) && headState.latestBlockHeader.slot > 0) {
|
|
385
|
+
const header = ssz.phase0.BeaconBlockHeader.clone(headState.latestBlockHeader);
|
|
386
|
+
if (byteArrayEquals(header.stateRoot, ssz.Root.defaultValue())) {
|
|
387
|
+
header.stateRoot = headState.hashTreeRoot();
|
|
388
|
+
}
|
|
389
|
+
const headRoot = ssz.phase0.BeaconBlockHeader.hashTreeRoot(header);
|
|
390
|
+
const headSlot = headState.latestBlockHeader.slot;
|
|
391
|
+
parentPayload = {
|
|
392
|
+
blockRoot: headRoot,
|
|
393
|
+
blockRootHex: toRootHex(headRoot),
|
|
394
|
+
slot: headSlot,
|
|
395
|
+
proposerIndex: headState.latestBlockHeader.proposerIndex,
|
|
396
|
+
forkName: this.config.getForkName(headSlot),
|
|
397
|
+
bid: (headState as IBeaconStateViewGloas).latestExecutionPayloadBid,
|
|
398
|
+
};
|
|
399
|
+
}
|
|
354
400
|
|
|
355
401
|
syncChain = new SyncChain(
|
|
356
402
|
startEpoch,
|
|
@@ -371,7 +417,7 @@ export class RangeSync extends (EventEmitter as {new (): RangeSyncEmitter}) {
|
|
|
371
417
|
custodyConfig: this.chain.custodyConfig,
|
|
372
418
|
metrics: this.metrics,
|
|
373
419
|
},
|
|
374
|
-
|
|
420
|
+
parentPayload
|
|
375
421
|
);
|
|
376
422
|
this.chains.set(syncType, syncChain);
|
|
377
423
|
|
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {ChainEvent, ChainEventData, IBeaconChain} from "../chain/index.js";
|
|
|
15
15
|
import {validateGloasBlockDataColumnSidecars} from "../chain/validation/dataColumnSidecar.js";
|
|
16
16
|
import {validateGossipExecutionPayloadEnvelope} from "../chain/validation/executionPayloadEnvelope.js";
|
|
17
17
|
import {Metrics} from "../metrics/index.js";
|
|
18
|
-
import {INetwork, NetworkEvent, NetworkEventData, prettyPrintPeerIdStr} from "../network/index.js";
|
|
18
|
+
import {INetwork, NetworkEvent, NetworkEventData, PeerAction, prettyPrintPeerIdStr} from "../network/index.js";
|
|
19
19
|
import {PeerSyncMeta} from "../network/peers/peersData.js";
|
|
20
20
|
import {MAX_PEERS_PER_ROOT} from "../network/processor/constants.js";
|
|
21
21
|
import {ClockEvent} from "../util/clock.js";
|
|
@@ -73,7 +73,11 @@ type AdvancePendingBlockResult =
|
|
|
73
73
|
| "removed";
|
|
74
74
|
|
|
75
75
|
class UnknownBlockRateLimitedError extends Error {
|
|
76
|
-
constructor(
|
|
76
|
+
constructor(
|
|
77
|
+
message: string,
|
|
78
|
+
/** Earliest backoff expiry seen when the download was deferred, it is retried once that has passed */
|
|
79
|
+
readonly retryAt: number
|
|
80
|
+
) {
|
|
77
81
|
super(message);
|
|
78
82
|
this.name = "UnknownBlockRateLimitedError";
|
|
79
83
|
}
|
|
@@ -442,6 +446,11 @@ export class BlockInputSync {
|
|
|
442
446
|
};
|
|
443
447
|
|
|
444
448
|
private addByRootHex = (rootHex: RootHex, peerIdStr?: PeerIdStr): boolean => {
|
|
449
|
+
if (this.knownBadBlocks.has(rootHex)) {
|
|
450
|
+
this.logger.debug("Ignoring known bad block root", {root: rootHex, peerIdStr: peerIdStr ?? "unknown peer"});
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
|
|
445
454
|
let pendingBlock = this.pendingBlocks.get(rootHex);
|
|
446
455
|
let added = false;
|
|
447
456
|
if (!pendingBlock) {
|
|
@@ -477,6 +486,11 @@ export class BlockInputSync {
|
|
|
477
486
|
};
|
|
478
487
|
|
|
479
488
|
private addByBlockInput = (blockInput: IBlockInput, peerIdStr?: string): void => {
|
|
489
|
+
if (this.knownBadBlocks.has(blockInput.blockRootHex)) {
|
|
490
|
+
this.logger.debug("Ignoring known bad block", {slot: blockInput.slot, root: blockInput.blockRootHex, peerIdStr});
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
|
|
480
494
|
let pendingBlock = this.pendingBlocks.get(blockInput.blockRootHex);
|
|
481
495
|
// if entry is missing or was added via rootHex and now we have more complete information overwrite
|
|
482
496
|
// the existing information with the more complete cache entry
|
|
@@ -513,6 +527,15 @@ export class BlockInputSync {
|
|
|
513
527
|
};
|
|
514
528
|
|
|
515
529
|
private addByPayloadRootHex = (rootHex: RootHex, peerIdStr?: PeerIdStr, slot?: Slot): boolean => {
|
|
530
|
+
if (this.knownBadBlocks.has(rootHex)) {
|
|
531
|
+
this.logger.debug("Ignoring payload for known bad block root", {
|
|
532
|
+
slot: slot ?? "unknown",
|
|
533
|
+
root: rootHex,
|
|
534
|
+
peerIdStr,
|
|
535
|
+
});
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
|
|
516
539
|
let pendingPayload = this.pendingPayloads.get(rootHex);
|
|
517
540
|
let added = false;
|
|
518
541
|
if (!pendingPayload) {
|
|
@@ -581,6 +604,15 @@ export class BlockInputSync {
|
|
|
581
604
|
peerIdStr?: PeerIdStr,
|
|
582
605
|
envelope?: gloas.SignedExecutionPayloadEnvelope
|
|
583
606
|
): void => {
|
|
607
|
+
if (this.knownBadBlocks.has(payloadInput.blockRootHex)) {
|
|
608
|
+
this.logger.debug("Ignoring payload input for known bad block root", {
|
|
609
|
+
slot: payloadInput.slot,
|
|
610
|
+
root: payloadInput.blockRootHex,
|
|
611
|
+
peerIdStr,
|
|
612
|
+
});
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
|
|
584
616
|
const pendingPayload = this.toPendingPayloadInput(
|
|
585
617
|
payloadInput,
|
|
586
618
|
this.pendingPayloads.get(payloadInput.blockRootHex),
|
|
@@ -654,6 +686,7 @@ export class BlockInputSync {
|
|
|
654
686
|
return {kind: "ready"};
|
|
655
687
|
}
|
|
656
688
|
|
|
689
|
+
// The parent's payload is known but does not match `parentBlockHashHex`
|
|
657
690
|
if (this.chain.forkChoice.hasPayloadHexUnsafe(parentRootHex)) {
|
|
658
691
|
return {kind: "invalidParentPayload", parentRootHex, parentBlockHashHex};
|
|
659
692
|
}
|
|
@@ -820,17 +853,20 @@ export class BlockInputSync {
|
|
|
820
853
|
}
|
|
821
854
|
};
|
|
822
855
|
|
|
823
|
-
|
|
856
|
+
/**
|
|
857
|
+
* Returns false if there is no backoff left to wait for, in which case no retry is scheduled.
|
|
858
|
+
*/
|
|
859
|
+
private scheduleRateLimitBackoffRetry(): boolean {
|
|
824
860
|
this.clearRateLimitBackoffTimer();
|
|
825
861
|
|
|
826
862
|
if (!this.subscribedToNetworkEvents || (this.pendingBlocks.size === 0 && this.pendingPayloads.size === 0)) {
|
|
827
|
-
return;
|
|
863
|
+
return false;
|
|
828
864
|
}
|
|
829
865
|
|
|
830
866
|
const now = Date.now();
|
|
831
867
|
const retryAt = this.peerBalancer.getNextRateLimitRetryAt();
|
|
832
868
|
if (retryAt === null) {
|
|
833
|
-
return;
|
|
869
|
+
return false;
|
|
834
870
|
}
|
|
835
871
|
|
|
836
872
|
this.rateLimitBackoffTimeout = setTimeout(
|
|
@@ -841,6 +877,7 @@ export class BlockInputSync {
|
|
|
841
877
|
},
|
|
842
878
|
Math.max(0, retryAt - now)
|
|
843
879
|
);
|
|
880
|
+
return true;
|
|
844
881
|
}
|
|
845
882
|
|
|
846
883
|
private clearRateLimitBackoffTimer(): void {
|
|
@@ -881,16 +918,17 @@ export class BlockInputSync {
|
|
|
881
918
|
* Poll unknown payloads of the current slot.
|
|
882
919
|
*/
|
|
883
920
|
private async pollPayloadsAtSlot(slot: Slot, signal: AbortSignal): Promise<void> {
|
|
921
|
+
const fork = this.config.getForkName(slot);
|
|
884
922
|
// fixed tick count so the loop cannot outlive its slot: for mainnet, it's 6 ticks
|
|
885
923
|
const tickCount = Math.floor(
|
|
886
|
-
(this.config.
|
|
924
|
+
(this.config.getSlotDurationMs(fork) - this.config.getPayloadDueMs(fork)) / PAYLOAD_POLL_INTERVAL_MS
|
|
887
925
|
);
|
|
888
926
|
// a root still missing on several ticks is searched on each of them, recorded once
|
|
889
927
|
const searchedRoots = new Set<RootHex>();
|
|
890
928
|
let polls = 0;
|
|
891
929
|
|
|
892
930
|
try {
|
|
893
|
-
await sleep(Math.max(0, this.config.getPayloadDueMs() - this.chain.clock.msFromSlot(slot)), signal);
|
|
931
|
+
await sleep(Math.max(0, this.config.getPayloadDueMs(fork) - this.chain.clock.msFromSlot(slot)), signal);
|
|
894
932
|
|
|
895
933
|
for (polls = 0; polls < tickCount; polls++) {
|
|
896
934
|
let importedCount = 0;
|
|
@@ -1032,7 +1070,8 @@ export class BlockInputSync {
|
|
|
1032
1070
|
}
|
|
1033
1071
|
} else if (blockSlot <= finalizedSlot) {
|
|
1034
1072
|
// the common ancestor of the downloading chain and canonical chain should be at least the finalized slot and
|
|
1035
|
-
// we should found it through forkchoice. If not,
|
|
1073
|
+
// we should found it through forkchoice. If not, drop the chain without penalizing peers because pending entries are
|
|
1074
|
+
// block retained on failed download, so finalization can pass the block while it is still pending
|
|
1036
1075
|
// 0 - 1 - ... - n - finalizedSlot
|
|
1037
1076
|
// \
|
|
1038
1077
|
// parent 1 - parent 2 - ... - unknownParent block
|
|
@@ -1040,7 +1079,7 @@ export class BlockInputSync {
|
|
|
1040
1079
|
...logCtx2,
|
|
1041
1080
|
finalizedSlot,
|
|
1042
1081
|
});
|
|
1043
|
-
this.
|
|
1082
|
+
this.removeAllDescendants(block, DroppedItemReason.belowFinalized);
|
|
1044
1083
|
} else {
|
|
1045
1084
|
this.onUnknownBlockRoot({rootHex: pending.blockInput.parentRootHex, source: BlockInputSource.byRoot});
|
|
1046
1085
|
}
|
|
@@ -1051,7 +1090,11 @@ export class BlockInputSync {
|
|
|
1051
1090
|
pendingBlock.status = PendingBlockInputStatus.pending;
|
|
1052
1091
|
}
|
|
1053
1092
|
this.logger.debug("Deferring unknown block download due to peer rate limit", logCtx, res.err);
|
|
1054
|
-
this.scheduleRateLimitBackoffRetry()
|
|
1093
|
+
if (!this.scheduleRateLimitBackoffRetry() || res.err.retryAt <= Date.now()) {
|
|
1094
|
+
// The backoff this download waited for expired in the meantime, a timer is only armed if another
|
|
1095
|
+
// peer is still in backoff and would retry it later than needed
|
|
1096
|
+
this.triggerUnknownBlockSearch();
|
|
1097
|
+
}
|
|
1055
1098
|
return;
|
|
1056
1099
|
}
|
|
1057
1100
|
|
|
@@ -1172,15 +1215,18 @@ export class BlockInputSync {
|
|
|
1172
1215
|
break;
|
|
1173
1216
|
|
|
1174
1217
|
case BlockErrorCode.EXECUTION_ENGINE_INVALID:
|
|
1175
|
-
//
|
|
1218
|
+
// Ban but do not downscore: optimistic-sync peers may forward and serve blocks whose payload is later
|
|
1219
|
+
// rejected by the execution engine. Per the spec, an INVALID execution payload SHOULD NOT cause a peer
|
|
1220
|
+
// to be down-scored or disconnected, only consensus-layer invalidity MAY.
|
|
1221
|
+
// https://github.com/ethereum/consensus-specs/blob/master/specs/bellatrix/p2p-interface.md#the-reqresp-domain
|
|
1176
1222
|
this.logger.debug("Execution engine rejected block from unknown parent sync", errorData, res.err);
|
|
1177
|
-
this.
|
|
1223
|
+
this.removeAndBanAllDescendants(pendingBlock, DroppedItemReason.elInvalid);
|
|
1178
1224
|
break;
|
|
1179
1225
|
|
|
1180
1226
|
default:
|
|
1181
1227
|
// Block is not correct with respect to our chain. Log error loudly
|
|
1182
1228
|
this.logger.debug("Error processing block from unknown parent sync", errorData, res.err);
|
|
1183
|
-
this.
|
|
1229
|
+
this.removeAllDescendants(pendingBlock, DroppedItemReason.invalidBlock);
|
|
1184
1230
|
}
|
|
1185
1231
|
}
|
|
1186
1232
|
|
|
@@ -1331,6 +1377,14 @@ export class BlockInputSync {
|
|
|
1331
1377
|
if (!isPendingPayloadEnvelope(payload)) {
|
|
1332
1378
|
payload.status = PendingPayloadInputStatus.pending;
|
|
1333
1379
|
}
|
|
1380
|
+
if (
|
|
1381
|
+
res.err instanceof UnknownBlockRateLimitedError &&
|
|
1382
|
+
(!this.scheduleRateLimitBackoffRetry() || res.err.retryAt <= Date.now())
|
|
1383
|
+
) {
|
|
1384
|
+
// The backoff this download waited for expired in the meantime, a timer is only armed if another
|
|
1385
|
+
// peer is still in backoff and would retry it later than needed
|
|
1386
|
+
this.triggerUnknownBlockSearch();
|
|
1387
|
+
}
|
|
1334
1388
|
}
|
|
1335
1389
|
|
|
1336
1390
|
private async processPayload(pendingPayload: PendingPayloadInput): Promise<void> {
|
|
@@ -1393,20 +1447,23 @@ export class BlockInputSync {
|
|
|
1393
1447
|
pendingPayload.status = PendingPayloadInputStatus.downloaded;
|
|
1394
1448
|
break;
|
|
1395
1449
|
|
|
1450
|
+
// The invalid envelope is evicted from the seen cache in the cases below, otherwise the next
|
|
1451
|
+
// attempt would reuse it instead of fetching another envelope from peers
|
|
1396
1452
|
case PayloadErrorCode.EXECUTION_ENGINE_INVALID:
|
|
1397
1453
|
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1454
|
+
this.chain.seenPayloadEnvelopeInputCache.removeInvalid(pendingPayload.payloadInput);
|
|
1398
1455
|
this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.elInvalid);
|
|
1399
1456
|
break;
|
|
1400
1457
|
|
|
1401
1458
|
case PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR:
|
|
1402
1459
|
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1460
|
+
this.chain.seenPayloadEnvelopeInputCache.removeInvalid(pendingPayload.payloadInput);
|
|
1403
1461
|
this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.invalidEnvelope);
|
|
1404
1462
|
break;
|
|
1405
1463
|
|
|
1406
1464
|
case PayloadErrorCode.INVALID_SIGNATURE:
|
|
1407
|
-
// TODO GLOAS: Decide how invalid payload inputs should eventually leave memory without
|
|
1408
|
-
// reintroducing envelope replacement / recreation flows.
|
|
1409
1465
|
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1466
|
+
this.chain.seenPayloadEnvelopeInputCache.removeInvalid(pendingPayload.payloadInput);
|
|
1410
1467
|
this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.invalidSignature);
|
|
1411
1468
|
break;
|
|
1412
1469
|
|
|
@@ -1452,16 +1509,21 @@ export class BlockInputSync {
|
|
|
1452
1509
|
const pendingColumns = payloadInput?.hasAllData()
|
|
1453
1510
|
? new Set<number>()
|
|
1454
1511
|
: new Set(payloadInput?.getMissingSampledColumnMeta().missing ?? []);
|
|
1512
|
+
// Same `now` for both calls, a backoff expiring in between would be reported as no peer available
|
|
1513
|
+
const now = Date.now();
|
|
1455
1514
|
// prefer peers that gossiped this payload root to us (#9923)
|
|
1456
1515
|
const peerMeta = this.peerBalancer.bestPeerForPendingColumns(
|
|
1457
1516
|
pendingColumns,
|
|
1458
1517
|
excludedPeers,
|
|
1459
|
-
cacheItem.peerIdStrings
|
|
1518
|
+
cacheItem.peerIdStrings,
|
|
1519
|
+
now
|
|
1460
1520
|
);
|
|
1461
1521
|
if (peerMeta === null) {
|
|
1462
|
-
|
|
1522
|
+
const retryAt = this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers, now);
|
|
1523
|
+
if (retryAt !== null) {
|
|
1463
1524
|
throw new UnknownBlockRateLimitedError(
|
|
1464
|
-
`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited
|
|
1525
|
+
`Error fetching payload by root slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`,
|
|
1526
|
+
retryAt
|
|
1465
1527
|
);
|
|
1466
1528
|
}
|
|
1467
1529
|
|
|
@@ -1478,11 +1540,11 @@ export class BlockInputSync {
|
|
|
1478
1540
|
}
|
|
1479
1541
|
|
|
1480
1542
|
const {peerId, client: peerClient} = peerMeta;
|
|
1481
|
-
cacheItem.peerIdStrings.add(peerId);
|
|
1482
1543
|
|
|
1483
1544
|
try {
|
|
1484
1545
|
if (!envelope) {
|
|
1485
1546
|
envelope = await this.fetchExecutionPayloadEnvelope(peerId, blockRoot, rootHex);
|
|
1547
|
+
cacheItem.peerIdStrings.add(peerId);
|
|
1486
1548
|
const slotWasUnknown = typeof slot !== "number";
|
|
1487
1549
|
slot = envelope.message.payload.slotNumber;
|
|
1488
1550
|
if (slotWasUnknown) {
|
|
@@ -1524,6 +1586,8 @@ export class BlockInputSync {
|
|
|
1524
1586
|
const missing = pendingPayload.payloadInput.getMissingSampledColumnMeta().missing;
|
|
1525
1587
|
if (missing.length > 0) {
|
|
1526
1588
|
const columnSidecars = await this.fetchPayloadColumns(peerMeta, pendingPayload.payloadInput, missing);
|
|
1589
|
+
// toPendingPayloadInput copied cacheItem's set, so add to the object that is carried forward
|
|
1590
|
+
pendingPayload.peerIdStrings.add(peerId);
|
|
1527
1591
|
const seenTimestampSec = Date.now() / 1000;
|
|
1528
1592
|
for (const columnSidecar of columnSidecars) {
|
|
1529
1593
|
if (pendingPayload.payloadInput.hasColumn(columnSidecar.index)) {
|
|
@@ -1598,9 +1662,11 @@ export class BlockInputSync {
|
|
|
1598
1662
|
);
|
|
1599
1663
|
this.metrics?.blockInputSync.payloadFetchPeers.set({result: FetchResult.FailureMaxAttempts}, i - 1);
|
|
1600
1664
|
|
|
1601
|
-
|
|
1665
|
+
const retryAt = deferredByRateLimit ? this.peerBalancer.getNextRateLimitRetryAt() : null;
|
|
1666
|
+
if (retryAt !== null) {
|
|
1602
1667
|
throw new UnknownBlockRateLimitedError(
|
|
1603
|
-
`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited
|
|
1668
|
+
`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts: peers are rate-limited`,
|
|
1669
|
+
retryAt
|
|
1604
1670
|
);
|
|
1605
1671
|
}
|
|
1606
1672
|
throw Error(`Error fetching payload with slot=${slot} root=${rootHex} after ${i - 1} attempts.`);
|
|
@@ -1692,16 +1758,21 @@ export class BlockInputSync {
|
|
|
1692
1758
|
isPendingBlockInput(cacheItem) && isBlockInputColumns(cacheItem.blockInput)
|
|
1693
1759
|
? new Set(cacheItem.blockInput.getMissingSampledColumnMeta().missing)
|
|
1694
1760
|
: defaultPendingColumns;
|
|
1761
|
+
// Same `now` for both calls, a backoff expiring in between would be reported as no peer available
|
|
1762
|
+
const now = Date.now();
|
|
1695
1763
|
// prefer peers that gossiped this block root to us (#9923)
|
|
1696
1764
|
const peerMeta = this.peerBalancer.bestPeerForPendingColumns(
|
|
1697
1765
|
pendingColumns,
|
|
1698
1766
|
excludedPeers,
|
|
1699
|
-
cacheItem.peerIdStrings
|
|
1767
|
+
cacheItem.peerIdStrings,
|
|
1768
|
+
now
|
|
1700
1769
|
);
|
|
1701
1770
|
if (peerMeta === null) {
|
|
1702
|
-
|
|
1771
|
+
const retryAt = this.peerBalancer.getNextRateLimitRetryAt(pendingColumns, excludedPeers, now);
|
|
1772
|
+
if (retryAt !== null) {
|
|
1703
1773
|
throw new UnknownBlockRateLimitedError(
|
|
1704
|
-
`Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited
|
|
1774
|
+
`Error fetching UnknownBlockRoot slot=${slot} root=${rootHex} after ${i}: peers with needed columns are rate-limited`,
|
|
1775
|
+
retryAt
|
|
1705
1776
|
);
|
|
1706
1777
|
}
|
|
1707
1778
|
|
|
@@ -1716,8 +1787,6 @@ export class BlockInputSync {
|
|
|
1716
1787
|
}
|
|
1717
1788
|
const {peerId, client: peerClient} = peerMeta;
|
|
1718
1789
|
|
|
1719
|
-
cacheItem.peerIdStrings.add(peerId);
|
|
1720
|
-
|
|
1721
1790
|
try {
|
|
1722
1791
|
const downloadResult = await downloadByRoot({
|
|
1723
1792
|
config: this.config,
|
|
@@ -1728,6 +1797,7 @@ export class BlockInputSync {
|
|
|
1728
1797
|
cacheItem,
|
|
1729
1798
|
});
|
|
1730
1799
|
cacheItem = downloadResult.result;
|
|
1800
|
+
cacheItem.peerIdStrings.add(peerId);
|
|
1731
1801
|
if (slot === undefined) {
|
|
1732
1802
|
slot = cacheItem.blockInput.slot;
|
|
1733
1803
|
// we were not able to observe the time into slot when starting the fetch, do it now
|
|
@@ -1808,8 +1878,9 @@ export class BlockInputSync {
|
|
|
1808
1878
|
|
|
1809
1879
|
const message = `Error fetching BlockInput with slot=${slot} root=${rootHex} after ${i - 1} attempts.`;
|
|
1810
1880
|
|
|
1811
|
-
|
|
1812
|
-
|
|
1881
|
+
const retryAt = deferredByRateLimit ? this.peerBalancer.getNextRateLimitRetryAt() : null;
|
|
1882
|
+
if (retryAt !== null) {
|
|
1883
|
+
throw new UnknownBlockRateLimitedError(`${message} Peers are rate-limited.`, retryAt);
|
|
1813
1884
|
}
|
|
1814
1885
|
|
|
1815
1886
|
if (!isPendingBlockInput(cacheItem)) {
|
|
@@ -1843,44 +1914,8 @@ export class BlockInputSync {
|
|
|
1843
1914
|
throw Error(message);
|
|
1844
1915
|
}
|
|
1845
1916
|
|
|
1846
|
-
/**
|
|
1847
|
-
* Gets all descendant blocks of `block` recursively from `pendingBlocks`.
|
|
1848
|
-
* Assumes that if a parent block does not exist or is not processable, all descendant blocks are bad too.
|
|
1849
|
-
* Downscore all peers that have referenced any of this bad blocks. May report peers multiple times if they have
|
|
1850
|
-
* referenced more than one bad block.
|
|
1851
|
-
*/
|
|
1852
|
-
private removeAndDownScoreAllDescendants(block: BlockInputSyncCacheItem, headReason: DroppedItemReason): void {
|
|
1853
|
-
// Get all blocks that are a descendant of this one
|
|
1854
|
-
const badPendingBlocks = this.removeAllDescendants(block, headReason, DroppedItemReason.invalidParent);
|
|
1855
|
-
// just console log and do not penalize on pending/bad blocks for debugging
|
|
1856
|
-
// console.log("removeAndDownscoreAllDescendants", {block});
|
|
1857
|
-
|
|
1858
|
-
for (const block of badPendingBlocks) {
|
|
1859
|
-
//
|
|
1860
|
-
// TODO(fulu): why is this commented out here?
|
|
1861
|
-
//
|
|
1862
|
-
// this.knownBadBlocks.add(block.blockRootHex);
|
|
1863
|
-
// for (const peerIdStr of block.peerIdStrings) {
|
|
1864
|
-
// // TODO: Refactor peerRpcScores to work with peerIdStr only
|
|
1865
|
-
// this.network.reportPeer(peerIdStr, PeerAction.LowToleranceError, "BadBlockByRoot");
|
|
1866
|
-
// }
|
|
1867
|
-
this.logger.debug("ignored Banning unknown block", {
|
|
1868
|
-
slot: getBlockInputSyncCacheItemSlot(block),
|
|
1869
|
-
root: getBlockInputSyncCacheItemRootHex(block),
|
|
1870
|
-
peerIdStrings: Array.from(block.peerIdStrings)
|
|
1871
|
-
.map((id) => prettyPrintPeerIdStr(id))
|
|
1872
|
-
.join(","),
|
|
1873
|
-
});
|
|
1874
|
-
}
|
|
1875
|
-
|
|
1876
|
-
// Prune knownBadBlocks
|
|
1877
|
-
pruneSetToMax(this.knownBadBlocks, MAX_KNOWN_BAD_BLOCKS);
|
|
1878
|
-
}
|
|
1879
|
-
|
|
1880
1917
|
// Once a parent payload is invalid, every descendant waiting on that payload lineage becomes unrecoverable too.
|
|
1881
1918
|
private removePendingPayloadAndDescendants(rootHex: RootHex, headReason: DroppedItemReason): void {
|
|
1882
|
-
// Keep PayloadEnvelopeInput resident in the seen cache. importBlock() owns that object and
|
|
1883
|
-
// later validation/finalization logic decides when it can leave memory.
|
|
1884
1919
|
if (this.pendingPayloads.delete(rootHex)) {
|
|
1885
1920
|
this.metrics?.blockInputSync.removedPayloads.inc({reason: headReason}, 1);
|
|
1886
1921
|
}
|
|
@@ -1903,13 +1938,61 @@ export class BlockInputSync {
|
|
|
1903
1938
|
}
|
|
1904
1939
|
}
|
|
1905
1940
|
|
|
1941
|
+
/**
|
|
1942
|
+
* Same as `removeAndBanAllDescendants`, and downscores every peer that referenced or served a banned item, once per
|
|
1943
|
+
* peer. Only call for consensus-layer invalidity, never for an INVALID execution payload:
|
|
1944
|
+
* https://github.com/ethereum/consensus-specs/blob/master/specs/bellatrix/p2p-interface.md#the-reqresp-domain
|
|
1945
|
+
*/
|
|
1946
|
+
private removeAndDownScoreAllDescendants(block: BlockInputSyncCacheItem, headReason: DroppedItemReason): void {
|
|
1947
|
+
const peersToReport = new Set<PeerIdStr>();
|
|
1948
|
+
for (const bannedBlock of this.removeAndBanAllDescendants(block, headReason)) {
|
|
1949
|
+
for (const peerIdStr of bannedBlock.peerIdStrings) {
|
|
1950
|
+
peersToReport.add(peerIdStr);
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
for (const peerIdStr of peersToReport) {
|
|
1955
|
+
this.network.reportPeer(peerIdStr, PeerAction.LowToleranceError, headReason);
|
|
1956
|
+
}
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
/**
|
|
1960
|
+
* Removes `block` and all its pending descendants and bans their roots in `knownBadBlocks`. Only call when the chain
|
|
1961
|
+
* is provably bad: a banned root is never searched for again. Returns the banned items.
|
|
1962
|
+
*/
|
|
1963
|
+
private removeAndBanAllDescendants(
|
|
1964
|
+
block: BlockInputSyncCacheItem,
|
|
1965
|
+
headReason: DroppedItemReason
|
|
1966
|
+
): BlockInputSyncCacheItem[] {
|
|
1967
|
+
const bannedBlocks: BlockInputSyncCacheItem[] = [];
|
|
1968
|
+
for (const badBlock of this.removeAllDescendants(block, headReason, DroppedItemReason.invalidParent)) {
|
|
1969
|
+
const rootHex = getBlockInputSyncCacheItemRootHex(badBlock);
|
|
1970
|
+
// a gossip import may race a failing sync path, never ban a root fork choice has imported
|
|
1971
|
+
if (this.chain.forkChoice.hasBlockHex(rootHex)) {
|
|
1972
|
+
continue;
|
|
1973
|
+
}
|
|
1974
|
+
this.knownBadBlocks.add(rootHex);
|
|
1975
|
+
bannedBlocks.push(badBlock);
|
|
1976
|
+
this.logger.debug("Banning unknown block", {
|
|
1977
|
+
slot: getBlockInputSyncCacheItemSlot(badBlock),
|
|
1978
|
+
root: rootHex,
|
|
1979
|
+
reason: headReason,
|
|
1980
|
+
peerIdStrings: Array.from(badBlock.peerIdStrings)
|
|
1981
|
+
.map((id) => prettyPrintPeerIdStr(id))
|
|
1982
|
+
.join(","),
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1986
|
+
pruneSetToMax(this.knownBadBlocks, MAX_KNOWN_BAD_BLOCKS);
|
|
1987
|
+
return bannedBlocks;
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1906
1990
|
private removeAllDescendants(
|
|
1907
1991
|
block: BlockInputSyncCacheItem,
|
|
1908
1992
|
headReason: DroppedItemReason,
|
|
1909
1993
|
descendantReason: DroppedItemReason = DroppedItemReason.invalidParent
|
|
1910
1994
|
): BlockInputSyncCacheItem[] {
|
|
1911
1995
|
const rootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
1912
|
-
const slot = getBlockInputSyncCacheItemSlot(block);
|
|
1913
1996
|
// Get all blocks that are a descendant of this one (index 0 is the head item itself)
|
|
1914
1997
|
const badPendingBlocks = [block, ...getAllDescendantBlocks(rootHex, this.pendingBlocks)];
|
|
1915
1998
|
|
|
@@ -1926,8 +2009,8 @@ export class BlockInputSync {
|
|
|
1926
2009
|
// Keep PayloadEnvelopeInput resident in the seen cache for consistency with the
|
|
1927
2010
|
// importBlock()-owned lifecycle.
|
|
1928
2011
|
this.logger.debug("Removing bad/unknown/incomplete BlockInputSyncCacheItem", {
|
|
1929
|
-
slot,
|
|
1930
|
-
|
|
2012
|
+
slot: getBlockInputSyncCacheItemSlot(block),
|
|
2013
|
+
root: rootHex,
|
|
1931
2014
|
});
|
|
1932
2015
|
}
|
|
1933
2016
|
|
|
@@ -1988,8 +2071,11 @@ export class UnknownBlockPeerBalancer {
|
|
|
1988
2071
|
this.rateLimitedUntilByPeer.set(peerId, rateLimitedUntilMs);
|
|
1989
2072
|
}
|
|
1990
2073
|
|
|
1991
|
-
getNextRateLimitRetryAt(
|
|
1992
|
-
|
|
2074
|
+
getNextRateLimitRetryAt(
|
|
2075
|
+
pendingColumns?: Set<number>,
|
|
2076
|
+
excludedPeers?: Set<PeerIdStr>,
|
|
2077
|
+
now = Date.now()
|
|
2078
|
+
): number | null {
|
|
1993
2079
|
let retryAt: number | null = null;
|
|
1994
2080
|
|
|
1995
2081
|
for (const [peerId, rateLimitedUntil] of this.rateLimitedUntilByPeer.entries()) {
|
|
@@ -2028,9 +2114,10 @@ export class UnknownBlockPeerBalancer {
|
|
|
2028
2114
|
bestPeerForPendingColumns(
|
|
2029
2115
|
pendingColumns: Set<number>,
|
|
2030
2116
|
excludedPeers: Set<PeerIdStr>,
|
|
2031
|
-
preferredPeers?: Set<PeerIdStr
|
|
2117
|
+
preferredPeers?: Set<PeerIdStr>,
|
|
2118
|
+
now = Date.now()
|
|
2032
2119
|
): PeerSyncMeta | null {
|
|
2033
|
-
const eligiblePeers = this.filterPeers(pendingColumns, excludedPeers);
|
|
2120
|
+
const eligiblePeers = this.filterPeers(pendingColumns, excludedPeers, now);
|
|
2034
2121
|
if (eligiblePeers.length === 0) {
|
|
2035
2122
|
return null;
|
|
2036
2123
|
}
|
|
@@ -2071,8 +2158,7 @@ export class UnknownBlockPeerBalancer {
|
|
|
2071
2158
|
return totalActiveRequests;
|
|
2072
2159
|
}
|
|
2073
2160
|
|
|
2074
|
-
private filterPeers(pendingDataColumns: Set<number>, excludedPeers: Set<PeerIdStr
|
|
2075
|
-
const now = Date.now();
|
|
2161
|
+
private filterPeers(pendingDataColumns: Set<number>, excludedPeers: Set<PeerIdStr>, now: number): PeerIdStr[] {
|
|
2076
2162
|
let maxColumnCount = 0;
|
|
2077
2163
|
const considerPeers: {peerId: PeerIdStr; columnCount: number}[] = [];
|
|
2078
2164
|
for (const [peerId, syncMeta] of this.peersMeta.entries()) {
|