@aztec/p2p 0.0.1-commit.f5d02921e → 0.0.1-commit.f7ea82942

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.
Files changed (156) hide show
  1. package/dest/client/factory.d.ts +3 -2
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +16 -15
  4. package/dest/client/p2p_client.d.ts +1 -1
  5. package/dest/client/p2p_client.d.ts.map +1 -1
  6. package/dest/client/p2p_client.js +9 -2
  7. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +4 -1
  8. package/dest/config.d.ts +103 -99
  9. package/dest/config.d.ts.map +1 -1
  10. package/dest/config.js +11 -6
  11. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
  12. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  13. package/dest/mem_pools/attestation_pool/attestation_pool.js +5 -3
  14. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  15. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  16. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  17. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  18. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  19. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  20. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  21. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +4 -1
  22. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  23. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +5 -2
  24. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  25. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +8 -5
  26. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
  27. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +2 -1
  29. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +5 -2
  30. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  31. package/dest/msg_validators/attestation_validator/attestation_validator.js +17 -9
  32. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +4 -2
  33. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  34. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +2 -2
  35. package/dest/msg_validators/clock_tolerance.d.ts +12 -1
  36. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  37. package/dest/msg_validators/clock_tolerance.js +50 -0
  38. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +2 -1
  39. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  40. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +2 -1
  41. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  42. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -1
  43. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  44. package/dest/msg_validators/proposal_validator/proposal_validator.js +16 -8
  45. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  46. package/dest/msg_validators/tx_validator/factory.d.ts +2 -2
  47. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  48. package/dest/msg_validators/tx_validator/factory.js +3 -3
  49. package/dest/msg_validators/tx_validator/gas_validator.d.ts +36 -4
  50. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  51. package/dest/msg_validators/tx_validator/gas_validator.js +50 -33
  52. package/dest/services/data_store.d.ts +1 -1
  53. package/dest/services/data_store.d.ts.map +1 -1
  54. package/dest/services/data_store.js +5 -5
  55. package/dest/services/dummy_service.d.ts +2 -1
  56. package/dest/services/dummy_service.d.ts.map +1 -1
  57. package/dest/services/dummy_service.js +1 -0
  58. package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
  59. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  60. package/dest/services/gossipsub/topic_score_params.js +21 -4
  61. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  62. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  63. package/dest/services/libp2p/instrumentation.js +14 -0
  64. package/dest/services/libp2p/libp2p_service.d.ts +6 -17
  65. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  66. package/dest/services/libp2p/libp2p_service.js +37 -73
  67. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  68. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  69. package/dest/services/peer-manager/peer_manager.js +15 -2
  70. package/dest/services/peer-manager/peer_scoring.d.ts +3 -1
  71. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  72. package/dest/services/peer-manager/peer_scoring.js +4 -0
  73. package/dest/services/reqresp/config.d.ts +3 -3
  74. package/dest/services/reqresp/config.d.ts.map +1 -1
  75. package/dest/services/reqresp/interface.d.ts +14 -9
  76. package/dest/services/reqresp/interface.d.ts.map +1 -1
  77. package/dest/services/reqresp/interface.js +10 -11
  78. package/dest/services/reqresp/metrics.d.ts +1 -1
  79. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  80. package/dest/services/reqresp/metrics.js +0 -1
  81. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  82. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  83. package/dest/services/reqresp/protocols/index.js +0 -1
  84. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  85. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  86. package/dest/services/reqresp/protocols/tx.js +1 -3
  87. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  88. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  89. package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
  90. package/dest/services/reqresp/reqresp.d.ts +4 -2
  91. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  92. package/dest/services/reqresp/reqresp.js +11 -2
  93. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  94. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  95. package/dest/test-helpers/make-test-p2p-clients.js +4 -1
  96. package/dest/test-helpers/mock-pubsub.d.ts +11 -3
  97. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  98. package/dest/test-helpers/mock-pubsub.js +36 -11
  99. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  100. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  101. package/dest/test-helpers/reqresp-nodes.js +5 -3
  102. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  103. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  104. package/dest/test-helpers/testbench-utils.js +1 -0
  105. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  106. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  107. package/dest/testbench/p2p_client_testbench_worker.js +29 -2
  108. package/dest/testbench/worker_client_manager.d.ts +8 -1
  109. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  110. package/dest/testbench/worker_client_manager.js +49 -0
  111. package/package.json +14 -14
  112. package/src/client/factory.ts +23 -18
  113. package/src/client/p2p_client.ts +11 -3
  114. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +2 -0
  115. package/src/config.ts +19 -7
  116. package/src/mem_pools/attestation_pool/attestation_pool.ts +5 -3
  117. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  118. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  119. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
  120. package/src/mem_pools/tx_pool_v2/interfaces.ts +3 -0
  121. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +13 -7
  122. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +2 -0
  123. package/src/msg_validators/attestation_validator/attestation_validator.ts +18 -7
  124. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +4 -1
  125. package/src/msg_validators/clock_tolerance.ts +68 -0
  126. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +4 -1
  127. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +4 -1
  128. package/src/msg_validators/proposal_validator/proposal_validator.ts +13 -7
  129. package/src/msg_validators/tx_validator/README.md +11 -3
  130. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  131. package/src/msg_validators/tx_validator/factory.ts +3 -1
  132. package/src/msg_validators/tx_validator/gas_validator.ts +82 -33
  133. package/src/services/data_store.ts +5 -13
  134. package/src/services/dummy_service.ts +1 -0
  135. package/src/services/gossipsub/topic_score_params.ts +36 -4
  136. package/src/services/libp2p/instrumentation.ts +14 -0
  137. package/src/services/libp2p/libp2p_service.ts +32 -68
  138. package/src/services/peer-manager/peer_manager.ts +17 -2
  139. package/src/services/peer-manager/peer_scoring.ts +6 -0
  140. package/src/services/reqresp/config.ts +2 -2
  141. package/src/services/reqresp/interface.ts +21 -11
  142. package/src/services/reqresp/metrics.ts +0 -1
  143. package/src/services/reqresp/protocols/index.ts +0 -1
  144. package/src/services/reqresp/protocols/tx.ts +1 -3
  145. package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
  146. package/src/services/reqresp/reqresp.ts +18 -1
  147. package/src/test-helpers/make-test-p2p-clients.ts +2 -0
  148. package/src/test-helpers/mock-pubsub.ts +34 -5
  149. package/src/test-helpers/reqresp-nodes.ts +4 -2
  150. package/src/test-helpers/testbench-utils.ts +1 -0
  151. package/src/testbench/p2p_client_testbench_worker.ts +30 -0
  152. package/src/testbench/worker_client_manager.ts +55 -0
  153. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  154. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  155. package/dest/services/reqresp/protocols/block.js +0 -32
  156. package/src/services/reqresp/protocols/block.ts +0 -37
@@ -1,15 +1,14 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
3
  import { maxBy } from '@aztec/foundation/collection';
4
- import { Fr } from '@aztec/foundation/curves/bn254';
5
4
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
6
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
7
6
  import { Timer } from '@aztec/foundation/timer';
8
7
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
9
8
  import { protocolContractsHash } from '@aztec/protocol-contracts';
10
- import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
9
+ import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
11
10
  import type { ContractDataSource } from '@aztec/stdlib/contract';
12
- import { GasFees } from '@aztec/stdlib/gas';
11
+ import { type BlockMinFeesProvider, GasFees } from '@aztec/stdlib/gas';
13
12
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
14
13
  import {
15
14
  BlockProposal,
@@ -105,7 +104,6 @@ import {
105
104
  ValidationError,
106
105
  pingHandler,
107
106
  reqGoodbyeHandler,
108
- reqRespBlockHandler,
109
107
  reqRespBlockTxsHandler,
110
108
  reqRespStatusHandler,
111
109
  reqRespTxHandler,
@@ -148,8 +146,6 @@ export class LibP2PService extends WithTracer implements P2PService {
148
146
  private protocolVersion = '';
149
147
  private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
150
148
 
151
- private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
152
-
153
149
  /** Callback invoked when a duplicate proposal is detected (triggers slashing). */
154
150
  private duplicateProposalCallback?: (info: {
155
151
  slot: SlotNumber;
@@ -199,6 +195,7 @@ export class LibP2PService extends WithTracer implements P2PService {
199
195
  private epochCache: EpochCacheInterface,
200
196
  private proofVerifier: ClientProtocolCircuitVerifier,
201
197
  private worldStateSynchronizer: WorldStateSynchronizer,
198
+ private blockMinFeesProvider: BlockMinFeesProvider,
202
199
  telemetry: TelemetryClient,
203
200
  logger: Logger = createLogger('p2p:libp2p_service'),
204
201
  ) {
@@ -230,15 +227,19 @@ export class LibP2PService extends WithTracer implements P2PService {
230
227
  this.protocolVersion,
231
228
  );
232
229
 
230
+ const p2pPropagationTime = config.attestationPropagationTime;
233
231
  const proposalValidatorOpts = {
234
232
  txsPermitted: !config.disableTransactions,
235
233
  maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
234
+ p2pPropagationTime,
236
235
  };
237
236
  this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
238
237
  this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
239
238
  this.checkpointAttestationValidator = config.fishermanMode
240
- ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
241
- : new CheckpointAttestationValidator(epochCache);
239
+ ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, {
240
+ l1PublishingTime: config.l1PublishingTime,
241
+ })
242
+ : new CheckpointAttestationValidator(epochCache, { l1PublishingTime: config.l1PublishingTime });
242
243
 
243
244
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
244
245
 
@@ -283,6 +284,7 @@ export class LibP2PService extends WithTracer implements P2PService {
283
284
  proofVerifier: ClientProtocolCircuitVerifier;
284
285
  worldStateSynchronizer: WorldStateSynchronizer;
285
286
  peerStore: AztecAsyncKVStore;
287
+ blockMinFeesProvider: BlockMinFeesProvider;
286
288
  telemetry: TelemetryClient;
287
289
  logger: Logger;
288
290
  packageVersion: string;
@@ -295,6 +297,7 @@ export class LibP2PService extends WithTracer implements P2PService {
295
297
  mempools,
296
298
  proofVerifier,
297
299
  peerStore,
300
+ blockMinFeesProvider,
298
301
  telemetry,
299
302
  logger,
300
303
  packageVersion,
@@ -348,9 +351,12 @@ export class LibP2PService extends WithTracer implements P2PService {
348
351
  const l1Constants = epochCache.getL1Constants();
349
352
  const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
350
353
  slotDurationMs: l1Constants.slotDuration * 1000,
354
+ ethereumSlotDuration: l1Constants.ethereumSlotDuration,
351
355
  heartbeatIntervalMs: config.gossipsubInterval,
352
356
  targetCommitteeSize: l1Constants.targetCommitteeSize,
353
357
  blockDurationMs: config.blockDurationMs,
358
+ l1PublishingTime: config.l1PublishingTime,
359
+ p2pPropagationTime: config.attestationPropagationTime,
354
360
  expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
355
361
  });
356
362
 
@@ -475,6 +481,9 @@ export class LibP2PService extends WithTracer implements P2PService {
475
481
  epochCache,
476
482
  );
477
483
 
484
+ // Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
485
+ reqresp.setShouldRejectPeer(peerId => peerManager.shouldDisableP2PGossip(peerId));
486
+
478
487
  // Configure application-specific scoring for gossipsub.
479
488
  // The weight scales app score to align with gossipsub thresholds:
480
489
  // - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
@@ -495,6 +504,7 @@ export class LibP2PService extends WithTracer implements P2PService {
495
504
  epochCache,
496
505
  proofVerifier,
497
506
  worldStateSynchronizer,
507
+ blockMinFeesProvider,
498
508
  telemetry,
499
509
  logger,
500
510
  );
@@ -520,14 +530,12 @@ export class LibP2PService extends WithTracer implements P2PService {
520
530
  // Create request response protocol handlers
521
531
  const txHandler = reqRespTxHandler(this.mempools);
522
532
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
523
- const blockHandler = reqRespBlockHandler(this.archiver);
524
533
  const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
525
534
 
526
535
  const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
527
536
  [ReqRespSubProtocol.PING]: pingHandler,
528
537
  [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
529
538
  [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
530
- [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
531
539
  };
532
540
 
533
541
  if (!this.config.disableTransactions) {
@@ -548,7 +556,6 @@ export class LibP2PService extends WithTracer implements P2PService {
548
556
  ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
549
557
  [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
550
558
  [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
551
- [ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
552
559
  };
553
560
 
554
561
  await this.peerManager.initializePeers();
@@ -912,6 +919,17 @@ export class LibP2PService extends WithTracer implements P2PService {
912
919
  this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
913
920
  }
914
921
 
922
+ const validationTimeMs = timer.ms();
923
+ const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
924
+ if (validationTimeMs > mcacheWindowMs * 0.75) {
925
+ this.instrumentation.incSlowValidation(topicType);
926
+ this.logger.warn(
927
+ `Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` +
928
+ `Message forwarding may be skipped if validation exceeds the window.`,
929
+ { msgId, source: source.toString(), topicType, validationTimeMs, mcacheWindowMs },
930
+ );
931
+ }
932
+
915
933
  if (resultAndObj.result === TopicValidatorResult.Accept) {
916
934
  this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
917
935
  this.instrumentation.recordMessageValidation(topicType, timer);
@@ -1574,53 +1592,6 @@ export class LibP2PService extends WithTracer implements P2PService {
1574
1592
  }
1575
1593
  }
1576
1594
 
1577
- /**
1578
- * Validates a BLOCK response.
1579
- *
1580
- * If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
1581
- * Penalizes on block number mismatch or hash mismatch.
1582
- *
1583
- * @param requestedBlockNumber - The requested block number.
1584
- * @param responseBlock - The block returned by the peer.
1585
- * @param peerId - The peer that returned the block.
1586
- * @returns True if the response is valid, false otherwise.
1587
- */
1588
- @trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
1589
- [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
1590
- }))
1591
- protected async validateRequestedBlock(
1592
- requestedBlockNumber: Fr,
1593
- responseBlock: L2Block,
1594
- peerId: PeerId,
1595
- ): Promise<boolean> {
1596
- try {
1597
- const reqNum = Number(requestedBlockNumber.toString());
1598
- if (responseBlock.number !== reqNum) {
1599
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1600
- return false;
1601
- }
1602
-
1603
- const local = await this.archiver.getBlock(BlockNumber(reqNum));
1604
- if (!local) {
1605
- // We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
1606
- // TODO: Consider extending this validator to accept an expected hash or
1607
- // performing quorum-based checks when using P2P syncing prior to L1 sync.
1608
- this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
1609
- return false;
1610
- }
1611
- const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
1612
- if (!localHash.equals(respHash)) {
1613
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1614
- return false;
1615
- }
1616
-
1617
- return true;
1618
- } catch (e) {
1619
- this.logger.warn(`Error validating requested block`, e);
1620
- return false;
1621
- }
1622
- }
1623
-
1624
1595
  protected async validateRequestedTx(
1625
1596
  tx: Tx,
1626
1597
  peerId: PeerId,
@@ -1647,15 +1618,8 @@ export class LibP2PService extends WithTracer implements P2PService {
1647
1618
  });
1648
1619
  }
1649
1620
 
1650
- private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1651
- if (blockNumber === this.feesCache?.blockNumber) {
1652
- return this.feesCache.gasFees;
1653
- }
1654
-
1655
- const header = await this.archiver.getBlockHeader(blockNumber);
1656
- const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
1657
- this.feesCache = { blockNumber, gasFees };
1658
- return gasFees;
1621
+ private getGasFees(): Promise<GasFees> {
1622
+ return this.blockMinFeesProvider.getCurrentMinFees();
1659
1623
  }
1660
1624
 
1661
1625
  /**
@@ -1697,7 +1661,7 @@ export class LibP2PService extends WithTracer implements P2PService {
1697
1661
  currentBlockNumber: BlockNumber,
1698
1662
  nextSlotTimestamp: UInt64,
1699
1663
  ): Promise<Record<string, TransactionValidator>> {
1700
- const gasFees = await this.getGasFees(currentBlockNumber);
1664
+ const gasFees = await this.getGasFees();
1701
1665
  const allowedInSetup = [
1702
1666
  ...(await getDefaultAllowedSetupFunctions()),
1703
1667
  ...(this.config.txPublicSetupAllowListExtend ?? []),
@@ -728,6 +728,12 @@ export class PeerManager implements PeerManagerInterface {
728
728
  return;
729
729
  }
730
730
 
731
+ // Don't dial peers that have exceeded the auth failure threshold
732
+ if (!this.isNodeAllowedToConnect(peerId)) {
733
+ this.logger.trace(`Skipping peer ${peerId} due to failed auth handshake attempts`);
734
+ return;
735
+ }
736
+
731
737
  const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
732
738
 
733
739
  this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
@@ -985,14 +991,14 @@ export class PeerManager implements PeerManagerInterface {
985
991
  const peerIdStr = peerId.toString();
986
992
 
987
993
  const existingEntry = this.failedAuthHandshakes.get(peerIdStr);
994
+ const failureCount = (existingEntry?.count || 0) + 1;
988
995
  this.failedAuthHandshakes.set(peerIdStr, {
989
- count: (existingEntry?.count || 0) + 1,
996
+ count: failureCount,
990
997
  lastFailureTimestamp: now,
991
998
  });
992
999
 
993
1000
  const connections = this.libP2PNode.getConnections(peerId);
994
1001
  connections.forEach(conn => {
995
- // We mark the IP address
996
1002
  const address = conn.remoteAddr.nodeAddress().address;
997
1003
  const existingAddressEntry = this.failedAuthHandshakes.get(address);
998
1004
  this.failedAuthHandshakes.set(address, {
@@ -1000,6 +1006,15 @@ export class PeerManager implements PeerManagerInterface {
1000
1006
  lastFailureTimestamp: now,
1001
1007
  });
1002
1008
  });
1009
+
1010
+ // Ban the peer from being re-dialed for a cooldown period (exponential backoff)
1011
+ const banTimeMs = this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS;
1012
+ const backoffMs = banTimeMs * Math.pow(2, Math.min(failureCount - 1, 5));
1013
+ this.timedOutPeers.set(peerIdStr, {
1014
+ peerId: peerIdStr,
1015
+ timeoutUntilMs: now + backoffMs,
1016
+ });
1017
+ this.cachedPeers.delete(peerIdStr);
1003
1018
  }
1004
1019
 
1005
1020
  /*
@@ -135,6 +135,12 @@ export class PeerScoring {
135
135
  }
136
136
  }
137
137
 
138
+ /** Resets all peer scores. Useful for benchmarks to prevent cross-case contamination. */
139
+ resetAllScores(): void {
140
+ this.scores.clear();
141
+ this.lastUpdateTime.clear();
142
+ }
143
+
138
144
  removePeer(peerId: string): void {
139
145
  this.scores.delete(peerId);
140
146
  this.lastUpdateTime.delete(peerId);
@@ -1,4 +1,4 @@
1
- import { type ConfigMapping, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
1
+ import { type ConfigMappingsType, booleanConfigHelper, numberConfigHelper } from '@aztec/foundation/config';
2
2
 
3
3
  export const DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS = 10_000;
4
4
  export const DEFAULT_OVERALL_REQUEST_TIMEOUT_MS = 10_000; // Not currently used
@@ -27,7 +27,7 @@ export interface P2PReqRespConfig {
27
27
  dialTimeoutMs: number;
28
28
  }
29
29
 
30
- export const p2pReqRespConfigMappings: Record<keyof P2PReqRespConfig, ConfigMapping> = {
30
+ export const p2pReqRespConfigMappings: ConfigMappingsType<P2PReqRespConfig> = {
31
31
  overallRequestTimeoutMs: {
32
32
  env: 'P2P_REQRESP_OVERALL_REQUEST_TIMEOUT_MS',
33
33
  description: 'The overall timeout for a request response operation.',
@@ -1,6 +1,3 @@
1
- import { Fr } from '@aztec/foundation/curves/bn254';
2
- import { L2Block } from '@aztec/stdlib/block';
3
- import { MAX_L2_BLOCK_SIZE_KB } from '@aztec/stdlib/p2p';
4
1
  import { TxArray, TxHashArray } from '@aztec/stdlib/tx';
5
2
 
6
3
  import type { PeerId } from '@libp2p/interface';
@@ -24,7 +21,6 @@ export const PING_PROTOCOL = '/aztec/req/ping/1.0.0';
24
21
  export const STATUS_PROTOCOL = '/aztec/req/status/1.0.0';
25
22
  export const GOODBYE_PROTOCOL = '/aztec/req/goodbye/1.0.0';
26
23
  export const TX_REQ_PROTOCOL = '/aztec/req/tx/1.0.0';
27
- export const BLOCK_REQ_PROTOCOL = '/aztec/req/block/1.0.0';
28
24
  export const AUTH_PROTOCOL = '/aztec/req/auth/1.0.0';
29
25
  export const BLOCK_TXS_REQ_PROTOCOL = '/aztec/req/block_txs/1.0.0';
30
26
 
@@ -33,7 +29,6 @@ export enum ReqRespSubProtocol {
33
29
  STATUS = STATUS_PROTOCOL,
34
30
  GOODBYE = GOODBYE_PROTOCOL,
35
31
  TX = TX_REQ_PROTOCOL,
36
- BLOCK = BLOCK_REQ_PROTOCOL,
37
32
  AUTH = AUTH_PROTOCOL,
38
33
  BLOCK_TXS = BLOCK_TXS_REQ_PROTOCOL,
39
34
  }
@@ -100,12 +95,29 @@ export type ReqRespSubProtocolValidators = {
100
95
  [S in ReqRespSubProtocol]: ResponseValidator<any, any>;
101
96
  };
102
97
 
98
+ /**
99
+ * Protocols that are always allowed without authentication, even when p2pAllowOnlyValidators is enabled.
100
+ * These are needed for the handshake and connection management flow.
101
+ * All other protocols require the remote peer to be authenticated.
102
+ */
103
+ export const UNAUTHENTICATED_ALLOWED_PROTOCOLS: ReadonlySet<ReqRespSubProtocol> = new Set([
104
+ ReqRespSubProtocol.PING,
105
+ ReqRespSubProtocol.STATUS,
106
+ ReqRespSubProtocol.AUTH,
107
+ ReqRespSubProtocol.GOODBYE,
108
+ ]);
109
+
110
+ /**
111
+ * Callback that checks whether a peer should be rejected from req/resp data protocols.
112
+ * Returns true if the peer should be rejected (i.e. p2pAllowOnlyValidators is on and peer is unauthenticated).
113
+ */
114
+ export type ShouldRejectPeer = (peerId: string) => boolean;
115
+
103
116
  export const DEFAULT_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
104
117
  [ReqRespSubProtocol.PING]: noopValidator,
105
118
  [ReqRespSubProtocol.STATUS]: noopValidator,
106
119
  [ReqRespSubProtocol.TX]: noopValidator,
107
120
  [ReqRespSubProtocol.GOODBYE]: noopValidator,
108
- [ReqRespSubProtocol.BLOCK]: noopValidator,
109
121
  [ReqRespSubProtocol.AUTH]: noopValidator,
110
122
  [ReqRespSubProtocol.BLOCK_TXS]: noopValidator,
111
123
  };
@@ -203,10 +215,6 @@ export const subProtocolMap = {
203
215
  request: RequestableBuffer,
204
216
  response: RequestableBuffer,
205
217
  },
206
- [ReqRespSubProtocol.BLOCK]: {
207
- request: Fr, // block number
208
- response: L2Block,
209
- },
210
218
  [ReqRespSubProtocol.AUTH]: {
211
219
  request: AuthRequest,
212
220
  response: AuthResponse,
@@ -229,7 +237,6 @@ export type ExpectedResponseSizeCalculator = (requestBuffer: Buffer) => number;
229
237
  export const subProtocolSizeCalculators: Record<ReqRespSubProtocol, ExpectedResponseSizeCalculator> = {
230
238
  [ReqRespSubProtocol.TX]: calculateTxResponseSize,
231
239
  [ReqRespSubProtocol.BLOCK_TXS]: calculateBlockTxsResponseSize,
232
- [ReqRespSubProtocol.BLOCK]: () => MAX_L2_BLOCK_SIZE_KB,
233
240
  [ReqRespSubProtocol.STATUS]: () => 1,
234
241
  [ReqRespSubProtocol.PING]: () => 1,
235
242
  [ReqRespSubProtocol.AUTH]: () => 1,
@@ -264,5 +271,8 @@ export interface ReqRespInterface {
264
271
 
265
272
  updateConfig(config: Partial<P2PReqRespConfig>): void;
266
273
 
274
+ /** Sets the callback used to reject unauthenticated peers on gated req/resp protocols. */
275
+ setShouldRejectPeer(checker: ShouldRejectPeer): void;
276
+
267
277
  getConnectionSampler(): Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'>;
268
278
  }
@@ -26,7 +26,6 @@ export class ReqRespMetrics {
26
26
  ReqRespSubProtocol.STATUS,
27
27
  ReqRespSubProtocol.GOODBYE,
28
28
  ReqRespSubProtocol.TX,
29
- ReqRespSubProtocol.BLOCK,
30
29
  ReqRespSubProtocol.AUTH,
31
30
  ReqRespSubProtocol.BLOCK_TXS,
32
31
  ],
@@ -5,6 +5,5 @@ export * from './ping.js';
5
5
  export * from './status.js';
6
6
  export * from './tx.js';
7
7
  export * from './goodbye.js';
8
- export * from './block.js';
9
8
  export * from './auth.js';
10
9
  export * from './block_txs/index.js';
@@ -51,9 +51,7 @@ export function reqRespTxHandler(mempools: MemPools): ReqRespSubProtocolHandler
51
51
  * Per: https://github.com/AztecProtocol/aztec-packages/issues/15149#issuecomment-2999054485
52
52
  * we define Q as max number of transactions per batch, the comment explains why we use 8.
53
53
  */
54
- //TODO: (mralj) chunk size should by default be 8, this is just temporary until the protocol is implemented correctly
55
- //more info: https://github.com/AztecProtocol/aztec-packages/pull/15516#pullrequestreview-2995474321
56
- export function chunkTxHashesRequest(hashes: TxHash[], chunkSize = 1): Array<TxHashArray> {
54
+ export function chunkTxHashesRequest(hashes: TxHash[], chunkSize = 8): Array<TxHashArray> {
57
55
  return chunk(hashes, chunkSize).map(chunk => new TxHashArray(...chunk));
58
56
  }
59
57
 
@@ -42,16 +42,6 @@ export const DEFAULT_RATE_LIMITS: ReqRespSubProtocolRateLimits = {
42
42
  quotaCount: 200,
43
43
  },
44
44
  },
45
- [ReqRespSubProtocol.BLOCK]: {
46
- peerLimit: {
47
- quotaTimeMs: 1000,
48
- quotaCount: 2,
49
- },
50
- globalLimit: {
51
- quotaTimeMs: 1000,
52
- quotaCount: 5,
53
- },
54
- },
55
45
  [ReqRespSubProtocol.GOODBYE]: {
56
46
  peerLimit: {
57
47
  quotaTimeMs: 1000,
@@ -34,7 +34,9 @@ import {
34
34
  type ReqRespSubProtocolHandlers,
35
35
  type ReqRespSubProtocolRateLimits,
36
36
  type ReqRespSubProtocolValidators,
37
+ type ShouldRejectPeer,
37
38
  type SubProtocolMap,
39
+ UNAUTHENTICATED_ALLOWED_PROTOCOLS,
38
40
  responseFromBuffer,
39
41
  subProtocolSizeCalculators,
40
42
  } from './interface.js';
@@ -72,6 +74,8 @@ export class ReqResp implements ReqRespInterface {
72
74
 
73
75
  private snappyTransform: SnappyTransform;
74
76
 
77
+ private shouldRejectPeer: ShouldRejectPeer | undefined;
78
+
75
79
  private metrics: ReqRespMetrics;
76
80
 
77
81
  constructor(
@@ -108,6 +112,10 @@ export class ReqResp implements ReqRespInterface {
108
112
  }
109
113
  }
110
114
 
115
+ public setShouldRejectPeer(checker: ShouldRejectPeer): void {
116
+ this.shouldRejectPeer = checker;
117
+ }
118
+
111
119
  get tracer() {
112
120
  return this.metrics.tracer;
113
121
  }
@@ -462,7 +470,7 @@ export class ReqResp implements ReqRespInterface {
462
470
  );
463
471
  return resp;
464
472
  } catch (e: any) {
465
- this.logger.warn(`SUBPROTOCOL: ${subProtocol}\n`, e);
473
+ this.logger.debug(`SUBPROTOCOL: ${subProtocol}\n`, e);
466
474
  // On error we immediately abort the stream, this is preferred way,
467
475
  // because it signals to the sender that error happened, whereas
468
476
  // closing the stream only closes our side and is much slower
@@ -596,6 +604,15 @@ export class ReqResp implements ReqRespInterface {
596
604
  throw new ReqRespStatusError(ReqRespStatus.RATE_LIMIT_EXCEEDED);
597
605
  }
598
606
 
607
+ // When p2pAllowOnlyValidators is enabled, reject unauthenticated peers on data protocols
608
+ if (
609
+ !UNAUTHENTICATED_ALLOWED_PROTOCOLS.has(protocol) &&
610
+ (this.shouldRejectPeer?.(connection.remotePeer.toString()) ?? false)
611
+ ) {
612
+ this.logger.debug(`Rejecting unauthenticated peer ${connection.remotePeer} on gated protocol ${protocol}`);
613
+ throw new ReqRespStatusError(ReqRespStatus.FAILURE);
614
+ }
615
+
599
616
  await this.processStream(protocol, incomingStream);
600
617
  } catch (err: any) {
601
618
  this.metrics.recordResponseError(protocol);
@@ -5,6 +5,7 @@ import { type Logger, createLogger } from '@aztec/foundation/log';
5
5
  import { retryUntil } from '@aztec/foundation/retry';
6
6
  import { sleep } from '@aztec/foundation/sleep';
7
7
  import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
8
+ import { GasFees } from '@aztec/stdlib/gas';
8
9
  import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
9
10
  import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
10
11
 
@@ -102,6 +103,7 @@ export async function makeTestP2PClient(
102
103
  proofVerifier,
103
104
  mockWorldState,
104
105
  mockEpochCache,
106
+ { getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
105
107
  'test-p2p-client',
106
108
  undefined,
107
109
  undefined,
@@ -1,8 +1,10 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { type Logger, createLogger } from '@aztec/foundation/log';
3
+ import { sleep } from '@aztec/foundation/sleep';
3
4
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
4
5
  import type { L2BlockSource } from '@aztec/stdlib/block';
5
6
  import type { ContractDataSource } from '@aztec/stdlib/contract';
7
+ import type { BlockMinFeesProvider } from '@aztec/stdlib/gas';
6
8
  import type { ClientProtocolCircuitVerifier, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
7
9
  import type { TelemetryClient } from '@aztec/telemetry-client';
8
10
 
@@ -55,6 +57,7 @@ export function getMockPubSubP2PServiceFactory(
55
57
  proofVerifier: ClientProtocolCircuitVerifier;
56
58
  worldStateSynchronizer: WorldStateSynchronizer;
57
59
  peerStore: AztecAsyncKVStore;
60
+ blockMinFeesProvider: BlockMinFeesProvider;
58
61
  telemetry: TelemetryClient;
59
62
  logger: Logger;
60
63
  },
@@ -75,6 +78,7 @@ export function getMockPubSubP2PServiceFactory(
75
78
  deps.epochCache,
76
79
  deps.proofVerifier,
77
80
  deps.worldStateSynchronizer,
81
+ deps.blockMinFeesProvider,
78
82
  deps.telemetry,
79
83
  deps.logger,
80
84
  );
@@ -100,6 +104,7 @@ class MockReqResp implements ReqRespInterface {
100
104
  }
101
105
 
102
106
  updateConfig(_config: Partial<P2PReqRespConfig>): void {}
107
+ setShouldRejectPeer(): void {}
103
108
 
104
109
  start(
105
110
  subProtocolHandlers: Partial<ReqRespSubProtocolHandlers>,
@@ -138,6 +143,11 @@ class MockReqResp implements ReqRespInterface {
138
143
  const responses: InstanceType<SubProtocolMap[SubProtocol]['response']>[] = [];
139
144
  const peers = this.network.getReqRespPeers().filter(p => !p.peerId.equals(this.peerId));
140
145
  const targetPeers = pinnedPeer ? peers.filter(p => p.peerId.equals(pinnedPeer)) : peers;
146
+ const delayMs = this.network.getPropagationDelayMs();
147
+
148
+ if (delayMs > 0) {
149
+ await sleep(delayMs);
150
+ }
141
151
 
142
152
  for (const request of requests) {
143
153
  const requestBuffer = request.toBuffer();
@@ -174,7 +184,12 @@ class MockReqResp implements ReqRespInterface {
174
184
  return { status: ReqRespStatus.SUCCESS, data: Buffer.from([]) };
175
185
  }
176
186
  try {
187
+ const delayMs = this.network.getPropagationDelayMs();
188
+ if (delayMs > 0) {
189
+ await sleep(delayMs);
190
+ }
177
191
  const data = await handler(this.peerId, payload);
192
+
178
193
  return { status: ReqRespStatus.SUCCESS, data };
179
194
  } catch {
180
195
  return { status: ReqRespStatus.FAILURE };
@@ -242,10 +257,10 @@ class MockGossipSubService extends TypedEventEmitter<GossipsubEvents> implements
242
257
  score: (_peerId: PeerIdStr) => 0,
243
258
  };
244
259
 
245
- publish(topic: TopicStr, data: Uint8Array, _opts?: PublishOpts): Promise<PublishResult> {
260
+ async publish(topic: TopicStr, data: Uint8Array, _opts?: PublishOpts): Promise<PublishResult> {
246
261
  this.logger.debug(`Publishing message on topic ${topic}`, { topic, sender: this.peerId.toString() });
247
- this.network.publishToPeers(topic, data, this.peerId);
248
- return Promise.resolve({ recipients: this.network.getPeers().filter(peer => !this.peerId.equals(peer)) });
262
+ await this.network.publishToPeers(topic, data, this.peerId);
263
+ return { recipients: this.network.getPeers().filter(peer => !this.peerId.equals(peer)) };
249
264
  }
250
265
 
251
266
  receive(msg: GossipsubMessage) {
@@ -281,7 +296,8 @@ class MockGossipSubService extends TypedEventEmitter<GossipsubEvents> implements
281
296
 
282
297
  /**
283
298
  * Mock gossip sub network used for testing.
284
- * All instances of MockGossipSubService connected to the same network will instantly receive the same messages.
299
+ * All instances of MockGossipSubService connected to the same network receive the same messages,
300
+ * optionally delayed by a configurable propagation time.
285
301
  */
286
302
  export class MockGossipSubNetwork {
287
303
  private peers: MockGossipSubService[] = [];
@@ -290,6 +306,15 @@ export class MockGossipSubNetwork {
290
306
 
291
307
  private logger = createLogger('p2p:test:mock-gossipsub-network');
292
308
 
309
+ constructor(
310
+ /** Artificial propagation delay in milliseconds applied to each message delivery. */
311
+ private propagationDelayMs: number = 0,
312
+ ) {}
313
+
314
+ public getPropagationDelayMs(): number {
315
+ return this.propagationDelayMs;
316
+ }
317
+
293
318
  public getPeers(): PeerId[] {
294
319
  return this.peers.map(peer => peer.peerId);
295
320
  }
@@ -306,7 +331,7 @@ export class MockGossipSubNetwork {
306
331
  return this.reqRespPeers;
307
332
  }
308
333
 
309
- public publishToPeers(topic: TopicStr, data: Uint8Array, sender: PeerId): void {
334
+ public async publishToPeers(topic: TopicStr, data: Uint8Array, sender: PeerId): Promise<void> {
310
335
  const msgId = (this.nextMsgId++).toString();
311
336
  this.logger.debug(`Network is distributing message on topic ${topic}`, {
312
337
  topic,
@@ -315,6 +340,10 @@ export class MockGossipSubNetwork {
315
340
  msgId,
316
341
  });
317
342
 
343
+ if (this.propagationDelayMs > 0) {
344
+ await sleep(this.propagationDelayMs);
345
+ }
346
+
318
347
  const gossipSubMsg: GossipsubMessage = { msgId, msg: { type: 'unsigned', topic, data }, propagationSource: sender };
319
348
  for (const peer of this.peers) {
320
349
  if (peer.subscribedTopics.has(topic)) {
@@ -6,6 +6,7 @@ import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
6
6
  import type { L2BlockSource } from '@aztec/stdlib/block';
7
7
  import { type ChainConfig, emptyChainConfig } from '@aztec/stdlib/config';
8
8
  import type { ContractDataSource } from '@aztec/stdlib/contract';
9
+ import { GasFees } from '@aztec/stdlib/gas';
9
10
  import type {
10
11
  ClientProtocolCircuitVerifier,
11
12
  IVCProofVerificationResult,
@@ -153,6 +154,8 @@ export async function createTestLibP2PService(
153
154
  epochCache,
154
155
  );
155
156
 
157
+ reqresp.setShouldRejectPeer(peerId => peerManager.shouldDisableP2PGossip(peerId));
158
+
156
159
  p2pNode.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
157
160
  p2pNode.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
158
161
  peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
@@ -168,6 +171,7 @@ export async function createTestLibP2PService(
168
171
  epochCache,
169
172
  proofVerifier,
170
173
  worldStateSynchronizer,
174
+ { getCurrentMinFees: () => Promise.resolve(GasFees.empty()) },
171
175
  telemetry,
172
176
  );
173
177
  }
@@ -187,7 +191,6 @@ export const MOCK_SUB_PROTOCOL_HANDLERS: ReqRespSubProtocolHandlers = {
187
191
  [ReqRespSubProtocol.STATUS]: (_msg: any) => Promise.resolve(Buffer.from('status')),
188
192
  [ReqRespSubProtocol.TX]: (_msg: any) => Promise.resolve(Buffer.from('tx')),
189
193
  [ReqRespSubProtocol.GOODBYE]: (_msg: any) => Promise.resolve(Buffer.from('goodbye')),
190
- [ReqRespSubProtocol.BLOCK]: (_msg: any) => Promise.resolve(Buffer.from('block')),
191
194
  [ReqRespSubProtocol.AUTH]: (_msg: any) => Promise.resolve(Buffer.from('auth')),
192
195
  [ReqRespSubProtocol.BLOCK_TXS]: (_msg: any) => Promise.resolve(Buffer.from('block_txs')),
193
196
  };
@@ -199,7 +202,6 @@ export const MOCK_SUB_PROTOCOL_VALIDATORS: ReqRespSubProtocolValidators = {
199
202
  [ReqRespSubProtocol.STATUS]: noopValidator,
200
203
  [ReqRespSubProtocol.TX]: noopValidator,
201
204
  [ReqRespSubProtocol.GOODBYE]: noopValidator,
202
- [ReqRespSubProtocol.BLOCK]: noopValidator,
203
205
  [ReqRespSubProtocol.AUTH]: noopValidator,
204
206
  [ReqRespSubProtocol.BLOCK_TXS]: noopValidator,
205
207
  };
@@ -287,6 +287,7 @@ export function createMockEpochCache(): EpochCacheInterface {
287
287
  nowMs: 0n,
288
288
  }),
289
289
  isProposerPipeliningEnabled: () => false,
290
+ pipeliningOffset: () => 0,
290
291
  computeProposerIndex: () => 0n,
291
292
  getCurrentAndNextSlot: () => ({ currentSlot: SlotNumber.ZERO, nextSlot: SlotNumber.ZERO }),
292
293
  getTargetAndNextSlot: () => ({ targetSlot: SlotNumber.ZERO, nextSlot: SlotNumber.ZERO }),