@lodestar/beacon-node 1.48.0-dev.e25eb75f31 → 1.48.0-dev.ec85b38ca5
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 -4
- package/lib/api/impl/beacon/blocks/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 +1 -0
- 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.map +1 -1
- package/lib/chain/archiveStore/utils/archiveBlocks.js +31 -34
- 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 +0 -13
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +3 -2
- package/lib/chain/blocks/index.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 +10 -1
- 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 +9 -3
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +127 -73
- 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 +19 -7
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +2 -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/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/interface.d.ts +2 -2
- package/lib/chain/interface.d.ts.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 +35 -54
- 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/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/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/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 +18 -0
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +55 -1
- 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/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +6 -7
- 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 +232 -98
- 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/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 -4
- package/src/api/impl/validator/index.ts +44 -43
- package/src/chain/archiveStore/archiveStore.ts +6 -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 +34 -39
- package/src/chain/blocks/importBlock.ts +0 -13
- package/src/chain/blocks/index.ts +13 -2
- package/src/chain/blocks/utils/chainSegment.ts +10 -1
- package/src/chain/blocks/writeBlockInputToDb.ts +10 -17
- package/src/chain/chain.ts +149 -80
- package/src/chain/emitter.ts +1 -1
- package/src/chain/errors/blockError.ts +22 -10
- package/src/chain/errors/dataColumnSidecarError.ts +24 -8
- package/src/chain/errors/executionPayloadEnvelope.ts +14 -11
- package/src/chain/interface.ts +2 -2
- package/src/chain/prepareNextSlot.ts +21 -17
- package/src/chain/produceBlock/produceBlockBody.ts +62 -79
- package/src/chain/validation/block.ts +35 -70
- package/src/chain/validation/dataColumnSidecar.ts +47 -14
- package/src/chain/validation/executionPayloadEnvelope.ts +10 -37
- 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/engine/mock.ts +4 -1
- package/src/metrics/metrics/lodestar.ts +57 -1
- 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/processor/gossipHandlers.ts +11 -11
- package/src/network/processor/index.ts +263 -148
- 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/util/sszBytes.ts +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
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";
|
|
@@ -20,6 +20,28 @@ export * from "./types.js";
|
|
|
20
20
|
* Keep up to 3 slot of unknown roots, so we don't always emit to UnknownBlock sync.
|
|
21
21
|
*/
|
|
22
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
|
+
};
|
|
23
45
|
/**
|
|
24
46
|
* This is respective to gossipsub seenTTL (which is 550 * 0.7 = 385s), also it's respective
|
|
25
47
|
* to beacon_attestation ATTESTATION_PROPAGATION_SLOT_RANGE (32 slots).
|
|
@@ -72,6 +94,14 @@ export var ReprocessRejectReason;
|
|
|
72
94
|
* There are too many gossip messages that have unknown block root.
|
|
73
95
|
*/
|
|
74
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";
|
|
75
105
|
/**
|
|
76
106
|
* The awaiting gossip message is pruned per clock slot.
|
|
77
107
|
*/
|
|
@@ -132,15 +162,16 @@ export class NetworkProcessor {
|
|
|
132
162
|
gossipTopicConcurrency;
|
|
133
163
|
extractBlockSlotRootFns = createExtractBlockSlotRootFns();
|
|
134
164
|
// we may not receive the block for messages like Attestation and SignedAggregateAndProof messages, in that case PendingGossipsubMessage needs
|
|
135
|
-
// 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.
|
|
136
167
|
awaitingMessagesByBlockRoot;
|
|
137
168
|
awaitingBlockMessageCount = 0;
|
|
138
169
|
// we may not receive the payload for messages that require the FULL payload variant to be processed,
|
|
139
170
|
// in that case PendingGossipsubMessage needs to be stored in this Map and reprocessed once the payload comes
|
|
140
171
|
awaitingMessagesByPayloadBlockRoot;
|
|
141
172
|
awaitingPayloadMessageCount = 0;
|
|
142
|
-
|
|
143
|
-
|
|
173
|
+
searchedRootsBySlot = new MapDef(() => new MapDef(() => ({})));
|
|
174
|
+
bufferedRootsBySlot = new MapDef(() => new Set());
|
|
144
175
|
constructor(modules, opts) {
|
|
145
176
|
this.opts = opts;
|
|
146
177
|
const { chain, events, logger, metrics } = modules;
|
|
@@ -157,8 +188,8 @@ export class NetworkProcessor {
|
|
|
157
188
|
this.chain.emitter.on(routes.events.EventType.block, this.onBlockProcessed);
|
|
158
189
|
this.chain.emitter.on(routes.events.EventType.executionPayload, this.onPayloadEnvelopeProcessed);
|
|
159
190
|
this.chain.clock.on(ClockEvent.slot, this.onClockSlot);
|
|
160
|
-
this.awaitingMessagesByBlockRoot = new MapDef(() => new Set());
|
|
161
|
-
this.awaitingMessagesByPayloadBlockRoot = new MapDef(() => new Set());
|
|
191
|
+
this.awaitingMessagesByBlockRoot = new MapDef(() => new MapDef(() => new Set()));
|
|
192
|
+
this.awaitingMessagesByPayloadBlockRoot = new MapDef(() => new MapDef(() => new Set()));
|
|
162
193
|
// TODO: Implement queues and priorization for ReqResp incoming requests
|
|
163
194
|
// Listens to NetworkEvent.reqRespIncomingRequest event
|
|
164
195
|
if (metrics) {
|
|
@@ -210,9 +241,12 @@ export class NetworkProcessor {
|
|
|
210
241
|
if (this.chain.seenBlock(root)) {
|
|
211
242
|
return;
|
|
212
243
|
}
|
|
213
|
-
const
|
|
214
|
-
const alreadySearching =
|
|
215
|
-
|
|
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;
|
|
216
250
|
// brand-new search always emits (peer may be undefined)
|
|
217
251
|
let shouldEmit = !alreadySearching;
|
|
218
252
|
if (peer !== undefined && !forwardedPeers.has(peer) && forwardedPeers.size < MAX_PEERS_PER_ROOT) {
|
|
@@ -234,10 +268,12 @@ export class NetworkProcessor {
|
|
|
234
268
|
if (this.chain.seenPayloadEnvelope(root)) {
|
|
235
269
|
return;
|
|
236
270
|
}
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
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;
|
|
241
277
|
let shouldEmit = !alreadySearching; // brand-new search always emits (peer may be undefined)
|
|
242
278
|
if (peer !== undefined && !forwardedPeers.has(peer) && forwardedPeers.size < MAX_PEERS_PER_ROOT) {
|
|
243
279
|
// First time we forward THIS peer for THIS root: emit so BlockInputSync accumulates it.
|
|
@@ -292,13 +328,14 @@ export class NetworkProcessor {
|
|
|
292
328
|
return;
|
|
293
329
|
}
|
|
294
330
|
message.msgSlot = slot;
|
|
331
|
+
const peerId = message.propagationSource.toString();
|
|
295
332
|
// this determines whether this message needs to wait for a Block or Envelope
|
|
296
|
-
// 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.
|
|
297
334
|
let preprocessResult = { action: PreprocessAction.PushToQueue };
|
|
298
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
|
|
299
336
|
if (root && !this.chain.forkChoice.hasBlockHexUnsafe(root)) {
|
|
300
337
|
// starting from GLOAS, unknown root from data_column_sidecar also falls into this case
|
|
301
|
-
this.
|
|
338
|
+
this.searchUnknownRoot({ slot, root }, true, false, peerId);
|
|
302
339
|
// for beacon_attestation and beacon_aggregate_and_proof messages, this is only temporary.
|
|
303
340
|
// if "index = 1" we need to await for the Envelope instead
|
|
304
341
|
preprocessResult = { action: PreprocessAction.AwaitBlock, root };
|
|
@@ -306,28 +343,32 @@ export class NetworkProcessor {
|
|
|
306
343
|
// 2nd extract round for some specific topics
|
|
307
344
|
// we separate the search action from the await action
|
|
308
345
|
// beacon_block: proactively search for parent block/envelope across all forks, but never queue.
|
|
309
|
-
// 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).
|
|
310
348
|
if (topicType === GossipType.beacon_block) {
|
|
311
349
|
const parentRoot = getParentRootFromSignedBeaconBlockSerialized(message.msg.data);
|
|
312
350
|
if (parentRoot) {
|
|
351
|
+
let searchParentBlock = false;
|
|
352
|
+
let searchParentEnvelope = false;
|
|
313
353
|
if (ForkSeq[fork] >= ForkSeq.gloas) {
|
|
314
354
|
// GLOAS: also check parent envelope, same logic as execution_payload_bid
|
|
315
355
|
const parentBlockHash = getParentBlockHashFromGloasSignedBeaconBlockSerialized(message.msg.data);
|
|
316
356
|
if (parentBlockHash && !this.chain.forkChoice.getBlockHexAndBlockHash(parentRoot, parentBlockHash)) {
|
|
317
357
|
const protoBlock = this.chain.forkChoice.getBlockHexDefaultStatus(parentRoot);
|
|
318
358
|
if (protoBlock === null) {
|
|
319
|
-
|
|
359
|
+
searchParentBlock = true;
|
|
320
360
|
}
|
|
321
361
|
else if (protoBlock.executionPayloadBlockHash &&
|
|
322
362
|
protoBlock.executionPayloadBlockHash !== parentBlockHash) {
|
|
323
363
|
// only search for the envelope by block root if we're sure there is one. Otherwise UnknownBlockSync will penalize the peer.
|
|
324
|
-
|
|
364
|
+
searchParentEnvelope = true;
|
|
325
365
|
}
|
|
326
366
|
}
|
|
327
367
|
}
|
|
328
368
|
else if (!this.chain.forkChoice.hasBlockHexUnsafe(parentRoot)) {
|
|
329
|
-
|
|
369
|
+
searchParentBlock = true;
|
|
330
370
|
}
|
|
371
|
+
this.searchUnknownRoot({ slot, root: parentRoot }, searchParentBlock, searchParentEnvelope, peerId);
|
|
331
372
|
}
|
|
332
373
|
preprocessResult = { action: PreprocessAction.PushToQueue };
|
|
333
374
|
}
|
|
@@ -345,7 +386,7 @@ export class NetworkProcessor {
|
|
|
345
386
|
: getDataIndexFromSignedAggregateAndProofSerialized(message.msg.data);
|
|
346
387
|
if (attIndex === 1 && !this.chain.forkChoice.hasPayloadHexUnsafe(root)) {
|
|
347
388
|
// attestation votes that the payload is available but it is not yet known
|
|
348
|
-
this.
|
|
389
|
+
this.searchUnknownRoot({ slot, root }, false, true, peerId);
|
|
349
390
|
preprocessResult = { action: PreprocessAction.AwaitEnvelope, root };
|
|
350
391
|
}
|
|
351
392
|
break;
|
|
@@ -356,7 +397,7 @@ export class NetworkProcessor {
|
|
|
356
397
|
const payloadPresent = getPayloadPresentFromPayloadAttestationMessageSerialized(message.msg.data);
|
|
357
398
|
if (payloadPresent && !this.chain.forkChoice.hasPayloadHexUnsafe(root)) {
|
|
358
399
|
// payload attestation votes that the payload is available but it is not yet known
|
|
359
|
-
this.
|
|
400
|
+
this.searchUnknownRoot({ slot, root }, false, true, peerId);
|
|
360
401
|
// do not await the envelope, payload attestation processing only requires that the block is known
|
|
361
402
|
// also do not reset preprocessResult, we may already await for the block
|
|
362
403
|
}
|
|
@@ -366,7 +407,7 @@ export class NetworkProcessor {
|
|
|
366
407
|
if (root == null)
|
|
367
408
|
break;
|
|
368
409
|
if (!this.chain.forkChoice.hasPayloadHexUnsafe(root)) {
|
|
369
|
-
this.
|
|
410
|
+
this.searchUnknownRoot({ slot, root }, false, true, peerId);
|
|
370
411
|
// do not await the envelope, we can do gossip validation
|
|
371
412
|
// also do not reset preprocessResult, we may already await for the block
|
|
372
413
|
}
|
|
@@ -377,7 +418,7 @@ export class NetworkProcessor {
|
|
|
377
418
|
// Extract beacon_block_root directly
|
|
378
419
|
const blockRoot = getBeaconBlockRootFromExecutionPayloadEnvelopeSerialized(message.msg.data);
|
|
379
420
|
if (blockRoot && !this.chain.forkChoice.hasBlockHexUnsafe(blockRoot)) {
|
|
380
|
-
this.
|
|
421
|
+
this.searchUnknownRoot({ slot, root: blockRoot }, true, false, peerId);
|
|
381
422
|
// We always want to await the block
|
|
382
423
|
// This allows us to properly forward the payload envelope
|
|
383
424
|
preprocessResult = { action: PreprocessAction.AwaitBlock, root: blockRoot };
|
|
@@ -394,12 +435,12 @@ export class NetworkProcessor {
|
|
|
394
435
|
!this.chain.forkChoice.getBlockHexAndBlockHash(parentBlockRoot, parentBlockHash)) {
|
|
395
436
|
const protoBlock = this.chain.forkChoice.getBlockHexDefaultStatus(parentBlockRoot);
|
|
396
437
|
if (protoBlock === null) {
|
|
397
|
-
this.
|
|
438
|
+
this.searchUnknownRoot({ slot, root: parentBlockRoot }, true, false, peerId);
|
|
398
439
|
preprocessResult = { action: PreprocessAction.AwaitBlock, root: parentBlockRoot };
|
|
399
440
|
}
|
|
400
441
|
else if (protoBlock.executionPayloadBlockHash &&
|
|
401
442
|
protoBlock.executionPayloadBlockHash !== parentBlockHash) {
|
|
402
|
-
this.
|
|
443
|
+
this.searchUnknownRoot({ slot, root: parentBlockRoot }, false, true, peerId);
|
|
403
444
|
preprocessResult = { action: PreprocessAction.AwaitEnvelope, root: parentBlockRoot };
|
|
404
445
|
}
|
|
405
446
|
}
|
|
@@ -411,37 +452,96 @@ export class NetworkProcessor {
|
|
|
411
452
|
case PreprocessAction.PushToQueue:
|
|
412
453
|
this.pushPendingGossipsubMessageToQueue(message);
|
|
413
454
|
break;
|
|
414
|
-
case PreprocessAction.AwaitBlock:
|
|
415
|
-
|
|
416
|
-
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
417
|
-
this.metrics?.awaitingBlockGossipMessages.reject.inc({
|
|
418
|
-
reason: ReprocessRejectReason.reached_limit,
|
|
419
|
-
topic: topicType,
|
|
420
|
-
});
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
this.metrics?.awaitingBlockGossipMessages.queue.inc({ topic: topicType });
|
|
424
|
-
const awaitingGossipsubMessages = this.awaitingMessagesByBlockRoot.getOrDefault(preprocessResult.root);
|
|
425
|
-
awaitingGossipsubMessages.add(message);
|
|
426
|
-
this.awaitingBlockMessageCount++;
|
|
455
|
+
case PreprocessAction.AwaitBlock:
|
|
456
|
+
this.maybeAwaitBlock(preprocessResult.root, topicType, slot, message);
|
|
427
457
|
break;
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if (this.awaitingPayloadMessageCount > MAX_QUEUED_UNKNOWN_PAYLOAD_GOSSIP_OBJECTS) {
|
|
431
|
-
this.metrics?.awaitingPayloadGossipMessages.reject.inc({
|
|
432
|
-
reason: ReprocessRejectReason.reached_limit,
|
|
433
|
-
topic: topicType,
|
|
434
|
-
});
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
this.metrics?.awaitingPayloadGossipMessages.queue.inc({ topic: topicType });
|
|
438
|
-
const awaitingPayloadGossipsubMessages = this.awaitingMessagesByPayloadBlockRoot.getOrDefault(preprocessResult.root);
|
|
439
|
-
awaitingPayloadGossipsubMessages.add(message);
|
|
440
|
-
this.awaitingPayloadMessageCount++;
|
|
458
|
+
case PreprocessAction.AwaitEnvelope:
|
|
459
|
+
this.maybeAwaitPayload(preprocessResult.root, topicType, slot, message);
|
|
441
460
|
break;
|
|
442
|
-
}
|
|
443
461
|
}
|
|
444
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
|
+
}
|
|
445
545
|
pushPendingGossipsubMessageToQueue(message) {
|
|
446
546
|
const topicType = message.topic.type;
|
|
447
547
|
message.queueAddedMs = Date.now();
|
|
@@ -454,66 +554,92 @@ export class NetworkProcessor {
|
|
|
454
554
|
this.executeWork();
|
|
455
555
|
}
|
|
456
556
|
onBlockProcessed = async ({ block: rootHex }) => {
|
|
457
|
-
const
|
|
458
|
-
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) {
|
|
459
566
|
return;
|
|
460
567
|
}
|
|
461
568
|
// Atomically remove from map and update counter before async iteration to
|
|
462
569
|
// prevent double-decrement race with onClockSlot during yield points below
|
|
463
570
|
if (this.awaitingMessagesByBlockRoot.delete(rootHex)) {
|
|
464
|
-
this.awaitingBlockMessageCount -=
|
|
571
|
+
this.awaitingBlockMessageCount -= total;
|
|
465
572
|
}
|
|
466
573
|
const nowSec = Date.now() / 1000;
|
|
467
574
|
let count = 0;
|
|
468
575
|
// TODO: we can group attestations to process in batches but since we have the SeenAttestationDatas
|
|
469
576
|
// cache, it may not be necessary at this time
|
|
470
|
-
for (const
|
|
471
|
-
const
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
count
|
|
479
|
-
|
|
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
|
+
}
|
|
480
589
|
}
|
|
481
590
|
}
|
|
482
591
|
};
|
|
483
592
|
onPayloadEnvelopeProcessed = async ({ blockRoot: rootHex }) => {
|
|
484
|
-
const
|
|
485
|
-
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) {
|
|
486
602
|
return;
|
|
487
603
|
}
|
|
488
604
|
// Atomically remove from map and update counter before async iteration to
|
|
489
605
|
// prevent double-decrement race with onClockSlot during yield points below
|
|
490
606
|
if (this.awaitingMessagesByPayloadBlockRoot.delete(rootHex)) {
|
|
491
|
-
this.awaitingPayloadMessageCount -=
|
|
607
|
+
this.awaitingPayloadMessageCount -= total;
|
|
492
608
|
}
|
|
493
609
|
const nowSec = Date.now() / 1000;
|
|
494
610
|
let count = 0;
|
|
495
|
-
for (const
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
count
|
|
503
|
-
|
|
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
|
+
}
|
|
504
622
|
}
|
|
505
623
|
}
|
|
506
624
|
};
|
|
507
625
|
onClockSlot = (clockSlot) => {
|
|
508
626
|
const nowSec = Date.now() / 1000;
|
|
509
627
|
const minSlot = clockSlot - MAX_UNKNOWN_ROOTS_SLOT_CACHE_SIZE;
|
|
510
|
-
for (const [slot,
|
|
628
|
+
for (const [slot, searchedRoots] of this.searchedRootsBySlot) {
|
|
511
629
|
if (slot > minSlot)
|
|
512
630
|
continue;
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
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) {
|
|
517
643
|
const topicType = message.topic.type;
|
|
518
644
|
this.metrics?.awaitingBlockGossipMessages.reject.inc({
|
|
519
645
|
topic: topicType,
|
|
@@ -522,20 +648,23 @@ export class NetworkProcessor {
|
|
|
522
648
|
this.metrics?.awaitingBlockGossipMessages.waitSecBeforeReject.set({ topic: topicType, reason: ReprocessRejectReason.expired }, nowSec - message.seenTimestampSec);
|
|
523
649
|
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
524
650
|
}
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
651
|
+
removed += messages.size;
|
|
652
|
+
}
|
|
653
|
+
if (this.awaitingMessagesByBlockRoot.delete(rootHex)) {
|
|
654
|
+
this.awaitingBlockMessageCount -= removed;
|
|
528
655
|
}
|
|
529
656
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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) {
|
|
539
668
|
const topicType = message.topic.type;
|
|
540
669
|
this.metrics?.awaitingPayloadGossipMessages.reject.inc({
|
|
541
670
|
topic: topicType,
|
|
@@ -544,12 +673,17 @@ export class NetworkProcessor {
|
|
|
544
673
|
this.metrics?.awaitingPayloadGossipMessages.waitSecBeforeReject.set({ topic: topicType, reason: ReprocessRejectReason.expired }, nowSec - message.seenTimestampSec);
|
|
545
674
|
// No need to report the dropped job to gossip. It will be eventually pruned from the mcache
|
|
546
675
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
676
|
+
removed += messages.size;
|
|
677
|
+
}
|
|
678
|
+
if (this.awaitingMessagesByPayloadBlockRoot.delete(rootHex)) {
|
|
679
|
+
this.awaitingPayloadMessageCount -= removed;
|
|
550
680
|
}
|
|
551
681
|
}
|
|
552
|
-
this.
|
|
682
|
+
this.searchedRootsBySlot.delete(slot);
|
|
683
|
+
}
|
|
684
|
+
for (const slot of this.bufferedRootsBySlot.keys()) {
|
|
685
|
+
if (slot <= minSlot)
|
|
686
|
+
this.bufferedRootsBySlot.delete(slot);
|
|
553
687
|
}
|
|
554
688
|
};
|
|
555
689
|
executeWork() {
|