@aztec/p2p 0.0.1-commit.9ef841308 → 0.0.1-commit.a5db02d

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 (344) hide show
  1. package/README.md +7 -6
  2. package/dest/bootstrap/bootstrap.d.ts +1 -1
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  4. package/dest/bootstrap/bootstrap.js +22 -6
  5. package/dest/client/factory.d.ts +4 -3
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +33 -24
  8. package/dest/client/interface.d.ts +48 -11
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +34 -19
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +105 -46
  13. package/dest/config.d.ts +143 -107
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +72 -26
  16. package/dest/errors/p2p-service.error.d.ts +9 -0
  17. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  18. package/dest/errors/p2p-service.error.js +10 -0
  19. package/dest/errors/reqresp.error.d.ts +9 -16
  20. package/dest/errors/reqresp.error.d.ts.map +1 -1
  21. package/dest/errors/reqresp.error.js +10 -17
  22. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +98 -56
  23. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool.js +269 -196
  25. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  26. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +218 -59
  28. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
  29. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/mocks.js +6 -4
  31. package/dest/mem_pools/instrumentation.d.ts +9 -4
  32. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  33. package/dest/mem_pools/instrumentation.js +28 -9
  34. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
  35. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
  36. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
  37. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -3
  38. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
  39. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +6 -6
  40. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +1 -1
  41. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  42. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  43. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  44. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  45. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  46. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  47. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  48. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +33 -5
  49. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
  51. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +5 -2
  52. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +8 -5
  54. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
  55. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  56. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +31 -0
  57. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -3
  58. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +19 -8
  60. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +17 -4
  61. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  62. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +208 -118
  63. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
  64. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  65. package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -16
  66. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
  67. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  68. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
  69. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +8 -3
  70. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  71. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +2 -2
  72. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +8 -3
  73. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  74. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +8 -2
  75. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +25 -3
  76. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  77. package/dest/msg_validators/proposal_validator/proposal_validator.js +85 -15
  78. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  79. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  80. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
  81. package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
  82. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  83. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  84. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  85. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  86. package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
  87. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  88. package/dest/msg_validators/tx_validator/data_validator.js +1 -0
  89. package/dest/msg_validators/tx_validator/factory.d.ts +14 -15
  90. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  91. package/dest/msg_validators/tx_validator/factory.js +29 -16
  92. package/dest/msg_validators/tx_validator/gas_validator.d.ts +47 -10
  93. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  94. package/dest/msg_validators/tx_validator/gas_validator.js +65 -48
  95. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  96. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  97. package/dest/msg_validators/tx_validator/index.js +2 -0
  98. package/dest/msg_validators/tx_validator/phases_validator.js +2 -2
  99. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
  100. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  101. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
  102. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  103. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  104. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  105. package/dest/services/data_store.d.ts +1 -1
  106. package/dest/services/data_store.d.ts.map +1 -1
  107. package/dest/services/data_store.js +5 -5
  108. package/dest/services/discv5/discV5_service.d.ts +13 -2
  109. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  110. package/dest/services/discv5/discV5_service.js +119 -25
  111. package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
  112. package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
  113. package/dest/services/discv5/persisted_enr_store.js +145 -0
  114. package/dest/services/dummy_service.d.ts +15 -15
  115. package/dest/services/dummy_service.d.ts.map +1 -1
  116. package/dest/services/dummy_service.js +15 -16
  117. package/dest/services/encoding.d.ts +19 -6
  118. package/dest/services/encoding.d.ts.map +1 -1
  119. package/dest/services/encoding.js +25 -15
  120. package/dest/services/gossipsub/topic_score_params.d.ts +6 -12
  121. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  122. package/dest/services/gossipsub/topic_score_params.js +4 -14
  123. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  124. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  125. package/dest/services/libp2p/instrumentation.js +14 -0
  126. package/dest/services/libp2p/libp2p_service.d.ts +40 -40
  127. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  128. package/dest/services/libp2p/libp2p_service.js +292 -264
  129. package/dest/services/peer-manager/peer_manager.d.ts +15 -2
  130. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  131. package/dest/services/peer-manager/peer_manager.js +59 -17
  132. package/dest/services/peer-manager/peer_scoring.d.ts +30 -1
  133. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  134. package/dest/services/peer-manager/peer_scoring.js +74 -3
  135. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +1 -8
  136. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  137. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +35 -44
  138. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +8 -5
  139. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  140. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
  141. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
  142. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
  143. package/dest/services/reqresp/config.d.ts +15 -3
  144. package/dest/services/reqresp/config.d.ts.map +1 -1
  145. package/dest/services/reqresp/config.js +11 -0
  146. package/dest/services/reqresp/interface.d.ts +16 -18
  147. package/dest/services/reqresp/interface.d.ts.map +1 -1
  148. package/dest/services/reqresp/interface.js +10 -20
  149. package/dest/services/reqresp/metrics.d.ts +1 -1
  150. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  151. package/dest/services/reqresp/metrics.js +0 -1
  152. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
  153. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  154. package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
  155. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  156. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  157. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
  158. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
  159. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  160. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
  161. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  162. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  163. package/dest/services/reqresp/protocols/index.js +0 -1
  164. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  165. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  166. package/dest/services/reqresp/protocols/tx.js +1 -3
  167. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  168. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  169. package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -13
  170. package/dest/services/reqresp/reqresp.d.ts +7 -29
  171. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  172. package/dest/services/reqresp/reqresp.js +59 -209
  173. package/dest/services/service.d.ts +23 -16
  174. package/dest/services/service.d.ts.map +1 -1
  175. package/dest/services/tx_collection/config.d.ts +2 -23
  176. package/dest/services/tx_collection/config.d.ts.map +1 -1
  177. package/dest/services/tx_collection/config.js +2 -55
  178. package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
  179. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  180. package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
  181. package/dest/services/tx_collection/index.d.ts +2 -3
  182. package/dest/services/tx_collection/index.d.ts.map +1 -1
  183. package/dest/services/tx_collection/index.js +0 -1
  184. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  185. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  186. package/dest/services/tx_collection/instrumentation.js +0 -2
  187. package/dest/services/tx_collection/tx_collection.d.ts +35 -51
  188. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  189. package/dest/services/tx_collection/tx_collection.js +275 -119
  190. package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
  191. package/dest/services/tx_collection/tx_collection_sink.js +2 -2
  192. package/dest/services/tx_collection/tx_source.d.ts +1 -1
  193. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  194. package/dest/services/tx_collection/tx_source.js +4 -1
  195. package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
  196. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  197. package/dest/services/tx_file_store/tx_file_store.js +4 -14
  198. package/dest/services/tx_provider.d.ts +3 -1
  199. package/dest/services/tx_provider.d.ts.map +1 -1
  200. package/dest/services/tx_provider.js +3 -0
  201. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  202. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  203. package/dest/test-helpers/make-test-p2p-clients.js +5 -2
  204. package/dest/test-helpers/mock-pubsub.d.ts +21 -12
  205. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  206. package/dest/test-helpers/mock-pubsub.js +39 -47
  207. package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
  208. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  209. package/dest/test-helpers/reqresp-nodes.js +16 -18
  210. package/dest/test-helpers/test_tx_provider.d.ts +3 -1
  211. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
  212. package/dest/test-helpers/test_tx_provider.js +3 -0
  213. package/dest/test-helpers/testbench-utils.d.ts +15 -14
  214. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  215. package/dest/test-helpers/testbench-utils.js +28 -13
  216. package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
  217. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  218. package/dest/testbench/p2p_client_testbench_worker.js +60 -27
  219. package/dest/testbench/worker_client_manager.d.ts +10 -6
  220. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  221. package/dest/testbench/worker_client_manager.js +51 -8
  222. package/dest/util.d.ts +8 -8
  223. package/dest/util.d.ts.map +1 -1
  224. package/dest/util.js +38 -10
  225. package/dest/versioning.d.ts +3 -6
  226. package/dest/versioning.d.ts.map +1 -1
  227. package/dest/versioning.js +3 -24
  228. package/package.json +16 -16
  229. package/src/bootstrap/bootstrap.ts +17 -3
  230. package/src/client/factory.ts +49 -25
  231. package/src/client/interface.ts +44 -17
  232. package/src/client/p2p_client.ts +125 -79
  233. package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
  234. package/src/config.ts +146 -34
  235. package/src/errors/p2p-service.error.ts +11 -0
  236. package/src/errors/reqresp.error.ts +13 -19
  237. package/src/mem_pools/attestation_pool/attestation_pool.ts +324 -239
  238. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +238 -63
  239. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  240. package/src/mem_pools/instrumentation.ts +18 -12
  241. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
  242. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
  243. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +1 -1
  244. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  245. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  246. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
  247. package/src/mem_pools/tx_pool_v2/interfaces.ts +31 -4
  248. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +13 -7
  249. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +35 -0
  250. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +22 -8
  251. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +233 -123
  252. package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -15
  253. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
  254. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +15 -3
  255. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +26 -3
  256. package/src/msg_validators/proposal_validator/proposal_validator.ts +94 -12
  257. package/src/msg_validators/tx_validator/README.md +13 -3
  258. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
  259. package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
  260. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  261. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  262. package/src/msg_validators/tx_validator/data_validator.ts +2 -0
  263. package/src/msg_validators/tx_validator/factory.ts +37 -20
  264. package/src/msg_validators/tx_validator/gas_validator.ts +99 -54
  265. package/src/msg_validators/tx_validator/index.ts +2 -0
  266. package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
  267. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
  268. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  269. package/src/services/data_store.ts +5 -13
  270. package/src/services/discv5/discV5_service.ts +126 -16
  271. package/src/services/discv5/persisted_enr_store.ts +158 -0
  272. package/src/services/dummy_service.ts +20 -39
  273. package/src/services/encoding.ts +28 -20
  274. package/src/services/gossipsub/README.md +33 -11
  275. package/src/services/gossipsub/topic_score_params.ts +9 -18
  276. package/src/services/libp2p/instrumentation.ts +14 -0
  277. package/src/services/libp2p/libp2p_service.ts +342 -290
  278. package/src/services/peer-manager/peer_manager.ts +63 -16
  279. package/src/services/peer-manager/peer_scoring.ts +81 -3
  280. package/src/services/reqresp/README.md +2 -37
  281. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +39 -52
  282. package/src/services/reqresp/batch-tx-requester/interface.ts +11 -4
  283. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
  284. package/src/services/reqresp/config.ts +19 -2
  285. package/src/services/reqresp/interface.ts +21 -47
  286. package/src/services/reqresp/metrics.ts +0 -1
  287. package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
  288. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
  289. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
  290. package/src/services/reqresp/protocols/index.ts +0 -1
  291. package/src/services/reqresp/protocols/tx.ts +1 -3
  292. package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
  293. package/src/services/reqresp/reqresp.ts +69 -252
  294. package/src/services/service.ts +28 -32
  295. package/src/services/tx_collection/config.ts +3 -80
  296. package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
  297. package/src/services/tx_collection/index.ts +1 -6
  298. package/src/services/tx_collection/instrumentation.ts +1 -7
  299. package/src/services/tx_collection/tx_collection.ts +330 -173
  300. package/src/services/tx_collection/tx_collection_sink.ts +2 -2
  301. package/src/services/tx_collection/tx_source.ts +2 -1
  302. package/src/services/tx_file_store/tx_file_store.ts +5 -17
  303. package/src/services/tx_provider.ts +5 -0
  304. package/src/test-helpers/make-test-p2p-clients.ts +3 -0
  305. package/src/test-helpers/mock-pubsub.ts +41 -64
  306. package/src/test-helpers/reqresp-nodes.ts +12 -22
  307. package/src/test-helpers/test_tx_provider.ts +5 -0
  308. package/src/test-helpers/testbench-utils.ts +35 -26
  309. package/src/testbench/p2p_client_testbench_worker.ts +68 -44
  310. package/src/testbench/worker_client_manager.ts +59 -19
  311. package/src/util.ts +33 -14
  312. package/src/versioning.ts +3 -33
  313. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
  314. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
  315. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -315
  316. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
  317. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
  318. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
  319. package/dest/msg_validators/clock_tolerance.d.ts +0 -21
  320. package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
  321. package/dest/msg_validators/clock_tolerance.js +0 -38
  322. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
  323. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  324. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
  325. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  326. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  327. package/dest/services/reqresp/protocols/block.js +0 -32
  328. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -51
  329. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  330. package/dest/services/tx_collection/fast_tx_collection.js +0 -311
  331. package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -48
  332. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
  333. package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
  334. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
  335. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  336. package/dest/services/tx_collection/slow_tx_collection.js +0 -211
  337. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -355
  338. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
  339. package/src/msg_validators/clock_tolerance.ts +0 -52
  340. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
  341. package/src/services/reqresp/protocols/block.ts +0 -37
  342. package/src/services/tx_collection/fast_tx_collection.ts +0 -361
  343. package/src/services/tx_collection/proposal_tx_collector.ts +0 -108
  344. package/src/services/tx_collection/slow_tx_collection.ts +0 -266
@@ -1,4 +1,5 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
+ import { compactArray } from '@aztec/foundation/collection';
2
3
  import { makeEthSignDigest, tryRecoverAddress } from '@aztec/foundation/crypto/secp256k1-signer';
3
4
  import { Fr } from '@aztec/foundation/curves/bn254';
4
5
  import type { EthAddress } from '@aztec/foundation/eth-address';
@@ -164,6 +165,7 @@ export class PeerManager implements PeerManagerInterface {
164
165
  public async heartbeat() {
165
166
  this.heartbeatCounter++;
166
167
  this.peerScoring.decayAllScores();
168
+ this.peerScoring.pruneExpiredBans();
167
169
  this.cleanupExpiredTimeouts();
168
170
 
169
171
  await this.setupDirectPeersIfValidator();
@@ -198,21 +200,27 @@ export class PeerManager implements PeerManagerInterface {
198
200
  .then(peerIds => peerIds.forEach(peerId => this.preferredPeers.add(peerId.toString())))
199
201
  .catch(e => this.logger.error('Error initializing preferred peers', e));
200
202
 
201
- const directPeers = (
203
+ const directPeers = compactArray(
202
204
  await Promise.all(
203
205
  preferredPeersEnrs.map(async enr => {
204
- const peerId = await enr.peerId();
205
- const address = enr.getLocationMultiaddr('tcp');
206
- if (address === undefined) {
207
- throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
206
+ try {
207
+ const peerId = await enr.peerId();
208
+ const address = enr.getLocationMultiaddr('tcp');
209
+ if (address === undefined) {
210
+ throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
211
+ }
212
+ return {
213
+ id: peerId,
214
+ addrs: [address],
215
+ };
216
+ } catch (err) {
217
+ // A malformed configured ENR shouldn't abort preferred-peer setup — skip it and log.
218
+ this.logger.warn(`Skipping preferred peer with invalid ENR`, { err });
219
+ return undefined;
208
220
  }
209
- return {
210
- id: peerId,
211
- addrs: [address],
212
- };
213
221
  }),
214
- )
215
- ).filter(peer => peer !== undefined);
222
+ ),
223
+ );
216
224
 
217
225
  await Promise.all(
218
226
  directPeers.map(peer => {
@@ -494,15 +502,38 @@ export class PeerManager implements PeerManagerInterface {
494
502
  *
495
503
  * @returns: True if node is allowed to connect, otherwise false
496
504
  * */
497
- public isNodeAllowedToConnect(id: string | PeerId): boolean {
498
- const entry = this.failedAuthHandshakes.get(id.toString());
505
+ /**
506
+ * Whether a peer is allowed to connect, given its peer id. Rejects peers serving an active ban and
507
+ * peers that have exceeded the failed auth-handshake limit. Use this once the peer id is known —
508
+ * i.e. for the encrypted-inbound gater and when dialing.
509
+ */
510
+ public isPeerAllowedToConnect(peerId: string | PeerId): boolean {
511
+ const id = peerId.toString();
512
+ if (this.peerScoring.getScoreState(id) === PeerScoreState.Banned) {
513
+ return false;
514
+ }
515
+ return this.isWithinFailedAuthLimit(id);
516
+ }
517
+
518
+ /**
519
+ * Whether a connection from an address is allowed. Bans are keyed by peer id, which isn't known at
520
+ * the raw-inbound layer, so only the failed auth-handshake limit (also tracked per address) is
521
+ * enforced here; the ban is applied once the peer id is known via {@link isPeerAllowedToConnect}.
522
+ */
523
+ public isAddressAllowedToConnect(address: string): boolean {
524
+ return this.isWithinFailedAuthLimit(address);
525
+ }
526
+
527
+ /** Whether the failed auth-handshake count for a peer id or address is below the configured limit. */
528
+ private isWithinFailedAuthLimit(key: string): boolean {
529
+ const entry = this.failedAuthHandshakes.get(key);
499
530
  if (!entry) {
500
531
  return true;
501
532
  }
502
533
 
503
534
  // In case entry is too old, remove it and allow connection
504
535
  if (this.dateProvider.now() - entry.lastFailureTimestamp > FAILED_AUTH_HANDSHAKE_EXPIRY_MS) {
505
- this.failedAuthHandshakes.delete(id.toString());
536
+ this.failedAuthHandshakes.delete(key);
506
537
  return true;
507
538
  }
508
539
 
@@ -527,6 +558,7 @@ export class PeerManager implements PeerManagerInterface {
527
558
  protectedConnections: protectedPeerCount,
528
559
  maxPeerCount: this.config.maxPeerCount,
529
560
  cachedPeers: this.cachedPeers.size,
561
+ discv5KadPeers: this.peerDiscoveryService.getKadValues().length,
530
562
  ...this.peerScoring.getStats(),
531
563
  });
532
564
 
@@ -728,6 +760,12 @@ export class PeerManager implements PeerManagerInterface {
728
760
  return;
729
761
  }
730
762
 
763
+ // Don't dial banned peers or those that have exceeded the auth failure threshold
764
+ if (!this.isPeerAllowedToConnect(peerId)) {
765
+ this.logger.trace(`Skipping peer ${peerId} due to ban or failed auth handshake attempts`);
766
+ return;
767
+ }
768
+
731
769
  const [multiaddrTcp] = await Promise.all([enr.getFullMultiaddr('tcp')]);
732
770
 
733
771
  this.logger.trace(`Handling discovered peer ${peerId} at ${multiaddrTcp?.toString() ?? 'undefined address'}`);
@@ -985,14 +1023,14 @@ export class PeerManager implements PeerManagerInterface {
985
1023
  const peerIdStr = peerId.toString();
986
1024
 
987
1025
  const existingEntry = this.failedAuthHandshakes.get(peerIdStr);
1026
+ const failureCount = (existingEntry?.count || 0) + 1;
988
1027
  this.failedAuthHandshakes.set(peerIdStr, {
989
- count: (existingEntry?.count || 0) + 1,
1028
+ count: failureCount,
990
1029
  lastFailureTimestamp: now,
991
1030
  });
992
1031
 
993
1032
  const connections = this.libP2PNode.getConnections(peerId);
994
1033
  connections.forEach(conn => {
995
- // We mark the IP address
996
1034
  const address = conn.remoteAddr.nodeAddress().address;
997
1035
  const existingAddressEntry = this.failedAuthHandshakes.get(address);
998
1036
  this.failedAuthHandshakes.set(address, {
@@ -1000,6 +1038,15 @@ export class PeerManager implements PeerManagerInterface {
1000
1038
  lastFailureTimestamp: now,
1001
1039
  });
1002
1040
  });
1041
+
1042
+ // Ban the peer from being re-dialed for a cooldown period (exponential backoff)
1043
+ const banTimeMs = this.config.peerFailedBanTimeMs ?? DEFAULT_FAILED_PEER_BAN_TIME_MS;
1044
+ const backoffMs = banTimeMs * Math.pow(2, Math.min(failureCount - 1, 5));
1045
+ this.timedOutPeers.set(peerIdStr, {
1046
+ peerId: peerIdStr,
1047
+ timeoutUntilMs: now + backoffMs,
1048
+ });
1049
+ this.cachedPeers.delete(peerIdStr);
1003
1050
  }
1004
1051
 
1005
1052
  /*
@@ -57,6 +57,9 @@ const MIN_SCORE_BEFORE_BAN = -100;
57
57
  const MIN_SCORE_BEFORE_DISCONNECT = -50;
58
58
  const SCORE_CLEANUP_THRESHOLD = 0.1;
59
59
 
60
+ /** An active ban: the score the peer held when banned, and the timestamp at which the ban lifts. */
61
+ type BanRecord = { score: number; expiry: number };
62
+
60
63
  export class PeerScoring {
61
64
  private logger = createLogger('p2p:peer-scoring');
62
65
  private scores: Map<string, number> = new Map();
@@ -67,11 +70,21 @@ export class PeerScoring {
67
70
 
68
71
  private peerStateCounter: UpDownCounter;
69
72
 
73
+ /** Active bans, keyed by peer id. Held in memory only, so they are cleared on restart. */
74
+ private bannedPeers: Map<string, BanRecord> = new Map();
75
+ /**
76
+ * How long a peer remains banned once its score crosses MIN_SCORE_BEFORE_BAN. While banned, the
77
+ * peer's ban score is returned by getScore regardless of decay, so it cannot recover its way out
78
+ * of the ban early. After the ban expires the live (decayed) score takes over again.
79
+ */
80
+ private readonly banDurationMs: number;
81
+
70
82
  constructor(
71
83
  config: P2PConfig,
72
84
  telemetry: TelemetryClient = getTelemetryClient(),
73
85
  private readonly dateProvider: DateProvider = new DateProvider(),
74
86
  ) {
87
+ this.banDurationMs = config.peerBanDurationSeconds * 1000;
75
88
  const orderedValues = config.peerPenaltyValues?.sort((a, b) => a - b);
76
89
  this.peerPenalties = {
77
90
  [PeerErrorSeverity.HighToleranceError]:
@@ -113,9 +126,31 @@ export class PeerScoring {
113
126
 
114
127
  this.scores.set(peerId, currentScore);
115
128
  this.lastUpdateTime.set(peerId, currentTime);
129
+
130
+ this.maybeBanPeer(peerId, currentScore);
131
+
116
132
  return currentScore;
117
133
  }
118
134
 
135
+ /**
136
+ * Records a ban for a peer whose score has crossed the ban threshold, with an expiry banDurationMs
137
+ * in the future. No-op if the score is above the threshold or the peer is already serving an active
138
+ * ban (an existing ban is not extended; the original window stands). A previously expired ban does
139
+ * not block a fresh one — getActiveBanScore prunes it first.
140
+ */
141
+ private maybeBanPeer(peerId: string, score: number): void {
142
+ if (score >= MIN_SCORE_BEFORE_BAN || this.getActiveBanScore(peerId) !== undefined) {
143
+ return;
144
+ }
145
+ const record: BanRecord = { score, expiry: this.dateProvider.now() + this.banDurationMs };
146
+ this.bannedPeers.set(peerId, record);
147
+ this.logger.verbose(`Banning peer ${peerId} until ${new Date(record.expiry).toISOString()}`, {
148
+ peerId,
149
+ score,
150
+ expiry: record.expiry,
151
+ });
152
+ }
153
+
119
154
  decayAllScores(): void {
120
155
  const currentTime = this.dateProvider.now();
121
156
  for (const [peerId, lastUpdate] of this.lastUpdateTime.entries()) {
@@ -135,17 +170,58 @@ export class PeerScoring {
135
170
  }
136
171
  }
137
172
 
173
+ /**
174
+ * Removes bans whose window has elapsed. Expired bans are otherwise only pruned lazily when their
175
+ * peer's score is next queried, so a banned peer that disconnects and is never queried again would
176
+ * linger in the map. Called periodically (per heartbeat) to bound the ban map's size.
177
+ */
178
+ pruneExpiredBans(): void {
179
+ const now = this.dateProvider.now();
180
+ const expired = [...this.bannedPeers.entries()].filter(([, ban]) => ban.expiry <= now).map(([peerId]) => peerId);
181
+ for (const peerId of expired) {
182
+ this.bannedPeers.delete(peerId);
183
+ }
184
+ }
185
+
186
+ /** Resets all peer scores. Useful for benchmarks to prevent cross-case contamination. */
187
+ resetAllScores(): void {
188
+ this.scores.clear();
189
+ this.lastUpdateTime.clear();
190
+ this.bannedPeers.clear();
191
+ }
192
+
138
193
  removePeer(peerId: string): void {
139
194
  this.scores.delete(peerId);
140
195
  this.lastUpdateTime.delete(peerId);
141
196
  }
142
197
 
198
+ /**
199
+ * The single source of truth for whether a peer is banned. Returns the ban score while the ban is
200
+ * active, or undefined if the peer is not banned. A ban that has expired is lazily lifted before
201
+ * returning undefined, so callers never see a stale ban.
202
+ */
203
+ private getActiveBanScore(peerId: string): number | undefined {
204
+ const ban = this.bannedPeers.get(peerId);
205
+ if (ban === undefined) {
206
+ return undefined;
207
+ }
208
+ if (ban.expiry > this.dateProvider.now()) {
209
+ return ban.score;
210
+ }
211
+ // Ban expired: lift it so the peer can recover.
212
+ this.bannedPeers.delete(peerId);
213
+ return undefined;
214
+ }
215
+
143
216
  getScore(peerId: string): number {
144
- return this.scores.get(peerId) || 0;
217
+ // While a ban is active its ban score is returned regardless of how the live score has decayed,
218
+ // so the peer stays banned for the full duration.
219
+ return this.getActiveBanScore(peerId) ?? this.scores.get(peerId) ?? 0;
145
220
  }
146
221
 
147
222
  public getScoreState(peerId: string): PeerScoreState {
148
- // TODO(#11329): permanently store banned peers?
223
+ // A banned peer stays banned for the full ban duration regardless of score decay (see getScore /
224
+ // maybeBanPeer), rather than silently recovering once its decayed score is cleaned up.
149
225
  const score = this.getScore(peerId);
150
226
  if (score < MIN_SCORE_BEFORE_BAN) {
151
227
  return PeerScoreState.Banned;
@@ -159,7 +235,9 @@ export class PeerScoring {
159
235
  getStats(): { medianScore: number; healthyCount: number; disconnectCount: number; bannedCount: number } {
160
236
  const stateCounts = { healthy: 0, disconnect: 0, banned: 0 };
161
237
 
162
- for (const peerId of this.scores.keys()) {
238
+ // Include banned peers whose live score may have been decayed away but whose ban is still active.
239
+ const peerIds = new Set([...this.scores.keys(), ...this.bannedPeers.keys()]);
240
+ for (const peerId of peerIds) {
163
241
  const state = this.getScoreState(peerId);
164
242
  switch (state) {
165
243
  case PeerScoreState.Healthy:
@@ -14,9 +14,8 @@ Applied before the protocol handler runs.
14
14
  | STATUS | 5/s | 10/s | same |
15
15
  | AUTH | 5/s | 10/s | same |
16
16
  | GOODBYE | 5/s | 10/s | same |
17
- | BLOCK | 2/s | 5/s | same |
18
17
  | BLOCK_TXS | 10/s | 200/s | same |
19
- | TX | (see rate limits file) | (see rate limits file) | same |
18
+ | TX | 10/s | 200/s | same |
20
19
 
21
20
  - Per-peer limit exceeded: `HighToleranceError` penalty + `RATE_LIMIT_EXCEEDED` status. Penalty fires inside `RequestResponseRateLimiter.allow()`, not the stream handler.
22
21
  - Global limit exceeded: `RATE_LIMIT_EXCEEDED` status only (no peer penalty).
@@ -46,7 +45,6 @@ Per-protocol size limits checked via preamble before decompression.
46
45
  | Error Type | Severity |
47
46
  |------------|----------|
48
47
  | GOODBYE subprotocol errors | None |
49
- | `CollectiveReqRespTimeoutError` / `InvalidResponseError` | None |
50
48
  | `AbortError` / connection close / muxer closed | None |
51
49
  | `ECONNRESET` / `EPIPE` / `ECONNREFUSED` / `ERR_UNEXPECTED_EOF` | HighToleranceError |
52
50
  | `ERR_UNSUPPORTED_PROTOCOL` | HighToleranceError |
@@ -150,26 +148,6 @@ Protected peers (private/trusted/preferred) are always considered "authenticated
150
148
 
151
149
  ## Block Data Protocols
152
150
 
153
- ### BLOCK Protocol (`/aztec/req/block/1.0.0`)
154
-
155
- **Server side**:
156
-
157
- | Rule | Consequence | File |
158
- |------|-------------|------|
159
- | Request must parse as `Fr` | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block.ts` |
160
- | Block lookup throws | `INTERNAL_ERROR` status | same |
161
- | Block not found | SUCCESS + empty buffer (design choice; no `NOT_FOUND` status used) | same |
162
-
163
- **Requester side** (Snappy limit: 3 MB):
164
-
165
- | Rule | Consequence | File |
166
- |------|-------------|------|
167
- | Response block number must match requested | LowToleranceError; rejected | `libp2p_service.ts` (`validateRequestedBlock`) |
168
- | Local block must exist for hash verification | Rejected (no penalty) | same |
169
- | Response block hash must equal local block hash | MidToleranceError; rejected | same |
170
-
171
- **Limitation**: the local-block requirement means BLOCK req/resp is unusable for initial P2P-only sync (before L1 sync provides local copies for verification). A TODO in the code acknowledges this.
172
-
173
151
  ### BLOCK_TXS Protocol (`/aztec/req/block_txs/1.0.0`)
174
152
 
175
153
  **Server side**:
@@ -179,23 +157,10 @@ Protected peers (private/trusted/preferred) are always considered "authenticated
179
157
  | Request must parse as `BlockTxsRequest` (Fr + TxHashArray + BitVector) | `BADLY_FORMED_REQUEST` + LowToleranceError | `protocols/block_txs/block_txs_handler.ts` |
180
158
  | BitVector length: non-negative and <= `MAX_TXS_PER_BLOCK` (65536) | Deserialization throws -> `BADLY_FORMED_REQUEST` | `protocols/block_txs/bitvector.ts` |
181
159
  | Archive root not found and no explicit txHashes | `NOT_FOUND` status | handler |
182
- | Internal error during lookup | Unhandled exception -> stream abort (no `INTERNAL_ERROR` status, unlike BLOCK) | handler |
160
+ | Internal error during lookup | Unhandled exception -> stream abort (no `INTERNAL_ERROR` status) | handler |
183
161
 
184
162
  Conditional registration: BLOCK_TXS handler only registered when `config.disableTransactions` is false. Otherwise peers get `ERR_UNSUPPORTED_PROTOCOL`.
185
163
 
186
- **Requester side via `sendBatchRequest`** (Snappy limit: `max(N, 1) * 512 + 1` KB):
187
-
188
- | Rule | Consequence | File |
189
- |------|-------------|------|
190
- | Archive root must match request | MidToleranceError | `libp2p_service.ts` (`validateRequestedBlockTxs`) |
191
- | BitVector length must match request | MidToleranceError | same |
192
- | No duplicate tx hashes | MidToleranceError | same |
193
- | Tx count within bounds | MidToleranceError | same |
194
- | Local block proposal must exist for archive root | Rejected (no penalty) | same |
195
- | All tx hashes must be in proposal's tx list at allowed indices | LowToleranceError | same |
196
- | Txs in strictly increasing index order | LowToleranceError | same |
197
- | Each tx passes well-formedness (Metadata [4 fields], Size, Data, Proof) | LowToleranceError | same |
198
-
199
164
  **Requester side via `BatchTxRequester`** (separate validation path):
200
165
 
201
166
  | Rule | Consequence | File |
@@ -4,9 +4,10 @@ import { FifoMemoryQueue, type ISemaphore, Semaphore } from '@aztec/foundation/q
4
4
  import { sleep } from '@aztec/foundation/sleep';
5
5
  import { DateProvider } from '@aztec/foundation/timer';
6
6
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
7
- import { Tx, TxArray, TxHash } from '@aztec/stdlib/tx';
7
+ import { Tx, TxArray, TxHash, type TxValidator } from '@aztec/stdlib/tx';
8
8
 
9
9
  import type { PeerId } from '@libp2p/interface';
10
+ import { strict as assert } from 'assert';
10
11
 
11
12
  import type { IRequestTracker } from '../../tx_collection/request_tracker.js';
12
13
  import { ReqRespSubProtocol } from '.././interface.js';
@@ -21,7 +22,7 @@ import {
21
22
  import type { BatchTxRequesterLibP2PService, BatchTxRequesterOptions, ITxMetadataCollection } from './interface.js';
22
23
  import { MissingTxMetadataCollection } from './missing_txs.js';
23
24
  import { type IPeerCollection, PeerCollection } from './peer_collection.js';
24
- import { BatchRequestTxValidator, type IBatchRequestTxValidator } from './tx_validator.js';
25
+ import { createBatchRequestTxValidator } from './tx_validator.js';
25
26
 
26
27
  /*
27
28
  * Tries to fetch all missing transaction until deadline is hit.
@@ -51,7 +52,7 @@ export class BatchTxRequester {
51
52
  private readonly txsMetadata: ITxMetadataCollection;
52
53
  private readonly smartRequesterSemaphore: ISemaphore;
53
54
  private readonly txQueue: FifoMemoryQueue<Tx>;
54
- private readonly txValidator: IBatchRequestTxValidator;
55
+ private readonly txValidator: TxValidator;
55
56
  private readonly smartParallelWorkerCount: number;
56
57
  private readonly dumbParallelWorkerCount: number;
57
58
  private readonly txBatchSize: number;
@@ -78,7 +79,7 @@ export class BatchTxRequester {
78
79
  this.opts.dumbParallelWorkerCount ?? DEFAULT_BATCH_TX_REQUESTER_DUMB_PARALLEL_WORKER_COUNT;
79
80
  this.txBatchSize = this.opts.txBatchSize ?? DEFAULT_BATCH_TX_REQUESTER_TX_BATCH_SIZE;
80
81
  this.txQueue = new FifoMemoryQueue(this.logger);
81
- this.txValidator = this.opts.txValidator ?? new BatchRequestTxValidator(this.p2pService.txValidatorConfig);
82
+ this.txValidator = this.opts.txValidator ?? createBatchRequestTxValidator(this.p2pService.txValidatorConfig);
82
83
 
83
84
  if (this.opts.peerCollection) {
84
85
  this.peers = this.opts.peerCollection;
@@ -97,7 +98,7 @@ export class BatchTxRequester {
97
98
  }
98
99
 
99
100
  /*
100
- * Fetches all missing transactions and yields them one by one
101
+ * Fetches all missing transactions and yields them one by one
101
102
  * */
102
103
  public async *run(): AsyncGenerator<Tx, Tx | undefined, unknown> {
103
104
  try {
@@ -428,6 +429,15 @@ export class BatchTxRequester {
428
429
  }
429
430
 
430
431
  const blockResponse = BlockTxsResponse.fromBuffer(response.data);
432
+
433
+ // Validate response. Peers will be penalised by the validator if they send invalid response.
434
+ const isValid = await this.p2pService.validateRequestedBlockTxsConsistency(request, blockResponse, peerId);
435
+ if (!isValid) {
436
+ this.logger.debug(`Peer ${peerId.toString()} sent invalid response`);
437
+ this.handleFailResponseFromPeer(peerId, ReqRespStatus.INTERNAL_ERROR);
438
+ return;
439
+ }
440
+
431
441
  await this.handleSuccessResponseFromPeer(peerId, blockResponse);
432
442
  } catch (err: any) {
433
443
  this.logger.error(`Failed to get valid response from peer ${peerId.toString()}: ${err.message}`, {
@@ -445,27 +455,24 @@ export class BatchTxRequester {
445
455
  * Handles failed response form the peer
446
456
  * There are 3 scenarios
447
457
  * - RATE_LIMIT_EXCEEDED: We mark this and don't query this peer again for some_time
458
+ * - INTERNAL_ERROR: We use this to cover cases where the request-response consistency validation fails.
448
459
  * - FAILURE and UNKNOWN: We penalise this, if peer has been penalised this way N times they are not queried again
449
460
  * this implies we will query these peers couple of more times and give them a chance to "redeem" themselves before completely ignoring them
450
461
  */
451
462
  private handleFailResponseFromPeer(peerId: PeerId, responseStatus: ReqRespStatus) {
452
- if (responseStatus === ReqRespStatus.FAILURE || responseStatus === ReqRespStatus.UNKNOWN) {
453
- this.peers.penalisePeer(peerId, PeerErrorSeverity.HighToleranceError);
454
- this.peers.markPeerDumb(peerId);
455
- this.txsMetadata.clearPeerData(peerId);
456
- return;
457
- }
458
-
459
- // NOT_FOUND means the peer pruned its block proposal — it can no longer serve
460
- // index-based requests, but this is a legitimate state so we don't penalize.
461
- if (responseStatus === ReqRespStatus.NOT_FOUND) {
462
- this.peers.markPeerDumb(peerId);
463
- this.txsMetadata.clearPeerData(peerId);
464
- return;
465
- }
466
-
467
- if (responseStatus === ReqRespStatus.RATE_LIMIT_EXCEEDED) {
468
- this.peers.markPeerRateLimitExceeded(peerId);
463
+ switch (responseStatus) {
464
+ case ReqRespStatus.RATE_LIMIT_EXCEEDED:
465
+ this.peers.markPeerRateLimitExceeded(peerId);
466
+ return;
467
+ case ReqRespStatus.INTERNAL_ERROR:
468
+ this.peers.markPeerDumb(peerId);
469
+ this.txsMetadata.clearPeerData(peerId);
470
+ return;
471
+ default: // includes FAILURE, UNKNOWN
472
+ this.peers.penalisePeer(peerId, PeerErrorSeverity.HighToleranceError);
473
+ this.peers.markPeerDumb(peerId);
474
+ this.txsMetadata.clearPeerData(peerId);
475
+ return;
469
476
  }
470
477
  }
471
478
 
@@ -485,7 +492,7 @@ export class BatchTxRequester {
485
492
  * Handles received txs.
486
493
  * Transactions are validated and then put on async queue
487
494
  * to be yielded by main running loop
488
- * */
495
+ */
489
496
  private async handleReceivedTxs(peerId: PeerId, txs: TxArray) {
490
497
  const newTxs = txs.filter(tx => !this.txsMetadata.alreadyFetched(tx.txHash));
491
498
 
@@ -493,12 +500,12 @@ export class BatchTxRequester {
493
500
  return;
494
501
  }
495
502
 
496
- //TODO: this validation can be slow, maybe spawn worker just for validation
503
+ // TODO: this validation can be slow, maybe spawn worker just for validation
497
504
  // We could use the async queue for communication.
498
505
  const validationResults = await Promise.allSettled(
499
506
  newTxs.map(async tx => ({
500
507
  tx,
501
- isValid: (await this.txValidator.validateRequestedTx(tx)).result === 'valid',
508
+ isValid: (await this.txValidator.validateTx(tx)).result === 'valid',
502
509
  })),
503
510
  );
504
511
 
@@ -553,9 +560,10 @@ export class BatchTxRequester {
553
560
  return;
554
561
  }
555
562
 
556
- const hasArchiveRootMismatch = this.blockTxsSource.archive.toString() !== response.archiveRoot.toString();
557
- if (hasArchiveRootMismatch) {
558
- this.handleArchiveRootMismatch(peerId, response);
563
+ // If the peer doesn't have the block, we mark them as dumb.
564
+ if (!response.peerHasBlock()) {
565
+ this.peers.markPeerDumb(peerId);
566
+ this.txsMetadata.clearPeerData(peerId);
559
567
  return;
560
568
  }
561
569
 
@@ -573,21 +581,6 @@ export class BatchTxRequester {
573
581
  this.smartRequesterSemaphore.release();
574
582
  }
575
583
 
576
- /**
577
- * Handles an archive root mismatch between local state and peer response.
578
- *
579
- * - Response archive is Fr.ZERO (peer pruned proposal, legitimate): marks peer dumb.
580
- * - Non-zero archive mismatch (malicious response): penalises + marks dumb.
581
- */
582
- private handleArchiveRootMismatch(peerId: PeerId, response: BlockTxsResponse): void {
583
- if (!response.archiveRoot.isZero()) {
584
- this.peers.penalisePeer(peerId, PeerErrorSeverity.LowToleranceError);
585
- }
586
-
587
- this.peers.markPeerDumb(peerId);
588
- this.txsMetadata.clearPeerData(peerId);
589
- }
590
-
591
584
  private peerHasSomeTxsWeAreMissing(_peerId: PeerId, response: BlockTxsResponse): boolean {
592
585
  if (response.txIndices.isEmpty()) {
593
586
  return false;
@@ -603,15 +596,9 @@ export class BatchTxRequester {
603
596
  }
604
597
 
605
598
  private extractHashesPeerHasFromResponse(response: BlockTxsResponse): Array<TxHash> {
606
- const hashes: TxHash[] = [];
607
- const indicesOfHashesPeerHas = new Set(response.txIndices.getTrueIndices());
608
- this.blockTxsSource.txHashes.forEach((hash, idx) => {
609
- if (indicesOfHashesPeerHas.has(idx)) {
610
- hashes.push(hash);
611
- }
612
- });
613
-
614
- return hashes;
599
+ // Should already have been validated, but just in case.
600
+ assert(response.txIndices.getLength() === this.blockTxsSource.txHashes.length);
601
+ return response.txIndices.getTrueIndices().map(idx => this.blockTxsSource.txHashes[idx]);
615
602
  }
616
603
 
617
604
  /*
@@ -1,13 +1,14 @@
1
1
  import type { ISemaphore } from '@aztec/foundation/queue';
2
2
  import type { PeerErrorSeverity } from '@aztec/stdlib/p2p';
3
- import type { Tx, TxHash } from '@aztec/stdlib/tx';
3
+ import type { Tx, TxHash, TxValidator } from '@aztec/stdlib/tx';
4
4
 
5
5
  import type { PeerId } from '@libp2p/interface';
6
6
 
7
7
  import type { ConnectionSampler } from '../connection-sampler/connection_sampler.js';
8
+ import type { BlockTxsRequest, BlockTxsResponse } from '../index.js';
8
9
  import type { ReqRespInterface } from '../interface.js';
9
10
  import type { IPeerCollection } from './peer_collection.js';
10
- import type { BatchRequestTxValidatorConfig, IBatchRequestTxValidator } from './tx_validator.js';
11
+ import type { BatchRequestTxValidatorConfig } from './tx_validator.js';
11
12
 
12
13
  export interface IPeerPenalizer {
13
14
  penalizePeer(peerId: PeerId, penalty: PeerErrorSeverity): void;
@@ -32,13 +33,19 @@ export interface ITxMetadataCollection {
32
33
  */
33
34
  export interface BatchTxRequesterLibP2PService {
34
35
  /** ReqResp interface for sending requests to peers */
35
- reqResp: Pick<ReqRespInterface, 'sendBatchRequest' | 'sendRequestToPeer'>;
36
+ reqResp: Pick<ReqRespInterface, 'sendRequestToPeer'>;
36
37
  /** Connection sampler for getting peer lists */
37
38
  connectionSampler: Pick<ConnectionSampler, 'getPeerListSortedByConnectionCountAsc'>;
38
39
  /** Configuration needed for transaction validation */
39
40
  txValidatorConfig: BatchRequestTxValidatorConfig;
40
41
  /** Peer scoring for penalizing peers */
41
42
  peerScoring: IPeerPenalizer;
43
+ /** Validate the requested block transactions request-response consistency */
44
+ validateRequestedBlockTxsConsistency: (
45
+ request: BlockTxsRequest,
46
+ response: BlockTxsResponse,
47
+ peerId: PeerId,
48
+ ) => Promise<boolean>;
42
49
  }
43
50
 
44
51
  export interface BatchTxRequesterOptions {
@@ -50,5 +57,5 @@ export interface BatchTxRequesterOptions {
50
57
  semaphore?: ISemaphore;
51
58
  peerCollection?: IPeerCollection;
52
59
  /** Optional tx validator for testing - if not provided, one is created from p2pService.txValidatorConfig */
53
- txValidator?: IBatchRequestTxValidator;
60
+ txValidator?: TxValidator;
54
61
  }
@@ -1,37 +1,24 @@
1
1
  import type { ClientProtocolCircuitVerifier } from '@aztec/stdlib/interfaces/server';
2
- import { Tx, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
2
+ import type { TxValidator } from '@aztec/stdlib/tx';
3
3
 
4
- import { createTxValidatorForReqResponseReceivedTxs } from '../../../msg_validators/index.js';
4
+ import { createTxValidatorForOnDemandReceivedTxs } from '../../../msg_validators/index.js';
5
+ import type { TxValidationCache } from '../../../msg_validators/tx_validator/tx_validation_cache.js';
5
6
 
6
7
  export interface BatchRequestTxValidatorConfig {
7
8
  l1ChainId: number;
8
9
  rollupVersion: number;
9
10
  proofVerifier: ClientProtocolCircuitVerifier;
11
+ txValidationCache?: TxValidationCache;
10
12
  }
11
13
 
12
- export interface IBatchRequestTxValidator {
13
- validateRequestedTx(tx: Tx): Promise<TxValidationResult>;
14
- validateRequestedTxs(txs: Tx[]): Promise<TxValidationResult[]>;
15
- }
16
-
17
- export class BatchRequestTxValidator implements IBatchRequestTxValidator {
18
- readonly txValidator: TxValidator;
19
- constructor(private readonly config: BatchRequestTxValidatorConfig) {
20
- this.txValidator = BatchRequestTxValidator.createRequestedTxValidator(this.config);
21
- }
22
-
23
- public async validateRequestedTx(tx: Tx): Promise<TxValidationResult> {
24
- return await this.txValidator.validateTx(tx);
25
- }
26
-
27
- public async validateRequestedTxs(txs: Tx[]): Promise<TxValidationResult[]> {
28
- return await Promise.all(txs.map(tx => this.validateRequestedTx(tx)));
29
- }
30
-
31
- static createRequestedTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
32
- return createTxValidatorForReqResponseReceivedTxs(config.proofVerifier, {
14
+ export function createBatchRequestTxValidator(config: BatchRequestTxValidatorConfig): TxValidator {
15
+ return createTxValidatorForOnDemandReceivedTxs(
16
+ config.proofVerifier,
17
+ {
33
18
  l1ChainId: config.l1ChainId,
34
19
  rollupVersion: config.rollupVersion,
35
- });
36
- }
20
+ },
21
+ /*bindings=*/ undefined,
22
+ config.txValidationCache,
23
+ );
37
24
  }
@@ -1,10 +1,27 @@
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
5
5
  export const DEFAULT_REQRESP_DIAL_TIMEOUT_MS = 5_000;
6
6
  export const DEFAULT_OPTIMISTIC_NEGOTIATION = false;
7
7
 
8
+ /**
9
+ * Max size of a yamux frame, header included. This is the library default, pinned explicitly when configuring the
10
+ * muxer in the libp2p service so a dependency upgrade cannot silently change it.
11
+ */
12
+ export const YAMUX_MAX_MESSAGE_SIZE_BYTES = 64 * 1024;
13
+
14
+ /** Size of a yamux data frame header. */
15
+ const YAMUX_HEADER_LENGTH_BYTES = 12;
16
+
17
+ /**
18
+ * Max size of a reqresp request payload. A request must fit in a single muxer frame: the responder never reassembles
19
+ * a request from multiple chunks (see `ReqResp.processStream`), and yamux splits writes larger than one frame into
20
+ * multiple frames, each of which arrives as a separate chunk. mplex only splits at 1 MiB, so yamux is the binding
21
+ * constraint.
22
+ */
23
+ export const MAX_REQRESP_REQUEST_SIZE_BYTES = YAMUX_MAX_MESSAGE_SIZE_BYTES - YAMUX_HEADER_LENGTH_BYTES;
24
+
8
25
  // For use in tests.
9
26
  export const DEFAULT_P2P_REQRESP_CONFIG: P2PReqRespConfig = {
10
27
  overallRequestTimeoutMs: DEFAULT_OVERALL_REQUEST_TIMEOUT_MS,
@@ -27,7 +44,7 @@ export interface P2PReqRespConfig {
27
44
  dialTimeoutMs: number;
28
45
  }
29
46
 
30
- export const p2pReqRespConfigMappings: Record<keyof P2PReqRespConfig, ConfigMapping> = {
47
+ export const p2pReqRespConfigMappings: ConfigMappingsType<P2PReqRespConfig> = {
31
48
  overallRequestTimeoutMs: {
32
49
  env: 'P2P_REQRESP_OVERALL_REQUEST_TIMEOUT_MS',
33
50
  description: 'The overall timeout for a request response operation.',