@aztec/p2p 0.0.1-commit.b1c78909e → 0.0.1-commit.b2a5d0dd1

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 (301) hide show
  1. package/README.md +129 -3
  2. package/dest/client/factory.d.ts +3 -2
  3. package/dest/client/factory.d.ts.map +1 -1
  4. package/dest/client/factory.js +19 -10
  5. package/dest/client/interface.d.ts +9 -2
  6. package/dest/client/interface.d.ts.map +1 -1
  7. package/dest/client/p2p_client.d.ts +3 -2
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +40 -14
  10. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +21 -7
  11. package/dest/config.d.ts +107 -97
  12. package/dest/config.d.ts.map +1 -1
  13. package/dest/config.js +20 -5
  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/index.d.ts +1 -2
  18. package/dest/index.d.ts.map +1 -1
  19. package/dest/index.js +0 -1
  20. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +7 -5
  21. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  22. package/dest/mem_pools/attestation_pool/attestation_pool.js +11 -8
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +6 -6
  24. package/dest/mem_pools/index.d.ts +1 -2
  25. package/dest/mem_pools/index.d.ts.map +1 -1
  26. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  27. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +2 -1
  29. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  30. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  31. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  32. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  33. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  34. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  35. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  36. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +10 -5
  37. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  38. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +13 -3
  39. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  40. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +20 -7
  41. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
  42. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  43. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +3 -0
  44. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
  45. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  46. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +13 -5
  47. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +5 -2
  48. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  49. package/dest/msg_validators/attestation_validator/attestation_validator.js +20 -11
  50. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +4 -2
  51. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  52. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +2 -2
  53. package/dest/msg_validators/clock_tolerance.d.ts +12 -1
  54. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  55. package/dest/msg_validators/clock_tolerance.js +54 -3
  56. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +2 -1
  57. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  58. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +2 -1
  59. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  60. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -1
  61. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  62. package/dest/msg_validators/proposal_validator/proposal_validator.js +19 -11
  63. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  64. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  65. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  66. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  67. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  68. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  69. package/dest/msg_validators/tx_validator/data_validator.js +35 -2
  70. package/dest/msg_validators/tx_validator/factory.d.ts +10 -2
  71. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  72. package/dest/msg_validators/tx_validator/factory.js +26 -7
  73. package/dest/msg_validators/tx_validator/gas_validator.d.ts +36 -4
  74. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  75. package/dest/msg_validators/tx_validator/gas_validator.js +50 -33
  76. package/dest/msg_validators/tx_validator/phases_validator.d.ts +21 -1
  77. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  78. package/dest/msg_validators/tx_validator/phases_validator.js +28 -1
  79. package/dest/services/data_store.d.ts +1 -1
  80. package/dest/services/data_store.d.ts.map +1 -1
  81. package/dest/services/data_store.js +5 -5
  82. package/dest/services/dummy_service.d.ts +6 -3
  83. package/dest/services/dummy_service.d.ts.map +1 -1
  84. package/dest/services/dummy_service.js +6 -1
  85. package/dest/services/encoding.d.ts +5 -1
  86. package/dest/services/encoding.d.ts.map +1 -1
  87. package/dest/services/encoding.js +7 -1
  88. package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
  89. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  90. package/dest/services/gossipsub/topic_score_params.js +21 -4
  91. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  92. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  93. package/dest/services/libp2p/instrumentation.js +14 -0
  94. package/dest/services/libp2p/libp2p_service.d.ts +19 -27
  95. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  96. package/dest/services/libp2p/libp2p_service.js +141 -130
  97. package/dest/services/peer-manager/peer_manager.d.ts +6 -2
  98. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  99. package/dest/services/peer-manager/peer_manager.js +37 -10
  100. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  101. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  102. package/dest/services/peer-manager/peer_scoring.js +32 -10
  103. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
  104. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  105. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +69 -65
  106. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +3 -2
  107. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  108. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  109. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  110. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  111. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
  112. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  113. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
  114. package/dest/services/reqresp/config.d.ts +3 -3
  115. package/dest/services/reqresp/config.d.ts.map +1 -1
  116. package/dest/services/reqresp/interface.d.ts +14 -9
  117. package/dest/services/reqresp/interface.d.ts.map +1 -1
  118. package/dest/services/reqresp/interface.js +10 -11
  119. package/dest/services/reqresp/metrics.d.ts +1 -1
  120. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  121. package/dest/services/reqresp/metrics.js +0 -1
  122. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  123. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  124. package/dest/services/reqresp/protocols/index.js +0 -1
  125. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  126. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  127. package/dest/services/reqresp/protocols/tx.js +1 -3
  128. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  129. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  130. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  131. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  132. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  133. package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
  134. package/dest/services/reqresp/reqresp.d.ts +4 -2
  135. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  136. package/dest/services/reqresp/reqresp.js +28 -11
  137. package/dest/services/service.d.ts +5 -2
  138. package/dest/services/service.d.ts.map +1 -1
  139. package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -4
  140. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  141. package/dest/services/tx_collection/fast_tx_collection.js +57 -73
  142. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  143. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  144. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  145. package/dest/services/tx_collection/proposal_tx_collector.d.ts +6 -7
  146. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  147. package/dest/services/tx_collection/proposal_tx_collector.js +4 -4
  148. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  149. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  150. package/dest/services/tx_collection/request_tracker.js +84 -0
  151. package/dest/services/tx_collection/slow_tx_collection.js +1 -1
  152. package/dest/services/tx_collection/tx_collection.d.ts +3 -6
  153. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  154. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  155. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  156. package/dest/services/tx_collection/tx_source.js +9 -7
  157. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  158. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  159. package/dest/test-helpers/make-test-p2p-clients.js +4 -1
  160. package/dest/test-helpers/mock-pubsub.d.ts +11 -3
  161. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  162. package/dest/test-helpers/mock-pubsub.js +36 -11
  163. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  164. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  165. package/dest/test-helpers/reqresp-nodes.js +5 -3
  166. package/dest/test-helpers/testbench-utils.d.ts +1 -1
  167. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  168. package/dest/test-helpers/testbench-utils.js +21 -2
  169. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  170. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  171. package/dest/testbench/p2p_client_testbench_worker.js +73 -17
  172. package/dest/testbench/worker_client_manager.d.ts +8 -1
  173. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  174. package/dest/testbench/worker_client_manager.js +49 -1
  175. package/package.json +14 -14
  176. package/src/client/factory.ts +31 -4
  177. package/src/client/interface.ts +9 -1
  178. package/src/client/p2p_client.ts +47 -15
  179. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +20 -8
  180. package/src/config.ts +35 -6
  181. package/src/errors/p2p-service.error.ts +11 -0
  182. package/src/index.ts +0 -1
  183. package/src/mem_pools/attestation_pool/attestation_pool.ts +12 -8
  184. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +6 -6
  185. package/src/mem_pools/index.ts +0 -3
  186. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  187. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  188. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  189. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
  190. package/src/mem_pools/tx_pool_v2/interfaces.ts +9 -4
  191. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +31 -9
  192. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +13 -1
  193. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +14 -4
  194. package/src/msg_validators/attestation_validator/README.md +49 -0
  195. package/src/msg_validators/attestation_validator/attestation_validator.ts +21 -9
  196. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +4 -1
  197. package/src/msg_validators/clock_tolerance.ts +72 -3
  198. package/src/msg_validators/proposal_validator/README.md +123 -0
  199. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +4 -1
  200. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +4 -1
  201. package/src/msg_validators/proposal_validator/proposal_validator.ts +17 -10
  202. package/src/msg_validators/tx_validator/README.md +15 -3
  203. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  204. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  205. package/src/msg_validators/tx_validator/data_validator.ts +42 -1
  206. package/src/msg_validators/tx_validator/factory.ts +31 -2
  207. package/src/msg_validators/tx_validator/gas_validator.ts +82 -33
  208. package/src/msg_validators/tx_validator/phases_validator.ts +31 -1
  209. package/src/services/data_store.ts +5 -13
  210. package/src/services/dummy_service.ts +8 -2
  211. package/src/services/encoding.ts +9 -1
  212. package/src/services/gossipsub/topic_score_params.ts +36 -4
  213. package/src/services/libp2p/instrumentation.ts +14 -0
  214. package/src/services/libp2p/libp2p_service.ts +141 -141
  215. package/src/services/peer-manager/peer_manager.ts +43 -10
  216. package/src/services/peer-manager/peer_scoring.ts +27 -5
  217. package/src/services/reqresp/README.md +229 -0
  218. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  219. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +64 -69
  220. package/src/services/reqresp/batch-tx-requester/interface.ts +2 -1
  221. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  222. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
  223. package/src/services/reqresp/config.ts +2 -2
  224. package/src/services/reqresp/interface.ts +21 -11
  225. package/src/services/reqresp/metrics.ts +0 -1
  226. package/src/services/reqresp/protocols/index.ts +0 -1
  227. package/src/services/reqresp/protocols/tx.ts +1 -3
  228. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  229. package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
  230. package/src/services/reqresp/reqresp.ts +37 -12
  231. package/src/services/service.ts +6 -1
  232. package/src/services/tx_collection/fast_tx_collection.ts +57 -83
  233. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  234. package/src/services/tx_collection/proposal_tx_collector.ts +8 -13
  235. package/src/services/tx_collection/request_tracker.ts +127 -0
  236. package/src/services/tx_collection/slow_tx_collection.ts +1 -1
  237. package/src/services/tx_collection/tx_collection.ts +3 -5
  238. package/src/services/tx_collection/tx_source.ts +8 -7
  239. package/src/test-helpers/make-test-p2p-clients.ts +2 -0
  240. package/src/test-helpers/mock-pubsub.ts +34 -5
  241. package/src/test-helpers/reqresp-nodes.ts +4 -2
  242. package/src/test-helpers/testbench-utils.ts +29 -3
  243. package/src/testbench/p2p_client_testbench_worker.ts +73 -14
  244. package/src/testbench/worker_client_manager.ts +55 -1
  245. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  246. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  247. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  248. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  249. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  250. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  251. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  252. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  253. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  254. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  255. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  256. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
  257. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  258. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  259. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  260. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  261. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  262. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  263. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  264. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  265. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  266. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  267. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  268. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  269. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  270. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  271. package/dest/mem_pools/tx_pool/index.js +0 -2
  272. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  273. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  274. package/dest/mem_pools/tx_pool/priority.js +0 -16
  275. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  276. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  277. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  278. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  279. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  280. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -402
  281. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  282. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  283. package/dest/services/reqresp/protocols/block.js +0 -32
  284. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  285. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  286. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  287. package/src/mem_pools/tx_pool/README.md +0 -270
  288. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  289. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  290. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  291. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
  292. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  293. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  294. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  295. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  296. package/src/mem_pools/tx_pool/index.ts +0 -2
  297. package/src/mem_pools/tx_pool/priority.ts +0 -23
  298. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  299. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -321
  300. package/src/services/reqresp/protocols/block.ts +0 -37
  301. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
@@ -0,0 +1,123 @@
1
+ # Proposal Validation
2
+
3
+ This module validates `BlockProposal` and `CheckpointProposal` gossipsub messages. Both share the same base `ProposalValidator` (neither subclass overrides `validate()`), with checkpoint-specific logic layered on top in the gossipsub handler.
4
+
5
+ ## BlockProposal
6
+
7
+ **Topic**: `block_proposal` | **Snappy size limit**: 10 MB
8
+
9
+ ### Stage 1: Gossipsub Validation (ProposalValidator)
10
+
11
+ File: `proposal_validator.ts`
12
+
13
+ | # | Rule | Consequence | Severity |
14
+ |---|------|-------------|----------|
15
+ | 1 | **Slot check**: must be `currentSlot` or `nextSlot`. Previous slot within 500ms tolerance: IGNORE. | REJECT | HighToleranceError |
16
+ | 2 | **Signature**: `getSender()` must recover a valid address. If `signedTxs` present, its recovered sender must match. | REJECT | MidToleranceError |
17
+ | 3 | **Txs permitted**: if `disableTransactions`, must have 0 txHashes and 0 embedded txs | REJECT | MidToleranceError |
18
+ | 4 | **Max txs**: `txHashes.length <= maxTxsPerBlock` | REJECT | MidToleranceError |
19
+ | 5 | **Embedded txs in txHashes**: every embedded tx's hash must appear in `txHashes` | REJECT | MidToleranceError |
20
+ | 6 | **Proposer check**: signer must match expected proposer for slot (skipped if committee size = 0) | REJECT | MidToleranceError |
21
+ | 7 | **Tx hash integrity**: each embedded tx's recomputed hash must match declared hash | REJECT | LowToleranceError |
22
+ | 8 | **NoCommitteeError**: epoch cache cannot determine committee | REJECT | LowToleranceError |
23
+
24
+ Deserialization guards: `BlockProposal.fromBuffer` and `SignedTxs.fromBuffer` both enforce `txCount <= MAX_TXS_PER_BLOCK` (65536). Violation -> REJECT + LowToleranceError.
25
+
26
+ ### Stage 2: Mempool (Attestation Pool)
27
+
28
+ | # | Rule | Consequence |
29
+ |---|------|-------------|
30
+ | 9 | **Duplicate**: same archive root already stored | IGNORE (no penalty) |
31
+ | 10 | **Per-position cap**: max 2 proposals per (slot, indexWithinCheckpoint) | REJECT + HighToleranceError |
32
+ | 11 | **Equivocation**: >1 distinct proposal for same (slot, index) | ACCEPT (rebroadcast for detection). At count=2: `duplicateProposalCallback` fires -> slash event (`OffenseType.DUPLICATE_PROPOSAL`, configured via `slashDuplicateProposalPenalty`) |
33
+
34
+ ### Stage 3: Validator-Client Processing (BlockProposalHandler)
35
+
36
+ Only runs on validator nodes. Non-validator nodes use a default handler that triggers tx collection without deep validation.
37
+
38
+ | # | Rule | Failure Reason |
39
+ |---|------|----------------|
40
+ | 12 | Signature re-check | `invalid_proposal` |
41
+ | 13 | ProposalValidator re-run | `invalid_proposal` |
42
+ | 14 | Self-proposal filter | Ignored silently |
43
+ | 15 | Parent block exists (`lastArchive.root` matches known block or genesis) | `parent_block_not_found` |
44
+ | 16 | Parent block slot <= proposal slot | `parent_block_wrong_slot` |
45
+ | 17 | Block number not already in archiver | `block_number_already_exists` |
46
+ | 18 | Checkpoint number consistency (multiple sub-rules for first/non-first blocks) | `invalid_proposal` |
47
+ | 19 | Global variables consistency (non-first block: chainId, version, slot, timestamp, coinbase, feeRecipient, gasFees match parent) | `global_variables_mismatch` |
48
+ | 20 | L1-to-L2 message hash matches `proposal.inHash` | `in_hash_mismatch` |
49
+ | 21 | All txs referenced by `txHashes` obtainable | `txs_not_available` |
50
+ | 22 | **Re-execution**: processed tx count matches `txHashes.length` | `timeout` (ReExTimeoutError) |
51
+ | 23 | **Re-execution**: no failed txs | `failed_txs` (ReExFailedTxsError) -- **SLASHABLE** |
52
+ | 24 | **Re-execution**: archive root and header match proposal | `state_mismatch` (ReExStateMismatchError) -- **SLASHABLE** |
53
+
54
+ **Escape hatch**: during escape hatch periods (`isEscapeHatchOpenAtSlot`), re-execution and slashing are both disabled, and the proposal is rejected locally.
55
+
56
+ **Conditional re-execution**: rules 22-24 only run when at least one condition is true: `fishermanMode` enabled, `slashBroadcastedInvalidBlockPenalty > 0`, committee membership, `alwaysReexecuteBlockProposals`, or `blobClient.canUpload()`.
57
+
58
+ **Slashing**: only `state_mismatch` and `failed_txs` trigger on-chain slashing (`OffenseType.BROADCASTED_INVALID_BLOCK_PROPOSAL`, gated by `slashBroadcastedInvalidBlockPenalty > 0`). Unknown errors during re-execution do NOT slash.
59
+
60
+ **Embedded tx validation**: txs in `signedTxs` are validated via `createTxValidatorForBlockProposalReceivedTxs` (well-formedness only) when stored in the tx pool. Invalid embedded txs are rejected from the pool but do not cause the block proposal itself to be rejected at gossipsub level.
61
+
62
+ ### Gossipsub Topic Scoring
63
+
64
+ | Parameter | Effect |
65
+ |-----------|--------|
66
+ | P4 (invalidMessageDeliveries) | weight = -20, decay over 4 slots |
67
+ | P3 (meshMessageDeliveries) | Enabled only when `expectedBlockProposalsPerSlot > 0` (MBPS mode) |
68
+ | P1/P2 | Only active when P3 is enabled |
69
+
70
+ ---
71
+
72
+ ## CheckpointProposal
73
+
74
+ **Topic**: `checkpoint_proposal` | **Snappy size limit**: 10 MB
75
+
76
+ ### Stage 1: Gossipsub Validation (ProposalValidator)
77
+
78
+ Same `ProposalValidator.validate()` as BlockProposal (shared implementation, neither subclass overrides it). See BlockProposal Stage 1 rules 1-8.
79
+
80
+ ### Stage 2: Embedded Block Proposal Validation (if `lastBlock` present)
81
+
82
+ The checkpoint's embedded `lastBlock` is extracted via `getBlockProposal()` and validated through `BlockProposalValidator.validate()` plus block mempool checks.
83
+
84
+ | Rule | Consequence | File |
85
+ |------|-------------|------|
86
+ | Block proposal must pass `BlockProposalValidator.validate()` | If REJECT: entire checkpoint REJECTED | `libp2p_service.ts` |
87
+ | Block proposal must not exceed per-position cap (2) | Checkpoint REJECTED + HighToleranceError | same |
88
+ | Block equivocation detected (>1 proposals for same slot+index) | Checkpoint REJECTED (block itself is ACCEPT for re-broadcast) | same |
89
+
90
+ ### Stage 3: Mempool (Attestation Pool)
91
+
92
+ | Rule | Consequence | File |
93
+ |------|-------------|------|
94
+ | Duplicate (same archive ID) | IGNORE (no penalty). Embedded block still processed if valid. | `attestation_pool.ts` |
95
+ | Per-slot cap: `MAX_CHECKPOINT_PROPOSALS_PER_SLOT` = 2 | REJECT + HighToleranceError. Embedded block still processed. | same |
96
+
97
+ ### Stage 4: Equivocation Detection
98
+
99
+ When >1 checkpoint proposals exist for same slot (count > 1): ACCEPT (re-broadcast). At count == 2 (exactly): `duplicateProposalCallback` fires. Proposal NOT further processed. Callback fires only once per equivocation pair.
100
+
101
+ ### Stage 5: Validator-Client Consensus Validation
102
+
103
+ Determines whether the validator signs an attestation.
104
+
105
+ | Rule | Consequence | File |
106
+ |------|-------------|------|
107
+ | Escape hatch open | No attestation | `validator-client/src/validator.ts` |
108
+ | Signature invalid (re-check) | No attestation | same |
109
+ | Self-proposal | No attestation (ignored) | same |
110
+ | `feeAssetPriceModifier` outside [-100, +100] bps | No attestation | same |
111
+ | Not in committee (unless fisherman mode) | No attestation | same |
112
+ | Checkpoint header mismatch (computed vs proposal) | No attestation | same |
113
+ | Archive root mismatch | No attestation | same |
114
+ | Epoch out hash mismatch | No attestation | same |
115
+ | Last block not found / not matching | No attestation | same |
116
+ | Already attested to this or earlier slot | No attestation (unless `attestToEquivocatedProposals`) | same |
117
+
118
+ **`skipCheckpointProposalValidation` config**: when true, the re-execution checks (header/archive/epoch hash) are all skipped. Signature, fee modifier, committee, escape hatch, and equivocation checks still apply.
119
+
120
+ ### Gossipsub Topic Scoring
121
+
122
+ P3 enabled with expected rate of 1 message per slot. P4 weight = -20, max P3 penalty = -34 per topic.
123
+
@@ -6,7 +6,10 @@ import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
6
6
  export class BlockProposalValidator implements P2PValidator<BlockProposal> {
7
7
  private proposalValidator: ProposalValidator;
8
8
 
9
- constructor(epochCache: EpochCacheInterface, opts: { txsPermitted: boolean; maxTxsPerBlock?: number }) {
9
+ constructor(
10
+ epochCache: EpochCacheInterface,
11
+ opts: { txsPermitted: boolean; maxTxsPerBlock?: number; p2pPropagationTime?: number },
12
+ ) {
10
13
  this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:block_proposal_validator');
11
14
  }
12
15
 
@@ -6,7 +6,10 @@ import { ProposalValidator } from '../proposal_validator/proposal_validator.js';
6
6
  export class CheckpointProposalValidator implements P2PValidator<CheckpointProposal> {
7
7
  private proposalValidator: ProposalValidator;
8
8
 
9
- constructor(epochCache: EpochCacheInterface, opts: { txsPermitted: boolean; maxTxsPerBlock?: number }) {
9
+ constructor(
10
+ epochCache: EpochCacheInterface,
11
+ opts: { txsPermitted: boolean; maxTxsPerBlock?: number; p2pPropagationTime?: number },
12
+ ) {
10
13
  this.proposalValidator = new ProposalValidator(epochCache, opts, 'p2p:checkpoint_proposal_validator');
11
14
  }
12
15
 
@@ -8,7 +8,7 @@ import {
8
8
  type ValidationResult,
9
9
  } from '@aztec/stdlib/p2p';
10
10
 
11
- import { isWithinClockTolerance } from '../clock_tolerance.js';
11
+ import { PipeliningWindow, isWithinClockTolerance } from '../clock_tolerance.js';
12
12
 
13
13
  /** Validates header-level and tx-level fields of block and checkpoint proposals. */
14
14
  export class ProposalValidator {
@@ -16,32 +16,39 @@ export class ProposalValidator {
16
16
  private logger: Logger;
17
17
  private txsPermitted: boolean;
18
18
  private maxTxsPerBlock?: number;
19
+ private pipeliningWindow: PipeliningWindow;
19
20
 
20
21
  constructor(
21
22
  epochCache: EpochCacheInterface,
22
- opts: { txsPermitted: boolean; maxTxsPerBlock?: number },
23
+ opts: { txsPermitted: boolean; maxTxsPerBlock?: number; p2pPropagationTime?: number },
23
24
  loggerName: string,
24
25
  ) {
25
26
  this.epochCache = epochCache;
26
27
  this.txsPermitted = opts.txsPermitted;
27
28
  this.maxTxsPerBlock = opts.maxTxsPerBlock;
29
+ this.pipeliningWindow = new PipeliningWindow(epochCache, { p2pPropagationTime: opts.p2pPropagationTime });
28
30
  this.logger = createLogger(loggerName);
29
31
  }
30
32
 
31
33
  /** Validates header-level fields: slot, signature, and proposer. */
32
34
  public async validate(proposal: BlockProposal | CheckpointProposalCore): Promise<ValidationResult> {
33
35
  try {
34
- // Slot check
35
- const { currentSlot, nextSlot } = this.epochCache.getCurrentAndNextSlot();
36
+ // Slot check: use target slots since proposals target pipeline slots (slot + 1 when pipelining).
37
+ const { targetSlot, nextSlot } = this.epochCache.getTargetAndNextSlot();
38
+
36
39
  const slotNumber = proposal.slotNumber;
37
- if (slotNumber !== currentSlot && slotNumber !== nextSlot) {
38
- // Check if message is for previous slot and within clock tolerance
39
- if (!isWithinClockTolerance(slotNumber, currentSlot, this.epochCache)) {
40
- this.logger.warn(`Penalizing peer for invalid slot number ${slotNumber}`, { currentSlot, nextSlot });
40
+ if (slotNumber !== targetSlot && slotNumber !== nextSlot) {
41
+ // When pipelining, accept proposals for the current slot (built in the previous slot)
42
+ // if they're still within the shared proposal acceptance window.
43
+ if (this.pipeliningWindow.acceptsProposal(slotNumber)) {
44
+ // Fall through to remaining validation (signature, proposer, etc.)
45
+ } else if (!isWithinClockTolerance(slotNumber, targetSlot, this.epochCache)) {
46
+ this.logger.warn(`Penalizing peer for invalid slot number ${slotNumber}`, { targetSlot, nextSlot });
41
47
  return { result: 'reject', severity: PeerErrorSeverity.HighToleranceError };
48
+ } else {
49
+ this.logger.verbose(`Ignoring proposal for previous slot ${slotNumber} within clock tolerance`);
50
+ return { result: 'ignore' };
42
51
  }
43
- this.logger.verbose(`Ignoring proposal for previous slot ${slotNumber} within clock tolerance`);
44
- return { result: 'ignore' };
45
52
  }
46
53
 
47
54
  // Signature validity
@@ -75,10 +75,12 @@ This validator is invoked on **every** transaction potentially entering the pend
75
75
  - Startup hydration — revalidating persisted non-mined txs on node restart
76
76
 
77
77
  Runs:
78
- - DoubleSpend, BlockHeader, GasLimits, Timestamp
78
+ - DoubleSpend, BlockHeader, GasLimits, MaxFeePerGas, Timestamp, AllowedSetupCalls
79
79
 
80
80
  Operates on `TxMetaData` (pre-built by the pool) rather than full `Tx` objects.
81
81
 
82
+ The `AllowedSetupCallsMetaValidator` checks a precomputed boolean flag (`TxMetaData.allowedSetupCalls`) rather than re-running the full `PhasesTxValidator`. This flag is computed by `createCheckAllowedSetupCalls` when the tx first enters the pool (via `addProtectedTxs` or startup hydration), so the pool migration validator can reject txs with disallowed setup calls without needing the full `Tx` object or its dependencies.
83
+
82
84
  ## Individual Validators
83
85
 
84
86
  | Validator | What it checks | Benchmarked verification duration |
@@ -89,9 +91,11 @@ Operates on `TxMetaData` (pre-built by the pool) rather than full `Tx` objects.
89
91
  | `MetadataTxValidator` | Chain ID, rollup version, protocol contracts hash, VK tree root | 4.18 us |
90
92
  | `TimestampTxValidator` | Transaction has not expired (expiration timestamp vs next slot) | 1.56 us |
91
93
  | `DoubleSpendTxValidator` | Nullifiers do not already exist in the nullifier tree | 106.08 us |
92
- | `GasTxValidator` | Gas limits are within bounds (delegates to `GasLimitsValidator`), max fee per gas meets current block fees, and fee payer has sufficient FeeJuice balance | 1.02 ms |
94
+ | `GasTxValidator` | Gas limits are within bounds (delegates to `GasLimitsValidator`), max fee per gas meets current block fees (delegates to `MaxFeePerGasValidator`), and fee payer has sufficient FeeJuice balance | 1.02 ms |
93
95
  | `GasLimitsValidator` | Gas limits are >= fixed minimums and <= AVM max processable L2 gas. Used standalone in pool migration; also called internally by `GasTxValidator` | 3–10 us |
96
+ | `MaxFeePerGasValidator` | Max fee per gas >= current block gas fees on both dimensions (DA and L2). Used standalone in pool migration; also called internally by `GasTxValidator` | 3–10 us |
94
97
  | `PhasesTxValidator` | Public function calls in setup phase are on the allow list | 10.12–13.12 us |
98
+ | `AllowedSetupCallsMetaValidator` | Checks the precomputed `allowedSetupCalls` flag on `TxMetaData`. Used in pool migration instead of the full `PhasesTxValidator` | — |
95
99
  | `BlockHeaderTxValidator` | Transaction's anchor block hash exists in the archive tree | 98.88 us |
96
100
  | `TxProofValidator` | Client proof verifies correctly | ~250ms |
97
101
 
@@ -107,9 +111,17 @@ Operates on `TxMetaData` (pre-built by the pool) rather than full `Tx` objects.
107
111
  | DoubleSpend | Stage 1 | Yes | — | Yes | Yes |
108
112
  | Gas (balance + limits) | Stage 1 | Optional* | — | Yes | — |
109
113
  | GasLimits (standalone) | — | — | — | — | Yes |
114
+ | MaxFeePerGas (standalone) | — | — | — | — | Yes |
110
115
  | Phases | Stage 1 | Yes | — | Yes | — |
116
+ | AllowedSetupCalls | — | — | — | — | Yes |
111
117
  | BlockHeader | Stage 1 | Yes | — | Yes | Yes |
112
118
  | Proof | Stage 2 | Optional** | Yes | — | — |
113
119
 
114
- \* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `GasLimitsValidator` as its first step, so gas limits are checked wherever `GasTxValidator` runs. Pool migration uses `GasLimitsValidator` standalone because it doesn't need the balance or fee-per-gas checks.
120
+ \* Gas balance check is skipped when `skipFeeEnforcement` is set (testing/dev). `GasTxValidator` internally delegates to `GasLimitsValidator` and `MaxFeePerGasValidator` as its first steps, so gas limits and fee-per-gas are checked wherever `GasTxValidator` runs. Pool migration uses `GasLimitsValidator` and `MaxFeePerGasValidator` standalone because it doesn't need the balance check.
115
121
  \** Proof verification is skipped for simulations (no verifier provided).
122
+
123
+ ## Fee-Per-Gas Rejection Strategy
124
+
125
+ The `MaxFeePerGasValidator` and `InsufficientFeePerGasEvictionRule` reject and evict transactions whose `maxFeesPerGas` falls below the current block's gas fees. This is a simple strategy: if a tx can't pay the current fees, it gets rejected on entry and evicted after each new block.
126
+
127
+ **Caveat**: This may evict transactions that would become valid again if block fees drop. A more nuanced approach would be to define a threshold (e.g., 50%) and only reject/evict when the tx's max fee falls below that fraction of the current fees. The current approach is simpler and ensures the pool doesn't accumulate transactions with low max fees that are unlikely to be mined soon.
@@ -15,7 +15,7 @@ export class ArchiveCache implements ArchiveSource {
15
15
  }
16
16
 
17
17
  public async getArchiveIndices(archives: BlockHash[]): Promise<(bigint | undefined)[]> {
18
- const toCheckDb = archives.filter(n => !this.archives.has(n.toString())).map(n => n.toFr());
18
+ const toCheckDb = archives.filter(n => !this.archives.has(n.toString()));
19
19
  const dbHits = await this.db.findLeafIndices(MerkleTreeId.ARCHIVE, toCheckDb);
20
20
  dbHits.forEach((x, index) => {
21
21
  if (x !== undefined) {
@@ -0,0 +1,56 @@
1
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
2
+ import { ContractInstancePublishedEvent } from '@aztec/protocol-contracts/instance-registry';
3
+ import { computeContractAddressFromInstance } from '@aztec/stdlib/contract';
4
+ import {
5
+ TX_ERROR_INCORRECT_CONTRACT_ADDRESS,
6
+ TX_ERROR_MALFORMED_CONTRACT_INSTANCE_LOG,
7
+ type Tx,
8
+ type TxValidationResult,
9
+ type TxValidator,
10
+ } from '@aztec/stdlib/tx';
11
+
12
+ /** Validates that contract instance deployment logs contain correct addresses. */
13
+ export class ContractInstanceTxValidator implements TxValidator<Tx> {
14
+ #log: Logger;
15
+
16
+ constructor(bindings?: LoggerBindings) {
17
+ this.#log = createLogger('p2p:tx_validator:contract_instance', bindings);
18
+ }
19
+
20
+ async validateTx(tx: Tx): Promise<TxValidationResult> {
21
+ const reason = await this.#hasCorrectContractInstanceAddresses(tx);
22
+ return reason ? { result: 'invalid', reason: [reason] } : { result: 'valid' };
23
+ }
24
+
25
+ async #hasCorrectContractInstanceAddresses(tx: Tx): Promise<string | undefined> {
26
+ const privateLogs = tx.data.getNonEmptyPrivateLogs();
27
+ for (const log of privateLogs) {
28
+ if (!ContractInstancePublishedEvent.isContractInstancePublishedEvent(log)) {
29
+ continue;
30
+ }
31
+
32
+ let event;
33
+ try {
34
+ event = ContractInstancePublishedEvent.fromLog(log);
35
+ } catch (e) {
36
+ this.#log.warn(`Rejecting tx ${tx.getTxHash()}: failed to parse contract instance event: ${e}`);
37
+ return TX_ERROR_MALFORMED_CONTRACT_INSTANCE_LOG;
38
+ }
39
+
40
+ try {
41
+ const instance = event.toContractInstance();
42
+ const computedAddress = await computeContractAddressFromInstance(instance);
43
+ if (!computedAddress.equals(instance.address)) {
44
+ this.#log.warn(
45
+ `Rejecting tx ${tx.getTxHash()}: contract instance address mismatch. Claimed ${instance.address}, computed ${computedAddress}`,
46
+ );
47
+ return TX_ERROR_INCORRECT_CONTRACT_ADDRESS;
48
+ }
49
+ } catch (e) {
50
+ this.#log.warn(`Rejecting tx ${tx.getTxHash()}: failed to compute contract instance address: ${e}`);
51
+ return TX_ERROR_MALFORMED_CONTRACT_INSTANCE_LOG;
52
+ }
53
+ }
54
+ return undefined;
55
+ }
56
+ }
@@ -1,5 +1,7 @@
1
1
  import { MAX_FR_CALLDATA_TO_ALL_ENQUEUED_CALLS } from '@aztec/constants';
2
2
  import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
3
+ import { ContractClassPublishedEvent } from '@aztec/protocol-contracts/class-registry';
4
+ import { computeContractClassId } from '@aztec/stdlib/contract';
3
5
  import { computeCalldataHash } from '@aztec/stdlib/hash';
4
6
  import {
5
7
  TX_ERROR_CALLDATA_COUNT_MISMATCH,
@@ -9,7 +11,9 @@ import {
9
11
  TX_ERROR_CONTRACT_CLASS_LOG_LENGTH,
10
12
  TX_ERROR_CONTRACT_CLASS_LOG_SORTING,
11
13
  TX_ERROR_INCORRECT_CALLDATA,
14
+ TX_ERROR_INCORRECT_CONTRACT_CLASS_ID,
12
15
  TX_ERROR_INCORRECT_HASH,
16
+ TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG,
13
17
  Tx,
14
18
  type TxValidationResult,
15
19
  type TxValidator,
@@ -26,7 +30,8 @@ export class DataTxValidator implements TxValidator<Tx> {
26
30
  const reason =
27
31
  (await this.#hasCorrectHash(tx)) ??
28
32
  (await this.#hasCorrectCalldata(tx)) ??
29
- (await this.#hasCorrectContractClassLogs(tx));
33
+ (await this.#hasCorrectContractClassLogs(tx)) ??
34
+ (await this.#hasCorrectContractClassIds(tx));
30
35
  return reason ? { result: 'invalid', reason: [reason] } : { result: 'valid' };
31
36
  }
32
37
 
@@ -127,4 +132,40 @@ export class DataTxValidator implements TxValidator<Tx> {
127
132
 
128
133
  return undefined;
129
134
  }
135
+
136
+ async #hasCorrectContractClassIds(tx: Tx): Promise<string | undefined> {
137
+ const contractClassLogs = tx.getContractClassLogs();
138
+ for (const log of contractClassLogs) {
139
+ if (!ContractClassPublishedEvent.isContractClassPublishedEvent(log)) {
140
+ continue;
141
+ }
142
+
143
+ let event;
144
+ try {
145
+ event = ContractClassPublishedEvent.fromLog(log);
146
+ } catch (e) {
147
+ this.#log.warn(`Rejecting tx ${tx.getTxHash()}: failed to parse contract class event: ${e}`);
148
+ return TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG;
149
+ }
150
+
151
+ try {
152
+ const { publicBytecodeCommitment } = await event.toContractClassPublicWithBytecodeCommitment();
153
+ const computedClassId = await computeContractClassId({
154
+ artifactHash: event.artifactHash,
155
+ privateFunctionsRoot: event.privateFunctionsRoot,
156
+ publicBytecodeCommitment,
157
+ });
158
+ if (!computedClassId.equals(event.contractClassId)) {
159
+ this.#log.warn(
160
+ `Rejecting tx ${tx.getTxHash()}: contract class id mismatch. Claimed ${event.contractClassId}, computed ${computedClassId}`,
161
+ );
162
+ return TX_ERROR_INCORRECT_CONTRACT_CLASS_ID;
163
+ }
164
+ } catch (e) {
165
+ this.#log.warn(`Rejecting tx ${tx.getTxHash()}: failed to compute contract class id: ${e}`);
166
+ return TX_ERROR_MALFORMED_CONTRACT_CLASS_LOG;
167
+ }
168
+ }
169
+ return undefined;
170
+ }
130
171
  }
@@ -53,12 +53,13 @@ import type { TxMetaData } from '../../mem_pools/tx_pool_v2/tx_metadata.js';
53
53
  import { AggregateTxValidator } from './aggregate_tx_validator.js';
54
54
  import { ArchiveCache } from './archive_cache.js';
55
55
  import { type ArchiveSource, BlockHeaderTxValidator } from './block_header_validator.js';
56
+ import { ContractInstanceTxValidator } from './contract_instance_validator.js';
56
57
  import { DataTxValidator } from './data_validator.js';
57
58
  import { DoubleSpendTxValidator, type NullifierSource } from './double_spend_validator.js';
58
- import { GasLimitsValidator, GasTxValidator } from './gas_validator.js';
59
+ import { GasLimitsValidator, GasTxValidator, MaxFeePerGasValidator } from './gas_validator.js';
59
60
  import { MetadataTxValidator } from './metadata_validator.js';
60
61
  import { NullifierCache } from './nullifier_cache.js';
61
- import { PhasesTxValidator } from './phases_validator.js';
62
+ import { AllowedSetupCallsMetaValidator, PhasesTxValidator } from './phases_validator.js';
62
63
  import { SizeTxValidator } from './size_validator.js';
63
64
  import { TimestampTxValidator } from './timestamp_validator.js';
64
65
  import { TxPermittedValidator } from './tx_permitted_validator.js';
@@ -167,6 +168,10 @@ export function createFirstStageTxValidationsForGossipedTransactions(
167
168
  validator: new DataTxValidator(bindings),
168
169
  severity: PeerErrorSeverity.MidToleranceError,
169
170
  },
171
+ contractInstanceValidator: {
172
+ validator: new ContractInstanceTxValidator(bindings),
173
+ severity: PeerErrorSeverity.MidToleranceError,
174
+ },
170
175
  };
171
176
  }
172
177
 
@@ -218,6 +223,7 @@ function createTxValidatorForMinimumTxIntegrityChecks(
218
223
  ),
219
224
  new SizeTxValidator(bindings),
220
225
  new DataTxValidator(bindings),
226
+ new ContractInstanceTxValidator(bindings),
221
227
  new TxProofValidator(verifier, bindings),
222
228
  );
223
229
  }
@@ -321,6 +327,7 @@ export function createTxValidatorForAcceptingTxsOverRPC(
321
327
  new BlockHeaderTxValidator(new ArchiveCache(db), bindings),
322
328
  new DoubleSpendTxValidator(new NullifierCache(db), bindings),
323
329
  new DataTxValidator(bindings),
330
+ new ContractInstanceTxValidator(bindings),
324
331
  ];
325
332
 
326
333
  if (!skipFeeEnforcement) {
@@ -416,6 +423,7 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
416
423
  timestamp: bigint,
417
424
  blockNumber: BlockNumber,
418
425
  gasLimitOpts: { rollupManaLimit?: number; maxBlockL2Gas?: number; maxBlockDAGas?: number },
426
+ gasFees: GasFees,
419
427
  bindings?: LoggerBindings,
420
428
  ): Promise<TxValidator<TxMetaData>> {
421
429
  await worldStateSynchronizer.syncImmediate();
@@ -433,8 +441,29 @@ export async function createTxValidatorForTransactionsEnteringPendingTxPool(
433
441
  };
434
442
  return new AggregateTxValidator<TxMetaData>(
435
443
  new GasLimitsValidator<TxMetaData>({ ...gasLimitOpts, bindings }),
444
+ new MaxFeePerGasValidator<TxMetaData>(gasFees, bindings),
436
445
  new TimestampTxValidator<TxMetaData>({ timestamp, blockNumber }, bindings),
437
446
  new DoubleSpendTxValidator<TxMetaData>(nullifierSource, bindings),
438
447
  new BlockHeaderTxValidator<TxMetaData>(archiveSource, bindings),
448
+ new AllowedSetupCallsMetaValidator<TxMetaData>(bindings),
439
449
  );
440
450
  }
451
+
452
+ /**
453
+ * Creates a function that checks whether a tx's setup-phase calls are on the allow list.
454
+ *
455
+ * Uses the `PhasesTxValidator` on the full Tx. The result is stored as a boolean
456
+ * flag in `TxMetaData.allowedSetupCalls` at receipt time, so the pending pool
457
+ * migration validator can check it without needing the full Tx or its dependencies.
458
+ */
459
+ export function createCheckAllowedSetupCalls(
460
+ contractDataSource: ContractDataSource,
461
+ setupAllowList: AllowedElement[],
462
+ getTimestamp: () => UInt64,
463
+ ): (tx: Tx) => Promise<boolean> {
464
+ return async (tx: Tx) => {
465
+ const validator = new PhasesTxValidator(contractDataSource, setupAllowList, getTimestamp());
466
+ const result = await validator.validateTx(tx);
467
+ return result.result === 'valid';
468
+ };
469
+ }
@@ -36,6 +36,18 @@ export interface HasGasLimitData {
36
36
  };
37
37
  }
38
38
 
39
+ /** Structural interface for types that carry max fee per gas data, used by {@link MaxFeePerGasValidator}. */
40
+ export interface HasMaxFeePerGasData {
41
+ txHash: { toString(): string };
42
+ data: {
43
+ constants: {
44
+ txContext: {
45
+ gasSettings: { maxFeesPerGas: GasFees };
46
+ };
47
+ };
48
+ };
49
+ }
50
+
39
51
  /**
40
52
  * Validates that a transaction's gas limits are within acceptable bounds.
41
53
  *
@@ -87,7 +99,12 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
87
99
  gasLimits,
88
100
  minGasLimits,
89
101
  });
90
- return { result: 'invalid', reason: [TX_ERROR_INSUFFICIENT_GAS_LIMIT] };
102
+ return {
103
+ result: 'invalid',
104
+ reason: [
105
+ `${TX_ERROR_INSUFFICIENT_GAS_LIMIT} (required=da:${minGasLimits.daGas},l2:${minGasLimits.l2Gas} got=da:${gasLimits.daGas},l2:${gasLimits.l2Gas})`,
106
+ ],
107
+ };
91
108
  }
92
109
 
93
110
  if (gasLimits.l2Gas > this.#effectiveMaxL2Gas) {
@@ -97,7 +114,10 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
97
114
  rollupManaLimit: this.#rollupManaLimit,
98
115
  maxBlockL2Gas: this.#maxBlockL2Gas,
99
116
  });
100
- return { result: 'invalid', reason: [TX_ERROR_GAS_LIMIT_TOO_HIGH] };
117
+ return {
118
+ result: 'invalid',
119
+ reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (l2Gas=${gasLimits.l2Gas}, max=${this.#effectiveMaxL2Gas})`],
120
+ };
101
121
  }
102
122
 
103
123
  if (gasLimits.daGas > this.#effectiveMaxDAGas) {
@@ -106,22 +126,70 @@ export class GasLimitsValidator<T extends HasGasLimitData> implements TxValidato
106
126
  effectiveMaxDAGas: this.#effectiveMaxDAGas,
107
127
  maxBlockDAGas: this.#maxBlockDAGas,
108
128
  });
109
- return { result: 'invalid', reason: [TX_ERROR_GAS_LIMIT_TOO_HIGH] };
129
+ return {
130
+ result: 'invalid',
131
+ reason: [`${TX_ERROR_GAS_LIMIT_TOO_HIGH} (daGas=${gasLimits.daGas}, max=${this.#effectiveMaxDAGas})`],
132
+ };
110
133
  }
111
134
 
112
135
  return { result: 'valid' };
113
136
  }
114
137
  }
115
138
 
139
+ /**
140
+ * Validates that a transaction's max fee per gas meets the current block's gas fees.
141
+ *
142
+ * Rejects transactions whose maxFeesPerGas is below the current block's gas fees
143
+ * on either dimension (DA or L2). This is a cheap, stateless check.
144
+ *
145
+ * Generic over T so it can validate both full {@link Tx} objects and {@link TxMetaData}
146
+ * (used during pending pool migration).
147
+ *
148
+ * Used by: pending pool migration (via factory), and indirectly by {@link GasTxValidator}.
149
+ */
150
+ export class MaxFeePerGasValidator<T extends HasMaxFeePerGasData> implements TxValidator<T> {
151
+ #log: Logger;
152
+ #gasFees: GasFees;
153
+
154
+ constructor(gasFees: GasFees, bindings?: LoggerBindings) {
155
+ this.#log = createLogger('sequencer:tx_validator:tx_gas', bindings);
156
+ this.#gasFees = gasFees;
157
+ }
158
+
159
+ validateTx(tx: T): Promise<TxValidationResult> {
160
+ return Promise.resolve(this.validateMaxFeePerGas(tx));
161
+ }
162
+
163
+ /** Checks maxFeesPerGas >= current block gas fees on both dimensions. */
164
+ validateMaxFeePerGas(tx: T): TxValidationResult {
165
+ const maxFeesPerGas = tx.data.constants.txContext.gasSettings.maxFeesPerGas;
166
+ const notEnoughMaxFees =
167
+ maxFeesPerGas.feePerDaGas < this.#gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < this.#gasFees.feePerL2Gas;
168
+
169
+ if (notEnoughMaxFees) {
170
+ this.#log.verbose(`Rejecting transaction ${tx.txHash.toString()} due to insufficient fee per gas`, {
171
+ txMaxFeesPerGas: maxFeesPerGas.toInspect(),
172
+ currentGasFees: this.#gasFees.toInspect(),
173
+ });
174
+ return {
175
+ result: 'invalid',
176
+ reason: [
177
+ `${TX_ERROR_INSUFFICIENT_FEE_PER_GAS} (maxFee=da:${maxFeesPerGas.feePerDaGas},l2:${maxFeesPerGas.feePerL2Gas} required=da:${this.#gasFees.feePerDaGas},l2:${this.#gasFees.feePerL2Gas})`,
178
+ ],
179
+ };
180
+ }
181
+ return { result: 'valid' };
182
+ }
183
+ }
184
+
116
185
  /**
117
186
  * Validates that a transaction can pay its gas fees.
118
187
  *
119
188
  * Runs three checks in order:
120
189
  * 1. **Gas limits** (delegates to {@link GasLimitsValidator}) — rejects if limits are
121
190
  * out of bounds.
122
- * 2. **Max fee per gas** — skips (not rejects) the tx if its maxFeesPerGas is below
123
- * the current block's gas fees. We skip rather than reject because the tx may
124
- * become eligible in a later block with lower fees.
191
+ * 2. **Max fee per gas** — rejects the tx if its maxFeesPerGas is below
192
+ * the current block's gas fees.
125
193
  * 3. **Fee payer balance** — reads the fee payer's FeeJuice balance from public state,
126
194
  * adds any pending claim from a setup-phase `_increase_public_balance` call, and
127
195
  * rejects if the total is less than the tx's fee limit (gasLimits * maxFeePerGas).
@@ -155,37 +223,15 @@ export class GasTxValidator implements TxValidator<Tx> {
155
223
  bindings: this.bindings,
156
224
  }).validateGasLimit(tx);
157
225
  if (gasLimitValidation.result === 'invalid') {
158
- return Promise.resolve(gasLimitValidation);
226
+ return gasLimitValidation;
159
227
  }
160
- if (this.#shouldSkip(tx)) {
161
- return Promise.resolve({ result: 'skipped', reason: [TX_ERROR_INSUFFICIENT_FEE_PER_GAS] });
228
+ const maxFeeValidation = new MaxFeePerGasValidator(this.#gasFees, this.bindings).validateMaxFeePerGas(tx);
229
+ if (maxFeeValidation.result === 'invalid') {
230
+ return maxFeeValidation;
162
231
  }
163
232
  return await this.validateTxFee(tx);
164
233
  }
165
234
 
166
- /**
167
- * Check whether the tx's max fees are valid for the current block, and skip if not.
168
- * We skip instead of invalidating since the tx may become eligible later.
169
- * Note that circuits check max fees even if fee payer is unset, so we
170
- * keep this validation even if the tx does not pay fees.
171
- */
172
- #shouldSkip(tx: Tx): boolean {
173
- const gasSettings = tx.data.constants.txContext.gasSettings;
174
-
175
- // Skip the tx if its max fees are not enough for the current block's gas fees.
176
- const maxFeesPerGas = gasSettings.maxFeesPerGas;
177
- const notEnoughMaxFees =
178
- maxFeesPerGas.feePerDaGas < this.#gasFees.feePerDaGas || maxFeesPerGas.feePerL2Gas < this.#gasFees.feePerL2Gas;
179
-
180
- if (notEnoughMaxFees) {
181
- this.#log.verbose(`Skipping transaction ${tx.getTxHash().toString()} due to insufficient fee per gas`, {
182
- txMaxFeesPerGas: maxFeesPerGas.toInspect(),
183
- currentGasFees: this.#gasFees.toInspect(),
184
- });
185
- }
186
- return notEnoughMaxFees;
187
- }
188
-
189
235
  /**
190
236
  * Checks the fee payer has enough FeeJuice balance to cover the tx's fee limit.
191
237
  * Accounts for any pending claim from a setup-phase `_increase_public_balance` call.
@@ -212,7 +258,10 @@ export class GasTxValidator implements TxValidator<Tx> {
212
258
  balance,
213
259
  feeLimit,
214
260
  });
215
- return { result: 'invalid', reason: [TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE] };
261
+ return {
262
+ result: 'invalid',
263
+ reason: [`${TX_ERROR_INSUFFICIENT_FEE_PAYER_BALANCE} (required=${feeLimit}, available=${balance})`],
264
+ };
216
265
  }
217
266
  return { result: 'valid' };
218
267
  }