@lodestar/beacon-node 1.48.0-dev.f22c5ce63e → 1.48.0-dev.ff9749be2c
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 +4 -11
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js +14 -0
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/config/index.d.ts.map +1 -1
- package/lib/api/impl/config/index.js +4 -1
- package/lib/api/impl/config/index.js.map +1 -1
- package/lib/api/impl/validator/index.d.ts.map +1 -1
- package/lib/api/impl/validator/index.js +39 -39
- package/lib/api/impl/validator/index.js.map +1 -1
- package/lib/chain/archiveStore/archiveStore.d.ts +1 -0
- package/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +5 -1
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js +1 -0
- package/lib/chain/archiveStore/historicalState/historicalStateRegen.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/metrics.js +12 -1
- package/lib/chain/archiveStore/historicalState/metrics.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.d.ts +2 -0
- package/lib/chain/archiveStore/historicalState/types.d.ts.map +1 -1
- package/lib/chain/archiveStore/historicalState/types.js.map +1 -1
- package/lib/chain/archiveStore/historicalState/worker.js +4 -1
- package/lib/chain/archiveStore/historicalState/worker.js.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts +9 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.d.ts.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +68 -38
- package/lib/chain/archiveStore/utils/archiveBlocks.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts +5 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +12 -18
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts +8 -4
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +83 -17
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/types.d.ts +8 -0
- package/lib/chain/blocks/types.d.ts.map +1 -1
- package/lib/chain/blocks/types.js.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts +1 -1
- package/lib/chain/blocks/utils/chainSegment.d.ts.map +1 -1
- package/lib/chain/blocks/utils/chainSegment.js +26 -11
- package/lib/chain/blocks/utils/chainSegment.js.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.d.ts.map +1 -1
- package/lib/chain/blocks/writeBlockInputToDb.js +9 -16
- package/lib/chain/blocks/writeBlockInputToDb.js.map +1 -1
- package/lib/chain/chain.d.ts +11 -5
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +129 -75
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/emitter.d.ts +1 -1
- package/lib/chain/emitter.js +1 -1
- package/lib/chain/errors/blockError.d.ts +14 -9
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +0 -2
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.d.ts +15 -2
- package/lib/chain/errors/dataColumnSidecarError.d.ts.map +1 -1
- package/lib/chain/errors/dataColumnSidecarError.js.map +1 -1
- package/lib/chain/errors/executionPayloadBid.d.ts +4 -0
- package/lib/chain/errors/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadBid.js +1 -0
- package/lib/chain/errors/executionPayloadBid.js.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.d.ts +10 -11
- package/lib/chain/errors/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/errors/executionPayloadEnvelope.js +0 -2
- package/lib/chain/errors/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/errors/gossipValidation.d.ts +2 -1
- package/lib/chain/errors/gossipValidation.d.ts.map +1 -1
- package/lib/chain/errors/gossipValidation.js +1 -0
- package/lib/chain/errors/gossipValidation.js.map +1 -1
- package/lib/chain/forkChoice/index.d.ts.map +1 -1
- package/lib/chain/forkChoice/index.js +2 -0
- package/lib/chain/forkChoice/index.js.map +1 -1
- package/lib/chain/interface.d.ts +4 -4
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/lightClient/index.d.ts +3 -3
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +21 -23
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/lightClient/proofs.d.ts +2 -1
- package/lib/chain/lightClient/proofs.d.ts.map +1 -1
- package/lib/chain/lightClient/proofs.js +5 -1
- package/lib/chain/lightClient/proofs.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/prepareNextSlot.d.ts.map +1 -1
- package/lib/chain/prepareNextSlot.js +16 -14
- package/lib/chain/prepareNextSlot.js.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.d.ts +4 -2
- package/lib/chain/produceBlock/produceBlockBody.d.ts.map +1 -1
- package/lib/chain/produceBlock/produceBlockBody.js +57 -72
- package/lib/chain/produceBlock/produceBlockBody.js.map +1 -1
- package/lib/chain/validation/block.d.ts.map +1 -1
- package/lib/chain/validation/block.js +27 -55
- package/lib/chain/validation/block.js.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.d.ts.map +1 -1
- package/lib/chain/validation/dataColumnSidecar.js +38 -13
- package/lib/chain/validation/dataColumnSidecar.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +56 -40
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +10 -29
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +5 -6
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validatorMonitor.d.ts +7 -1
- package/lib/chain/validatorMonitor.d.ts.map +1 -1
- package/lib/chain/validatorMonitor.js +22 -5
- package/lib/chain/validatorMonitor.js.map +1 -1
- package/lib/db/beacon.d.ts +14 -5
- package/lib/db/beacon.d.ts.map +1 -1
- package/lib/db/beacon.js +17 -3
- package/lib/db/beacon.js.map +1 -1
- package/lib/db/dataColumnStore.d.ts +39 -0
- package/lib/db/dataColumnStore.d.ts.map +1 -0
- package/lib/db/dataColumnStore.js +81 -0
- package/lib/db/dataColumnStore.js.map +1 -0
- package/lib/db/flatFileStore/atomicWrite.d.ts +8 -0
- package/lib/db/flatFileStore/atomicWrite.d.ts.map +1 -0
- package/lib/db/flatFileStore/atomicWrite.js +61 -0
- package/lib/db/flatFileStore/atomicWrite.js.map +1 -0
- package/lib/db/flatFileStore/dcolFormat.d.ts +90 -0
- package/lib/db/flatFileStore/dcolFormat.d.ts.map +1 -0
- package/lib/db/flatFileStore/dcolFormat.js +286 -0
- package/lib/db/flatFileStore/dcolFormat.js.map +1 -0
- package/lib/db/flatFileStore/errors.d.ts +82 -0
- package/lib/db/flatFileStore/errors.d.ts.map +1 -0
- package/lib/db/flatFileStore/errors.js +32 -0
- package/lib/db/flatFileStore/errors.js.map +1 -0
- package/lib/db/flatFileStore/flatFileStore.d.ts +41 -0
- package/lib/db/flatFileStore/flatFileStore.d.ts.map +1 -0
- package/lib/db/flatFileStore/flatFileStore.js +251 -0
- package/lib/db/flatFileStore/flatFileStore.js.map +1 -0
- package/lib/db/flatFileStore/index.d.ts +4 -0
- package/lib/db/flatFileStore/index.d.ts.map +1 -0
- package/lib/db/flatFileStore/index.js +2 -0
- package/lib/db/flatFileStore/index.js.map +1 -0
- package/lib/db/flatFileStore/interface.d.ts +25 -0
- package/lib/db/flatFileStore/interface.d.ts.map +1 -0
- package/lib/db/flatFileStore/interface.js +2 -0
- package/lib/db/flatFileStore/interface.js.map +1 -0
- package/lib/db/flatFileStore/metrics.d.ts +24 -0
- package/lib/db/flatFileStore/metrics.d.ts.map +1 -0
- package/lib/db/flatFileStore/metrics.js +25 -0
- package/lib/db/flatFileStore/metrics.js.map +1 -0
- package/lib/db/flatFileStore/path.d.ts +9 -0
- package/lib/db/flatFileStore/path.d.ts.map +1 -0
- package/lib/db/flatFileStore/path.js +21 -0
- package/lib/db/flatFileStore/path.js.map +1 -0
- package/lib/db/flatFileStore/slotIndex.d.ts +14 -0
- package/lib/db/flatFileStore/slotIndex.d.ts.map +1 -0
- package/lib/db/flatFileStore/slotIndex.js +46 -0
- package/lib/db/flatFileStore/slotIndex.js.map +1 -0
- package/lib/db/flatFileStore/snappy.d.ts +3 -0
- package/lib/db/flatFileStore/snappy.d.ts.map +1 -0
- package/lib/db/flatFileStore/snappy.js +12 -0
- package/lib/db/flatFileStore/snappy.js.map +1 -0
- package/lib/db/index.d.ts +1 -0
- package/lib/db/index.d.ts.map +1 -1
- package/lib/db/interface.d.ts +8 -1
- package/lib/db/interface.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.d.ts +8 -1
- package/lib/db/repositories/blockArchive.d.ts.map +1 -1
- package/lib/db/repositories/blockArchive.js +65 -28
- package/lib/db/repositories/blockArchive.js.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.d.ts +1 -2
- package/lib/db/repositories/blockArchiveIndex.d.ts.map +1 -1
- package/lib/db/repositories/blockArchiveIndex.js +3 -7
- package/lib/db/repositories/blockArchiveIndex.js.map +1 -1
- package/lib/execution/builder/validateBid.d.ts.map +1 -1
- package/lib/execution/builder/validateBid.js +8 -5
- package/lib/execution/builder/validateBid.js.map +1 -1
- package/lib/execution/engine/mock.d.ts.map +1 -1
- package/lib/execution/engine/mock.js +4 -1
- package/lib/execution/engine/mock.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +22 -3
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +60 -6
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/monitoring/clientStats.js +1 -1
- package/lib/monitoring/clientStats.js.map +1 -1
- package/lib/network/gossip/encoding.d.ts.map +1 -1
- package/lib/network/gossip/encoding.js +0 -7
- package/lib/network/gossip/encoding.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +2 -1
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +4 -20
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/libp2p/index.d.ts +9 -1
- package/lib/network/libp2p/index.d.ts.map +1 -1
- package/lib/network/libp2p/index.js +23 -0
- package/lib/network/libp2p/index.js.map +1 -1
- package/lib/network/network.js +2 -2
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +388 -285
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/processor/index.d.ts +49 -3
- package/lib/network/processor/index.d.ts.map +1 -1
- package/lib/network/processor/index.js +254 -114
- package/lib/network/processor/index.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js +112 -91
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRange.js.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.d.ts.map +1 -1
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js +2 -0
- package/lib/network/reqresp/handlers/dataColumnSidecarsByRoot.js.map +1 -1
- package/lib/network/reqresp/protocols.d.ts.map +1 -1
- package/lib/network/reqresp/protocols.js +6 -22
- package/lib/network/reqresp/protocols.js.map +1 -1
- package/lib/network/reqresp/rateLimit.js +2 -1
- package/lib/network/reqresp/rateLimit.js.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts +2 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.d.ts.map +1 -1
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js +14 -9
- package/lib/network/reqresp/utils/dataColumnResponseValidation.js.map +1 -1
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js +4 -2
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/range/range.d.ts.map +1 -1
- package/lib/sync/range/range.js +24 -1
- package/lib/sync/range/range.js.map +1 -1
- package/lib/util/sszBytes.d.ts +6 -0
- package/lib/util/sszBytes.d.ts.map +1 -1
- package/lib/util/sszBytes.js +1 -1
- package/lib/util/sszBytes.js.map +1 -1
- package/package.json +18 -19
- package/src/api/impl/beacon/blocks/index.ts +8 -14
- package/src/api/impl/beacon/state/utils.ts +15 -0
- package/src/api/impl/config/index.ts +4 -1
- package/src/api/impl/validator/index.ts +44 -43
- package/src/chain/archiveStore/archiveStore.ts +12 -1
- package/src/chain/archiveStore/historicalState/historicalStateRegen.ts +1 -0
- package/src/chain/archiveStore/historicalState/metrics.ts +14 -1
- package/src/chain/archiveStore/historicalState/types.ts +2 -0
- package/src/chain/archiveStore/historicalState/worker.ts +4 -1
- package/src/chain/archiveStore/utils/archiveBlocks.ts +73 -42
- package/src/chain/blocks/importBlock.ts +25 -20
- package/src/chain/blocks/index.ts +120 -23
- package/src/chain/blocks/types.ts +9 -0
- package/src/chain/blocks/utils/chainSegment.ts +26 -12
- package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
- package/src/chain/chain.ts +153 -84
- package/src/chain/emitter.ts +1 -1
- package/src/chain/errors/blockError.ts +19 -10
- package/src/chain/errors/dataColumnSidecarError.ts +24 -8
- package/src/chain/errors/executionPayloadBid.ts +2 -0
- package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
- package/src/chain/errors/gossipValidation.ts +1 -0
- package/src/chain/forkChoice/index.ts +2 -0
- package/src/chain/interface.ts +4 -4
- package/src/chain/lightClient/index.ts +32 -36
- package/src/chain/lightClient/proofs.ts +10 -0
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/prepareNextSlot.ts +21 -17
- package/src/chain/produceBlock/produceBlockBody.ts +62 -79
- package/src/chain/validation/block.ts +27 -72
- package/src/chain/validation/dataColumnSidecar.ts +47 -14
- package/src/chain/validation/executionPayloadBid.ts +62 -44
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
- package/src/chain/validation/payloadAttestationMessage.ts +8 -9
- package/src/chain/validatorMonitor.ts +24 -7
- package/src/db/beacon.ts +33 -6
- package/src/db/dataColumnStore.ts +113 -0
- package/src/db/flatFileStore/atomicWrite.ts +65 -0
- package/src/db/flatFileStore/dcolFormat.ts +389 -0
- package/src/db/flatFileStore/errors.ts +53 -0
- package/src/db/flatFileStore/flatFileStore.ts +310 -0
- package/src/db/flatFileStore/index.ts +3 -0
- package/src/db/flatFileStore/interface.ts +21 -0
- package/src/db/flatFileStore/metrics.ts +48 -0
- package/src/db/flatFileStore/path.ts +32 -0
- package/src/db/flatFileStore/slotIndex.ts +56 -0
- package/src/db/flatFileStore/snappy.ts +14 -0
- package/src/db/index.ts +1 -0
- package/src/db/interface.ts +9 -1
- package/src/db/repositories/blockArchive.ts +89 -30
- package/src/db/repositories/blockArchiveIndex.ts +4 -9
- package/src/execution/builder/validateBid.ts +10 -6
- package/src/execution/engine/mock.ts +4 -1
- package/src/metrics/metrics/lodestar.ts +63 -6
- package/src/monitoring/clientStats.ts +1 -1
- package/src/network/gossip/encoding.ts +0 -7
- package/src/network/gossip/topic.ts +3 -25
- package/src/network/libp2p/index.ts +28 -1
- package/src/network/network.ts +2 -2
- package/src/network/processor/gossipHandlers.ts +500 -355
- package/src/network/processor/index.ts +287 -165
- package/src/network/reqresp/handlers/dataColumnSidecarsByRange.ts +139 -105
- package/src/network/reqresp/handlers/dataColumnSidecarsByRoot.ts +2 -0
- package/src/network/reqresp/protocols.ts +7 -24
- package/src/network/reqresp/rateLimit.ts +2 -1
- package/src/network/reqresp/utils/dataColumnResponseValidation.ts +15 -7
- package/src/node/nodejs.ts +6 -1
- package/src/sync/range/range.ts +23 -1
- package/src/util/sszBytes.ts +1 -1
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { TopicValidatorResult } from "@libp2p/gossipsub";
|
|
2
2
|
import { routes } from "@lodestar/api";
|
|
3
|
-
import { ForkSeq } from "@lodestar/params";
|
|
3
|
+
import { ForkSeq, NUMBER_OF_COLUMNS } from "@lodestar/params";
|
|
4
4
|
import { computeStartSlotAtEpoch } from "@lodestar/state-transition";
|
|
5
5
|
import { MapDef, mapValues, sleep } from "@lodestar/utils";
|
|
6
6
|
import { BlockInputSource } from "../../chain/blocks/blockInput/types.js";
|
|
7
7
|
import { ChainEvent } from "../../chain/emitter.js";
|
|
8
8
|
import { GossipErrorCode } from "../../chain/errors/gossipValidation.js";
|
|
9
9
|
import { ClockEvent } from "../../util/clock.js";
|
|
10
|
-
import { callInNextEventLoop } from "../../util/eventLoop.js";
|
|
11
10
|
import { getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized, getDataIndexFromSignedAggregateAndProofSerialized, getDataIndexFromSingleAttestationSerialized, getParentBlockHashFromGloasSignedBeaconBlockSerialized, getParentBlockHashFromSignedExecutionPayloadBidSerialized, getParentBlockRootFromSignedExecutionPayloadBidSerialized, getParentRootFromSignedBeaconBlockSerialized, getPayloadPresentFromPayloadAttestationMessageSerialized, } from "../../util/sszBytes.js";
|
|
12
11
|
import { NetworkEvent } from "../events.js";
|
|
13
12
|
import { GossipType, } from "../gossip/interface.js";
|
|
@@ -21,6 +20,28 @@ export * from "./types.js";
|
|
|
21
20
|
* Keep up to 3 slot of unknown roots, so we don't always emit to UnknownBlock sync.
|
|
22
21
|
*/
|
|
23
22
|
const MAX_UNKNOWN_ROOTS_SLOT_CACHE_SIZE = 3;
|
|
23
|
+
/**
|
|
24
|
+
* Max distinct roots we BUFFER messages for, per slot. Kept tight to avoid the OOM
|
|
25
|
+
* risk. We don't support super forky condition where there are more than this many roots per slot via gossip.
|
|
26
|
+
*/
|
|
27
|
+
export const MAX_BUFFERED_ROOTS_PER_SLOT = 5;
|
|
28
|
+
/**
|
|
29
|
+
* Max distinct roots we emit an unknown-root search for, per slot. Higher than
|
|
30
|
+
* the buffer budget because:
|
|
31
|
+
* - in the attack scenario, the genuine root may comes after the first MAX_BUFFERED_ROOTS_PER_SLOT roots
|
|
32
|
+
* - if we cannot search, we'll penalize peers in UnknownBlockInput, not in NetworkProcessor
|
|
33
|
+
*/
|
|
34
|
+
export const MAX_SEARCHED_ROOTS_PER_SLOT = 32;
|
|
35
|
+
/**
|
|
36
|
+
* Given the same root and topic, we'll ignore messages after the below cap. Each cap is the number of
|
|
37
|
+
* legitimate messages we expect for one block, plus headroom for some malformed messages that may arrives first
|
|
38
|
+
* they will be penalized by the gossip handler
|
|
39
|
+
*/
|
|
40
|
+
export const MAX_AWAITING_MESSAGES_PER_ROOT = {
|
|
41
|
+
[GossipType.data_column_sidecar]: 2 * NUMBER_OF_COLUMNS,
|
|
42
|
+
[GossipType.execution_payload]: 2,
|
|
43
|
+
[GossipType.execution_payload_bid]: 8,
|
|
44
|
+
};
|
|
24
45
|
/**
|
|
25
46
|
* This is respective to gossipsub seenTTL (which is 550 * 0.7 = 385s), also it's respective
|
|
26
47
|
* to beacon_attestation ATTESTATION_PROPAGATION_SLOT_RANGE (32 slots).
|
|
@@ -73,6 +94,14 @@ export var ReprocessRejectReason;
|
|
|
73
94
|
* There are too many gossip messages that have unknown block root.
|
|
74
95
|
*/
|
|
75
96
|
ReprocessRejectReason["reached_limit"] = "reached_limit";
|
|
97
|
+
/**
|
|
98
|
+
* Too many distinct unknown roots are already tracked for the message's slot (MAX_UNKNOWN_ROOTS_PER_SLOT).
|
|
99
|
+
*/
|
|
100
|
+
ReprocessRejectReason["reached_root_limit"] = "reached_root_limit";
|
|
101
|
+
/**
|
|
102
|
+
* Too many gossip messages are already buffered for this (root, topic) (MAX_AWAITING_MESSAGES_PER_ROOT).
|
|
103
|
+
*/
|
|
104
|
+
ReprocessRejectReason["reached_topic_limit"] = "reached_topic_limit";
|
|
76
105
|
/**
|
|
77
106
|
* The awaiting gossip message is pruned per clock slot.
|
|
78
107
|
*/
|
|
@@ -133,15 +162,16 @@ export class NetworkProcessor {
|
|
|
133
162
|
gossipTopicConcurrency;
|
|
134
163
|
extractBlockSlotRootFns = createExtractBlockSlotRootFns();
|
|
135
164
|
// we may not receive the block for messages like Attestation and SignedAggregateAndProof messages, in that case PendingGossipsubMessage needs
|
|
136
|
-
// to be stored in this Map and reprocessed once the block comes
|
|
165
|
+
// to be stored in this Map and reprocessed once the block comes. Keyed by topic per root so we can cap
|
|
166
|
+
// the number of buffered messages per (root, topic) - see MAX_AWAITING_MESSAGES_PER_ROOT.
|
|
137
167
|
awaitingMessagesByBlockRoot;
|
|
138
168
|
awaitingBlockMessageCount = 0;
|
|
139
169
|
// we may not receive the payload for messages that require the FULL payload variant to be processed,
|
|
140
170
|
// in that case PendingGossipsubMessage needs to be stored in this Map and reprocessed once the payload comes
|
|
141
171
|
awaitingMessagesByPayloadBlockRoot;
|
|
142
172
|
awaitingPayloadMessageCount = 0;
|
|
143
|
-
|
|
144
|
-
|
|
173
|
+
searchedRootsBySlot = new MapDef(() => new MapDef(() => ({})));
|
|
174
|
+
bufferedRootsBySlot = new MapDef(() => new Set());
|
|
145
175
|
constructor(modules, opts) {
|
|
146
176
|
this.opts = opts;
|
|
147
177
|
const { chain, events, logger, metrics } = modules;
|
|
@@ -158,8 +188,8 @@ export class NetworkProcessor {
|
|
|
158
188
|
this.chain.emitter.on(routes.events.EventType.block, this.onBlockProcessed);
|
|
159
189
|
this.chain.emitter.on(routes.events.EventType.executionPayload, this.onPayloadEnvelopeProcessed);
|
|
160
190
|
this.chain.clock.on(ClockEvent.slot, this.onClockSlot);
|
|
161
|
-
this.awaitingMessagesByBlockRoot = new MapDef(() => new Set());
|
|
162
|
-
this.awaitingMessagesByPayloadBlockRoot = new MapDef(() => new Set());
|
|
191
|
+
this.awaitingMessagesByBlockRoot = new MapDef(() => new MapDef(() => new Set()));
|
|
192
|
+
this.awaitingMessagesByPayloadBlockRoot = new MapDef(() => new MapDef(() => new Set()));
|
|
163
193
|
// TODO: Implement queues and priorization for ReqResp incoming requests
|
|
164
194
|
// Listens to NetworkEvent.reqRespIncomingRequest event
|
|
165
195
|
if (metrics) {
|
|
@@ -211,9 +241,12 @@ export class NetworkProcessor {
|
|
|
211
241
|
if (this.chain.seenBlock(root)) {
|
|
212
242
|
return;
|
|
213
243
|
}
|
|
214
|
-
const
|
|
215
|
-
const alreadySearching =
|
|
216
|
-
|
|
244
|
+
const entry = this.searchedRootsBySlot.getOrDefault(slot).getOrDefault(root);
|
|
245
|
+
const alreadySearching = entry.blockPeerIds !== undefined;
|
|
246
|
+
if (entry.blockPeerIds === undefined) {
|
|
247
|
+
entry.blockPeerIds = new Set();
|
|
248
|
+
}
|
|
249
|
+
const forwardedPeers = entry.blockPeerIds;
|
|
217
250
|
// brand-new search always emits (peer may be undefined)
|
|
218
251
|
let shouldEmit = !alreadySearching;
|
|
219
252
|
if (peer !== undefined && !forwardedPeers.has(peer) && forwardedPeers.size < MAX_PEERS_PER_ROOT) {
|
|
@@ -235,10 +268,12 @@ export class NetworkProcessor {
|
|
|
235
268
|
if (this.chain.seenPayloadEnvelope(root)) {
|
|
236
269
|
return;
|
|
237
270
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
271
|
+
const entry = this.searchedRootsBySlot.getOrDefault(slot).getOrDefault(root);
|
|
272
|
+
const alreadySearching = entry.envelopePeerIds !== undefined;
|
|
273
|
+
if (entry.envelopePeerIds === undefined) {
|
|
274
|
+
entry.envelopePeerIds = new Set();
|
|
275
|
+
}
|
|
276
|
+
const forwardedPeers = entry.envelopePeerIds;
|
|
242
277
|
let shouldEmit = !alreadySearching; // brand-new search always emits (peer may be undefined)
|
|
243
278
|
if (peer !== undefined && !forwardedPeers.has(peer) && forwardedPeers.size < MAX_PEERS_PER_ROOT) {
|
|
244
279
|
// First time we forward THIS peer for THIS root: emit so BlockInputSync accumulates it.
|
|
@@ -281,14 +316,26 @@ export class NetworkProcessor {
|
|
|
281
316
|
});
|
|
282
317
|
return;
|
|
283
318
|
}
|
|
319
|
+
// DOS protection: drop far-future messages before allocating any unknown-root tracking entry.
|
|
320
|
+
// Bound each topic to what its gossip validator accepts; only execution_payload_bid accepts the next slot.
|
|
321
|
+
const latestPermissableSlot = this.chain.clock.currentSlotWithGossipDisparity + (topicType === GossipType.execution_payload_bid ? 1 : 0);
|
|
322
|
+
if (slot > latestPermissableSlot) {
|
|
323
|
+
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
324
|
+
this.metrics?.networkProcessor.gossipValidationError.inc({
|
|
325
|
+
topic: topicType,
|
|
326
|
+
error: GossipErrorCode.FUTURE_SLOT,
|
|
327
|
+
});
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
284
330
|
message.msgSlot = slot;
|
|
331
|
+
const peerId = message.propagationSource.toString();
|
|
285
332
|
// this determines whether this message needs to wait for a Block or Envelope
|
|
286
|
-
// a message should only wait for what it voted for, hence we don't want to put it on both queues
|
|
333
|
+
// a message should only wait for what it voted for, hence we don't want to put it on both queues.
|
|
287
334
|
let preprocessResult = { action: PreprocessAction.PushToQueue };
|
|
288
335
|
// no need to check if root is a descendant of the current finalized block, it will be checked once we validate the message if needed
|
|
289
336
|
if (root && !this.chain.forkChoice.hasBlockHexUnsafe(root)) {
|
|
290
337
|
// starting from GLOAS, unknown root from data_column_sidecar also falls into this case
|
|
291
|
-
this.
|
|
338
|
+
this.searchUnknownRoot({ slot, root }, true, false, peerId);
|
|
292
339
|
// for beacon_attestation and beacon_aggregate_and_proof messages, this is only temporary.
|
|
293
340
|
// if "index = 1" we need to await for the Envelope instead
|
|
294
341
|
preprocessResult = { action: PreprocessAction.AwaitBlock, root };
|
|
@@ -296,28 +343,32 @@ export class NetworkProcessor {
|
|
|
296
343
|
// 2nd extract round for some specific topics
|
|
297
344
|
// we separate the search action from the await action
|
|
298
345
|
// beacon_block: proactively search for parent block/envelope across all forks, but never queue.
|
|
299
|
-
// BlockInputSync handles cascading recovery if the gossip handler throws.
|
|
346
|
+
// BlockInputSync handles cascading recovery if the gossip handler throws. The parent root differs from
|
|
347
|
+
// the message root and this message never awaits, so its search flushes inline here (gated by the budget).
|
|
300
348
|
if (topicType === GossipType.beacon_block) {
|
|
301
349
|
const parentRoot = getParentRootFromSignedBeaconBlockSerialized(message.msg.data);
|
|
302
350
|
if (parentRoot) {
|
|
351
|
+
let searchParentBlock = false;
|
|
352
|
+
let searchParentEnvelope = false;
|
|
303
353
|
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
304
354
|
// GLOAS: also check parent envelope, same logic as execution_payload_bid
|
|
305
355
|
const parentBlockHash = getParentBlockHashFromGloasSignedBeaconBlockSerialized(message.msg.data);
|
|
306
356
|
if (parentBlockHash && !this.chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash)) {
|
|
307
357
|
const protoBlock = this.chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
308
358
|
if (protoBlock === null) {
|
|
309
|
-
|
|
359
|
+
searchParentBlock = true;
|
|
310
360
|
}
|
|
311
361
|
else if (protoBlock.executionPayloadBlockHash &&
|
|
312
362
|
protoBlock.executionPayloadBlockHash !== parentBlockHash) {
|
|
313
363
|
// only search for the envelope by block root if we're sure there is one. Otherwise UnknownBlockSync will penalize the peer.
|
|
314
|
-
|
|
364
|
+
searchParentEnvelope = true;
|
|
315
365
|
}
|
|
316
366
|
}
|
|
317
367
|
}
|
|
318
368
|
else if (!this.chain.forkChoice.hasBlockHexUnsafe(parentRoot)) {
|
|
319
|
-
|
|
369
|
+
searchParentBlock = true;
|
|
320
370
|
}
|
|
371
|
+
this.searchUnknownRoot({ slot, root: parentRoot }, searchParentBlock, searchParentEnvelope, peerId);
|
|
321
372
|
}
|
|
322
373
|
preprocessResult = { action: PreprocessAction.PushToQueue };
|
|
323
374
|
}
|
|
@@ -335,7 +386,7 @@ export class NetworkProcessor {
|
|
|
335
386
|
: getDataIndexFromSignedAggregateAndProofSerialized(message.msg.data);
|
|
336
387
|
if (attIndex === 1 && !this.chain.forkChoice.hasPayloadHexUnsafe(root)) {
|
|
337
388
|
// attestation votes that the payload is available but it is not yet known
|
|
338
|
-
this.
|
|
389
|
+
this.searchUnknownRoot({ slot, root }, false, true, peerId);
|
|
339
390
|
preprocessResult = { action: PreprocessAction.AwaitEnvelope, root };
|
|
340
391
|
}
|
|
341
392
|
break;
|
|
@@ -346,7 +397,7 @@ export class NetworkProcessor {
|
|
|
346
397
|
const payloadPresent = getPayloadPresentFromPayloadAttestationMessageSerialized(message.msg.data);
|
|
347
398
|
if (payloadPresent && !this.chain.forkChoice.hasPayloadHexUnsafe(root)) {
|
|
348
399
|
// payload attestation votes that the payload is available but it is not yet known
|
|
349
|
-
this.
|
|
400
|
+
this.searchUnknownRoot({ slot, root }, false, true, peerId);
|
|
350
401
|
// do not await the envelope, payload attestation processing only requires that the block is known
|
|
351
402
|
// also do not reset preprocessResult, we may already await for the block
|
|
352
403
|
}
|
|
@@ -356,7 +407,7 @@ export class NetworkProcessor {
|
|
|
356
407
|
if (root == null)
|
|
357
408
|
break;
|
|
358
409
|
if (!this.chain.forkChoice.hasPayloadHexUnsafe(root)) {
|
|
359
|
-
this.
|
|
410
|
+
this.searchUnknownRoot({ slot, root }, false, true, peerId);
|
|
360
411
|
// do not await the envelope, we can do gossip validation
|
|
361
412
|
// also do not reset preprocessResult, we may already await for the block
|
|
362
413
|
}
|
|
@@ -367,7 +418,7 @@ export class NetworkProcessor {
|
|
|
367
418
|
// Extract beacon_block_root directly
|
|
368
419
|
const blockRoot = getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(message.msg.data);
|
|
369
420
|
if (blockRoot && !this.chain.forkChoice.hasBlockHexUnsafe(blockRoot)) {
|
|
370
|
-
this.
|
|
421
|
+
this.searchUnknownRoot({ slot, root: blockRoot }, true, false, peerId);
|
|
371
422
|
// We always want to await the block
|
|
372
423
|
// This allows us to properly forward the payload envelope
|
|
373
424
|
preprocessResult = { action: PreprocessAction.AwaitBlock, root: blockRoot };
|
|
@@ -384,12 +435,12 @@ export class NetworkProcessor {
|
|
|
384
435
|
!this.chain.forkChoice.getBlockHexAndBlockHash(parentBlockRoot, parentBlockHash)) {
|
|
385
436
|
const protoBlock = this.chain.forkChoice.getBlockHexDefaultStatus(parentBlockRoot);
|
|
386
437
|
if (protoBlock === null) {
|
|
387
|
-
this.
|
|
438
|
+
this.searchUnknownRoot({ slot, root: parentBlockRoot }, true, false, peerId);
|
|
388
439
|
preprocessResult = { action: PreprocessAction.AwaitBlock, root: parentBlockRoot };
|
|
389
440
|
}
|
|
390
441
|
else if (protoBlock.executionPayloadBlockHash &&
|
|
391
442
|
protoBlock.executionPayloadBlockHash !== parentBlockHash) {
|
|
392
|
-
this.
|
|
443
|
+
this.searchUnknownRoot({ slot, root: parentBlockRoot }, false, true, peerId);
|
|
393
444
|
preprocessResult = { action: PreprocessAction.AwaitEnvelope, root: parentBlockRoot };
|
|
394
445
|
}
|
|
395
446
|
}
|
|
@@ -401,37 +452,96 @@ export class NetworkProcessor {
|
|
|
401
452
|
case PreprocessAction.PushToQueue:
|
|
402
453
|
this.pushPendingGossipsubMessageToQueue(message);
|
|
403
454
|
break;
|
|
404
|
-
case PreprocessAction.AwaitBlock:
|
|
405
|
-
|
|
406
|
-
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
407
|
-
this.metrics?.awaitingBlockGossipMessages.reject.inc({
|
|
408
|
-
reason: ReprocessRejectReason.reached_limit,
|
|
409
|
-
topic: topicType,
|
|
410
|
-
});
|
|
411
|
-
return;
|
|
412
|
-
}
|
|
413
|
-
this.metrics?.awaitingBlockGossipMessages.queue.inc({ topic: topicType });
|
|
414
|
-
const awaitingGossipsubMessages = this.awaitingMessagesByBlockRoot.getOrDefault(preprocessResult.root);
|
|
415
|
-
awaitingGossipsubMessages.add(message);
|
|
416
|
-
this.awaitingBlockMessageCount++;
|
|
455
|
+
case PreprocessAction.AwaitBlock:
|
|
456
|
+
this.maybeAwaitBlock(preprocessResult.root, topicType, slot, message);
|
|
417
457
|
break;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if (this.awaitingPayloadMessageCount > MAX_QUEUED_UNKNOWN_PAYLOAD_GOSSIP_OBJECTS) {
|
|
421
|
-
this.metrics?.awaitingPayloadGossipMessages.reject.inc({
|
|
422
|
-
reason: ReprocessRejectReason.reached_limit,
|
|
423
|
-
topic: topicType,
|
|
424
|
-
});
|
|
425
|
-
return;
|
|
426
|
-
}
|
|
427
|
-
this.metrics?.awaitingPayloadGossipMessages.queue.inc({ topic: topicType });
|
|
428
|
-
const awaitingPayloadGossipsubMessages = this.awaitingMessagesByPayloadBlockRoot.getOrDefault(preprocessResult.root);
|
|
429
|
-
awaitingPayloadGossipsubMessages.add(message);
|
|
430
|
-
this.awaitingPayloadMessageCount++;
|
|
458
|
+
case PreprocessAction.AwaitEnvelope:
|
|
459
|
+
this.maybeAwaitPayload(preprocessResult.root, topicType, slot, message);
|
|
431
460
|
break;
|
|
432
|
-
}
|
|
433
461
|
}
|
|
434
462
|
};
|
|
463
|
+
/**
|
|
464
|
+
* Buffer a gossip message that must wait for an unknown block before it can be validated.
|
|
465
|
+
*
|
|
466
|
+
* For DOS protection, the message is ignored (reject metric incremented) when any cap is hit:
|
|
467
|
+
* - MAX_QUEUED_UNKNOWN_BLOCK_GOSSIP_OBJECTS: global awaiting-block message count
|
|
468
|
+
* - MAX_BUFFERED_ROOTS_PER_SLOT: distinct roots we buffer messages for, per slot
|
|
469
|
+
* - MAX_AWAITING_MESSAGES_PER_ROOT[topic]: messages buffered per (root, topic)
|
|
470
|
+
*/
|
|
471
|
+
maybeAwaitBlock(root, topicType, slot, message) {
|
|
472
|
+
const metric = this.metrics?.awaitingBlockGossipMessages;
|
|
473
|
+
// global message-count cap - cheapest check first
|
|
474
|
+
if (this.awaitingBlockMessageCount > MAX_QUEUED_UNKNOWN_BLOCK_GOSSIP_OBJECTS) {
|
|
475
|
+
metric?.reject.inc({ reason: ReprocessRejectReason.reached_limit, topic: topicType });
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
// per-(root, topic) message cap: e.g. <= NUMBER_OF_COLUMNS columns per root
|
|
479
|
+
const perRootCap = MAX_AWAITING_MESSAGES_PER_ROOT[topicType];
|
|
480
|
+
if (perRootCap !== undefined &&
|
|
481
|
+
(this.awaitingMessagesByBlockRoot.get(root)?.get(topicType)?.size ?? 0) >= perRootCap) {
|
|
482
|
+
metric?.reject.inc({ reason: ReprocessRejectReason.reached_topic_limit, topic: topicType });
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
if (!this.tryReserveBufferedRoot(slot, root)) {
|
|
486
|
+
metric?.reject.inc({ reason: ReprocessRejectReason.reached_root_limit, topic: topicType });
|
|
487
|
+
return;
|
|
488
|
+
}
|
|
489
|
+
metric?.queue.inc({ topic: topicType });
|
|
490
|
+
this.awaitingMessagesByBlockRoot.getOrDefault(root).getOrDefault(topicType).add(message);
|
|
491
|
+
this.awaitingBlockMessageCount++;
|
|
492
|
+
}
|
|
493
|
+
/** Payload counterpart of maybeAwaitBlock */
|
|
494
|
+
maybeAwaitPayload(root, topicType, slot, message) {
|
|
495
|
+
const metric = this.metrics?.awaitingPayloadGossipMessages;
|
|
496
|
+
if (this.awaitingPayloadMessageCount > MAX_QUEUED_UNKNOWN_PAYLOAD_GOSSIP_OBJECTS) {
|
|
497
|
+
metric?.reject.inc({ reason: ReprocessRejectReason.reached_limit, topic: topicType });
|
|
498
|
+
return;
|
|
499
|
+
}
|
|
500
|
+
const perRootCap = MAX_AWAITING_MESSAGES_PER_ROOT[topicType];
|
|
501
|
+
if (perRootCap !== undefined &&
|
|
502
|
+
(this.awaitingMessagesByPayloadBlockRoot.get(root)?.get(topicType)?.size ?? 0) >= perRootCap) {
|
|
503
|
+
metric?.reject.inc({ reason: ReprocessRejectReason.reached_topic_limit, topic: topicType });
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
if (!this.tryReserveBufferedRoot(slot, root)) {
|
|
507
|
+
metric?.reject.inc({ reason: ReprocessRejectReason.reached_root_limit, topic: topicType });
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
metric?.queue.inc({ topic: topicType });
|
|
511
|
+
this.awaitingMessagesByPayloadBlockRoot.getOrDefault(root).getOrDefault(topicType).add(message);
|
|
512
|
+
this.awaitingPayloadMessageCount++;
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Cap distinct roots we emit an unknown-root search for, an already-tracked root (dedup) never counts as "too many".
|
|
516
|
+
*/
|
|
517
|
+
tooManySearchedRoots(slot, root) {
|
|
518
|
+
const roots = this.searchedRootsBySlot.get(slot);
|
|
519
|
+
if (roots === undefined)
|
|
520
|
+
return false;
|
|
521
|
+
return !roots.has(root) && roots.size >= MAX_SEARCHED_ROOTS_PER_SLOT;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Cap distinct roots we buffer per slot.
|
|
525
|
+
*/
|
|
526
|
+
tryReserveBufferedRoot(slot, root) {
|
|
527
|
+
const roots = this.bufferedRootsBySlot.get(slot);
|
|
528
|
+
if (roots?.has(root))
|
|
529
|
+
return true;
|
|
530
|
+
if ((roots?.size ?? 0) >= MAX_BUFFERED_ROOTS_PER_SLOT)
|
|
531
|
+
return false;
|
|
532
|
+
this.bufferedRootsBySlot.getOrDefault(slot).add(root);
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
searchUnknownRoot(slotRoot, searchBlock, searchEnvelope, peerId) {
|
|
536
|
+
if (!searchBlock && !searchEnvelope)
|
|
537
|
+
return;
|
|
538
|
+
if (this.tooManySearchedRoots(slotRoot.slot, slotRoot.root))
|
|
539
|
+
return;
|
|
540
|
+
if (searchBlock)
|
|
541
|
+
this.searchUnknownBlock(slotRoot, BlockInputSource.network_processor, peerId);
|
|
542
|
+
if (searchEnvelope)
|
|
543
|
+
this.searchUnknownEnvelope(slotRoot, BlockInputSource.network_processor, peerId);
|
|
544
|
+
}
|
|
435
545
|
pushPendingGossipsubMessageToQueue(message) {
|
|
436
546
|
const topicType = message.topic.type;
|
|
437
547
|
message.queueAddedMs = Date.now();
|
|
@@ -444,66 +554,92 @@ export class NetworkProcessor {
|
|
|
444
554
|
this.executeWork();
|
|
445
555
|
}
|
|
446
556
|
onBlockProcessed = async ({ block: rootHex }) => {
|
|
447
|
-
const
|
|
448
|
-
if (
|
|
557
|
+
const messagesByTopic = this.awaitingMessagesByBlockRoot.get(rootHex);
|
|
558
|
+
if (messagesByTopic === undefined) {
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
let total = 0;
|
|
562
|
+
for (const messages of messagesByTopic.values()) {
|
|
563
|
+
total += messages.size;
|
|
564
|
+
}
|
|
565
|
+
if (total === 0) {
|
|
449
566
|
return;
|
|
450
567
|
}
|
|
451
568
|
// Atomically remove from map and update counter before async iteration to
|
|
452
569
|
// prevent double-decrement race with onClockSlot during yield points below
|
|
453
570
|
if (this.awaitingMessagesByBlockRoot.delete(rootHex)) {
|
|
454
|
-
this.awaitingBlockMessageCount -=
|
|
571
|
+
this.awaitingBlockMessageCount -= total;
|
|
455
572
|
}
|
|
456
573
|
const nowSec = Date.now() / 1000;
|
|
457
574
|
let count = 0;
|
|
458
575
|
// TODO: we can group attestations to process in batches but since we have the SeenAttestationDatas
|
|
459
576
|
// cache, it may not be necessary at this time
|
|
460
|
-
for (const
|
|
461
|
-
const
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
count
|
|
469
|
-
|
|
577
|
+
for (const messages of messagesByTopic.values()) {
|
|
578
|
+
for (const message of messages) {
|
|
579
|
+
const topicType = message.topic.type;
|
|
580
|
+
this.metrics?.awaitingBlockGossipMessages.waitSecBeforeResolve.set({ topic: topicType }, nowSec - message.seenTimestampSec);
|
|
581
|
+
this.metrics?.awaitingBlockGossipMessages.resolve.inc({ topic: topicType });
|
|
582
|
+
this.pushPendingGossipsubMessageToQueue(message);
|
|
583
|
+
count++;
|
|
584
|
+
// don't want to block the event loop, worse case it'd wait for 16_084 / 1024 * 50ms = 800ms which is not a big deal
|
|
585
|
+
if (count === MAX_AWAITING_GOSSIP_OBJECTS_PER_TICK) {
|
|
586
|
+
count = 0;
|
|
587
|
+
await sleep(AWAITING_GOSSIP_OBJECTS_YIELD_EVERY_MS);
|
|
588
|
+
}
|
|
470
589
|
}
|
|
471
590
|
}
|
|
472
591
|
};
|
|
473
592
|
onPayloadEnvelopeProcessed = async ({ blockRoot: rootHex }) => {
|
|
474
|
-
const
|
|
475
|
-
if (
|
|
593
|
+
const messagesByTopic = this.awaitingMessagesByPayloadBlockRoot.get(rootHex);
|
|
594
|
+
if (messagesByTopic === undefined) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
let total = 0;
|
|
598
|
+
for (const messages of messagesByTopic.values()) {
|
|
599
|
+
total += messages.size;
|
|
600
|
+
}
|
|
601
|
+
if (total === 0) {
|
|
476
602
|
return;
|
|
477
603
|
}
|
|
478
604
|
// Atomically remove from map and update counter before async iteration to
|
|
479
605
|
// prevent double-decrement race with onClockSlot during yield points below
|
|
480
606
|
if (this.awaitingMessagesByPayloadBlockRoot.delete(rootHex)) {
|
|
481
|
-
this.awaitingPayloadMessageCount -=
|
|
607
|
+
this.awaitingPayloadMessageCount -= total;
|
|
482
608
|
}
|
|
483
609
|
const nowSec = Date.now() / 1000;
|
|
484
610
|
let count = 0;
|
|
485
|
-
for (const
|
|
486
|
-
const
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
count
|
|
493
|
-
|
|
611
|
+
for (const messages of messagesByTopic.values()) {
|
|
612
|
+
for (const message of messages) {
|
|
613
|
+
const topicType = message.topic.type;
|
|
614
|
+
this.metrics?.awaitingPayloadGossipMessages.waitSecBeforeResolve.set({ topic: topicType }, nowSec - message.seenTimestampSec);
|
|
615
|
+
this.metrics?.awaitingPayloadGossipMessages.resolve.inc({ topic: topicType });
|
|
616
|
+
this.pushPendingGossipsubMessageToQueue(message);
|
|
617
|
+
count++;
|
|
618
|
+
if (count === MAX_AWAITING_GOSSIP_OBJECTS_PER_TICK) {
|
|
619
|
+
count = 0;
|
|
620
|
+
await sleep(AWAITING_GOSSIP_OBJECTS_YIELD_EVERY_MS);
|
|
621
|
+
}
|
|
494
622
|
}
|
|
495
623
|
}
|
|
496
624
|
};
|
|
497
625
|
onClockSlot = (clockSlot) => {
|
|
498
626
|
const nowSec = Date.now() / 1000;
|
|
499
627
|
const minSlot = clockSlot - MAX_UNKNOWN_ROOTS_SLOT_CACHE_SIZE;
|
|
500
|
-
for (const [slot,
|
|
628
|
+
for (const [slot, searchedRoots] of this.searchedRootsBySlot) {
|
|
501
629
|
if (slot > minSlot)
|
|
502
630
|
continue;
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
631
|
+
// expire messages awaiting an unknown block for these roots. Only roots this slot did a BLOCK search
|
|
632
|
+
// for (blockPeerIds set) have block waits keyed here; skipping the rest avoids deleting a payload wait
|
|
633
|
+
// that a newer slot created for the same root (block/envelope searches share searchedRootsBySlot).
|
|
634
|
+
for (const [rootHex, entry] of searchedRoots) {
|
|
635
|
+
if (entry.blockPeerIds === undefined)
|
|
636
|
+
continue;
|
|
637
|
+
const messagesByTopic = this.awaitingMessagesByBlockRoot.get(rootHex);
|
|
638
|
+
if (messagesByTopic === undefined)
|
|
639
|
+
continue;
|
|
640
|
+
let removed = 0;
|
|
641
|
+
for (const messages of messagesByTopic.values()) {
|
|
642
|
+
for (const message of messages) {
|
|
507
643
|
const topicType = message.topic.type;
|
|
508
644
|
this.metrics?.awaitingBlockGossipMessages.reject.inc({
|
|
509
645
|
topic: topicType,
|
|
@@ -512,20 +648,23 @@ export class NetworkProcessor {
|
|
|
512
648
|
this.metrics?.awaitingBlockGossipMessages.waitSecBeforeReject.set({ topic: topicType, reason: ReprocessRejectReason.expired }, nowSec - message.seenTimestampSec);
|
|
513
649
|
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
514
650
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
651
|
+
removed += messages.size;
|
|
652
|
+
}
|
|
653
|
+
if (this.awaitingMessagesByBlockRoot.delete(rootHex)) {
|
|
654
|
+
this.awaitingBlockMessageCount -= removed;
|
|
518
655
|
}
|
|
519
656
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
657
|
+
// expire messages awaiting an unknown payload envelope for these roots. Symmetric to the block pass:
|
|
658
|
+
// only roots this slot did an ENVELOPE search for (envelopePeerIds set) have payload waits keyed here.
|
|
659
|
+
for (const [rootHex, entry] of searchedRoots) {
|
|
660
|
+
if (entry.envelopePeerIds === undefined)
|
|
661
|
+
continue;
|
|
662
|
+
const messagesByTopic = this.awaitingMessagesByPayloadBlockRoot.get(rootHex);
|
|
663
|
+
if (messagesByTopic === undefined)
|
|
664
|
+
continue;
|
|
665
|
+
let removed = 0;
|
|
666
|
+
for (const messages of messagesByTopic.values()) {
|
|
667
|
+
for (const message of messages) {
|
|
529
668
|
const topicType = message.topic.type;
|
|
530
669
|
this.metrics?.awaitingPayloadGossipMessages.reject.inc({
|
|
531
670
|
topic: topicType,
|
|
@@ -534,12 +673,17 @@ export class NetworkProcessor {
|
|
|
534
673
|
this.metrics?.awaitingPayloadGossipMessages.waitSecBeforeReject.set({ topic: topicType, reason: ReprocessRejectReason.expired }, nowSec - message.seenTimestampSec);
|
|
535
674
|
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
536
675
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
676
|
+
removed += messages.size;
|
|
677
|
+
}
|
|
678
|
+
if (this.awaitingMessagesByPayloadBlockRoot.delete(rootHex)) {
|
|
679
|
+
this.awaitingPayloadMessageCount -= removed;
|
|
540
680
|
}
|
|
541
681
|
}
|
|
542
|
-
this.
|
|
682
|
+
this.searchedRootsBySlot.delete(slot);
|
|
683
|
+
}
|
|
684
|
+
for (const slot of this.bufferedRootsBySlot.keys()) {
|
|
685
|
+
if (slot <= minSlot)
|
|
686
|
+
this.bufferedRootsBySlot.delete(slot);
|
|
543
687
|
}
|
|
544
688
|
};
|
|
545
689
|
executeWork() {
|
|
@@ -614,27 +758,23 @@ export class NetworkProcessor {
|
|
|
614
758
|
else {
|
|
615
759
|
this.trackJobTime(messageOrArray, 1, acceptanceArr[0]);
|
|
616
760
|
}
|
|
617
|
-
//
|
|
618
|
-
//
|
|
619
|
-
//
|
|
761
|
+
// Report the validation verdict synchronously so it reaches the network worker before any deferred
|
|
762
|
+
// handler (e.g. block import) runs on the next event loop. At network thread side, gossipsub onValidationResult()
|
|
763
|
+
// has its own callInNextEventLoop
|
|
620
764
|
if (Array.isArray(messageOrArray)) {
|
|
621
765
|
for (const [i, msg] of messageOrArray.entries()) {
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
acceptance: acceptanceArr[i],
|
|
627
|
-
});
|
|
766
|
+
this.events.emit(NetworkEvent.gossipMessageValidationResult, {
|
|
767
|
+
msgId: msg.msgId,
|
|
768
|
+
propagationSource: msg.propagationSource,
|
|
769
|
+
acceptance: acceptanceArr[i],
|
|
628
770
|
});
|
|
629
771
|
}
|
|
630
772
|
}
|
|
631
773
|
else {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
acceptance: acceptanceArr[0],
|
|
637
|
-
});
|
|
774
|
+
this.events.emit(NetworkEvent.gossipMessageValidationResult, {
|
|
775
|
+
msgId: messageOrArray.msgId,
|
|
776
|
+
propagationSource: messageOrArray.propagationSource,
|
|
777
|
+
acceptance: acceptanceArr[0],
|
|
638
778
|
});
|
|
639
779
|
}
|
|
640
780
|
}
|