@aztec/p2p 0.0.1-commit.e61ad554 → 0.0.1-commit.f146247c

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 (217) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +4 -3
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +4 -4
  4. package/dest/client/factory.d.ts +1 -1
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +6 -5
  7. package/dest/client/p2p_client.d.ts +1 -1
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +9 -2
  10. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
  11. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
  12. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
  13. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
  14. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
  15. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
  16. package/dest/config.d.ts +8 -2
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +2 -0
  19. package/dest/mem_pools/instrumentation.d.ts +1 -1
  20. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  21. package/dest/mem_pools/instrumentation.js +2 -2
  22. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +1 -1
  23. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  24. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +7 -2
  25. package/dest/msg_validators/proposal_validator/proposal_validator.js +5 -5
  26. package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
  27. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  28. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  29. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +5 -4
  30. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  31. package/dest/msg_validators/tx_validator/block_header_validator.js +4 -3
  32. package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
  33. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  34. package/dest/msg_validators/tx_validator/data_validator.js +4 -1
  35. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +3 -2
  36. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  37. package/dest/msg_validators/tx_validator/double_spend_validator.js +3 -2
  38. package/dest/msg_validators/tx_validator/factory.d.ts +8 -3
  39. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  40. package/dest/msg_validators/tx_validator/factory.js +21 -11
  41. package/dest/msg_validators/tx_validator/gas_validator.d.ts +3 -2
  42. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  43. package/dest/msg_validators/tx_validator/gas_validator.js +3 -2
  44. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -2
  45. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  46. package/dest/msg_validators/tx_validator/metadata_validator.js +2 -2
  47. package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
  48. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  49. package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
  50. package/dest/msg_validators/tx_validator/size_validator.d.ts +3 -1
  51. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -1
  52. package/dest/msg_validators/tx_validator/size_validator.js +4 -1
  53. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
  54. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  55. package/dest/msg_validators/tx_validator/timestamp_validator.js +2 -2
  56. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
  57. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  58. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
  59. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
  60. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  61. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -2
  62. package/dest/services/data_store.d.ts +1 -1
  63. package/dest/services/data_store.d.ts.map +1 -1
  64. package/dest/services/data_store.js +10 -6
  65. package/dest/services/discv5/discV5_service.js +1 -1
  66. package/dest/services/dummy_service.d.ts +13 -1
  67. package/dest/services/dummy_service.d.ts.map +1 -1
  68. package/dest/services/dummy_service.js +39 -0
  69. package/dest/services/libp2p/instrumentation.d.ts +1 -1
  70. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  71. package/dest/services/libp2p/instrumentation.js +14 -3
  72. package/dest/services/libp2p/libp2p_service.d.ts +9 -3
  73. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  74. package/dest/services/libp2p/libp2p_service.js +37 -28
  75. package/dest/services/peer-manager/metrics.d.ts +2 -2
  76. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  77. package/dest/services/peer-manager/metrics.js +20 -5
  78. package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
  79. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  80. package/dest/services/peer-manager/peer_scoring.js +8 -2
  81. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +47 -0
  82. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  83. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +566 -0
  84. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  85. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  86. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  87. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
  88. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  89. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  90. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +37 -0
  91. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  92. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +151 -0
  93. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
  94. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  95. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
  96. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
  97. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  98. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
  99. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +22 -3
  100. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  101. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +63 -4
  102. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -1
  103. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  104. package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
  105. package/dest/services/reqresp/interface.d.ts +3 -1
  106. package/dest/services/reqresp/interface.d.ts.map +1 -1
  107. package/dest/services/reqresp/metrics.d.ts +6 -5
  108. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  109. package/dest/services/reqresp/metrics.js +17 -5
  110. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +5 -1
  111. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  112. package/dest/services/reqresp/protocols/block_txs/bitvector.js +5 -0
  113. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  114. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  115. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +16 -3
  116. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +18 -6
  117. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  118. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +43 -13
  119. package/dest/services/reqresp/reqresp.d.ts +6 -1
  120. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  121. package/dest/services/reqresp/reqresp.js +58 -22
  122. package/dest/services/service.d.ts +4 -1
  123. package/dest/services/service.d.ts.map +1 -1
  124. package/dest/services/tx_collection/config.d.ts +4 -1
  125. package/dest/services/tx_collection/config.d.ts.map +1 -1
  126. package/dest/services/tx_collection/config.js +9 -1
  127. package/dest/services/tx_collection/fast_tx_collection.d.ts +6 -4
  128. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  129. package/dest/services/tx_collection/fast_tx_collection.js +16 -5
  130. package/dest/services/tx_collection/index.d.ts +2 -1
  131. package/dest/services/tx_collection/index.d.ts.map +1 -1
  132. package/dest/services/tx_collection/index.js +1 -0
  133. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  134. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  135. package/dest/services/tx_collection/instrumentation.js +9 -2
  136. package/dest/services/tx_collection/proposal_tx_collector.d.ts +48 -0
  137. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
  138. package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
  139. package/dest/services/tx_collection/tx_collection.d.ts +4 -4
  140. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  141. package/dest/services/tx_collection/tx_collection.js +5 -5
  142. package/dest/services/tx_provider_instrumentation.d.ts +1 -1
  143. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  144. package/dest/services/tx_provider_instrumentation.js +5 -5
  145. package/dest/test-helpers/index.d.ts +3 -1
  146. package/dest/test-helpers/index.d.ts.map +1 -1
  147. package/dest/test-helpers/index.js +2 -0
  148. package/dest/test-helpers/test_tx_provider.d.ts +40 -0
  149. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  150. package/dest/test-helpers/test_tx_provider.js +41 -0
  151. package/dest/test-helpers/testbench-utils.d.ts +158 -0
  152. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  153. package/dest/test-helpers/testbench-utils.js +297 -0
  154. package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
  155. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  156. package/dest/testbench/p2p_client_testbench_worker.js +212 -131
  157. package/dest/testbench/worker_client_manager.d.ts +51 -6
  158. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  159. package/dest/testbench/worker_client_manager.js +226 -44
  160. package/package.json +14 -14
  161. package/src/bootstrap/bootstrap.ts +7 -4
  162. package/src/client/factory.ts +6 -10
  163. package/src/client/p2p_client.ts +9 -2
  164. package/src/client/test/tx_proposal_collector/README.md +227 -0
  165. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +336 -0
  166. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
  167. package/src/config.ts +6 -1
  168. package/src/mem_pools/instrumentation.ts +2 -1
  169. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +8 -2
  170. package/src/msg_validators/proposal_validator/proposal_validator.ts +5 -5
  171. package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
  172. package/src/msg_validators/tx_validator/block_header_validator.ts +7 -8
  173. package/src/msg_validators/tx_validator/data_validator.ts +6 -2
  174. package/src/msg_validators/tx_validator/double_spend_validator.ts +4 -3
  175. package/src/msg_validators/tx_validator/factory.ts +64 -23
  176. package/src/msg_validators/tx_validator/gas_validator.ts +9 -3
  177. package/src/msg_validators/tx_validator/metadata_validator.ts +6 -3
  178. package/src/msg_validators/tx_validator/phases_validator.ts +5 -3
  179. package/src/msg_validators/tx_validator/size_validator.ts +6 -2
  180. package/src/msg_validators/tx_validator/timestamp_validator.ts +6 -3
  181. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
  182. package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
  183. package/src/services/data_store.ts +10 -7
  184. package/src/services/discv5/discV5_service.ts +1 -1
  185. package/src/services/dummy_service.ts +45 -0
  186. package/src/services/libp2p/instrumentation.ts +15 -2
  187. package/src/services/libp2p/libp2p_service.ts +60 -46
  188. package/src/services/peer-manager/metrics.ts +21 -4
  189. package/src/services/peer-manager/peer_scoring.ts +4 -1
  190. package/src/services/reqresp/batch-tx-requester/README.md +305 -0
  191. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
  192. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  193. package/src/services/reqresp/batch-tx-requester/interface.ts +57 -0
  194. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +209 -0
  195. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
  196. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
  197. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
  198. package/src/services/reqresp/connection-sampler/connection_sampler.ts +16 -0
  199. package/src/services/reqresp/interface.ts +3 -0
  200. package/src/services/reqresp/metrics.ts +34 -9
  201. package/src/services/reqresp/protocols/block_txs/bitvector.ts +7 -0
  202. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +18 -4
  203. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +51 -9
  204. package/src/services/reqresp/reqresp.ts +66 -19
  205. package/src/services/service.ts +4 -0
  206. package/src/services/tx_collection/config.ts +15 -1
  207. package/src/services/tx_collection/fast_tx_collection.ts +36 -13
  208. package/src/services/tx_collection/index.ts +5 -0
  209. package/src/services/tx_collection/instrumentation.ts +11 -2
  210. package/src/services/tx_collection/proposal_tx_collector.ts +114 -0
  211. package/src/services/tx_collection/tx_collection.ts +4 -4
  212. package/src/services/tx_provider_instrumentation.ts +11 -5
  213. package/src/test-helpers/index.ts +2 -0
  214. package/src/test-helpers/test_tx_provider.ts +64 -0
  215. package/src/test-helpers/testbench-utils.ts +374 -0
  216. package/src/testbench/p2p_client_testbench_worker.ts +321 -122
  217. package/src/testbench/worker_client_manager.ts +304 -47
@@ -6,7 +6,6 @@ import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/f
6
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
7
7
  import { Timer } from '@aztec/foundation/timer';
8
8
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
9
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
10
9
  import { protocolContractsHash } from '@aztec/protocol-contracts';
11
10
  import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
12
11
  import type { ContractDataSource } from '@aztec/stdlib/contract';
@@ -67,18 +66,15 @@ import {
67
66
  CheckpointAttestationValidator,
68
67
  CheckpointProposalValidator,
69
68
  FishermanAttestationValidator,
70
- SizeTxValidator,
71
69
  } from '../../msg_validators/index.js';
72
70
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
73
71
  import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
74
- import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
75
72
  import {
76
- AggregateTxValidator,
77
- DataTxValidator,
78
- DoubleSpendTxValidator,
79
- MetadataTxValidator,
80
- TxProofValidator,
81
- } from '../../msg_validators/tx_validator/index.js';
73
+ type MessageValidator,
74
+ createTxMessageValidators,
75
+ createTxReqRespValidator,
76
+ } from '../../msg_validators/tx_validator/factory.js';
77
+ import { DoubleSpendTxValidator } from '../../msg_validators/tx_validator/index.js';
82
78
  import { GossipSubEvent } from '../../types/index.js';
83
79
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
84
80
  import { getVersions } from '../../versioning.js';
@@ -89,10 +85,12 @@ import { gossipScoreThresholds } from '../gossipsub/scoring.js';
89
85
  import type { PeerManagerInterface } from '../peer-manager/interface.js';
90
86
  import { PeerManager } from '../peer-manager/peer_manager.js';
91
87
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
88
+ import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
92
89
  import type { P2PReqRespConfig } from '../reqresp/config.js';
93
90
  import {
94
91
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
95
92
  type ReqRespInterface,
93
+ type ReqRespResponse,
96
94
  ReqRespSubProtocol,
97
95
  type ReqRespSubProtocolHandler,
98
96
  type ReqRespSubProtocolHandlers,
@@ -286,14 +284,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
286
284
 
287
285
  const datastore = new AztecDatastore(peerStore);
288
286
 
289
- const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
287
+ const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
290
288
 
291
289
  const peerDiscoveryService = new DiscV5Service(
292
290
  peerId,
293
291
  config,
294
292
  packageVersion,
295
293
  telemetry,
296
- createLogger(`${logger.module}:discv5_service`),
294
+ createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
297
295
  );
298
296
 
299
297
  // Seed libp2p's bootstrap discovery with private and trusted peers
@@ -454,7 +452,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
454
452
  connectionManager: components.connectionManager,
455
453
  }),
456
454
  },
457
- logger: createLibp2pComponentLogger(logger.module),
455
+ logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
458
456
  });
459
457
 
460
458
  const peerScoring = new PeerScoring(config, telemetry);
@@ -642,6 +640,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
642
640
  return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
643
641
  }
644
642
 
643
+ public sendRequestToPeer(
644
+ peerId: PeerId,
645
+ subProtocol: ReqRespSubProtocol,
646
+ payload: Buffer,
647
+ dialTimeout?: number,
648
+ ): Promise<ReqRespResponse> {
649
+ return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
650
+ }
651
+
645
652
  /**
646
653
  * Get the ENR of the node
647
654
  * @returns The ENR of the node
@@ -1207,7 +1214,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1207
1214
  * @returns True if the requested block transactions are valid, false otherwise.
1208
1215
  */
1209
1216
  @trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
1210
- [Attributes.BLOCK_HASH]: request.blockHash.toString(),
1217
+ [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
1211
1218
  }))
1212
1219
  private async validateRequestedBlockTxs(
1213
1220
  request: BlockTxsRequest,
@@ -1217,10 +1224,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1217
1224
  const requestedTxValidator = this.createRequestedTxValidator();
1218
1225
 
1219
1226
  try {
1220
- if (!response.blockHash.equals(request.blockHash)) {
1227
+ if (!response.archiveRoot.equals(request.archiveRoot)) {
1221
1228
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1222
1229
  throw new ValidationError(
1223
- `Received block txs for unexpected block: expected ${request.blockHash.toString()}, got ${response.blockHash.toString()}`,
1230
+ `Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
1224
1231
  );
1225
1232
  }
1226
1233
 
@@ -1250,7 +1257,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1250
1257
  }
1251
1258
 
1252
1259
  // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1253
- const proposal = await this.mempools.attestationPool.getBlockProposal(request.blockHash.toString());
1260
+ const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
1254
1261
  if (proposal) {
1255
1262
  // Build intersected indices
1256
1263
  const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
@@ -1270,7 +1277,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1270
1277
  } else {
1271
1278
  // No local proposal, cannot check the membership/order of the returned txs
1272
1279
  this.logger.warn(
1273
- `Block proposal not found for block hash ${request.blockHash.toString()}; cannot validate membership/order of returned txs`,
1280
+ `Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
1274
1281
  );
1275
1282
  return false;
1276
1283
  }
@@ -1309,7 +1316,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1309
1316
  const requested = new Set(requestedTxHash.map(h => h.toString()));
1310
1317
  const requestedTxValidator = this.createRequestedTxValidator();
1311
1318
 
1312
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
1319
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
1313
1320
  // I think we should still extract the valid txs and return them, so that we can still use the response.
1314
1321
  try {
1315
1322
  await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
@@ -1372,28 +1379,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1372
1379
  }
1373
1380
  }
1374
1381
 
1375
- private createRequestedTxValidator(): TxValidator {
1376
- return new AggregateTxValidator(
1377
- new DataTxValidator(),
1378
- new SizeTxValidator(),
1379
- new MetadataTxValidator({
1380
- l1ChainId: new Fr(this.config.l1ChainId),
1381
- rollupVersion: new Fr(this.config.rollupVersion),
1382
- protocolContractsHash,
1383
- vkTreeRoot: getVKTreeRoot(),
1384
- }),
1385
- new TxProofValidator(this.proofVerifier),
1386
- );
1387
- }
1388
-
1389
1382
  private async validateRequestedTx(tx: Tx, peerId: PeerId, txValidator: TxValidator, requested?: Set<`0x${string}`>) {
1390
1383
  const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
1391
-
1392
- if (!(await tx.validateTxHash())) {
1393
- penalize(PeerErrorSeverity.MidToleranceError);
1394
- throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
1395
- }
1396
-
1397
1384
  if (requested && !requested.has(tx.getTxHash().toString())) {
1398
1385
  penalize(PeerErrorSeverity.MidToleranceError);
1399
1386
  throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
@@ -1406,6 +1393,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1406
1393
  }
1407
1394
  }
1408
1395
 
1396
+ private createRequestedTxValidator(): TxValidator {
1397
+ return createTxReqRespValidator(this.proofVerifier, {
1398
+ l1ChainId: this.config.l1ChainId,
1399
+ rollupVersion: this.config.rollupVersion,
1400
+ });
1401
+ }
1402
+
1409
1403
  @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
1410
1404
  [Attributes.TX_HASH]: tx.getTxHash().toString(),
1411
1405
  }))
@@ -1448,6 +1442,22 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1448
1442
  return gasFees;
1449
1443
  }
1450
1444
 
1445
+ /**
1446
+ * Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
1447
+ */
1448
+ public getBatchTxRequesterService(): BatchTxRequesterLibP2PService {
1449
+ return {
1450
+ reqResp: this.reqresp,
1451
+ connectionSampler: this.reqresp.getConnectionSampler(),
1452
+ txValidatorConfig: {
1453
+ l1ChainId: this.config.l1ChainId,
1454
+ rollupVersion: this.config.rollupVersion,
1455
+ proofVerifier: this.proofVerifier,
1456
+ },
1457
+ peerScoring: this.peerManager,
1458
+ };
1459
+ }
1460
+
1451
1461
  public async validate(txs: Tx[]): Promise<void> {
1452
1462
  const currentBlockNumber = await this.archiver.getBlockNumber();
1453
1463
 
@@ -1498,6 +1508,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1498
1508
  this.proofVerifier,
1499
1509
  !this.config.disableTransactions,
1500
1510
  allowedInSetup,
1511
+ this.logger.getBindings(),
1501
1512
  );
1502
1513
  }
1503
1514
 
@@ -1551,15 +1562,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1551
1562
  return PeerErrorSeverity.HighToleranceError;
1552
1563
  }
1553
1564
 
1554
- const snapshotValidator = new DoubleSpendTxValidator({
1555
- nullifiersExist: async (nullifiers: Buffer[]) => {
1556
- const merkleTree = this.worldStateSynchronizer.getSnapshot(
1557
- BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
1558
- );
1559
- const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1560
- return indices.map(index => index !== undefined);
1565
+ const snapshotValidator = new DoubleSpendTxValidator(
1566
+ {
1567
+ nullifiersExist: async (nullifiers: Buffer[]) => {
1568
+ const merkleTree = this.worldStateSynchronizer.getSnapshot(
1569
+ BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
1570
+ );
1571
+ const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1572
+ return indices.map(index => index !== undefined);
1573
+ },
1561
1574
  },
1562
- });
1575
+ this.logger.getBindings(),
1576
+ );
1563
1577
 
1564
1578
  const validSnapshot = await snapshotValidator.validateTx(tx);
1565
1579
  if (validSnapshot.result !== 'valid') {
@@ -6,12 +6,13 @@ import {
6
6
  type TelemetryClient,
7
7
  type Tracer,
8
8
  type UpDownCounter,
9
+ createUpDownCounterWithDefault,
9
10
  getTelemetryClient,
10
11
  } from '@aztec/telemetry-client';
11
12
 
12
13
  import type { PeerId } from '@libp2p/interface';
13
14
 
14
- import { type GoodByeReason, prettyGoodbyeReason } from '../reqresp/protocols/index.js';
15
+ import { GoodByeReason, prettyGoodbyeReason } from '../reqresp/protocols/index.js';
15
16
 
16
17
  export class PeerManagerMetrics {
17
18
  private sentGoodbyes: UpDownCounter;
@@ -31,10 +32,26 @@ export class PeerManagerMetrics {
31
32
  this.tracer = telemetryClient.getTracer(name);
32
33
 
33
34
  const meter = telemetryClient.getMeter(name);
34
- this.sentGoodbyes = meter.createUpDownCounter(Metrics.PEER_MANAGER_GOODBYES_SENT);
35
- this.receivedGoodbyes = meter.createUpDownCounter(Metrics.PEER_MANAGER_GOODBYES_RECEIVED);
35
+ const goodbyeReasonAttrs = {
36
+ [Attributes.P2P_GOODBYE_REASON]: [
37
+ prettyGoodbyeReason(GoodByeReason.SHUTDOWN),
38
+ prettyGoodbyeReason(GoodByeReason.MAX_PEERS),
39
+ prettyGoodbyeReason(GoodByeReason.LOW_SCORE),
40
+ prettyGoodbyeReason(GoodByeReason.BANNED),
41
+ prettyGoodbyeReason(GoodByeReason.WRONG_NETWORK),
42
+ prettyGoodbyeReason(GoodByeReason.UNKNOWN),
43
+ ],
44
+ };
45
+ this.sentGoodbyes = createUpDownCounterWithDefault(meter, Metrics.PEER_MANAGER_GOODBYES_SENT, goodbyeReasonAttrs);
46
+ this.receivedGoodbyes = createUpDownCounterWithDefault(
47
+ meter,
48
+ Metrics.PEER_MANAGER_GOODBYES_RECEIVED,
49
+ goodbyeReasonAttrs,
50
+ );
36
51
  this.peerCount = meter.createGauge(Metrics.PEER_MANAGER_PEER_COUNT);
37
- this.lowScoreDisconnects = meter.createUpDownCounter(Metrics.PEER_MANAGER_LOW_SCORE_DISCONNECTS);
52
+ this.lowScoreDisconnects = createUpDownCounterWithDefault(meter, Metrics.PEER_MANAGER_LOW_SCORE_DISCONNECTS, {
53
+ [Attributes.P2P_PEER_SCORE_STATE]: ['Banned', 'Disconnect'],
54
+ });
38
55
  this.peerConnectionDuration = meter.createHistogram(Metrics.PEER_MANAGER_PEER_CONNECTION_DURATION);
39
56
  }
40
57
 
@@ -6,6 +6,7 @@ import {
6
6
  Metrics,
7
7
  type TelemetryClient,
8
8
  type UpDownCounter,
9
+ createUpDownCounterWithDefault,
9
10
  getTelemetryClient,
10
11
  } from '@aztec/telemetry-client';
11
12
 
@@ -52,7 +53,9 @@ export class PeerScoring {
52
53
 
53
54
  const meter = telemetry.getMeter('PeerScoring');
54
55
 
55
- this.peerStateCounter = meter.createUpDownCounter(Metrics.P2P_PEER_STATE_COUNT);
56
+ this.peerStateCounter = createUpDownCounterWithDefault(meter, Metrics.P2P_PEER_STATE_COUNT, {
57
+ [Attributes.P2P_PEER_SCORE_STATE]: ['Healthy', 'Disconnect', 'Banned'],
58
+ });
56
59
  }
57
60
 
58
61
  public penalizePeer(peerId: PeerId, penalty: PeerErrorSeverity) {
@@ -0,0 +1,305 @@
1
+ # BatchTxRequester
2
+
3
+ The `BatchTxRequester` is a specialized P2P service that aggressively fetches missing transactions from peers when a node receives a block proposal but lacks some of the referenced transactions. This is critical for validators who need all transactions to attest to a proposal.
4
+
5
+ ## Overview
6
+
7
+ When a validator receives a block proposal, they must verify all transactions in the block. If some transactions are missing from the local mempool (e.g., due to gossip delays), the `BatchTxRequester` kicks in to fetch them via direct peer-to-peer requests before the attestation deadline.
8
+
9
+ ```
10
+ ┌─────────────────────────────────────────────────────────────────────────────┐
11
+ │ Block Proposal Received │
12
+ │ (contains hashes of N transactions) │
13
+ └─────────────────────────────────────────────────────────────────────────────┘
14
+
15
+
16
+ ┌─────────────────────────────────┐
17
+ │ Check local mempool for txs │
18
+ └─────────────────────────────────┘
19
+
20
+ ┌─────────────────┴─────────────────┐
21
+ │ │
22
+ ▼ ▼
23
+ ┌─────────────────┐ ┌─────────────────┐
24
+ │ All txs found │ │ Missing M txs │
25
+ │ → Attest now │ │ │
26
+ └─────────────────┘ └─────────────────┘
27
+
28
+
29
+ ┌───────────────────────────────┐
30
+ │ BatchTxRequester.run() │
31
+ │ Fetch missing txs until │
32
+ │ deadline or all collected │
33
+ └───────────────────────────────┘
34
+ ```
35
+
36
+ ## Architecture
37
+
38
+ ### Peer Classification
39
+
40
+ The requester classifies peers into three categories to optimize fetching:
41
+
42
+ ```
43
+ ┌─────────────────────────────┐
44
+ │ All Known Peers │
45
+ └─────────────────────────────┘
46
+
47
+ ┌────────────────────────────┼────────────────────────────┐
48
+ │ │ │
49
+ ▼ ▼ ▼
50
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
51
+ │ Pinned Peer │ │ Dumb Peers │ │ Smart Peers │
52
+ │ │ │ │ │ │
53
+ │ The peer who │ │ Peers we query │ │ Peers that have │
54
+ │ sent us the │ │ blindly - we │ │ told us which │
55
+ │ block proposal. │ │ don't know what │ │ txs they have │
56
+ │ Should have ALL │ │ txs they have. │ │ via BitVector │
57
+ │ transactions. │ │ │ │ responses. │
58
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
59
+ │ │ │
60
+ │ │ │
61
+ ▼ ▼ ▼
62
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
63
+ │ Queried in │ │ Queried with │ │ Queried with │
64
+ │ dedicated loop, │ │ full tx hashes │ │ BitVector only │
65
+ │ prioritizes │ │ (peer may not │ │ (peer has the │
66
+ │ least-requested │ │ have proposal) │ │ block proposal) │
67
+ │ transactions │ │ │ │ │
68
+ └─────────────────┘ └─────────────────┘ └─────────────────┘
69
+ ```
70
+
71
+ ### Blind Phase → Smart Phase Transition
72
+
73
+ Peers transition from "dumb" to "smart" when they respond with a valid `BlockTxsResponse` containing:
74
+ 1. A matching `archiveRoot`
75
+ 2. A non-empty `txIndices` BitVector indicating which transactions they have
76
+ 3. At least one transaction we're still missing
77
+
78
+ ```
79
+ ┌──────────────────────────────────────────────────────────────────────────────┐
80
+ │ BLIND PHASE │
81
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
82
+ │ │ Initial State: All peers are "dumb" (except pinned peer) │ │
83
+ │ │ │ │
84
+ │ │ Request: [archiveRoot, txHashes (full list), txIndices (BitVector)] │ │
85
+ │ │ └─ Include full hashes because peer may not have proposal │ │
86
+ │ │ │ │
87
+ │ │ Response: [archiveRoot, txs[], txIndices (what peer has)] │ │
88
+ │ │ └─ Tells us exactly which txs this peer can provide │ │
89
+ │ └────────────────────────────────────────────────────────────────────────┘ │
90
+ └──────────────────────────────────────────────────────────────────────────────┘
91
+
92
+ │ Peer responds with valid txIndices
93
+ │ AND has txs we're missing
94
+
95
+ ┌──────────────────────────────────────────────────────────────────────────────┐
96
+ │ SMART PHASE │
97
+ │ ┌────────────────────────────────────────────────────────────────────────┐ │
98
+ │ │ Peer promoted to "smart" - we know exactly what they have │ │
99
+ │ │ │ │
100
+ │ │ Request: [archiveRoot, txIndices (BitVector only)] │ │
101
+ │ │ └─ No need for full hashes, peer has the proposal │ │
102
+ │ │ │ │
103
+ │ │ Response: [archiveRoot, txs[], txIndices (updated availability)] │ │
104
+ │ │ └─ May have received more txs since last response │ │
105
+ │ └────────────────────────────────────────────────────────────────────────┘ │
106
+ └──────────────────────────────────────────────────────────────────────────────┘
107
+ ```
108
+
109
+ ## Concurrent Worker Architecture
110
+
111
+ The `BatchTxRequester` runs three types of workers concurrently:
112
+
113
+ ```
114
+ ┌─────────────────────────────────────┐
115
+ │ BatchTxRequester.run() │
116
+ │ │
117
+ │ ┌─────────────────────────────┐ │
118
+ │ │ txQueue (FifoMemoryQueue)│◄───┼──── Yields Tx objects
119
+ │ └─────────────────────────────┘ │ to caller
120
+ └─────────────────────────────────────┘
121
+
122
+ │ put(tx)
123
+ ┌──────────────────────────────┼────────────────────────────┐
124
+ │ │ │
125
+ │ │ │
126
+ ┌──────────┴──────────┐ ┌───────────┴─────────┐ ┌──────────┴──────────┐
127
+ │ pinnedPeerRequester │ │ dumbRequester │ │ smartRequester │
128
+ │ │ │ │ │ │
129
+ │ Single dedicated │ │ N parallel workers │ │ M parallel workers │
130
+ │ loop for pinned │ │ (default: 10) │ │ (default: 10) │
131
+ │ peer │ │ │ │ │
132
+ │ │ │ Round-robin through │ │ Wait on semaphore │
133
+ │ Prioritizes txs │ │ available dumb │ │ until peers become │
134
+ │ that have been │ │ peers │ │ smart │
135
+ │ requested least │ │ │ │ │
136
+ └─────────────────────┘ └─────────────────────┘ └─────────────────────┘
137
+ │ │ │
138
+ └──────────────────────────────┼──────────────────────────────┘
139
+
140
+
141
+ ┌───────────────────────┐
142
+ │ requestTxBatch() │
143
+ │ │
144
+ │ sendRequestToPeer() │
145
+ │ via libp2p ReqResp │
146
+ └───────────────────────┘
147
+ ```
148
+
149
+ ## Wire Protocol
150
+
151
+ ### BlockTxsRequest
152
+
153
+ ```typescript
154
+ class BlockTxsRequest {
155
+ archiveRoot: Fr; // Archive root after the proposed block is applied
156
+ txHashes: TxHashArray; // Full tx hashes (for dumb peers without proposal)
157
+ txIndices: BitVector; // Which txs from proposal we're requesting (1 = want)
158
+ }
159
+ ```
160
+
161
+ ### BlockTxsResponse
162
+
163
+ ```typescript
164
+ class BlockTxsResponse {
165
+ archiveRoot: Fr; // Echo back the proposal archive root
166
+ txs: TxArray; // Actual transaction data
167
+ txIndices: BitVector; // Which txs the peer has available (1 = have)
168
+ }
169
+ ```
170
+
171
+ The `BitVector` is a compact representation where each bit corresponds to a transaction index in the block proposal. This allows efficient capability advertisement without repeating full hashes.
172
+
173
+ ## Key Files
174
+
175
+ | File | Description |
176
+ |------|-------------|
177
+ | `batch_tx_requester.ts` | Main orchestrator with worker loops |
178
+ | `missing_txs.ts` | Tracks metadata for each missing tx (request count, in-flight status, which peers have it) |
179
+ | `peer_collection.ts` | Manages peer classification (dumb/smart/bad) and rate limiting |
180
+ | `interface.ts` | Type definitions for dependencies |
181
+ | `../protocols/block_txs/` | Wire protocol definitions (`BlockTxsRequest`, `BlockTxsResponse`, `BitVector`) |
182
+
183
+ ## Stopping Conditions
184
+
185
+ The `BatchTxRequester` stops when any of these conditions are met:
186
+
187
+ 1. **All transactions fetched** - Success!
188
+ 2. **Deadline exceeded** - Timeout configured by caller
189
+ 3. **Abort signal** - External cancellation
190
+ 4. **No transactions to fetch** - Nothing was missing
191
+
192
+ ## Configuration
193
+
194
+ | Parameter | Default | Description |
195
+ |-----------|---------|-------------|
196
+ | `batchTxRequesterSmartParallelWorkerCount` | 10 | Max concurrent requests to smart peers |
197
+ | `batchTxRequesterDumbParallelWorkerCount` | 10 | Max concurrent requests to dumb peers |
198
+ | `batchTxRequesterTxBatchSize` | 8 | Max transactions per request |
199
+ | `batchTxRequesterBadPeerThreshold` | 2 | Penalties before marking peer as bad (see > threshold logic) |
200
+ | `RATE_LIMIT_EXCEEDED_PEER_CACHE_TTL` | 1000ms | Cooldown after rate limit hit |
201
+
202
+ ## Error Handling
203
+
204
+ ### Peer States
205
+
206
+ - **Bad Peer**: After `batchTxRequesterBadPeerThreshold` penalties, peer is excluded from queries
207
+ - **Bad Peer Penalties**: A penalty is applied on `FAILURE`/`UNKNOWN` responses or when transaction validation fails
208
+ - **Rate Limited**: On `RATE_LIMIT_EXCEEDED` response, peer is temporarily excluded
209
+ - **Redemption**: A peer is removed from the bad set only after a successful response with all transactions valid (this clears the penalty counter)
210
+ - **Peer Scoring**: Each penalty is forwarded to the injected `peerScoring` service with a severity
211
+
212
+ ### Failure Recovery
213
+
214
+ ```
215
+ Request to peer fails
216
+
217
+ ├── RATE_LIMIT_EXCEEDED → Mark peer rate-limited, sleep, retry later
218
+
219
+ ├── FAILURE/UNKNOWN → Penalise peer (severity), increment penalty counter
220
+ │ │
221
+ │ ├── Counter < threshold → Continue querying
222
+ │ │
223
+ │ └── Counter ≥ threshold → Exclude peer
224
+
225
+ └── SUCCESS → Process response, if all transactions are valid clear penalties
226
+ ```
227
+
228
+ ## Usage Example
229
+
230
+ ```typescript
231
+ const requester = new BatchTxRequester(
232
+ missingTxHashes, // TxHash[] - what we need
233
+ blockProposal, // BlockProposal - the proposal we're attesting to
234
+ pinnedPeer, // PeerId | undefined - who sent us the proposal
235
+ timeoutMs, // number - how long to try
236
+ p2pService, // BatchTxRequesterLibP2PService
237
+ );
238
+
239
+ // Async generator yields transactions as they arrive
240
+ for await (const tx of requester.run()) {
241
+ // Process each transaction as it's fetched and validated
242
+ mempool.addTx(tx);
243
+ }
244
+
245
+ // Or collect all at once
246
+ const txs = await BatchTxRequester.collectAllTxs(requester.run());
247
+ ```
248
+
249
+ ## Integration with Broader Codebase
250
+
251
+ ```
252
+ ┌─────────────────────────────────────────────────────────────────────────────┐
253
+ │ P2PClient │
254
+ │ │
255
+ │ Receives block proposals via gossipsub │
256
+ │ Triggers transaction collection when needed │
257
+ └───────────────────────────────────┬─────────────────────────────────────────┘
258
+
259
+
260
+ ┌─────────────────────────────────────────────────────────────────────────────┐
261
+ │ TxCollection │
262
+ │ │
263
+ │ Coordinates Fast and Slow collection strategies │
264
+ │ Manages lifecycle of collection requests │
265
+ └───────────────────┬─────────────────────────────────┬───────────────────────┘
266
+ │ │
267
+ ▼ ▼
268
+ ┌───────────────────────────────────┐ ┌─────────────────────────────────────┐
269
+ │ FastTxCollection │ │ SlowTxCollection │
270
+ │ │ │ │
271
+ │ Time-critical: attestations │ │ Background: unproven blocks │
272
+ │ │ │ │
273
+ │ 1. Try RPC nodes first (fast) │ │ Periodic polling of RPC nodes │
274
+ │ 2. Fall back to BatchTxRequester │ │ and peers for missing txs │
275
+ │ │ │ │
276
+ └───────────────────┬───────────────┘ └─────────────────────────────────────┘
277
+
278
+ │ For 'proposal' requests
279
+
280
+ ┌─────────────────────────────────────────────────────────────────────────────┐
281
+ │ BatchTxRequester │
282
+ │ │
283
+ │ Aggressive parallel fetching from multiple peers │
284
+ │ Uses BLOCK_TXS sub-protocol for efficient batching │
285
+ └───────────────────┬─────────────────────────────────────────────────────────┘
286
+
287
+
288
+ ┌─────────────────────────────────────────────────────────────────────────────┐
289
+ │ ReqResp (libp2p) │
290
+ │ │
291
+ │ Low-level stream management │
292
+ │ sendRequestToPeer() → opens stream → sends request → awaits response │
293
+ └───────────────────┬─────────────────────────────────────────────────────────┘
294
+
295
+
296
+ ┌─────────────────────────────────────────────────────────────────────────────┐
297
+ │ reqRespBlockTxsHandler (on peer) │
298
+ │ │
299
+ │ 1. Parse BlockTxsRequest │
300
+ │ 2. Look up block proposal in AttestationPool │
301
+ │ 3. Check TxPool for available transactions │
302
+ │ 4. Build BitVector of available tx indices │
303
+ │ 5. Return BlockTxsResponse with txs + availability info │
304
+ └─────────────────────────────────────────────────────────────────────────────┘
305
+ ```