@aztec/p2p 0.0.1-commit.87a0206 → 0.0.1-commit.88c5703d4

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 (372) hide show
  1. package/README.md +129 -3
  2. package/dest/client/factory.d.ts +9 -9
  3. package/dest/client/factory.d.ts.map +1 -1
  4. package/dest/client/factory.js +50 -13
  5. package/dest/client/interface.d.ts +39 -33
  6. package/dest/client/interface.d.ts.map +1 -1
  7. package/dest/client/p2p_client.d.ts +37 -50
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +148 -223
  10. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -7
  11. package/dest/config.d.ts +48 -17
  12. package/dest/config.d.ts.map +1 -1
  13. package/dest/config.js +92 -38
  14. package/dest/errors/tx-pool.error.d.ts +8 -0
  15. package/dest/errors/tx-pool.error.d.ts.map +1 -0
  16. package/dest/errors/tx-pool.error.js +9 -0
  17. package/dest/index.d.ts +2 -1
  18. package/dest/index.d.ts.map +1 -1
  19. package/dest/index.js +1 -0
  20. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +21 -12
  21. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  22. package/dest/mem_pools/attestation_pool/attestation_pool.js +72 -38
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +53 -53
  26. package/dest/mem_pools/attestation_pool/index.d.ts +2 -2
  27. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  28. package/dest/mem_pools/attestation_pool/index.js +1 -1
  29. package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
  30. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  31. package/dest/mem_pools/attestation_pool/mocks.js +2 -2
  32. package/dest/mem_pools/index.d.ts +2 -1
  33. package/dest/mem_pools/index.d.ts.map +1 -1
  34. package/dest/mem_pools/instrumentation.d.ts +4 -2
  35. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  36. package/dest/mem_pools/instrumentation.js +16 -14
  37. package/dest/mem_pools/interface.d.ts +3 -3
  38. package/dest/mem_pools/interface.d.ts.map +1 -1
  39. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  40. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +2 -1
  42. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +3 -3
  43. package/dest/mem_pools/tx_pool/priority.d.ts +2 -2
  44. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  45. package/dest/mem_pools/tx_pool/priority.js +4 -4
  46. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  47. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  48. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +3 -1
  49. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
  50. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
  51. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
  52. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
  53. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
  54. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
  55. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  56. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  57. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +7 -3
  58. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
  59. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  60. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
  61. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
  62. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  63. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
  64. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +54 -5
  65. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  66. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
  67. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
  68. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +7 -5
  69. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
  70. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  71. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
  72. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
  73. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  74. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
  75. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
  76. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  77. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
  78. package/dest/mem_pools/tx_pool_v2/index.d.ts +3 -2
  79. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
  80. package/dest/mem_pools/tx_pool_v2/index.js +2 -1
  81. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  82. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  83. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  84. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +26 -8
  85. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  86. package/dest/mem_pools/tx_pool_v2/interfaces.js +5 -1
  87. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +78 -15
  88. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  89. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +139 -18
  90. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
  91. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  92. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +50 -45
  93. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -5
  94. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  95. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +17 -6
  96. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +14 -5
  97. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  98. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +364 -189
  99. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
  100. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  101. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
  102. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
  103. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  104. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
  105. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
  106. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  107. package/dest/msg_validators/proposal_validator/proposal_validator.js +48 -36
  108. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +4 -4
  109. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  110. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
  111. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  112. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  113. package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
  114. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  115. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  116. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  117. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +16 -3
  118. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  119. package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
  120. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
  121. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  122. package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
  123. package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
  124. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  125. package/dest/msg_validators/tx_validator/factory.js +240 -59
  126. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  127. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  128. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  129. package/dest/msg_validators/tx_validator/gas_validator.d.ts +67 -3
  130. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  131. package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
  132. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  133. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  134. package/dest/msg_validators/tx_validator/index.js +2 -0
  135. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  136. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  137. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  138. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  139. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  140. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  141. package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
  142. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  143. package/dest/msg_validators/tx_validator/phases_validator.js +71 -23
  144. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
  145. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  146. package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
  147. package/dest/services/dummy_service.d.ts +9 -5
  148. package/dest/services/dummy_service.d.ts.map +1 -1
  149. package/dest/services/dummy_service.js +7 -4
  150. package/dest/services/encoding.d.ts +3 -3
  151. package/dest/services/encoding.d.ts.map +1 -1
  152. package/dest/services/encoding.js +11 -10
  153. package/dest/services/gossipsub/index.d.ts +3 -0
  154. package/dest/services/gossipsub/index.d.ts.map +1 -0
  155. package/dest/services/gossipsub/index.js +2 -0
  156. package/dest/services/gossipsub/scoring.d.ts +21 -3
  157. package/dest/services/gossipsub/scoring.d.ts.map +1 -1
  158. package/dest/services/gossipsub/scoring.js +24 -7
  159. package/dest/services/gossipsub/topic_score_params.d.ts +173 -0
  160. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
  161. package/dest/services/gossipsub/topic_score_params.js +346 -0
  162. package/dest/services/libp2p/libp2p_service.d.ts +25 -14
  163. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  164. package/dest/services/libp2p/libp2p_service.js +195 -153
  165. package/dest/services/peer-manager/metrics.d.ts +3 -1
  166. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  167. package/dest/services/peer-manager/metrics.js +6 -0
  168. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  169. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  170. package/dest/services/peer-manager/peer_manager.js +2 -1
  171. package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
  172. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  173. package/dest/services/peer-manager/peer_scoring.js +25 -2
  174. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -4
  175. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  176. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +45 -55
  177. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +4 -6
  178. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  179. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +11 -13
  180. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  181. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +31 -46
  182. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
  183. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  184. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
  185. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
  186. package/dest/services/reqresp/interface.d.ts +10 -1
  187. package/dest/services/reqresp/interface.d.ts.map +1 -1
  188. package/dest/services/reqresp/interface.js +15 -1
  189. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +3 -3
  190. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  191. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
  192. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  193. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +15 -0
  194. package/dest/services/reqresp/protocols/tx.d.ts +7 -1
  195. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  196. package/dest/services/reqresp/protocols/tx.js +20 -0
  197. package/dest/services/reqresp/reqresp.d.ts +1 -1
  198. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  199. package/dest/services/reqresp/reqresp.js +14 -6
  200. package/dest/services/service.d.ts +22 -3
  201. package/dest/services/service.d.ts.map +1 -1
  202. package/dest/services/tx_collection/config.d.ts +19 -1
  203. package/dest/services/tx_collection/config.d.ts.map +1 -1
  204. package/dest/services/tx_collection/config.js +46 -0
  205. package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -1
  206. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  207. package/dest/services/tx_collection/fast_tx_collection.js +56 -36
  208. package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
  209. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
  210. package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
  211. package/dest/services/tx_collection/file_store_tx_source.d.ts +37 -0
  212. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
  213. package/dest/services/tx_collection/file_store_tx_source.js +90 -0
  214. package/dest/services/tx_collection/index.d.ts +2 -1
  215. package/dest/services/tx_collection/index.d.ts.map +1 -1
  216. package/dest/services/tx_collection/index.js +1 -0
  217. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  218. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  219. package/dest/services/tx_collection/instrumentation.js +2 -1
  220. package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
  221. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
  222. package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
  223. package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
  224. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  225. package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
  226. package/dest/services/tx_collection/slow_tx_collection.d.ts +7 -3
  227. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  228. package/dest/services/tx_collection/slow_tx_collection.js +60 -26
  229. package/dest/services/tx_collection/tx_collection.d.ts +23 -10
  230. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  231. package/dest/services/tx_collection/tx_collection.js +75 -3
  232. package/dest/services/tx_collection/tx_collection_sink.d.ts +18 -8
  233. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  234. package/dest/services/tx_collection/tx_collection_sink.js +26 -29
  235. package/dest/services/tx_collection/tx_source.d.ts +8 -3
  236. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  237. package/dest/services/tx_collection/tx_source.js +19 -2
  238. package/dest/services/tx_file_store/config.d.ts +1 -3
  239. package/dest/services/tx_file_store/config.d.ts.map +1 -1
  240. package/dest/services/tx_file_store/config.js +0 -4
  241. package/dest/services/tx_file_store/tx_file_store.d.ts +4 -3
  242. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  243. package/dest/services/tx_file_store/tx_file_store.js +9 -6
  244. package/dest/services/tx_provider.d.ts +4 -4
  245. package/dest/services/tx_provider.d.ts.map +1 -1
  246. package/dest/services/tx_provider.js +9 -8
  247. package/dest/test-helpers/make-test-p2p-clients.d.ts +7 -8
  248. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  249. package/dest/test-helpers/make-test-p2p-clients.js +1 -2
  250. package/dest/test-helpers/mock-pubsub.d.ts +30 -4
  251. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  252. package/dest/test-helpers/mock-pubsub.js +105 -4
  253. package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
  254. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  255. package/dest/test-helpers/reqresp-nodes.js +4 -3
  256. package/dest/test-helpers/testbench-utils.d.ts +35 -24
  257. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  258. package/dest/test-helpers/testbench-utils.js +104 -36
  259. package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
  260. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  261. package/dest/testbench/p2p_client_testbench_worker.js +16 -15
  262. package/dest/testbench/worker_client_manager.d.ts +3 -1
  263. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  264. package/dest/testbench/worker_client_manager.js +6 -2
  265. package/dest/util.d.ts +3 -3
  266. package/dest/util.d.ts.map +1 -1
  267. package/package.json +14 -14
  268. package/src/client/factory.ts +96 -24
  269. package/src/client/interface.ts +43 -33
  270. package/src/client/p2p_client.ts +172 -265
  271. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +20 -11
  272. package/src/config.ts +141 -44
  273. package/src/errors/tx-pool.error.ts +12 -0
  274. package/src/index.ts +1 -0
  275. package/src/mem_pools/attestation_pool/attestation_pool.ts +100 -48
  276. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +57 -53
  277. package/src/mem_pools/attestation_pool/index.ts +3 -3
  278. package/src/mem_pools/attestation_pool/mocks.ts +2 -1
  279. package/src/mem_pools/index.ts +3 -0
  280. package/src/mem_pools/instrumentation.ts +17 -13
  281. package/src/mem_pools/interface.ts +2 -2
  282. package/src/mem_pools/tx_pool/README.md +1 -1
  283. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  284. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
  285. package/src/mem_pools/tx_pool/priority.ts +4 -4
  286. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +3 -1
  287. package/src/mem_pools/tx_pool_v2/README.md +85 -11
  288. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  289. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
  290. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +7 -3
  291. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
  292. package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
  293. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +59 -4
  294. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
  295. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
  296. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
  297. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
  298. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
  299. package/src/mem_pools/tx_pool_v2/index.ts +2 -1
  300. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  301. package/src/mem_pools/tx_pool_v2/interfaces.ts +28 -8
  302. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +202 -26
  303. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +58 -45
  304. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +34 -8
  305. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +410 -187
  306. package/src/msg_validators/attestation_validator/README.md +49 -0
  307. package/src/msg_validators/proposal_validator/README.md +123 -0
  308. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
  309. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
  310. package/src/msg_validators/proposal_validator/proposal_validator.ts +63 -40
  311. package/src/msg_validators/tx_validator/README.md +119 -0
  312. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +5 -5
  313. package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
  314. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  315. package/src/msg_validators/tx_validator/block_header_validator.ts +15 -3
  316. package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
  317. package/src/msg_validators/tx_validator/factory.ts +387 -78
  318. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  319. package/src/msg_validators/tx_validator/gas_validator.ts +123 -27
  320. package/src/msg_validators/tx_validator/index.ts +2 -0
  321. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  322. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  323. package/src/msg_validators/tx_validator/phases_validator.ts +81 -26
  324. package/src/msg_validators/tx_validator/timestamp_validator.ts +23 -18
  325. package/src/services/dummy_service.ts +12 -6
  326. package/src/services/encoding.ts +9 -9
  327. package/src/services/gossipsub/README.md +641 -0
  328. package/src/services/gossipsub/index.ts +2 -0
  329. package/src/services/gossipsub/scoring.ts +29 -5
  330. package/src/services/gossipsub/topic_score_params.ts +487 -0
  331. package/src/services/libp2p/libp2p_service.ts +206 -164
  332. package/src/services/peer-manager/metrics.ts +7 -0
  333. package/src/services/peer-manager/peer_manager.ts +2 -1
  334. package/src/services/peer-manager/peer_scoring.ts +25 -0
  335. package/src/services/reqresp/README.md +229 -0
  336. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +49 -57
  337. package/src/services/reqresp/batch-tx-requester/interface.ts +3 -5
  338. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +30 -71
  339. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
  340. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
  341. package/src/services/reqresp/interface.ts +26 -1
  342. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +2 -2
  343. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
  344. package/src/services/reqresp/protocols/tx.ts +22 -0
  345. package/src/services/reqresp/reqresp.ts +17 -5
  346. package/src/services/service.ts +31 -2
  347. package/src/services/tx_collection/config.ts +68 -0
  348. package/src/services/tx_collection/fast_tx_collection.ts +65 -32
  349. package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
  350. package/src/services/tx_collection/file_store_tx_source.ts +117 -0
  351. package/src/services/tx_collection/index.ts +1 -0
  352. package/src/services/tx_collection/instrumentation.ts +7 -1
  353. package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
  354. package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
  355. package/src/services/tx_collection/slow_tx_collection.ts +66 -33
  356. package/src/services/tx_collection/tx_collection.ts +113 -16
  357. package/src/services/tx_collection/tx_collection_sink.ts +30 -34
  358. package/src/services/tx_collection/tx_source.ts +22 -3
  359. package/src/services/tx_file_store/config.ts +0 -6
  360. package/src/services/tx_file_store/tx_file_store.ts +10 -8
  361. package/src/services/tx_provider.ts +10 -9
  362. package/src/test-helpers/make-test-p2p-clients.ts +4 -6
  363. package/src/test-helpers/mock-pubsub.ts +146 -9
  364. package/src/test-helpers/reqresp-nodes.ts +5 -7
  365. package/src/test-helpers/testbench-utils.ts +118 -40
  366. package/src/testbench/p2p_client_testbench_worker.ts +25 -21
  367. package/src/testbench/worker_client_manager.ts +13 -5
  368. package/src/util.ts +8 -2
  369. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
  370. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  371. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
  372. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
@@ -1,6 +1,6 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
2
  import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
- import { randomInt } from '@aztec/foundation/crypto/random';
3
+ import { maxBy } from '@aztec/foundation/collection';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
6
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
@@ -17,13 +17,13 @@ import {
17
17
  CheckpointProposal,
18
18
  type CheckpointProposalCore,
19
19
  type Gossipable,
20
- P2PClientType,
21
20
  P2PMessage,
22
21
  type ValidationResult as P2PValidationResult,
23
22
  PeerErrorSeverity,
23
+ PeerErrorSeverityByHarshness,
24
24
  TopicType,
25
25
  createTopicString,
26
- getTopicsForClientAndConfig,
26
+ getTopicsForConfig,
27
27
  metricsTopicStrToLabels,
28
28
  } from '@aztec/stdlib/p2p';
29
29
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -45,7 +45,7 @@ import {
45
45
  type GossipsubMessage,
46
46
  gossipsub,
47
47
  } from '@chainsafe/libp2p-gossipsub';
48
- import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
48
+ import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
49
49
  import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
50
50
  import { noise } from '@chainsafe/libp2p-noise';
51
51
  import { yamux } from '@chainsafe/libp2p-yamux';
@@ -70,9 +70,11 @@ import {
70
70
  } from '../../msg_validators/index.js';
71
71
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
72
72
  import {
73
- type MessageValidator,
74
- createTxMessageValidators,
75
- createTxReqRespValidator,
73
+ type TransactionValidator,
74
+ createFirstStageTxValidationsForGossipedTransactions,
75
+ createSecondStageTxValidationsForGossipedTransactions,
76
+ createTxValidatorForBlockProposalReceivedTxs,
77
+ createTxValidatorForReqResponseReceivedTxs,
76
78
  } from '../../msg_validators/tx_validator/factory.js';
77
79
  import { GossipSubEvent } from '../../types/index.js';
78
80
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
@@ -80,13 +82,17 @@ import { getVersions } from '../../versioning.js';
80
82
  import { AztecDatastore } from '../data_store.js';
81
83
  import { DiscV5Service } from '../discv5/discV5_service.js';
82
84
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
83
- import { gossipScoreThresholds } from '../gossipsub/scoring.js';
85
+ import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
86
+ import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
84
87
  import type { PeerManagerInterface } from '../peer-manager/interface.js';
85
88
  import { PeerManager } from '../peer-manager/peer_manager.js';
86
89
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
87
90
  import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
88
91
  import type { P2PReqRespConfig } from '../reqresp/config.js';
89
92
  import {
93
+ AuthRequest,
94
+ BlockTxsRequest,
95
+ BlockTxsResponse,
90
96
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
91
97
  type ReqRespInterface,
92
98
  type ReqRespResponse,
@@ -94,14 +100,9 @@ import {
94
100
  type ReqRespSubProtocolHandler,
95
101
  type ReqRespSubProtocolHandlers,
96
102
  type ReqRespSubProtocolValidators,
103
+ StatusMessage,
97
104
  type SubProtocolMap,
98
105
  ValidationError,
99
- } from '../reqresp/index.js';
100
- import {
101
- AuthRequest,
102
- BlockTxsRequest,
103
- BlockTxsResponse,
104
- StatusMessage,
105
106
  pingHandler,
106
107
  reqGoodbyeHandler,
107
108
  reqRespBlockHandler,
@@ -113,6 +114,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
113
114
  import type {
114
115
  P2PBlockReceivedCallback,
115
116
  P2PCheckpointReceivedCallback,
117
+ P2PDuplicateAttestationCallback,
116
118
  P2PService,
117
119
  PeerDiscoveryService,
118
120
  } from '../service.js';
@@ -134,7 +136,7 @@ type ReceivedMessageValidationResult<T, M = undefined> =
134
136
  /**
135
137
  * Lib P2P implementation of the P2PService interface.
136
138
  */
137
- export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
139
+ export class LibP2PService extends WithTracer implements P2PService {
138
140
  private discoveryRunningPromise?: RunningPromise;
139
141
  private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
140
142
 
@@ -155,6 +157,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
155
157
  type: 'checkpoint' | 'block';
156
158
  }) => void;
157
159
 
160
+ /** Callback invoked when a duplicate attestation is detected (triggers slashing). */
161
+ private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
162
+
158
163
  /**
159
164
  * Callback for when a block is received from a peer.
160
165
  * @param block - The block received from the peer.
@@ -178,7 +183,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
178
183
  protected logger: Logger;
179
184
 
180
185
  constructor(
181
- private clientType: T,
182
186
  private config: P2PConfig,
183
187
  protected node: PubSubLibp2p,
184
188
  private peerDiscoveryService: PeerDiscoveryService,
@@ -220,10 +224,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
220
224
  this.protocolVersion,
221
225
  );
222
226
 
223
- this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
224
- this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
227
+ const proposalValidatorOpts = {
225
228
  txsPermitted: !config.disableTransactions,
226
- });
229
+ maxTxsPerBlock: config.validateMaxTxsPerBlock,
230
+ };
231
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
232
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
227
233
  this.checkpointAttestationValidator = config.fishermanMode
228
234
  ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
229
235
  : new CheckpointAttestationValidator(epochCache);
@@ -231,11 +237,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
231
237
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
232
238
 
233
239
  this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
234
- this.logger.debug(
235
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
240
+ this.logger.warn(
241
+ `Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
236
242
  { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
237
243
  );
238
- return false;
244
+ return true;
239
245
  };
240
246
 
241
247
  this.checkpointReceivedCallback = (
@@ -258,8 +264,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
258
264
  * @param txPool - The transaction pool to be accessed by the service.
259
265
  * @returns The new service.
260
266
  */
261
- public static async new<T extends P2PClientType>(
262
- clientType: T,
267
+ public static async new(
263
268
  config: P2PConfig,
264
269
  peerId: PeerId,
265
270
  deps: {
@@ -311,11 +316,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
311
316
  const versions = getVersions(config);
312
317
  const protocolVersion = compressComponentVersions(versions);
313
318
 
314
- const txTopic = createTopicString(TopicType.tx, protocolVersion);
315
- const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
316
- const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
317
- const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
318
-
319
319
  const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
320
320
  const directPeers = (
321
321
  await Promise.all(
@@ -335,6 +335,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
335
335
 
336
336
  const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
337
337
 
338
+ // Create dynamic topic score params based on network configuration
339
+ const l1Constants = epochCache.getL1Constants();
340
+ const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
341
+ slotDurationMs: l1Constants.slotDuration * 1000,
342
+ heartbeatIntervalMs: config.gossipsubInterval,
343
+ targetCommitteeSize: l1Constants.targetCommitteeSize,
344
+ blockDurationMs: config.blockDurationMs,
345
+ expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
346
+ });
347
+
338
348
  const node = await createLibp2p({
339
349
  start: false,
340
350
  peerId,
@@ -430,28 +440,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
430
440
  scoreParams: createPeerScoreParams({
431
441
  // IPColocation factor can be disabled for local testing - default to -5
432
442
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
433
- topics: {
434
- [txTopic]: createTopicScoreParams({
435
- topicWeight: 1,
436
- invalidMessageDeliveriesWeight: -20,
437
- invalidMessageDeliveriesDecay: 0.5,
438
- }),
439
- [blockProposalTopic]: createTopicScoreParams({
440
- topicWeight: 1,
441
- invalidMessageDeliveriesWeight: -20,
442
- invalidMessageDeliveriesDecay: 0.5,
443
- }),
444
- [checkpointProposalTopic]: createTopicScoreParams({
445
- topicWeight: 1,
446
- invalidMessageDeliveriesWeight: -20,
447
- invalidMessageDeliveriesDecay: 0.5,
448
- }),
449
- [checkpointAttestationTopic]: createTopicScoreParams({
450
- topicWeight: 1,
451
- invalidMessageDeliveriesWeight: -20,
452
- invalidMessageDeliveriesDecay: 0.5,
453
- }),
454
- },
443
+ topics: topicScoreParams,
455
444
  }),
456
445
  }) as (components: GossipSubComponents) => GossipSub,
457
446
  components: (components: { connectionManager: ConnectionManager }) => ({
@@ -477,13 +466,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
477
466
  epochCache,
478
467
  );
479
468
 
480
- // Update gossipsub score params
481
- node.services.pubsub.score.params.appSpecificWeight = 10;
469
+ // Configure application-specific scoring for gossipsub.
470
+ // The weight scales app score to align with gossipsub thresholds:
471
+ // - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
472
+ // - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
473
+ // Note: positive topic scores can offset penalties, so alignment is best-effort.
474
+ node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
482
475
  node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
483
476
  peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
484
477
 
485
478
  return new LibP2PService(
486
- clientType,
487
479
  config,
488
480
  node,
489
481
  peerDiscoveryService,
@@ -557,7 +549,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
557
549
  await this.node.start();
558
550
 
559
551
  // Subscribe to standard GossipSub topics by default
560
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
552
+ for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
561
553
  this.subscribeToTopic(this.topicStrings[topic]);
562
554
  }
563
555
 
@@ -623,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
623
615
  return this.peerManager.getPeers(includePending);
624
616
  }
625
617
 
618
+ public getGossipMeshPeerCount(topicType: TopicType): number {
619
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
620
+ }
621
+
626
622
  private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
627
623
  this.logger.trace(`Received PUBSUB message.`);
628
624
 
@@ -685,6 +681,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
685
681
  this.duplicateProposalCallback = callback;
686
682
  }
687
683
 
684
+ /**
685
+ * Registers a callback to be invoked when a duplicate attestation is detected.
686
+ * A validator signing attestations for different proposals at the same slot.
687
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
688
+ */
689
+ public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
690
+ this.duplicateAttestationCallback = callback;
691
+ }
692
+
688
693
  /**
689
694
  * Subscribes to a topic.
690
695
  * @param topic - The topic to subscribe to.
@@ -749,6 +754,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
749
754
  if (!validator || !validator.addMessage(msgId)) {
750
755
  this.instrumentation.incMessagePrevalidationStatus(false, topicType);
751
756
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
757
+ if (topicType === TopicType.tx) {
758
+ this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
759
+ }
752
760
  return { result: false, topicType };
753
761
  }
754
762
 
@@ -813,9 +821,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
813
821
  if (msg.topic === this.topicStrings[TopicType.tx]) {
814
822
  await this.handleGossipedTx(p2pMessage.payload, msgId, source);
815
823
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
816
- if (this.clientType === P2PClientType.Full) {
817
- await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
818
- }
824
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
819
825
  } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
820
826
  await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
821
827
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
@@ -901,21 +907,76 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
901
907
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
902
908
  const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
903
909
  const tx = Tx.fromBuffer(payloadData);
904
- const isValid = await this.validatePropagatedTx(tx, source);
905
- const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
906
910
 
907
- this.logger.trace(`Validate propagated tx`, {
908
- isValid,
909
- exists,
911
+ const currentBlockNumber = await this.archiver.getBlockNumber();
912
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
913
+
914
+ // Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
915
+ const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
916
+ const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
917
+ if (!firstStageOutcome.allPassed) {
918
+ const { name } = firstStageOutcome.failure;
919
+ let { severity } = firstStageOutcome.failure;
920
+
921
+ // Double spend validator has a special case handler. We perform more detailed examination
922
+ // as to how recently the nullifier was entered into the tree and if the transaction should
923
+ // have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
924
+ if (name === 'doubleSpendValidator') {
925
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1);
926
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
927
+ }
928
+
929
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
930
+ validator: name,
931
+ severity,
932
+ source: source.toString(),
933
+ });
934
+ this.peerManager.penalizePeer(source, severity);
935
+ return { result: TopicValidatorResult.Reject };
936
+ }
937
+
938
+ // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
939
+ const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
940
+ if (canAdd === 'ignored') {
941
+ this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
942
+ source: source.toString(),
943
+ });
944
+ return { result: TopicValidatorResult.Ignore, obj: tx };
945
+ }
946
+
947
+ // Stage 2: expensive proof verification
948
+ const secondStageValidators = this.createSecondStageMessageValidators();
949
+ const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
950
+ if (!secondStageOutcome.allPassed) {
951
+ const { severity, name } = secondStageOutcome.failure;
952
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
953
+ validator: name,
954
+ severity,
955
+ source: source.toString(),
956
+ });
957
+ this.peerManager.penalizePeer(source, severity);
958
+ return { result: TopicValidatorResult.Reject };
959
+ }
960
+
961
+ // Pool add: persist the tx
962
+ const txHash = tx.getTxHash();
963
+ const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
964
+
965
+ const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
966
+ const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
967
+
968
+ this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
969
+ wasAccepted,
970
+ wasIgnored,
910
971
  [Attributes.P2P_ID]: source.toString(),
911
972
  });
912
973
 
913
- if (!isValid) {
914
- return { result: TopicValidatorResult.Reject };
915
- } else if (exists) {
974
+ if (wasAccepted) {
975
+ return { result: TopicValidatorResult.Accept, obj: tx };
976
+ } else if (wasIgnored) {
916
977
  return { result: TopicValidatorResult.Ignore, obj: tx };
917
978
  } else {
918
- return { result: TopicValidatorResult.Accept, obj: tx };
979
+ return { result: TopicValidatorResult.Reject };
919
980
  }
920
981
  };
921
982
 
@@ -924,6 +985,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
924
985
  return;
925
986
  }
926
987
 
988
+ // Tx was accepted into pool and will be propagated - just log and record metrics
927
989
  const txHash = tx.getTxHash();
928
990
  const txHashString = txHash.toString();
929
991
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
@@ -931,13 +993,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
931
993
  txHash: txHashString,
932
994
  });
933
995
 
934
- if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
935
- this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
936
- return;
937
- }
938
-
939
996
  this.instrumentation.incrementTxReceived(1);
940
- await this.mempools.txPool.addTxs([tx]);
941
997
  }
942
998
 
943
999
  /**
@@ -991,40 +1047,53 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
991
1047
  return { result: TopicValidatorResult.Ignore, obj: attestation };
992
1048
  }
993
1049
 
994
- // Get committee size for the attestation's slot
995
- const slot = attestation.payload.header.slotNumber;
996
- const { committee } = await this.epochCache.getCommittee(slot);
997
- const committeeSize = committee?.length ?? 0;
998
-
999
1050
  // Try to add the attestation: this handles existence check, cap check, and adding in one call
1000
- const { added, alreadyExists } = await this.mempools.attestationPool.tryAddCheckpointAttestation(
1001
- attestation,
1002
- committeeSize,
1003
- );
1051
+ // count is the number of attestations by this signer for this slot (for duplicate detection)
1052
+ const slot = attestation.payload.header.slotNumber;
1053
+ const { added, alreadyExists, count } =
1054
+ await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
1004
1055
 
1005
1056
  this.logger.trace(`Validate propagated checkpoint attestation`, {
1006
1057
  added,
1007
1058
  alreadyExists,
1059
+ count,
1008
1060
  [Attributes.SLOT_NUMBER]: slot.toString(),
1009
1061
  [Attributes.P2P_ID]: peerId.toString(),
1010
1062
  });
1011
1063
 
1012
- // Duplicate attestation received, no need to re-broadcast
1064
+ // Exact same attestation received, no need to re-broadcast
1013
1065
  if (alreadyExists) {
1014
1066
  return { result: TopicValidatorResult.Ignore, obj: attestation };
1015
1067
  }
1016
1068
 
1017
- // Could not add (cap reached), no need to re-broadcast
1069
+ // Could not add (cap reached for signer), no need to re-broadcast
1018
1070
  if (!added) {
1019
- this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
1071
+ this.logger.warn(`Dropping checkpoint attestation due to cap`, {
1020
1072
  slot: slot.toString(),
1021
1073
  archive: attestation.archive.toString(),
1022
1074
  source: peerId.toString(),
1075
+ attester: attestation.getSender()?.toString(),
1076
+ count,
1023
1077
  });
1024
1078
  return { result: TopicValidatorResult.Ignore, obj: attestation };
1025
1079
  }
1026
1080
 
1027
- // Attestation was added successfully
1081
+ // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
1082
+ // count is the number of attestations by this signer for this slot
1083
+ if (count === 2) {
1084
+ const attester = attestation.getSender();
1085
+ if (attester) {
1086
+ this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
1087
+ slot: slot.toString(),
1088
+ archive: attestation.archive.toString(),
1089
+ source: peerId.toString(),
1090
+ attester: attester.toString(),
1091
+ });
1092
+ this.duplicateAttestationCallback?.({ slot, attester });
1093
+ }
1094
+ }
1095
+
1096
+ // Attestation was added successfully - accept it so other nodes can also detect the equivocation
1028
1097
  return { result: TopicValidatorResult.Accept, obj: attestation };
1029
1098
  }
1030
1099
 
@@ -1070,8 +1139,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1070
1139
  }
1071
1140
 
1072
1141
  // Try to add the proposal: this handles existence check, cap check, and adding in one call
1073
- const { added, alreadyExists, totalForPosition } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1074
- const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
1142
+ const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1143
+ const isEquivocated = count !== undefined && count > 1;
1075
1144
 
1076
1145
  // Duplicate proposal received, no need to re-broadcast
1077
1146
  if (alreadyExists) {
@@ -1090,7 +1159,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1090
1159
  this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1091
1160
  ...block.toBlockInfo(),
1092
1161
  indexWithinCheckpoint: block.indexWithinCheckpoint,
1093
- totalForPosition,
1162
+ count,
1094
1163
  proposer: block.getSender()?.toString(),
1095
1164
  source: peerId.toString(),
1096
1165
  });
@@ -1107,7 +1176,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1107
1176
  proposer: proposer?.toString(),
1108
1177
  });
1109
1178
  // Invoke the duplicate callback on the first duplicate spotted only
1110
- if (proposer && totalForPosition === 2) {
1179
+ if (proposer && count === 2) {
1111
1180
  this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
1112
1181
  }
1113
1182
  return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
@@ -1132,14 +1201,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1132
1201
  ...block.toBlockInfo(),
1133
1202
  });
1134
1203
 
1135
- // Mark the txs in this proposal as non-evictable
1136
- await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
1204
+ // Mark the txs in this proposal as protected
1205
+ await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
1137
1206
 
1138
1207
  // Call the block received callback to validate the proposal.
1139
1208
  // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1140
1209
  const isValid = await this.blockReceivedCallback(block, sender);
1141
1210
  if (!isValid) {
1142
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1211
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1143
1212
  }
1144
1213
  }
1145
1214
 
@@ -1224,8 +1293,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1224
1293
  // Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
1225
1294
  const checkpointCore = checkpoint.toCore();
1226
1295
  const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
1227
- const { added, alreadyExists, totalForPosition } = tryAddResult;
1228
- const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
1296
+ const { added, alreadyExists, count } = tryAddResult;
1297
+ const isEquivocated = count !== undefined && count > 1;
1229
1298
 
1230
1299
  // Duplicate proposal received, do not re-broadcast
1231
1300
  if (alreadyExists) {
@@ -1246,7 +1315,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1246
1315
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1247
1316
  this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1248
1317
  ...checkpoint.toCheckpointInfo(),
1249
- totalForPosition,
1318
+ count,
1250
1319
  source: peerId.toString(),
1251
1320
  });
1252
1321
  return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
@@ -1262,7 +1331,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1262
1331
  proposer: proposer?.toString(),
1263
1332
  });
1264
1333
  // Invoke the duplicate callback on the first duplicate spotted only
1265
- if (proposer && totalForPosition === 2) {
1334
+ if (proposer && count === 2) {
1266
1335
  this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
1267
1336
  }
1268
1337
  return {
@@ -1511,43 +1580,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1511
1580
  }
1512
1581
 
1513
1582
  protected createRequestedTxValidator(): TxValidator {
1514
- return createTxReqRespValidator(this.proofVerifier, {
1583
+ return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
1515
1584
  l1ChainId: this.config.l1ChainId,
1516
1585
  rollupVersion: this.config.rollupVersion,
1517
1586
  });
1518
1587
  }
1519
1588
 
1520
- @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
1521
- [Attributes.TX_HASH]: tx.getTxHash().toString(),
1522
- }))
1523
- private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
1524
- const currentBlockNumber = await this.archiver.getBlockNumber();
1525
-
1526
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1527
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1528
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1529
-
1530
- for (const validator of messageValidators) {
1531
- const outcome = await this.runValidations(tx, validator);
1532
-
1533
- if (outcome.allPassed) {
1534
- continue;
1535
- }
1536
- const { name } = outcome.failure;
1537
- let { severity } = outcome.failure;
1538
-
1539
- // Double spend validator has a special case handler
1540
- if (name === 'doubleSpendValidator') {
1541
- const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
1542
- severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1543
- }
1544
-
1545
- this.peerManager.penalizePeer(peerId, severity);
1546
- return false;
1547
- }
1548
- return true;
1549
- }
1550
-
1551
1589
  private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1552
1590
  if (blockNumber === this.feesCache?.blockNumber) {
1553
1591
  return this.feesCache.gasFees;
@@ -1575,60 +1613,62 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1575
1613
  };
1576
1614
  }
1577
1615
 
1578
- public async validate(txs: Tx[]): Promise<void> {
1579
- const currentBlockNumber = await this.archiver.getBlockNumber();
1580
-
1581
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1582
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1583
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1616
+ public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
1617
+ const validator = createTxValidatorForBlockProposalReceivedTxs(
1618
+ this.proofVerifier,
1619
+ { l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
1620
+ this.logger.getBindings(),
1621
+ );
1584
1622
 
1585
- await Promise.all(
1623
+ const results = await Promise.all(
1586
1624
  txs.map(async tx => {
1587
- for (const validator of messageValidators) {
1588
- const outcome = await this.runValidations(tx, validator);
1589
- if (!outcome.allPassed) {
1590
- throw new Error('Invalid tx detected', { cause: { outcome } });
1591
- }
1592
- }
1625
+ const result = await validator.validateTx(tx);
1626
+ return result.result !== 'invalid';
1593
1627
  }),
1594
1628
  );
1629
+ if (results.some(value => value === false)) {
1630
+ throw new Error('Invalid tx detected');
1631
+ }
1595
1632
  }
1596
1633
 
1597
- /**
1598
- * Create message validators for the given block number and timestamp.
1599
- *
1600
- * Each validator is a pair of a validator and a severity.
1601
- * If a validator fails, the peer is penalized with the severity of the validator.
1602
- *
1603
- * @param currentBlockNumber - The current synced block number.
1604
- * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
1605
- * @returns The message validators.
1606
- */
1607
- private async createMessageValidators(
1634
+ /** Creates the first stage (fast) validators for gossiped transactions. */
1635
+ protected async createFirstStageMessageValidators(
1608
1636
  currentBlockNumber: BlockNumber,
1609
1637
  nextSlotTimestamp: UInt64,
1610
- ): Promise<Record<string, MessageValidator>[]> {
1638
+ ): Promise<Record<string, TransactionValidator>> {
1611
1639
  const gasFees = await this.getGasFees(currentBlockNumber);
1612
- const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1613
-
1614
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1615
-
1616
- return createTxMessageValidators(
1640
+ const allowedInSetup = [
1641
+ ...(await getDefaultAllowedSetupFunctions()),
1642
+ ...(this.config.txPublicSetupAllowListExtend ?? []),
1643
+ ];
1644
+ const blockNumber = BlockNumber(currentBlockNumber + 1);
1645
+ const l1Constants = await this.archiver.getL1Constants();
1646
+
1647
+ return createFirstStageTxValidationsForGossipedTransactions(
1617
1648
  nextSlotTimestamp,
1618
- blockNumberInWhichTheTxIsConsideredToBeIncluded,
1649
+ blockNumber,
1619
1650
  this.worldStateSynchronizer,
1620
1651
  gasFees,
1621
1652
  this.config.l1ChainId,
1622
1653
  this.config.rollupVersion,
1623
1654
  protocolContractsHash,
1624
1655
  this.archiver,
1625
- this.proofVerifier,
1626
1656
  !this.config.disableTransactions,
1627
1657
  allowedInSetup,
1628
1658
  this.logger.getBindings(),
1659
+ {
1660
+ rollupManaLimit: l1Constants.rollupManaLimit,
1661
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1662
+ maxBlockDAGas: this.config.validateMaxDABlockGas,
1663
+ },
1629
1664
  );
1630
1665
  }
1631
1666
 
1667
+ /** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
1668
+ protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
1669
+ return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
1670
+ }
1671
+
1632
1672
  /**
1633
1673
  * Run validations on a tx.
1634
1674
  * @param tx - The tx to validate.
@@ -1637,7 +1677,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1637
1677
  */
1638
1678
  private async runValidations(
1639
1679
  tx: Tx,
1640
- messageValidators: Record<string, MessageValidator>,
1680
+ messageValidators: Record<string, TransactionValidator>,
1641
1681
  ): Promise<ValidationOutcome> {
1642
1682
  const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
1643
1683
  const { result } = await validator.validateTx(tx);
@@ -1646,8 +1686,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1646
1686
 
1647
1687
  // A promise that resolves when all validations have been run
1648
1688
  const allValidations = await Promise.all(validationPromises);
1649
- const failed = allValidations.find(x => !x.isValid);
1650
- if (failed) {
1689
+ const failures = allValidations.filter(x => !x.isValid);
1690
+ if (failures.length > 0) {
1691
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1692
+ const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
1651
1693
  return {
1652
1694
  allPassed: false,
1653
1695
  failure: {