@lodestar/beacon-node 1.51.0-dev.312812503e → 1.51.0-dev.36022cc5cb
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +17 -27
- 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 +5 -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/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 +21 -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 +8 -2
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +57 -7
- package/lib/chain/chain.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 +5 -5
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +23 -10
- 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/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/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 +0 -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 +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +1 -1
- package/lib/chain/regen/interface.d.ts.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.js +13 -13
- 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 +4 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +10 -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 +2 -0
- package/lib/network/core/networkCore.d.ts.map +1 -1
- package/lib/network/core/networkCore.js +3 -0
- package/lib/network/core/networkCore.js.map +1 -1
- package/lib/network/core/networkCoreWorker.js +1 -0
- package/lib/network/core/networkCoreWorker.js.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.d.ts +2 -0
- package/lib/network/core/networkCoreWorkerHandler.d.ts.map +1 -1
- package/lib/network/core/networkCoreWorkerHandler.js +3 -0
- package/lib/network/core/networkCoreWorkerHandler.js.map +1 -1
- package/lib/network/core/types.d.ts +2 -0
- 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 +4 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +45 -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.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/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +33 -19
- 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/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/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/beacon/blocks/index.ts +35 -45
- package/src/api/impl/beacon/pool/index.ts +5 -1
- package/src/api/impl/beacon/state/utils.ts +1 -1
- package/src/api/impl/validator/index.ts +47 -30
- 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 +40 -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 +67 -8
- 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 +5 -5
- package/src/chain/opPools/aggregatedAttestationPool.ts +25 -9
- package/src/chain/opPools/attestationPool.ts +16 -4
- package/src/chain/opPools/payloadAttestationPool.ts +18 -7
- 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 +0 -2
- package/src/chain/produceBlock/produceBlockBody.ts +4 -2
- package/src/chain/regen/interface.ts +1 -1
- package/src/chain/regen/queued.ts +6 -4
- package/src/chain/validation/executionPayloadBid.ts +14 -13
- 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 +10 -0
- package/src/metrics/server/http.ts +5 -5
- package/src/monitoring/service.ts +1 -1
- package/src/network/core/networkCore.ts +5 -0
- package/src/network/core/networkCoreWorker.ts +1 -0
- package/src/network/core/networkCoreWorkerHandler.ts +4 -0
- package/src/network/core/types.ts +2 -0
- 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 +45 -19
- package/src/network/options.ts +2 -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/processor/gossipHandlers.ts +38 -21
- package/src/network/processor/index.ts +25 -3
- 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/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
package/src/network/network.ts
CHANGED
|
@@ -30,10 +30,11 @@ import {
|
|
|
30
30
|
isGloasDataColumnSidecar,
|
|
31
31
|
phase0,
|
|
32
32
|
} from "@lodestar/types";
|
|
33
|
-
import {prettyPrintIndices, sleep} from "@lodestar/utils";
|
|
33
|
+
import {defer, prettyPrintIndices, sleep} from "@lodestar/utils";
|
|
34
34
|
import {BlockInputSource} from "../chain/blocks/blockInput/types.js";
|
|
35
35
|
import {ChainEvent, IBeaconChain} from "../chain/index.js";
|
|
36
36
|
import {computeSubnetForDataColumnSidecar} from "../chain/validation/dataColumnSidecar.js";
|
|
37
|
+
import {GoodByeReasonCode} from "../constants/index.js";
|
|
37
38
|
import {IBeaconDb} from "../db/interface.js";
|
|
38
39
|
import {Metrics, RegistryMetricCreator} from "../metrics/index.js";
|
|
39
40
|
import {IClock} from "../util/clock.js";
|
|
@@ -127,6 +128,7 @@ export class Network implements INetwork {
|
|
|
127
128
|
|
|
128
129
|
private subscribedToCoreTopics = false;
|
|
129
130
|
private connectedPeersSyncMeta = new Map<PeerIdStr, Omit<PeerSyncMeta, "peerId">>();
|
|
131
|
+
private closePromise: Promise<void> | undefined;
|
|
130
132
|
|
|
131
133
|
constructor(modules: NetworkModules) {
|
|
132
134
|
this.peerId = peerIdFromPrivateKey(modules.privateKey);
|
|
@@ -144,12 +146,8 @@ export class Network implements INetwork {
|
|
|
144
146
|
this.events.on(NetworkEvent.peerConnected, this.onPeerConnected);
|
|
145
147
|
this.events.on(NetworkEvent.peerDisconnected, this.onPeerDisconnected);
|
|
146
148
|
this.chain.emitter.on(routes.events.EventType.head, this.onHead);
|
|
147
|
-
this.chain.emitter.on(routes.events.EventType.lightClientFinalityUpdate,
|
|
148
|
-
|
|
149
|
-
);
|
|
150
|
-
this.chain.emitter.on(routes.events.EventType.lightClientOptimisticUpdate, ({data}) =>
|
|
151
|
-
this.onLightClientOptimisticUpdate(data)
|
|
152
|
-
);
|
|
149
|
+
this.chain.emitter.on(routes.events.EventType.lightClientFinalityUpdate, this.onLightClientFinalityUpdate);
|
|
150
|
+
this.chain.emitter.on(routes.events.EventType.lightClientOptimisticUpdate, this.onLightClientOptimisticUpdate);
|
|
153
151
|
this.chain.emitter.on(ChainEvent.updateTargetCustodyGroupCount, this.onTargetGroupCountUpdated);
|
|
154
152
|
this.chain.emitter.on(ChainEvent.publishDataColumns, this.onPublishDataColumns);
|
|
155
153
|
this.chain.emitter.on(ChainEvent.publishBlobSidecars, this.onPublishBlobSidecars);
|
|
@@ -239,9 +237,16 @@ export class Network implements INetwork {
|
|
|
239
237
|
return this.controller.signal.aborted;
|
|
240
238
|
}
|
|
241
239
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
240
|
+
close(): Promise<void> {
|
|
241
|
+
if (this.closePromise !== undefined) return this.closePromise;
|
|
242
|
+
const completion = defer<void>();
|
|
243
|
+
this.closePromise = completion.promise;
|
|
244
|
+
void this.closeInternal().then(completion.resolve, completion.reject);
|
|
245
|
+
return this.closePromise;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private async closeInternal(): Promise<void> {
|
|
249
|
+
this.controller.abort();
|
|
245
250
|
|
|
246
251
|
this.events.off(NetworkEvent.peerConnected, this.onPeerConnected);
|
|
247
252
|
this.events.off(NetworkEvent.peerDisconnected, this.onPeerDisconnected);
|
|
@@ -253,10 +258,12 @@ export class Network implements INetwork {
|
|
|
253
258
|
this.chain.emitter.off(ChainEvent.publishBlobSidecars, this.onPublishBlobSidecars);
|
|
254
259
|
this.chain.emitter.off(ChainEvent.publishProposerSlashing, this.onPublishProposerSlashing);
|
|
255
260
|
this.chain.emitter.off(ChainEvent.updateStatus, this.onUpdateStatus);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
this.connectedPeersSyncMeta.clear();
|
|
262
|
+
this.subscribedToCoreTopics = false;
|
|
263
|
+
const results = await Promise.allSettled([this.networkProcessor.stop(), this.core.close()]);
|
|
264
|
+
for (const result of results) {
|
|
265
|
+
if (result.status === "rejected") throw result.reason;
|
|
266
|
+
}
|
|
260
267
|
this.logger.debug("network core closed");
|
|
261
268
|
}
|
|
262
269
|
|
|
@@ -289,6 +296,10 @@ export class Network implements INetwork {
|
|
|
289
296
|
return this.core.reStatusPeers(peers);
|
|
290
297
|
}
|
|
291
298
|
|
|
299
|
+
async goodbyeAndDisconnect(peer: PeerIdStr, reason: GoodByeReasonCode): Promise<void> {
|
|
300
|
+
return this.core.goodbyeAndDisconnect(peer, reason);
|
|
301
|
+
}
|
|
302
|
+
|
|
292
303
|
searchUnknownBlock(slotRoot: SlotRootHex, source: BlockInputSource, peer?: PeerIdStr): void {
|
|
293
304
|
this.networkProcessor.searchUnknownBlock(slotRoot, source, peer);
|
|
294
305
|
}
|
|
@@ -328,6 +339,7 @@ export class Network implements INetwork {
|
|
|
328
339
|
async subscribeGossipCoreTopics(): Promise<void> {
|
|
329
340
|
if (!this.subscribedToCoreTopics) {
|
|
330
341
|
await this.core.subscribeGossipCoreTopics();
|
|
342
|
+
if (this.closed) return;
|
|
331
343
|
// Only mark subscribedToCoreTopics if worker resolved this call
|
|
332
344
|
this.subscribedToCoreTopics = true;
|
|
333
345
|
}
|
|
@@ -798,26 +810,32 @@ export class Network implements INetwork {
|
|
|
798
810
|
return this.core.writeDiscv5HeapSnapshot(prefix, dirpath);
|
|
799
811
|
}
|
|
800
812
|
|
|
801
|
-
private onLightClientFinalityUpdate = async (
|
|
813
|
+
private onLightClientFinalityUpdate = async ({
|
|
814
|
+
data: finalityUpdate,
|
|
815
|
+
}: routes.events.EventData[routes.events.EventType.lightClientFinalityUpdate]): Promise<void> => {
|
|
802
816
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
803
817
|
|
|
804
818
|
try {
|
|
805
819
|
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
806
820
|
// https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
807
821
|
await this.waitForSyncMessageCutoff(finalityUpdate.signatureSlot);
|
|
822
|
+
if (this.closed) return;
|
|
808
823
|
await this.publishLightClientFinalityUpdate(finalityUpdate);
|
|
809
824
|
} catch (e) {
|
|
810
825
|
this.logger.debug("Error on BeaconGossipHandler.onLightclientFinalityUpdate", {}, e as Error);
|
|
811
826
|
}
|
|
812
827
|
};
|
|
813
828
|
|
|
814
|
-
private onLightClientOptimisticUpdate = async (
|
|
829
|
+
private onLightClientOptimisticUpdate = async ({
|
|
830
|
+
data: optimisticUpdate,
|
|
831
|
+
}: routes.events.EventData[routes.events.EventType.lightClientOptimisticUpdate]): Promise<void> => {
|
|
815
832
|
// TODO: Review is OK to remove if (this.hasAttachedSyncCommitteeMember())
|
|
816
833
|
|
|
817
834
|
try {
|
|
818
835
|
// messages SHOULD be broadcast after SYNC_MESSAGE_DUE_BPS of slot has transpired
|
|
819
836
|
// https://github.com/ethereum/consensus-specs/blob/v1.6.1/specs/altair/light-client/p2p-interface.md#sync-committee
|
|
820
837
|
await this.waitForSyncMessageCutoff(optimisticUpdate.signatureSlot);
|
|
838
|
+
if (this.closed) return;
|
|
821
839
|
await this.publishLightClientOptimisticUpdate(optimisticUpdate);
|
|
822
840
|
} catch (e) {
|
|
823
841
|
this.logger.debug("Error on BeaconGossipHandler.onLightclientOptimisticUpdate", {}, e as Error);
|
|
@@ -854,8 +872,12 @@ export class Network implements INetwork {
|
|
|
854
872
|
this.connectedPeersSyncMeta.delete(data.peer);
|
|
855
873
|
};
|
|
856
874
|
|
|
857
|
-
private onTargetGroupCountUpdated = (count: number): void => {
|
|
858
|
-
|
|
875
|
+
private onTargetGroupCountUpdated = async (count: number): Promise<void> => {
|
|
876
|
+
try {
|
|
877
|
+
await this.core.setTargetGroupCount(count);
|
|
878
|
+
} catch (error) {
|
|
879
|
+
this.logger.error("Error updating network custody group count", {count}, error as Error);
|
|
880
|
+
}
|
|
859
881
|
};
|
|
860
882
|
|
|
861
883
|
private onPublishDataColumns = async (sidecars: DataColumnSidecar[]): Promise<void> => {
|
|
@@ -879,6 +901,10 @@ export class Network implements INetwork {
|
|
|
879
901
|
};
|
|
880
902
|
|
|
881
903
|
private onUpdateStatus = async (): Promise<void> => {
|
|
882
|
-
|
|
904
|
+
try {
|
|
905
|
+
await this.core.updateStatus(this.chain.getStatus());
|
|
906
|
+
} catch (error) {
|
|
907
|
+
this.logger.error("Error updating network status", {}, error as Error);
|
|
908
|
+
}
|
|
883
909
|
};
|
|
884
910
|
}
|
package/src/network/options.ts
CHANGED
|
@@ -25,6 +25,8 @@ export interface NetworkOptions
|
|
|
25
25
|
mdns?: boolean;
|
|
26
26
|
connectToDiscv5Bootnodes?: boolean;
|
|
27
27
|
version?: string;
|
|
28
|
+
/** Include the version in libp2p Identify. Private mode takes precedence. */
|
|
29
|
+
advertiseVersion?: boolean;
|
|
28
30
|
private?: boolean;
|
|
29
31
|
useWorker?: boolean;
|
|
30
32
|
maxYoungGenerationSizeMb?: number;
|
|
@@ -14,6 +14,7 @@ import {NetworkCoreMetrics} from "../core/metrics.js";
|
|
|
14
14
|
import {LodestarDiscv5Opts} from "../discv5/types.js";
|
|
15
15
|
import {INetworkEventBus, NetworkEvent, NetworkEventData} from "../events.js";
|
|
16
16
|
import {Eth2Gossipsub} from "../gossip/gossipsub.js";
|
|
17
|
+
import {GossipType} from "../gossip/interface.js";
|
|
17
18
|
import {Libp2p} from "../interface.js";
|
|
18
19
|
import {SubnetType} from "../metadata.js";
|
|
19
20
|
import {NetworkConfig} from "../networkConfig.js";
|
|
@@ -577,6 +578,8 @@ export class PeerManager {
|
|
|
577
578
|
this.lastStatus = status;
|
|
578
579
|
this.metrics?.peerManager.starved.set(starved ? 1 : 0);
|
|
579
580
|
const forkSeq = this.config.getForkSeq(this.clock.currentSlot);
|
|
581
|
+
const boundary = this.config.getForkBoundaryAtEpoch(this.clock.currentEpoch);
|
|
582
|
+
const connectedHealthyPeerIds = new Set(connectedHealthyPeers.map((peer) => peer.toString()));
|
|
580
583
|
|
|
581
584
|
const prioritizeTimer = this.metrics?.peerManager.prioritizePeersDuration.startTimer();
|
|
582
585
|
const {peersToDisconnect, peersToConnect, attnetQueries, syncnetQueries, custodyGroupQueries} = prioritizePeers(
|
|
@@ -594,8 +597,30 @@ export class PeerManager {
|
|
|
594
597
|
};
|
|
595
598
|
}),
|
|
596
599
|
// Collect subnets which we need peers for in the current slot
|
|
597
|
-
this.attnetsService.getActiveSubnets()
|
|
598
|
-
|
|
600
|
+
this.attnetsService.getActiveSubnets().map((request) => {
|
|
601
|
+
const subscribers = this.gossipsub.getSubscribersWithOutboundStream({
|
|
602
|
+
type: GossipType.beacon_attestation,
|
|
603
|
+
boundary,
|
|
604
|
+
subnet: request.subnet,
|
|
605
|
+
});
|
|
606
|
+
let peerCount = 0;
|
|
607
|
+
for (const peer of subscribers) {
|
|
608
|
+
if (connectedHealthyPeerIds.has(peer)) peerCount++;
|
|
609
|
+
}
|
|
610
|
+
return {...request, peerCount};
|
|
611
|
+
}),
|
|
612
|
+
this.syncnetsService.getActiveSubnets().map((request) => {
|
|
613
|
+
const subscribers = this.gossipsub.getSubscribersWithOutboundStream({
|
|
614
|
+
type: GossipType.sync_committee,
|
|
615
|
+
boundary,
|
|
616
|
+
subnet: request.subnet,
|
|
617
|
+
});
|
|
618
|
+
let peerCount = 0;
|
|
619
|
+
for (const peer of subscribers) {
|
|
620
|
+
if (connectedHealthyPeerIds.has(peer)) peerCount++;
|
|
621
|
+
}
|
|
622
|
+
return {...request, peerCount};
|
|
623
|
+
}),
|
|
599
624
|
// ignore samplingGroups for pre-fulu forks
|
|
600
625
|
forkSeq >= ForkSeq.fulu ? this.networkConfig.custodyConfig.sampleGroups : undefined,
|
|
601
626
|
{
|
|
@@ -893,7 +918,7 @@ export class PeerManager {
|
|
|
893
918
|
}
|
|
894
919
|
}
|
|
895
920
|
|
|
896
|
-
|
|
921
|
+
async goodbyeAndDisconnect(peer: PeerId, goodbye: GoodByeReasonCode): Promise<void> {
|
|
897
922
|
const reason = GOODBYE_KNOWN_CODES[goodbye.toString()] || "";
|
|
898
923
|
const peerIdStr = peer.toString();
|
|
899
924
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {ForkName, isForkPostFulu} from "@lodestar/params";
|
|
2
|
-
import {
|
|
1
|
+
import {ForkName, GENESIS_EPOCH, isForkPostFulu} from "@lodestar/params";
|
|
2
|
+
import {computeEpochAtSlot} from "@lodestar/state-transition";
|
|
3
|
+
import {Epoch, ForkDigest, Root, Slot, Status, fulu, ssz} from "@lodestar/types";
|
|
3
4
|
import {toHex, toRootHex} from "@lodestar/utils";
|
|
4
5
|
|
|
5
6
|
// TODO: Why this value? (From Lighthouse)
|
|
@@ -9,6 +10,8 @@ export enum IrrelevantPeerCode {
|
|
|
9
10
|
INCOMPATIBLE_FORKS = "IRRELEVANT_PEER_INCOMPATIBLE_FORKS",
|
|
10
11
|
DIFFERENT_CLOCKS = "IRRELEVANT_PEER_DIFFERENT_CLOCKS",
|
|
11
12
|
DIFFERENT_FINALIZED = "IRRELEVANT_PEER_DIFFERENT_FINALIZED",
|
|
13
|
+
FINALIZED_EPOCH_TOO_HIGH = "IRRELEVANT_PEER_FINALIZED_EPOCH_TOO_HIGH",
|
|
14
|
+
INVALID_FINALIZED_ROOT = "IRRELEVANT_PEER_INVALID_FINALIZED_ROOT",
|
|
12
15
|
NO_EARLIEST_AVAILABLE_SLOT = "NO_EARLIEST_AVAILABLE_SLOT",
|
|
13
16
|
}
|
|
14
17
|
|
|
@@ -16,6 +19,8 @@ type IrrelevantPeerType =
|
|
|
16
19
|
| {code: IrrelevantPeerCode.INCOMPATIBLE_FORKS; ours: ForkDigest; theirs: ForkDigest}
|
|
17
20
|
| {code: IrrelevantPeerCode.DIFFERENT_CLOCKS; slotDiff: number}
|
|
18
21
|
| {code: IrrelevantPeerCode.NO_EARLIEST_AVAILABLE_SLOT}
|
|
22
|
+
| {code: IrrelevantPeerCode.FINALIZED_EPOCH_TOO_HIGH; finalizedEpoch: Epoch; maxFinalizedEpoch: Epoch}
|
|
23
|
+
| {code: IrrelevantPeerCode.INVALID_FINALIZED_ROOT}
|
|
19
24
|
| {code: IrrelevantPeerCode.DIFFERENT_FINALIZED; expectedRoot: Root; remoteRoot: Root};
|
|
20
25
|
|
|
21
26
|
/**
|
|
@@ -45,29 +50,35 @@ export function assertPeerRelevance(
|
|
|
45
50
|
return {code: IrrelevantPeerCode.DIFFERENT_CLOCKS, slotDiff};
|
|
46
51
|
}
|
|
47
52
|
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
// A checkpoint can be finalized at the earliest at the start of epoch + 2
|
|
54
|
+
const maxFinalizedEpoch = Math.max(
|
|
55
|
+
GENESIS_EPOCH,
|
|
56
|
+
computeEpochAtSlot(Math.max(currentSlot, 0) + FUTURE_SLOT_TOLERANCE) - 2
|
|
57
|
+
);
|
|
58
|
+
if (remote.finalizedEpoch > maxFinalizedEpoch) {
|
|
59
|
+
return {
|
|
60
|
+
code: IrrelevantPeerCode.FINALIZED_EPOCH_TOO_HIGH,
|
|
61
|
+
finalizedEpoch: remote.finalizedEpoch,
|
|
62
|
+
maxFinalizedEpoch,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (remote.finalizedEpoch > GENESIS_EPOCH && isZeroRoot(remote.finalizedRoot)) {
|
|
67
|
+
return {code: IrrelevantPeerCode.INVALID_FINALIZED_ROOT};
|
|
68
|
+
}
|
|
51
69
|
|
|
70
|
+
// The remote's finalized epoch is equal to ours, but the block root is different to the one in our chain.
|
|
71
|
+
// Therefore, the node is on a different chain and we should not communicate with them.
|
|
52
72
|
if (
|
|
53
|
-
remote.finalizedEpoch
|
|
54
|
-
!isZeroRoot(
|
|
55
|
-
!
|
|
73
|
+
remote.finalizedEpoch === local.finalizedEpoch &&
|
|
74
|
+
!isZeroRoot(local.finalizedRoot) &&
|
|
75
|
+
!ssz.Root.equals(remote.finalizedRoot, local.finalizedRoot)
|
|
56
76
|
) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const expectedRoot = remote.finalizedEpoch === local.finalizedEpoch ? local.finalizedRoot : null;
|
|
63
|
-
|
|
64
|
-
if (expectedRoot !== null && !ssz.Root.equals(remoteRoot, expectedRoot)) {
|
|
65
|
-
return {
|
|
66
|
-
code: IrrelevantPeerCode.DIFFERENT_FINALIZED,
|
|
67
|
-
expectedRoot: expectedRoot, // forkChoice returns Tree BranchNode which the logger prints as {}
|
|
68
|
-
remoteRoot: remoteRoot,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
77
|
+
return {
|
|
78
|
+
code: IrrelevantPeerCode.DIFFERENT_FINALIZED,
|
|
79
|
+
expectedRoot: local.finalizedRoot,
|
|
80
|
+
remoteRoot: remote.finalizedRoot,
|
|
81
|
+
};
|
|
71
82
|
}
|
|
72
83
|
|
|
73
84
|
if (isForkPostFulu(forkName) && (remote as fulu.Status).earliestAvailableSlot === undefined) {
|
|
@@ -76,7 +87,8 @@ export function assertPeerRelevance(
|
|
|
76
87
|
};
|
|
77
88
|
}
|
|
78
89
|
|
|
79
|
-
// Note:
|
|
90
|
+
// Note: for a behind finalized checkpoint, we validate it more on the main thread against our history,
|
|
91
|
+
// see BeaconSync.verifyPastFinalizedCheckpoint
|
|
80
92
|
return null;
|
|
81
93
|
}
|
|
82
94
|
|
|
@@ -93,6 +105,10 @@ export function renderIrrelevantPeerType(type: IrrelevantPeerType): string {
|
|
|
93
105
|
return `DIFFERENT_CLOCKS slotDiff: ${type.slotDiff}`;
|
|
94
106
|
case IrrelevantPeerCode.DIFFERENT_FINALIZED:
|
|
95
107
|
return `DIFFERENT_FINALIZED root: ${toRootHex(type.remoteRoot)} expected: ${toRootHex(type.expectedRoot)}`;
|
|
108
|
+
case IrrelevantPeerCode.FINALIZED_EPOCH_TOO_HIGH:
|
|
109
|
+
return `FINALIZED_EPOCH_TOO_HIGH finalizedEpoch: ${type.finalizedEpoch} max: ${type.maxFinalizedEpoch}`;
|
|
110
|
+
case IrrelevantPeerCode.INVALID_FINALIZED_ROOT:
|
|
111
|
+
return "INVALID_FINALIZED_ROOT zero root for a non-genesis finalized epoch";
|
|
96
112
|
case IrrelevantPeerCode.NO_EARLIEST_AVAILABLE_SLOT:
|
|
97
113
|
return "No earliestAvailableSlot announced via peer Status";
|
|
98
114
|
}
|
|
@@ -49,6 +49,8 @@ const syncnetsZero = BitArray.fromBitLen(SYNC_COMMITTEE_SUBNET_COUNT);
|
|
|
49
49
|
|
|
50
50
|
type SubnetDiscvQuery = {subnet: SubnetID; toSlot: number; maxPeersToDiscover: number};
|
|
51
51
|
|
|
52
|
+
export type RequestedSubnetWithPeerCount = RequestedSubnet & {peerCount: number};
|
|
53
|
+
|
|
52
54
|
/**
|
|
53
55
|
* A map of das custody group index to maxPeersToDiscover
|
|
54
56
|
*/
|
|
@@ -145,8 +147,8 @@ export function prioritizePeers(
|
|
|
145
147
|
samplingGroups: CustodyIndex[] | null;
|
|
146
148
|
score: number;
|
|
147
149
|
}[],
|
|
148
|
-
activeAttnets:
|
|
149
|
-
activeSyncnets:
|
|
150
|
+
activeAttnets: RequestedSubnetWithPeerCount[],
|
|
151
|
+
activeSyncnets: RequestedSubnetWithPeerCount[],
|
|
150
152
|
samplingGroups: CustodyIndex[] | undefined,
|
|
151
153
|
opts: PrioritizePeersOpts,
|
|
152
154
|
config: ChainConfig,
|
|
@@ -231,8 +233,8 @@ export function prioritizePeers(
|
|
|
231
233
|
*/
|
|
232
234
|
function requestSubnetPeers(
|
|
233
235
|
connectedPeers: PeerInfo[],
|
|
234
|
-
activeAttnets:
|
|
235
|
-
activeSyncnets:
|
|
236
|
+
activeAttnets: RequestedSubnetWithPeerCount[],
|
|
237
|
+
activeSyncnets: RequestedSubnetWithPeerCount[],
|
|
236
238
|
ourSamplingGroups: CustodyIndex[] | undefined,
|
|
237
239
|
opts: PrioritizePeersOpts,
|
|
238
240
|
config: ChainConfig,
|
|
@@ -252,54 +254,44 @@ function requestSubnetPeers(
|
|
|
252
254
|
|
|
253
255
|
// attnets, do we need queries for more peers
|
|
254
256
|
if (activeAttnets.length > 0) {
|
|
255
|
-
/** Map of peers per subnet, peer may be in multiple arrays */
|
|
256
|
-
const peersPerSubnet = new Map<number, number>();
|
|
257
|
-
|
|
258
257
|
for (const peer of connectedPeers) {
|
|
259
258
|
const trueBitIndices = peer.attnetsTrueBitIndices;
|
|
260
259
|
let dutyCount = 0;
|
|
261
260
|
for (const {subnet} of activeAttnets) {
|
|
262
261
|
if (trueBitIndices.includes(subnet)) {
|
|
263
262
|
dutyCount += 1;
|
|
264
|
-
peersPerSubnet.set(subnet, 1 + (peersPerSubnet.get(subnet) ?? 0));
|
|
265
263
|
}
|
|
266
264
|
}
|
|
267
265
|
dutiesByPeer.set(peer, dutyCount);
|
|
268
266
|
}
|
|
269
267
|
|
|
270
|
-
for (const {subnet, toSlot} of activeAttnets) {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
if (peersInSubnet < targetSubnetPeers) {
|
|
268
|
+
for (const {subnet, toSlot, peerCount} of activeAttnets) {
|
|
269
|
+
metrics?.peerManager.peersPerActiveSubnet.observe({type: SubnetType.attnets}, peerCount);
|
|
270
|
+
if (peerCount < targetSubnetPeers) {
|
|
274
271
|
// We need more peers
|
|
275
|
-
attnetQueries.push({subnet, toSlot, maxPeersToDiscover: targetSubnetPeers -
|
|
272
|
+
attnetQueries.push({subnet, toSlot, maxPeersToDiscover: targetSubnetPeers - peerCount});
|
|
276
273
|
}
|
|
277
274
|
}
|
|
278
275
|
}
|
|
279
276
|
|
|
280
277
|
// syncnets, do we need queries for more peers
|
|
281
278
|
if (activeSyncnets.length > 0) {
|
|
282
|
-
/** Map of peers per subnet, peer may be in multiple arrays */
|
|
283
|
-
const peersPerSubnet = new Map<number, number>();
|
|
284
|
-
|
|
285
279
|
for (const peer of connectedPeers) {
|
|
286
280
|
const trueBitIndices = peer.syncnetsTrueBitIndices;
|
|
287
281
|
let dutyCount = dutiesByPeer.get(peer) ?? 0;
|
|
288
282
|
for (const {subnet} of activeSyncnets) {
|
|
289
283
|
if (trueBitIndices.includes(subnet)) {
|
|
290
284
|
dutyCount += 1;
|
|
291
|
-
peersPerSubnet.set(subnet, 1 + (peersPerSubnet.get(subnet) ?? 0));
|
|
292
285
|
}
|
|
293
286
|
}
|
|
294
287
|
dutiesByPeer.set(peer, dutyCount);
|
|
295
288
|
}
|
|
296
289
|
|
|
297
|
-
for (const {subnet, toSlot} of activeSyncnets) {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
if (peersInSubnet < targetSubnetPeers) {
|
|
290
|
+
for (const {subnet, toSlot, peerCount} of activeSyncnets) {
|
|
291
|
+
metrics?.peerManager.peersPerActiveSubnet.observe({type: SubnetType.syncnets}, peerCount);
|
|
292
|
+
if (peerCount < targetSubnetPeers) {
|
|
301
293
|
// We need more peers
|
|
302
|
-
syncnetQueries.push({subnet, toSlot, maxPeersToDiscover: targetSubnetPeers -
|
|
294
|
+
syncnetQueries.push({subnet, toSlot, maxPeersToDiscover: targetSubnetPeers - peerCount});
|
|
303
295
|
}
|
|
304
296
|
}
|
|
305
297
|
}
|
|
@@ -66,7 +66,10 @@ import {
|
|
|
66
66
|
validateGossipGloasDataColumnSidecar,
|
|
67
67
|
} from "../../chain/validation/dataColumnSidecar.js";
|
|
68
68
|
import {validateGossipExecutionPayloadBid} from "../../chain/validation/executionPayloadBid.js";
|
|
69
|
-
import {
|
|
69
|
+
import {
|
|
70
|
+
validateGossipExecutionPayloadEnvelope,
|
|
71
|
+
validateGossipExecutionPayloadEnvelopeSerialized,
|
|
72
|
+
} from "../../chain/validation/executionPayloadEnvelope.js";
|
|
70
73
|
import {InclusionListValidationResult, validateGossipInclusionList} from "../../chain/validation/inclusionList.js";
|
|
71
74
|
import {
|
|
72
75
|
AggregateAndProofValidationResult,
|
|
@@ -705,10 +708,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
705
708
|
|
|
706
709
|
// Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
|
|
707
710
|
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
708
|
-
//
|
|
709
|
-
//
|
|
710
|
-
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
711
|
-
// 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.
|
|
712
713
|
chain.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
713
714
|
}
|
|
714
715
|
})
|
|
@@ -718,11 +719,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
718
719
|
|
|
719
720
|
if (e instanceof BlockError) {
|
|
720
721
|
switch (e.type.code) {
|
|
721
|
-
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
722
|
-
//
|
|
722
|
+
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
723
|
+
// Data did not arrive in time, BlockInputSync keeps pulling it and retries the import
|
|
723
724
|
logLevel = LogLevel.debug;
|
|
724
725
|
break;
|
|
725
|
-
}
|
|
726
726
|
// ALREADY_KNOWN should not happen with ignoreIfKnown=true above
|
|
727
727
|
// PARENT_BLOCK_UNKNOWN should not happen, we handled this in validateBeaconBlock() function above
|
|
728
728
|
case BlockErrorCode.ALREADY_KNOWN:
|
|
@@ -930,7 +930,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
930
930
|
}
|
|
931
931
|
|
|
932
932
|
// NOTE: we do NOT call chain.processExecutionPayload here. That is triggered only by
|
|
933
|
-
// envelope arrival (gossip or API).
|
|
933
|
+
// envelope arrival (gossip or API). A pending payload import is awaiting
|
|
934
934
|
// payloadInput.waitForAllData(); addColumn above will resolve it once hasAllData flips.
|
|
935
935
|
|
|
936
936
|
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
@@ -1279,6 +1279,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1279
1279
|
seenTimestampSec,
|
|
1280
1280
|
}: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
|
|
1281
1281
|
const {serializedData} = gossipData;
|
|
1282
|
+
validateGossipExecutionPayloadEnvelopeSerialized(chain, serializedData);
|
|
1282
1283
|
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
1283
1284
|
const envelope = signedEnvelope.message;
|
|
1284
1285
|
|
|
@@ -1331,18 +1332,22 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1331
1332
|
});
|
|
1332
1333
|
}
|
|
1333
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
|
+
|
|
1334
1348
|
// Handler - deferred to next event loop so the validation result propagates first
|
|
1335
1349
|
callInNextEventLoop(() => {
|
|
1336
1350
|
try {
|
|
1337
|
-
chain.serializedCache.set(signedEnvelope, serializedData);
|
|
1338
|
-
|
|
1339
|
-
payloadInput.addPayloadEnvelope({
|
|
1340
|
-
envelope: signedEnvelope,
|
|
1341
|
-
source: PayloadEnvelopeInputSource.gossip,
|
|
1342
|
-
seenTimestampSec,
|
|
1343
|
-
peerIdStr,
|
|
1344
|
-
});
|
|
1345
|
-
|
|
1346
1351
|
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
1347
1352
|
|
|
1348
1353
|
chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
|
|
@@ -1352,12 +1357,18 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1352
1357
|
blockRoot: blockRootHex,
|
|
1353
1358
|
});
|
|
1354
1359
|
|
|
1355
|
-
|
|
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) => {
|
|
1356
1363
|
// Adjust verbosity based on error type
|
|
1357
1364
|
let logLevel: LogLevel;
|
|
1358
1365
|
|
|
1359
1366
|
if (e instanceof PayloadError) {
|
|
1360
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;
|
|
1361
1372
|
// BLOCK_NOT_IN_FORK_CHOICE should not happen, validateGossipExecutionPayloadEnvelope above
|
|
1362
1373
|
// already verified the block is in fork choice
|
|
1363
1374
|
case PayloadErrorCode.BLOCK_NOT_IN_FORK_CHOICE:
|
|
@@ -1366,11 +1377,17 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1366
1377
|
// Errors might indicate an issue with our node or the connected EL client
|
|
1367
1378
|
logLevel = LogLevel.error;
|
|
1368
1379
|
break;
|
|
1369
|
-
|
|
1380
|
+
case PayloadErrorCode.BLOCK_EXECUTION_INVALID:
|
|
1381
|
+
logLevel = LogLevel.warn;
|
|
1382
|
+
break;
|
|
1383
|
+
// INVALID_SIGNATURE only happens for an envelope added by another source
|
|
1370
1384
|
case PayloadErrorCode.INVALID_SIGNATURE:
|
|
1371
1385
|
case PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR:
|
|
1372
1386
|
case PayloadErrorCode.EXECUTION_ENGINE_INVALID:
|
|
1373
|
-
|
|
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
|
+
}
|
|
1374
1391
|
// The builder may have signed another envelope that is valid, keeping this one would make
|
|
1375
1392
|
// by-root and range sync reuse it and never import the payload
|
|
1376
1393
|
chain.seenPayloadEnvelopeInputCache.removeInvalid(payloadInput);
|
|
@@ -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();
|