@aztec/p2p 0.0.1-commit.6d63667d → 0.0.1-commit.733c4a3

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 (315) hide show
  1. package/dest/client/factory.d.ts +7 -6
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +35 -11
  4. package/dest/client/interface.d.ts +45 -32
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +38 -50
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +145 -200
  9. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +6 -6
  10. package/dest/config.d.ts +24 -8
  11. package/dest/config.d.ts.map +1 -1
  12. package/dest/config.js +16 -6
  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/index.d.ts +2 -1
  17. package/dest/index.d.ts.map +1 -1
  18. package/dest/index.js +1 -0
  19. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +104 -88
  20. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/attestation_pool.js +441 -3
  22. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +353 -87
  25. package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
  26. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/index.js +1 -2
  28. package/dest/mem_pools/attestation_pool/mocks.d.ts +2 -2
  29. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/mocks.js +2 -2
  31. package/dest/mem_pools/index.d.ts +3 -2
  32. package/dest/mem_pools/index.d.ts.map +1 -1
  33. package/dest/mem_pools/index.js +1 -1
  34. package/dest/mem_pools/interface.d.ts +5 -5
  35. package/dest/mem_pools/interface.d.ts.map +1 -1
  36. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +3 -3
  37. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
  38. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
  39. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
  40. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +3 -3
  41. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -1
  42. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +18 -9
  43. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  44. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  45. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +5 -2
  46. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +3 -3
  47. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -1
  48. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +10 -4
  49. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -2
  50. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  51. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -1
  52. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +48 -5
  53. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -1
  54. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +8 -0
  55. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +7 -5
  56. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +7 -5
  57. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +2 -2
  58. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +14 -6
  60. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +4 -4
  61. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -1
  62. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +14 -4
  63. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +3 -3
  64. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -1
  65. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +2 -2
  66. package/dest/mem_pools/tx_pool_v2/index.d.ts +2 -1
  67. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -1
  68. package/dest/mem_pools/tx_pool_v2/index.js +1 -0
  69. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  70. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  71. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  72. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +22 -8
  73. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  74. package/dest/mem_pools/tx_pool_v2/interfaces.js +4 -1
  75. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +39 -5
  76. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  77. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +74 -5
  78. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +12 -3
  79. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  80. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +27 -4
  81. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +9 -4
  82. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  83. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +11 -6
  84. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +13 -5
  85. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  86. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +312 -169
  87. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
  88. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  89. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +4 -4
  90. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  91. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +3 -3
  92. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +16 -3
  93. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  94. package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
  95. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +13 -3
  96. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  97. package/dest/msg_validators/tx_validator/double_spend_validator.js +4 -4
  98. package/dest/msg_validators/tx_validator/factory.d.ts +114 -6
  99. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  100. package/dest/msg_validators/tx_validator/factory.js +219 -58
  101. package/dest/msg_validators/tx_validator/gas_validator.d.ts +58 -3
  102. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  103. package/dest/msg_validators/tx_validator/gas_validator.js +73 -36
  104. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  105. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  106. package/dest/msg_validators/tx_validator/index.js +1 -0
  107. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  108. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  109. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  110. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +20 -4
  111. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  112. package/dest/msg_validators/tx_validator/timestamp_validator.js +6 -6
  113. package/dest/services/dummy_service.d.ts +13 -5
  114. package/dest/services/dummy_service.d.ts.map +1 -1
  115. package/dest/services/dummy_service.js +10 -4
  116. package/dest/services/encoding.d.ts +2 -2
  117. package/dest/services/encoding.d.ts.map +1 -1
  118. package/dest/services/encoding.js +4 -3
  119. package/dest/services/gossipsub/index.d.ts +3 -0
  120. package/dest/services/gossipsub/index.d.ts.map +1 -0
  121. package/dest/services/gossipsub/index.js +2 -0
  122. package/dest/services/gossipsub/scoring.d.ts +21 -3
  123. package/dest/services/gossipsub/scoring.d.ts.map +1 -1
  124. package/dest/services/gossipsub/scoring.js +24 -7
  125. package/dest/services/gossipsub/topic_score_params.d.ts +173 -0
  126. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
  127. package/dest/services/gossipsub/topic_score_params.js +346 -0
  128. package/dest/services/libp2p/libp2p_service.d.ts +91 -38
  129. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  130. package/dest/services/libp2p/libp2p_service.js +411 -321
  131. package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
  132. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  133. package/dest/services/peer-manager/peer_scoring.js +25 -2
  134. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -3
  135. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  136. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +19 -46
  137. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +2 -6
  138. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  139. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +10 -13
  140. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  141. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +25 -46
  142. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +17 -11
  143. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  144. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +49 -15
  145. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +2 -2
  146. package/dest/services/reqresp/interface.d.ts +10 -1
  147. package/dest/services/reqresp/interface.d.ts.map +1 -1
  148. package/dest/services/reqresp/interface.js +15 -1
  149. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +4 -3
  150. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  151. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +7 -1
  152. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  153. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +15 -0
  154. package/dest/services/reqresp/protocols/tx.d.ts +7 -1
  155. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  156. package/dest/services/reqresp/protocols/tx.js +20 -0
  157. package/dest/services/reqresp/reqresp.d.ts +1 -1
  158. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  159. package/dest/services/reqresp/reqresp.js +11 -4
  160. package/dest/services/service.d.ts +39 -3
  161. package/dest/services/service.d.ts.map +1 -1
  162. package/dest/services/tx_collection/config.d.ts +19 -1
  163. package/dest/services/tx_collection/config.d.ts.map +1 -1
  164. package/dest/services/tx_collection/config.js +46 -0
  165. package/dest/services/tx_collection/fast_tx_collection.d.ts +3 -1
  166. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  167. package/dest/services/tx_collection/fast_tx_collection.js +56 -36
  168. package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
  169. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
  170. package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
  171. package/dest/services/tx_collection/file_store_tx_source.d.ts +37 -0
  172. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
  173. package/dest/services/tx_collection/file_store_tx_source.js +90 -0
  174. package/dest/services/tx_collection/index.d.ts +2 -1
  175. package/dest/services/tx_collection/index.d.ts.map +1 -1
  176. package/dest/services/tx_collection/index.js +1 -0
  177. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  178. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  179. package/dest/services/tx_collection/instrumentation.js +2 -1
  180. package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
  181. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
  182. package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
  183. package/dest/services/tx_collection/proposal_tx_collector.d.ts +7 -6
  184. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -1
  185. package/dest/services/tx_collection/proposal_tx_collector.js +5 -4
  186. package/dest/services/tx_collection/slow_tx_collection.d.ts +7 -3
  187. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  188. package/dest/services/tx_collection/slow_tx_collection.js +60 -26
  189. package/dest/services/tx_collection/tx_collection.d.ts +23 -10
  190. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  191. package/dest/services/tx_collection/tx_collection.js +75 -3
  192. package/dest/services/tx_collection/tx_collection_sink.d.ts +18 -8
  193. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  194. package/dest/services/tx_collection/tx_collection_sink.js +26 -29
  195. package/dest/services/tx_collection/tx_source.d.ts +8 -3
  196. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  197. package/dest/services/tx_collection/tx_source.js +19 -2
  198. package/dest/services/tx_file_store/config.d.ts +1 -3
  199. package/dest/services/tx_file_store/config.d.ts.map +1 -1
  200. package/dest/services/tx_file_store/config.js +0 -4
  201. package/dest/services/tx_file_store/tx_file_store.d.ts +4 -3
  202. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  203. package/dest/services/tx_file_store/tx_file_store.js +9 -6
  204. package/dest/services/tx_provider.d.ts +4 -4
  205. package/dest/services/tx_provider.d.ts.map +1 -1
  206. package/dest/services/tx_provider.js +9 -8
  207. package/dest/test-helpers/make-test-p2p-clients.d.ts +3 -3
  208. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  209. package/dest/test-helpers/mock-pubsub.d.ts +29 -2
  210. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  211. package/dest/test-helpers/mock-pubsub.js +103 -2
  212. package/dest/test-helpers/reqresp-nodes.d.ts +1 -1
  213. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  214. package/dest/test-helpers/reqresp-nodes.js +2 -1
  215. package/dest/test-helpers/testbench-utils.d.ts +43 -38
  216. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  217. package/dest/test-helpers/testbench-utils.js +128 -59
  218. package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -2
  219. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  220. package/dest/testbench/p2p_client_testbench_worker.js +10 -10
  221. package/dest/util.d.ts +2 -2
  222. package/dest/util.d.ts.map +1 -1
  223. package/package.json +14 -14
  224. package/src/client/factory.ts +66 -14
  225. package/src/client/interface.ts +61 -33
  226. package/src/client/p2p_client.ts +179 -236
  227. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +19 -9
  228. package/src/config.ts +35 -11
  229. package/src/errors/tx-pool.error.ts +12 -0
  230. package/src/index.ts +1 -0
  231. package/src/mem_pools/attestation_pool/attestation_pool.ts +496 -91
  232. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +442 -102
  233. package/src/mem_pools/attestation_pool/index.ts +9 -2
  234. package/src/mem_pools/attestation_pool/mocks.ts +2 -1
  235. package/src/mem_pools/index.ts +4 -1
  236. package/src/mem_pools/interface.ts +4 -4
  237. package/src/mem_pools/tx_pool/README.md +1 -1
  238. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +3 -3
  239. package/src/mem_pools/tx_pool_v2/README.md +76 -10
  240. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  241. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +21 -8
  242. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +5 -2
  243. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +15 -4
  244. package/src/mem_pools/tx_pool_v2/eviction/index.ts +4 -0
  245. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +49 -4
  246. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +5 -5
  247. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +5 -5
  248. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +14 -9
  249. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +24 -6
  250. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +3 -3
  251. package/src/mem_pools/tx_pool_v2/index.ts +1 -0
  252. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  253. package/src/mem_pools/tx_pool_v2/interfaces.ts +23 -8
  254. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +103 -9
  255. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +32 -5
  256. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +18 -7
  257. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +347 -166
  258. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +2 -2
  259. package/src/msg_validators/tx_validator/README.md +115 -0
  260. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +5 -5
  261. package/src/msg_validators/tx_validator/block_header_validator.ts +15 -3
  262. package/src/msg_validators/tx_validator/double_spend_validator.ts +11 -6
  263. package/src/msg_validators/tx_validator/factory.ts +353 -77
  264. package/src/msg_validators/tx_validator/gas_validator.ts +90 -27
  265. package/src/msg_validators/tx_validator/index.ts +1 -0
  266. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  267. package/src/msg_validators/tx_validator/timestamp_validator.ts +23 -18
  268. package/src/services/dummy_service.ts +18 -6
  269. package/src/services/encoding.ts +4 -3
  270. package/src/services/gossipsub/README.md +641 -0
  271. package/src/services/gossipsub/index.ts +2 -0
  272. package/src/services/gossipsub/scoring.ts +29 -5
  273. package/src/services/gossipsub/topic_score_params.ts +487 -0
  274. package/src/services/libp2p/libp2p_service.ts +431 -344
  275. package/src/services/peer-manager/peer_scoring.ts +25 -0
  276. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +20 -48
  277. package/src/services/reqresp/batch-tx-requester/interface.ts +1 -5
  278. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +23 -71
  279. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +63 -24
  280. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +2 -2
  281. package/src/services/reqresp/interface.ts +26 -1
  282. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +4 -3
  283. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +17 -0
  284. package/src/services/reqresp/protocols/tx.ts +22 -0
  285. package/src/services/reqresp/reqresp.ts +13 -3
  286. package/src/services/service.ts +51 -2
  287. package/src/services/tx_collection/config.ts +68 -0
  288. package/src/services/tx_collection/fast_tx_collection.ts +65 -32
  289. package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
  290. package/src/services/tx_collection/file_store_tx_source.ts +117 -0
  291. package/src/services/tx_collection/index.ts +1 -0
  292. package/src/services/tx_collection/instrumentation.ts +7 -1
  293. package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
  294. package/src/services/tx_collection/proposal_tx_collector.ts +8 -7
  295. package/src/services/tx_collection/slow_tx_collection.ts +66 -33
  296. package/src/services/tx_collection/tx_collection.ts +113 -16
  297. package/src/services/tx_collection/tx_collection_sink.ts +30 -34
  298. package/src/services/tx_collection/tx_source.ts +22 -3
  299. package/src/services/tx_file_store/config.ts +0 -6
  300. package/src/services/tx_file_store/tx_file_store.ts +10 -8
  301. package/src/services/tx_provider.ts +10 -9
  302. package/src/test-helpers/make-test-p2p-clients.ts +3 -3
  303. package/src/test-helpers/mock-pubsub.ts +143 -3
  304. package/src/test-helpers/reqresp-nodes.ts +2 -1
  305. package/src/test-helpers/testbench-utils.ts +127 -71
  306. package/src/testbench/p2p_client_testbench_worker.ts +22 -15
  307. package/src/util.ts +7 -1
  308. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -40
  309. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
  310. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -218
  311. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -31
  312. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
  313. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -180
  314. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -320
  315. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -264
@@ -1,10 +1,13 @@
1
+ import { BlockNumber } from '@aztec/foundation/branded-types';
1
2
  import { ProtocolContractAddress } from '@aztec/protocol-contracts';
2
3
  import { computeFeePayerBalanceStorageSlot } from '@aztec/protocol-contracts/fee-juice';
3
4
  import { AztecAddress } from '@aztec/stdlib/aztec-address';
4
5
  import { DatabasePublicStateSource } from '@aztec/stdlib/trees';
5
6
  import { Tx, TxHash } from '@aztec/stdlib/tx';
6
7
  import { TxArchive } from './archive/index.js';
7
- import { EvictionManager, FeePayerBalanceEvictionRule, FeePayerBalancePreAddRule, InvalidTxsAfterMiningRule, InvalidTxsAfterReorgRule, LowPriorityEvictionRule, LowPriorityPreAddRule, NullifierConflictRule } from './eviction/index.js';
8
+ import { DeletedPool } from './deleted_pool.js';
9
+ import { EvictionManager, FeePayerBalanceEvictionRule, FeePayerBalancePreAddRule, InvalidTxsAfterMiningRule, InvalidTxsAfterReorgRule, LowPriorityEvictionRule, LowPriorityPreAddRule, NullifierConflictRule, TxPoolRejectionCode } from './eviction/index.js';
10
+ import { TxPoolV2Instrumentation } from './instrumentation.js';
8
11
  import { DEFAULT_TX_POOL_V2_CONFIG } from './interfaces.js';
9
12
  import { buildTxMetaData, checkNullifierConflict } from './tx_metadata.js';
10
13
  import { TxPoolIndices } from './tx_pool_indices.js';
@@ -19,26 +22,33 @@ import { TxPoolIndices } from './tx_pool_indices.js';
19
22
  // === Dependencies ===
20
23
  #l2BlockSource;
21
24
  #worldStateSynchronizer;
22
- #pendingTxValidator;
25
+ #createTxValidator;
23
26
  // === In-Memory Indices ===
24
27
  #indices = new TxPoolIndices();
25
28
  // === Config & Services ===
26
29
  #config;
27
30
  #archive;
31
+ #deletedPool;
28
32
  #evictionManager;
33
+ #dateProvider;
34
+ #instrumentation;
35
+ #evictedTxHashes = new Set();
29
36
  #log;
30
37
  #callbacks;
31
- constructor(store, archiveStore, deps, callbacks, config = {}, log){
38
+ constructor(store, archiveStore, deps, callbacks, telemetry, config = {}, dateProvider, log){
32
39
  this.#store = store;
33
40
  this.#txsDB = store.openMap('txs');
34
41
  this.#l2BlockSource = deps.l2BlockSource;
35
42
  this.#worldStateSynchronizer = deps.worldStateSynchronizer;
36
- this.#pendingTxValidator = deps.pendingTxValidator;
43
+ this.#createTxValidator = deps.createTxValidator;
37
44
  this.#config = {
38
45
  ...DEFAULT_TX_POOL_V2_CONFIG,
39
46
  ...config
40
47
  };
41
48
  this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
49
+ this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
50
+ this.#dateProvider = dateProvider;
51
+ this.#instrumentation = new TxPoolV2Instrumentation(telemetry, ()=>this.#indices.getTotalMetadataBytes());
42
52
  this.#log = log;
43
53
  this.#callbacks = callbacks;
44
54
  // Setup eviction manager with rules
@@ -69,7 +79,9 @@ import { TxPoolIndices } from './tx_pool_indices.js';
69
79
  * Note: Protected status is lost on restart. All non-mined txs are rebuilt as pending
70
80
  * by running pre-add rules to resolve nullifier conflicts, balance checks, and pool size limits.
71
81
  */ async hydrateFromDatabase() {
72
- // Step 1: Load all transactions from DB
82
+ // Step 0: Hydrate deleted pool state
83
+ await this.#deletedPool.hydrateFromDatabase();
84
+ // Step 1: Load all transactions from DB (excluding soft-deleted)
73
85
  const { loaded, errors: deserializationErrors } = await this.#loadAllTxsFromDb();
74
86
  // Step 2: Check mined status for each tx
75
87
  await this.#markMinedStatusBatch(loaded.map((l)=>l.meta));
@@ -84,7 +96,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
84
96
  }
85
97
  }
86
98
  // Step 4: Validate non-mined transactions
87
- const { valid, invalid } = await this.#validateTxBatch(nonMined, 'on startup');
99
+ const { valid, invalid } = await this.#revalidateMetadata(nonMined.map((e)=>e.meta), 'on startup');
88
100
  // Step 5: Populate mined indices (these don't need conflict resolution)
89
101
  for (const meta of mined){
90
102
  this.#indices.addMined(meta);
@@ -106,14 +118,20 @@ import { TxPoolIndices } from './tx_pool_indices.js';
106
118
  await this.#txsDB.delete(txHashStr);
107
119
  }
108
120
  });
109
- this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`);
121
+ this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, {
122
+ txHashes: toDelete
123
+ });
110
124
  }
111
125
  async addPendingTxs(txs, opts) {
112
126
  const accepted = [];
113
127
  const ignored = [];
114
128
  const rejected = [];
129
+ const errors = new Map();
115
130
  const acceptedPending = new Set();
116
131
  const poolAccess = this.#createPreAddPoolAccess();
132
+ const preAddContext = opts.feeComparisonOnly !== undefined ? {
133
+ feeComparisonOnly: opts.feeComparisonOnly
134
+ } : undefined;
117
135
  await this.#store.transactionAsync(async ()=>{
118
136
  for (const tx of txs){
119
137
  const txHash = tx.getTxHash();
@@ -140,7 +158,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
140
158
  accepted.push(txHash);
141
159
  } else {
142
160
  // Regular pending tx - validate and run pre-add rules
143
- const result = await this.#tryAddRegularPendingTx(tx, opts, poolAccess, acceptedPending, ignored);
161
+ const result = await this.#tryAddRegularPendingTx(tx, opts, poolAccess, acceptedPending, ignored, errors, preAddContext);
144
162
  if (result.status === 'accepted') {
145
163
  acceptedPending.add(txHashStr);
146
164
  } else if (result.status === 'rejected') {
@@ -150,53 +168,91 @@ import { TxPoolIndices } from './tx_pool_indices.js';
150
168
  }
151
169
  }
152
170
  }
171
+ // Run post-add eviction rules for pending txs (inside transaction for atomicity)
172
+ if (acceptedPending.size > 0) {
173
+ const feePayers = Array.from(acceptedPending).map((txHash)=>this.#indices.getMetadata(txHash).feePayer);
174
+ const uniqueFeePayers = new Set(feePayers);
175
+ await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [
176
+ ...uniqueFeePayers
177
+ ]);
178
+ }
153
179
  });
154
180
  // Build final accepted list for pending txs (excludes intra-batch evictions)
155
181
  for (const txHashStr of acceptedPending){
156
182
  accepted.push(TxHash.fromString(txHashStr));
157
183
  }
158
- // Run post-add eviction rules for pending txs
159
- if (acceptedPending.size > 0) {
160
- const feePayers = Array.from(acceptedPending).map((txHash)=>this.#indices.getMetadata(txHash).feePayer);
161
- const uniqueFeePayers = new Set(feePayers);
162
- await this.#evictionManager.evictAfterNewTxs(Array.from(acceptedPending), [
163
- ...uniqueFeePayers
164
- ]);
184
+ // Record metrics
185
+ if (ignored.length > 0) {
186
+ this.#instrumentation.recordIgnored(ignored.length);
187
+ }
188
+ if (rejected.length > 0) {
189
+ this.#instrumentation.recordRejected(rejected.length);
165
190
  }
166
191
  return {
167
192
  accepted,
168
193
  ignored,
169
- rejected
194
+ rejected,
195
+ ...errors.size > 0 ? {
196
+ errors
197
+ } : {}
170
198
  };
171
199
  }
172
- /** Validates and adds a regular pending tx. Returns status. */ async #tryAddRegularPendingTx(tx, opts, poolAccess, acceptedPending, ignored) {
200
+ /** Validates and adds a regular pending tx. Returns status. */ async #tryAddRegularPendingTx(tx, opts, poolAccess, acceptedPending, ignored, errors, preAddContext) {
173
201
  const txHash = tx.getTxHash();
174
202
  const txHashStr = txHash.toString();
175
- // Validate transaction
176
- if (!await this.#validateTx(tx)) {
203
+ // Build metadata and validate using metadata
204
+ const meta = await buildTxMetaData(tx);
205
+ if (!await this.#validateMeta(meta)) {
177
206
  return {
178
207
  status: 'rejected'
179
208
  };
180
209
  }
181
- // Build metadata and run pre-add rules
182
- const meta = await buildTxMetaData(tx);
183
- const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
210
+ // Run pre-add rules
211
+ const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess, preAddContext);
184
212
  if (preAddResult.shouldIgnore) {
185
- this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason}`);
213
+ this.#log.debug(`Ignoring tx ${txHashStr}: ${preAddResult.reason?.message ?? 'unknown reason'}`);
214
+ if (preAddResult.reason && preAddResult.reason.code !== TxPoolRejectionCode.INTERNAL_ERROR) {
215
+ errors.set(txHashStr, preAddResult.reason);
216
+ }
186
217
  return {
187
218
  status: 'ignored'
188
219
  };
189
220
  }
190
- // Evict conflicts
191
- for (const evictHashStr of preAddResult.txHashesToEvict){
192
- await this.#deleteTx(evictHashStr);
193
- this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`);
194
- if (acceptedPending.has(evictHashStr)) {
195
- // Evicted tx was from this batch - mark as ignored in result
196
- acceptedPending.delete(evictHashStr);
197
- ignored.push(TxHash.fromString(evictHashStr));
221
+ // Evict conflicts, grouped by rule name for metrics
222
+ if (preAddResult.evictions && preAddResult.evictions.length > 0) {
223
+ const byReason = new Map();
224
+ for (const { txHash: evictHash, reason } of preAddResult.evictions){
225
+ const group = byReason.get(reason);
226
+ if (group) {
227
+ group.push(evictHash);
228
+ } else {
229
+ byReason.set(reason, [
230
+ evictHash
231
+ ]);
232
+ }
233
+ }
234
+ for (const [reason, hashes] of byReason){
235
+ await this.#evictTxs(hashes, reason);
236
+ }
237
+ for (const evictHashStr of preAddResult.txHashesToEvict){
238
+ this.#log.debug(`Evicted tx ${evictHashStr} due to higher-fee tx ${txHashStr}`, {
239
+ evictedTxHash: evictHashStr,
240
+ replacementTxHash: txHashStr
241
+ });
242
+ if (acceptedPending.has(evictHashStr)) {
243
+ // Evicted tx was from this batch - mark as ignored in result
244
+ acceptedPending.delete(evictHashStr);
245
+ ignored.push(TxHash.fromString(evictHashStr));
246
+ }
198
247
  }
199
248
  }
249
+ // Randomly drop the transaction for testing purposes (report as accepted so it propagates)
250
+ if (this.#config.dropTransactionsProbability > 0 && Math.random() < this.#config.dropTransactionsProbability) {
251
+ this.#log.debug(`Dropping tx ${txHashStr} (simulated drop for testing)`);
252
+ return {
253
+ status: 'accepted'
254
+ };
255
+ }
200
256
  // Add the transaction
201
257
  await this.#addTx(tx, 'pending', opts);
202
258
  return {
@@ -209,12 +265,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
209
265
  if (this.#indices.has(txHashStr)) {
210
266
  return 'ignored';
211
267
  }
212
- // Validate transaction (no logging for dry-run check)
213
- const validationResult = await this.#pendingTxValidator.validateTx(tx);
214
- if (validationResult.result !== 'valid') {
215
- return 'rejected';
216
- }
217
- // Build metadata and use pre-add rules
268
+ // Build metadata and check pre-add rules
218
269
  const meta = await buildTxMetaData(tx);
219
270
  const poolAccess = this.#createPreAddPoolAccess();
220
271
  const preAddResult = await this.#evictionManager.runPreAddRules(meta, poolAccess);
@@ -251,20 +302,53 @@ import { TxPoolIndices } from './tx_pool_indices.js';
251
302
  }
252
303
  });
253
304
  }
254
- protectTxs(txHashes, block) {
305
+ async protectTxs(txHashes, block) {
255
306
  const slotNumber = block.globalVariables.slotNumber;
256
307
  const missing = [];
257
- for (const txHash of txHashes){
258
- const txHashStr = txHash.toString();
259
- if (this.#indices.has(txHashStr)) {
260
- // Update protection for existing tx
261
- this.#indices.updateProtection(txHashStr, slotNumber);
262
- } else {
263
- // Pre-record protection for tx we don't have yet
264
- this.#indices.setProtection(txHashStr, slotNumber);
265
- missing.push(txHash);
308
+ let softDeletedHits = 0;
309
+ let missingPreviouslyEvicted = 0;
310
+ await this.#store.transactionAsync(async ()=>{
311
+ for (const txHash of txHashes){
312
+ const txHashStr = txHash.toString();
313
+ if (this.#indices.has(txHashStr)) {
314
+ // Update protection for existing tx
315
+ this.#indices.updateProtection(txHashStr, slotNumber);
316
+ } else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
317
+ // Resurrect soft-deleted tx as protected
318
+ const buffer = await this.#txsDB.getAsync(txHashStr);
319
+ if (buffer) {
320
+ const tx = Tx.fromBuffer(buffer);
321
+ await this.#addTx(tx, {
322
+ protected: slotNumber
323
+ });
324
+ softDeletedHits++;
325
+ } else {
326
+ // Data missing despite soft-delete flag — treat as truly missing
327
+ this.#indices.setProtection(txHashStr, slotNumber);
328
+ missing.push(txHash);
329
+ }
330
+ } else {
331
+ // Truly missing — pre-record protection for tx we don't have yet
332
+ this.#indices.setProtection(txHashStr, slotNumber);
333
+ missing.push(txHash);
334
+ if (this.#evictedTxHashes.has(txHashStr)) {
335
+ missingPreviouslyEvicted++;
336
+ }
337
+ }
266
338
  }
339
+ });
340
+ // Record metrics
341
+ if (softDeletedHits > 0) {
342
+ this.#instrumentation.recordSoftDeletedHits(softDeletedHits);
343
+ }
344
+ if (missing.length > 0) {
345
+ this.#log.debug(`protectTxs missing tx hashes: ${missing.map((h)=>h.toString()).join(', ')}`);
346
+ this.#instrumentation.recordMissingOnProtect(missing.length);
347
+ }
348
+ if (missingPreviouslyEvicted > 0) {
349
+ this.#instrumentation.recordMissingPreviouslyEvicted(missingPreviouslyEvicted);
267
350
  }
351
+ this.#log.info(`Protected ${txHashes.length} txs, missing: ${missing.length}, soft-deleted hits: ${softDeletedHits}`);
268
352
  return missing;
269
353
  }
270
354
  async addMinedTxs(txs, block, opts) {
@@ -283,6 +367,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
283
367
  mined: blockId
284
368
  }, opts);
285
369
  }
370
+ await this.#deletedPool.clearIfMinedHigher(txHashStr, blockId.number);
286
371
  }
287
372
  });
288
373
  }
@@ -302,44 +387,50 @@ import { TxPoolIndices } from './tx_pool_indices.js';
302
387
  found.push(meta);
303
388
  }
304
389
  }
305
- // Step 4: Mark txs as mined (only those we have in the pool)
306
- for (const meta of found){
307
- this.#indices.markAsMined(meta, blockId);
308
- }
309
- // Step 5: Run eviction rules (remove pending txs with conflicting nullifiers/expired timestamps)
310
- await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
390
+ await this.#store.transactionAsync(async ()=>{
391
+ // Step 4: Mark txs as mined (only those we have in the pool)
392
+ for (const meta of found){
393
+ this.#indices.markAsMined(meta, blockId);
394
+ await this.#deletedPool.clearIfMinedHigher(meta.txHash, blockId.number);
395
+ }
396
+ // Step 5: Run post-event eviction rules (inside transaction for atomicity)
397
+ await this.#evictionManager.evictAfterNewBlock(block.header, nullifiers, feePayers);
398
+ });
311
399
  this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
312
400
  }
313
401
  async prepareForSlot(slotNumber) {
314
- // Step 1: Find expired protected txs
315
- const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
316
- // Step 2: Clear protection for all expired entries (including those without metadata)
317
- this.#indices.clearProtection(expiredProtected);
318
- // Step 3: Filter to only txs that have metadata and are not mined
319
- const txsToRestore = this.#indices.filterRestorable(expiredProtected);
320
- if (txsToRestore.length === 0) {
321
- return;
322
- }
323
- this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
324
- // Step 4: Validate for pending pool
325
- const { valid, invalid } = await this.#loadAndValidateTxs(txsToRestore, 'during prepareForSlot');
326
- // Step 5: Resolve nullifier conflicts and add winners to pending indices
327
- const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
328
- // Step 6: Delete invalid and evicted txs
329
- await this.#deleteTxsBatch([
330
- ...invalid,
331
- ...toEvict
332
- ]);
333
- // Step 7: Run eviction rules (enforce pool size limit)
334
- if (added.length > 0) {
335
- const feePayers = added.map((meta)=>meta.feePayer);
336
- const uniqueFeePayers = new Set(feePayers);
337
- await this.#evictionManager.evictAfterNewTxs(added.map((m)=>m.txHash), [
338
- ...uniqueFeePayers
339
- ]);
340
- }
402
+ await this.#store.transactionAsync(async ()=>{
403
+ // Step 0: Clean up slot-deleted txs from previous slots
404
+ await this.#deletedPool.cleanupSlotDeleted(slotNumber);
405
+ // Step 1: Find expired protected txs
406
+ const expiredProtected = this.#indices.findExpiredProtectedTxs(slotNumber);
407
+ // Step 2: Clear protection for all expired entries (including those without metadata)
408
+ this.#indices.clearProtection(expiredProtected);
409
+ // Step 3: Filter to only txs that have metadata and are not mined
410
+ const txsToRestore = this.#indices.filterRestorable(expiredProtected);
411
+ if (txsToRestore.length === 0) {
412
+ this.#log.debug(`Preparing for slot ${slotNumber}, no txs to unprotect`);
413
+ return;
414
+ }
415
+ this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
416
+ // Step 4: Validate for pending pool
417
+ const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
418
+ // Step 5: Resolve nullifier conflicts and add winners to pending indices
419
+ const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
420
+ // Step 6: Delete invalid txs and evict conflict losers
421
+ await this.#deleteTxsBatch(invalid);
422
+ await this.#evictTxs(toEvict, 'NullifierConflict');
423
+ // Step 7: Run eviction rules (enforce pool size limit)
424
+ if (added.length > 0) {
425
+ const feePayers = added.map((meta)=>meta.feePayer);
426
+ const uniqueFeePayers = new Set(feePayers);
427
+ await this.#evictionManager.evictAfterNewTxs(added.map((m)=>m.txHash), [
428
+ ...uniqueFeePayers
429
+ ]);
430
+ }
431
+ });
341
432
  }
342
- async handlePrunedBlocks(latestBlock) {
433
+ async handlePrunedBlocks(latestBlock, options) {
343
434
  // Step 1: Find transactions mined after the prune point
344
435
  const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
345
436
  if (txsToUnmine.length === 0) {
@@ -347,54 +438,81 @@ import { TxPoolIndices } from './tx_pool_indices.js';
347
438
  return;
348
439
  }
349
440
  this.#log.info(`Handling prune to block ${latestBlock.number}: un-mining ${txsToUnmine.length} txs`);
350
- // Step 2: Unmine - clear mined status from metadata
351
- for (const meta of txsToUnmine){
352
- this.#indices.markAsUnmined(meta);
353
- }
354
- // Step 3: Filter out protected txs (they'll be handled by prepareForSlot)
355
- const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
356
- // Step 4: Validate for pending pool
357
- const { valid, invalid } = await this.#loadAndValidateTxs(unprotectedTxs, 'during handlePrunedBlocks');
358
- // Step 5: Resolve nullifier conflicts and add winners to pending indices
359
- const { toEvict } = this.#applyNullifierConflictResolution(valid);
360
- // Step 6: Delete invalid and evicted txs
361
- await this.#deleteTxsBatch([
362
- ...invalid,
363
- ...toEvict
364
- ]);
365
- // Step 7: Run eviction rules for ALL pending txs (not just restored ones)
366
- // This handles cases like existing pending txs with invalid fee payer balances
367
- await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
441
+ await this.#store.transactionAsync(async ()=>{
442
+ // Step 2: Mark ALL un-mined txs with their original mined block number
443
+ // This ensures they get soft-deleted if removed later, and only hard-deleted
444
+ // when their original mined block is finalized
445
+ await this.#deletedPool.markFromPrunedBlock(txsToUnmine.map((m)=>({
446
+ txHash: m.txHash,
447
+ minedAtBlock: BlockNumber(m.minedL2BlockId.number)
448
+ })));
449
+ // Step 3: Unmine - clear mined status from metadata
450
+ for (const meta of txsToUnmine){
451
+ this.#indices.markAsUnmined(meta);
452
+ }
453
+ // If deleteAllTxs is set (epoch prune), delete all un-mined txs and return early
454
+ if (options?.deleteAllTxs) {
455
+ const allTxHashes = txsToUnmine.map((m)=>m.txHash);
456
+ await this.#deleteTxsBatch(allTxHashes);
457
+ this.#log.info(`Handled prune to block ${latestBlock.number} with deleteAllTxs: deleted ${allTxHashes.length} txs`);
458
+ return;
459
+ }
460
+ // Step 4: Filter out protected txs (they'll be handled by prepareForSlot)
461
+ const unprotectedTxs = this.#indices.filterUnprotected(txsToUnmine);
462
+ // Step 5: Validate for pending pool
463
+ const { valid, invalid } = await this.#revalidateMetadata(unprotectedTxs, 'during handlePrunedBlocks');
464
+ // Step 6: Resolve nullifier conflicts and add winners to pending indices
465
+ const { toEvict } = this.#applyNullifierConflictResolution(valid);
466
+ // Step 7: Delete invalid txs and evict conflict losers
467
+ await this.#deleteTxsBatch(invalid);
468
+ await this.#evictTxs(toEvict, 'NullifierConflict');
469
+ this.#log.info(`Handled prune to block ${latestBlock.number}: ${valid.length} txs restored to pending, ${invalid.length} invalid, ${toEvict.length} evicted due to nullifier conflicts`, {
470
+ txHashesRestored: valid.map((m)=>m.txHash),
471
+ txHashesInvalid: invalid,
472
+ txHashesEvicted: toEvict
473
+ });
474
+ // Step 8: Run eviction rules for ALL pending txs (not just restored ones)
475
+ // This handles cases like existing pending txs with invalid fee payer balances
476
+ await this.#evictionManager.evictAfterChainPrune(latestBlock.number);
477
+ });
368
478
  }
369
479
  async handleFailedExecution(txHashes) {
370
- // Delete failed txs
371
- await this.#deleteTxsBatch(txHashes.map((h)=>h.toString()));
372
- this.#log.info(`Deleted ${txHashes.length} failed txs`);
480
+ await this.#store.transactionAsync(async ()=>{
481
+ await this.#deleteTxsBatch(txHashes.map((h)=>h.toString()));
482
+ });
483
+ this.#log.info(`Deleted ${txHashes.length} failed txs`, {
484
+ txHashes: txHashes.map((h)=>h.toString())
485
+ });
373
486
  }
374
487
  async handleFinalizedBlock(block) {
375
488
  const blockNumber = block.globalVariables.blockNumber;
376
- // Step 1: Find txs mined at or before finalized block
377
- const txsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
378
- if (txsToFinalize.length === 0) {
379
- return;
380
- }
381
- // Step 2: Collect txs for archiving (before deletion)
382
- const txsToArchive = [];
383
- if (this.#archive.isEnabled()) {
384
- for (const txHashStr of txsToFinalize){
385
- const buffer = await this.#txsDB.getAsync(txHashStr);
386
- if (buffer) {
387
- txsToArchive.push(Tx.fromBuffer(buffer));
489
+ // Step 1: Find mined txs at or before finalized block
490
+ const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
491
+ await this.#store.transactionAsync(async ()=>{
492
+ // Step 2: Collect mined txs for archiving (before deletion)
493
+ const txsToArchive = [];
494
+ if (this.#archive.isEnabled()) {
495
+ for (const txHashStr of minedTxsToFinalize){
496
+ const buffer = await this.#txsDB.getAsync(txHashStr);
497
+ if (buffer) {
498
+ txsToArchive.push(Tx.fromBuffer(buffer));
499
+ }
388
500
  }
389
501
  }
502
+ // Step 3: Delete mined txs from active pool
503
+ await this.#deleteTxsBatch(minedTxsToFinalize);
504
+ // Step 4: Finalize soft-deleted txs
505
+ await this.#deletedPool.finalizeBlock(blockNumber);
506
+ // Step 5: Archive mined txs
507
+ if (txsToArchive.length > 0) {
508
+ await this.#archive.archiveTxs(txsToArchive);
509
+ }
510
+ });
511
+ if (minedTxsToFinalize.length > 0) {
512
+ this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
513
+ txHashes: minedTxsToFinalize
514
+ });
390
515
  }
391
- // Step 3: Delete from active pool
392
- await this.#deleteTxsBatch(txsToFinalize);
393
- // Step 4: Archive
394
- if (txsToArchive.length > 0) {
395
- await this.#archive.archiveTxs(txsToArchive);
396
- }
397
- this.#log.info(`Finalized ${txsToFinalize.length} txs from blocks up to ${blockNumber}`);
398
516
  }
399
517
  // === Query Methods ===
400
518
  async getTxByHash(txHash) {
@@ -410,20 +528,34 @@ import { TxPoolIndices } from './tx_pool_indices.js';
410
528
  return results;
411
529
  }
412
530
  hasTxs(txHashes) {
413
- return txHashes.map((h)=>this.#indices.has(h.toString()));
531
+ return txHashes.map((h)=>{
532
+ const hashStr = h.toString();
533
+ return this.#indices.has(hashStr) || this.#deletedPool.isSoftDeleted(hashStr);
534
+ });
414
535
  }
415
536
  getTxStatus(txHash) {
416
- const meta = this.#indices.getMetadata(txHash.toString());
417
- if (!meta) {
418
- return undefined;
537
+ const txHashStr = txHash.toString();
538
+ const meta = this.#indices.getMetadata(txHashStr);
539
+ if (meta) {
540
+ return this.#indices.getTxState(meta);
541
+ }
542
+ // Check if soft-deleted
543
+ if (this.#deletedPool.isSoftDeleted(txHashStr)) {
544
+ return 'deleted';
419
545
  }
420
- return this.#indices.getTxState(meta);
546
+ return undefined;
421
547
  }
422
548
  getPendingTxHashes() {
423
549
  return [
424
550
  ...this.#indices.iteratePendingByPriority('desc')
425
551
  ].map((hash)=>TxHash.fromString(hash));
426
552
  }
553
+ getEligiblePendingTxHashes() {
554
+ const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
555
+ return [
556
+ ...this.#indices.iterateEligiblePendingByPriority('desc', maxReceivedAt)
557
+ ].map((hash)=>TxHash.fromString(hash));
558
+ }
427
559
  getPendingTxCount() {
428
560
  return this.#indices.getPendingTxCount();
429
561
  }
@@ -463,6 +595,9 @@ import { TxPoolIndices } from './tx_pool_indices.js';
463
595
  this.#config.archivedTxLimit = config.archivedTxLimit;
464
596
  this.#archive.updateLimit(config.archivedTxLimit);
465
597
  }
598
+ if (config.minTxPoolAgeMs !== undefined) {
599
+ this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
600
+ }
466
601
  // Update eviction rules with new config
467
602
  this.#evictionManager.updateConfig(config);
468
603
  }
@@ -477,7 +612,10 @@ import { TxPoolIndices } from './tx_pool_indices.js';
477
612
  }
478
613
  // === Metrics ===
479
614
  countTxs() {
480
- return this.#indices.countTxs();
615
+ return {
616
+ ...this.#indices.countTxs(),
617
+ softDeleted: this.#deletedPool.getSoftDeletedCount()
618
+ };
481
619
  }
482
620
  // ============================================================================
483
621
  // PRIVATE HELPERS - Transaction Management
@@ -488,7 +626,9 @@ import { TxPoolIndices } from './tx_pool_indices.js';
488
626
  */ async #addTx(tx, state, opts = {}) {
489
627
  const txHashStr = tx.getTxHash().toString();
490
628
  const meta = await buildTxMetaData(tx);
629
+ meta.receivedAt = this.#dateProvider.now();
491
630
  await this.#txsDB.set(txHashStr, tx.toBuffer());
631
+ await this.#deletedPool.clearSoftDeleted(txHashStr);
492
632
  this.#callbacks.onTxsAdded([
493
633
  tx
494
634
  ], opts);
@@ -501,64 +641,74 @@ import { TxPoolIndices } from './tx_pool_indices.js';
501
641
  this.#indices.addMined(meta);
502
642
  }
503
643
  const stateStr = typeof state === 'string' ? state : Object.keys(state)[0];
504
- this.#log.verbose(`Added ${stateStr} tx ${txHashStr}`, {
644
+ this.#log.debug(`Added tx ${txHashStr} as ${stateStr}`, {
505
645
  eventName: 'tx-added-to-pool',
506
- state: stateStr
646
+ txHash: txHashStr,
647
+ state: stateStr,
648
+ source: opts.source
507
649
  });
508
650
  return meta;
509
651
  }
510
652
  /**
511
653
  * Deletes a transaction from both indices and DB.
512
654
  * Emits onTxsRemoved callback immediately after DB delete.
655
+ */ /**
656
+ * Deletes a transaction from the pool.
657
+ * Delegates to DeletedPool which decides soft vs hard delete based on whether
658
+ * the tx is from a pruned block.
513
659
  */ async #deleteTx(txHashStr) {
514
660
  this.#indices.remove(txHashStr);
515
- await this.#txsDB.delete(txHashStr);
516
661
  this.#callbacks.onTxsRemoved([
517
662
  txHashStr
518
663
  ]);
664
+ await this.#deletedPool.deleteTx(txHashStr);
519
665
  }
520
666
  /** Deletes a batch of transactions, emitting callbacks individually for each. */ async #deleteTxsBatch(txHashes) {
521
667
  for (const txHashStr of txHashes){
522
668
  await this.#deleteTx(txHashStr);
523
669
  }
524
670
  }
671
+ /** Evicts transactions: records eviction metric with reason, caches hashes, then deletes. */ async #evictTxs(txHashes, reason) {
672
+ if (txHashes.length === 0) {
673
+ return;
674
+ }
675
+ this.#instrumentation.recordEvictions(txHashes.length, reason);
676
+ for (const txHashStr of txHashes){
677
+ this.#log.debug(`Evicting tx ${txHashStr}`, {
678
+ txHash: txHashStr,
679
+ reason
680
+ });
681
+ this.#addToEvictedCache(txHashStr);
682
+ }
683
+ await this.#deleteTxsBatch(txHashes);
684
+ }
685
+ /** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */ #addToEvictedCache(txHashStr) {
686
+ if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
687
+ // FIFO eviction: remove the first (oldest) entry
688
+ const oldest = this.#evictedTxHashes.values().next().value;
689
+ this.#evictedTxHashes.delete(oldest);
690
+ }
691
+ this.#evictedTxHashes.add(txHashStr);
692
+ }
525
693
  // ============================================================================
526
694
  // PRIVATE HELPERS - Validation & Conflict Resolution
527
695
  // ============================================================================
528
- /** Validates a single transaction, returning true if valid */ async #validateTx(tx, context) {
529
- const result = await this.#pendingTxValidator.validateTx(tx);
696
+ /** Validates transaction metadata, returning true if valid */ async #validateMeta(meta, validator, context) {
697
+ const txValidator = validator ?? await this.#createTxValidator();
698
+ const result = await txValidator.validateTx(meta);
530
699
  if (result.result !== 'valid') {
531
700
  const contextStr = context ? ` ${context}` : '';
532
- this.#log.info(`Tx ${tx.getTxHash()}${contextStr} failed validation: ${result.reason?.join(', ')}`);
701
+ this.#log.info(`Tx ${meta.txHash}${contextStr} failed validation: ${result.reason?.join(', ')}`);
533
702
  return false;
534
703
  }
535
704
  return true;
536
705
  }
537
- /** Loads transactions from DB, returning loaded txs and missing hashes */ async #loadTxsFromDb(metas) {
538
- const loaded = [];
539
- const missing = [];
540
- for (const meta of metas){
541
- const buffer = await this.#txsDB.getAsync(meta.txHash);
542
- if (!buffer) {
543
- this.#log.warn(`Tx ${meta.txHash} not found in DB`);
544
- missing.push(meta.txHash);
545
- continue;
546
- }
547
- loaded.push({
548
- tx: Tx.fromBuffer(buffer),
549
- meta
550
- });
551
- }
552
- return {
553
- loaded,
554
- missing
555
- };
556
- }
557
- /** Validates a batch of transactions, returning valid and invalid groups */ async #validateTxBatch(txs, context) {
706
+ /** Validates metadata directly */ async #revalidateMetadata(metas, context) {
558
707
  const valid = [];
559
708
  const invalid = [];
560
- for (const { tx, meta } of txs){
561
- if (await this.#validateTx(tx, context)) {
709
+ const validator = await this.#createTxValidator();
710
+ for (const meta of metas){
711
+ if (await this.#validateMeta(meta, validator, context)) {
562
712
  valid.push(meta);
563
713
  } else {
564
714
  invalid.push(meta.txHash);
@@ -569,17 +719,6 @@ import { TxPoolIndices } from './tx_pool_indices.js';
569
719
  invalid
570
720
  };
571
721
  }
572
- /** Loads transactions from DB and validates them */ async #loadAndValidateTxs(metas, context) {
573
- const { loaded, missing } = await this.#loadTxsFromDb(metas);
574
- const { valid, invalid } = await this.#validateTxBatch(loaded, context);
575
- return {
576
- valid,
577
- invalid: [
578
- ...missing,
579
- ...invalid
580
- ]
581
- };
582
- }
583
722
  /**
584
723
  * Resolves nullifier conflicts between incoming txs and existing pending txs.
585
724
  * Modifies the pending indices during iteration to maintain consistent state
@@ -635,6 +774,10 @@ import { TxPoolIndices } from './tx_pool_indices.js';
635
774
  const loaded = [];
636
775
  const errors = [];
637
776
  for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()){
777
+ // Skip soft-deleted transactions - they stay in DB but not in indices
778
+ if (this.#deletedPool.isSoftDeleted(txHashStr)) {
779
+ continue;
780
+ }
638
781
  try {
639
782
  const tx = Tx.fromBuffer(buffer);
640
783
  const meta = await buildTxMetaData(tx);
@@ -685,7 +828,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
685
828
  if (preAddResult.shouldIgnore) {
686
829
  // Transaction rejected - mark for deletion from DB
687
830
  rejected.push(meta.txHash);
688
- this.#log.debug(`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason}`);
831
+ this.#log.debug(`Rejected tx ${meta.txHash} during rebuild: ${preAddResult.reason?.message ?? 'unknown reason'}`);
689
832
  continue;
690
833
  }
691
834
  // Evict any conflicting txs identified by pre-add rules
@@ -721,7 +864,7 @@ import { TxPoolIndices } from './tx_pool_indices.js';
721
864
  getFeePayerPendingTxs: (feePayer)=>this.#indices.getFeePayerPendingTxs(feePayer),
722
865
  getPendingTxCount: ()=>this.#indices.getPendingTxCount(),
723
866
  getLowestPriorityPending: (limit)=>this.#indices.getLowestPriorityPending(limit),
724
- deleteTxs: (txHashes)=>this.#deleteTxsBatch(txHashes)
867
+ deleteTxs: (txHashes, reason)=>this.#evictTxs(txHashes, reason ?? 'unknown')
725
868
  };
726
869
  }
727
870
  #createPreAddPoolAccess() {