@lodestar/beacon-node 1.47.0-dev.be9d5b774d → 1.47.0-dev.c1d9395d5e
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 +3 -2
- package/lib/api/impl/beacon/blocks/index.js.map +1 -1
- package/lib/api/impl/beacon/pool/index.d.ts.map +1 -1
- package/lib/api/impl/beacon/pool/index.js +8 -1
- package/lib/api/impl/beacon/pool/index.js.map +1 -1
- package/lib/api/impl/beacon/state/utils.d.ts +2 -1
- package/lib/api/impl/beacon/state/utils.d.ts.map +1 -1
- package/lib/api/impl/beacon/state/utils.js.map +1 -1
- package/lib/api/impl/events/index.d.ts.map +1 -1
- package/lib/api/impl/events/index.js +2 -0
- package/lib/api/impl/events/index.js.map +1 -1
- package/lib/api/rest/base.d.ts.map +1 -1
- package/lib/api/rest/base.js +7 -0
- package/lib/api/rest/base.js.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.d.ts +3 -2
- package/lib/chain/blocks/importExecutionPayload.d.ts.map +1 -1
- package/lib/chain/blocks/importExecutionPayload.js +11 -9
- package/lib/chain/blocks/importExecutionPayload.js.map +1 -1
- package/lib/chain/blocks/index.d.ts.map +1 -1
- package/lib/chain/blocks/index.js +14 -6
- package/lib/chain/blocks/index.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts +2 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js +6 -2
- package/lib/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.js.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts +14 -5
- package/lib/chain/blocks/payloadEnvelopeInput/types.d.ts.map +1 -1
- package/lib/chain/blocks/payloadEnvelopeInput/types.js +5 -0
- package/lib/chain/blocks/payloadEnvelopeInput/types.js.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.d.ts.map +1 -1
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js +22 -12
- package/lib/chain/blocks/verifyBlocksStateTransitionOnly.js.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.d.ts.map +1 -1
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js +2 -2
- package/lib/chain/blocks/verifyExecutionPayloadEnvelope.js.map +1 -1
- package/lib/chain/bls/index.d.ts +1 -1
- package/lib/chain/bls/index.d.ts.map +1 -1
- package/lib/chain/bls/interface.d.ts +5 -5
- package/lib/chain/bls/interface.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.d.ts +5 -11
- package/lib/chain/bls/multithread/index.d.ts.map +1 -1
- package/lib/chain/bls/multithread/index.js +116 -101
- package/lib/chain/bls/multithread/index.js.map +1 -1
- package/lib/chain/bls/multithread/jobItem.d.ts +5 -19
- package/lib/chain/bls/multithread/jobItem.d.ts.map +1 -1
- package/lib/chain/bls/multithread/jobItem.js +10 -65
- package/lib/chain/bls/multithread/jobItem.js.map +1 -1
- package/lib/chain/bls/multithread/types.d.ts +29 -8
- package/lib/chain/bls/multithread/types.d.ts.map +1 -1
- package/lib/chain/bls/multithread/types.js +12 -0
- package/lib/chain/bls/multithread/types.js.map +1 -1
- package/lib/chain/bls/multithread/utils.d.ts +4 -0
- package/lib/chain/bls/multithread/utils.d.ts.map +1 -1
- package/lib/chain/bls/multithread/utils.js +10 -0
- package/lib/chain/bls/multithread/utils.js.map +1 -1
- package/lib/chain/bls/multithread/worker.js +49 -23
- package/lib/chain/bls/multithread/worker.js.map +1 -1
- package/lib/chain/bls/singleThread.d.ts +4 -10
- package/lib/chain/bls/singleThread.d.ts.map +1 -1
- package/lib/chain/bls/singleThread.js +8 -45
- package/lib/chain/bls/singleThread.js.map +1 -1
- package/lib/chain/bls/utils.d.ts +4 -4
- package/lib/chain/bls/utils.d.ts.map +1 -1
- package/lib/chain/bls/utils.js +18 -19
- package/lib/chain/bls/utils.js.map +1 -1
- package/lib/chain/chain.d.ts +2 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +12 -5
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/errors/blockError.d.ts +1 -0
- package/lib/chain/errors/blockError.d.ts.map +1 -1
- package/lib/chain/errors/blockError.js +6 -1
- package/lib/chain/errors/blockError.js.map +1 -1
- package/lib/chain/interface.d.ts +2 -1
- package/lib/chain/interface.d.ts.map +1 -1
- package/lib/chain/interface.js.map +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js +1 -1
- package/lib/chain/opPools/aggregatedAttestationPool.js.map +1 -1
- package/lib/chain/opPools/attestationPool.d.ts +1 -1
- package/lib/chain/opPools/attestationPool.d.ts.map +1 -1
- package/lib/chain/opPools/attestationPool.js +1 -1
- package/lib/chain/opPools/attestationPool.js.map +1 -1
- package/lib/chain/opPools/payloadAttestationPool.js +3 -3
- package/lib/chain/opPools/payloadAttestationPool.js.map +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js +1 -1
- package/lib/chain/opPools/syncCommitteeMessagePool.js.map +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js +1 -1
- package/lib/chain/opPools/syncContributionAndProofPool.js.map +1 -1
- package/lib/chain/opPools/utils.d.ts +1 -1
- package/lib/chain/opPools/utils.d.ts.map +1 -1
- package/lib/chain/opPools/utils.js +1 -1
- package/lib/chain/opPools/utils.js.map +1 -1
- package/lib/chain/seenCache/seenAttesters.d.ts +9 -5
- package/lib/chain/seenCache/seenAttesters.d.ts.map +1 -1
- package/lib/chain/seenCache/seenAttesters.js +25 -4
- package/lib/chain/seenCache/seenAttesters.js.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts +28 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js +121 -13
- package/lib/chain/seenCache/seenPayloadEnvelopeInput.js.map +1 -1
- package/lib/chain/validation/attestation.d.ts.map +1 -1
- package/lib/chain/validation/attestation.js +1 -4
- package/lib/chain/validation/attestation.js.map +1 -1
- package/lib/chain/validation/attesterSlashing.d.ts.map +1 -1
- package/lib/chain/validation/attesterSlashing.js +1 -1
- package/lib/chain/validation/attesterSlashing.js.map +1 -1
- package/lib/chain/validation/executionPayloadBid.d.ts.map +1 -1
- package/lib/chain/validation/executionPayloadBid.js +1 -2
- package/lib/chain/validation/executionPayloadBid.js.map +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js +1 -1
- package/lib/chain/validation/executionPayloadEnvelope.js.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.d.ts.map +1 -1
- package/lib/chain/validation/payloadAttestationMessage.js +5 -14
- package/lib/chain/validation/payloadAttestationMessage.js.map +1 -1
- package/lib/chain/validation/proposerPreferences.js +2 -2
- package/lib/chain/validation/proposerPreferences.js.map +1 -1
- package/lib/chain/validation/proposerSlashing.js +1 -1
- package/lib/chain/validation/proposerSlashing.js.map +1 -1
- package/lib/metrics/metrics/lodestar.d.ts +52 -22
- package/lib/metrics/metrics/lodestar.d.ts.map +1 -1
- package/lib/metrics/metrics/lodestar.js +94 -52
- package/lib/metrics/metrics/lodestar.js.map +1 -1
- package/lib/network/gossip/topic.d.ts +13 -0
- package/lib/network/gossip/topic.d.ts.map +1 -1
- package/lib/network/gossip/topic.js +37 -0
- package/lib/network/gossip/topic.js.map +1 -1
- package/lib/network/network.d.ts.map +1 -1
- package/lib/network/network.js +22 -43
- package/lib/network/network.js.map +1 -1
- package/lib/network/processor/gossipHandlers.d.ts.map +1 -1
- package/lib/network/processor/gossipHandlers.js +5 -1
- package/lib/network/processor/gossipHandlers.js.map +1 -1
- package/lib/network/util.d.ts +0 -1
- package/lib/network/util.d.ts.map +1 -1
- package/lib/network/util.js +0 -4
- package/lib/network/util.js.map +1 -1
- package/lib/node/nodejs.d.ts +2 -1
- package/lib/node/nodejs.d.ts.map +1 -1
- package/lib/node/nodejs.js.map +1 -1
- package/lib/sync/range/batch.d.ts +23 -5
- package/lib/sync/range/batch.d.ts.map +1 -1
- package/lib/sync/range/batch.js +61 -22
- package/lib/sync/range/batch.js.map +1 -1
- package/lib/sync/range/chain.d.ts +2 -1
- package/lib/sync/range/chain.d.ts.map +1 -1
- package/lib/sync/range/chain.js +23 -10
- package/lib/sync/range/chain.js.map +1 -1
- package/lib/sync/types.d.ts +32 -0
- package/lib/sync/types.d.ts.map +1 -1
- package/lib/sync/types.js +33 -0
- package/lib/sync/types.js.map +1 -1
- package/lib/sync/unknownBlock.d.ts.map +1 -1
- package/lib/sync/unknownBlock.js +95 -51
- package/lib/sync/unknownBlock.js.map +1 -1
- package/lib/sync/utils/downloadByRange.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRange.js +16 -11
- package/lib/sync/utils/downloadByRange.js.map +1 -1
- package/lib/sync/utils/downloadByRoot.d.ts.map +1 -1
- package/lib/sync/utils/downloadByRoot.js +3 -1
- package/lib/sync/utils/downloadByRoot.js.map +1 -1
- package/package.json +35 -35
- package/src/api/impl/beacon/blocks/index.ts +3 -2
- package/src/api/impl/beacon/pool/index.ts +7 -1
- package/src/api/impl/beacon/state/utils.ts +2 -1
- package/src/api/impl/events/index.ts +3 -1
- package/src/api/rest/base.ts +7 -0
- package/src/chain/blocks/importExecutionPayload.ts +12 -11
- package/src/chain/blocks/index.ts +18 -6
- package/src/chain/blocks/payloadEnvelopeInput/payloadEnvelopeInput.ts +8 -2
- package/src/chain/blocks/payloadEnvelopeInput/types.ts +17 -4
- package/src/chain/blocks/verifyBlocksStateTransitionOnly.ts +25 -16
- package/src/chain/blocks/verifyExecutionPayloadEnvelope.ts +1 -9
- package/src/chain/bls/index.ts +1 -1
- package/src/chain/bls/interface.ts +7 -3
- package/src/chain/bls/multithread/index.ts +148 -120
- package/src/chain/bls/multithread/jobItem.ts +12 -82
- package/src/chain/bls/multithread/types.ts +33 -8
- package/src/chain/bls/multithread/utils.ts +11 -0
- package/src/chain/bls/multithread/worker.ts +85 -27
- package/src/chain/bls/singleThread.ts +11 -55
- package/src/chain/bls/utils.ts +23 -24
- package/src/chain/chain.ts +13 -6
- package/src/chain/errors/blockError.ts +8 -2
- package/src/chain/interface.ts +2 -1
- package/src/chain/opPools/aggregatedAttestationPool.ts +1 -1
- package/src/chain/opPools/attestationPool.ts +1 -1
- package/src/chain/opPools/payloadAttestationPool.ts +3 -3
- package/src/chain/opPools/syncCommitteeMessagePool.ts +1 -1
- package/src/chain/opPools/syncContributionAndProofPool.ts +1 -1
- package/src/chain/opPools/utils.ts +1 -1
- package/src/chain/seenCache/seenAttesters.ts +31 -5
- package/src/chain/seenCache/seenPayloadEnvelopeInput.ts +143 -14
- package/src/chain/validation/attestation.ts +1 -7
- package/src/chain/validation/attesterSlashing.ts +1 -8
- package/src/chain/validation/executionPayloadBid.ts +1 -2
- package/src/chain/validation/executionPayloadEnvelope.ts +0 -1
- package/src/chain/validation/payloadAttestationMessage.ts +6 -17
- package/src/chain/validation/proposerPreferences.ts +3 -3
- package/src/chain/validation/proposerSlashing.ts +1 -1
- package/src/metrics/metrics/lodestar.ts +106 -57
- package/src/network/gossip/topic.ts +38 -0
- package/src/network/network.ts +27 -55
- package/src/network/processor/gossipHandlers.ts +5 -1
- package/src/network/util.ts +0 -5
- package/src/node/nodejs.ts +2 -1
- package/src/sync/range/batch.ts +83 -28
- package/src/sync/range/chain.ts +26 -11
- package/src/sync/types.ts +33 -0
- package/src/sync/unknownBlock.ts +105 -55
- package/src/sync/utils/downloadByRange.ts +21 -12
- package/src/sync/utils/downloadByRoot.ts +3 -1
- package/lib/chain/bls/maybeBatch.d.ts +0 -12
- package/lib/chain/bls/maybeBatch.d.ts.map +0 -1
- package/lib/chain/bls/maybeBatch.js +0 -35
- package/lib/chain/bls/maybeBatch.js.map +0 -1
- package/src/chain/bls/maybeBatch.ts +0 -45
package/src/sync/unknownBlock.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {routes} from "@lodestar/api";
|
|
2
2
|
import {ChainForkConfig} from "@lodestar/config";
|
|
3
3
|
import {CheckpointWithHex} from "@lodestar/fork-choice";
|
|
4
|
-
import {ForkSeq, isForkPostGloas} from "@lodestar/params";
|
|
4
|
+
import {ForkSeq, SLOTS_PER_EPOCH, isForkPostGloas} from "@lodestar/params";
|
|
5
5
|
import {RequestError, RequestErrorCode} from "@lodestar/reqresp";
|
|
6
6
|
import {computeTimeAtSlot} from "@lodestar/state-transition";
|
|
7
7
|
import {RootHex, Slot, gloas} from "@lodestar/types";
|
|
@@ -25,6 +25,7 @@ import {MAX_CONCURRENT_REQUESTS} from "./constants.js";
|
|
|
25
25
|
import {SyncOptions} from "./options.js";
|
|
26
26
|
import {
|
|
27
27
|
BlockInputSyncCacheItem,
|
|
28
|
+
DroppedItemReason,
|
|
28
29
|
PayloadSyncCacheItem,
|
|
29
30
|
PendingBlockInput,
|
|
30
31
|
PendingBlockInputStatus,
|
|
@@ -48,6 +49,10 @@ import {getRateLimitedUntilMs} from "./utils/rateLimit.js";
|
|
|
48
49
|
const MAX_ATTEMPTS_PER_BLOCK = 5;
|
|
49
50
|
const MAX_KNOWN_BAD_BLOCKS = 500;
|
|
50
51
|
const MAX_PENDING_BLOCKS = 100;
|
|
52
|
+
/**
|
|
53
|
+
* A pending payload without slot can only stay at most 2 epochs.
|
|
54
|
+
*/
|
|
55
|
+
const PRUNE_UNRESOLVED_SLOT_EPOCHS = 2;
|
|
51
56
|
|
|
52
57
|
type AdvancePendingBlockResult =
|
|
53
58
|
| "ready"
|
|
@@ -255,7 +260,7 @@ export class BlockInputSync {
|
|
|
255
260
|
parentRoot: missingDependency.parentRootHex,
|
|
256
261
|
parentBlockHash: missingDependency.parentBlockHashHex,
|
|
257
262
|
});
|
|
258
|
-
this.removeAndDownScoreAllDescendants(pendingBlock);
|
|
263
|
+
this.removeAndDownScoreAllDescendants(pendingBlock, DroppedItemReason.invalidParentPayload);
|
|
259
264
|
}
|
|
260
265
|
return;
|
|
261
266
|
}
|
|
@@ -295,28 +300,37 @@ export class BlockInputSync {
|
|
|
295
300
|
// Use the actual finalized block slot, not computeStartSlotAtEpoch(checkpoint.epoch)
|
|
296
301
|
// because the payload at the finalized block is not finalized
|
|
297
302
|
const finalizedSlot = this.chain.forkChoice.getFinalizedBlock().slot;
|
|
303
|
+
const nowSec = Date.now() / 1000;
|
|
304
|
+
const maxSecInCache = (PRUNE_UNRESOLVED_SLOT_EPOCHS * SLOTS_PER_EPOCH * this.config.SLOT_DURATION_MS) / 1000;
|
|
298
305
|
|
|
299
|
-
let
|
|
306
|
+
let belowFinalizedPayloads = 0;
|
|
307
|
+
let agedOutPayloads = 0;
|
|
300
308
|
let unresolvedSlotPayloads = 0;
|
|
309
|
+
|
|
301
310
|
for (const [rootHex, payload] of this.pendingPayloads) {
|
|
302
311
|
// Last-effort resolve for a slot-less PendingPayloadRootHex, and store it back for later passes.
|
|
303
312
|
if (!isPendingPayloadInput(payload) && !isPendingPayloadEnvelope(payload) && payload.slot === undefined) {
|
|
304
313
|
payload.slot = this.resolvePayloadSlot(rootHex);
|
|
314
|
+
if (payload.slot === undefined) {
|
|
315
|
+
// Still unresolvable: age it out so the MAX_PENDING_BLOCKS cap cannot stay saturated.
|
|
316
|
+
if (nowSec - payload.timeAddedSec > maxSecInCache) {
|
|
317
|
+
this.pendingPayloads.delete(rootHex);
|
|
318
|
+
agedOutPayloads++;
|
|
319
|
+
} else {
|
|
320
|
+
unresolvedSlotPayloads++;
|
|
321
|
+
this.logger.debug("BlockInputSync.pruneFinalized: pending payload with unresolved slot", {
|
|
322
|
+
root: rootHex,
|
|
323
|
+
finalizedSlot,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
305
328
|
}
|
|
306
329
|
|
|
307
330
|
const slot = getPayloadSyncCacheItemSlot(payload);
|
|
308
|
-
if (typeof slot
|
|
309
|
-
unresolvedSlotPayloads++;
|
|
310
|
-
this.logger.debug("BlockInputSync.pruneFinalized: pending payload with unresolved slot", {
|
|
311
|
-
root: rootHex,
|
|
312
|
-
finalizedSlot,
|
|
313
|
-
});
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (slot < finalizedSlot) {
|
|
331
|
+
if (typeof slot === "number" && slot < finalizedSlot) {
|
|
318
332
|
this.pendingPayloads.delete(rootHex);
|
|
319
|
-
|
|
333
|
+
belowFinalizedPayloads++;
|
|
320
334
|
}
|
|
321
335
|
}
|
|
322
336
|
|
|
@@ -329,14 +343,24 @@ export class BlockInputSync {
|
|
|
329
343
|
}
|
|
330
344
|
}
|
|
331
345
|
|
|
332
|
-
if (
|
|
333
|
-
this.metrics?.blockInputSync.
|
|
346
|
+
if (belowFinalizedPayloads > 0) {
|
|
347
|
+
this.metrics?.blockInputSync.removedPayloads.inc(
|
|
348
|
+
{reason: DroppedItemReason.belowFinalized},
|
|
349
|
+
belowFinalizedPayloads
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
if (agedOutPayloads > 0) {
|
|
353
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason: DroppedItemReason.agedOut}, agedOutPayloads);
|
|
354
|
+
}
|
|
355
|
+
if (deletedBlocks > 0) {
|
|
356
|
+
this.metrics?.blockInputSync.removedBlocks.inc({reason: DroppedItemReason.belowFinalized}, deletedBlocks);
|
|
334
357
|
}
|
|
335
358
|
|
|
336
359
|
this.logger.debug("BlockInputSync.pruneFinalized dropped pre-finalized pending items", {
|
|
337
360
|
finalizedSlot,
|
|
338
361
|
finalizedRoot: checkpoint.rootHex,
|
|
339
|
-
|
|
362
|
+
belowFinalizedPayloads,
|
|
363
|
+
agedOutPayloads,
|
|
340
364
|
deletedBlocks,
|
|
341
365
|
unresolvedSlotPayloads,
|
|
342
366
|
});
|
|
@@ -369,6 +393,7 @@ export class BlockInputSync {
|
|
|
369
393
|
// Limit pending blocks to prevent DOS attacks that cause OOM
|
|
370
394
|
const prunedItemCount = pruneSetToMax(this.pendingBlocks, this.maxPendingBlocks);
|
|
371
395
|
if (prunedItemCount > 0) {
|
|
396
|
+
this.metrics?.blockInputSync.removedBlocks.inc({reason: DroppedItemReason.capacity}, prunedItemCount);
|
|
372
397
|
this.logger.verbose(`Pruned ${prunedItemCount} items from BlockInputSync.pendingBlocks`);
|
|
373
398
|
}
|
|
374
399
|
return added;
|
|
@@ -403,6 +428,7 @@ export class BlockInputSync {
|
|
|
403
428
|
// Limit pending blocks to prevent DOS attacks that cause OOM
|
|
404
429
|
const prunedItemCount = pruneSetToMax(this.pendingBlocks, this.maxPendingBlocks);
|
|
405
430
|
if (prunedItemCount > 0) {
|
|
431
|
+
this.metrics?.blockInputSync.removedBlocks.inc({reason: DroppedItemReason.capacity}, prunedItemCount);
|
|
406
432
|
this.logger.verbose(`Pruned ${prunedItemCount} items from BlockInputSync.pendingBlocks`);
|
|
407
433
|
}
|
|
408
434
|
};
|
|
@@ -427,6 +453,14 @@ export class BlockInputSync {
|
|
|
427
453
|
root: rootHex,
|
|
428
454
|
peerIdStr: peerIdStr ?? "unknown peer",
|
|
429
455
|
});
|
|
456
|
+
} else if (
|
|
457
|
+
// update a previously slot-less entry once a slot becomes available
|
|
458
|
+
slot !== undefined &&
|
|
459
|
+
!isPendingPayloadInput(pendingPayload) &&
|
|
460
|
+
!isPendingPayloadEnvelope(pendingPayload) &&
|
|
461
|
+
pendingPayload.slot === undefined
|
|
462
|
+
) {
|
|
463
|
+
pendingPayload.slot = slot;
|
|
430
464
|
}
|
|
431
465
|
|
|
432
466
|
if (peerIdStr) {
|
|
@@ -435,6 +469,7 @@ export class BlockInputSync {
|
|
|
435
469
|
|
|
436
470
|
const prunedItemCount = pruneSetToMax(this.pendingPayloads, this.maxPendingBlocks);
|
|
437
471
|
if (prunedItemCount > 0) {
|
|
472
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason: DroppedItemReason.capacity}, prunedItemCount);
|
|
438
473
|
this.logger.verbose(`Pruned ${prunedItemCount} items from BlockInputSync.pendingPayloads`);
|
|
439
474
|
}
|
|
440
475
|
return added;
|
|
@@ -488,6 +523,7 @@ export class BlockInputSync {
|
|
|
488
523
|
|
|
489
524
|
const prunedItemCount = pruneSetToMax(this.pendingPayloads, this.maxPendingBlocks);
|
|
490
525
|
if (prunedItemCount > 0) {
|
|
526
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason: DroppedItemReason.capacity}, prunedItemCount);
|
|
491
527
|
this.logger.verbose(`Pruned ${prunedItemCount} items from BlockInputSync.pendingPayloads`);
|
|
492
528
|
}
|
|
493
529
|
};
|
|
@@ -544,15 +580,7 @@ export class BlockInputSync {
|
|
|
544
580
|
return {kind: "invalidParentPayload", parentRootHex, parentBlockHashHex};
|
|
545
581
|
}
|
|
546
582
|
|
|
547
|
-
|
|
548
|
-
if (parentPayloadInput) {
|
|
549
|
-
if (parentPayloadInput.getBlockHashHex() === parentBlockHashHex) {
|
|
550
|
-
return {kind: "parentPayload", rootHex: parentRootHex, slot: parentBlock.slot};
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
return {kind: "invalidParentPayload", parentRootHex, parentBlockHashHex};
|
|
554
|
-
}
|
|
555
|
-
|
|
583
|
+
// Parent is in fork choice but its payload `parentBlockHashHex` isn't revealed yet
|
|
556
584
|
return {kind: "parentPayload", rootHex: parentRootHex, slot: parentBlock.slot};
|
|
557
585
|
}
|
|
558
586
|
|
|
@@ -590,7 +618,7 @@ export class BlockInputSync {
|
|
|
590
618
|
parentRoot: missingDependency.parentRootHex,
|
|
591
619
|
parentBlockHash: missingDependency.parentBlockHashHex,
|
|
592
620
|
});
|
|
593
|
-
this.removeAndDownScoreAllDescendants(pendingBlock);
|
|
621
|
+
this.removeAndDownScoreAllDescendants(pendingBlock, DroppedItemReason.invalidParentPayload);
|
|
594
622
|
return "removed";
|
|
595
623
|
}
|
|
596
624
|
}
|
|
@@ -813,7 +841,7 @@ export class BlockInputSync {
|
|
|
813
841
|
...logCtx2,
|
|
814
842
|
finalizedSlot,
|
|
815
843
|
});
|
|
816
|
-
this.removeAndDownScoreAllDescendants(block);
|
|
844
|
+
this.removeAndDownScoreAllDescendants(block, DroppedItemReason.belowFinalized);
|
|
817
845
|
} else {
|
|
818
846
|
this.onUnknownBlockRoot({rootHex: pending.blockInput.parentRootHex, source: BlockInputSource.byRoot});
|
|
819
847
|
}
|
|
@@ -830,7 +858,7 @@ export class BlockInputSync {
|
|
|
830
858
|
|
|
831
859
|
this.metrics?.blockInputSync.downloadedBlocksError.inc();
|
|
832
860
|
this.logger.debug("Ignoring unknown block root after many failed downloads", logCtx, res.err);
|
|
833
|
-
this.removeAndDownScoreAllDescendants(block);
|
|
861
|
+
this.removeAndDownScoreAllDescendants(block, DroppedItemReason.unavailable);
|
|
834
862
|
}
|
|
835
863
|
}
|
|
836
864
|
|
|
@@ -894,9 +922,9 @@ export class BlockInputSync {
|
|
|
894
922
|
this.pendingBlocks.delete(blockRootHex);
|
|
895
923
|
|
|
896
924
|
if (isForkPostGloas(fork)) {
|
|
897
|
-
const payloadInput = this.chain.seenPayloadEnvelopeInputCache.
|
|
925
|
+
const payloadInput = await this.chain.seenPayloadEnvelopeInputCache.getOrReload(blockRootHex);
|
|
898
926
|
if (!payloadInput) {
|
|
899
|
-
this.logger.
|
|
927
|
+
this.logger.debug("PayloadEnvelopeInput unavailable during unknown sync processReadyBlock()", logCtx);
|
|
900
928
|
} else {
|
|
901
929
|
// Similar to the gossip path: immediately attempt fetch of data columns from the execution engine.
|
|
902
930
|
// The bid already carries the kzg commitments, so there is no reason to wait for the payload to arrive.
|
|
@@ -938,19 +966,19 @@ export class BlockInputSync {
|
|
|
938
966
|
case BlockErrorCode.EXECUTION_ENGINE_ERROR:
|
|
939
967
|
// Removing the block(s) without penalizing the peers, hoping for EL to
|
|
940
968
|
// recover on a latter download + verify attempt.
|
|
941
|
-
this.removeAllDescendants(pendingBlock);
|
|
969
|
+
this.removeAllDescendants(pendingBlock, DroppedItemReason.elError, DroppedItemReason.elError);
|
|
942
970
|
break;
|
|
943
971
|
|
|
944
972
|
case BlockErrorCode.EXECUTION_ENGINE_INVALID:
|
|
945
973
|
// the peer served a bad block
|
|
946
974
|
this.logger.debug("Execution engine rejected block from unknown parent sync", errorData, res.err);
|
|
947
|
-
this.removeAndDownScoreAllDescendants(pendingBlock);
|
|
975
|
+
this.removeAndDownScoreAllDescendants(pendingBlock, DroppedItemReason.elInvalid);
|
|
948
976
|
break;
|
|
949
977
|
|
|
950
978
|
default:
|
|
951
979
|
// Block is not correct with respect to our chain. Log error loudly
|
|
952
980
|
this.logger.debug("Error processing block from unknown parent sync", errorData, res.err);
|
|
953
|
-
this.removeAndDownScoreAllDescendants(pendingBlock);
|
|
981
|
+
this.removeAndDownScoreAllDescendants(pendingBlock, DroppedItemReason.invalidBlock);
|
|
954
982
|
}
|
|
955
983
|
}
|
|
956
984
|
|
|
@@ -969,12 +997,12 @@ export class BlockInputSync {
|
|
|
969
997
|
*/
|
|
970
998
|
private async reconcilePayloadEnvelope(pendingPayload: PendingPayloadEnvelope): Promise<void> {
|
|
971
999
|
const rootHex = getPayloadSyncCacheItemRootHex(pendingPayload);
|
|
1000
|
+
|
|
972
1001
|
if (this.chain.forkChoice.hasPayloadHexUnsafe(rootHex)) {
|
|
973
1002
|
this.pendingPayloads.delete(rootHex);
|
|
974
1003
|
return;
|
|
975
1004
|
}
|
|
976
1005
|
|
|
977
|
-
const payloadInput = this.chain.seenPayloadEnvelopeInputCache.get(rootHex);
|
|
978
1006
|
if (!this.chain.forkChoice.hasBlockHex(rootHex)) {
|
|
979
1007
|
// Block not in fork choice yet. payloadInput may be seeded from the block body during download, so a
|
|
980
1008
|
// non-null payloadInput does not imply the block is imported; defer regardless and pull the block first.
|
|
@@ -990,8 +1018,9 @@ export class BlockInputSync {
|
|
|
990
1018
|
return;
|
|
991
1019
|
}
|
|
992
1020
|
|
|
1021
|
+
const payloadInput = await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
|
|
993
1022
|
if (!payloadInput) {
|
|
994
|
-
this.logger.debug("
|
|
1023
|
+
this.logger.debug("PayloadEnvelopeInput not yet reloadable for imported block, will retry", {
|
|
995
1024
|
root: rootHex,
|
|
996
1025
|
});
|
|
997
1026
|
return;
|
|
@@ -1153,17 +1182,27 @@ export class BlockInputSync {
|
|
|
1153
1182
|
break;
|
|
1154
1183
|
|
|
1155
1184
|
case PayloadErrorCode.EXECUTION_ENGINE_INVALID:
|
|
1185
|
+
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1186
|
+
this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.elInvalid);
|
|
1187
|
+
break;
|
|
1188
|
+
|
|
1156
1189
|
case PayloadErrorCode.ENVELOPE_VERIFICATION_ERROR:
|
|
1190
|
+
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1191
|
+
this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.invalidEnvelope);
|
|
1192
|
+
break;
|
|
1193
|
+
|
|
1157
1194
|
case PayloadErrorCode.INVALID_SIGNATURE:
|
|
1158
1195
|
// TODO GLOAS: Decide how invalid payload inputs should eventually leave memory without
|
|
1159
1196
|
// reintroducing envelope replacement / recreation flows.
|
|
1160
1197
|
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1161
|
-
this.removePendingPayloadAndDescendants(rootHex);
|
|
1198
|
+
this.removePendingPayloadAndDescendants(rootHex, DroppedItemReason.invalidSignature);
|
|
1162
1199
|
break;
|
|
1163
1200
|
|
|
1164
1201
|
default:
|
|
1165
1202
|
this.logger.debug("Error processing payload from unknown sync", logCtx, res.err);
|
|
1166
|
-
this.pendingPayloads.delete(rootHex)
|
|
1203
|
+
if (this.pendingPayloads.delete(rootHex)) {
|
|
1204
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason: DroppedItemReason.unknown}, 1);
|
|
1205
|
+
}
|
|
1167
1206
|
}
|
|
1168
1207
|
return;
|
|
1169
1208
|
}
|
|
@@ -1187,7 +1226,7 @@ export class BlockInputSync {
|
|
|
1187
1226
|
let slot = getPayloadSyncCacheItemSlot(cacheItem);
|
|
1188
1227
|
let payloadInput = isPendingPayloadInput(cacheItem)
|
|
1189
1228
|
? cacheItem.payloadInput
|
|
1190
|
-
: this.chain.seenPayloadEnvelopeInputCache.
|
|
1229
|
+
: await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
|
|
1191
1230
|
let envelope = payloadInput?.hasPayloadEnvelope() ? payloadInput.getPayloadEnvelope() : undefined;
|
|
1192
1231
|
|
|
1193
1232
|
let i = 0;
|
|
@@ -1220,7 +1259,7 @@ export class BlockInputSync {
|
|
|
1220
1259
|
slot = envelope.message.payload.slotNumber;
|
|
1221
1260
|
}
|
|
1222
1261
|
|
|
1223
|
-
payloadInput ??= this.chain.seenPayloadEnvelopeInputCache.
|
|
1262
|
+
payloadInput ??= await this.chain.seenPayloadEnvelopeInputCache.getOrReload(rootHex);
|
|
1224
1263
|
if (!this.chain.forkChoice.hasBlockHex(rootHex)) {
|
|
1225
1264
|
// Block not in fork choice yet. Validating now would throw BLOCK_ROOT_UNKNOWN, so keep the downloaded
|
|
1226
1265
|
// envelope and wait for the block body; reconcilePayloadEnvelope validates once the block lands.
|
|
@@ -1553,9 +1592,9 @@ export class BlockInputSync {
|
|
|
1553
1592
|
* Downscore all peers that have referenced any of this bad blocks. May report peers multiple times if they have
|
|
1554
1593
|
* referenced more than one bad block.
|
|
1555
1594
|
*/
|
|
1556
|
-
private removeAndDownScoreAllDescendants(block: BlockInputSyncCacheItem): void {
|
|
1595
|
+
private removeAndDownScoreAllDescendants(block: BlockInputSyncCacheItem, headReason: DroppedItemReason): void {
|
|
1557
1596
|
// Get all blocks that are a descendant of this one
|
|
1558
|
-
const badPendingBlocks = this.removeAllDescendants(block);
|
|
1597
|
+
const badPendingBlocks = this.removeAllDescendants(block, headReason, DroppedItemReason.invalidParent);
|
|
1559
1598
|
// just console log and do not penalize on pending/bad blocks for debugging
|
|
1560
1599
|
// console.log("removeAndDownscoreAllDescendants", {block});
|
|
1561
1600
|
|
|
@@ -1582,18 +1621,22 @@ export class BlockInputSync {
|
|
|
1582
1621
|
}
|
|
1583
1622
|
|
|
1584
1623
|
// Once a parent payload is invalid, every descendant waiting on that payload lineage becomes unrecoverable too.
|
|
1585
|
-
private removePendingPayloadAndDescendants(rootHex: RootHex): void {
|
|
1624
|
+
private removePendingPayloadAndDescendants(rootHex: RootHex, headReason: DroppedItemReason): void {
|
|
1586
1625
|
// Keep PayloadEnvelopeInput resident in the seen cache. importBlock() owns that object and
|
|
1587
1626
|
// later validation/finalization logic decides when it can leave memory.
|
|
1588
|
-
this.pendingPayloads.delete(rootHex)
|
|
1627
|
+
if (this.pendingPayloads.delete(rootHex)) {
|
|
1628
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason: headReason}, 1);
|
|
1629
|
+
}
|
|
1589
1630
|
|
|
1590
1631
|
const badPendingBlocks = getAllDescendantBlocks(rootHex, this.pendingBlocks);
|
|
1591
|
-
this.metrics?.blockInputSync.removedBlocks.inc(badPendingBlocks.length);
|
|
1592
|
-
|
|
1593
1632
|
for (const block of badPendingBlocks) {
|
|
1594
1633
|
const descendantRootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
1595
|
-
this.pendingBlocks.delete(descendantRootHex)
|
|
1596
|
-
|
|
1634
|
+
if (this.pendingBlocks.delete(descendantRootHex)) {
|
|
1635
|
+
this.metrics?.blockInputSync.removedBlocks.inc({reason: DroppedItemReason.invalidParent}, 1);
|
|
1636
|
+
}
|
|
1637
|
+
if (this.pendingPayloads.delete(descendantRootHex)) {
|
|
1638
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason: DroppedItemReason.invalidParent}, 1);
|
|
1639
|
+
}
|
|
1597
1640
|
this.chain.seenBlockInputCache.prune(descendantRootHex);
|
|
1598
1641
|
this.logger.debug("Removing pending descendant after invalid parent payload", {
|
|
1599
1642
|
slot: getBlockInputSyncCacheItemSlot(block),
|
|
@@ -1603,18 +1646,25 @@ export class BlockInputSync {
|
|
|
1603
1646
|
}
|
|
1604
1647
|
}
|
|
1605
1648
|
|
|
1606
|
-
private removeAllDescendants(
|
|
1649
|
+
private removeAllDescendants(
|
|
1650
|
+
block: BlockInputSyncCacheItem,
|
|
1651
|
+
headReason: DroppedItemReason,
|
|
1652
|
+
descendantReason: DroppedItemReason = DroppedItemReason.invalidParent
|
|
1653
|
+
): BlockInputSyncCacheItem[] {
|
|
1607
1654
|
const rootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
1608
1655
|
const slot = getBlockInputSyncCacheItemSlot(block);
|
|
1609
|
-
// Get all blocks that are a descendant of this one
|
|
1656
|
+
// Get all blocks that are a descendant of this one (index 0 is the head item itself)
|
|
1610
1657
|
const badPendingBlocks = [block, ...getAllDescendantBlocks(rootHex, this.pendingBlocks)];
|
|
1611
1658
|
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
for (const block of badPendingBlocks) {
|
|
1659
|
+
for (const [i, block] of badPendingBlocks.entries()) {
|
|
1615
1660
|
const rootHex = getBlockInputSyncCacheItemRootHex(block);
|
|
1616
|
-
|
|
1617
|
-
this.
|
|
1661
|
+
const reason = i === 0 ? headReason : descendantReason;
|
|
1662
|
+
if (this.pendingBlocks.delete(rootHex)) {
|
|
1663
|
+
this.metrics?.blockInputSync.removedBlocks.inc({reason}, 1);
|
|
1664
|
+
}
|
|
1665
|
+
if (this.pendingPayloads.delete(rootHex)) {
|
|
1666
|
+
this.metrics?.blockInputSync.removedPayloads.inc({reason}, 1);
|
|
1667
|
+
}
|
|
1618
1668
|
this.chain.seenBlockInputCache.prune(rootHex);
|
|
1619
1669
|
// Keep PayloadEnvelopeInput resident in the seen cache for consistency with the
|
|
1620
1670
|
// importBlock()-owned lifecycle.
|
|
@@ -136,6 +136,8 @@ export function cacheByRangeResponses({
|
|
|
136
136
|
const source = BlockInputSource.byRange;
|
|
137
137
|
const updatedBatchBlocks = new Map<Slot, IBlockInput>(batchBlocks.map((block) => [block.slot, block]));
|
|
138
138
|
|
|
139
|
+
const payloadEnvelopes = new Map<Slot, PayloadEnvelopeInput>(existingPayloadEnvelopes);
|
|
140
|
+
|
|
139
141
|
const blocks = responses.validatedBlocks ?? [];
|
|
140
142
|
for (let i = 0; i < blocks.length; i++) {
|
|
141
143
|
const {block, blockRoot} = blocks[i];
|
|
@@ -172,15 +174,17 @@ export function cacheByRangeResponses({
|
|
|
172
174
|
// later step) can throw and abort the batch — otherwise a gloas block would sit in
|
|
173
175
|
// seenBlockInputCache but unseeded here, and payload-by-root sync would later throw "Missing
|
|
174
176
|
// PayloadEnvelopeInput for known block" (see issue #9306). add() is idempotent.
|
|
175
|
-
if (isForkPostGloas(blockInput.forkName)) {
|
|
176
|
-
seenPayloadEnvelopeInputCache.add({
|
|
177
|
+
if (isForkPostGloas(blockInput.forkName) && !payloadEnvelopes.has(blockInput.slot)) {
|
|
178
|
+
const payloadInput = seenPayloadEnvelopeInputCache.add({
|
|
177
179
|
blockRootHex: blockInput.blockRootHex,
|
|
178
180
|
block: blockInput.getBlock() as SignedBeaconBlock<ForkPostGloas>,
|
|
179
181
|
forkName: blockInput.forkName,
|
|
180
182
|
sampledColumns: custodyConfig.sampledColumns,
|
|
181
183
|
custodyColumns: custodyConfig.custodyColumns,
|
|
182
|
-
|
|
184
|
+
seenTimestampSec,
|
|
185
|
+
source: PayloadEnvelopeInputSource.byRange,
|
|
183
186
|
});
|
|
187
|
+
payloadEnvelopes.set(blockInput.slot, payloadInput);
|
|
184
188
|
}
|
|
185
189
|
}
|
|
186
190
|
|
|
@@ -222,17 +226,22 @@ export function cacheByRangeResponses({
|
|
|
222
226
|
}
|
|
223
227
|
}
|
|
224
228
|
|
|
225
|
-
let payloadEnvelopes: Map<Slot, PayloadEnvelopeInput> | null =
|
|
226
|
-
existingPayloadEnvelopes !== null ? new Map(existingPayloadEnvelopes) : null;
|
|
227
229
|
if (downloadedPayloadEnvelopes !== null) {
|
|
228
|
-
payloadEnvelopes ??= new Map();
|
|
229
230
|
for (const [slot, envelope] of downloadedPayloadEnvelopes) {
|
|
230
|
-
|
|
231
|
-
|
|
231
|
+
// the only PayloadEnvelopeInput miss is the dangling parent, which we can get from the seen cache
|
|
232
|
+
let payloadInput = payloadEnvelopes.get(slot);
|
|
232
233
|
if (payloadInput === undefined) {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
if (updatedBatchBlocks.has(slot)) {
|
|
235
|
+
throw new Error(
|
|
236
|
+
`Missing PayloadEnvelopeInput for in-batch slot ${slot} root ${toRootHex(envelope.message.beaconBlockRoot)}`
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
payloadInput = seenPayloadEnvelopeInputCache.get(toRootHex(envelope.message.beaconBlockRoot));
|
|
240
|
+
}
|
|
241
|
+
if (payloadInput === undefined) {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`Missing PayloadEnvelopeInput for slot ${slot} root ${toRootHex(envelope.message.beaconBlockRoot)}`
|
|
244
|
+
);
|
|
236
245
|
}
|
|
237
246
|
|
|
238
247
|
if (!payloadInput.hasPayloadEnvelope()) {
|
|
@@ -262,7 +271,7 @@ export function cacheByRangeResponses({
|
|
|
262
271
|
// Gloas columns are attached to the matching PayloadEnvelopeInput, NOT to IBlockInput.
|
|
263
272
|
// Gloas DataColumnSidecar has `slot` directly (no signedBlockHeader).
|
|
264
273
|
const dataSlot = firstColumn.slot;
|
|
265
|
-
const payloadInput = payloadEnvelopes
|
|
274
|
+
const payloadInput = payloadEnvelopes.get(dataSlot);
|
|
266
275
|
if (!payloadInput) {
|
|
267
276
|
// Should not happen: we built payloadInputs for all gloas blocks above
|
|
268
277
|
continue;
|
|
@@ -13,6 +13,7 @@ import {BlobIndex, ColumnIndex, SignedBeaconBlock, Slot, deneb, fulu} from "@lod
|
|
|
13
13
|
import {LodestarError, byteArrayEquals, fromHex, prettyPrintIndices, toHex, toRootHex} from "@lodestar/utils";
|
|
14
14
|
import {isBlockInputBlobs, isBlockInputColumns} from "../../chain/blocks/blockInput/blockInput.js";
|
|
15
15
|
import {BlockInputSource, IBlockInput} from "../../chain/blocks/blockInput/types.js";
|
|
16
|
+
import {PayloadEnvelopeInputSource} from "../../chain/blocks/payloadEnvelopeInput/index.js";
|
|
16
17
|
import {ChainEventEmitter} from "../../chain/emitter.js";
|
|
17
18
|
import {IBeaconChain} from "../../chain/interface.js";
|
|
18
19
|
import {validateBlockBlobSidecars} from "../../chain/validation/blobSidecar.js";
|
|
@@ -122,7 +123,8 @@ export async function downloadByRoot({
|
|
|
122
123
|
forkName: blockInput.forkName,
|
|
123
124
|
sampledColumns: chain.custodyConfig.sampledColumns,
|
|
124
125
|
custodyColumns: chain.custodyConfig.custodyColumns,
|
|
125
|
-
|
|
126
|
+
seenTimestampSec: Date.now() / 1000,
|
|
127
|
+
source: PayloadEnvelopeInputSource.byRoot,
|
|
126
128
|
});
|
|
127
129
|
}
|
|
128
130
|
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { PublicKey } from "@chainsafe/blst";
|
|
2
|
-
export type SignatureSetDeserialized = {
|
|
3
|
-
publicKey: PublicKey;
|
|
4
|
-
message: Uint8Array;
|
|
5
|
-
signature: Uint8Array;
|
|
6
|
-
};
|
|
7
|
-
/**
|
|
8
|
-
* Verify signatures sets with batch verification or regular core verify depending on the set count.
|
|
9
|
-
* Abstracted in a separate file to be consumed by the threaded pool and the main thread implementation.
|
|
10
|
-
*/
|
|
11
|
-
export declare function verifySignatureSetsMaybeBatch(sets: SignatureSetDeserialized[]): boolean;
|
|
12
|
-
//# sourceMappingURL=maybeBatch.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"maybeBatch.d.ts","sourceRoot":"","sources":["../../../src/chain/bls/maybeBatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAuD,MAAM,iBAAiB,CAAC;AAIhG,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,UAAU,CAAC;IACpB,SAAS,EAAE,UAAU,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,wBAAwB,EAAE,GAAG,OAAO,CA8BvF"}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Signature, verify, verifyMultipleAggregateSignatures } from "@chainsafe/blst";
|
|
2
|
-
const MIN_SET_COUNT_TO_BATCH = 2;
|
|
3
|
-
/**
|
|
4
|
-
* Verify signatures sets with batch verification or regular core verify depending on the set count.
|
|
5
|
-
* Abstracted in a separate file to be consumed by the threaded pool and the main thread implementation.
|
|
6
|
-
*/
|
|
7
|
-
export function verifySignatureSetsMaybeBatch(sets) {
|
|
8
|
-
try {
|
|
9
|
-
if (sets.length >= MIN_SET_COUNT_TO_BATCH) {
|
|
10
|
-
return verifyMultipleAggregateSignatures(sets.map((s) => ({
|
|
11
|
-
pk: s.publicKey,
|
|
12
|
-
msg: s.message,
|
|
13
|
-
// true = validate signature
|
|
14
|
-
sig: Signature.fromBytes(s.signature, true),
|
|
15
|
-
})));
|
|
16
|
-
}
|
|
17
|
-
// .every on an empty array returns true
|
|
18
|
-
if (sets.length === 0) {
|
|
19
|
-
throw Error("Empty signature set");
|
|
20
|
-
}
|
|
21
|
-
// If too few signature sets verify them without batching
|
|
22
|
-
return sets.every((set) => {
|
|
23
|
-
// true = validate signature
|
|
24
|
-
const sig = Signature.fromBytes(set.signature, true);
|
|
25
|
-
return verify(set.message, set.publicKey, sig);
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
catch (_) {
|
|
29
|
-
// A signature could be malformed, in that case fromBytes throws error
|
|
30
|
-
// blst-ts `verifyMultipleSignatures` is also a fallible operation if mul_n_aggregate fails
|
|
31
|
-
// see https://github.com/ChainSafe/blst-ts/blob/b1ba6333f664b08e5c50b2b0d18c4f079203962b/src/lib.ts#L291
|
|
32
|
-
return false;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
//# sourceMappingURL=maybeBatch.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"maybeBatch.js","sourceRoot":"","sources":["../../../src/chain/bls/maybeBatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,SAAS,EAAE,MAAM,EAAE,iCAAiC,EAAC,MAAM,iBAAiB,CAAC;AAEhG,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAQjC;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAAC,IAAgC;IAC5E,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,MAAM,IAAI,sBAAsB,EAAE,CAAC;YAC1C,OAAO,iCAAiC,CACtC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACf,EAAE,EAAE,CAAC,CAAC,SAAS;gBACf,GAAG,EAAE,CAAC,CAAC,OAAO;gBACd,4BAA4B;gBAC5B,GAAG,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,CAAC;aAC5C,CAAC,CAAC,CACJ,CAAC;QACJ,CAAC;QAED,wCAAwC;QACxC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,MAAM,KAAK,CAAC,qBAAqB,CAAC,CAAC;QACrC,CAAC;QAED,yDAAyD;QACzD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;YACxB,4BAA4B;YAC5B,MAAM,GAAG,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACrD,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,sEAAsE;QACtE,2FAA2F;QAC3F,yGAAyG;QACzG,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import {PublicKey, Signature, verify, verifyMultipleAggregateSignatures} from "@chainsafe/blst";
|
|
2
|
-
|
|
3
|
-
const MIN_SET_COUNT_TO_BATCH = 2;
|
|
4
|
-
|
|
5
|
-
export type SignatureSetDeserialized = {
|
|
6
|
-
publicKey: PublicKey;
|
|
7
|
-
message: Uint8Array;
|
|
8
|
-
signature: Uint8Array;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Verify signatures sets with batch verification or regular core verify depending on the set count.
|
|
13
|
-
* Abstracted in a separate file to be consumed by the threaded pool and the main thread implementation.
|
|
14
|
-
*/
|
|
15
|
-
export function verifySignatureSetsMaybeBatch(sets: SignatureSetDeserialized[]): boolean {
|
|
16
|
-
try {
|
|
17
|
-
if (sets.length >= MIN_SET_COUNT_TO_BATCH) {
|
|
18
|
-
return verifyMultipleAggregateSignatures(
|
|
19
|
-
sets.map((s) => ({
|
|
20
|
-
pk: s.publicKey,
|
|
21
|
-
msg: s.message,
|
|
22
|
-
// true = validate signature
|
|
23
|
-
sig: Signature.fromBytes(s.signature, true),
|
|
24
|
-
}))
|
|
25
|
-
);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// .every on an empty array returns true
|
|
29
|
-
if (sets.length === 0) {
|
|
30
|
-
throw Error("Empty signature set");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// If too few signature sets verify them without batching
|
|
34
|
-
return sets.every((set) => {
|
|
35
|
-
// true = validate signature
|
|
36
|
-
const sig = Signature.fromBytes(set.signature, true);
|
|
37
|
-
return verify(set.message, set.publicKey, sig);
|
|
38
|
-
});
|
|
39
|
-
} catch (_) {
|
|
40
|
-
// A signature could be malformed, in that case fromBytes throws error
|
|
41
|
-
// blst-ts `verifyMultipleSignatures` is also a fallible operation if mul_n_aggregate fails
|
|
42
|
-
// see https://github.com/ChainSafe/blst-ts/blob/b1ba6333f664b08e5c50b2b0d18c4f079203962b/src/lib.ts#L291
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
}
|