@aztec/p2p 0.0.1-commit.64b6bbb → 0.0.1-commit.684755437

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 (295) hide show
  1. package/dest/client/factory.d.ts +7 -7
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +24 -30
  4. package/dest/client/interface.d.ts +14 -19
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +9 -18
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +52 -96
  9. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -7
  10. package/dest/config.d.ts +31 -15
  11. package/dest/config.d.ts.map +1 -1
  12. package/dest/config.js +71 -37
  13. package/dest/errors/tx-pool.error.d.ts +8 -0
  14. package/dest/errors/tx-pool.error.d.ts.map +1 -0
  15. package/dest/errors/tx-pool.error.js +9 -0
  16. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +4 -2
  17. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  18. package/dest/mem_pools/attestation_pool/attestation_pool.js +10 -1
  19. package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
  20. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/mocks.js +2 -2
  22. package/dest/mem_pools/instrumentation.d.ts +4 -2
  23. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  24. package/dest/mem_pools/instrumentation.js +16 -14
  25. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +3 -3
  26. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +30 -13
  27. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +91 -20
  29. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
  30. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
  31. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
  32. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  33. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  34. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +5 -2
  35. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
  36. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  37. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +12 -4
  38. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
  39. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  40. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
  41. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +54 -5
  42. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  43. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
  44. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
  45. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +7 -5
  46. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
  47. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  48. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
  49. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
  50. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  51. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +16 -4
  52. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
  53. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  54. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +3 -3
  55. package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -2
  56. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
  57. package/dest/mem_pools/tx_pool_v2/index.js +1 -1
  58. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  59. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  60. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  61. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +22 -6
  62. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  63. package/dest/mem_pools/tx_pool_v2/interfaces.js +5 -1
  64. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +48 -14
  65. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  66. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +100 -17
  67. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
  68. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  69. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +50 -45
  70. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -4
  71. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  72. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +14 -6
  73. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +14 -5
  74. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  75. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +300 -142
  76. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -4
  77. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  78. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +10 -2
  79. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -4
  80. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  81. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +16 -2
  82. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -8
  83. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  84. package/dest/msg_validators/proposal_validator/proposal_validator.js +48 -36
  85. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +2 -2
  86. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  87. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
  88. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  89. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  90. package/dest/msg_validators/tx_validator/allowed_public_setup.js +24 -20
  91. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  92. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  93. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  94. package/dest/msg_validators/tx_validator/factory.d.ts +114 -6
  95. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  96. package/dest/msg_validators/tx_validator/factory.js +219 -58
  97. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +1 -1
  98. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -1
  99. package/dest/msg_validators/tx_validator/fee_payer_balance.js +6 -2
  100. package/dest/msg_validators/tx_validator/gas_validator.d.ts +58 -3
  101. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  102. package/dest/msg_validators/tx_validator/gas_validator.js +73 -36
  103. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  104. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  105. package/dest/msg_validators/tx_validator/index.js +2 -0
  106. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +1 -1
  107. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  108. package/dest/msg_validators/tx_validator/metadata_validator.js +4 -4
  109. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  110. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  111. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  112. package/dest/msg_validators/tx_validator/phases_validator.d.ts +2 -2
  113. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  114. package/dest/msg_validators/tx_validator/phases_validator.js +44 -23
  115. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +2 -2
  116. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  117. package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
  118. package/dest/services/dummy_service.d.ts +4 -4
  119. package/dest/services/dummy_service.d.ts.map +1 -1
  120. package/dest/services/dummy_service.js +4 -4
  121. package/dest/services/encoding.d.ts +2 -2
  122. package/dest/services/encoding.d.ts.map +1 -1
  123. package/dest/services/encoding.js +9 -8
  124. package/dest/services/gossipsub/topic_score_params.d.ts +18 -6
  125. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  126. package/dest/services/gossipsub/topic_score_params.js +32 -10
  127. package/dest/services/libp2p/libp2p_service.d.ts +16 -13
  128. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  129. package/dest/services/libp2p/libp2p_service.js +84 -90
  130. package/dest/services/peer-manager/metrics.d.ts +3 -1
  131. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  132. package/dest/services/peer-manager/metrics.js +6 -0
  133. package/dest/services/peer-manager/peer_manager.d.ts +1 -1
  134. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  135. package/dest/services/peer-manager/peer_manager.js +2 -1
  136. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
  137. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  138. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +19 -46
  139. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
  140. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  141. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -13
  142. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  143. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +25 -46
  144. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +17 -11
  145. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  146. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +49 -15
  147. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
  148. package/dest/services/reqresp/reqresp.d.ts +1 -1
  149. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  150. package/dest/services/reqresp/reqresp.js +2 -1
  151. package/dest/services/service.d.ts +5 -3
  152. package/dest/services/service.d.ts.map +1 -1
  153. package/dest/services/tx_collection/config.d.ts +13 -1
  154. package/dest/services/tx_collection/config.d.ts.map +1 -1
  155. package/dest/services/tx_collection/config.js +30 -0
  156. package/dest/services/tx_collection/fast_tx_collection.d.ts +1 -1
  157. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  158. package/dest/services/tx_collection/fast_tx_collection.js +39 -33
  159. package/dest/services/tx_collection/file_store_tx_collection.d.ts +38 -29
  160. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  161. package/dest/services/tx_collection/file_store_tx_collection.js +126 -77
  162. package/dest/services/tx_collection/file_store_tx_source.d.ts +16 -6
  163. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  164. package/dest/services/tx_collection/file_store_tx_source.js +49 -16
  165. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  166. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  167. package/dest/services/tx_collection/instrumentation.js +2 -1
  168. package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
  169. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
  170. package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
  171. package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
  172. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  173. package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
  174. package/dest/services/tx_collection/slow_tx_collection.d.ts +5 -3
  175. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  176. package/dest/services/tx_collection/slow_tx_collection.js +17 -12
  177. package/dest/services/tx_collection/tx_collection.d.ts +9 -6
  178. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  179. package/dest/services/tx_collection/tx_collection.js +26 -10
  180. package/dest/services/tx_collection/tx_collection_sink.d.ts +6 -5
  181. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  182. package/dest/services/tx_collection/tx_collection_sink.js +13 -22
  183. package/dest/services/tx_collection/tx_source.d.ts +8 -3
  184. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  185. package/dest/services/tx_collection/tx_source.js +19 -2
  186. package/dest/services/tx_file_store/tx_file_store.d.ts +3 -2
  187. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  188. package/dest/services/tx_file_store/tx_file_store.js +9 -6
  189. package/dest/services/tx_provider.d.ts +3 -3
  190. package/dest/services/tx_provider.d.ts.map +1 -1
  191. package/dest/services/tx_provider.js +4 -4
  192. package/dest/test-helpers/make-test-p2p-clients.d.ts +5 -6
  193. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  194. package/dest/test-helpers/make-test-p2p-clients.js +1 -2
  195. package/dest/test-helpers/mock-pubsub.d.ts +4 -4
  196. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  197. package/dest/test-helpers/mock-pubsub.js +8 -2
  198. package/dest/test-helpers/reqresp-nodes.d.ts +2 -3
  199. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  200. package/dest/test-helpers/reqresp-nodes.js +2 -2
  201. package/dest/test-helpers/testbench-utils.d.ts +8 -3
  202. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  203. package/dest/test-helpers/testbench-utils.js +7 -1
  204. package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
  205. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  206. package/dest/testbench/p2p_client_testbench_worker.js +15 -14
  207. package/dest/testbench/worker_client_manager.d.ts +3 -1
  208. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  209. package/dest/testbench/worker_client_manager.js +6 -2
  210. package/dest/util.d.ts +3 -3
  211. package/dest/util.d.ts.map +1 -1
  212. package/package.json +14 -14
  213. package/src/client/factory.ts +41 -49
  214. package/src/client/interface.ts +17 -20
  215. package/src/client/p2p_client.ts +60 -126
  216. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +20 -11
  217. package/src/config.ts +100 -43
  218. package/src/errors/tx-pool.error.ts +12 -0
  219. package/src/mem_pools/attestation_pool/attestation_pool.ts +13 -4
  220. package/src/mem_pools/attestation_pool/mocks.ts +2 -1
  221. package/src/mem_pools/instrumentation.ts +17 -13
  222. package/src/mem_pools/tx_pool/README.md +1 -1
  223. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
  224. package/src/mem_pools/tx_pool_v2/README.md +52 -28
  225. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +109 -22
  226. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
  227. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +5 -2
  228. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +18 -4
  229. package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
  230. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +59 -4
  231. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
  232. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
  233. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
  234. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +33 -6
  235. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +4 -3
  236. package/src/mem_pools/tx_pool_v2/index.ts +1 -1
  237. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  238. package/src/mem_pools/tx_pool_v2/interfaces.ts +24 -6
  239. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +145 -25
  240. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +58 -45
  241. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +21 -7
  242. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +333 -138
  243. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +14 -4
  244. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +20 -7
  245. package/src/msg_validators/proposal_validator/proposal_validator.ts +63 -40
  246. package/src/msg_validators/tx_validator/README.md +115 -0
  247. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -3
  248. package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
  249. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  250. package/src/msg_validators/tx_validator/factory.ts +353 -77
  251. package/src/msg_validators/tx_validator/fee_payer_balance.ts +6 -2
  252. package/src/msg_validators/tx_validator/gas_validator.ts +90 -27
  253. package/src/msg_validators/tx_validator/index.ts +2 -0
  254. package/src/msg_validators/tx_validator/metadata_validator.ts +12 -4
  255. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  256. package/src/msg_validators/tx_validator/phases_validator.ts +51 -26
  257. package/src/msg_validators/tx_validator/timestamp_validator.ts +7 -7
  258. package/src/services/dummy_service.ts +6 -6
  259. package/src/services/encoding.ts +7 -7
  260. package/src/services/gossipsub/README.md +29 -14
  261. package/src/services/gossipsub/topic_score_params.ts +49 -13
  262. package/src/services/libp2p/libp2p_service.ts +95 -96
  263. package/src/services/peer-manager/metrics.ts +7 -0
  264. package/src/services/peer-manager/peer_manager.ts +2 -1
  265. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +20 -48
  266. package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
  267. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
  268. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +63 -24
  269. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
  270. package/src/services/reqresp/reqresp.ts +3 -1
  271. package/src/services/service.ts +11 -2
  272. package/src/services/tx_collection/config.ts +42 -0
  273. package/src/services/tx_collection/fast_tx_collection.ts +51 -30
  274. package/src/services/tx_collection/file_store_tx_collection.ts +143 -93
  275. package/src/services/tx_collection/file_store_tx_source.ts +64 -17
  276. package/src/services/tx_collection/instrumentation.ts +7 -1
  277. package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
  278. package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
  279. package/src/services/tx_collection/slow_tx_collection.ts +17 -13
  280. package/src/services/tx_collection/tx_collection.ts +45 -14
  281. package/src/services/tx_collection/tx_collection_sink.ts +15 -29
  282. package/src/services/tx_collection/tx_source.ts +22 -3
  283. package/src/services/tx_file_store/tx_file_store.ts +6 -4
  284. package/src/services/tx_provider.ts +2 -2
  285. package/src/test-helpers/make-test-p2p-clients.ts +1 -3
  286. package/src/test-helpers/mock-pubsub.ts +13 -6
  287. package/src/test-helpers/reqresp-nodes.ts +3 -6
  288. package/src/test-helpers/testbench-utils.ts +11 -3
  289. package/src/testbench/p2p_client_testbench_worker.ts +24 -20
  290. package/src/testbench/worker_client_manager.ts +13 -5
  291. package/src/util.ts +8 -2
  292. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +0 -23
  293. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +0 -1
  294. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +0 -212
  295. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +0 -230
@@ -1,5 +1,6 @@
1
1
  import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
2
  import type { Logger } from '@aztec/foundation/log';
3
+ import type { DateProvider } from '@aztec/foundation/timer';
3
4
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
4
5
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
5
6
  import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
@@ -8,6 +9,7 @@ import type { L2Block, L2BlockId, L2BlockSource } from '@aztec/stdlib/block';
8
9
  import type { WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
9
10
  import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
10
11
  import { BlockHeader, Tx, TxHash, type TxValidator } from '@aztec/stdlib/tx';
12
+ import type { TelemetryClient } from '@aztec/telemetry-client';
11
13
 
12
14
  import { TxArchive } from './archive/index.js';
13
15
  import { DeletedPool } from './deleted_pool.js';
@@ -21,8 +23,12 @@ import {
21
23
  LowPriorityPreAddRule,
22
24
  NullifierConflictRule,
23
25
  type PoolOperations,
26
+ type PreAddContext,
24
27
  type PreAddPoolAccess,
28
+ TxPoolRejectionCode,
29
+ type TxPoolRejectionError,
25
30
  } from './eviction/index.js';
31
+ import { TxPoolV2Instrumentation } from './instrumentation.js';
26
32
  import {
27
33
  type AddTxsResult,
28
34
  DEFAULT_TX_POOL_V2_CONFIG,
@@ -39,6 +45,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
39
45
  export interface TxPoolV2Callbacks {
40
46
  onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
41
47
  onTxsRemoved: (txHashes: string[] | bigint[]) => void;
48
+ onTxsMined: (txHashes: string[]) => void;
42
49
  }
43
50
 
44
51
  /**
@@ -64,6 +71,9 @@ export class TxPoolV2Impl {
64
71
  #archive: TxArchive;
65
72
  #deletedPool: DeletedPool;
66
73
  #evictionManager: EvictionManager;
74
+ #dateProvider: DateProvider;
75
+ #instrumentation: TxPoolV2Instrumentation;
76
+ #evictedTxHashes: Set<string> = new Set();
67
77
  #log: Logger;
68
78
  #callbacks: TxPoolV2Callbacks;
69
79
 
@@ -72,7 +82,9 @@ export class TxPoolV2Impl {
72
82
  archiveStore: AztecAsyncKVStore,
73
83
  deps: TxPoolV2Dependencies,
74
84
  callbacks: TxPoolV2Callbacks,
85
+ telemetry: TelemetryClient,
75
86
  config: Partial<TxPoolV2Config> = {},
87
+ dateProvider: DateProvider,
76
88
  log: Logger,
77
89
  ) {
78
90
  this.#store = store;
@@ -85,6 +97,8 @@ export class TxPoolV2Impl {
85
97
  this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
86
98
  this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
87
99
  this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
100
+ this.#dateProvider = dateProvider;
101
+ this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
88
102
  this.#log = log;
89
103
  this.#callbacks = callbacks;
90
104
 
@@ -164,16 +178,45 @@ export class TxPoolV2Impl {
164
178
  await this.#txsDB.delete(txHashStr);
165
179
  }
166
180
  });
167
- this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`);
181
+ this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
168
182
  }
169
183
 
170
- async addPendingTxs(txs: Tx[], opts: { source?: string }): Promise<AddTxsResult> {
184
+ async addPendingTxs(txs: Tx[], opts: { source?: string; feeComparisonOnly?: boolean }): Promise<AddTxsResult> {
171
185
  const accepted: TxHash[] = [];
172
186
  const ignored: TxHash[] = [];
173
187
  const rejected: TxHash[] = [];
188
+ const errors = new Map<string, TxPoolRejectionError>();
174
189
  const acceptedPending = new Set<string>();
175
190
 
191
+ // Phase 1: Pre-compute all throwable I/O outside the transaction.
192
+ // If any pre-computation throws, the entire call fails before mutations happen.
193
+ const precomputed = new Map<string, { meta: TxMetaData; minedBlockId: L2BlockId | undefined; isValid: boolean }>();
194
+
195
+ const validator = await this.#createTxValidator();
196
+
197
+ for (const tx of txs) {
198
+ const txHash = tx.getTxHash();
199
+ const txHashStr = txHash.toString();
200
+
201
+ const meta = await buildTxMetaData(tx);
202
+ const minedBlockId = await this.#getMinedBlockId(txHash);
203
+
204
+ // Validate non-mined txs (mined and pre-protected txs bypass validation inside the transaction)
205
+ let isValid = true;
206
+ if (!minedBlockId) {
207
+ isValid = await this.#validateMeta(meta, validator);
208
+ }
209
+
210
+ precomputed.set(txHashStr, { meta, minedBlockId, isValid });
211
+ }
212
+
213
+ // Phase 2: Apply mutations inside the transaction using only pre-computed results,
214
+ // in-memory reads, and buffered DB writes. Nothing here can throw an unhandled exception.
176
215
  const poolAccess = this.#createPreAddPoolAccess();
216
+ const preAddContext: PreAddContext | undefined =
217
+ opts.feeComparisonOnly !== undefined
218
+ ? { feeComparisonOnly: opts.feeComparisonOnly, priceBumpPercentage: this.#config.priceBumpPercentage }
219
+ : undefined;
177
220
 
178
221
  await this.#store.transactionAsync(async () => {
179
222
  for (const tx of txs) {
@@ -186,30 +229,46 @@ export class TxPoolV2Impl {
186
229
  continue;
187
230
  }
188
231
 
189
- // Check mined status first (applies to all paths)
190
- const minedBlockId = await this.#getMinedBlockId(txHash);
232
+ const { meta, minedBlockId, isValid } = precomputed.get(txHashStr)!;
191
233
  const preProtectedSlot = this.#indices.getProtectionSlot(txHashStr);
192
234
 
193
235
  if (minedBlockId) {
194
236
  // Already mined - add directly (protection already set if pre-protected)
195
- await this.#addTx(tx, { mined: minedBlockId }, opts);
237
+ await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
196
238
  accepted.push(txHash);
197
239
  } else if (preProtectedSlot !== undefined) {
198
240
  // Pre-protected and not mined - add as protected (bypass validation)
199
- await this.#addTx(tx, { protected: preProtectedSlot }, opts);
241
+ await this.#addTx(tx, { protected: preProtectedSlot }, opts, meta);
200
242
  accepted.push(txHash);
243
+ } else if (!isValid) {
244
+ // Failed pre-computed validation
245
+ rejected.push(txHash);
201
246
  } else {
202
- // Regular pending tx - validate and run pre-add rules
203
- const result = await this.#tryAddRegularPendingTx(tx, opts, poolAccess, acceptedPending, ignored);
247
+ // Regular pending tx - run pre-add rules using pre-computed metadata
248
+ const result = await this.#tryAddRegularPendingTx(
249
+ tx,
250
+ meta,
251
+ opts,
252
+ poolAccess,
253
+ acceptedPending,
254
+ ignored,
255
+ errors,
256
+ preAddContext,
257
+ );
204
258
  if (result.status === 'accepted') {
205
259
  acceptedPending.add(txHashStr);
206
- } else if (result.status === 'rejected') {
207
- rejected.push(txHash);
208
260
  } else {
209
261
  ignored.push(txHash);
210
262
  }
211
263
  }
212
264
  }
265
+
266
+ // Run post-add eviction rules for pending txs (inside transaction for atomicity)
267
+ if (acceptedPending.size > 0) {
268
+ const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
269
+ const uniqueFeePayers = new Set<string>(feePayers);
270
+ await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
271
+ }
213
272
  });
214
273
 
215
274
  // Build final accepted list for pending txs (excludes intra-batch evictions)
@@ -217,58 +276,80 @@ export class TxPoolV2Impl {
217
276
  accepted.push(TxHash.fromString(txHashStr));
218
277
  }
219
278
 
220
- // Run post-add eviction rules for pending txs
221
- if (acceptedPending.size > 0) {
222
- const feePayers = Array.from(acceptedPending).map(txHash => this.#indices.getMetadata(txHash)!.feePayer);
223
- const uniqueFeePayers = new Set<string>(feePayers);
224
- await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [...uniqueFeePayers]);
279
+ // Record metrics
280
+ if (ignored.length > 0) {
281
+ this.#instrumentation.recordIgnored(ignored.length);
282
+ }
283
+ if (rejected.length > 0) {
284
+ this.#instrumentation.recordRejected(rejected.length);
225
285
  }
226
286
 
227
- return { accepted, ignored, rejected };
287
+ return { accepted, ignored, rejected, ...(errors.size > 0 ? { errors } : {}) };
228
288
  }
229
289
 
230
- /** Validates and adds a regular pending tx. Returns status. */
290
+ /** Adds a validated pending tx, running pre-add rules and evicting conflicts. */
231
291
  async #tryAddRegularPendingTx(
232
292
  tx: Tx,
293
+ precomputedMeta: TxMetaData,
233
294
  opts: { source?: string },
234
295
  poolAccess: PreAddPoolAccess,
235
296
  acceptedPending: Set<string>,
236
297
  ignored: TxHash[],
237
- ): Promise<{ status: 'accepted' | 'ignored' | 'rejected' }> {
238
- const txHash = tx.getTxHash();
239
- const txHashStr = txHash.toString();
240
-
241
- // Build metadata and validate using metadata
242
- const meta = await buildTxMetaData(tx);
243
- if (!(await this.#validateMeta(meta))) {
244
- return { status: 'rejected' };
245
- }
298
+ errors: Map<string, TxPoolRejectionError>,
299
+ preAddContext?: PreAddContext,
300
+ ): Promise<{ status: 'accepted' | 'ignored' }> {
301
+ const txHashStr = tx.getTxHash().toString();
246
302
 
247
303
  // Run pre-add rules
248
- const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
304
+ const preAddResult = await this.#evictionManager.runPreAddRules(precomputedMeta, poolAccess, preAddContext);
249
305
 
250
306
  if (preAddResult.shouldIgnore) {
251
- this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
307
+ this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
308
+ if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
309
+ errors.set(txHashStr, preAddResult.reason);
310
+ }
252
311
  return { status: 'ignored' };
253
312
  }
254
313
 
255
- // Evict conflicts
256
- for (const evictHashStr of preAddResult.txHashesToEvict) {
257
- await this.#deleteTx(evictHashStr);
258
- this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`);
259
- if (acceptedPending.has(evictHashStr)) {
260
- // Evicted tx was from this batch - mark as ignored in result
261
- acceptedPending.delete(evictHashStr);
262
- ignored.push(TxHash.fromString(evictHashStr));
314
+ // Evict conflicts, grouped by rule name for metrics
315
+ if (preAddResult.evictions && preAddResult.evictions.length > 0) {
316
+ const byReason = new Map<string, string[]>();
317
+ for (const { txHash: evictHash, reason } of preAddResult.evictions) {
318
+ const group = byReason.get(reason);
319
+ if (group) {
320
+ group.push(evictHash);
321
+ } else {
322
+ byReason.set(reason, [evictHash]);
323
+ }
263
324
  }
325
+ for (const [reason, hashes] of byReason) {
326
+ await this.#evictTxs(hashes, reason);
327
+ }
328
+ for (const evictHashStr of preAddResult.txHashesToEvict) {
329
+ this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
330
+ evictedTxHash: evictHashStr,
331
+ replacementTxHash: txHashStr,
332
+ });
333
+ if (acceptedPending.has(evictHashStr)) {
334
+ // Evicted tx was from this batch - mark as ignored in result
335
+ acceptedPending.delete(evictHashStr);
336
+ ignored.push(TxHash.fromString(evictHashStr));
337
+ }
338
+ }
339
+ }
340
+
341
+ // Randomly drop the transaction for testing purposes (report as accepted so it propagates)
342
+ if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
343
+ this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
344
+ return { status: 'accepted' };
264
345
  }
265
346
 
266
347
  // Add the transaction
267
- await this.#addTx(tx, 'pending', opts);
348
+ await this.#addTx(tx, 'pending', opts, precomputedMeta);
268
349
  return { status: 'accepted' };
269
350
  }
270
351
 
271
- async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored' | 'rejected'> {
352
+ async canAddPendingTx(tx: Tx): Promise<'accepted' | 'ignored'> {
272
353
  const txHashStr = tx.getTxHash().toString();
273
354
 
274
355
  // Check if already in pool
@@ -276,14 +357,8 @@ export class TxPoolV2Impl {
276
357
  return 'ignored';
277
358
  }
278
359
 
279
- // Build metadata and validate using metadata
360
+ // Build metadata and check pre-add rules
280
361
  const meta = await buildTxMetaData(tx);
281
- const validationResult = await this.#validateMeta(meta, undefined, 'can add pending');
282
- if (validationResult !== true) {
283
- return 'rejected';
284
- }
285
-
286
- // Use pre-add rules
287
362
  const poolAccess = this.#createPreAddPoolAccess();
288
363
  const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
289
364
 
@@ -320,23 +395,58 @@ export class TxPoolV2Impl {
320
395
  });
321
396
  }
322
397
 
323
- protectTxs(txHashes: TxHash[], block: BlockHeader): TxHash[] {
398
+ async protectTxs(txHashes: TxHash[], block: BlockHeader): Promise<TxHash[]> {
324
399
  const slotNumber = block.globalVariables.slotNumber;
325
400
  const missing: TxHash[] = [];
401
+ let softDeletedHits = 0;
402
+ let missingPreviouslyEvicted = 0;
326
403
 
327
- for (const txHash of txHashes) {
328
- const txHashStr = txHash.toString();
404
+ await this.#store.transactionAsync(async () => {
405
+ for (const txHash of txHashes) {
406
+ const txHashStr = txHash.toString();
329
407
 
330
- if (this.#indices.has(txHashStr)) {
331
- // Update protection for existing tx
332
- this.#indices.updateProtection(txHashStr, slotNumber);
333
- } else {
334
- // Pre-record protection for tx we don't have yet
335
- this.#indices.setProtection(txHashStr, slotNumber);
336
- missing.push(txHash);
408
+ if (this.#indices.has(txHashStr)) {
409
+ // Update protection for existing tx
410
+ this.#indices.updateProtection(txHashStr, slotNumber);
411
+ } else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
412
+ // Resurrect soft-deleted tx as protected
413
+ const buffer = await this.#txsDB.getAsync(txHashStr);
414
+ if (buffer) {
415
+ const tx = Tx.fromBuffer(buffer);
416
+ await this.#addTx(tx, { protected: slotNumber });
417
+ softDeletedHits++;
418
+ } else {
419
+ // Data missing despite soft-delete flag — treat as truly missing
420
+ this.#indices.setProtection(txHashStr, slotNumber);
421
+ missing.push(txHash);
422
+ }
423
+ } else {
424
+ // Truly missing — pre-record protection for tx we don't have yet
425
+ this.#indices.setProtection(txHashStr, slotNumber);
426
+ missing.push(txHash);
427
+ if (this.#evictedTxHashes.has(txHashStr)) {
428
+ missingPreviouslyEvicted++;
429
+ }
430
+ }
337
431
  }
432
+ });
433
+
434
+ // Record metrics
435
+ if (softDeletedHits > 0) {
436
+ this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
437
+ }
438
+ if (missing.length > 0) {
439
+ this.#log.debug(`protectTxs missing tx hashes: ${missing.map(h => h.toString()).join(', ')}`);
440
+ this.#instrumentation.recordMissingOnProtect(missing.length);
441
+ }
442
+ if (missingPreviouslyEvicted > 0) {
443
+ this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
338
444
  }
339
445
 
446
+ this.#log.info(
447
+ `Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`,
448
+ );
449
+
340
450
  return missing;
341
451
  }
342
452
 
@@ -380,54 +490,67 @@ export class TxPoolV2Impl {
380
490
  }
381
491
  }
382
492
 
383
- // Step 4: Mark txs as mined (only those we have in the pool)
384
- for (const meta of found) {
385
- this.#indices.markAsMined(meta, blockId);
386
- await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
387
- }
493
+ await this.#store.transactionAsync(async () => {
494
+ // Step 4: Mark txs as mined (only those we have in the pool)
495
+ for (const meta of found) {
496
+ this.#indices.markAsMined(meta, blockId);
497
+ await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
498
+ }
388
499
 
389
- // Step 5: Run eviction rules (remove pending txs with conflicting nullifiers/expired timestamps)
390
- await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
500
+ // Step 5: Run post-event eviction rules (inside transaction for atomicity)
501
+ await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
502
+ });
503
+
504
+ if (found.length > 0) {
505
+ this.#callbacks.onTxsMined(found.map(m => m.txHash));
506
+ }
391
507
 
392
508
  this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
393
509
  }
394
510
 
395
511
  async prepareForSlot(slotNumber: SlotNumber): Promise<void> {
396
- // Step 1: Find expired protected txs
397
- const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
512
+ await this.#store.transactionAsync(async () => {
513
+ // Step 0: Clean up slot-deleted txs from previous slots
514
+ await this.#deletedPool.cleanupSlotDeleted(slotNumber);
398
515
 
399
- // Step 2: Clear protection for all expired entries (including those without metadata)
400
- this.#indices.clearProtection(expiredProtected);
516
+ // Step 1: Find expired protected txs
517
+ const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
401
518
 
402
- // Step 3: Filter to only txs that have metadata and are not mined
403
- const txsToRestore = this.#indices.filterRestorable(expiredProtected);
404
- if (txsToRestore.length === 0) {
405
- return;
406
- }
519
+ // Step 2: Clear protection for all expired entries (including those without metadata)
520
+ this.#indices.clearProtection(expiredProtected);
407
521
 
408
- this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
522
+ // Step 3: Filter to only txs that have metadata and are not mined
523
+ const txsToRestore = this.#indices.filterRestorable(expiredProtected);
524
+ if (txsToRestore.length === 0) {
525
+ this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
526
+ return;
527
+ }
409
528
 
410
- // Step 4: Validate for pending pool
411
- const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
529
+ this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
412
530
 
413
- // Step 5: Resolve nullifier conflicts and add winners to pending indices
414
- const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
531
+ // Step 4: Validate for pending pool
532
+ const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
415
533
 
416
- // Step 6: Delete invalid and evicted txs
417
- await this.#deleteTxsBatch([...invalid, ...toEvict]);
534
+ // Step 5: Resolve nullifier conflicts and add winners to pending indices
535
+ const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
418
536
 
419
- // Step 7: Run eviction rules (enforce pool size limit)
420
- if (added.length > 0) {
421
- const feePayers = added.map(meta => meta.feePayer);
422
- const uniqueFeePayers = new Set<string>(feePayers);
423
- await this.#evictionManager.evictAfterNewTxs(
424
- added.map(m => m.txHash),
425
- [...uniqueFeePayers],
426
- );
427
- }
537
+ // Step 6: Delete invalid txs and evict conflict losers
538
+ await this.#deleteTxsBatch(invalid);
539
+ await this.#evictTxs(toEvict, 'NullifierConflict');
540
+
541
+ // Step 7: Run eviction rules (enforce pool size limit)
542
+ if (added.length > 0) {
543
+ const feePayers = added.map(meta => meta.feePayer);
544
+ const uniqueFeePayers = new Set<string>(feePayers);
545
+ await this.#evictionManager.evictAfterNewTxs(
546
+ added.map(m => m.txHash),
547
+ [...uniqueFeePayers],
548
+ );
549
+ }
550
+ });
428
551
  }
429
552
 
430
- async handlePrunedBlocks(latestBlock: L2BlockId): Promise<void> {
553
+ async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
431
554
  // Step 1: Find transactions mined after the prune point
432
555
  const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
433
556
  if (txsToUnmine.length === 0) {
@@ -437,43 +560,62 @@ export class TxPoolV2Impl {
437
560
 
438
561
  this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
439
562
 
440
- // Step 2: Mark ALL un-mined txs with their original mined block number
441
- // This ensures they get soft-deleted if removed later, and only hard-deleted
442
- // when their original mined block is finalized
443
- await this.#deletedPool.markFromPrunedBlock(
444
- txsToUnmine.map(m => ({
445
- txHash: m.txHash,
446
- minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
447
- })),
448
- );
563
+ await this.#store.transactionAsync(async () => {
564
+ // Step 2: Mark ALL un-mined txs with their original mined block number
565
+ // This ensures they get soft-deleted if removed later, and only hard-deleted
566
+ // when their original mined block is finalized
567
+ await this.#deletedPool.markFromPrunedBlock(
568
+ txsToUnmine.map(m => ({
569
+ txHash: m.txHash,
570
+ minedAtBlock: BlockNumber(m.minedL2BlockId!.number),
571
+ })),
572
+ );
449
573
 
450
- // Step 3: Unmine - clear mined status from metadata
451
- for (const meta of txsToUnmine) {
452
- this.#indices.markAsUnmined(meta);
453
- }
574
+ // Step 3: Unmine - clear mined status from metadata
575
+ for (const meta of txsToUnmine) {
576
+ this.#indices.markAsUnmined(meta);
577
+ }
454
578
 
455
- // Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
456
- const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
579
+ // If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
580
+ if (options?.deleteAllTxs) {
581
+ const allTxHashes = txsToUnmine.map(m => m.txHash);
582
+ await this.#deleteTxsBatch(allTxHashes);
583
+ this.#log.info(
584
+ `Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`,
585
+ );
586
+ return;
587
+ }
588
+
589
+ // Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
590
+ const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
457
591
 
458
- // Step 4: Validate for pending pool
459
- const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
592
+ // Step 5: Validate for pending pool
593
+ const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
460
594
 
461
- // Step 6: Resolve nullifier conflicts and add winners to pending indices
462
- const { toEvict } = this.#applyNullifierConflictResolution(valid);
595
+ // Step 6: Resolve nullifier conflicts and add winners to pending indices
596
+ const { toEvict } = this.#applyNullifierConflictResolution(valid);
463
597
 
464
- // Step 7: Delete invalid and evicted txs
465
- await this.#deleteTxsBatch([...invalid, ...toEvict]);
598
+ // Step 7: Delete invalid txs and evict conflict losers
599
+ await this.#deleteTxsBatch(invalid);
600
+ await this.#evictTxs(toEvict, 'NullifierConflict');
466
601
 
467
- // Step 8: Run eviction rules for ALL pending txs (not just restored ones)
468
- // This handles cases like existing pending txs with invalid fee payer balances
469
- await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
602
+ this.#log.info(
603
+ `Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`,
604
+ { txHashesRestored: valid.map(m => m.txHash), txHashesInvalid: invalid, txHashesEvicted: toEvict },
605
+ );
606
+
607
+ // Step 8: Run eviction rules for ALL pending txs (not just restored ones)
608
+ // This handles cases like existing pending txs with invalid fee payer balances
609
+ await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
610
+ });
470
611
  }
471
612
 
472
613
  async handleFailedExecution(txHashes: TxHash[]): Promise<void> {
473
- // Delete failed txs
474
- await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
614
+ await this.#store.transactionAsync(async () => {
615
+ await this.#deleteTxsBatch(txHashes.map(h => h.toString()));
616
+ });
475
617
 
476
- this.#log.info(`Deleted ${txHashes.length} failed txs`);
618
+ this.#log.info(`Deleted ${txHashes.length} failed txs`, { txHashes: txHashes.map(h => h.toString()) });
477
619
  }
478
620
 
479
621
  async handleFinalizedBlock(block: BlockHeader): Promise<void> {
@@ -482,30 +624,34 @@ export class TxPoolV2Impl {
482
624
  // Step 1: Find mined txs at or before finalized block
483
625
  const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
484
626
 
485
- // Step 2: Collect mined txs for archiving (before deletion)
486
- const txsToArchive: Tx[] = [];
487
- if (this.#archive.isEnabled()) {
488
- for (const txHashStr of minedTxsToFinalize) {
489
- const buffer = await this.#txsDB.getAsync(txHashStr);
490
- if (buffer) {
491
- txsToArchive.push(Tx.fromBuffer(buffer));
627
+ await this.#store.transactionAsync(async () => {
628
+ // Step 2: Collect mined txs for archiving (before deletion)
629
+ const txsToArchive: Tx[] = [];
630
+ if (this.#archive.isEnabled()) {
631
+ for (const txHashStr of minedTxsToFinalize) {
632
+ const buffer = await this.#txsDB.getAsync(txHashStr);
633
+ if (buffer) {
634
+ txsToArchive.push(Tx.fromBuffer(buffer));
635
+ }
492
636
  }
493
637
  }
494
- }
495
638
 
496
- // Step 3: Delete mined txs from active pool
497
- await this.#deleteTxsBatch(minedTxsToFinalize);
639
+ // Step 3: Delete mined txs from active pool
640
+ await this.#deleteTxsBatch(minedTxsToFinalize);
498
641
 
499
- // Step 4: Finalize soft-deleted txs
500
- await this.#deletedPool.finalizeBlock(blockNumber);
642
+ // Step 4: Finalize soft-deleted txs
643
+ await this.#deletedPool.finalizeBlock(blockNumber);
501
644
 
502
- // Step 5: Archive mined txs
503
- if (txsToArchive.length > 0) {
504
- await this.#archive.archiveTxs(txsToArchive);
505
- }
645
+ // Step 5: Archive mined txs
646
+ if (txsToArchive.length > 0) {
647
+ await this.#archive.archiveTxs(txsToArchive);
648
+ }
649
+ });
506
650
 
507
651
  if (minedTxsToFinalize.length > 0) {
508
- this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`);
652
+ this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
653
+ txHashes: minedTxsToFinalize,
654
+ });
509
655
  }
510
656
  }
511
657
 
@@ -549,6 +695,13 @@ export class TxPoolV2Impl {
549
695
  return [...this.#indices.iteratePendingByPriority('desc')].map(hash => TxHash.fromString(hash));
550
696
  }
551
697
 
698
+ getEligiblePendingTxHashes(): TxHash[] {
699
+ const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
700
+ return [...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)].map(hash =>
701
+ TxHash.fromString(hash),
702
+ );
703
+ }
704
+
552
705
  getPendingTxCount(): number {
553
706
  return this.#indices.getPendingTxCount();
554
707
  }
@@ -593,6 +746,9 @@ export class TxPoolV2Impl {
593
746
  this.#config.archivedTxLimit = config.archivedTxLimit;
594
747
  this.#archive.updateLimit(config.archivedTxLimit);
595
748
  }
749
+ if (config.minTxPoolAgeMs !== undefined) {
750
+ this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
751
+ }
596
752
  // Update eviction rules with new config
597
753
  this.#evictionManager.updateConfig(config);
598
754
  }
@@ -610,8 +766,17 @@ export class TxPoolV2Impl {
610
766
 
611
767
  // === Metrics ===
612
768
 
613
- countTxs(): { pending: number; protected: number; mined: number } {
614
- return this.#indices.countTxs();
769
+ countTxs(): {
770
+ pending: number;
771
+ protected: number;
772
+ mined: number;
773
+ softDeleted: number;
774
+ totalMetadataBytes: number;
775
+ } {
776
+ return {
777
+ ...this.#indices.countTxs(),
778
+ softDeleted: this.#deletedPool.getSoftDeletedCount(),
779
+ };
615
780
  }
616
781
 
617
782
  // ============================================================================
@@ -626,11 +791,14 @@ export class TxPoolV2Impl {
626
791
  tx: Tx,
627
792
  state: 'pending' | { protected: SlotNumber } | { mined: L2BlockId },
628
793
  opts: { source?: string } = {},
794
+ precomputedMeta?: TxMetaData,
629
795
  ): Promise<TxMetaData> {
630
796
  const txHashStr = tx.getTxHash().toString();
631
- const meta = await buildTxMetaData(tx);
797
+ const meta = precomputedMeta ?? (await buildTxMetaData(tx));
798
+ meta.receivedAt = this.#dateProvider.now();
632
799
 
633
800
  await this.#txsDB.set(txHashStr, tx.toBuffer());
801
+ await this.#deletedPool.clearSoftDeleted(txHashStr);
634
802
  this.#callbacks.onTxsAdded([tx], opts);
635
803
 
636
804
  if (state === 'pending') {
@@ -643,9 +811,11 @@ export class TxPoolV2Impl {
643
811
  }
644
812
 
645
813
  const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
646
- this.#log.verbose(`Added ${stateStr} tx ${txHashStr}`, {
814
+ this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
647
815
  eventName: 'tx-added-to-pool',
816
+ txHash: txHashStr,
648
817
  state: stateStr,
818
+ source: opts.source,
649
819
  });
650
820
 
651
821
  return meta;
@@ -673,6 +843,29 @@ export class TxPoolV2Impl {
673
843
  }
674
844
  }
675
845
 
846
+ /** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */
847
+ async #evictTxs(txHashes: string[], reason: string): Promise<void> {
848
+ if (txHashes.length === 0) {
849
+ return;
850
+ }
851
+ this.#instrumentation.recordEvictions(txHashes.length, reason);
852
+ for (const txHashStr of txHashes) {
853
+ this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
854
+ this.#addToEvictedCache(txHashStr);
855
+ }
856
+ await this.#deleteTxsBatch(txHashes);
857
+ }
858
+
859
+ /** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
860
+ #addToEvictedCache(txHashStr: string): void {
861
+ if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
862
+ // FIFO eviction: remove the first (oldest) entry
863
+ const oldest = this.#evictedTxHashes.values().next().value!;
864
+ this.#evictedTxHashes.delete(oldest);
865
+ }
866
+ this.#evictedTxHashes.add(txHashStr);
867
+ }
868
+
676
869
  // ============================================================================
677
870
  // PRIVATE HELPERS - Validation & Conflict Resolution
678
871
  // ============================================================================
@@ -828,7 +1021,9 @@ export class TxPoolV2Impl {
828
1021
  if (preAddResult.shouldIgnore) {
829
1022
  // Transaction rejected - mark for deletion from DB
830
1023
  rejected.push(meta.txHash);
831
- this.#log.debug(`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason}`);
1024
+ this.#log.debug(
1025
+ `Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`,
1026
+ );
832
1027
  continue;
833
1028
  }
834
1029
 
@@ -864,7 +1059,7 @@ export class TxPoolV2Impl {
864
1059
  getFeePayerPendingTxs: (feePayer: string) => this.#indices.getFeePayerPendingTxs(feePayer),
865
1060
  getPendingTxCount: () => this.#indices.getPendingTxCount(),
866
1061
  getLowestPriorityPending: (limit: number) => this.#indices.getLowestPriorityPending(limit),
867
- deleteTxs: (txHashes: string[]) => this.#deleteTxsBatch(txHashes),
1062
+ deleteTxs: (txHashes: string[], reason?: string) => this.#evictTxs(txHashes, reason ?? 'unknown'),
868
1063
  };
869
1064
  }
870
1065