@lodestar/beacon-node 1.51.0-dev.a736f94f66 → 1.51.0-dev.aa1ecb7c18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/impl/api.js +1 -1
- package/lib/api/impl/api.js.map +1 -1
- package/lib/api/impl/beacon/blocks/index.d.ts +2 -1
- package/lib/api/impl/beacon/blocks/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/blocks/index.js +29 -34
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/index.d.ts +2 -1
- package/lib/api/impl/beacon/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/index.js +2 -2
- package/lib/api/impl/beacon/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +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/api/options.d.ts +2 -0
- package/lib/api/options.d.ts.map +1 -1
- package/lib/api/options.js +1 -0
- package/lib/api/options.js.map +1 -1
- package/lib/chain/GetBlobsTracker.d.ts +11 -0
- 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 +6 -5
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +6 -11
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +10 -16
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.js +2 -2
- 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/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 +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +4 -4
- 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/interface.d.ts +2 -3
- 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/inclusionListStore.d.ts.map +1 -1
- package/lib/chain/opPools/inclusionListStore.js +2 -2
- package/lib/chain/opPools/inclusionListStore.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.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +0 -1
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/regen/interface.d.ts +0 -1
- package/lib/chain/regen/interface.d.ts.map +1 -1
- package/lib/chain/regen/interface.js +0 -1
- package/lib/chain/regen/interface.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts +0 -15
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +13 -166
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts +6 -0
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +53 -0
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/inclusionList.d.ts.map +1 -1
- package/lib/chain/validation/inclusionList.js +11 -2
- package/lib/chain/validation/inclusionList.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/blobVersionedHashes.d.ts +1 -1
- package/lib/execution/engine/blobVersionedHashes.d.ts.map +1 -1
- package/lib/execution/engine/blobVersionedHashes.js.map +1 -1
- package/lib/execution/engine/http.d.ts.map +1 -1
- package/lib/execution/engine/http.js +0 -1
- 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 +1 -1
- package/lib/execution/engine/interface.d.ts.map +1 -1
- package/lib/execution/engine/interface.js.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +6 -4
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/execution/engine/payloadIdCache.d.ts +1 -2
- package/lib/execution/engine/payloadIdCache.d.ts.map +1 -1
- package/lib/execution/engine/payloadIdCache.js +3 -3
- package/lib/execution/engine/payloadIdCache.js.map +1 -1
- package/lib/execution/engine/sszTypes.d.ts +38 -38
- package/lib/execution/engine/types.d.ts +1 -1
- package/lib/execution/engine/types.d.ts.map +1 -1
- package/lib/execution/engine/types.js +9 -8
- 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 +7 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +15 -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/gossip/topic.d.ts +6 -6
- 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 +57 -37
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +6 -0
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +29 -3
- package/lib/network/processor/index.js.map +1 -1
- package/lib/node/nodejs.d.ts +3 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +47 -21
- package/lib/node/nodejs.js.map +1 -1
- package/lib/node/options.d.ts +3 -1
- package/lib/node/options.d.ts.map +1 -1
- package/lib/node/options.js +4 -2
- package/lib/node/options.js.map +1 -1
- package/lib/sync/interface.d.ts.map +1 -1
- package/lib/sync/interface.js.map +1 -1
- package/lib/sync/sync.d.ts +7 -0
- package/lib/sync/sync.d.ts.map +1 -1
- package/lib/sync/sync.js +61 -3
- package/lib/sync/sync.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +42 -18
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/util/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 +31 -32
- package/src/api/impl/api.ts +1 -1
- package/src/api/impl/beacon/blocks/index.ts +57 -62
- package/src/api/impl/beacon/index.ts +3 -1
- package/src/api/impl/beacon/pool/index.ts +5 -1
- package/src/api/impl/beacon/state/utils.ts +1 -1
- package/src/api/impl/validator/index.ts +47 -30
- package/src/api/options.ts +3 -0
- package/src/chain/GetBlobsTracker.ts +97 -38
- package/src/chain/archiveStore/archiveStore.ts +1 -0
- package/src/chain/archiveStore/utils/archiveBlocks.ts +76 -130
- package/src/chain/blocks/importBlock.ts +8 -7
- package/src/chain/blocks/importExecutionPayload.ts +15 -22
- package/src/chain/blocks/index.ts +6 -2
- 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/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 +5 -5
- package/src/chain/errors/blockError.ts +1 -1
- package/src/chain/errors/executionPayloadEnvelope.ts +8 -0
- package/src/chain/interface.ts +2 -3
- package/src/chain/opPools/aggregatedAttestationPool.ts +25 -9
- package/src/chain/opPools/attestationPool.ts +16 -4
- package/src/chain/opPools/inclusionListStore.ts +3 -3
- 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 +0 -1
- package/src/chain/regen/interface.ts +0 -1
- package/src/chain/validation/executionPayloadBid.ts +14 -193
- package/src/chain/validation/executionPayloadEnvelope.ts +68 -1
- package/src/chain/validation/inclusionList.ts +11 -2
- 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/blobVersionedHashes.ts +1 -1
- package/src/execution/engine/http.ts +0 -1
- package/src/execution/engine/index.ts +1 -1
- package/src/execution/engine/interface.ts +1 -1
- package/src/execution/engine/mock.ts +6 -4
- package/src/execution/engine/payloadIdCache.ts +6 -7
- package/src/execution/engine/types.ts +11 -9
- package/src/execution/engine/utils.ts +4 -2
- package/src/index.ts +2 -0
- package/src/metrics/metrics/lodestar.ts +15 -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 +69 -40
- 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/sync/unknownBlock.ts +47 -28
- 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
|
}
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
deneb,
|
|
25
25
|
fulu,
|
|
26
26
|
gloas,
|
|
27
|
+
isGloasBeaconBlock,
|
|
27
28
|
isGloasDataColumnSidecar,
|
|
28
29
|
ssz,
|
|
29
30
|
sszTypesFor,
|
|
@@ -65,7 +66,10 @@ import {
|
|
|
65
66
|
validateGossipGloasDataColumnSidecar,
|
|
66
67
|
} from "../../chain/validation/dataColumnSidecar.js";
|
|
67
68
|
import {validateGossipExecutionPayloadBid} from "../../chain/validation/executionPayloadBid.js";
|
|
68
|
-
import {
|
|
69
|
+
import {
|
|
70
|
+
validateGossipExecutionPayloadEnvelope,
|
|
71
|
+
validateGossipExecutionPayloadEnvelopeSerialized,
|
|
72
|
+
} from "../../chain/validation/executionPayloadEnvelope.js";
|
|
69
73
|
import {InclusionListValidationResult, validateGossipInclusionList} from "../../chain/validation/inclusionList.js";
|
|
70
74
|
import {
|
|
71
75
|
AggregateAndProofValidationResult,
|
|
@@ -150,6 +154,31 @@ export function getGossipHandlers(modules: ValidatorFnsModules, options: GossipH
|
|
|
150
154
|
*/
|
|
151
155
|
function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHandlerOpts): SequentialGossipHandlers {
|
|
152
156
|
const {chain, config, metrics, logger, core} = modules;
|
|
157
|
+
const incompletePayloadWaits = new WeakSet<PayloadEnvelopeInput>();
|
|
158
|
+
|
|
159
|
+
function scheduleIncompletePayloadEnvelope(payloadInput: PayloadEnvelopeInput, peer: string): void {
|
|
160
|
+
if (payloadInput.isComplete() || incompletePayloadWaits.has(payloadInput)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
incompletePayloadWaits.add(payloadInput);
|
|
164
|
+
|
|
165
|
+
const fork = config.getForkName(payloadInput.slot);
|
|
166
|
+
const cutoffTimeMs = getCutoffTimeMs(chain, payloadInput.slot, config.getPayloadDueMs(fork));
|
|
167
|
+
payloadInput.waitForEnvelopeAndAllData(cutoffTimeMs).catch(() => {
|
|
168
|
+
if (
|
|
169
|
+
payloadInput.isComplete() ||
|
|
170
|
+
chain.seenPayloadEnvelopeInputCache.get(payloadInput.blockRootHex) !== payloadInput
|
|
171
|
+
) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
chain.logger.debug("Payload envelope incomplete at payload deadline", payloadInput.getLogMeta());
|
|
175
|
+
chain.emitter.emit(ChainEvent.incompletePayloadEnvelope, {
|
|
176
|
+
payloadInput,
|
|
177
|
+
peer,
|
|
178
|
+
source: BlockInputSource.gossip,
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
}
|
|
153
182
|
|
|
154
183
|
/**
|
|
155
184
|
* Add a gossip block to the seen caches. The proposer signature of the block MUST be verified.
|
|
@@ -679,10 +708,8 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
679
708
|
|
|
680
709
|
// Immediately attempt fetch of data columns from execution engine as the bid contains kzg commitments
|
|
681
710
|
// which is all the information we need so there is no reason to delay until execution payload arrives
|
|
682
|
-
//
|
|
683
|
-
//
|
|
684
|
-
// Columns fetched here feed payloadInput.addColumn, which resolves waitForAllData for any
|
|
685
|
-
// in-flight importExecutionPayload. No processExecutionPayload trigger needed from this path.
|
|
711
|
+
// Columns fetched here feed payloadInput.addColumn, which resolves the waitForAllData of a
|
|
712
|
+
// pending payload import. No processExecutionPayload trigger needed from this path.
|
|
686
713
|
chain.getBlobsTracker.triggerGetBlobs(payloadInput);
|
|
687
714
|
}
|
|
688
715
|
})
|
|
@@ -692,11 +719,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
692
719
|
|
|
693
720
|
if (e instanceof BlockError) {
|
|
694
721
|
switch (e.type.code) {
|
|
695
|
-
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
696
|
-
//
|
|
722
|
+
case BlockErrorCode.DATA_UNAVAILABLE:
|
|
723
|
+
// Data did not arrive in time, BlockInputSync keeps pulling it and retries the import
|
|
697
724
|
logLevel = LogLevel.debug;
|
|
698
725
|
break;
|
|
699
|
-
}
|
|
700
726
|
// ALREADY_KNOWN should not happen with ignoreIfKnown=true above
|
|
701
727
|
// PARENT_BLOCK_UNKNOWN should not happen, we handled this in validateBeaconBlock() function above
|
|
702
728
|
case BlockErrorCode.ALREADY_KNOWN:
|
|
@@ -764,7 +790,12 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
764
790
|
// roots per proposer and slot, which bounds full imports over gossip to one alternate
|
|
765
791
|
chain.seenBlockProposers.hasBlockRoot(signedBlock.message.slot, e.type.proposerIndex, e.type.root) &&
|
|
766
792
|
// A sibling with an unknown parent cannot be imported, sync fetches it if its branch becomes relevant
|
|
767
|
-
chain.forkChoice.getBlockHexDefaultStatus(toRootHex(signedBlock.message.parentRoot)) !== null
|
|
793
|
+
chain.forkChoice.getBlockHexDefaultStatus(toRootHex(signedBlock.message.parentRoot)) !== null &&
|
|
794
|
+
(!isGloasBeaconBlock(signedBlock.message) ||
|
|
795
|
+
chain.forkChoice.getBlockHexAndBlockHash(
|
|
796
|
+
toRootHex(signedBlock.message.parentRoot),
|
|
797
|
+
toRootHex(signedBlock.message.body.signedExecutionPayloadBid.message.parentBlockHash)
|
|
798
|
+
) !== null)
|
|
768
799
|
) {
|
|
769
800
|
const blockInput = cacheSignatureVerifiedBlock(
|
|
770
801
|
signedBlock,
|
|
@@ -899,28 +930,10 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
899
930
|
}
|
|
900
931
|
|
|
901
932
|
// NOTE: we do NOT call chain.processExecutionPayload here. That is triggered only by
|
|
902
|
-
// envelope arrival (gossip or API).
|
|
933
|
+
// envelope arrival (gossip or API). A pending payload import is awaiting
|
|
903
934
|
// payloadInput.waitForAllData(); addColumn above will resolve it once hasAllData flips.
|
|
904
935
|
|
|
905
|
-
|
|
906
|
-
const cutoffTimeMs = getCutoffTimeMs(chain, dataColumnSlot, BLOCK_AVAILABILITY_CUTOFF_MS);
|
|
907
|
-
// do not await here to not delay gossip validation
|
|
908
|
-
payloadInput.waitForEnvelopeAndAllData(cutoffTimeMs).catch((_e) => {
|
|
909
|
-
chain.logger.debug(
|
|
910
|
-
"Waited for envelope and data after receiving gossip column. Cut-off reached so emitting incompletePayloadEnvelope",
|
|
911
|
-
{
|
|
912
|
-
dataColumnIndex: index,
|
|
913
|
-
...payloadInputMeta,
|
|
914
|
-
}
|
|
915
|
-
);
|
|
916
|
-
// TODO GLOAS: UnknownBlockSync to handle this event
|
|
917
|
-
chain.emitter.emit(ChainEvent.incompletePayloadEnvelope, {
|
|
918
|
-
payloadInput,
|
|
919
|
-
peer: peerIdStr,
|
|
920
|
-
source: BlockInputSource.gossip,
|
|
921
|
-
});
|
|
922
|
-
});
|
|
923
|
-
}
|
|
936
|
+
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
924
937
|
} catch (e) {
|
|
925
938
|
logger.debug(
|
|
926
939
|
"Error handling gossip data column",
|
|
@@ -1266,6 +1279,7 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1266
1279
|
seenTimestampSec,
|
|
1267
1280
|
}: GossipHandlerParamGeneric<GossipType.execution_payload>) => {
|
|
1268
1281
|
const {serializedData} = gossipData;
|
|
1282
|
+
validateGossipExecutionPayloadEnvelopeSerialized(chain, serializedData);
|
|
1269
1283
|
const signedEnvelope = sszDeserialize(topic, serializedData);
|
|
1270
1284
|
const envelope = signedEnvelope.message;
|
|
1271
1285
|
|
|
@@ -1318,17 +1332,23 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1318
1332
|
});
|
|
1319
1333
|
}
|
|
1320
1334
|
|
|
1335
|
+
// Add the envelope in the same tick as validation, otherwise a by-root download that completes
|
|
1336
|
+
// before the next event loop sees no envelope, validates it again and adds it first
|
|
1337
|
+
if (!payloadInput.hasPayloadEnvelope()) {
|
|
1338
|
+
chain.serializedCache.set(signedEnvelope, serializedData);
|
|
1339
|
+
|
|
1340
|
+
payloadInput.addPayloadEnvelope({
|
|
1341
|
+
envelope: signedEnvelope,
|
|
1342
|
+
source: PayloadEnvelopeInputSource.gossip,
|
|
1343
|
+
seenTimestampSec,
|
|
1344
|
+
peerIdStr,
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1321
1348
|
// Handler - deferred to next event loop so the validation result propagates first
|
|
1322
1349
|
callInNextEventLoop(() => {
|
|
1323
1350
|
try {
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
payloadInput.addPayloadEnvelope({
|
|
1327
|
-
envelope: signedEnvelope,
|
|
1328
|
-
source: PayloadEnvelopeInputSource.gossip,
|
|
1329
|
-
seenTimestampSec,
|
|
1330
|
-
peerIdStr,
|
|
1331
|
-
});
|
|
1351
|
+
scheduleIncompletePayloadEnvelope(payloadInput, peerIdStr);
|
|
1332
1352
|
|
|
1333
1353
|
chain.emitter.emit(routes.events.EventType.executionPayloadGossip, {
|
|
1334
1354
|
slot,
|
|
@@ -1337,12 +1357,18 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1337
1357
|
blockRoot: blockRootHex,
|
|
1338
1358
|
});
|
|
1339
1359
|
|
|
1340
|
-
|
|
1360
|
+
// Signature is verified above only for this envelope, one added by another source is verified at import
|
|
1361
|
+
const validSignature = payloadInput.getPayloadEnvelope() === signedEnvelope;
|
|
1362
|
+
chain.processExecutionPayload(payloadInput, {validSignature}).catch((e) => {
|
|
1341
1363
|
// Adjust verbosity based on error type
|
|
1342
1364
|
let logLevel: LogLevel;
|
|
1343
1365
|
|
|
1344
1366
|
if (e instanceof PayloadError) {
|
|
1345
1367
|
switch (e.type.code) {
|
|
1368
|
+
case PayloadErrorCode.DATA_UNAVAILABLE:
|
|
1369
|
+
// Columns did not arrive in time, BlockInputSync keeps pulling them and retries the import
|
|
1370
|
+
logLevel = LogLevel.debug;
|
|
1371
|
+
break;
|
|
1346
1372
|
// BLOCK_NOT_IN_FORK_CHOICE should not happen, validateGossipExecutionPayloadEnvelope above
|
|
1347
1373
|
// already verified the block is in fork choice
|
|
1348
1374
|
case PayloadErrorCode.BLOCK_NOT_IN_FORK_CHOICE:
|
|
@@ -1351,11 +1377,14 @@ function getSequentialHandlers(modules: ValidatorFnsModules, options: GossipHand
|
|
|
1351
1377
|
// Errors might indicate an issue with our node or the connected EL client
|
|
1352
1378
|
logLevel = LogLevel.error;
|
|
1353
1379
|
break;
|
|
1354
|
-
// INVALID_SIGNATURE
|
|
1380
|
+
// INVALID_SIGNATURE only happens for an envelope added by another source
|
|
1355
1381
|
case PayloadErrorCode.INVALID_SIGNATURE:
|
|
1356
1382
|
case PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR:
|
|
1357
1383
|
case PayloadErrorCode.EXECUTION_ENGINE_INVALID:
|
|
1358
|
-
|
|
1384
|
+
// Penalize only when the stored envelope is the one this peer sent, not one added by another source
|
|
1385
|
+
if (validSignature) {
|
|
1386
|
+
core.reportPeer(peerIdStr, PeerAction.LowToleranceError, "BadGossipPayload");
|
|
1387
|
+
}
|
|
1359
1388
|
// The builder may have signed another envelope that is valid, keeping this one would make
|
|
1360
1389
|
// by-root and range sync reuse it and never import the payload
|
|
1361
1390
|
chain.seenPayloadEnvelopeInputCache.removeInvalid(payloadInput);
|