@aztec/p2p 4.0.0-nightly.20250907 → 4.0.0-nightly.20260107

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 (334) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +14 -4
  4. package/dest/client/factory.d.ts +3 -2
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +9 -5
  7. package/dest/client/index.d.ts +1 -1
  8. package/dest/client/interface.d.ts +8 -6
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +12 -35
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +457 -61
  13. package/dest/config.d.ts +67 -61
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +28 -15
  16. package/dest/enr/generate-enr.d.ts +2 -2
  17. package/dest/enr/generate-enr.d.ts.map +1 -1
  18. package/dest/enr/generate-enr.js +1 -1
  19. package/dest/enr/index.d.ts +1 -1
  20. package/dest/errors/attestation-pool.error.d.ts +7 -0
  21. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  22. package/dest/errors/attestation-pool.error.js +12 -0
  23. package/dest/errors/reqresp.error.d.ts +1 -1
  24. package/dest/errors/reqresp.error.d.ts.map +1 -1
  25. package/dest/index.d.ts +1 -1
  26. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +43 -6
  27. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  28. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  29. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +72 -46
  31. package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
  32. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +15 -6
  33. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  34. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +73 -18
  35. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +13 -6
  36. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  37. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +69 -11
  38. package/dest/mem_pools/attestation_pool/mocks.d.ts +226 -5
  39. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  40. package/dest/mem_pools/attestation_pool/mocks.js +9 -7
  41. package/dest/mem_pools/index.d.ts +1 -1
  42. package/dest/mem_pools/instrumentation.d.ts +9 -1
  43. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  44. package/dest/mem_pools/instrumentation.js +38 -2
  45. package/dest/mem_pools/interface.d.ts +3 -4
  46. package/dest/mem_pools/interface.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +39 -58
  48. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  49. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +314 -317
  50. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +18 -0
  51. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
  52. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +56 -0
  53. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +83 -0
  54. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
  55. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +5 -0
  56. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +15 -0
  57. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +1 -0
  58. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +88 -0
  59. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
  60. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  61. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
  62. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
  63. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  64. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +76 -0
  65. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
  66. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  67. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
  68. package/dest/mem_pools/tx_pool/index.d.ts +1 -2
  69. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
  70. package/dest/mem_pools/tx_pool/index.js +0 -1
  71. package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
  72. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  73. package/dest/mem_pools/tx_pool/priority.js +6 -1
  74. package/dest/mem_pools/tx_pool/tx_pool.d.ts +28 -9
  75. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  76. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  77. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  78. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +155 -25
  79. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -2
  80. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  81. package/dest/msg_validators/attestation_validator/attestation_validator.js +32 -5
  82. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  83. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  84. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +67 -0
  85. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  86. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  87. package/dest/msg_validators/attestation_validator/index.js +1 -0
  88. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +5 -2
  89. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
  90. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +44 -12
  91. package/dest/msg_validators/block_proposal_validator/index.d.ts +1 -1
  92. package/dest/msg_validators/index.d.ts +1 -1
  93. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
  94. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  96. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  97. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  98. package/dest/msg_validators/tx_validator/archive_cache.d.ts +2 -2
  99. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  100. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +2 -2
  101. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  102. package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
  103. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  104. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  105. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +1 -1
  106. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  107. package/dest/msg_validators/tx_validator/double_spend_validator.js +1 -1
  108. package/dest/msg_validators/tx_validator/factory.d.ts +4 -3
  109. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  110. package/dest/msg_validators/tx_validator/factory.js +11 -5
  111. package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
  112. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  113. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  114. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  115. package/dest/msg_validators/tx_validator/index.js +1 -0
  116. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -6
  117. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  118. package/dest/msg_validators/tx_validator/metadata_validator.js +6 -24
  119. package/dest/msg_validators/tx_validator/phases_validator.d.ts +1 -1
  120. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  121. package/dest/msg_validators/tx_validator/phases_validator.js +3 -1
  122. package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
  123. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
  124. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +13 -0
  125. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  126. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  127. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +1 -1
  128. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  129. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
  130. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  131. package/dest/services/data_store.d.ts +1 -1
  132. package/dest/services/data_store.d.ts.map +1 -1
  133. package/dest/services/discv5/discV5_service.d.ts +3 -3
  134. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  135. package/dest/services/discv5/discV5_service.js +2 -2
  136. package/dest/services/dummy_service.d.ts +2 -2
  137. package/dest/services/dummy_service.d.ts.map +1 -1
  138. package/dest/services/encoding.d.ts +25 -4
  139. package/dest/services/encoding.d.ts.map +1 -1
  140. package/dest/services/encoding.js +74 -6
  141. package/dest/services/gossipsub/scoring.d.ts +1 -1
  142. package/dest/services/index.d.ts +1 -1
  143. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  144. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  145. package/dest/services/libp2p/instrumentation.js +9 -2
  146. package/dest/services/libp2p/libp2p_service.d.ts +32 -72
  147. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  148. package/dest/services/libp2p/libp2p_service.js +796 -171
  149. package/dest/services/peer-manager/interface.d.ts +1 -1
  150. package/dest/services/peer-manager/metrics.d.ts +8 -1
  151. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  152. package/dest/services/peer-manager/metrics.js +28 -0
  153. package/dest/services/peer-manager/peer_manager.d.ts +1 -32
  154. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  155. package/dest/services/peer-manager/peer_manager.js +412 -21
  156. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  157. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  158. package/dest/services/peer-manager/peer_scoring.js +40 -2
  159. package/dest/services/reqresp/config.d.ts +1 -1
  160. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
  161. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  162. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -4
  163. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  164. package/dest/services/reqresp/index.d.ts +1 -1
  165. package/dest/services/reqresp/interface.d.ts +2 -11
  166. package/dest/services/reqresp/interface.d.ts.map +1 -1
  167. package/dest/services/reqresp/interface.js +1 -18
  168. package/dest/services/reqresp/metrics.d.ts +1 -1
  169. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  170. package/dest/services/reqresp/protocols/auth.d.ts +2 -2
  171. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  172. package/dest/services/reqresp/protocols/auth.js +2 -2
  173. package/dest/services/reqresp/protocols/block.d.ts +1 -1
  174. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  175. package/dest/services/reqresp/protocols/block.js +3 -2
  176. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
  177. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  178. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  179. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +4 -6
  180. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  181. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +1 -1
  182. package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
  183. package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
  184. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  185. package/dest/services/reqresp/protocols/index.d.ts +1 -1
  186. package/dest/services/reqresp/protocols/ping.d.ts +1 -1
  187. package/dest/services/reqresp/protocols/status.d.ts +6 -5
  188. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  189. package/dest/services/reqresp/protocols/status.js +4 -3
  190. package/dest/services/reqresp/protocols/tx.d.ts +2 -3
  191. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  192. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  193. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
  194. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  195. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  196. package/dest/services/reqresp/reqresp.d.ts +1 -41
  197. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  198. package/dest/services/reqresp/reqresp.js +416 -34
  199. package/dest/services/reqresp/status.d.ts +2 -2
  200. package/dest/services/reqresp/status.d.ts.map +1 -1
  201. package/dest/services/service.d.ts +2 -2
  202. package/dest/services/service.d.ts.map +1 -1
  203. package/dest/services/tx_collection/config.d.ts +1 -1
  204. package/dest/services/tx_collection/config.js +1 -1
  205. package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -9
  206. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  207. package/dest/services/tx_collection/fast_tx_collection.js +6 -1
  208. package/dest/services/tx_collection/index.d.ts +1 -1
  209. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  210. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  211. package/dest/services/tx_collection/slow_tx_collection.d.ts +6 -7
  212. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  213. package/dest/services/tx_collection/slow_tx_collection.js +2 -1
  214. package/dest/services/tx_collection/tx_collection.d.ts +12 -11
  215. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  216. package/dest/services/tx_collection/tx_collection.js +3 -2
  217. package/dest/services/tx_collection/tx_collection_sink.d.ts +3 -3
  218. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  219. package/dest/services/tx_collection/tx_collection_sink.js +34 -4
  220. package/dest/services/tx_collection/tx_source.d.ts +1 -1
  221. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  222. package/dest/services/tx_collection/tx_source.js +2 -2
  223. package/dest/services/tx_provider.d.ts +6 -4
  224. package/dest/services/tx_provider.d.ts.map +1 -1
  225. package/dest/services/tx_provider.js +19 -6
  226. package/dest/services/tx_provider_instrumentation.d.ts +5 -2
  227. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  228. package/dest/services/tx_provider_instrumentation.js +14 -1
  229. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  230. package/dest/test-helpers/get-ports.d.ts +1 -1
  231. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  232. package/dest/test-helpers/index.d.ts +1 -1
  233. package/dest/test-helpers/make-enrs.d.ts +1 -1
  234. package/dest/test-helpers/make-enrs.js +1 -1
  235. package/dest/test-helpers/make-test-p2p-clients.d.ts +2 -2
  236. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  237. package/dest/test-helpers/mock-pubsub.d.ts +4 -4
  238. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  239. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  240. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  241. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  242. package/dest/test-helpers/reqresp-nodes.d.ts +3 -3
  243. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  244. package/dest/test-helpers/reqresp-nodes.js +4 -3
  245. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  246. package/dest/testbench/p2p_client_testbench_worker.js +17 -9
  247. package/dest/testbench/parse_log_file.d.ts +1 -1
  248. package/dest/testbench/testbench.d.ts +1 -1
  249. package/dest/testbench/testbench.js +2 -2
  250. package/dest/testbench/worker_client_manager.d.ts +1 -1
  251. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  252. package/dest/types/index.d.ts +1 -1
  253. package/dest/util.d.ts +2 -1
  254. package/dest/util.d.ts.map +1 -1
  255. package/dest/util.js +11 -2
  256. package/dest/versioning.d.ts +2 -2
  257. package/dest/versioning.d.ts.map +1 -1
  258. package/dest/versioning.js +2 -2
  259. package/package.json +21 -21
  260. package/src/bootstrap/bootstrap.ts +15 -4
  261. package/src/client/factory.ts +21 -12
  262. package/src/client/interface.ts +8 -5
  263. package/src/client/p2p_client.ts +97 -88
  264. package/src/config.ts +42 -21
  265. package/src/enr/generate-enr.ts +1 -1
  266. package/src/errors/attestation-pool.error.ts +13 -0
  267. package/src/mem_pools/attestation_pool/attestation_pool.ts +46 -5
  268. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +89 -48
  269. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +107 -24
  270. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +98 -19
  271. package/src/mem_pools/attestation_pool/mocks.ts +11 -8
  272. package/src/mem_pools/instrumentation.ts +46 -0
  273. package/src/mem_pools/interface.ts +2 -4
  274. package/src/mem_pools/tx_pool/README.md +255 -0
  275. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +368 -360
  276. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +71 -0
  277. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +93 -0
  278. package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +108 -0
  279. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  280. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +91 -0
  281. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  282. package/src/mem_pools/tx_pool/index.ts +0 -1
  283. package/src/mem_pools/tx_pool/priority.ts +8 -1
  284. package/src/mem_pools/tx_pool/tx_pool.ts +28 -8
  285. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +131 -18
  286. package/src/msg_validators/attestation_validator/attestation_validator.ts +41 -6
  287. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +91 -0
  288. package/src/msg_validators/attestation_validator/index.ts +1 -0
  289. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +53 -12
  290. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  291. package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
  292. package/src/msg_validators/tx_validator/double_spend_validator.ts +1 -1
  293. package/src/msg_validators/tx_validator/factory.ts +13 -6
  294. package/src/msg_validators/tx_validator/index.ts +1 -0
  295. package/src/msg_validators/tx_validator/metadata_validator.ts +8 -42
  296. package/src/msg_validators/tx_validator/phases_validator.ts +3 -1
  297. package/src/msg_validators/tx_validator/test_utils.ts +1 -1
  298. package/src/msg_validators/tx_validator/timestamp_validator.ts +47 -0
  299. package/src/services/discv5/discV5_service.ts +2 -2
  300. package/src/services/dummy_service.ts +1 -1
  301. package/src/services/encoding.ts +81 -6
  302. package/src/services/libp2p/instrumentation.ts +10 -1
  303. package/src/services/libp2p/libp2p_service.ts +430 -165
  304. package/src/services/peer-manager/metrics.ts +32 -0
  305. package/src/services/peer-manager/peer_manager.ts +24 -14
  306. package/src/services/peer-manager/peer_scoring.ts +46 -3
  307. package/src/services/reqresp/interface.ts +1 -22
  308. package/src/services/reqresp/protocols/auth.ts +2 -2
  309. package/src/services/reqresp/protocols/block.ts +3 -2
  310. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +1 -1
  311. package/src/services/reqresp/protocols/status.ts +9 -8
  312. package/src/services/reqresp/protocols/tx.ts +1 -2
  313. package/src/services/reqresp/reqresp.ts +15 -11
  314. package/src/services/service.ts +1 -1
  315. package/src/services/tx_collection/config.ts +1 -1
  316. package/src/services/tx_collection/fast_tx_collection.ts +8 -5
  317. package/src/services/tx_collection/slow_tx_collection.ts +7 -6
  318. package/src/services/tx_collection/tx_collection.ts +12 -10
  319. package/src/services/tx_collection/tx_collection_sink.ts +34 -3
  320. package/src/services/tx_collection/tx_source.ts +2 -2
  321. package/src/services/tx_provider.ts +26 -9
  322. package/src/services/tx_provider_instrumentation.ts +19 -2
  323. package/src/test-helpers/make-enrs.ts +1 -1
  324. package/src/test-helpers/mock-pubsub.ts +1 -1
  325. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  326. package/src/test-helpers/reqresp-nodes.ts +4 -3
  327. package/src/testbench/p2p_client_testbench_worker.ts +14 -6
  328. package/src/testbench/testbench.ts +2 -2
  329. package/src/util.ts +12 -2
  330. package/src/versioning.ts +3 -3
  331. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -68
  332. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  333. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -160
  334. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -199
@@ -1,12 +1,14 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
- import { randomInt } from '@aztec/foundation/crypto';
2
+ import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { randomInt } from '@aztec/foundation/crypto/random';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
5
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
4
- import { SerialQueue } from '@aztec/foundation/queue';
5
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
6
7
  import { Timer } from '@aztec/foundation/timer';
7
8
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
8
- import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
9
- import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
9
+ import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
10
+ import { protocolContractsHash } from '@aztec/protocol-contracts';
11
+ import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
10
12
  import type { ContractDataSource } from '@aztec/stdlib/contract';
11
13
  import { GasFees } from '@aztec/stdlib/gas';
12
14
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
@@ -23,12 +25,11 @@ import {
23
25
  metricsTopicStrToLabels,
24
26
  } from '@aztec/stdlib/p2p';
25
27
  import { MerkleTreeId } from '@aztec/stdlib/trees';
26
- import { Tx, type TxHash, type TxValidationResult } from '@aztec/stdlib/tx';
28
+ import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
27
29
  import type { UInt64 } from '@aztec/stdlib/types';
28
30
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
29
31
  import { Attributes, OtelMetricsAdapter, type TelemetryClient, WithTracer, trackSpan } from '@aztec/telemetry-client';
30
32
 
31
- import { ENR } from '@chainsafe/enr';
32
33
  import {
33
34
  type GossipSub,
34
35
  type GossipSubComponents,
@@ -43,18 +44,29 @@ import { bootstrap } from '@libp2p/bootstrap';
43
44
  import { identify } from '@libp2p/identify';
44
45
  import { type Message, type MultiaddrConnection, type PeerId, TopicValidatorResult } from '@libp2p/interface';
45
46
  import type { ConnectionManager } from '@libp2p/interface-internal';
46
- import '@libp2p/kad-dht';
47
47
  import { mplex } from '@libp2p/mplex';
48
48
  import { tcp } from '@libp2p/tcp';
49
+ import { ENR } from '@nethermindeth/enr';
49
50
  import { createLibp2p } from 'libp2p';
50
51
 
51
52
  import type { P2PConfig } from '../../config.js';
53
+ import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
52
54
  import type { MemPools } from '../../mem_pools/interface.js';
53
- import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
55
+ import {
56
+ AttestationValidator,
57
+ BlockProposalValidator,
58
+ FishermanAttestationValidator,
59
+ } from '../../msg_validators/index.js';
54
60
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
55
61
  import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
56
62
  import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
57
- import { DoubleSpendTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
63
+ import {
64
+ AggregateTxValidator,
65
+ DataTxValidator,
66
+ DoubleSpendTxValidator,
67
+ MetadataTxValidator,
68
+ TxProofValidator,
69
+ } from '../../msg_validators/tx_validator/index.js';
58
70
  import { GossipSubEvent } from '../../types/index.js';
59
71
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
60
72
  import { getVersions } from '../../versioning.js';
@@ -80,6 +92,8 @@ import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs
80
92
  import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
81
93
  import {
82
94
  AuthRequest,
95
+ BlockTxsRequest,
96
+ BlockTxsResponse,
83
97
  StatusMessage,
84
98
  pingHandler,
85
99
  reqRespBlockHandler,
@@ -98,11 +112,15 @@ interface ValidationResult {
98
112
 
99
113
  type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
100
114
 
115
+ // REFACTOR: Unify with the type above
116
+ type ReceivedMessageValidationResult<T> =
117
+ | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject> }
118
+ | { obj?: undefined; result: TopicValidatorResult.Reject };
119
+
101
120
  /**
102
121
  * Lib P2P implementation of the P2PService interface.
103
122
  */
104
123
  export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
105
- private jobQueue: SerialQueue = new SerialQueue();
106
124
  private discoveryRunningPromise?: RunningPromise;
107
125
  private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
108
126
 
@@ -113,7 +131,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
113
131
  private protocolVersion = '';
114
132
  private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
115
133
 
116
- private feesCache: { blockNumber: number; gasFees: GasFees } | undefined;
134
+ private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
117
135
 
118
136
  /**
119
137
  * Callback for when a block is received from a peer.
@@ -126,6 +144,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
126
144
 
127
145
  private instrumentation: P2PInstrumentation;
128
146
 
147
+ protected logger: Logger;
148
+
129
149
  constructor(
130
150
  private clientType: T,
131
151
  private config: P2PConfig,
@@ -133,16 +153,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
133
153
  private peerDiscoveryService: PeerDiscoveryService,
134
154
  private reqresp: ReqRespInterface,
135
155
  private peerManager: PeerManagerInterface,
136
- protected mempools: MemPools<T>,
156
+ protected mempools: MemPools,
137
157
  private archiver: L2BlockSource & ContractDataSource,
138
158
  private epochCache: EpochCacheInterface,
139
159
  private proofVerifier: ClientProtocolCircuitVerifier,
140
160
  private worldStateSynchronizer: WorldStateSynchronizer,
141
161
  telemetry: TelemetryClient,
142
- protected logger = createLogger('p2p:libp2p_service'),
162
+ logger: Logger = createLogger('p2p:libp2p_service'),
143
163
  ) {
144
164
  super(telemetry, 'LibP2PService');
145
165
 
166
+ // Create child logger with fisherman prefix if in fisherman mode
167
+ this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
168
+
146
169
  this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
147
170
 
148
171
  this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
@@ -160,15 +183,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
160
183
  this.protocolVersion,
161
184
  );
162
185
 
163
- this.attestationValidator = new AttestationValidator(epochCache);
164
- this.blockProposalValidator = new BlockProposalValidator(epochCache);
186
+ // Use FishermanAttestationValidator in fisherman mode to validate attestation payloads against proposals
187
+ this.attestationValidator = config.fishermanMode
188
+ ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
189
+ : new AttestationValidator(epochCache);
190
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
165
191
 
166
192
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
167
193
 
168
194
  this.blockReceivedCallback = async (block: BlockProposal): Promise<BlockAttestation[] | undefined> => {
169
195
  this.logger.debug(
170
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`,
171
- { p2pMessageIdentifier: await block.p2pMessageIdentifier() },
196
+ `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
197
+ { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
172
198
  );
173
199
  return undefined;
174
200
  };
@@ -189,7 +215,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
189
215
  config: P2PConfig,
190
216
  peerId: PeerId,
191
217
  deps: {
192
- mempools: MemPools<T>;
218
+ mempools: MemPools;
193
219
  l2BlockSource: L2BlockSource & ContractDataSource;
194
220
  epochCache: EpochCacheInterface;
195
221
  proofVerifier: ClientProtocolCircuitVerifier;
@@ -273,7 +299,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
273
299
  // The connection attempts to the node on TCP layer are not necessarily valid Aztec peers so we want to have a bit of leeway here
274
300
  // If we hit the limit, the connection will be temporarily accepted and immediately dropped.
275
301
  // Docs: https://nodejs.org/api/net.html#servermaxconnections
276
- maxConnections: Math.ceil(maxPeerCount * 1.5),
302
+ maxConnections: maxPeerCount * 2,
277
303
  // socket option: the maximum length of the queue of pending connections
278
304
  // https://nodejs.org/dist/latest-v22.x/docs/api/net.html#serverlisten
279
305
  // it's not safe if we increase this number
@@ -284,7 +310,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
284
310
  // In case closeAbove is reached, the server stops listening altogether
285
311
  // It's important that there is enough difference between closeAbove and listenAbove,
286
312
  // otherwise the server.listener will flap between being closed and open potentially degrading perf even more
287
- closeAbove: maxPeerCount * 2,
313
+ closeAbove: maxPeerCount * 3,
288
314
  listenBelow: Math.floor(maxPeerCount * 0.9),
289
315
  },
290
316
  }),
@@ -294,8 +320,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
294
320
  streamMuxers: [yamux(), mplex()],
295
321
  connectionEncryption: [noise()],
296
322
  connectionManager: {
297
- minConnections: 0,
298
- maxConnections: maxPeerCount,
323
+ minConnections: 0, // Disable libp2p peer dialing, we do it manually
324
+ // We set maxConnections above maxPeerCount because if we hit limit of maxPeerCount
325
+ // libp2p will start aggressively rejecting all new connections, preventing network discovery and crawling.
326
+ maxConnections: maxPeerCount * 2,
299
327
  maxParallelDials: 100,
300
328
  dialTimeout: 30_000,
301
329
  maxPeerAddrsToDial: 5,
@@ -379,7 +407,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
379
407
  logger: createLibp2pComponentLogger(logger.module),
380
408
  });
381
409
 
382
- const peerScoring = new PeerScoring(config);
410
+ const peerScoring = new PeerScoring(config, telemetry);
383
411
  const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
384
412
 
385
413
  const peerManager = new PeerManager(
@@ -434,9 +462,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
434
462
  }
435
463
  const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
436
464
 
437
- // Start job queue, peer discovery service and libp2p node
438
- this.jobQueue.start();
439
-
440
465
  await this.peerManager.initializePeers();
441
466
  if (!this.config.p2pDiscoveryDisabled) {
442
467
  await this.peerDiscoveryService.start();
@@ -453,10 +478,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
453
478
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
454
479
  const blockHandler = reqRespBlockHandler(this.archiver);
455
480
  const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
456
- // In case P2P client doesnt'have attestation pool,
457
- // const blockTxsHandler = this.mempools.attestationPool
458
- // ? reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool)
459
- // : def;
460
481
 
461
482
  const requestResponseHandlers: Partial<ReqRespSubProtocolHandlers> = {
462
483
  [ReqRespSubProtocol.PING]: pingHandler,
@@ -465,8 +486,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
465
486
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
466
487
  };
467
488
 
468
- // Only handle block transactions request if attestation pool is available to the client
469
- if (this.mempools.attestationPool) {
489
+ if (!this.config.disableTransactions) {
470
490
  const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
471
491
  requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
472
492
  }
@@ -478,9 +498,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
478
498
  // add GossipSub listener
479
499
  this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
480
500
 
481
- // Start running promise for peer discovery
501
+ // Start running promise for peer discovery and metrics collection
482
502
  this.discoveryRunningPromise = new RunningPromise(
483
- () => this.peerManager.heartbeat(),
503
+ async () => {
504
+ await this.peerManager.heartbeat();
505
+ },
484
506
  this.logger,
485
507
  this.config.peerCheckIntervalMS,
486
508
  );
@@ -489,8 +511,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
489
511
  // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
490
512
  const reqrespSubProtocolValidators = {
491
513
  ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
492
- // TODO(#11336): A request validator for blocks
493
- [ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this),
514
+ [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
515
+ [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
516
+ [ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
494
517
  };
495
518
  await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
496
519
  this.logger.info(`Started P2P service`, {
@@ -512,9 +535,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
512
535
  // Stop peer manager
513
536
  this.logger.debug('Stopping peer manager...');
514
537
  await this.peerManager.stop();
515
-
516
- this.logger.debug('Stopping job queue...');
517
- await this.jobQueue.end();
518
538
  this.logger.debug('Stopping running promise...');
519
539
  await this.discoveryRunningPromise?.stop();
520
540
  this.logger.debug('Stopping peer discovery service...');
@@ -602,16 +622,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
602
622
  if (!this.node.services.pubsub) {
603
623
  throw new Error('Pubsub service not available.');
604
624
  }
605
- const p2pMessage = await P2PMessage.fromGossipable(message);
606
- this.logger.debug(`Publishing message`, {
607
- topic,
608
- messageId: p2pMessage.id,
609
- });
625
+ const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages);
610
626
  const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
611
-
612
627
  return result.recipients.length;
613
628
  }
614
629
 
630
+ /**
631
+ * Checks if this message has already been seen, based on its msgId computed from hashing the message data.
632
+ * Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
633
+ * messages to avoid tx echoes across the network.
634
+ */
615
635
  protected preValidateReceivedMessage(
616
636
  msg: Message,
617
637
  msgId: string,
@@ -647,82 +667,122 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
647
667
  return { result: true, topicType };
648
668
  }
649
669
 
670
+ /**
671
+ * Safely deserializes a P2PMessage from raw message data.
672
+ * @param msgId - The message ID.
673
+ * @param source - The peer ID of the message source.
674
+ * @param data - The raw message data.
675
+ * @returns The deserialized P2PMessage or undefined if deserialization fails.
676
+ */
677
+ private safelyDeserializeP2PMessage(msgId: string, source: PeerId, data: Uint8Array): P2PMessage | undefined {
678
+ try {
679
+ return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
680
+ } catch (err) {
681
+ this.logger.error(`Error deserializing P2PMessage`, err, {
682
+ msgId,
683
+ source: source.toString(),
684
+ });
685
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
686
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
687
+ return undefined;
688
+ }
689
+ }
690
+
650
691
  /**
651
692
  * Handles a new gossip message that was received by the client.
652
693
  * @param topic - The message's topic.
653
694
  * @param data - The message data
654
695
  */
655
696
  protected async handleNewGossipMessage(msg: Message, msgId: string, source: PeerId) {
656
- const p2pMessage = P2PMessage.fromMessageData(Buffer.from(msg.data));
657
- const currentTime = new Date();
658
- const messageLatency = currentTime.getTime() - p2pMessage.publishTime.getTime();
659
- this.logger.debug(`Received message`, {
660
- topic: msg.topic,
661
- messageId: p2pMessage.id,
662
- messageLatency,
663
- });
697
+ const msgReceivedTime = Date.now();
698
+ let topicType: TopicType | undefined;
699
+ const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
700
+ if (!p2pMessage) {
701
+ return;
702
+ }
664
703
 
665
704
  const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
666
705
 
667
706
  if (!preValidationResult.result) {
668
707
  return;
669
- } else if (preValidationResult.topicType !== undefined) {
670
- // guard against clock skew & DST
671
- if (messageLatency > 0) {
672
- this.instrumentation.recordMessageLatency(preValidationResult.topicType, messageLatency);
673
- }
674
708
  }
675
709
 
676
710
  if (msg.topic === this.topicStrings[TopicType.tx]) {
711
+ topicType = TopicType.tx;
677
712
  await this.handleGossipedTx(p2pMessage.payload, msgId, source);
678
713
  }
679
- if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
680
- await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
714
+ if (msg.topic === this.topicStrings[TopicType.block_attestation]) {
715
+ topicType = TopicType.block_attestation;
716
+ if (this.clientType === P2PClientType.Full) {
717
+ await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
718
+ }
681
719
  }
682
720
  if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
721
+ topicType = TopicType.block_proposal;
683
722
  await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
684
723
  }
685
724
 
725
+ if (p2pMessage.timestamp !== undefined && topicType !== undefined) {
726
+ const latency = msgReceivedTime - p2pMessage.timestamp.getTime();
727
+ this.instrumentation.recordMessageLatency(topicType, latency);
728
+ }
729
+
686
730
  return;
687
731
  }
688
732
 
689
733
  protected async validateReceivedMessage<T>(
690
- validationFunc: () => Promise<{ result: boolean; obj: T }>,
734
+ validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
691
735
  msgId: string,
692
736
  source: PeerId,
693
737
  topicType: TopicType,
694
- ): Promise<{ result: boolean; obj: T | undefined }> {
695
- let resultAndObj: { result: boolean; obj: T | undefined } = { result: false, obj: undefined };
738
+ ): Promise<ReceivedMessageValidationResult<T>> {
739
+ let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
696
740
  const timer = new Timer();
697
741
  try {
698
742
  resultAndObj = await validationFunc();
699
743
  } catch (err) {
700
- this.logger.error(`Error deserializing and validating message `, err);
744
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
745
+ this.logger.error(`Error deserializing and validating gossipsub message`, err, {
746
+ msgId,
747
+ source: source.toString(),
748
+ topicType,
749
+ });
701
750
  }
702
751
 
703
- if (resultAndObj.result) {
752
+ if (resultAndObj.result === TopicValidatorResult.Accept) {
704
753
  this.instrumentation.recordMessageValidation(topicType, timer);
705
754
  }
706
755
 
707
- this.node.services.pubsub.reportMessageValidationResult(
708
- msgId,
709
- source.toString(),
710
- resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject,
711
- );
756
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
712
757
  return resultAndObj;
713
758
  }
714
759
 
715
760
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
716
- const validationFunc = async () => {
761
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
717
762
  const tx = Tx.fromBuffer(payloadData);
718
- const result = await this.validatePropagatedTx(tx, source);
719
- return { result, obj: tx };
763
+ const isValid = await this.validatePropagatedTx(tx, source);
764
+ const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
765
+
766
+ this.logger.trace(`Validate propagated tx`, {
767
+ isValid,
768
+ exists,
769
+ [Attributes.P2P_ID]: source.toString(),
770
+ });
771
+
772
+ if (!isValid) {
773
+ return { result: TopicValidatorResult.Reject };
774
+ } else if (exists) {
775
+ return { result: TopicValidatorResult.Ignore, obj: tx };
776
+ } else {
777
+ return { result: TopicValidatorResult.Accept, obj: tx };
778
+ }
720
779
  };
721
780
 
722
781
  const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
723
- if (!result || !tx) {
782
+ if (result !== TopicValidatorResult.Accept || !tx) {
724
783
  return;
725
784
  }
785
+
726
786
  const txHash = tx.getTxHash();
727
787
  const txHashString = txHash.toString();
728
788
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
@@ -731,10 +791,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
731
791
  });
732
792
 
733
793
  if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
734
- this.logger.debug(`Intentionally dropping tx ${txHashString} (probability rule)`);
794
+ this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
735
795
  return;
736
796
  }
737
797
 
798
+ this.instrumentation.incrementTxReceived(1);
738
799
  await this.mempools.txPool.addTxs([tx]);
739
800
  }
740
801
 
@@ -745,14 +806,42 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
745
806
  * @param attestation - The attestation to process.
746
807
  */
747
808
  private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
748
- const validationFunc = async () => {
809
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockAttestation>> = async () => {
749
810
  const attestation = BlockAttestation.fromBuffer(payloadData);
750
- const result = await this.validateAttestation(source, attestation);
751
- this.logger.trace(`validatePropagatedAttestation: ${result}`, {
811
+ const pool = this.mempools.attestationPool;
812
+ const isValid = await this.validateAttestation(source, attestation);
813
+ const exists = isValid && (await pool.hasAttestation(attestation));
814
+
815
+ let canAdd = true;
816
+ if (isValid && !exists) {
817
+ const slot = attestation.payload.header.slotNumber;
818
+ const { committee } = await this.epochCache.getCommittee(slot);
819
+ const committeeSize = committee?.length ?? 0;
820
+ canAdd = await pool.canAddAttestation(attestation, committeeSize);
821
+ }
822
+
823
+ this.logger.trace(`Validate propagated block attestation`, {
824
+ isValid,
825
+ exists,
826
+ canAdd,
752
827
  [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
753
828
  [Attributes.P2P_ID]: source.toString(),
754
829
  });
755
- return { result, obj: attestation };
830
+
831
+ if (!isValid) {
832
+ return { result: TopicValidatorResult.Reject };
833
+ } else if (exists) {
834
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
835
+ } else if (!canAdd) {
836
+ this.logger.warn(`Dropping block attestation due to per-(slot, proposalId) attestation cap`, {
837
+ slot: attestation.payload.header.slotNumber.toString(),
838
+ archive: attestation.archive.toString(),
839
+ source: source.toString(),
840
+ });
841
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
842
+ } else {
843
+ return { result: TopicValidatorResult.Accept, obj: attestation };
844
+ }
756
845
  };
757
846
 
758
847
  const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
@@ -761,31 +850,56 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
761
850
  source,
762
851
  TopicType.block_attestation,
763
852
  );
764
- if (!result || !attestation) {
853
+
854
+ if (result !== TopicValidatorResult.Accept || !attestation) {
765
855
  return;
766
856
  }
857
+
767
858
  this.logger.debug(
768
- `Received attestation for block ${attestation.blockNumber} slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`,
859
+ `Received attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
769
860
  {
770
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
771
- slot: attestation.slotNumber.toNumber(),
861
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
862
+ slot: attestation.slotNumber,
772
863
  archive: attestation.archive.toString(),
773
- block: attestation.blockNumber,
774
864
  source: source.toString(),
775
865
  },
776
866
  );
777
- await this.mempools.attestationPool!.addAttestations([attestation]);
867
+
868
+ await this.mempools.attestationPool.addAttestations([attestation]);
778
869
  }
779
870
 
780
871
  private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
781
- const validationFunc = async () => {
872
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
782
873
  const block = BlockProposal.fromBuffer(payloadData);
783
- const result = await this.validateBlockProposal(source, block);
784
- this.logger.trace(`validatePropagatedBlock: ${result}`, {
874
+ const isValid = await this.validateBlockProposal(source, block);
875
+ const pool = this.mempools.attestationPool;
876
+
877
+ const exists = isValid && (await pool.hasBlockProposal(block));
878
+ const canAdd = isValid && (await pool.canAddProposal(block));
879
+
880
+ this.logger.trace(`Validate propagated block proposal`, {
881
+ isValid,
882
+ exists,
883
+ canAdd,
785
884
  [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
786
885
  [Attributes.P2P_ID]: source.toString(),
787
886
  });
788
- return { result, obj: block };
887
+
888
+ if (!isValid) {
889
+ return { result: TopicValidatorResult.Reject };
890
+ } else if (exists) {
891
+ return { result: TopicValidatorResult.Ignore, obj: block };
892
+ } else if (!canAdd) {
893
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
894
+ this.logger.warn(`Penalizing peer for block proposal exceeding per-slot cap`, {
895
+ slot: block.slotNumber.toString(),
896
+ archive: block.archive.toString(),
897
+ source: source.toString(),
898
+ });
899
+ return { result: TopicValidatorResult.Reject };
900
+ } else {
901
+ return { result: TopicValidatorResult.Accept, obj: block };
902
+ }
789
903
  };
790
904
 
791
905
  const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
@@ -794,6 +908,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
794
908
  source,
795
909
  TopicType.block_proposal,
796
910
  );
911
+
797
912
  if (!result || !block) {
798
913
  return;
799
914
  }
@@ -803,48 +918,49 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
803
918
 
804
919
  // REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
805
920
  @trackSpan('Libp2pService.processValidBlockProposal', async block => ({
806
- [Attributes.BLOCK_NUMBER]: block.blockNumber,
807
- [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
921
+ [Attributes.SLOT_NUMBER]: block.slotNumber,
808
922
  [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
809
- [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then(i => i.toString()),
923
+ [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
810
924
  }))
811
925
  private async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
812
- const slot = block.slotNumber.toBigInt();
813
- const previousSlot = slot - 1n;
814
- const epoch = slot / 32n;
815
- this.logger.verbose(
816
- `Received block ${block.blockNumber} for slot ${slot} epoch ${epoch} from external peer ${sender.toString()}.`,
817
- {
818
- p2pMessageIdentifier: await block.p2pMessageIdentifier(),
819
- slot: block.slotNumber.toNumber(),
820
- archive: block.archive.toString(),
821
- block: block.blockNumber,
822
- source: sender.toString(),
823
- },
824
- );
825
- const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
826
- if (attestationsForPreviousSlot !== undefined) {
827
- this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
828
- }
926
+ const slot = block.slotNumber;
927
+ const previousSlot = SlotNumber(slot - 1);
928
+ this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
929
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
930
+ slot: block.slotNumber,
931
+ archive: block.archive.toString(),
932
+ source: sender.toString(),
933
+ });
934
+ const attestationsForPreviousSlot = await this.mempools.attestationPool.getAttestationsForSlot(previousSlot);
935
+ this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
829
936
 
830
- // Mark the txs in this proposal as non-evictable
937
+ // Attempt to add proposal, then mark the txs in this proposal as non-evictable
938
+ try {
939
+ await this.mempools.attestationPool.addBlockProposal(block);
940
+ } catch (err: unknown) {
941
+ // Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
942
+ if (err instanceof ProposalSlotCapExceededError) {
943
+ this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
944
+ slot: String(slot),
945
+ archive: block.archive.toString(),
946
+ error: (err as Error).message,
947
+ });
948
+ return;
949
+ }
950
+ throw err;
951
+ }
831
952
  await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
832
- await this.mempools.attestationPool?.addBlockProposal(block);
833
953
  const attestations = await this.blockReceivedCallback(block, sender);
834
954
 
835
955
  // TODO: fix up this pattern - the abstraction is not nice
836
- // The attestation can be undefined if no handler is registered / the validator deems the block invalid
956
+ // The attestation can be undefined if no handler is registered / the validator deems the block invalid / in fisherman mode
837
957
  if (attestations?.length) {
838
958
  for (const attestation of attestations) {
839
- this.logger.verbose(
840
- `Broadcasting attestation for block ${attestation.blockNumber} slot ${attestation.slotNumber.toNumber()}`,
841
- {
842
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
843
- slot: attestation.slotNumber.toNumber(),
844
- archive: attestation.archive.toString(),
845
- block: attestation.blockNumber,
846
- },
847
- );
959
+ this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber}`, {
960
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
961
+ slot: attestation.slotNumber,
962
+ archive: attestation.archive.toString(),
963
+ });
848
964
  await this.broadcastAttestation(attestation);
849
965
  }
850
966
  }
@@ -855,10 +971,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
855
971
  * @param attestation - The attestation to broadcast.
856
972
  */
857
973
  @trackSpan('Libp2pService.broadcastAttestation', async attestation => ({
858
- [Attributes.BLOCK_NUMBER]: attestation.blockNumber,
859
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
974
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
860
975
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
861
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
976
+ [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
862
977
  }))
863
978
  private async broadcastAttestation(attestation: BlockAttestation) {
864
979
  await this.propagate(attestation);
@@ -869,15 +984,100 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
869
984
  * @param message - The message to propagate.
870
985
  */
871
986
  public async propagate<T extends Gossipable>(message: T) {
872
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
987
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
873
988
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, { p2pMessageIdentifier });
874
- void this.jobQueue
875
- .put(async () => {
876
- await this.sendToPeers(message);
877
- })
878
- .catch(error => {
879
- this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
880
- });
989
+ void this.sendToPeers(message).catch(error => {
990
+ this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
991
+ });
992
+ }
993
+
994
+ /**
995
+ * Validate the requested block transactions. Allow partial returns.
996
+ * @param request - The block transactions request.
997
+ * @param response - The block transactions response.
998
+ * @param peerId - The ID of the peer that made the request.
999
+ * @returns True if the requested block transactions are valid, false otherwise.
1000
+ */
1001
+ @trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
1002
+ [Attributes.BLOCK_HASH]: request.blockHash.toString(),
1003
+ }))
1004
+ private async validateRequestedBlockTxs(
1005
+ request: BlockTxsRequest,
1006
+ response: BlockTxsResponse,
1007
+ peerId: PeerId,
1008
+ ): Promise<boolean> {
1009
+ const requestedTxValidator = this.createRequestedTxValidator();
1010
+
1011
+ try {
1012
+ if (!response.blockHash.equals(request.blockHash)) {
1013
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1014
+ throw new ValidationError(
1015
+ `Received block txs for unexpected block: expected ${request.blockHash.toString()}, got ${response.blockHash.toString()}`,
1016
+ );
1017
+ }
1018
+
1019
+ if (response.txIndices.getLength() !== request.txIndices.getLength()) {
1020
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1021
+ throw new ValidationError(
1022
+ `Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`,
1023
+ );
1024
+ }
1025
+
1026
+ // Check no duplicates and not exceeding returnable count
1027
+ const requestedIndices = new Set(request.txIndices.getTrueIndices());
1028
+ const availableIndices = new Set(response.txIndices.getTrueIndices());
1029
+ const maxReturnable = [...requestedIndices].filter(i => availableIndices.has(i)).length;
1030
+
1031
+ const returnedHashes = await Promise.all(response.txs.map(tx => tx.getTxHash().toString()));
1032
+ const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1033
+ if (uniqueReturned.size !== returnedHashes.length) {
1034
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1035
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1036
+ }
1037
+ if (response.txs.length > maxReturnable) {
1038
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1039
+ throw new ValidationError(
1040
+ `Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`,
1041
+ );
1042
+ }
1043
+
1044
+ // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1045
+ const proposal = await this.mempools.attestationPool.getBlockProposal(request.blockHash.toString());
1046
+ if (proposal) {
1047
+ // Build intersected indices
1048
+ const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1049
+
1050
+ // Enforce subset membership and preserve increasing order by index.
1051
+ const hashToIndexInProposal = new Map<string, number>(
1052
+ proposal.txHashes.map((h, i) => [h.toString(), i] as [string, number]),
1053
+ );
1054
+ const allowedIndexSet = new Set(intersectIdx);
1055
+ const indices = returnedHashes.map(h => hashToIndexInProposal.get(h));
1056
+ const allAllowed = indices.every(idx => idx !== undefined && allowedIndexSet.has(idx));
1057
+ const strictlyIncreasing = indices.every((idx, i) => (i === 0 ? idx !== undefined : idx! > indices[i - 1]!));
1058
+ if (!allAllowed || !strictlyIncreasing) {
1059
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1060
+ throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
1061
+ }
1062
+ } else {
1063
+ // No local proposal, cannot check the membership/order of the returned txs
1064
+ this.logger.warn(
1065
+ `Block proposal not found for block hash ${request.blockHash.toString()}; cannot validate membership/order of returned txs`,
1066
+ );
1067
+ return false;
1068
+ }
1069
+
1070
+ await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
1071
+ return true;
1072
+ } catch (e: any) {
1073
+ if (e instanceof ValidationError) {
1074
+ this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
1075
+ } else {
1076
+ this.logger.error(`Error during validation of requested block txs`, e);
1077
+ }
1078
+
1079
+ return false;
1080
+ }
881
1081
  }
882
1082
 
883
1083
  /**
@@ -890,47 +1090,113 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
890
1090
  * ReqRespSubProtocol.TX subprotocol validation.
891
1091
  *
892
1092
  * @param requestedTxHash - The collection of the txs that was requested.
893
- * @param responseTx - The collectin of txs that was received as a response to the request.
1093
+ * @param responseTx - The collection of txs that was received as a response to the request.
894
1094
  * @param peerId - The peer ID of the peer that sent the tx.
895
1095
  * @returns True if the whole collection of txs is valid, false otherwise.
896
1096
  */
897
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
898
- // I think we should still extract the valid txs and return them, so that we can still use the response.
899
1097
  @trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx) => ({
900
1098
  [Attributes.TX_HASH]: requestedTxHash.toString(),
901
1099
  }))
902
- private async validateRequestedTx(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
1100
+ private async validateRequestedTxs(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
903
1101
  const requested = new Set(requestedTxHash.map(h => h.toString()));
1102
+ const requestedTxValidator = this.createRequestedTxValidator();
904
1103
 
905
- const proofValidator = new TxProofValidator(this.proofVerifier);
906
-
1104
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
1105
+ // I think we should still extract the valid txs and return them, so that we can still use the response.
907
1106
  try {
908
- await Promise.all(
909
- responseTx.map(async tx => {
910
- if (!requested.has(tx.getTxHash().toString())) {
911
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
912
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
913
- }
914
-
915
- const { result } = await proofValidator.validateTx(tx);
916
- if (result === 'invalid') {
917
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
918
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
919
- }
920
- }),
921
- );
1107
+ await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
922
1108
  return true;
923
1109
  } catch (e: any) {
924
1110
  if (e instanceof ValidationError) {
925
- this.logger.debug(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
1111
+ this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
926
1112
  } else {
927
- this.logger.warn(`Error during validation of requested txs`, e);
1113
+ this.logger.error(`Error during validation of requested txs`, e);
1114
+ }
1115
+
1116
+ return false;
1117
+ }
1118
+ }
1119
+
1120
+ /**
1121
+ * Validates a BLOCK response.
1122
+ *
1123
+ * If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
1124
+ * Penalizes on block number mismatch or hash mismatch.
1125
+ *
1126
+ * @param requestedBlockNumber - The requested block number.
1127
+ * @param responseBlock - The block returned by the peer.
1128
+ * @param peerId - The peer that returned the block.
1129
+ * @returns True if the response is valid, false otherwise.
1130
+ */
1131
+ @trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
1132
+ [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
1133
+ }))
1134
+ private async validateRequestedBlock(
1135
+ requestedBlockNumber: Fr,
1136
+ responseBlock: L2Block,
1137
+ peerId: PeerId,
1138
+ ): Promise<boolean> {
1139
+ try {
1140
+ const reqNum = Number(requestedBlockNumber.toString());
1141
+ if (responseBlock.number !== reqNum) {
1142
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1143
+ return false;
928
1144
  }
929
1145
 
1146
+ const local = await this.archiver.getBlock(BlockNumber(reqNum));
1147
+ if (!local) {
1148
+ // We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
1149
+ // TODO: Consider extending this validator to accept an expected hash or
1150
+ // performing quorum-based checks when using P2P syncing prior to L1 sync.
1151
+ this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
1152
+ return false;
1153
+ }
1154
+ const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
1155
+ if (!localHash.equals(respHash)) {
1156
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1157
+ return false;
1158
+ }
1159
+
1160
+ return true;
1161
+ } catch (e) {
1162
+ this.logger.warn(`Error validating requested block`, e);
930
1163
  return false;
931
1164
  }
932
1165
  }
933
1166
 
1167
+ private createRequestedTxValidator(): TxValidator {
1168
+ return new AggregateTxValidator(
1169
+ new DataTxValidator(),
1170
+ new MetadataTxValidator({
1171
+ l1ChainId: new Fr(this.config.l1ChainId),
1172
+ rollupVersion: new Fr(this.config.rollupVersion),
1173
+ protocolContractsHash,
1174
+ vkTreeRoot: getVKTreeRoot(),
1175
+ }),
1176
+ new TxProofValidator(this.proofVerifier),
1177
+ );
1178
+ }
1179
+
1180
+ private async validateRequestedTx(tx: Tx, peerId: PeerId, txValidator: TxValidator, requested?: Set<`0x${string}`>) {
1181
+ const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
1182
+
1183
+ if (!(await tx.validateTxHash())) {
1184
+ penalize(PeerErrorSeverity.MidToleranceError);
1185
+ throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
1186
+ }
1187
+
1188
+ if (requested && !requested.has(tx.getTxHash().toString())) {
1189
+ penalize(PeerErrorSeverity.MidToleranceError);
1190
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
1191
+ }
1192
+
1193
+ const { result } = await txValidator.validateTx(tx);
1194
+ if (result === 'invalid') {
1195
+ penalize(PeerErrorSeverity.LowToleranceError);
1196
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
1197
+ }
1198
+ }
1199
+
934
1200
  @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
935
1201
  [Attributes.TX_HASH]: tx.getTxHash().toString(),
936
1202
  }))
@@ -952,7 +1218,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
952
1218
 
953
1219
  // Double spend validator has a special case handler
954
1220
  if (name === 'doubleSpendValidator') {
955
- const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
1221
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
956
1222
  severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
957
1223
  }
958
1224
 
@@ -962,7 +1228,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
962
1228
  return true;
963
1229
  }
964
1230
 
965
- private async getGasFees(blockNumber: number): Promise<GasFees> {
1231
+ private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
966
1232
  if (blockNumber === this.feesCache?.blockNumber) {
967
1233
  return this.feesCache.gasFees;
968
1234
  }
@@ -1003,13 +1269,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1003
1269
  * @returns The message validators.
1004
1270
  */
1005
1271
  private async createMessageValidators(
1006
- currentBlockNumber: number,
1272
+ currentBlockNumber: BlockNumber,
1007
1273
  nextSlotTimestamp: UInt64,
1008
1274
  ): Promise<Record<string, MessageValidator>[]> {
1009
1275
  const gasFees = await this.getGasFees(currentBlockNumber);
1010
1276
  const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1011
1277
 
1012
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
1278
+ const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1013
1279
 
1014
1280
  return createTxMessageValidators(
1015
1281
  nextSlotTimestamp,
@@ -1018,7 +1284,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1018
1284
  gasFees,
1019
1285
  this.config.l1ChainId,
1020
1286
  this.config.rollupVersion,
1021
- protocolContractTreeRoot,
1287
+ protocolContractsHash,
1022
1288
  this.archiver,
1023
1289
  this.proofVerifier,
1024
1290
  !this.config.disableTransactions,
@@ -1071,7 +1337,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1071
1337
  * @param peerId - The peer ID of the peer that sent the tx.
1072
1338
  * @returns Severity
1073
1339
  */
1074
- private async handleDoubleSpendFailure(tx: Tx, blockNumber: number): Promise<PeerErrorSeverity> {
1340
+ private async handleDoubleSpendFailure(tx: Tx, blockNumber: BlockNumber): Promise<PeerErrorSeverity> {
1075
1341
  if (blockNumber <= this.config.doubleSpendSeverePeerPenaltyWindow) {
1076
1342
  return PeerErrorSeverity.HighToleranceError;
1077
1343
  }
@@ -1079,7 +1345,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1079
1345
  const snapshotValidator = new DoubleSpendTxValidator({
1080
1346
  nullifiersExist: async (nullifiers: Buffer[]) => {
1081
1347
  const merkleTree = this.worldStateSynchronizer.getSnapshot(
1082
- blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow,
1348
+ BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
1083
1349
  );
1084
1350
  const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1085
1351
  return indices.map(index => index !== undefined);
@@ -1101,10 +1367,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1101
1367
  * @returns True if the attestation is valid, false otherwise.
1102
1368
  */
1103
1369
  @trackSpan('Libp2pService.validateAttestation', async (_, attestation) => ({
1104
- [Attributes.BLOCK_NUMBER]: attestation.blockNumber,
1105
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
1370
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1106
1371
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1107
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
1372
+ [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1108
1373
  }))
1109
1374
  public async validateAttestation(peerId: PeerId, attestation: BlockAttestation): Promise<boolean> {
1110
1375
  const severity = await this.attestationValidator.validate(attestation);
@@ -1147,7 +1412,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1147
1412
  private async sendToPeers<T extends Gossipable>(message: T) {
1148
1413
  const parent = message.constructor as typeof Gossipable;
1149
1414
 
1150
- const identifier = await message.p2pMessageIdentifier().then(i => i.toString());
1415
+ const identifier = await message.p2pMessageLoggingIdentifier().then(i => i.toString());
1151
1416
  this.logger.trace(`Sending message ${identifier}`, { p2pMessageIdentifier: identifier });
1152
1417
 
1153
1418
  const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);