@lodestar/beacon-node 1.51.0-dev.ab56d90f0c → 1.51.0-dev.ab8f3f6381
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/api.js +1 -1
- package/lib/api/impl/api.js.map +1 -1
- package/lib/api/impl/beacon/blocks/index.d.ts +2 -1
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +29 -34
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/index.d.ts +2 -1
- package/lib/api/impl/beacon/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/index.js +2 -2
- package/lib/api/impl/beacon/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +22 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/validator/index.d.ts +6 -0
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +42 -26
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/api/options.d.ts +2 -0
- package/lib/api/options.d.ts.map +1 -1
- package/lib/api/options.js +1 -0
- package/lib/api/options.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +13 -2
- package/lib/chain/GetBlobsTracker.d.ts.map +1 -1
- package/lib/chain/GetBlobsTracker.js +85 -27
- package/lib/chain/GetBlobsTracker.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -0
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +4 -0
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +61 -97
- 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 +39 -50
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +10 -11
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +32 -18
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +4 -4
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts +12 -9
- package/lib/chain/blocks/payloadEnvelopeProcessor.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeProcessor.js +24 -19
- package/lib/chain/blocks/payloadEnvelopeProcessor.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +4 -1
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +18 -7
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js +8 -1
- package/lib/chain/blocks/verifyBlocksDataAvailability.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts +1 -1
- package/lib/chain/blocks/verifyBlocksExecutionPayloads.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSanityChecks.js +4 -0
- package/lib/chain/blocks/verifyBlocksSanityChecks.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksSignatures.js +7 -5
- package/lib/chain/blocks/verifyBlocksSignatures.js.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts +3 -3
- package/lib/chain/blocks/verifyPayloadsDataAvailability.d.ts.map +1 -1
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js +11 -6
- package/lib/chain/blocks/verifyPayloadsDataAvailability.js.map +1 -1
- package/lib/chain/bls/interface.d.ts +2 -0
- package/lib/chain/bls/interface.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +13 -11
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/types.d.ts +1 -1
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/worker.js +1 -1
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.js +1 -1
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.js +1 -1
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +25 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +123 -10
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +6 -0
- 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/blockError.d.ts +1 -1
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +1 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +7 -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/forkChoice/index.d.ts +11 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +11 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/forkChoiceExecutionEngine.d.ts +53 -0
- package/lib/chain/forkChoiceExecutionEngine.d.ts.map +1 -0
- package/lib/chain/forkChoiceExecutionEngine.js +121 -0
- package/lib/chain/forkChoiceExecutionEngine.js.map +1 -0
- package/lib/chain/interface.d.ts +9 -6
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts +17 -4
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +199 -46
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +1 -1
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +15 -4
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/index.d.ts +1 -0
- package/lib/chain/opPools/index.d.ts.map +1 -1
- package/lib/chain/opPools/index.js +1 -0
- package/lib/chain/opPools/index.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +17 -7
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/singleAttestationPool.d.ts +77 -0
- package/lib/chain/opPools/singleAttestationPool.d.ts.map +1 -0
- package/lib/chain/opPools/singleAttestationPool.js +209 -0
- package/lib/chain/opPools/singleAttestationPool.js.map +1 -0
- package/lib/chain/opPools/syncCommitteeMessagePool.d.ts.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +9 -3
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.d.ts.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +11 -3
- package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +1 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +1 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/options.d.ts +5 -1
- package/lib/chain/options.d.ts.map +1 -1
- package/lib/chain/options.js +0 -1
- package/lib/chain/options.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +3 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +3 -2
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/proposerTracker.d.ts +31 -0
- package/lib/chain/proposerTracker.d.ts.map +1 -0
- package/lib/chain/proposerTracker.js +75 -0
- package/lib/chain/proposerTracker.js.map +1 -0
- package/lib/chain/regen/interface.d.ts +1 -2
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +0 -1
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +1 -1
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +5 -3
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +0 -15
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -166
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/db/beacon.d.ts +7 -0
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +34 -0
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +1 -1
- package/lib/db/dataColumnStore.d.ts.map +1 -1
- package/lib/db/dataColumnStore.js +1 -4
- package/lib/db/dataColumnStore.js.map +1 -1
- package/lib/db/flatFileStore/flatFileStore.js +5 -5
- package/lib/db/flatFileStore/flatFileStore.js.map +1 -1
- package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -1
- package/lib/db/flatFileStore/slotIndex.js +2 -2
- package/lib/db/flatFileStore/slotIndex.js.map +1 -1
- package/lib/db/interface.d.ts +1 -0
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts +6 -0
- package/lib/db/repositories/dataColumnSidecarArchive.d.ts.map +1 -1
- package/lib/db/repositories/dataColumnSidecarArchive.js +19 -0
- package/lib/db/repositories/dataColumnSidecarArchive.js.map +1 -1
- package/lib/execution/builder/apiClient.d.ts +14 -8
- package/lib/execution/builder/apiClient.d.ts.map +1 -1
- package/lib/execution/builder/apiClient.js +12 -10
- package/lib/execution/builder/apiClient.js.map +1 -1
- package/lib/execution/builder/http.d.ts +2 -0
- package/lib/execution/builder/http.d.ts.map +1 -1
- package/lib/execution/builder/http.js +2 -0
- package/lib/execution/builder/http.js.map +1 -1
- package/lib/execution/engine/http.d.ts +2 -2
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +5 -4
- package/lib/execution/engine/http.js.map +1 -1
- package/lib/execution/engine/index.d.ts +1 -1
- package/lib/execution/engine/index.d.ts.map +1 -1
- package/lib/execution/engine/index.js +1 -1
- package/lib/execution/engine/index.js.map +1 -1
- package/lib/execution/engine/interface.d.ts +17 -3
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/interface.js.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.d.ts +2 -2
- package/lib/execution/engine/jsonRpcTransport.d.ts.map +1 -1
- package/lib/execution/engine/jsonRpcTransport.js +1 -1
- package/lib/execution/engine/jsonRpcTransport.js.map +1 -1
- package/lib/execution/engine/restTransport.d.ts +2 -2
- package/lib/execution/engine/restTransport.d.ts.map +1 -1
- package/lib/execution/engine/restTransport.js.map +1 -1
- package/lib/execution/engine/transport.d.ts +1 -12
- package/lib/execution/engine/transport.d.ts.map +1 -1
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +2 -2
- 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 +3 -2
- package/lib/execution/engine/utils.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +33 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +84 -0
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/metrics/server/http.js +5 -5
- package/lib/metrics/server/http.js.map +1 -1
- package/lib/monitoring/service.js +1 -1
- package/lib/monitoring/service.js.map +1 -1
- package/lib/network/core/networkCore.d.ts +4 -1
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js +7 -0
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorker.js +2 -0
- package/lib/network/core/networkCoreWorker.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +4 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.js +6 -0
- package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
- package/lib/network/core/types.d.ts +6 -1
- package/lib/network/core/types.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.d.ts +1 -0
- package/lib/network/gossip/gossipsub.d.ts.map +1 -1
- package/lib/network/gossip/gossipsub.js +10 -0
- package/lib/network/gossip/gossipsub.js.map +1 -1
- package/lib/network/interface.d.ts +2 -0
- package/lib/network/interface.d.ts.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +5 -1
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts +6 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +53 -15
- package/lib/network/network.js.map +1 -1
- package/lib/network/options.d.ts +2 -0
- package/lib/network/options.d.ts.map +1 -1
- package/lib/network/options.js +2 -0
- package/lib/network/options.js.map +1 -1
- package/lib/network/peers/peerManager.d.ts +2 -1
- package/lib/network/peers/peerManager.d.ts.map +1 -1
- package/lib/network/peers/peerManager.js +28 -1
- package/lib/network/peers/peerManager.js.map +1 -1
- package/lib/network/peers/utils/assertPeerRelevance.d.ts +9 -1
- package/lib/network/peers/utils/assertPeerRelevance.d.ts.map +1 -1
- package/lib/network/peers/utils/assertPeerRelevance.js +32 -21
- package/lib/network/peers/utils/assertPeerRelevance.js.map +1 -1
- package/lib/network/peers/utils/prioritizePeers.d.ts +4 -1
- package/lib/network/peers/utils/prioritizePeers.d.ts.map +1 -1
- package/lib/network/peers/utils/prioritizePeers.js +8 -16
- package/lib/network/peers/utils/prioritizePeers.js.map +1 -1
- package/lib/network/peers/utils/subnetMap.d.ts +5 -2
- package/lib/network/peers/utils/subnetMap.d.ts.map +1 -1
- package/lib/network/peers/utils/subnetMap.js +6 -3
- package/lib/network/peers/utils/subnetMap.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +77 -37
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +6 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +29 -3
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/subnets/attnetsService.d.ts +35 -5
- package/lib/network/subnets/attnetsService.d.ts.map +1 -1
- package/lib/network/subnets/attnetsService.js +84 -6
- package/lib/network/subnets/attnetsService.js.map +1 -1
- package/lib/network/subnets/interface.d.ts +7 -0
- package/lib/network/subnets/interface.d.ts.map +1 -1
- package/lib/network/subnets/interface.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 +47 -21
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/options.d.ts +3 -1
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +4 -2
- package/lib/node/options.js.map +1 -1
- package/lib/sync/interface.d.ts.map +1 -1
- package/lib/sync/interface.js.map +1 -1
- package/lib/sync/sync.d.ts +7 -0
- package/lib/sync/sync.d.ts.map +1 -1
- package/lib/sync/sync.js +61 -3
- package/lib/sync/sync.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +42 -18
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/execution.d.ts +4 -4
- package/lib/util/execution.d.ts.map +1 -1
- package/lib/util/execution.js.map +1 -1
- package/lib/util/file.d.ts.map +1 -1
- package/lib/util/file.js +8 -9
- package/lib/util/file.js.map +1 -1
- package/lib/util/queue/itemQueue.js +1 -1
- package/lib/util/queue/itemQueue.js.map +1 -1
- package/lib/util/sszBytes.d.ts +5 -0
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +35 -2
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +16 -17
- package/src/api/impl/api.ts +1 -1
- package/src/api/impl/beacon/blocks/index.ts +57 -62
- package/src/api/impl/beacon/index.ts +3 -1
- package/src/api/impl/beacon/pool/index.ts +31 -1
- package/src/api/impl/beacon/state/utils.ts +1 -1
- package/src/api/impl/validator/index.ts +47 -30
- package/src/api/options.ts +3 -0
- package/src/chain/GetBlobsTracker.ts +99 -40
- package/src/chain/archiveStore/archiveStore.ts +1 -0
- package/src/chain/archiveStore/utils/archiveBlocks.ts +76 -130
- package/src/chain/blocks/importBlock.ts +60 -71
- package/src/chain/blocks/importExecutionPayload.ts +55 -34
- package/src/chain/blocks/index.ts +11 -4
- package/src/chain/blocks/payloadEnvelopeProcessor.ts +35 -24
- package/src/chain/blocks/types.ts +4 -1
- package/src/chain/blocks/verifyBlock.ts +31 -16
- package/src/chain/blocks/verifyBlocksDataAvailability.ts +10 -1
- package/src/chain/blocks/verifyBlocksExecutionPayloads.ts +1 -1
- package/src/chain/blocks/verifyBlocksSanityChecks.ts +4 -1
- package/src/chain/blocks/verifyBlocksSignatures.ts +7 -5
- package/src/chain/blocks/verifyPayloadsDataAvailability.ts +14 -6
- package/src/chain/bls/interface.ts +2 -0
- package/src/chain/bls/multithread/index.ts +14 -10
- package/src/chain/bls/multithread/types.ts +1 -1
- package/src/chain/bls/multithread/worker.ts +1 -5
- package/src/chain/bls/singleThread.ts +1 -1
- package/src/chain/bls/utils.ts +1 -1
- package/src/chain/chain.ts +139 -8
- package/src/chain/emitter.ts +7 -0
- package/src/chain/errors/blockError.ts +1 -1
- package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
- package/src/chain/forkChoice/index.ts +11 -0
- package/src/chain/forkChoiceExecutionEngine.ts +197 -0
- package/src/chain/interface.ts +9 -5
- package/src/chain/opPools/aggregatedAttestationPool.ts +246 -43
- package/src/chain/opPools/attestationPool.ts +16 -4
- package/src/chain/opPools/index.ts +1 -0
- package/src/chain/opPools/payloadAttestationPool.ts +18 -7
- package/src/chain/opPools/singleAttestationPool.ts +287 -0
- package/src/chain/opPools/syncCommitteeMessagePool.ts +10 -3
- package/src/chain/opPools/syncContributionAndProofPool.ts +13 -3
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/options.ts +5 -2
- package/src/chain/produceBlock/produceBlockBody.ts +7 -3
- package/src/chain/proposerTracker.ts +94 -0
- package/src/chain/regen/interface.ts +1 -2
- package/src/chain/regen/queued.ts +6 -4
- package/src/chain/validation/executionPayloadBid.ts +14 -193
- package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
- package/src/db/beacon.ts +44 -0
- package/src/db/dataColumnStore.ts +2 -4
- package/src/db/flatFileStore/flatFileStore.ts +7 -7
- package/src/db/flatFileStore/slotIndex.ts +4 -3
- package/src/db/interface.ts +2 -0
- package/src/db/repositories/dataColumnSidecarArchive.ts +20 -0
- package/src/execution/builder/apiClient.ts +16 -13
- package/src/execution/builder/http.ts +4 -0
- package/src/execution/engine/http.ts +12 -13
- package/src/execution/engine/index.ts +1 -1
- package/src/execution/engine/interface.ts +19 -3
- package/src/execution/engine/jsonRpcTransport.ts +10 -2
- package/src/execution/engine/restTransport.ts +3 -1
- package/src/execution/engine/transport.ts +8 -14
- package/src/execution/engine/types.ts +3 -1
- package/src/execution/engine/utils.ts +4 -2
- package/src/index.ts +2 -0
- package/src/metrics/metrics/lodestar.ts +85 -0
- package/src/metrics/server/http.ts +5 -5
- package/src/monitoring/service.ts +1 -1
- package/src/network/core/networkCore.ts +11 -1
- package/src/network/core/networkCoreWorker.ts +2 -0
- package/src/network/core/networkCoreWorkerHandler.ts +8 -1
- package/src/network/core/types.ts +6 -1
- package/src/network/gossip/gossipsub.ts +11 -0
- package/src/network/interface.ts +2 -0
- package/src/network/libp2p/index.ts +5 -1
- package/src/network/network.ts +55 -19
- package/src/network/options.ts +4 -0
- package/src/network/peers/peerManager.ts +28 -3
- package/src/network/peers/utils/assertPeerRelevance.ts +39 -23
- package/src/network/peers/utils/prioritizePeers.ts +14 -22
- package/src/network/peers/utils/subnetMap.ts +6 -3
- package/src/network/processor/gossipHandlers.ts +98 -40
- package/src/network/processor/index.ts +25 -3
- package/src/network/subnets/attnetsService.ts +94 -6
- package/src/network/subnets/interface.ts +7 -0
- package/src/node/nodejs.ts +58 -22
- package/src/node/options.ts +9 -6
- package/src/sync/interface.ts +1 -0
- package/src/sync/sync.ts +65 -4
- package/src/sync/unknownBlock.ts +47 -28
- package/src/util/execution.ts +6 -6
- package/src/util/file.ts +8 -9
- package/src/util/queue/itemQueue.ts +1 -1
- package/src/util/sszBytes.ts +42 -2
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
deneb,
|
|
25
25
|
fulu,
|
|
26
26
|
gloas,
|
|
27
|
+
isGloasBeaconBlock,
|
|
27
28
|
isGloasDataColumnSidecar,
|
|
28
29
|
ssz,
|
|
29
30
|
sszTypesFor,
|
|
@@ -65,7 +66,10 @@ import {
|
|
|
65
66
|
validateGossipGloasDataColumnSidecar,
|
|
66
67
|
} from "../../chain/validation/dataColumnSidecar.js";
|
|
67
68
|
import {validateGossipExecutionPayloadBid} from "../../chain/validation/executionPayloadBid.js";
|
|
68
|
-
import {
|
|
69
|
+
import {
|
|
70
|
+
validateGossipExecutionPayloadEnvelope,
|
|
71
|
+
validateGossipExecutionPayloadEnvelopeSerialized,
|
|
72
|
+
} from "../../chain/validation/executionPayloadEnvelope.js";
|
|
69
73
|
import {InclusionListValidationResult, validateGossipInclusionList} from "../../chain/validation/inclusionList.js";
|
|
70
74
|
import {
|
|
71
75
|
AggregateAndProofValidationResult,
|
|
@@ -150,6 +154,31 @@ export function getGossipHandlers(modules: ValidatorFnsModules, options: GossipH
|
|
|
150
154
|
*/
|
|
151
155
|
function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): SequentialGossipHandlers {
|
|
152
156
|
const {chain, config, metrics, logger, core} = modules;
|
|
157
|
+
const incompletePayloadWaits = new WeakSet<PayloadEnvelopeInput>();
|
|
158
|
+
|
|
159
|
+
function scheduleIncompletePayloadEnvelope(payloadInput: PayloadEnvelopeInput, peer: string): void {
|
|
160
|
+
if (payloadInput.isComplete() || incompletePayloadWaits.has(payloadInput)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
incompletePayloadWaits.add(payloadInput);
|
|
164
|
+
|
|
165
|
+
const fork = config.getForkName(payloadInput.slot);
|
|
166
|
+
const cutoffTimeMs = getCutoffTimeMs(chain, payloadInput.slot, config.getPayloadDueMs(fork));
|
|
167
|
+
payloadInput.waitForEnvelopeAndAllData(cutoffTimeMs).catch(() => {
|
|
168
|
+
if (
|
|
169
|
+
payloadInput.isComplete() ||
|
|
170
|
+
chain.seenPayloadEnvelopeInputCache.get(payloadInput.blockRootHex) !== payloadInput
|
|
171
|
+
) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
chain.logger.debug("Payload envelope incomplete at payload deadline", payloadInput.getLogMeta());
|
|
175
|
+
chain.emitter.emit(ChainEvent.incompletePayloadEnvelope, {
|
|
176
|
+
payloadInput,
|
|
177
|
+
peer,
|
|
178
|
+
source: BlockInputSource.gossip,
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
153
182
|
|
|
154
183
|
/**
|
|
155
184
|
* Add a gossip block to the seen caches. The proposer signature of the block MUST be verified.
|
|
@@ -679,10 +708,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
679
708
|
|
|
680
709
|
// Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
|
|
681
710
|
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
682
|
-
//
|
|
683
|
-
//
|
|
684
|
-
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
685
|
-
// in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
|
|
711
|
+
// Columns fetched here feed payloadInput.addColumn, which resolves the waitForAllData of a
|
|
712
|
+
// pending payload import. No processExecutionPayload trigger needed from this path.
|
|
686
713
|
chain.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
687
714
|
}
|
|
688
715
|
})
|
|
@@ -692,11 +719,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
692
719
|
|
|
693
720
|
if (e instanceof BlockError) {
|
|
694
721
|
switch (e.type.code) {
|
|
695
|
-
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
696
|
-
//
|
|
722
|
+
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
723
|
+
// Data did not arrive in time, BlockInputSync keeps pulling it and retries the import
|
|
697
724
|
logLevel = LogLevel.debug;
|
|
698
725
|
break;
|
|
699
|
-
}
|
|
700
726
|
// ALREADY_KNOWN should not happen with ignoreIfKnown=true above
|
|
701
727
|
// PARENT_BLOCK_UNKNOWN should not happen, we handled this in validateBeaconBlock() function above
|
|
702
728
|
case BlockErrorCode.ALREADY_KNOWN:
|
|
@@ -764,7 +790,12 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
764
790
|
// roots per proposer and slot, which bounds full imports over gossip to one alternate
|
|
765
791
|
chain.seenBlockProposers.hasBlockRoot(signedBlock.message.slot, e.type.proposerIndex, e.type.root) &&
|
|
766
792
|
// A sibling with an unknown parent cannot be imported, sync fetches it if its branch becomes relevant
|
|
767
|
-
chain.forkChoice.getBlockHexDefaultStatus(toRootHex(signedBlock.message.parentRoot)) !== null
|
|
793
|
+
chain.forkChoice.getBlockHexDefaultStatus(toRootHex(signedBlock.message.parentRoot)) !== null &&
|
|
794
|
+
(!isGloasBeaconBlock(signedBlock.message) ||
|
|
795
|
+
chain.forkChoice.getBlockHexAndBlockHash(
|
|
796
|
+
toRootHex(signedBlock.message.parentRoot),
|
|
797
|
+
toRootHex(signedBlock.message.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
798
|
+
) !== null)
|
|
768
799
|
) {
|
|
769
800
|
const blockInput = cacheSignatureVerifiedBlock(
|
|
770
801
|
signedBlock,
|
|
@@ -899,28 +930,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
899
930
|
}
|
|
900
931
|
|
|
901
932
|
// NOTE: we do NOT call chain.processExecutionPayload here. That is triggered only by
|
|
902
|
-
// envelope arrival (gossip or API).
|
|
933
|
+
// envelope arrival (gossip or API). A pending payload import is awaiting
|
|
903
934
|
// payloadInput.waitForAllData(); addColumn above will resolve it once hasAllData flips.
|
|
904
935
|
|
|
905
|
-
|
|
906
|
-
const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
|
|
907
|
-
// do not await here to not delay gossip validation
|
|
908
|
-
payloadInput.waitForEnvelopeAndAllData(cutoffTimeMs).catch((_e) => {
|
|
909
|
-
chain.logger.debug(
|
|
910
|
-
"Waited for envelope and data after receiving gossip column. Cut-off reached so emitting incompletePayloadEnvelope",
|
|
911
|
-
{
|
|
912
|
-
dataColumnIndex: index,
|
|
913
|
-
...payloadInputMeta,
|
|
914
|
-
}
|
|
915
|
-
);
|
|
916
|
-
// TODO GLOAS: UnknownBlockSync to handle this event
|
|
917
|
-
chain.emitter.emit(ChainEvent.incompletePayloadEnvelope, {
|
|
918
|
-
payloadInput,
|
|
919
|
-
peer: peerIdStr,
|
|
920
|
-
source: BlockInputSource.gossip,
|
|
921
|
-
});
|
|
922
|
-
});
|
|
923
|
-
}
|
|
936
|
+
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
924
937
|
} catch (e) {
|
|
925
938
|
logger.debug(
|
|
926
939
|
"Error handling gossip data column",
|
|
@@ -1266,6 +1279,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1266
1279
|
seenTimestampSec,
|
|
1267
1280
|
}: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
|
|
1268
1281
|
const {serializedData} = gossipData;
|
|
1282
|
+
validateGossipExecutionPayloadEnvelopeSerialized(chain, serializedData);
|
|
1269
1283
|
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
1270
1284
|
const envelope = signedEnvelope.message;
|
|
1271
1285
|
|
|
@@ -1318,17 +1332,23 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1318
1332
|
});
|
|
1319
1333
|
}
|
|
1320
1334
|
|
|
1335
|
+
// Add the envelope in the same tick as validation, otherwise a by-root download that completes
|
|
1336
|
+
// before the next event loop sees no envelope, validates it again and adds it first
|
|
1337
|
+
if (!payloadInput.hasPayloadEnvelope()) {
|
|
1338
|
+
chain.serializedCache.set(signedEnvelope, serializedData);
|
|
1339
|
+
|
|
1340
|
+
payloadInput.addPayloadEnvelope({
|
|
1341
|
+
envelope: signedEnvelope,
|
|
1342
|
+
source: PayloadEnvelopeInputSource.gossip,
|
|
1343
|
+
seenTimestampSec,
|
|
1344
|
+
peerIdStr,
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1321
1348
|
// Handler - deferred to next event loop so the validation result propagates first
|
|
1322
1349
|
callInNextEventLoop(() => {
|
|
1323
1350
|
try {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
payloadInput.addPayloadEnvelope({
|
|
1327
|
-
envelope: signedEnvelope,
|
|
1328
|
-
source: PayloadEnvelopeInputSource.gossip,
|
|
1329
|
-
seenTimestampSec,
|
|
1330
|
-
peerIdStr,
|
|
1331
|
-
});
|
|
1351
|
+
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
1332
1352
|
|
|
1333
1353
|
chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
|
|
1334
1354
|
slot,
|
|
@@ -1337,12 +1357,18 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1337
1357
|
blockRoot: blockRootHex,
|
|
1338
1358
|
});
|
|
1339
1359
|
|
|
1340
|
-
|
|
1360
|
+
// Signature is verified above only for this envelope, one added by another source is verified at import
|
|
1361
|
+
const validSignature = payloadInput.getPayloadEnvelope() === signedEnvelope;
|
|
1362
|
+
chain.processExecutionPayload(payloadInput, {validSignature}).catch((e) => {
|
|
1341
1363
|
// Adjust verbosity based on error type
|
|
1342
1364
|
let logLevel: LogLevel;
|
|
1343
1365
|
|
|
1344
1366
|
if (e instanceof PayloadError) {
|
|
1345
1367
|
switch (e.type.code) {
|
|
1368
|
+
case PayloadErrorCode.DATA_UNAVAILABLE:
|
|
1369
|
+
// Columns did not arrive in time, BlockInputSync keeps pulling them and retries the import
|
|
1370
|
+
logLevel = LogLevel.debug;
|
|
1371
|
+
break;
|
|
1346
1372
|
// BLOCK_NOT_IN_FORK_CHOICE should not happen, validateGossipExecutionPayloadEnvelope above
|
|
1347
1373
|
// already verified the block is in fork choice
|
|
1348
1374
|
case PayloadErrorCode.BLOCK_NOT_IN_FORK_CHOICE:
|
|
@@ -1351,11 +1377,17 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1351
1377
|
// Errors might indicate an issue with our node or the connected EL client
|
|
1352
1378
|
logLevel = LogLevel.error;
|
|
1353
1379
|
break;
|
|
1354
|
-
|
|
1380
|
+
case PayloadErrorCode.BLOCK_EXECUTION_INVALID:
|
|
1381
|
+
logLevel = LogLevel.warn;
|
|
1382
|
+
break;
|
|
1383
|
+
// INVALID_SIGNATURE only happens for an envelope added by another source
|
|
1355
1384
|
case PayloadErrorCode.INVALID_SIGNATURE:
|
|
1356
1385
|
case PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR:
|
|
1357
1386
|
case PayloadErrorCode.EXECUTION_ENGINE_INVALID:
|
|
1358
|
-
|
|
1387
|
+
// Penalize only when the stored envelope is the one this peer sent, not one added by another source
|
|
1388
|
+
if (validSignature) {
|
|
1389
|
+
core.reportPeer(peerIdStr, PeerAction.LowToleranceError, "BadGossipPayload");
|
|
1390
|
+
}
|
|
1359
1391
|
// The builder may have signed another envelope that is valid, keeping this one would make
|
|
1360
1392
|
// by-root and range sync reuse it and never import the payload
|
|
1361
1393
|
chain.seenPayloadEnvelopeInputCache.removeInvalid(payloadInput);
|
|
@@ -1630,6 +1662,32 @@ function getBatchHandlers(modules: ValidatorFnsModules, options: GossipHandlerOp
|
|
|
1630
1662
|
logger.debug("Error adding gossip unaggregated attestation to pool", {subnet}, e as Error);
|
|
1631
1663
|
}
|
|
1632
1664
|
|
|
1665
|
+
// Collected only for vote slots that an upcoming block of a connected validator can include
|
|
1666
|
+
if (isForkPostElectra(fork) && chain.proposerTracker.shouldCollect(indexedAttestation.data.slot)) {
|
|
1667
|
+
try {
|
|
1668
|
+
const insertOutcome = chain.singleAttestationPool.add(
|
|
1669
|
+
attestation as SingleAttestation<ForkPostElectra>,
|
|
1670
|
+
attDataRootHex,
|
|
1671
|
+
validatorCommitteeIndex,
|
|
1672
|
+
committeeSize
|
|
1673
|
+
);
|
|
1674
|
+
metrics?.opPool.singleAttestationPool.gossipInsertOutcome.inc({insertOutcome});
|
|
1675
|
+
} catch (e) {
|
|
1676
|
+
logger.debug(
|
|
1677
|
+
"Error adding gossip single attestation to pool",
|
|
1678
|
+
{
|
|
1679
|
+
slot: indexedAttestation.data.slot,
|
|
1680
|
+
committeeIndex,
|
|
1681
|
+
validatorCommitteeIndex,
|
|
1682
|
+
validatorIndex: (attestation as SingleAttestation<ForkPostElectra>).attesterIndex,
|
|
1683
|
+
subnet,
|
|
1684
|
+
attDataRoot: attDataRootHex,
|
|
1685
|
+
},
|
|
1686
|
+
e as Error
|
|
1687
|
+
);
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1633
1691
|
// Separate boundary: a pool insertion error above must not skip the fork-choice vote
|
|
1634
1692
|
if (!options.dontSendGossipAttestationsToForkchoice) {
|
|
1635
1693
|
try {
|
|
@@ -244,6 +244,12 @@ type SearchUnknownRootTarget =
|
|
|
244
244
|
* Such that enough work is processed to fill either one of the queue.
|
|
245
245
|
*/
|
|
246
246
|
export class NetworkProcessor {
|
|
247
|
+
private stopped = false;
|
|
248
|
+
/**
|
|
249
|
+
* Replaced by dropAllJobs(). Loops that yield while re-queueing awaiting messages compare it after each yield
|
|
250
|
+
* and stop, so no message is queued after a drop.
|
|
251
|
+
*/
|
|
252
|
+
private jobGeneration = Symbol();
|
|
247
253
|
private readonly chain: IBeaconChain;
|
|
248
254
|
private readonly core: INetworkCore;
|
|
249
255
|
private readonly events: NetworkEventBus;
|
|
@@ -335,16 +341,27 @@ export class NetworkProcessor {
|
|
|
335
341
|
}
|
|
336
342
|
|
|
337
343
|
async stop(): Promise<void> {
|
|
344
|
+
if (this.stopped) return;
|
|
345
|
+
this.stopped = true;
|
|
338
346
|
this.events.off(NetworkEvent.pendingGossipsubMessage, this.onPendingGossipsubMessage);
|
|
339
347
|
this.chain.emitter.off(routes.events.EventType.block, this.onBlockProcessed);
|
|
340
348
|
this.chain.emitter.off(routes.events.EventType.executionPayload, this.onPayloadEnvelopeProcessed);
|
|
341
|
-
this.chain.
|
|
349
|
+
this.chain.clock.off(ClockEvent.slot, this.onClockSlot);
|
|
350
|
+
this.dropAllJobs();
|
|
342
351
|
}
|
|
343
352
|
|
|
344
353
|
dropAllJobs(): void {
|
|
354
|
+
this.jobGeneration = Symbol();
|
|
345
355
|
for (const topic of executeGossipWorkOrder) {
|
|
346
356
|
this.gossipQueues[topic].clear();
|
|
347
357
|
}
|
|
358
|
+
this.awaitingMessagesByBlockRoot.clear();
|
|
359
|
+
this.awaitingBlockMessageCount = 0;
|
|
360
|
+
this.awaitingMessagesByPayloadBlockRoot.clear();
|
|
361
|
+
this.awaitingPayloadMessageCount = 0;
|
|
362
|
+
this.searchedRootsBySlot.clear();
|
|
363
|
+
this.bufferedRootsBySlot.clear();
|
|
364
|
+
this.fatalPeers.clear();
|
|
348
365
|
}
|
|
349
366
|
|
|
350
367
|
dumpGossipQueue(topic: GossipType): PendingGossipsubMessage[] {
|
|
@@ -364,7 +381,7 @@ export class NetworkProcessor {
|
|
|
364
381
|
* prefer them as by-root download candidates.
|
|
365
382
|
*/
|
|
366
383
|
searchUnknownBlock({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
367
|
-
if (this.chain.seenBlock(root)) {
|
|
384
|
+
if (this.stopped || this.chain.seenBlock(root)) {
|
|
368
385
|
return;
|
|
369
386
|
}
|
|
370
387
|
const entry = this.searchedRootsBySlot.getOrDefault(slot).getOrDefault(root);
|
|
@@ -398,7 +415,7 @@ export class NetworkProcessor {
|
|
|
398
415
|
peer?: PeerIdStr,
|
|
399
416
|
slotIsPayloadSlot = false
|
|
400
417
|
): void {
|
|
401
|
-
if (this.chain.seenPayloadEnvelope(root)) {
|
|
418
|
+
if (this.stopped || this.chain.seenPayloadEnvelope(root)) {
|
|
402
419
|
return;
|
|
403
420
|
}
|
|
404
421
|
const entry = this.searchedRootsBySlot.getOrDefault(slot).getOrDefault(root);
|
|
@@ -801,6 +818,7 @@ export class NetworkProcessor {
|
|
|
801
818
|
this.awaitingBlockMessageCount -= total;
|
|
802
819
|
}
|
|
803
820
|
|
|
821
|
+
const generation = this.jobGeneration;
|
|
804
822
|
const nowSec = Date.now() / 1000;
|
|
805
823
|
let count = 0;
|
|
806
824
|
// TODO: we can group attestations to process in batches but since we have the SeenAttestationDatas
|
|
@@ -819,6 +837,7 @@ export class NetworkProcessor {
|
|
|
819
837
|
if (count === MAX_AWAITING_GOSSIP_OBJECTS_PER_TICK) {
|
|
820
838
|
count = 0;
|
|
821
839
|
await sleep(AWAITING_GOSSIP_OBJECTS_YIELD_EVERY_MS);
|
|
840
|
+
if (generation !== this.jobGeneration) return;
|
|
822
841
|
}
|
|
823
842
|
}
|
|
824
843
|
}
|
|
@@ -843,6 +862,7 @@ export class NetworkProcessor {
|
|
|
843
862
|
this.awaitingPayloadMessageCount -= total;
|
|
844
863
|
}
|
|
845
864
|
|
|
865
|
+
const generation = this.jobGeneration;
|
|
846
866
|
const nowSec = Date.now() / 1000;
|
|
847
867
|
let count = 0;
|
|
848
868
|
for (const messages of messagesByTopic.values()) {
|
|
@@ -858,6 +878,7 @@ export class NetworkProcessor {
|
|
|
858
878
|
if (count === MAX_AWAITING_GOSSIP_OBJECTS_PER_TICK) {
|
|
859
879
|
count = 0;
|
|
860
880
|
await sleep(AWAITING_GOSSIP_OBJECTS_YIELD_EVERY_MS);
|
|
881
|
+
if (generation !== this.jobGeneration) return;
|
|
861
882
|
}
|
|
862
883
|
}
|
|
863
884
|
}
|
|
@@ -937,6 +958,7 @@ export class NetworkProcessor {
|
|
|
937
958
|
};
|
|
938
959
|
|
|
939
960
|
private executeWork(): void {
|
|
961
|
+
if (this.stopped) return;
|
|
940
962
|
// TODO: Maybe de-bounce by timing the last time executeWork was run
|
|
941
963
|
|
|
942
964
|
this.metrics?.networkProcessor.executeWorkCalls.inc();
|
|
@@ -20,6 +20,7 @@ const gossipType = GossipType.beacon_attestation;
|
|
|
20
20
|
export enum SubnetSource {
|
|
21
21
|
committee = "committee",
|
|
22
22
|
longLived = "long_lived",
|
|
23
|
+
beforeProposal = "before_proposal",
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
// map of subnet to time to form stable mesh as seconds, null if not yet formed
|
|
@@ -40,7 +41,7 @@ export class AttnetsService implements IAttnetsService {
|
|
|
40
41
|
/** Committee subnets - PeerManager must find peers for those */
|
|
41
42
|
private committeeSubnets = new SubnetMap();
|
|
42
43
|
/**
|
|
43
|
-
* All currently subscribed short-lived subnets, for attestation aggregation
|
|
44
|
+
* All currently subscribed short-lived subnets, for attestation aggregation and before local block proposals
|
|
44
45
|
* This class will tell gossip to subscribe and un-subscribe
|
|
45
46
|
* If a value exists for `SubscriptionId` it means that gossip subscription is active in network.gossip
|
|
46
47
|
*/
|
|
@@ -52,6 +53,11 @@ export class AttnetsService implements IAttnetsService {
|
|
|
52
53
|
* Used to determine if we should process an attestation.
|
|
53
54
|
*/
|
|
54
55
|
private aggregatorSlotSubnet = new MapDef<Slot, AggregatorDutyInfo>(() => new Map());
|
|
56
|
+
/**
|
|
57
|
+
* Block proposal slots of validators connected to this node.
|
|
58
|
+
* Used to subscribe to all subnets `slotsToSubscribeBeforeProposalDuty` slots before, see onSlot
|
|
59
|
+
*/
|
|
60
|
+
private localProposalSlots = new Set<Slot>();
|
|
55
61
|
|
|
56
62
|
constructor(
|
|
57
63
|
private readonly config: BeaconConfig,
|
|
@@ -119,6 +125,22 @@ export class AttnetsService implements IAttnetsService {
|
|
|
119
125
|
}
|
|
120
126
|
}
|
|
121
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Called from the main thread with upcoming block proposal slots of connected validators.
|
|
130
|
+
* Tracked here, the subscription happens in onSlot like aggregator duties, or right away for a proposal learned
|
|
131
|
+
* after its subscription slot (node restart, newly connected validator)
|
|
132
|
+
*/
|
|
133
|
+
addLocalProposalSlots(slots: Slot[]): void {
|
|
134
|
+
const clockSlot = this.clock.currentSlot;
|
|
135
|
+
for (const proposalSlot of slots) {
|
|
136
|
+
this.localProposalSlots.add(proposalSlot);
|
|
137
|
+
// not from the slot before the proposal, its votes are published before a mesh could form
|
|
138
|
+
if (proposalSlot - this.opts.slotsToSubscribeBeforeProposalDuty <= clockSlot && clockSlot < proposalSlot - 1) {
|
|
139
|
+
this.subscribeAllSubnetsUntilProposal(proposalSlot);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
122
144
|
/**
|
|
123
145
|
* Check if a subscription is still active before handling a gossip object
|
|
124
146
|
*/
|
|
@@ -158,7 +180,8 @@ export class AttnetsService implements IAttnetsService {
|
|
|
158
180
|
|
|
159
181
|
/**
|
|
160
182
|
* Run per slot.
|
|
161
|
-
* - Subscribe to gossip subnets 2 slots in advance
|
|
183
|
+
* - Subscribe to gossip subnets 2 slots in advance of aggregator duties
|
|
184
|
+
* - Subscribe to all subnets `slotsToSubscribeBeforeProposalDuty` slots in advance of local block proposals
|
|
162
185
|
* - Unsubscribe from expired subnets
|
|
163
186
|
* - Track time to stable mesh if not yet formed
|
|
164
187
|
*/
|
|
@@ -186,19 +209,76 @@ export class AttnetsService implements IAttnetsService {
|
|
|
186
209
|
this.trackTimeToStableMesh(clockSlot, dutiedSlot, dutiedInfo);
|
|
187
210
|
}
|
|
188
211
|
|
|
212
|
+
// Must run before unsubscribeExpiredCommitteeSubnets so that a subnet whose subscription expires in this slot
|
|
213
|
+
// gets its ttl extended instead of being unsubscribed and subscribed again
|
|
214
|
+
this.subscribeAllSubnetsBeforeProposal(clockSlot);
|
|
215
|
+
|
|
189
216
|
this.unsubscribeExpiredCommitteeSubnets(clockSlot);
|
|
190
217
|
this.pruneExpiredAggregator(clockSlot);
|
|
218
|
+
this.pruneExpiredLocalProposals(clockSlot);
|
|
191
219
|
} catch (e) {
|
|
192
220
|
this.logger.error("Error on AttnetsService.onSlot", {slot: clockSlot}, e as Error);
|
|
193
221
|
}
|
|
194
222
|
};
|
|
195
223
|
|
|
196
224
|
private onHalfSlot = (clockSlot: Slot): void => {
|
|
197
|
-
|
|
198
|
-
|
|
225
|
+
try {
|
|
226
|
+
for (const [dutiedSlot, dutiedInfo] of this.aggregatorSlotSubnet.entries()) {
|
|
227
|
+
this.trackTimeToStableMesh(clockSlot, dutiedSlot, dutiedInfo);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
this.unsubscribeAllSubnetsBeforeProposal(clockSlot);
|
|
231
|
+
} catch (e) {
|
|
232
|
+
this.logger.error("Error on AttnetsService.onHalfSlot", {slot: clockSlot}, e as Error);
|
|
199
233
|
}
|
|
200
234
|
};
|
|
201
235
|
|
|
236
|
+
/**
|
|
237
|
+
* Subscribe to all subnets `slotsToSubscribeBeforeProposalDuty` slots before a block proposal of a connected
|
|
238
|
+
* validator, so that single attestations of those slots can be packed into the block. The subscription expires in
|
|
239
|
+
* the slot before the proposal, see unsubscribeAllSubnetsBeforeProposal
|
|
240
|
+
*/
|
|
241
|
+
private subscribeAllSubnetsBeforeProposal(clockSlot: Slot): void {
|
|
242
|
+
for (const proposalSlot of this.localProposalSlots) {
|
|
243
|
+
if (proposalSlot === clockSlot + this.opts.slotsToSubscribeBeforeProposalDuty) {
|
|
244
|
+
this.subscribeAllSubnetsUntilProposal(proposalSlot);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
private subscribeAllSubnetsUntilProposal(proposalSlot: Slot): void {
|
|
250
|
+
if (this.opts.slotsToSubscribeBeforeProposalDuty === 0 || this.opts.subscribeAllSubnets) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const subnets = Array.from({length: ATTESTATION_SUBNET_COUNT}, (_, subnet) => subnet);
|
|
255
|
+
// Same as aggregator duties: trigger gossip subscription first, then register the subscriptions.
|
|
256
|
+
// Do not add to committeeSubnets: it drives peer discovery, we only use the peers we already have
|
|
257
|
+
this.subscribeToSubnets(subnets, SubnetSource.beforeProposal);
|
|
258
|
+
for (const subnet of subnets) {
|
|
259
|
+
this.shortLivedSubscriptions.request({subnet, toSlot: proposalSlot - 1});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Unsubscribe from subnets of subscribeAllSubnetsBeforeProposal at half of the slot before the proposal instead of
|
|
265
|
+
* the proposal slot start, so the proposal slot does not carry their traffic. Single attestations are published at
|
|
266
|
+
* 1/3 of the slot so they have arrived by then.
|
|
267
|
+
* Short-lived subscriptions are either aggregator duties or these, an aggregator duty ends in its dutied slot and is
|
|
268
|
+
* kept here (aggregates are due later), it expires at the next slot start in onSlot as before. So only subnets of
|
|
269
|
+
* subscribeAllSubnetsBeforeProposal are unsubscribed here.
|
|
270
|
+
*/
|
|
271
|
+
private unsubscribeAllSubnetsBeforeProposal(clockSlot: Slot): void {
|
|
272
|
+
const aggregatorSubnets = this.aggregatorSlotSubnet.get(clockSlot);
|
|
273
|
+
const expiring = this.shortLivedSubscriptions.getExpired(
|
|
274
|
+
clockSlot + 1,
|
|
275
|
+
(subnet) => aggregatorSubnets?.has(subnet) === true
|
|
276
|
+
);
|
|
277
|
+
if (expiring.length > 0) {
|
|
278
|
+
this.unsubscribeSubnets(expiring, clockSlot + 1, SubnetSource.beforeProposal);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
202
282
|
/**
|
|
203
283
|
* Track time to form stable mesh if not yet formed
|
|
204
284
|
*/
|
|
@@ -291,8 +371,8 @@ export class AttnetsService implements IAttnetsService {
|
|
|
291
371
|
}
|
|
292
372
|
|
|
293
373
|
/**
|
|
294
|
-
* Unsubscribe
|
|
295
|
-
* If a
|
|
374
|
+
* Unsubscribe from short-lived subnets whose subscription expired.
|
|
375
|
+
* If a long-lived subnet is present, we do not unsubscribe from it.
|
|
296
376
|
*/
|
|
297
377
|
private unsubscribeExpiredCommitteeSubnets(slot: Slot): void {
|
|
298
378
|
const expired = this.shortLivedSubscriptions.getExpired(slot);
|
|
@@ -313,6 +393,14 @@ export class AttnetsService implements IAttnetsService {
|
|
|
313
393
|
}
|
|
314
394
|
}
|
|
315
395
|
|
|
396
|
+
private pruneExpiredLocalProposals(currentSlot: Slot): void {
|
|
397
|
+
for (const proposalSlot of this.localProposalSlots) {
|
|
398
|
+
if (currentSlot > proposalSlot) {
|
|
399
|
+
this.localProposalSlots.delete(proposalSlot);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
316
404
|
/** Update ENR */
|
|
317
405
|
private updateMetadata(): void {
|
|
318
406
|
const subnets = ssz.phase0.AttestationSubnets.defaultValue();
|
|
@@ -25,6 +25,8 @@ export type SubnetsService = {
|
|
|
25
25
|
|
|
26
26
|
export interface IAttnetsService extends SubnetsService {
|
|
27
27
|
shouldProcess(subnet: SubnetID, slot: Slot): boolean;
|
|
28
|
+
/** Block proposal slots of validators connected to this node, see `slotsToSubscribeBeforeProposalDuty` */
|
|
29
|
+
addLocalProposalSlots(slots: Slot[]): void;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
export type RandBetweenFn = (min: number, max: number) => number;
|
|
@@ -33,6 +35,11 @@ export type ShuffleFn = <T>(arr: T[]) => T[];
|
|
|
33
35
|
export type SubnetsServiceOpts = {
|
|
34
36
|
subscribeAllSubnets?: boolean;
|
|
35
37
|
slotsToSubscribeBeforeAggregatorDuty: number;
|
|
38
|
+
/**
|
|
39
|
+
* Subscribe to all attestation subnets this many slots before a block proposal of a connected validator, so that
|
|
40
|
+
* its single attestations can be packed into the block. In `[0, SLOTS_PER_EPOCH]`, 0 disables
|
|
41
|
+
*/
|
|
42
|
+
slotsToSubscribeBeforeProposalDuty: number;
|
|
36
43
|
};
|
|
37
44
|
|
|
38
45
|
export type SubnetsServiceTestOpts = {
|
package/src/node/nodejs.ts
CHANGED
|
@@ -1,23 +1,29 @@
|
|
|
1
1
|
import {setMaxListeners} from "node:events";
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Registry} from "prom-client";
|
|
4
|
+
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
5
|
+
import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
6
|
+
import {BeaconConfig} from "@lodestar/config";
|
|
7
|
+
import type {LoggerNode} from "@lodestar/logger/node";
|
|
4
8
|
import {
|
|
5
9
|
init as initNativeMetrics,
|
|
6
10
|
registerLocalValidator as registerNativeLocalValidator,
|
|
7
11
|
scrapeMetrics as scrapeNativeMetrics,
|
|
8
12
|
unregisterLocalValidator as unregisterNativeLocalValidator,
|
|
9
|
-
} from "@
|
|
10
|
-
import {type PubkeyCache} from "@
|
|
11
|
-
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
12
|
-
import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
13
|
-
import {BeaconConfig} from "@lodestar/config";
|
|
14
|
-
import type {LoggerNode} from "@lodestar/logger/node";
|
|
13
|
+
} from "@lodestar/native/metrics";
|
|
14
|
+
import {type PubkeyCache} from "@lodestar/native/pubkeys";
|
|
15
15
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
IBeaconStateView,
|
|
18
|
+
computeStartSlotAtEpoch,
|
|
19
|
+
isStatePostBellatrix,
|
|
20
|
+
isStatePostGloas,
|
|
21
|
+
} from "@lodestar/state-transition";
|
|
17
22
|
import {Slot} from "@lodestar/types";
|
|
18
|
-
import {sleep, toRootHex} from "@lodestar/utils";
|
|
23
|
+
import {defer, sleep, toRootHex} from "@lodestar/utils";
|
|
19
24
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
20
25
|
import {BeaconRestApiServer, getApi} from "../api/index.js";
|
|
26
|
+
import {getDataColumnSidecarsMinEpoch} from "../chain/archiveStore/utils/archiveBlocks.js";
|
|
21
27
|
import {BeaconChain, IBeaconChain, initBeaconMetrics} from "../chain/index.js";
|
|
22
28
|
import {ValidatorMonitor, createValidatorMonitor} from "../chain/validatorMonitor.js";
|
|
23
29
|
import {IBeaconDb} from "../db/index.js";
|
|
@@ -111,6 +117,7 @@ export class BeaconNode {
|
|
|
111
117
|
|
|
112
118
|
status: BeaconNodeStatus;
|
|
113
119
|
private controller?: AbortController;
|
|
120
|
+
private closePromise: Promise<void> | undefined;
|
|
114
121
|
|
|
115
122
|
constructor({
|
|
116
123
|
opts,
|
|
@@ -212,6 +219,17 @@ export class BeaconNode {
|
|
|
212
219
|
|
|
213
220
|
const clock = new Clock({config, genesisTime: anchorState.genesisTime, signal});
|
|
214
221
|
|
|
222
|
+
// Before any lookup into the legacy column buckets, which can be slow until compacted
|
|
223
|
+
const columnsMinEpoch =
|
|
224
|
+
opts.chain.archiveDataEpochs === Infinity
|
|
225
|
+
? null
|
|
226
|
+
: getDataColumnSidecarsMinEpoch(config, clock.currentEpoch, opts.chain.archiveDataEpochs);
|
|
227
|
+
await db.compactLegacyDataColumns(
|
|
228
|
+
columnsMinEpoch !== null && columnsMinEpoch >= config.FULU_FORK_EPOCH
|
|
229
|
+
? computeStartSlotAtEpoch(columnsMinEpoch)
|
|
230
|
+
: 0
|
|
231
|
+
);
|
|
232
|
+
|
|
215
233
|
await db.init();
|
|
216
234
|
|
|
217
235
|
// Prune hot db repos
|
|
@@ -280,6 +298,7 @@ export class BeaconNode {
|
|
|
280
298
|
: undefined,
|
|
281
299
|
builderApiClientOpts: {
|
|
282
300
|
timeout: opts.executionBuilder.timeout,
|
|
301
|
+
bidDeadline: opts.executionBuilder.bidDeadline,
|
|
283
302
|
// Sent with all builder api requests, unless the node runs in private mode
|
|
284
303
|
userAgent: opts.executionBuilder.userAgent,
|
|
285
304
|
},
|
|
@@ -375,23 +394,40 @@ export class BeaconNode {
|
|
|
375
394
|
/**
|
|
376
395
|
* Stop beacon node and its sub-components.
|
|
377
396
|
*/
|
|
378
|
-
|
|
379
|
-
if (this.
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
397
|
+
close(): Promise<void> {
|
|
398
|
+
if (this.closePromise !== undefined) return this.closePromise;
|
|
399
|
+
const completion = defer<void>();
|
|
400
|
+
this.closePromise = completion.promise;
|
|
401
|
+
this.status = BeaconNodeStatus.closing;
|
|
402
|
+
void this.closeInternal().then(completion.resolve, completion.reject);
|
|
403
|
+
return this.closePromise;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
private async closeInternal(): Promise<void> {
|
|
407
|
+
const errors: unknown[] = [];
|
|
408
|
+
for (const cleanup of [
|
|
409
|
+
() => this.sync.close(),
|
|
410
|
+
() => this.restApi?.close(),
|
|
411
|
+
() => this.network.close(),
|
|
412
|
+
() => this.metricsServer?.close(),
|
|
413
|
+
() => this.monitoring?.close(),
|
|
414
|
+
() => this.chain.persistToDisk(),
|
|
415
|
+
() => this.chain.close(),
|
|
388
416
|
// Abort signal last: close() calls above clear intervals/timeouts so no new
|
|
389
417
|
// operations get scheduled. If we aborted first, a still-pending interval could
|
|
390
418
|
// fire and schedule a new operation after abort, leaving it stuck and delaying shutdown.
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
419
|
+
() => this.controller?.abort(),
|
|
420
|
+
() => sleep(DELAY_BEFORE_CLOSING_DB_MS),
|
|
421
|
+
() => this.db.close(),
|
|
422
|
+
]) {
|
|
423
|
+
try {
|
|
424
|
+
await cleanup();
|
|
425
|
+
} catch (error) {
|
|
426
|
+
errors.push(error);
|
|
427
|
+
}
|
|
395
428
|
}
|
|
429
|
+
this.status = BeaconNodeStatus.closed;
|
|
430
|
+
if (errors.length === 1) throw errors[0];
|
|
431
|
+
if (errors.length > 1) throw new AggregateError(errors, "Beacon node cleanup failed");
|
|
396
432
|
}
|
|
397
433
|
}
|