@lodestar/beacon-node 1.47.0-dev.ec596194e2 → 1.47.0-dev.f0f26cd2b6
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 +47 -18
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +25 -2
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/events/index.d.ts +1 -1
- package/lib/api/impl/events/index.d.ts.map +1 -1
- package/lib/api/impl/events/index.js +12 -3
- package/lib/api/impl/events/index.js.map +1 -1
- package/lib/api/impl/lodestar/index.js +1 -1
- package/lib/api/impl/lodestar/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +232 -49
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/api/impl/validator/utils.js +1 -1
- package/lib/api/impl/validator/utils.js.map +1 -1
- package/lib/api/rest/base.d.ts.map +1 -1
- package/lib/api/rest/base.js +7 -0
- package/lib/api/rest/base.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +1 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +21 -0
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +2 -7
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +3 -2
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +11 -9
- 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 +21 -13
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +6 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +14 -5
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.js +5 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlock.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlock.js +5 -2
- package/lib/chain/blocks/verifyBlock.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +22 -12
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/bls/index.d.ts +1 -1
- package/lib/chain/bls/index.d.ts.map +1 -1
- package/lib/chain/bls/interface.d.ts +5 -5
- package/lib/chain/bls/interface.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +5 -11
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +116 -101
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +5 -19
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +10 -65
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/multithread/types.d.ts +29 -8
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/types.js +12 -0
- package/lib/chain/bls/multithread/types.js.map +1 -1
- package/lib/chain/bls/multithread/utils.d.ts +4 -0
- package/lib/chain/bls/multithread/utils.d.ts.map +1 -1
- package/lib/chain/bls/multithread/utils.js +10 -0
- package/lib/chain/bls/multithread/utils.js.map +1 -1
- package/lib/chain/bls/multithread/worker.js +49 -23
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -10
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +8 -45
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +4 -4
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +18 -19
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +9 -4
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +22 -8
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +1 -0
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +6 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/proposerPreferences.d.ts +6 -0
- package/lib/chain/errors/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/errors/proposerPreferences.js +1 -0
- package/lib/chain/errors/proposerPreferences.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +4 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +8 -4
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- 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 +1 -1
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/deferredVoluntaryExitPool.d.ts +16 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.d.ts.map +1 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.js +57 -0
- package/lib/chain/opPools/deferredVoluntaryExitPool.js.map +1 -0
- package/lib/chain/opPools/executionPayloadBidPool.d.ts +7 -2
- package/lib/chain/opPools/executionPayloadBidPool.d.ts.map +1 -1
- package/lib/chain/opPools/executionPayloadBidPool.js +4 -4
- package/lib/chain/opPools/executionPayloadBidPool.js.map +1 -1
- package/lib/chain/opPools/index.d.ts +2 -1
- 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.js +3 -3
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +1 -1
- 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/prepareNextSlot.d.ts +5 -0
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +47 -6
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.d.ts.map +1 -1
- package/lib/chain/produceBlock/computeNewStateRoot.js +3 -25
- package/lib/chain/produceBlock/computeNewStateRoot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +5 -2
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +3 -0
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/regen/queued.d.ts +2 -2
- package/lib/chain/regen/queued.d.ts.map +1 -1
- package/lib/chain/regen/queued.js +5 -5
- package/lib/chain/regen/queued.js.map +1 -1
- package/lib/chain/seenCache/seenAttesters.d.ts +9 -5
- package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
- package/lib/chain/seenCache/seenAttesters.js +25 -4
- package/lib/chain/seenCache/seenAttesters.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +28 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +121 -13
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts +5 -1
- package/lib/chain/stateCache/fifoBlockStateCache.d.ts.map +1 -1
- package/lib/chain/stateCache/fifoBlockStateCache.js +6 -0
- package/lib/chain/stateCache/fifoBlockStateCache.js.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts +47 -5
- package/lib/chain/stateCache/persistentCheckpointsCache.d.ts.map +1 -1
- package/lib/chain/stateCache/persistentCheckpointsCache.js +117 -7
- package/lib/chain/stateCache/persistentCheckpointsCache.js.map +1 -1
- package/lib/chain/stateCache/types.d.ts +3 -3
- package/lib/chain/stateCache/types.d.ts.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +1 -4
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +40 -10
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +13 -3
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +147 -12
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +5 -14
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts +1 -1
- package/lib/chain/validation/proposerPreferences.d.ts.map +1 -1
- package/lib/chain/validation/proposerPreferences.js +13 -4
- package/lib/chain/validation/proposerPreferences.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/chain/validation/voluntaryExit.d.ts +9 -1
- package/lib/chain/validation/voluntaryExit.d.ts.map +1 -1
- package/lib/chain/validation/voluntaryExit.js +46 -1
- package/lib/chain/validation/voluntaryExit.js.map +1 -1
- package/lib/execution/builder/apiClient.d.ts +70 -0
- package/lib/execution/builder/apiClient.d.ts.map +1 -0
- package/lib/execution/builder/apiClient.js +202 -0
- package/lib/execution/builder/apiClient.js.map +1 -0
- package/lib/execution/builder/validateBid.d.ts +22 -0
- package/lib/execution/builder/validateBid.d.ts.map +1 -0
- package/lib/execution/builder/validateBid.js +111 -0
- package/lib/execution/builder/validateBid.js.map +1 -0
- package/lib/metrics/metrics/lodestar.d.ts +94 -23
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +177 -55
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +13 -0
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +37 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +10 -2
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +23 -43
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/constants.d.ts +7 -0
- package/lib/network/processor/constants.d.ts.map +1 -0
- package/lib/network/processor/constants.js +7 -0
- package/lib/network/processor/constants.js.map +1 -0
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +13 -4
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/gossipQueues/indexed.d.ts.map +1 -1
- package/lib/network/processor/gossipQueues/indexed.js +0 -1
- package/lib/network/processor/gossipQueues/indexed.js.map +1 -1
- package/lib/network/processor/index.d.ts +3 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +52 -23
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/score.d.ts.map +1 -1
- package/lib/network/reqresp/score.js +5 -11
- package/lib/network/reqresp/score.js.map +1 -1
- package/lib/network/util.d.ts +0 -1
- package/lib/network/util.d.ts.map +1 -1
- package/lib/network/util.js +0 -4
- package/lib/network/util.js.map +1 -1
- package/lib/node/deferredVoluntaryExitPublisher.d.ts +15 -0
- package/lib/node/deferredVoluntaryExitPublisher.d.ts.map +1 -0
- package/lib/node/deferredVoluntaryExitPublisher.js +38 -0
- package/lib/node/deferredVoluntaryExitPublisher.js.map +1 -0
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +7 -0
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/range/batch.d.ts +23 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +61 -22
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +2 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +32 -12
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/range/range.js +1 -1
- package/lib/sync/range/range.js.map +1 -1
- package/lib/sync/types.d.ts +32 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +33 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts +15 -2
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +220 -61
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +16 -11
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +3 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/package.json +35 -35
- package/src/api/impl/beacon/blocks/index.ts +55 -21
- package/src/api/impl/beacon/pool/index.ts +27 -2
- package/src/api/impl/beacon/state/utils.ts +2 -1
- package/src/api/impl/events/index.ts +12 -4
- package/src/api/impl/lodestar/index.ts +1 -1
- package/src/api/impl/validator/index.ts +285 -49
- package/src/api/impl/validator/utils.ts +1 -1
- package/src/api/rest/base.ts +7 -0
- package/src/chain/archiveStore/archiveStore.ts +1 -1
- package/src/chain/archiveStore/historicalState/metrics.ts +22 -0
- package/src/chain/blocks/importBlock.ts +1 -6
- package/src/chain/blocks/importExecutionPayload.ts +12 -11
- package/src/chain/blocks/index.ts +25 -13
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +8 -2
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +17 -4
- package/src/chain/blocks/verifyBlock.ts +5 -2
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +25 -16
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +1 -9
- package/src/chain/bls/index.ts +1 -1
- package/src/chain/bls/interface.ts +7 -3
- package/src/chain/bls/multithread/index.ts +148 -120
- package/src/chain/bls/multithread/jobItem.ts +12 -82
- package/src/chain/bls/multithread/types.ts +33 -8
- package/src/chain/bls/multithread/utils.ts +11 -0
- package/src/chain/bls/multithread/worker.ts +85 -27
- package/src/chain/bls/singleThread.ts +11 -55
- package/src/chain/bls/utils.ts +23 -24
- package/src/chain/chain.ts +25 -7
- package/src/chain/errors/blockError.ts +8 -2
- package/src/chain/errors/proposerPreferences.ts +7 -0
- package/src/chain/forkChoice/index.ts +4 -0
- package/src/chain/interface.ts +8 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/opPools/attestationPool.ts +1 -1
- package/src/chain/opPools/deferredVoluntaryExitPool.ts +65 -0
- package/src/chain/opPools/executionPayloadBidPool.ts +13 -7
- package/src/chain/opPools/index.ts +2 -1
- package/src/chain/opPools/payloadAttestationPool.ts +3 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +1 -1
- package/src/chain/opPools/syncContributionAndProofPool.ts +1 -1
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/prepareNextSlot.ts +49 -6
- package/src/chain/produceBlock/computeNewStateRoot.ts +3 -38
- package/src/chain/produceBlock/produceBlockBody.ts +1 -1
- package/src/chain/regen/interface.ts +5 -2
- package/src/chain/regen/queued.ts +5 -5
- package/src/chain/seenCache/seenAttesters.ts +31 -5
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +143 -14
- package/src/chain/stateCache/fifoBlockStateCache.ts +8 -1
- package/src/chain/stateCache/persistentCheckpointsCache.ts +133 -8
- package/src/chain/stateCache/types.ts +3 -3
- package/src/chain/validation/attestation.ts +1 -7
- package/src/chain/validation/attesterSlashing.ts +1 -8
- package/src/chain/validation/block.ts +43 -10
- package/src/chain/validation/executionPayloadBid.ts +168 -14
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -1
- package/src/chain/validation/payloadAttestationMessage.ts +6 -17
- package/src/chain/validation/proposerPreferences.ts +15 -5
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/chain/validation/voluntaryExit.ts +59 -2
- package/src/execution/builder/apiClient.ts +264 -0
- package/src/execution/builder/validateBid.ts +166 -0
- package/src/metrics/metrics/lodestar.ts +192 -61
- package/src/network/gossip/topic.ts +38 -0
- package/src/network/libp2p/index.ts +11 -2
- package/src/network/network.ts +29 -54
- package/src/network/processor/constants.ts +6 -0
- package/src/network/processor/gossipHandlers.ts +15 -2
- package/src/network/processor/gossipQueues/indexed.ts +0 -1
- package/src/network/processor/index.ts +67 -30
- package/src/network/reqresp/score.ts +5 -11
- package/src/network/util.ts +0 -5
- package/src/node/deferredVoluntaryExitPublisher.ts +54 -0
- package/src/node/nodejs.ts +10 -1
- package/src/sync/range/batch.ts +83 -28
- package/src/sync/range/chain.ts +35 -13
- package/src/sync/range/range.ts +1 -1
- package/src/sync/types.ts +36 -1
- package/src/sync/unknownBlock.ts +258 -68
- package/src/sync/utils/downloadByRange.ts +21 -12
- package/src/sync/utils/downloadByRoot.ts +3 -1
- package/lib/chain/bls/maybeBatch.d.ts +0 -12
- package/lib/chain/bls/maybeBatch.d.ts.map +0 -1
- package/lib/chain/bls/maybeBatch.js +0 -35
- package/lib/chain/bls/maybeBatch.js.map +0 -1
- package/src/chain/bls/maybeBatch.ts +0 -45
package/src/network/network.ts
CHANGED
|
@@ -49,7 +49,12 @@ import {INetworkCore, NetworkCore, WorkerNetworkCore} from "./core/index.js";
|
|
|
49
49
|
import {INetworkEventBus, NetworkEvent, NetworkEventBus, NetworkEventData} from "./events.js";
|
|
50
50
|
import {getActiveForkBoundaries} from "./forks.js";
|
|
51
51
|
import {GossipHandlers, GossipTopicMap, GossipType, GossipTypeMap} from "./gossip/index.js";
|
|
52
|
-
import {
|
|
52
|
+
import {
|
|
53
|
+
getGossipSSZType,
|
|
54
|
+
gossipTopicAllowPublishToZeroPeers,
|
|
55
|
+
gossipTopicIgnoreDuplicatePublishError,
|
|
56
|
+
stringifyGossipTopic,
|
|
57
|
+
} from "./gossip/topic.js";
|
|
53
58
|
import {INetwork} from "./interface.js";
|
|
54
59
|
import {NetworkOptions} from "./options.js";
|
|
55
60
|
import {PeerAction, PeerScoreStats} from "./peers/index.js";
|
|
@@ -65,7 +70,7 @@ import {
|
|
|
65
70
|
} from "./reqresp/utils/collect.js";
|
|
66
71
|
import {collectSequentialBlocksInRange} from "./reqresp/utils/collectSequentialBlocksInRange.js";
|
|
67
72
|
import {CommitteeSubscription} from "./subnets/index.js";
|
|
68
|
-
import {isPublishDuplicateError,
|
|
73
|
+
import {isPublishDuplicateError, prettyPrintPeerIdStr} from "./util.js";
|
|
69
74
|
|
|
70
75
|
type NetworkModules = {
|
|
71
76
|
opts: NetworkOptions;
|
|
@@ -352,9 +357,7 @@ export class Network implements INetwork {
|
|
|
352
357
|
const epoch = computeEpochAtSlot(signedBlock.message.slot);
|
|
353
358
|
const boundary = this.config.getForkBoundaryAtEpoch(epoch);
|
|
354
359
|
|
|
355
|
-
return this.publishGossip<GossipType.beacon_block>({type: GossipType.beacon_block, boundary}, signedBlock
|
|
356
|
-
ignoreDuplicatePublishError: true,
|
|
357
|
-
});
|
|
360
|
+
return this.publishGossip<GossipType.beacon_block>({type: GossipType.beacon_block, boundary}, signedBlock);
|
|
358
361
|
}
|
|
359
362
|
|
|
360
363
|
async publishBlobSidecar(blobSidecar: deneb.BlobSidecar): Promise<number> {
|
|
@@ -363,9 +366,7 @@ export class Network implements INetwork {
|
|
|
363
366
|
|
|
364
367
|
const subnet = blobSidecar.index;
|
|
365
368
|
|
|
366
|
-
return this.publishGossip<GossipType.blob_sidecar>({type: GossipType.blob_sidecar, boundary, subnet}, blobSidecar
|
|
367
|
-
ignoreDuplicatePublishError: true,
|
|
368
|
-
});
|
|
369
|
+
return this.publishGossip<GossipType.blob_sidecar>({type: GossipType.blob_sidecar, boundary, subnet}, blobSidecar);
|
|
369
370
|
}
|
|
370
371
|
|
|
371
372
|
async publishDataColumnSidecar(
|
|
@@ -381,14 +382,7 @@ export class Network implements INetwork {
|
|
|
381
382
|
try {
|
|
382
383
|
const sentPeers = await this.publishGossip<GossipType.data_column_sidecar>(
|
|
383
384
|
{type: GossipType.data_column_sidecar, boundary, subnet},
|
|
384
|
-
dataColumnSidecar
|
|
385
|
-
{
|
|
386
|
-
// we ensure having all topic peers via prioritizePeers() function
|
|
387
|
-
// in the worse case, if there is 0 peer on the topic, the overall publish operation could be still a success
|
|
388
|
-
// because supernode will rebuild and publish missing data column sidecars for us
|
|
389
|
-
// hence we want to track sent peers as 0 instead of an error
|
|
390
|
-
allowPublishToZeroTopicPeers: true,
|
|
391
|
-
}
|
|
385
|
+
dataColumnSidecar
|
|
392
386
|
);
|
|
393
387
|
return {sentPeers, alreadyPublished: false};
|
|
394
388
|
} catch (e) {
|
|
@@ -405,8 +399,7 @@ export class Network implements INetwork {
|
|
|
405
399
|
|
|
406
400
|
return this.publishGossip<GossipType.beacon_aggregate_and_proof>(
|
|
407
401
|
{type: GossipType.beacon_aggregate_and_proof, boundary},
|
|
408
|
-
aggregateAndProof
|
|
409
|
-
{ignoreDuplicatePublishError: true}
|
|
402
|
+
aggregateAndProof
|
|
410
403
|
);
|
|
411
404
|
}
|
|
412
405
|
|
|
@@ -416,8 +409,7 @@ export class Network implements INetwork {
|
|
|
416
409
|
|
|
417
410
|
return this.publishGossip<GossipType.beacon_attestation>(
|
|
418
411
|
{type: GossipType.beacon_attestation, boundary, subnet},
|
|
419
|
-
attestation
|
|
420
|
-
{ignoreDuplicatePublishError: true}
|
|
412
|
+
attestation
|
|
421
413
|
);
|
|
422
414
|
}
|
|
423
415
|
|
|
@@ -425,9 +417,7 @@ export class Network implements INetwork {
|
|
|
425
417
|
const epoch = voluntaryExit.message.epoch;
|
|
426
418
|
const boundary = this.config.getForkBoundaryAtEpoch(epoch);
|
|
427
419
|
|
|
428
|
-
return this.publishGossip<GossipType.voluntary_exit>({type: GossipType.voluntary_exit, boundary}, voluntaryExit
|
|
429
|
-
ignoreDuplicatePublishError: true,
|
|
430
|
-
});
|
|
420
|
+
return this.publishGossip<GossipType.voluntary_exit>({type: GossipType.voluntary_exit, boundary}, voluntaryExit);
|
|
431
421
|
}
|
|
432
422
|
|
|
433
423
|
async publishBlsToExecutionChange(blsToExecutionChange: capella.SignedBLSToExecutionChange): Promise<number> {
|
|
@@ -438,8 +428,7 @@ export class Network implements INetwork {
|
|
|
438
428
|
if (fork >= ForkSeq.capella) {
|
|
439
429
|
const publishPromise = this.publishGossip<GossipType.bls_to_execution_change>(
|
|
440
430
|
{type: GossipType.bls_to_execution_change, boundary},
|
|
441
|
-
blsToExecutionChange
|
|
442
|
-
{ignoreDuplicatePublishError: true}
|
|
431
|
+
blsToExecutionChange
|
|
443
432
|
);
|
|
444
433
|
publishChanges.push(publishPromise);
|
|
445
434
|
}
|
|
@@ -457,8 +446,7 @@ export class Network implements INetwork {
|
|
|
457
446
|
|
|
458
447
|
return this.publishGossip<GossipType.proposer_slashing>(
|
|
459
448
|
{type: GossipType.proposer_slashing, boundary},
|
|
460
|
-
proposerSlashing
|
|
461
|
-
{ignoreDuplicatePublishError: true}
|
|
449
|
+
proposerSlashing
|
|
462
450
|
);
|
|
463
451
|
}
|
|
464
452
|
|
|
@@ -478,10 +466,7 @@ export class Network implements INetwork {
|
|
|
478
466
|
|
|
479
467
|
return this.publishGossip<GossipType.sync_committee>(
|
|
480
468
|
{type: GossipType.sync_committee, boundary, subnet},
|
|
481
|
-
signature
|
|
482
|
-
{
|
|
483
|
-
ignoreDuplicatePublishError: true,
|
|
484
|
-
}
|
|
469
|
+
signature
|
|
485
470
|
);
|
|
486
471
|
}
|
|
487
472
|
|
|
@@ -491,8 +476,7 @@ export class Network implements INetwork {
|
|
|
491
476
|
|
|
492
477
|
return this.publishGossip<GossipType.sync_committee_contribution_and_proof>(
|
|
493
478
|
{type: GossipType.sync_committee_contribution_and_proof, boundary},
|
|
494
|
-
contributionAndProof
|
|
495
|
-
{ignoreDuplicatePublishError: true}
|
|
479
|
+
contributionAndProof
|
|
496
480
|
);
|
|
497
481
|
}
|
|
498
482
|
|
|
@@ -522,8 +506,7 @@ export class Network implements INetwork {
|
|
|
522
506
|
|
|
523
507
|
return this.publishGossip<GossipType.execution_payload>(
|
|
524
508
|
{type: GossipType.execution_payload, boundary},
|
|
525
|
-
signedEnvelope
|
|
526
|
-
{ignoreDuplicatePublishError: true}
|
|
509
|
+
signedEnvelope
|
|
527
510
|
);
|
|
528
511
|
}
|
|
529
512
|
|
|
@@ -534,7 +517,7 @@ export class Network implements INetwork {
|
|
|
534
517
|
return this.publishGossip<GossipType.execution_payload_bid>(
|
|
535
518
|
{type: GossipType.execution_payload_bid, boundary},
|
|
536
519
|
signedBid,
|
|
537
|
-
{
|
|
520
|
+
{floodPublish: true}
|
|
538
521
|
);
|
|
539
522
|
}
|
|
540
523
|
|
|
@@ -544,8 +527,7 @@ export class Network implements INetwork {
|
|
|
544
527
|
|
|
545
528
|
return this.publishGossip<GossipType.payload_attestation_message>(
|
|
546
529
|
{type: GossipType.payload_attestation_message, boundary},
|
|
547
|
-
payloadAttestationMessage
|
|
548
|
-
{ignoreDuplicatePublishError: true}
|
|
530
|
+
payloadAttestationMessage
|
|
549
531
|
);
|
|
550
532
|
}
|
|
551
533
|
|
|
@@ -555,24 +537,25 @@ export class Network implements INetwork {
|
|
|
555
537
|
|
|
556
538
|
return this.publishGossip<GossipType.proposer_preferences>(
|
|
557
539
|
{type: GossipType.proposer_preferences, boundary},
|
|
558
|
-
signedProposerPreferences
|
|
559
|
-
{ignoreDuplicatePublishError: true}
|
|
540
|
+
signedProposerPreferences
|
|
560
541
|
);
|
|
561
542
|
}
|
|
562
543
|
|
|
563
544
|
private async publishGossip<K extends GossipType>(
|
|
564
545
|
topic: GossipTopicMap[K],
|
|
565
546
|
object: GossipTypeMap[K],
|
|
566
|
-
opts?: PublishOpts
|
|
547
|
+
opts?: PublishOpts
|
|
567
548
|
): Promise<number> {
|
|
568
549
|
const topicStr = stringifyGossipTopic(this.config, topic);
|
|
569
550
|
const sszType = getGossipSSZType(topic);
|
|
570
551
|
const messageData = (sszType.serialize as (object: GossipTypeMap[GossipType]) => Uint8Array)(object);
|
|
571
|
-
|
|
572
|
-
...opts,
|
|
552
|
+
const publishOpts: PublishOpts = {
|
|
573
553
|
ignoreDuplicatePublishError: gossipTopicIgnoreDuplicatePublishError[topic.type],
|
|
554
|
+
// Leave undefined unless the topic opts out, so `--network.allowPublishToZeroPeers` still applies
|
|
555
|
+
allowPublishToZeroTopicPeers: gossipTopicAllowPublishToZeroPeers[topic.type] ? true : undefined,
|
|
556
|
+
...opts,
|
|
574
557
|
};
|
|
575
|
-
const sentPeers = await this.core.publishGossip(topicStr, messageData,
|
|
558
|
+
const sentPeers = await this.core.publishGossip(topicStr, messageData, publishOpts);
|
|
576
559
|
|
|
577
560
|
this.logger.verbose("Publish to topic", {topic: topicStr, sentPeers, currentSlot: this.clock.currentSlot});
|
|
578
561
|
return sentPeers;
|
|
@@ -813,11 +796,7 @@ export class Network implements INetwork {
|
|
|
813
796
|
await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
|
|
814
797
|
await this.publishLightClientFinalityUpdate(finalityUpdate);
|
|
815
798
|
} catch (e) {
|
|
816
|
-
|
|
817
|
-
// Remove once https://github.com/ChainSafe/js-libp2p-gossipsub/issues/367
|
|
818
|
-
if (!isPublishToZeroPeersError(e as Error)) {
|
|
819
|
-
this.logger.debug("Error on BeaconGossipHandler.onLightclientFinalityUpdate", {}, e as Error);
|
|
820
|
-
}
|
|
799
|
+
this.logger.debug("Error on BeaconGossipHandler.onLightclientFinalityUpdate", {}, e as Error);
|
|
821
800
|
}
|
|
822
801
|
};
|
|
823
802
|
|
|
@@ -830,11 +809,7 @@ export class Network implements INetwork {
|
|
|
830
809
|
await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
|
|
831
810
|
await this.publishLightClientOptimisticUpdate(optimisticUpdate);
|
|
832
811
|
} catch (e) {
|
|
833
|
-
|
|
834
|
-
// Remove once https://github.com/ChainSafe/js-libp2p-gossipsub/issues/367
|
|
835
|
-
if (!isPublishToZeroPeersError(e as Error)) {
|
|
836
|
-
this.logger.debug("Error on BeaconGossipHandler.onLightclientOptimisticUpdate", {}, e as Error);
|
|
837
|
-
}
|
|
812
|
+
this.logger.debug("Error on BeaconGossipHandler.onLightclientOptimisticUpdate", {}, e as Error);
|
|
838
813
|
}
|
|
839
814
|
};
|
|
840
815
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Max distinct peers tracked per unknown block/payload root.
|
|
3
|
+
* Normally we have 8 mesh peers per topic, and multi topics may point to the same root.
|
|
4
|
+
* Having 32 peers per root seems enough to search for missing blocks/payloads.
|
|
5
|
+
**/
|
|
6
|
+
export const MAX_PEERS_PER_ROOT = 32;
|
|
@@ -196,7 +196,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
196
196
|
forkName: fork,
|
|
197
197
|
sampledColumns: chain.custodyConfig.sampledColumns,
|
|
198
198
|
custodyColumns: chain.custodyConfig.custodyColumns,
|
|
199
|
-
|
|
199
|
+
seenTimestampSec,
|
|
200
|
+
source: PayloadEnvelopeInputSource.gossip,
|
|
200
201
|
});
|
|
201
202
|
}
|
|
202
203
|
|
|
@@ -640,6 +641,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
640
641
|
metrics?.gossipBlock.elapsedTimeTillProcessed.observe(delaySec);
|
|
641
642
|
|
|
642
643
|
if (isForkPostGloas(blockInput.forkName)) {
|
|
644
|
+
// we should have the payloadInput in the seen cache so no need getOrReload() here
|
|
643
645
|
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockInput.blockRootHex);
|
|
644
646
|
// This payloadInput should have been created just after gossip validation
|
|
645
647
|
if (!payloadInput) {
|
|
@@ -1189,6 +1191,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1189
1191
|
chain.validatorMonitor?.registerExecutionPayloadEnvelope(OpSource.gossip, delaySec, signedEnvelope);
|
|
1190
1192
|
|
|
1191
1193
|
const blockRootHex = toRootHex(envelope.beaconBlockRoot);
|
|
1194
|
+
// a gossip payload cannot be `MAX_PAYLOAD_ENVELOPE_INPUT_CACHE_SIZE` slots after the block
|
|
1195
|
+
// otherwise it'll get to UnknownBlockInput flow
|
|
1192
1196
|
const payloadInput = chain.seenPayloadEnvelopeInputCache.get(blockRootHex);
|
|
1193
1197
|
|
|
1194
1198
|
if (!payloadInput) {
|
|
@@ -1255,11 +1259,15 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1255
1259
|
[GossipType.payload_attestation_message]: async ({
|
|
1256
1260
|
gossipData,
|
|
1257
1261
|
topic,
|
|
1262
|
+
seenTimestampSec,
|
|
1258
1263
|
}: GossipHandlerParamGeneric<GossipType.payload_attestation_message>) => {
|
|
1259
1264
|
const {serializedData} = gossipData;
|
|
1260
1265
|
const payloadAttestationMessage = sszDeserialize(topic, serializedData);
|
|
1261
1266
|
const validationResult = await validateGossipPayloadAttestationMessage(chain, payloadAttestationMessage);
|
|
1262
1267
|
|
|
1268
|
+
const delaySec = chain.clock.secFromSlot(payloadAttestationMessage.data.slot, seenTimestampSec);
|
|
1269
|
+
metrics?.gossipPayloadAttestationMessage.elapsedTimeTillReceived.observe({source: OpSource.gossip}, delaySec);
|
|
1270
|
+
|
|
1263
1271
|
try {
|
|
1264
1272
|
const insertOutcome = chain.payloadAttestationPool.add(
|
|
1265
1273
|
payloadAttestationMessage,
|
|
@@ -1286,14 +1294,19 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1286
1294
|
[GossipType.execution_payload_bid]: async ({
|
|
1287
1295
|
gossipData,
|
|
1288
1296
|
topic,
|
|
1297
|
+
seenTimestampSec,
|
|
1289
1298
|
}: GossipHandlerParamGeneric<GossipType.execution_payload_bid>) => {
|
|
1290
1299
|
const {serializedData} = gossipData;
|
|
1291
1300
|
const executionPayloadBid = sszDeserialize(topic, serializedData);
|
|
1292
1301
|
const {proposerIndex} = await validateGossipExecutionPayloadBid(chain, executionPayloadBid);
|
|
1293
1302
|
|
|
1303
|
+
// this could be negative, because it's most likely the bid of next slot comes at this clock slot
|
|
1304
|
+
const elapsedSec = chain.clock.secFromSlot(executionPayloadBid.message.slot, seenTimestampSec);
|
|
1305
|
+
metrics?.gossipExecutionPayloadBid.elapsedTimeTillReceived.observe({source: OpSource.gossip}, elapsedSec);
|
|
1306
|
+
|
|
1294
1307
|
// Handle valid payload bid by storing in a bid pool
|
|
1295
1308
|
try {
|
|
1296
|
-
const insertOutcome = chain.executionPayloadBidPool.add(executionPayloadBid);
|
|
1309
|
+
const insertOutcome = chain.executionPayloadBidPool.add(executionPayloadBid, Math.floor(elapsedSec * 1000));
|
|
1297
1310
|
metrics?.opPool.executionPayloadBidPool.gossipInsertOutcome.inc({insertOutcome});
|
|
1298
1311
|
} catch (e) {
|
|
1299
1312
|
logger.error("Error adding to executionPayloadBid pool", {}, e as Error);
|
|
@@ -86,7 +86,6 @@ export class IndexedGossipQueueMinSize<T extends {indexed?: string; queueAddedMs
|
|
|
86
86
|
const now = Date.now();
|
|
87
87
|
// here we mutate item, which is used for gossip validation later
|
|
88
88
|
item.indexed = key;
|
|
89
|
-
item.queueAddedMs = now;
|
|
90
89
|
let queueItem = this.indexedItems.get(key);
|
|
91
90
|
if (queueItem == null) {
|
|
92
91
|
queueItem = {firstSeenMs: now, listItems: new LinkedList<T>()};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import {TopicValidatorResult} from "@libp2p/gossipsub";
|
|
1
2
|
import {routes} from "@lodestar/api";
|
|
2
3
|
import {ForkSeq} from "@lodestar/params";
|
|
3
4
|
import {computeStartSlotAtEpoch} from "@lodestar/state-transition";
|
|
@@ -30,6 +31,7 @@ import {
|
|
|
30
31
|
GossipValidatorBatchFn,
|
|
31
32
|
GossipValidatorFn,
|
|
32
33
|
} from "../gossip/interface.js";
|
|
34
|
+
import {MAX_PEERS_PER_ROOT} from "./constants.js";
|
|
33
35
|
import {createExtractBlockSlotRootFns} from "./extractSlotRootFns.js";
|
|
34
36
|
import {GossipHandlerOpts, ValidatorFnsModules, getGossipHandlers} from "./gossipHandlers.js";
|
|
35
37
|
import {createGossipQueues} from "./gossipQueues/index.js";
|
|
@@ -191,8 +193,12 @@ export class NetworkProcessor {
|
|
|
191
193
|
// in that case PendingGossipsubMessage needs to be stored in this Map and reprocessed once the payload comes
|
|
192
194
|
private readonly awaitingMessagesByPayloadBlockRoot: MapDef<RootHex, Set<PendingGossipsubMessage>>;
|
|
193
195
|
private awaitingPayloadMessageCount = 0;
|
|
194
|
-
private unknownBlocksBySlot = new MapDef<Slot,
|
|
195
|
-
|
|
196
|
+
private unknownBlocksBySlot = new MapDef<Slot, MapDef<RootHex, Set<PeerIdStr>>>(
|
|
197
|
+
() => new MapDef<RootHex, Set<PeerIdStr>>(() => new Set())
|
|
198
|
+
);
|
|
199
|
+
private unknownEnvelopesBySlot = new MapDef<Slot, MapDef<RootHex, Set<PeerIdStr>>>(
|
|
200
|
+
() => new MapDef<RootHex, Set<PeerIdStr>>(() => new Set())
|
|
201
|
+
);
|
|
196
202
|
|
|
197
203
|
constructor(
|
|
198
204
|
modules: NetworkProcessorModules,
|
|
@@ -271,35 +277,53 @@ export class NetworkProcessor {
|
|
|
271
277
|
* Search block via `ChainEvent.unknownBlockRoot` event
|
|
272
278
|
* Slot is the message slot, which is not necessarily the same as the block's slot, but it can be used for a good prune strategy.
|
|
273
279
|
* In the rare case, if 2 messages on 2 slots search for the same root (for example beacon_attestation) we may emit the same root twice but BlockInputSync should handle it well.
|
|
280
|
+
* We forward every distinct peer that gossiped this root (not just the first) so BlockInputSync can
|
|
281
|
+
* prefer them as by-root download candidates.
|
|
274
282
|
*/
|
|
275
283
|
searchUnknownBlock({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
276
|
-
if (
|
|
277
|
-
this.chain.seenBlock(root) ||
|
|
278
|
-
this.awaitingMessagesByBlockRoot.has(root) ||
|
|
279
|
-
this.unknownBlocksBySlot.getOrDefault(slot).has(root)
|
|
280
|
-
) {
|
|
284
|
+
if (this.chain.seenBlock(root)) {
|
|
281
285
|
return;
|
|
282
286
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
287
|
+
const peersForRoot = this.unknownBlocksBySlot.getOrDefault(slot);
|
|
288
|
+
const alreadySearching = peersForRoot.has(root) || this.awaitingMessagesByBlockRoot.has(root);
|
|
289
|
+
const forwardedPeers = peersForRoot.getOrDefault(root);
|
|
290
|
+
|
|
291
|
+
// brand-new search always emits (peer may be undefined)
|
|
292
|
+
let shouldEmit = !alreadySearching;
|
|
293
|
+
if (peer !== undefined && !forwardedPeers.has(peer) && forwardedPeers.size < MAX_PEERS_PER_ROOT) {
|
|
294
|
+
// First time we forward THIS peer for THIS root: emit so BlockInputSync accumulates it.
|
|
295
|
+
forwardedPeers.add(peer);
|
|
296
|
+
shouldEmit = true;
|
|
297
|
+
}
|
|
298
|
+
if (shouldEmit) {
|
|
299
|
+
this.chain.emitter.emit(ChainEvent.unknownBlockRoot, {rootHex: root, peer, source});
|
|
300
|
+
}
|
|
286
301
|
}
|
|
287
302
|
|
|
288
303
|
/**
|
|
289
304
|
* Search envelope via `ChainEvent.unknownEnvelopeBlockRoot` event
|
|
290
305
|
* Slot is the message slot, which is not necessarily the same as the envelope's slot, but it can be used for a good prune strategy.
|
|
291
306
|
* In the rare case, if 2 messages on 2 slots search for the same root (for example beacon_attestation) we may emit the same root twice but BlockInputSync should handle it well.
|
|
307
|
+
* Same peer-forwarding + dedup behavior as searchUnknownBlock.
|
|
292
308
|
*/
|
|
293
309
|
searchUnknownEnvelope({slot, root}: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
294
|
-
if (
|
|
295
|
-
this.chain.seenPayloadEnvelope(root) ||
|
|
296
|
-
this.awaitingMessagesByPayloadBlockRoot.has(root) ||
|
|
297
|
-
this.unknownEnvelopesBySlot.getOrDefault(slot).has(root)
|
|
298
|
-
) {
|
|
310
|
+
if (this.chain.seenPayloadEnvelope(root)) {
|
|
299
311
|
return;
|
|
300
312
|
}
|
|
301
|
-
this.unknownEnvelopesBySlot.getOrDefault(slot)
|
|
302
|
-
|
|
313
|
+
const peersForRoot = this.unknownEnvelopesBySlot.getOrDefault(slot);
|
|
314
|
+
// capture "already searching" BEFORE getOrDefault(root) creates the entry
|
|
315
|
+
const alreadySearching = peersForRoot.has(root) || this.awaitingMessagesByPayloadBlockRoot.has(root);
|
|
316
|
+
const forwardedPeers = peersForRoot.getOrDefault(root);
|
|
317
|
+
|
|
318
|
+
let shouldEmit = !alreadySearching; // brand-new search always emits (peer may be undefined)
|
|
319
|
+
if (peer !== undefined && !forwardedPeers.has(peer) && forwardedPeers.size < MAX_PEERS_PER_ROOT) {
|
|
320
|
+
// First time we forward THIS peer for THIS root: emit so BlockInputSync accumulates it.
|
|
321
|
+
forwardedPeers.add(peer);
|
|
322
|
+
shouldEmit = true;
|
|
323
|
+
}
|
|
324
|
+
if (shouldEmit) {
|
|
325
|
+
this.chain.emitter.emit(ChainEvent.unknownEnvelopeBlockRoot, {rootHex: root, slot, peer, source});
|
|
326
|
+
}
|
|
303
327
|
}
|
|
304
328
|
|
|
305
329
|
private onPendingGossipsubMessage = (message: PendingGossipsubMessage): void => {
|
|
@@ -537,6 +561,7 @@ export class NetworkProcessor {
|
|
|
537
561
|
|
|
538
562
|
private pushPendingGossipsubMessageToQueue(message: PendingGossipsubMessage): void {
|
|
539
563
|
const topicType = message.topic.type;
|
|
564
|
+
message.queueAddedMs = Date.now();
|
|
540
565
|
const droppedCount = this.gossipQueues[topicType].add(message);
|
|
541
566
|
if (droppedCount) {
|
|
542
567
|
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
@@ -616,7 +641,7 @@ export class NetworkProcessor {
|
|
|
616
641
|
|
|
617
642
|
for (const [slot, roots] of this.unknownBlocksBySlot) {
|
|
618
643
|
if (slot > minSlot) continue;
|
|
619
|
-
for (const rootHex of roots) {
|
|
644
|
+
for (const rootHex of roots.keys()) {
|
|
620
645
|
const gossipMessages = this.awaitingMessagesByBlockRoot.get(rootHex);
|
|
621
646
|
if (gossipMessages !== undefined) {
|
|
622
647
|
for (const message of gossipMessages) {
|
|
@@ -641,7 +666,7 @@ export class NetworkProcessor {
|
|
|
641
666
|
|
|
642
667
|
for (const [slot, roots] of this.unknownEnvelopesBySlot) {
|
|
643
668
|
if (slot > minSlot) continue;
|
|
644
|
-
for (const rootHex of roots) {
|
|
669
|
+
for (const rootHex of roots.keys()) {
|
|
645
670
|
const gossipMessages = this.awaitingMessagesByPayloadBlockRoot.get(rootHex);
|
|
646
671
|
if (gossipMessages !== undefined) {
|
|
647
672
|
for (const message of gossipMessages) {
|
|
@@ -723,12 +748,20 @@ export class NetworkProcessor {
|
|
|
723
748
|
for (const msg of messageOrArray) {
|
|
724
749
|
msg.startProcessUnixSec = nowSec;
|
|
725
750
|
if (msg.queueAddedMs !== undefined) {
|
|
726
|
-
this.metrics?.gossipValidationQueue.queueTime.observe(
|
|
751
|
+
this.metrics?.gossipValidationQueue.queueTime.observe(
|
|
752
|
+
{topic: msg.topic.type},
|
|
753
|
+
nowSec - msg.queueAddedMs / 1000
|
|
754
|
+
);
|
|
727
755
|
}
|
|
728
756
|
}
|
|
729
757
|
} else {
|
|
730
|
-
// indexed queue is not used here
|
|
731
758
|
messageOrArray.startProcessUnixSec = nowSec;
|
|
759
|
+
if (messageOrArray.queueAddedMs !== undefined) {
|
|
760
|
+
this.metrics?.gossipValidationQueue.queueTime.observe(
|
|
761
|
+
{topic: messageOrArray.topic.type},
|
|
762
|
+
nowSec - messageOrArray.queueAddedMs / 1000
|
|
763
|
+
);
|
|
764
|
+
}
|
|
732
765
|
}
|
|
733
766
|
|
|
734
767
|
const acceptanceArr = Array.isArray(messageOrArray)
|
|
@@ -741,11 +774,11 @@ export class NetworkProcessor {
|
|
|
741
774
|
];
|
|
742
775
|
|
|
743
776
|
if (Array.isArray(messageOrArray)) {
|
|
744
|
-
for (const msg of messageOrArray) {
|
|
745
|
-
this.trackJobTime(msg, messageOrArray.length);
|
|
777
|
+
for (const [i, msg] of messageOrArray.entries()) {
|
|
778
|
+
this.trackJobTime(msg, messageOrArray.length, acceptanceArr[i]);
|
|
746
779
|
}
|
|
747
780
|
} else {
|
|
748
|
-
this.trackJobTime(messageOrArray, 1);
|
|
781
|
+
this.trackJobTime(messageOrArray, 1, acceptanceArr[0]);
|
|
749
782
|
}
|
|
750
783
|
|
|
751
784
|
// Use setTimeout to yield to the macro queue
|
|
@@ -773,17 +806,21 @@ export class NetworkProcessor {
|
|
|
773
806
|
}
|
|
774
807
|
}
|
|
775
808
|
|
|
776
|
-
private trackJobTime(message: PendingGossipsubMessage, numJob: number): void {
|
|
809
|
+
private trackJobTime(message: PendingGossipsubMessage, numJob: number, acceptance: TopicValidatorResult): void {
|
|
777
810
|
if (message.startProcessUnixSec !== null) {
|
|
811
|
+
// record job wait time for all messages
|
|
778
812
|
this.metrics?.gossipValidationQueue.jobWaitTime.observe(
|
|
779
813
|
{topic: message.topic.type},
|
|
780
814
|
message.startProcessUnixSec - message.seenTimestampSec
|
|
781
815
|
);
|
|
782
|
-
//
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
816
|
+
// but only record job time for ACCEPT messages
|
|
817
|
+
if (acceptance === TopicValidatorResult.Accept) {
|
|
818
|
+
// if it takes 64ms to process 64 jobs, the average job time is 1ms
|
|
819
|
+
this.metrics?.gossipValidationQueue.jobTime.observe(
|
|
820
|
+
{topic: message.topic.type},
|
|
821
|
+
(Date.now() / 1000 - message.startProcessUnixSec) / numJob
|
|
822
|
+
);
|
|
823
|
+
}
|
|
787
824
|
}
|
|
788
825
|
}
|
|
789
826
|
|
|
@@ -44,17 +44,11 @@ export function onOutgoingReqRespError(e: RequestError, method: ReqRespMethod):
|
|
|
44
44
|
// failure, so keep the stronger penalty (Fatal for Ping, as before).
|
|
45
45
|
return method === ReqRespMethod.Ping ? PeerAction.Fatal : PeerAction.LowToleranceError;
|
|
46
46
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
case ReqRespMethod.Ping:
|
|
53
|
-
case ReqRespMethod.Status:
|
|
54
|
-
return PeerAction.HighToleranceError;
|
|
55
|
-
default:
|
|
56
|
-
return PeerAction.LowToleranceError;
|
|
57
|
-
}
|
|
47
|
+
// A dial failure means we could not open a stream. That is evidence about the transport, not
|
|
48
|
+
// about the peer's behavior, and it is dominated by transient congestion on our side, so
|
|
49
|
+
// penalize leniently for every method to avoid self-inflicted peer starvation (#9562). A
|
|
50
|
+
// genuinely dead peer still accumulates penalty and is eventually evicted, freeing the slot.
|
|
51
|
+
return PeerAction.HighToleranceError;
|
|
58
52
|
// TODO: Detect SSZDecodeError and return PeerAction.Fatal
|
|
59
53
|
|
|
60
54
|
case RequestErrorCode.RESP_TIMEOUT:
|
package/src/network/util.ts
CHANGED
|
@@ -23,11 +23,6 @@ export function getConnection(libp2p: Libp2p, peerIdStr: string): Connection | u
|
|
|
23
23
|
return getConnectionsMap(libp2p).get(peerIdStr)?.value[0] ?? undefined;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
// https://github.com/libp2p/js-libp2p/blob/f87cba928991736d9646b3e054c367f55cab315c/packages/gossipsub/src/gossipsub.ts#L2076
|
|
27
|
-
export function isPublishToZeroPeersError(e: Error): boolean {
|
|
28
|
-
return e.message.includes("PublishError.NoPeersSubscribedToTopic");
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
// https://github.com/libp2p/js-libp2p/blob/f87cba928991736d9646b3e054c367f55cab315c/packages/gossipsub/src/gossipsub.ts#L2076
|
|
32
27
|
export function isPublishDuplicateError(e: Error): boolean {
|
|
33
28
|
return e.message.includes("PublishError.Duplicate");
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {routes} from "@lodestar/api";
|
|
2
|
+
import {Logger} from "@lodestar/utils";
|
|
3
|
+
import {IBeaconChain} from "../chain/index.js";
|
|
4
|
+
import {INetwork} from "../network/index.js";
|
|
5
|
+
import {ClockEvent} from "../util/clock.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* On every epoch, drain the deferred voluntary exit pool and publish the exits that have become
|
|
9
|
+
* processable. Lives at the node layer rather than inside `BeaconChain` because publishing needs
|
|
10
|
+
* `network`, which the chain does not (and should not) depend on.
|
|
11
|
+
*/
|
|
12
|
+
export function startDeferredVoluntaryExitPublisher({
|
|
13
|
+
chain,
|
|
14
|
+
network,
|
|
15
|
+
logger,
|
|
16
|
+
signal,
|
|
17
|
+
}: {
|
|
18
|
+
chain: IBeaconChain;
|
|
19
|
+
network: INetwork;
|
|
20
|
+
logger: Logger;
|
|
21
|
+
signal: AbortSignal;
|
|
22
|
+
}): void {
|
|
23
|
+
const onEpoch = async (): Promise<void> => {
|
|
24
|
+
try {
|
|
25
|
+
// Use the cached head state directly rather than getHeadStateAtCurrentEpoch, which would regen
|
|
26
|
+
// the head forward to the current epoch. At init from a stale db-finalized state that regen can
|
|
27
|
+
// be many epoch transitions. The head state is fine here: this is a best-effort drain that
|
|
28
|
+
// re-runs every epoch, so a just-processable exit is republished next tick.
|
|
29
|
+
const state = chain.getHeadState();
|
|
30
|
+
const exits = chain.deferredVoluntaryExitPool.drainProcessableExits(state);
|
|
31
|
+
for (const exit of exits) {
|
|
32
|
+
try {
|
|
33
|
+
chain.opPool.insertVoluntaryExit(exit);
|
|
34
|
+
chain.emitter.emit(routes.events.EventType.voluntaryExit, exit);
|
|
35
|
+
await network.publishVoluntaryExit(exit);
|
|
36
|
+
logger.info("Voluntary exit successfully published for validator", {
|
|
37
|
+
validatorIndex: exit.message.validatorIndex,
|
|
38
|
+
});
|
|
39
|
+
} catch (e) {
|
|
40
|
+
logger.warn(
|
|
41
|
+
"Failed to publish deferred voluntary exit",
|
|
42
|
+
{validatorIndex: exit.message.validatorIndex},
|
|
43
|
+
e as Error
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
} catch (e) {
|
|
48
|
+
logger.warn("Failed to drain deferred voluntary exit pool", {}, e as Error);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
chain.clock.addListener(ClockEvent.epoch, onEpoch);
|
|
53
|
+
signal.addEventListener("abort", () => chain.clock.removeListener(ClockEvent.epoch, onEpoch), {once: true});
|
|
54
|
+
}
|
package/src/node/nodejs.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import {setMaxListeners} from "node:events";
|
|
2
2
|
import {PrivateKey} from "@libp2p/interface";
|
|
3
3
|
import {Registry} from "prom-client";
|
|
4
|
+
import {type PubkeyCache} from "@chainsafe/lodestar-z/pubkeys";
|
|
4
5
|
import {hasher} from "@chainsafe/persistent-merkle-tree";
|
|
5
6
|
import {BeaconApiMethods} from "@lodestar/api/beacon/server";
|
|
6
7
|
import {BeaconConfig} from "@lodestar/config";
|
|
7
8
|
import type {LoggerNode} from "@lodestar/logger/node";
|
|
8
9
|
import {ZERO_HASH_HEX} from "@lodestar/params";
|
|
9
|
-
import {IBeaconStateView,
|
|
10
|
+
import {IBeaconStateView, isStatePostBellatrix, isStatePostGloas} from "@lodestar/state-transition";
|
|
10
11
|
import {phase0} from "@lodestar/types";
|
|
11
12
|
import {sleep, toRootHex} from "@lodestar/utils";
|
|
12
13
|
import {ProcessShutdownCallback} from "@lodestar/validator";
|
|
@@ -21,6 +22,7 @@ import {Network, getReqRespHandlers} from "../network/index.js";
|
|
|
21
22
|
import {BackfillSync} from "../sync/backfill/index.js";
|
|
22
23
|
import {BeaconSync, IBeaconSync} from "../sync/index.js";
|
|
23
24
|
import {Clock} from "../util/clock.js";
|
|
25
|
+
import {startDeferredVoluntaryExitPublisher} from "./deferredVoluntaryExitPublisher.js";
|
|
24
26
|
import {runNodeNotifier} from "./notifier.js";
|
|
25
27
|
import {IBeaconNodeOptions} from "./options.js";
|
|
26
28
|
|
|
@@ -258,6 +260,11 @@ export class BeaconNode {
|
|
|
258
260
|
executionBuilder: opts.executionBuilder.enabled
|
|
259
261
|
? initializeExecutionBuilder(opts.executionBuilder, config, metrics, logger)
|
|
260
262
|
: undefined,
|
|
263
|
+
builderApiClientOpts: {
|
|
264
|
+
timeout: opts.executionBuilder.timeout,
|
|
265
|
+
// Sent with all builder api requests, unless the node runs in private mode
|
|
266
|
+
userAgent: opts.executionBuilder.userAgent,
|
|
267
|
+
},
|
|
261
268
|
});
|
|
262
269
|
|
|
263
270
|
// Load persisted data from disk to in-memory caches
|
|
@@ -334,6 +341,8 @@ export class BeaconNode {
|
|
|
334
341
|
|
|
335
342
|
void runNodeNotifier({network, chain, sync, config, logger, signal});
|
|
336
343
|
|
|
344
|
+
startDeferredVoluntaryExitPublisher({chain, network, logger, signal});
|
|
345
|
+
|
|
337
346
|
return new BeaconNode({
|
|
338
347
|
opts,
|
|
339
348
|
config,
|