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

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 (423) 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 +52 -14
  5. package/dest/client/interface.d.ts +47 -34
  6. package/dest/client/interface.d.ts.map +1 -1
  7. package/dest/client/p2p_client.d.ts +39 -51
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +164 -224
  10. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +20 -10
  11. package/dest/config.d.ts +52 -16
  12. package/dest/config.d.ts.map +1 -1
  13. package/dest/config.js +100 -37
  14. package/dest/errors/p2p-service.error.d.ts +9 -0
  15. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  16. package/dest/errors/p2p-service.error.js +10 -0
  17. package/dest/errors/tx-pool.error.d.ts +8 -0
  18. package/dest/errors/tx-pool.error.d.ts.map +1 -0
  19. package/dest/errors/tx-pool.error.js +9 -0
  20. package/dest/index.d.ts +2 -2
  21. package/dest/index.d.ts.map +1 -1
  22. package/dest/index.js +1 -1
  23. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +21 -12
  24. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool.js +75 -40
  26. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  28. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +57 -57
  29. package/dest/mem_pools/attestation_pool/index.d.ts +2 -2
  30. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  31. package/dest/mem_pools/attestation_pool/index.js +1 -1
  32. package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
  33. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  34. package/dest/mem_pools/attestation_pool/mocks.js +2 -2
  35. package/dest/mem_pools/index.d.ts +2 -2
  36. package/dest/mem_pools/index.d.ts.map +1 -1
  37. package/dest/mem_pools/instrumentation.d.ts +4 -2
  38. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  39. package/dest/mem_pools/instrumentation.js +16 -14
  40. package/dest/mem_pools/interface.d.ts +3 -3
  41. package/dest/mem_pools/interface.d.ts.map +1 -1
  42. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
  43. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
  44. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
  45. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
  46. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
  48. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  49. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +7 -3
  51. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
  52. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
  54. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
  55. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  56. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
  57. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +54 -5
  58. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
  60. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
  61. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +7 -5
  62. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
  63. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  64. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
  65. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
  66. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  67. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
  68. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
  69. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  70. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
  71. package/dest/mem_pools/tx_pool_v2/index.d.ts +3 -2
  72. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
  73. package/dest/mem_pools/tx_pool_v2/index.js +2 -1
  74. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  75. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  76. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  77. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +30 -12
  78. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  79. package/dest/mem_pools/tx_pool_v2/interfaces.js +5 -1
  80. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +78 -15
  81. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  82. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +144 -19
  83. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
  84. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  85. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +50 -45
  86. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -5
  87. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  88. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +17 -6
  89. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +14 -5
  90. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  91. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +364 -189
  92. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -1
  93. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  94. package/dest/msg_validators/attestation_validator/attestation_validator.js +5 -4
  95. package/dest/msg_validators/clock_tolerance.d.ts +1 -1
  96. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  97. package/dest/msg_validators/clock_tolerance.js +4 -3
  98. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
  99. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  100. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
  101. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
  102. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  103. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
  104. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
  105. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  106. package/dest/msg_validators/proposal_validator/proposal_validator.js +53 -41
  107. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +4 -4
  108. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  109. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
  110. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  111. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  112. package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
  113. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  114. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  115. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  116. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +16 -3
  117. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  118. package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
  119. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  120. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  121. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  122. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  123. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  124. package/dest/msg_validators/tx_validator/data_validator.js +35 -2
  125. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
  126. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  127. package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
  128. package/dest/msg_validators/tx_validator/factory.d.ts +133 -6
  129. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  130. package/dest/msg_validators/tx_validator/factory.js +247 -60
  131. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  132. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  133. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  134. package/dest/msg_validators/tx_validator/gas_validator.d.ts +67 -3
  135. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  136. package/dest/msg_validators/tx_validator/gas_validator.js +104 -37
  137. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  138. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  139. package/dest/msg_validators/tx_validator/index.js +2 -0
  140. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  141. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  142. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  143. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  144. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  145. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  146. package/dest/msg_validators/tx_validator/phases_validator.d.ts +22 -2
  147. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  148. package/dest/msg_validators/tx_validator/phases_validator.js +72 -24
  149. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
  150. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  151. package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
  152. package/dest/services/dummy_service.d.ts +12 -6
  153. package/dest/services/dummy_service.d.ts.map +1 -1
  154. package/dest/services/dummy_service.js +12 -5
  155. package/dest/services/encoding.d.ts +7 -3
  156. package/dest/services/encoding.d.ts.map +1 -1
  157. package/dest/services/encoding.js +18 -11
  158. package/dest/services/gossipsub/topic_score_params.d.ts +18 -6
  159. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  160. package/dest/services/gossipsub/topic_score_params.js +32 -10
  161. package/dest/services/libp2p/libp2p_service.d.ts +37 -23
  162. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  163. package/dest/services/libp2p/libp2p_service.js +274 -173
  164. package/dest/services/peer-manager/metrics.d.ts +3 -1
  165. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  166. package/dest/services/peer-manager/metrics.js +6 -0
  167. package/dest/services/peer-manager/peer_manager.d.ts +6 -2
  168. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  169. package/dest/services/peer-manager/peer_manager.js +24 -9
  170. package/dest/services/peer-manager/peer_scoring.d.ts +5 -2
  171. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  172. package/dest/services/peer-manager/peer_scoring.js +28 -10
  173. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +12 -8
  174. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  175. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +83 -106
  176. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +4 -7
  177. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  178. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +11 -13
  179. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  180. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +31 -46
  181. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +19 -11
  182. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  183. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +52 -15
  184. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
  185. package/dest/services/reqresp/interface.d.ts +10 -1
  186. package/dest/services/reqresp/interface.d.ts.map +1 -1
  187. package/dest/services/reqresp/interface.js +15 -1
  188. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +3 -3
  189. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  190. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
  191. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  192. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +15 -0
  193. package/dest/services/reqresp/protocols/tx.d.ts +7 -1
  194. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  195. package/dest/services/reqresp/protocols/tx.js +20 -0
  196. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  197. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  198. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  199. package/dest/services/reqresp/reqresp.d.ts +1 -1
  200. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  201. package/dest/services/reqresp/reqresp.js +30 -14
  202. package/dest/services/service.d.ts +26 -4
  203. package/dest/services/service.d.ts.map +1 -1
  204. package/dest/services/tx_collection/config.d.ts +19 -1
  205. package/dest/services/tx_collection/config.d.ts.map +1 -1
  206. package/dest/services/tx_collection/config.js +46 -0
  207. package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -4
  208. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  209. package/dest/services/tx_collection/fast_tx_collection.js +80 -76
  210. package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
  211. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
  212. package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
  213. package/dest/services/tx_collection/file_store_tx_source.d.ts +38 -0
  214. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
  215. package/dest/services/tx_collection/file_store_tx_source.js +100 -0
  216. package/dest/services/tx_collection/index.d.ts +2 -1
  217. package/dest/services/tx_collection/index.d.ts.map +1 -1
  218. package/dest/services/tx_collection/index.js +1 -0
  219. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  220. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  221. package/dest/services/tx_collection/instrumentation.js +2 -1
  222. package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -7
  223. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  224. package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
  225. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  226. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  227. package/dest/services/tx_collection/request_tracker.js +84 -0
  228. package/dest/services/tx_collection/slow_tx_collection.d.ts +7 -3
  229. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  230. package/dest/services/tx_collection/slow_tx_collection.js +60 -26
  231. package/dest/services/tx_collection/tx_collection.d.ts +23 -13
  232. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  233. package/dest/services/tx_collection/tx_collection.js +75 -3
  234. package/dest/services/tx_collection/tx_collection_sink.d.ts +18 -8
  235. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  236. package/dest/services/tx_collection/tx_collection_sink.js +26 -29
  237. package/dest/services/tx_collection/tx_source.d.ts +13 -7
  238. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  239. package/dest/services/tx_collection/tx_source.js +26 -7
  240. package/dest/services/tx_file_store/config.d.ts +1 -3
  241. package/dest/services/tx_file_store/config.d.ts.map +1 -1
  242. package/dest/services/tx_file_store/config.js +0 -4
  243. package/dest/services/tx_file_store/tx_file_store.d.ts +4 -3
  244. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  245. package/dest/services/tx_file_store/tx_file_store.js +9 -6
  246. package/dest/services/tx_provider.d.ts +4 -4
  247. package/dest/services/tx_provider.d.ts.map +1 -1
  248. package/dest/services/tx_provider.js +9 -8
  249. package/dest/test-helpers/make-test-p2p-clients.d.ts +7 -8
  250. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  251. package/dest/test-helpers/make-test-p2p-clients.js +1 -2
  252. package/dest/test-helpers/mock-pubsub.d.ts +30 -4
  253. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  254. package/dest/test-helpers/mock-pubsub.js +105 -4
  255. package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
  256. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  257. package/dest/test-helpers/reqresp-nodes.js +2 -2
  258. package/dest/test-helpers/testbench-utils.d.ts +35 -24
  259. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  260. package/dest/test-helpers/testbench-utils.js +115 -38
  261. package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
  262. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  263. package/dest/testbench/p2p_client_testbench_worker.js +57 -27
  264. package/dest/testbench/worker_client_manager.d.ts +3 -1
  265. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  266. package/dest/testbench/worker_client_manager.js +6 -3
  267. package/dest/util.d.ts +3 -3
  268. package/dest/util.d.ts.map +1 -1
  269. package/package.json +14 -14
  270. package/src/client/factory.ts +102 -25
  271. package/src/client/interface.ts +52 -34
  272. package/src/client/p2p_client.ts +190 -266
  273. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +33 -14
  274. package/src/config.ts +149 -43
  275. package/src/errors/p2p-service.error.ts +11 -0
  276. package/src/errors/tx-pool.error.ts +12 -0
  277. package/src/index.ts +1 -1
  278. package/src/mem_pools/attestation_pool/attestation_pool.ts +104 -50
  279. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +61 -57
  280. package/src/mem_pools/attestation_pool/index.ts +3 -3
  281. package/src/mem_pools/attestation_pool/mocks.ts +2 -1
  282. package/src/mem_pools/index.ts +1 -1
  283. package/src/mem_pools/instrumentation.ts +17 -13
  284. package/src/mem_pools/interface.ts +2 -2
  285. package/src/mem_pools/tx_pool_v2/README.md +85 -11
  286. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  287. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
  288. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +7 -3
  289. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
  290. package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
  291. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +59 -4
  292. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
  293. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
  294. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
  295. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
  296. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
  297. package/src/mem_pools/tx_pool_v2/index.ts +2 -1
  298. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  299. package/src/mem_pools/tx_pool_v2/interfaces.ts +32 -12
  300. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +209 -27
  301. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +58 -45
  302. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +34 -8
  303. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +410 -187
  304. package/src/msg_validators/attestation_validator/README.md +49 -0
  305. package/src/msg_validators/attestation_validator/attestation_validator.ts +5 -4
  306. package/src/msg_validators/clock_tolerance.ts +4 -3
  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 +69 -45
  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/contract_instance_validator.ts +56 -0
  317. package/src/msg_validators/tx_validator/data_validator.ts +42 -1
  318. package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
  319. package/src/msg_validators/tx_validator/factory.ts +394 -78
  320. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  321. package/src/msg_validators/tx_validator/gas_validator.ts +123 -27
  322. package/src/msg_validators/tx_validator/index.ts +2 -0
  323. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  324. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  325. package/src/msg_validators/tx_validator/phases_validator.ts +82 -27
  326. package/src/msg_validators/tx_validator/timestamp_validator.ts +23 -18
  327. package/src/services/dummy_service.ts +18 -7
  328. package/src/services/encoding.ts +18 -10
  329. package/src/services/gossipsub/README.md +29 -14
  330. package/src/services/gossipsub/topic_score_params.ts +49 -13
  331. package/src/services/libp2p/libp2p_service.ts +288 -198
  332. package/src/services/peer-manager/metrics.ts +7 -0
  333. package/src/services/peer-manager/peer_manager.ts +28 -9
  334. package/src/services/peer-manager/peer_scoring.ts +21 -5
  335. package/src/services/reqresp/README.md +229 -0
  336. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  337. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +79 -112
  338. package/src/services/reqresp/batch-tx-requester/interface.ts +3 -6
  339. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +30 -71
  340. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +68 -24
  341. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
  342. package/src/services/reqresp/interface.ts +26 -1
  343. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +2 -2
  344. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
  345. package/src/services/reqresp/protocols/tx.ts +22 -0
  346. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  347. package/src/services/reqresp/reqresp.ts +35 -15
  348. package/src/services/service.ts +37 -3
  349. package/src/services/tx_collection/config.ts +68 -0
  350. package/src/services/tx_collection/fast_tx_collection.ts +83 -76
  351. package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
  352. package/src/services/tx_collection/file_store_tx_source.ts +129 -0
  353. package/src/services/tx_collection/index.ts +1 -0
  354. package/src/services/tx_collection/instrumentation.ts +7 -1
  355. package/src/services/tx_collection/proposal_tx_collector.ts +9 -13
  356. package/src/services/tx_collection/request_tracker.ts +127 -0
  357. package/src/services/tx_collection/slow_tx_collection.ts +66 -33
  358. package/src/services/tx_collection/tx_collection.ts +114 -19
  359. package/src/services/tx_collection/tx_collection_sink.ts +30 -34
  360. package/src/services/tx_collection/tx_source.ts +28 -8
  361. package/src/services/tx_file_store/config.ts +0 -6
  362. package/src/services/tx_file_store/tx_file_store.ts +10 -8
  363. package/src/services/tx_provider.ts +10 -9
  364. package/src/test-helpers/make-test-p2p-clients.ts +4 -6
  365. package/src/test-helpers/mock-pubsub.ts +146 -9
  366. package/src/test-helpers/reqresp-nodes.ts +3 -6
  367. package/src/test-helpers/testbench-utils.ts +137 -43
  368. package/src/testbench/p2p_client_testbench_worker.ts +63 -30
  369. package/src/testbench/worker_client_manager.ts +13 -6
  370. package/src/util.ts +8 -2
  371. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  372. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  373. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  374. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  375. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  376. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  377. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  378. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  379. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  380. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  381. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  382. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
  383. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  384. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  385. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  386. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  387. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  388. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  389. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  390. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  391. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  392. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  393. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  394. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  395. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  396. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  397. package/dest/mem_pools/tx_pool/index.js +0 -2
  398. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  399. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  400. package/dest/mem_pools/tx_pool/priority.js +0 -15
  401. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  402. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  403. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  404. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  405. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  406. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
  407. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
  408. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  409. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
  410. package/src/mem_pools/tx_pool/README.md +0 -270
  411. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  412. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  413. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  414. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
  415. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  416. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  417. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  418. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  419. package/src/mem_pools/tx_pool/index.ts +0 -2
  420. package/src/mem_pools/tx_pool/priority.ts +0 -20
  421. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  422. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
  423. 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,12 @@ import {
17
17
  CheckpointProposal,
18
18
  type CheckpointProposalCore,
19
19
  type Gossipable,
20
- P2PClientType,
21
20
  P2PMessage,
22
- type ValidationResult as P2PValidationResult,
23
21
  PeerErrorSeverity,
22
+ PeerErrorSeverityByHarshness,
24
23
  TopicType,
25
24
  createTopicString,
26
- getTopicsForClientAndConfig,
25
+ getTopicsForConfig,
27
26
  metricsTopicStrToLabels,
28
27
  } from '@aztec/stdlib/p2p';
29
28
  import { MerkleTreeId } from '@aztec/stdlib/trees';
@@ -59,6 +58,7 @@ import { ENR } from '@nethermindeth/enr';
59
58
  import { createLibp2p } from 'libp2p';
60
59
 
61
60
  import type { P2PConfig } from '../../config.js';
61
+ import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
62
62
  import type { MemPools } from '../../mem_pools/interface.js';
63
63
  import {
64
64
  BlockProposalValidator,
@@ -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';
@@ -88,6 +90,9 @@ import { PeerScoring } from '../peer-manager/peer_scoring.js';
88
90
  import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
89
91
  import type { P2PReqRespConfig } from '../reqresp/config.js';
90
92
  import {
93
+ AuthRequest,
94
+ BlockTxsRequest,
95
+ BlockTxsResponse,
91
96
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
92
97
  type ReqRespInterface,
93
98
  type ReqRespResponse,
@@ -95,14 +100,9 @@ import {
95
100
  type ReqRespSubProtocolHandler,
96
101
  type ReqRespSubProtocolHandlers,
97
102
  type ReqRespSubProtocolValidators,
103
+ StatusMessage,
98
104
  type SubProtocolMap,
99
105
  ValidationError,
100
- } from '../reqresp/index.js';
101
- import {
102
- AuthRequest,
103
- BlockTxsRequest,
104
- BlockTxsResponse,
105
- StatusMessage,
106
106
  pingHandler,
107
107
  reqGoodbyeHandler,
108
108
  reqRespBlockHandler,
@@ -114,6 +114,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
114
114
  import type {
115
115
  P2PBlockReceivedCallback,
116
116
  P2PCheckpointReceivedCallback,
117
+ P2PDuplicateAttestationCallback,
117
118
  P2PService,
118
119
  PeerDiscoveryService,
119
120
  } from '../service.js';
@@ -130,12 +131,12 @@ type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: Vali
130
131
  // REFACTOR: Unify with the type above
131
132
  type ReceivedMessageValidationResult<T, M = undefined> =
132
133
  | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
133
- | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
134
+ | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M; severity: PeerErrorSeverity };
134
135
 
135
136
  /**
136
137
  * Lib P2P implementation of the P2PService interface.
137
138
  */
138
- export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
139
+ export class LibP2PService extends WithTracer implements P2PService {
139
140
  private discoveryRunningPromise?: RunningPromise;
140
141
  private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
141
142
 
@@ -156,6 +157,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
156
157
  type: 'checkpoint' | 'block';
157
158
  }) => void;
158
159
 
160
+ /** Callback invoked when a duplicate attestation is detected (triggers slashing). */
161
+ private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
162
+
159
163
  /**
160
164
  * Callback for when a block is received from a peer.
161
165
  * @param block - The block received from the peer.
@@ -168,7 +172,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
168
172
  * @param checkpoint - The checkpoint proposal received from the peer.
169
173
  * @returns The attestations for the checkpoint, if any.
170
174
  */
171
- private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
175
+ private allNodesCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
176
+ /**
177
+ * Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
178
+ * @param checkpoint - The checkpoint proposal received from the peer.
179
+ * @returns The attestations for the checkpoint, if any.
180
+ */
181
+ private validatorCheckpointReceivedCallback: P2PCheckpointReceivedCallback;
172
182
 
173
183
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
174
184
 
@@ -179,7 +189,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
179
189
  protected logger: Logger;
180
190
 
181
191
  constructor(
182
- private clientType: T,
183
192
  private config: P2PConfig,
184
193
  protected node: PubSubLibp2p,
185
194
  private peerDiscoveryService: PeerDiscoveryService,
@@ -221,10 +230,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
221
230
  this.protocolVersion,
222
231
  );
223
232
 
224
- this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
225
- this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
233
+ const proposalValidatorOpts = {
226
234
  txsPermitted: !config.disableTransactions,
227
- });
235
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
236
+ };
237
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
238
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
228
239
  this.checkpointAttestationValidator = config.fishermanMode
229
240
  ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
230
241
  : new CheckpointAttestationValidator(epochCache);
@@ -232,19 +243,22 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
232
243
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
233
244
 
234
245
  this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
235
- this.logger.debug(
236
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
246
+ this.logger.warn(
247
+ `Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`,
237
248
  { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
238
249
  );
239
- return false;
250
+ return true;
240
251
  };
241
252
 
242
- this.checkpointReceivedCallback = (
243
- checkpoint: CheckpointProposalCore,
253
+ this.allNodesCheckpointReceivedCallback = (
254
+ _checkpoint: CheckpointProposalCore,
255
+ ): Promise<CheckpointAttestation[] | undefined> => {
256
+ throw new CheckpointProposalReceivedCallbackNotRegisteredError();
257
+ };
258
+
259
+ this.validatorCheckpointReceivedCallback = (
260
+ _checkpoint: CheckpointProposalCore,
244
261
  ): Promise<CheckpointAttestation[] | undefined> => {
245
- this.logger.debug(
246
- `Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
247
- );
248
262
  return Promise.resolve(undefined);
249
263
  };
250
264
  }
@@ -259,8 +273,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
259
273
  * @param txPool - The transaction pool to be accessed by the service.
260
274
  * @returns The new service.
261
275
  */
262
- public static async new<T extends P2PClientType>(
263
- clientType: T,
276
+ public static async new(
264
277
  config: P2PConfig,
265
278
  peerId: PeerId,
266
279
  deps: {
@@ -338,6 +351,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
338
351
  heartbeatIntervalMs: config.gossipsubInterval,
339
352
  targetCommitteeSize: l1Constants.targetCommitteeSize,
340
353
  blockDurationMs: config.blockDurationMs,
354
+ expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
341
355
  });
342
356
 
343
357
  const node = await createLibp2p({
@@ -471,7 +485,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
471
485
  peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
472
486
 
473
487
  return new LibP2PService(
474
- clientType,
475
488
  config,
476
489
  node,
477
490
  peerDiscoveryService,
@@ -545,7 +558,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
545
558
  await this.node.start();
546
559
 
547
560
  // Subscribe to standard GossipSub topics by default
548
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
561
+ for (const topic of getTopicsForConfig(this.config.disableTransactions)) {
549
562
  this.subscribeToTopic(this.topicStrings[topic]);
550
563
  }
551
564
 
@@ -611,6 +624,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
611
624
  return this.peerManager.getPeers(includePending);
612
625
  }
613
626
 
627
+ public getGossipMeshPeerCount(topicType: TopicType): number {
628
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
629
+ }
630
+
614
631
  private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
615
632
  this.logger.trace(`Received PUBSUB message.`);
616
633
 
@@ -659,8 +676,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
659
676
  this.blockReceivedCallback = callback;
660
677
  }
661
678
 
662
- public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
663
- this.checkpointReceivedCallback = callback;
679
+ public registerValidatorCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
680
+ this.validatorCheckpointReceivedCallback = callback;
681
+ }
682
+
683
+ public registerAllNodesCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
684
+ this.allNodesCheckpointReceivedCallback = callback;
685
+ }
686
+
687
+ public async notifyOwnCheckpointProposal(checkpoint: CheckpointProposalCore): Promise<void> {
688
+ await this.allNodesCheckpointReceivedCallback(checkpoint, this.node.peerId);
664
689
  }
665
690
 
666
691
  /**
@@ -673,6 +698,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
673
698
  this.duplicateProposalCallback = callback;
674
699
  }
675
700
 
701
+ /**
702
+ * Registers a callback to be invoked when a duplicate attestation is detected.
703
+ * A validator signing attestations for different proposals at the same slot.
704
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
705
+ */
706
+ public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
707
+ this.duplicateAttestationCallback = callback;
708
+ }
709
+
676
710
  /**
677
711
  * Subscribes to a topic.
678
712
  * @param topic - The topic to subscribe to.
@@ -737,6 +771,9 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
737
771
  if (!validator || !validator.addMessage(msgId)) {
738
772
  this.instrumentation.incMessagePrevalidationStatus(false, topicType);
739
773
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
774
+ if (topicType === TopicType.tx) {
775
+ this.logger.verbose(`Ignoring already-seen tx gossip message`, { msgId, source: source.toString() });
776
+ }
740
777
  return { result: false, topicType };
741
778
  }
742
779
 
@@ -801,9 +838,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
801
838
  if (msg.topic === this.topicStrings[TopicType.tx]) {
802
839
  await this.handleGossipedTx(p2pMessage.payload, msgId, source);
803
840
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
804
- if (this.clientType === P2PClientType.Full) {
805
- await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
806
- }
841
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
807
842
  } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
808
843
  await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
809
844
  } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
@@ -865,45 +900,128 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
865
900
  source: PeerId,
866
901
  topicType: TopicType,
867
902
  ): Promise<ReceivedMessageValidationResult<T, M>> {
868
- let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
903
+ // Default to reject result with a penalty if validation function throws an error
904
+ let resultAndObj: ReceivedMessageValidationResult<T, M> = {
905
+ result: TopicValidatorResult.Reject,
906
+ severity: PeerErrorSeverity.MidToleranceError,
907
+ };
869
908
  const timer = new Timer();
870
909
  try {
871
910
  resultAndObj = await validationFunc();
872
911
  } catch (err) {
873
- this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
874
- this.logger.error(`Error deserializing and validating gossipsub message`, err, {
875
- msgId,
876
- source: source.toString(),
877
- topicType,
878
- });
912
+ this.logger.error(`Error validating gossipsub message`, err, { msgId, source: source.toString(), topicType });
879
913
  }
880
914
 
881
915
  if (resultAndObj.result === TopicValidatorResult.Accept) {
916
+ this.logger.debug(`Message ${topicType} accepted by validator`, { msgId, source: source.toString(), topicType });
882
917
  this.instrumentation.recordMessageValidation(topicType, timer);
918
+ } else if (resultAndObj.result === TopicValidatorResult.Reject) {
919
+ this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
920
+ msgId,
921
+ source: source.toString(),
922
+ topicType,
923
+ severity: resultAndObj.severity,
924
+ });
925
+ this.peerManager.penalizePeer(source, resultAndObj.severity);
926
+ } else {
927
+ this.logger.trace(`Message ${topicType} ignored by validator`, { msgId, source: source.toString(), topicType });
883
928
  }
884
929
 
885
930
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
886
931
  return resultAndObj;
887
932
  }
888
933
 
934
+ private tryDeserialize<T>(deserializeFunc: () => T, msgId: string, source: PeerId): T | undefined {
935
+ try {
936
+ return deserializeFunc();
937
+ } catch (err) {
938
+ this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
939
+ err,
940
+ msgId,
941
+ source: source.toString(),
942
+ });
943
+ return undefined;
944
+ }
945
+ }
946
+
889
947
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
890
948
  const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
891
- const tx = Tx.fromBuffer(payloadData);
892
- const isValid = await this.validatePropagatedTx(tx, source);
893
- const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
949
+ const tx = this.tryDeserialize(() => Tx.fromBuffer(payloadData), msgId, source);
950
+ if (!tx) {
951
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.LowToleranceError };
952
+ }
953
+
954
+ const currentBlockNumber = await this.archiver.getBlockNumber();
955
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
956
+
957
+ // Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
958
+ const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
959
+ const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
960
+ if (!firstStageOutcome.allPassed) {
961
+ const { name } = firstStageOutcome.failure;
962
+ let { severity } = firstStageOutcome.failure;
963
+
964
+ // Double spend validator has a special case handler. We perform more detailed examination
965
+ // as to how recently the nullifier was entered into the tree and if the transaction should
966
+ // have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
967
+ if (name === 'doubleSpendValidator') {
968
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1);
969
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
970
+ }
971
+
972
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
973
+ validator: name,
974
+ severity,
975
+ source: source.toString(),
976
+ });
977
+ return { result: TopicValidatorResult.Reject, severity };
978
+ }
979
+
980
+ // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
981
+ const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
982
+ if (canAdd === 'ignored') {
983
+ this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
984
+ source: source.toString(),
985
+ });
986
+ return { result: TopicValidatorResult.Ignore, obj: tx };
987
+ }
988
+
989
+ // Stage 2: expensive proof verification
990
+ const secondStageValidators = this.createSecondStageMessageValidators();
991
+ const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
992
+ if (!secondStageOutcome.allPassed) {
993
+ const { severity, name } = secondStageOutcome.failure;
994
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
995
+ validator: name,
996
+ severity,
997
+ source: source.toString(),
998
+ });
999
+ return { result: TopicValidatorResult.Reject, severity };
1000
+ }
894
1001
 
895
- this.logger.trace(`Validate propagated tx`, {
896
- isValid,
897
- exists,
1002
+ // Pool add: persist the tx
1003
+ const txHash = tx.getTxHash();
1004
+ const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
1005
+
1006
+ const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
1007
+ const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
1008
+
1009
+ this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
1010
+ wasAccepted,
1011
+ wasIgnored,
898
1012
  [Attributes.P2P_ID]: source.toString(),
899
1013
  });
900
1014
 
901
- if (!isValid) {
902
- return { result: TopicValidatorResult.Reject };
903
- } else if (exists) {
1015
+ if (wasAccepted) {
1016
+ return { result: TopicValidatorResult.Accept, obj: tx };
1017
+ } else if (wasIgnored) {
904
1018
  return { result: TopicValidatorResult.Ignore, obj: tx };
905
1019
  } else {
906
- return { result: TopicValidatorResult.Accept, obj: tx };
1020
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
1021
+ source: source.toString(),
1022
+ txHash: txHash.toString(),
1023
+ });
1024
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
907
1025
  }
908
1026
  };
909
1027
 
@@ -912,6 +1030,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
912
1030
  return;
913
1031
  }
914
1032
 
1033
+ // Tx was accepted into pool and will be propagated - just log and record metrics
915
1034
  const txHash = tx.getTxHash();
916
1035
  const txHashString = txHash.toString();
917
1036
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
@@ -919,13 +1038,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
919
1038
  txHash: txHashString,
920
1039
  });
921
1040
 
922
- if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
923
- this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
924
- return;
925
- }
926
-
927
1041
  this.instrumentation.incrementTxReceived(1);
928
- await this.mempools.txPool.addTxs([tx]);
929
1042
  }
930
1043
 
931
1044
  /**
@@ -938,7 +1051,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
938
1051
  source: PeerId,
939
1052
  ): Promise<void> {
940
1053
  const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
941
- () => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
1054
+ () => {
1055
+ const attestation = this.tryDeserialize(() => CheckpointAttestation.fromBuffer(payloadData), msgId, source);
1056
+ if (!attestation) {
1057
+ return Promise.resolve({
1058
+ result: TopicValidatorResult.Reject,
1059
+ severity: PeerErrorSeverity.LowToleranceError,
1060
+ });
1061
+ }
1062
+ return this.validateAndStoreCheckpointAttestation(source, attestation);
1063
+ },
942
1064
  msgId,
943
1065
  source,
944
1066
  TopicType.checkpoint_attestation,
@@ -971,48 +1093,60 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
971
1093
 
972
1094
  if (validationResult.result === 'reject') {
973
1095
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
974
- this.peerManager.penalizePeer(peerId, validationResult.severity);
975
- return { result: TopicValidatorResult.Reject };
1096
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
976
1097
  }
977
1098
 
978
1099
  if (validationResult.result === 'ignore') {
979
1100
  return { result: TopicValidatorResult.Ignore, obj: attestation };
980
1101
  }
981
1102
 
982
- // Get committee size for the attestation's slot
983
- const slot = attestation.payload.header.slotNumber;
984
- const { committee } = await this.epochCache.getCommittee(slot);
985
- const committeeSize = committee?.length ?? 0;
986
-
987
1103
  // Try to add the attestation: this handles existence check, cap check, and adding in one call
988
- const { added, alreadyExists } = await this.mempools.attestationPool.tryAddCheckpointAttestation(
989
- attestation,
990
- committeeSize,
991
- );
1104
+ // count is the number of attestations by this signer for this slot (for duplicate detection)
1105
+ const slot = attestation.payload.header.slotNumber;
1106
+ const { added, alreadyExists, count } =
1107
+ await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
992
1108
 
993
1109
  this.logger.trace(`Validate propagated checkpoint attestation`, {
994
1110
  added,
995
1111
  alreadyExists,
1112
+ count,
996
1113
  [Attributes.SLOT_NUMBER]: slot.toString(),
997
1114
  [Attributes.P2P_ID]: peerId.toString(),
998
1115
  });
999
1116
 
1000
- // Duplicate attestation received, no need to re-broadcast
1117
+ // Exact same attestation received, no need to re-broadcast
1001
1118
  if (alreadyExists) {
1002
1119
  return { result: TopicValidatorResult.Ignore, obj: attestation };
1003
1120
  }
1004
1121
 
1005
- // Could not add (cap reached), no need to re-broadcast
1122
+ // Could not add (cap reached for signer), penalize and do not re-broadcast
1006
1123
  if (!added) {
1007
- this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
1124
+ this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
1008
1125
  slot: slot.toString(),
1009
1126
  archive: attestation.archive.toString(),
1010
1127
  source: peerId.toString(),
1128
+ attester: attestation.getSender()?.toString(),
1129
+ count,
1011
1130
  });
1012
- return { result: TopicValidatorResult.Ignore, obj: attestation };
1131
+ return { result: TopicValidatorResult.Reject, severity: PeerErrorSeverity.HighToleranceError };
1132
+ }
1133
+
1134
+ // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
1135
+ // count is the number of attestations by this signer for this slot
1136
+ if (count === 2) {
1137
+ const attester = attestation.getSender();
1138
+ if (attester) {
1139
+ this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
1140
+ slot: slot.toString(),
1141
+ archive: attestation.archive.toString(),
1142
+ source: peerId.toString(),
1143
+ attester: attester.toString(),
1144
+ });
1145
+ this.duplicateAttestationCallback?.({ slot, attester });
1146
+ }
1013
1147
  }
1014
1148
 
1015
- // Attestation was added successfully
1149
+ // Attestation was added successfully - accept it so other nodes can also detect the equivocation
1016
1150
  return { result: TopicValidatorResult.Accept, obj: attestation };
1017
1151
  }
1018
1152
 
@@ -1049,8 +1183,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1049
1183
 
1050
1184
  if (validationResult.result === 'reject') {
1051
1185
  this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1052
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1053
- return { result: TopicValidatorResult.Reject };
1186
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1054
1187
  }
1055
1188
 
1056
1189
  if (validationResult.result === 'ignore') {
@@ -1058,8 +1191,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1058
1191
  }
1059
1192
 
1060
1193
  // Try to add the proposal: this handles existence check, cap check, and adding in one call
1061
- const { added, alreadyExists, totalForPosition } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1062
- const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
1194
+ const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1195
+ const isEquivocated = count !== undefined && count > 1;
1063
1196
 
1064
1197
  // Duplicate proposal received, no need to re-broadcast
1065
1198
  if (alreadyExists) {
@@ -1074,15 +1207,18 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1074
1207
 
1075
1208
  // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1076
1209
  if (!added) {
1077
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1078
1210
  this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1079
1211
  ...block.toBlockInfo(),
1080
1212
  indexWithinCheckpoint: block.indexWithinCheckpoint,
1081
- totalForPosition,
1213
+ count,
1082
1214
  proposer: block.getSender()?.toString(),
1083
1215
  source: peerId.toString(),
1084
1216
  });
1085
- return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
1217
+ return {
1218
+ result: TopicValidatorResult.Reject,
1219
+ metadata: { isEquivocated },
1220
+ severity: PeerErrorSeverity.HighToleranceError,
1221
+ };
1086
1222
  }
1087
1223
 
1088
1224
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1095,7 +1231,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1095
1231
  proposer: proposer?.toString(),
1096
1232
  });
1097
1233
  // Invoke the duplicate callback on the first duplicate spotted only
1098
- if (proposer && totalForPosition === 2) {
1234
+ if (proposer && count === 2) {
1099
1235
  this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
1100
1236
  }
1101
1237
  return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
@@ -1120,14 +1256,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1120
1256
  ...block.toBlockInfo(),
1121
1257
  });
1122
1258
 
1123
- // Mark the txs in this proposal as non-evictable
1124
- await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
1259
+ // Mark the txs in this proposal as protected
1260
+ await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
1125
1261
 
1126
1262
  // Call the block received callback to validate the proposal.
1127
1263
  // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1128
1264
  const isValid = await this.blockReceivedCallback(block, sender);
1129
1265
  if (!isValid) {
1130
- this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1266
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1131
1267
  }
1132
1268
  }
1133
1269
 
@@ -1175,8 +1311,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1175
1311
 
1176
1312
  if (validationResult.result === 'reject') {
1177
1313
  this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1178
- this.peerManager.penalizePeer(peerId, validationResult.severity);
1179
- return { result: TopicValidatorResult.Reject };
1314
+ return { result: TopicValidatorResult.Reject, severity: validationResult.severity };
1180
1315
  }
1181
1316
 
1182
1317
  if (validationResult.result === 'ignore') {
@@ -1191,20 +1326,21 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1191
1326
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1192
1327
  [Attributes.P2P_ID]: peerId.toString(),
1193
1328
  });
1194
- const {
1195
- result,
1196
- obj,
1197
- metadata: { isEquivocated } = {},
1198
- } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1199
- if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1329
+ const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1330
+ const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
1331
+ if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1200
1332
  this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1201
1333
  [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1202
1334
  [Attributes.P2P_ID]: peerId.toString(),
1203
1335
  isEquivocated,
1204
- result,
1336
+ result: blockProposalResult.result,
1205
1337
  });
1206
- return { result: TopicValidatorResult.Reject };
1207
- } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1338
+ return {
1339
+ result: TopicValidatorResult.Reject,
1340
+ severity:
1341
+ 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError,
1342
+ };
1343
+ } else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1208
1344
  processBlock = true;
1209
1345
  }
1210
1346
  }
@@ -1212,8 +1348,8 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1212
1348
  // Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
1213
1349
  const checkpointCore = checkpoint.toCore();
1214
1350
  const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
1215
- const { added, alreadyExists, totalForPosition } = tryAddResult;
1216
- const isEquivocated = totalForPosition !== undefined && totalForPosition > 1;
1351
+ const { added, alreadyExists, count } = tryAddResult;
1352
+ const isEquivocated = count !== undefined && count > 1;
1217
1353
 
1218
1354
  // Duplicate proposal received, do not re-broadcast
1219
1355
  if (alreadyExists) {
@@ -1231,13 +1367,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1231
1367
  // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1232
1368
  // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1233
1369
  if (!added) {
1234
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1235
1370
  this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1236
1371
  ...checkpoint.toCheckpointInfo(),
1237
- totalForPosition,
1372
+ count,
1238
1373
  source: peerId.toString(),
1239
1374
  });
1240
- return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
1375
+ return {
1376
+ result: TopicValidatorResult.Reject,
1377
+ obj: checkpoint,
1378
+ metadata: { isEquivocated, processBlock },
1379
+ severity: PeerErrorSeverity.HighToleranceError,
1380
+ };
1241
1381
  }
1242
1382
 
1243
1383
  // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
@@ -1250,7 +1390,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1250
1390
  proposer: proposer?.toString(),
1251
1391
  });
1252
1392
  // Invoke the duplicate callback on the first duplicate spotted only
1253
- if (proposer && totalForPosition === 2) {
1393
+ if (proposer && count === 2) {
1254
1394
  this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
1255
1395
  }
1256
1396
  return {
@@ -1282,9 +1422,11 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1282
1422
  source: sender.toString(),
1283
1423
  });
1284
1424
 
1425
+ await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
1426
+
1285
1427
  // Call the checkpoint received callback with the core version (without lastBlock)
1286
1428
  // to validate and potentially generate attestations
1287
- const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
1429
+ const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
1288
1430
  if (attestations && attestations.length > 0) {
1289
1431
  // If the callback returned attestations, add them to the pool and propagate them
1290
1432
  await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
@@ -1499,43 +1641,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1499
1641
  }
1500
1642
 
1501
1643
  protected createRequestedTxValidator(): TxValidator {
1502
- return createTxReqRespValidator(this.proofVerifier, {
1644
+ return createTxValidatorForReqResponseReceivedTxs(this.proofVerifier, {
1503
1645
  l1ChainId: this.config.l1ChainId,
1504
1646
  rollupVersion: this.config.rollupVersion,
1505
1647
  });
1506
1648
  }
1507
1649
 
1508
- @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
1509
- [Attributes.TX_HASH]: tx.getTxHash().toString(),
1510
- }))
1511
- private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
1512
- const currentBlockNumber = await this.archiver.getBlockNumber();
1513
-
1514
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1515
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1516
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1517
-
1518
- for (const validator of messageValidators) {
1519
- const outcome = await this.runValidations(tx, validator);
1520
-
1521
- if (outcome.allPassed) {
1522
- continue;
1523
- }
1524
- const { name } = outcome.failure;
1525
- let { severity } = outcome.failure;
1526
-
1527
- // Double spend validator has a special case handler
1528
- if (name === 'doubleSpendValidator') {
1529
- const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
1530
- severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1531
- }
1532
-
1533
- this.peerManager.penalizePeer(peerId, severity);
1534
- return false;
1535
- }
1536
- return true;
1537
- }
1538
-
1539
1650
  private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
1540
1651
  if (blockNumber === this.feesCache?.blockNumber) {
1541
1652
  return this.feesCache.gasFees;
@@ -1563,60 +1674,62 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1563
1674
  };
1564
1675
  }
1565
1676
 
1566
- public async validate(txs: Tx[]): Promise<void> {
1567
- const currentBlockNumber = await this.archiver.getBlockNumber();
1568
-
1569
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1570
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1571
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1677
+ public async validateTxsReceivedInBlockProposal(txs: Tx[]): Promise<void> {
1678
+ const validator = createTxValidatorForBlockProposalReceivedTxs(
1679
+ this.proofVerifier,
1680
+ { l1ChainId: this.config.l1ChainId, rollupVersion: this.config.rollupVersion },
1681
+ this.logger.getBindings(),
1682
+ );
1572
1683
 
1573
- await Promise.all(
1684
+ const results = await Promise.all(
1574
1685
  txs.map(async tx => {
1575
- for (const validator of messageValidators) {
1576
- const outcome = await this.runValidations(tx, validator);
1577
- if (!outcome.allPassed) {
1578
- throw new Error('Invalid tx detected', { cause: { outcome } });
1579
- }
1580
- }
1686
+ const result = await validator.validateTx(tx);
1687
+ return result.result !== 'invalid';
1581
1688
  }),
1582
1689
  );
1690
+ if (results.some(value => value === false)) {
1691
+ throw new Error('Invalid tx detected');
1692
+ }
1583
1693
  }
1584
1694
 
1585
- /**
1586
- * Create message validators for the given block number and timestamp.
1587
- *
1588
- * Each validator is a pair of a validator and a severity.
1589
- * If a validator fails, the peer is penalized with the severity of the validator.
1590
- *
1591
- * @param currentBlockNumber - The current synced block number.
1592
- * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
1593
- * @returns The message validators.
1594
- */
1595
- private async createMessageValidators(
1695
+ /** Creates the first stage (fast) validators for gossiped transactions. */
1696
+ protected async createFirstStageMessageValidators(
1596
1697
  currentBlockNumber: BlockNumber,
1597
1698
  nextSlotTimestamp: UInt64,
1598
- ): Promise<Record<string, MessageValidator>[]> {
1699
+ ): Promise<Record<string, TransactionValidator>> {
1599
1700
  const gasFees = await this.getGasFees(currentBlockNumber);
1600
- const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1601
-
1602
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1603
-
1604
- return createTxMessageValidators(
1701
+ const allowedInSetup = [
1702
+ ...(await getDefaultAllowedSetupFunctions()),
1703
+ ...(this.config.txPublicSetupAllowListExtend ?? []),
1704
+ ];
1705
+ const blockNumber = BlockNumber(currentBlockNumber + 1);
1706
+ const l1Constants = await this.archiver.getL1Constants();
1707
+
1708
+ return createFirstStageTxValidationsForGossipedTransactions(
1605
1709
  nextSlotTimestamp,
1606
- blockNumberInWhichTheTxIsConsideredToBeIncluded,
1710
+ blockNumber,
1607
1711
  this.worldStateSynchronizer,
1608
1712
  gasFees,
1609
1713
  this.config.l1ChainId,
1610
1714
  this.config.rollupVersion,
1611
1715
  protocolContractsHash,
1612
1716
  this.archiver,
1613
- this.proofVerifier,
1614
1717
  !this.config.disableTransactions,
1615
1718
  allowedInSetup,
1616
1719
  this.logger.getBindings(),
1720
+ {
1721
+ rollupManaLimit: l1Constants.rollupManaLimit,
1722
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1723
+ maxBlockDAGas: this.config.validateMaxDABlockGas,
1724
+ },
1617
1725
  );
1618
1726
  }
1619
1727
 
1728
+ /** Creates the second stage (expensive proof verification) validators for gossiped transactions. */
1729
+ protected createSecondStageMessageValidators(): Record<string, TransactionValidator> {
1730
+ return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
1731
+ }
1732
+
1620
1733
  /**
1621
1734
  * Run validations on a tx.
1622
1735
  * @param tx - The tx to validate.
@@ -1625,7 +1738,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1625
1738
  */
1626
1739
  private async runValidations(
1627
1740
  tx: Tx,
1628
- messageValidators: Record<string, MessageValidator>,
1741
+ messageValidators: Record<string, TransactionValidator>,
1629
1742
  ): Promise<ValidationOutcome> {
1630
1743
  const validationPromises = Object.entries(messageValidators).map(async ([name, { validator, severity }]) => {
1631
1744
  const { result } = await validator.validateTx(tx);
@@ -1634,8 +1747,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1634
1747
 
1635
1748
  // A promise that resolves when all validations have been run
1636
1749
  const allValidations = await Promise.all(validationPromises);
1637
- const failed = allValidations.find(x => !x.isValid);
1638
- if (failed) {
1750
+ const failures = allValidations.filter(x => !x.isValid);
1751
+ if (failures.length > 0) {
1752
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1753
+ const failed = maxBy(failures, f => PeerErrorSeverityByHarshness.indexOf(f.severity))!;
1639
1754
  return {
1640
1755
  allPassed: false,
1641
1756
  failure: {
@@ -1688,31 +1803,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1688
1803
  return PeerErrorSeverity.HighToleranceError;
1689
1804
  }
1690
1805
 
1691
- /**
1692
- * Validate a checkpoint attestation.
1693
- *
1694
- * @param attestation - The checkpoint attestation to validate.
1695
- * @returns True if the checkpoint attestation is valid, false otherwise.
1696
- */
1697
- @trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
1698
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1699
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1700
- [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1701
- }))
1702
- public async validateCheckpointAttestation(
1703
- peerId: PeerId,
1704
- attestation: CheckpointAttestation,
1705
- ): Promise<P2PValidationResult> {
1706
- const result = await this.checkpointAttestationValidator.validate(attestation);
1707
-
1708
- if (result.result === 'reject') {
1709
- this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1710
- this.peerManager.penalizePeer(peerId, result.severity);
1711
- }
1712
-
1713
- return result;
1714
- }
1715
-
1716
1806
  public getPeerScore(peerId: PeerId): number {
1717
1807
  return this.node.services.pubsub.score.score(peerId.toString());
1718
1808
  }