@aztec/p2p 0.0.1-commit.343b43af6 → 0.0.1-commit.350e0a4d

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 (435) hide show
  1. package/README.md +130 -3
  2. package/dest/bootstrap/bootstrap.d.ts +1 -1
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  4. package/dest/bootstrap/bootstrap.js +22 -6
  5. package/dest/client/factory.d.ts +4 -3
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +36 -19
  8. package/dest/client/interface.d.ts +48 -11
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +34 -19
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +115 -50
  13. package/dest/config.d.ts +147 -105
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +80 -24
  16. package/dest/errors/p2p-service.error.d.ts +9 -0
  17. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  18. package/dest/errors/p2p-service.error.js +10 -0
  19. package/dest/errors/reqresp.error.d.ts +9 -16
  20. package/dest/errors/reqresp.error.d.ts.map +1 -1
  21. package/dest/errors/reqresp.error.js +10 -17
  22. package/dest/index.d.ts +1 -2
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +0 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +101 -59
  26. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool.js +272 -199
  28. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  29. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +224 -65
  31. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
  32. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  33. package/dest/mem_pools/attestation_pool/mocks.js +6 -4
  34. package/dest/mem_pools/index.d.ts +1 -2
  35. package/dest/mem_pools/index.d.ts.map +1 -1
  36. package/dest/mem_pools/instrumentation.d.ts +9 -4
  37. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  38. package/dest/mem_pools/instrumentation.js +28 -9
  39. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +1 -5
  40. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +1 -7
  42. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +3 -3
  43. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +6 -6
  45. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  46. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +3 -2
  48. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  49. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  51. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  52. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  53. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  54. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  55. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +39 -9
  56. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  57. package/dest/mem_pools/tx_pool_v2/interfaces.js +2 -1
  58. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +13 -3
  59. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  60. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +20 -7
  61. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +15 -1
  62. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -1
  63. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +31 -0
  64. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +12 -4
  65. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  66. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +22 -8
  67. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +17 -4
  68. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  69. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +217 -120
  70. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +10 -3
  71. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  72. package/dest/msg_validators/attestation_validator/attestation_validator.js +38 -15
  73. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
  74. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  75. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
  76. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +8 -3
  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 +2 -2
  79. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +8 -3
  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 +8 -2
  82. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +25 -3
  83. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  84. package/dest/msg_validators/proposal_validator/proposal_validator.js +85 -15
  85. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  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 +8 -15
  88. package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
  89. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  90. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  91. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  92. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  93. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  94. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  95. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  96. package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
  97. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/data_validator.js +36 -2
  99. package/dest/msg_validators/tx_validator/factory.d.ts +22 -15
  100. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  101. package/dest/msg_validators/tx_validator/factory.js +51 -19
  102. package/dest/msg_validators/tx_validator/gas_validator.d.ts +47 -10
  103. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  104. package/dest/msg_validators/tx_validator/gas_validator.js +65 -48
  105. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  106. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  107. package/dest/msg_validators/tx_validator/index.js +2 -0
  108. package/dest/msg_validators/tx_validator/phases_validator.d.ts +21 -1
  109. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  110. package/dest/msg_validators/tx_validator/phases_validator.js +30 -3
  111. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
  112. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  113. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
  114. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  115. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  116. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  117. package/dest/services/data_store.d.ts +1 -1
  118. package/dest/services/data_store.d.ts.map +1 -1
  119. package/dest/services/data_store.js +5 -5
  120. package/dest/services/discv5/discV5_service.d.ts +13 -2
  121. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  122. package/dest/services/discv5/discV5_service.js +119 -23
  123. package/dest/services/discv5/persisted_enr_store.d.ts +38 -0
  124. package/dest/services/discv5/persisted_enr_store.d.ts.map +1 -0
  125. package/dest/services/discv5/persisted_enr_store.js +145 -0
  126. package/dest/services/dummy_service.d.ts +15 -15
  127. package/dest/services/dummy_service.d.ts.map +1 -1
  128. package/dest/services/dummy_service.js +15 -16
  129. package/dest/services/encoding.d.ts +23 -6
  130. package/dest/services/encoding.d.ts.map +1 -1
  131. package/dest/services/encoding.js +32 -16
  132. package/dest/services/gossipsub/topic_score_params.d.ts +6 -12
  133. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  134. package/dest/services/gossipsub/topic_score_params.js +4 -14
  135. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  136. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  137. package/dest/services/libp2p/instrumentation.js +14 -0
  138. package/dest/services/libp2p/libp2p_service.d.ts +45 -47
  139. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  140. package/dest/services/libp2p/libp2p_service.js +392 -300
  141. package/dest/services/peer-manager/peer_manager.d.ts +20 -3
  142. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  143. package/dest/services/peer-manager/peer_manager.js +81 -25
  144. package/dest/services/peer-manager/peer_scoring.d.ts +34 -2
  145. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  146. package/dest/services/peer-manager/peer_scoring.js +102 -13
  147. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +4 -8
  148. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  149. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +81 -86
  150. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +10 -6
  151. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  152. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  153. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  154. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  155. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
  156. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  157. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
  158. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
  159. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
  160. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
  161. package/dest/services/reqresp/config.d.ts +15 -3
  162. package/dest/services/reqresp/config.d.ts.map +1 -1
  163. package/dest/services/reqresp/config.js +11 -0
  164. package/dest/services/reqresp/interface.d.ts +16 -18
  165. package/dest/services/reqresp/interface.d.ts.map +1 -1
  166. package/dest/services/reqresp/interface.js +10 -20
  167. package/dest/services/reqresp/metrics.d.ts +1 -1
  168. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  169. package/dest/services/reqresp/metrics.js +0 -1
  170. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +4 -3
  171. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  172. package/dest/services/reqresp/protocols/block_txs/bitvector.js +3 -2
  173. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  174. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  175. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +31 -28
  176. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +12 -7
  177. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  178. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +42 -24
  179. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  180. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  181. package/dest/services/reqresp/protocols/index.js +0 -1
  182. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  183. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  184. package/dest/services/reqresp/protocols/tx.js +1 -3
  185. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  186. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  187. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  188. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  189. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  190. package/dest/services/reqresp/rate-limiter/rate_limits.js +3 -13
  191. package/dest/services/reqresp/reqresp.d.ts +7 -29
  192. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  193. package/dest/services/reqresp/reqresp.js +73 -215
  194. package/dest/services/service.d.ts +25 -12
  195. package/dest/services/service.d.ts.map +1 -1
  196. package/dest/services/tx_collection/config.d.ts +2 -23
  197. package/dest/services/tx_collection/config.d.ts.map +1 -1
  198. package/dest/services/tx_collection/config.js +2 -55
  199. package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
  200. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  201. package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
  202. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  203. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  204. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  205. package/dest/services/tx_collection/index.d.ts +2 -3
  206. package/dest/services/tx_collection/index.d.ts.map +1 -1
  207. package/dest/services/tx_collection/index.js +0 -1
  208. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  209. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  210. package/dest/services/tx_collection/instrumentation.js +0 -2
  211. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  212. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  213. package/dest/services/tx_collection/request_tracker.js +84 -0
  214. package/dest/services/tx_collection/tx_collection.d.ts +36 -55
  215. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  216. package/dest/services/tx_collection/tx_collection.js +275 -119
  217. package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
  218. package/dest/services/tx_collection/tx_collection_sink.js +2 -2
  219. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  220. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  221. package/dest/services/tx_collection/tx_source.js +13 -8
  222. package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
  223. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  224. package/dest/services/tx_file_store/tx_file_store.js +4 -14
  225. package/dest/services/tx_provider.d.ts +3 -1
  226. package/dest/services/tx_provider.d.ts.map +1 -1
  227. package/dest/services/tx_provider.js +3 -0
  228. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  229. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  230. package/dest/test-helpers/make-test-p2p-clients.js +5 -2
  231. package/dest/test-helpers/mock-pubsub.d.ts +23 -9
  232. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  233. package/dest/test-helpers/mock-pubsub.js +44 -44
  234. package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
  235. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  236. package/dest/test-helpers/reqresp-nodes.js +16 -18
  237. package/dest/test-helpers/test_tx_provider.d.ts +3 -1
  238. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
  239. package/dest/test-helpers/test_tx_provider.js +3 -0
  240. package/dest/test-helpers/testbench-utils.d.ts +15 -14
  241. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  242. package/dest/test-helpers/testbench-utils.js +47 -14
  243. package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
  244. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  245. package/dest/testbench/p2p_client_testbench_worker.js +102 -40
  246. package/dest/testbench/worker_client_manager.d.ts +10 -6
  247. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  248. package/dest/testbench/worker_client_manager.js +51 -9
  249. package/dest/util.d.ts +11 -6
  250. package/dest/util.d.ts.map +1 -1
  251. package/dest/util.js +35 -14
  252. package/dest/versioning.d.ts +3 -6
  253. package/dest/versioning.d.ts.map +1 -1
  254. package/dest/versioning.js +3 -24
  255. package/package.json +16 -16
  256. package/src/bootstrap/bootstrap.ts +17 -3
  257. package/src/client/factory.ts +57 -11
  258. package/src/client/interface.ts +44 -17
  259. package/src/client/p2p_client.ts +138 -83
  260. package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
  261. package/src/config.ts +160 -31
  262. package/src/errors/p2p-service.error.ts +11 -0
  263. package/src/errors/reqresp.error.ts +13 -19
  264. package/src/index.ts +0 -1
  265. package/src/mem_pools/attestation_pool/attestation_pool.ts +327 -242
  266. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +244 -69
  267. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  268. package/src/mem_pools/index.ts +0 -3
  269. package/src/mem_pools/instrumentation.ts +18 -12
  270. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +1 -9
  271. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +7 -7
  272. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +3 -2
  273. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  274. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  275. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
  276. package/src/mem_pools/tx_pool_v2/interfaces.ts +37 -8
  277. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +31 -9
  278. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +35 -0
  279. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +35 -9
  280. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +243 -125
  281. package/src/msg_validators/attestation_validator/README.md +49 -0
  282. package/src/msg_validators/attestation_validator/attestation_validator.ts +46 -14
  283. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +15 -7
  284. package/src/msg_validators/proposal_validator/README.md +123 -0
  285. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +15 -3
  286. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +26 -3
  287. package/src/msg_validators/proposal_validator/proposal_validator.ts +95 -12
  288. package/src/msg_validators/tx_validator/README.md +17 -3
  289. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
  290. package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
  291. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  292. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  293. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  294. package/src/msg_validators/tx_validator/data_validator.ts +44 -1
  295. package/src/msg_validators/tx_validator/factory.ts +65 -21
  296. package/src/msg_validators/tx_validator/gas_validator.ts +99 -54
  297. package/src/msg_validators/tx_validator/index.ts +2 -0
  298. package/src/msg_validators/tx_validator/phases_validator.ts +33 -3
  299. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
  300. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  301. package/src/services/data_store.ts +5 -13
  302. package/src/services/discv5/discV5_service.ts +126 -14
  303. package/src/services/discv5/persisted_enr_store.ts +158 -0
  304. package/src/services/dummy_service.ts +20 -39
  305. package/src/services/encoding.ts +35 -19
  306. package/src/services/gossipsub/README.md +33 -11
  307. package/src/services/gossipsub/topic_score_params.ts +9 -18
  308. package/src/services/libp2p/instrumentation.ts +14 -0
  309. package/src/services/libp2p/libp2p_service.ts +444 -339
  310. package/src/services/peer-manager/peer_manager.ts +89 -24
  311. package/src/services/peer-manager/peer_scoring.ts +102 -8
  312. package/src/services/reqresp/README.md +194 -0
  313. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  314. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +77 -95
  315. package/src/services/reqresp/batch-tx-requester/interface.ts +13 -5
  316. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  317. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
  318. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
  319. package/src/services/reqresp/config.ts +19 -2
  320. package/src/services/reqresp/interface.ts +21 -47
  321. package/src/services/reqresp/metrics.ts +0 -1
  322. package/src/services/reqresp/protocols/block_txs/bitvector.ts +3 -2
  323. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -30
  324. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +47 -20
  325. package/src/services/reqresp/protocols/index.ts +0 -1
  326. package/src/services/reqresp/protocols/tx.ts +1 -3
  327. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  328. package/src/services/reqresp/rate-limiter/rate_limits.ts +3 -13
  329. package/src/services/reqresp/reqresp.ts +84 -259
  330. package/src/services/service.ts +31 -28
  331. package/src/services/tx_collection/config.ts +3 -80
  332. package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
  333. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  334. package/src/services/tx_collection/index.ts +1 -6
  335. package/src/services/tx_collection/instrumentation.ts +1 -7
  336. package/src/services/tx_collection/request_tracker.ts +127 -0
  337. package/src/services/tx_collection/tx_collection.ts +331 -176
  338. package/src/services/tx_collection/tx_collection_sink.ts +2 -2
  339. package/src/services/tx_collection/tx_source.ts +10 -8
  340. package/src/services/tx_file_store/tx_file_store.ts +5 -17
  341. package/src/services/tx_provider.ts +5 -0
  342. package/src/test-helpers/make-test-p2p-clients.ts +3 -0
  343. package/src/test-helpers/mock-pubsub.ts +46 -60
  344. package/src/test-helpers/reqresp-nodes.ts +12 -22
  345. package/src/test-helpers/test_tx_provider.ts +5 -0
  346. package/src/test-helpers/testbench-utils.ts +62 -28
  347. package/src/testbench/p2p_client_testbench_worker.ts +109 -56
  348. package/src/testbench/worker_client_manager.ts +59 -20
  349. package/src/util.ts +32 -17
  350. package/src/versioning.ts +3 -33
  351. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
  352. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
  353. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -304
  354. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
  355. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
  356. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
  357. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  358. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  359. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  360. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  361. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  362. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  363. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  364. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  365. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  366. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  367. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  368. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
  369. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  370. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  371. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  372. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  373. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  374. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  375. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  376. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  377. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  378. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  379. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  380. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  381. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  382. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  383. package/dest/mem_pools/tx_pool/index.js +0 -2
  384. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  385. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  386. package/dest/mem_pools/tx_pool/priority.js +0 -16
  387. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  388. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  389. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  390. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  391. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  392. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -402
  393. package/dest/msg_validators/clock_tolerance.d.ts +0 -21
  394. package/dest/msg_validators/clock_tolerance.d.ts.map +0 -1
  395. package/dest/msg_validators/clock_tolerance.js +0 -37
  396. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
  397. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  398. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
  399. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  400. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  401. package/dest/services/reqresp/protocols/block.js +0 -32
  402. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -54
  403. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  404. package/dest/services/tx_collection/fast_tx_collection.js +0 -327
  405. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  406. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  407. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  408. package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -49
  409. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
  410. package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
  411. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
  412. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  413. package/dest/services/tx_collection/slow_tx_collection.js +0 -211
  414. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -345
  415. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
  416. package/src/mem_pools/tx_pool/README.md +0 -270
  417. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  418. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  419. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  420. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
  421. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  422. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  423. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  424. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  425. package/src/mem_pools/tx_pool/index.ts +0 -2
  426. package/src/mem_pools/tx_pool/priority.ts +0 -23
  427. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  428. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -321
  429. package/src/msg_validators/clock_tolerance.ts +0 -51
  430. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
  431. package/src/services/reqresp/protocols/block.ts +0 -37
  432. package/src/services/tx_collection/fast_tx_collection.ts +0 -387
  433. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
  434. package/src/services/tx_collection/proposal_tx_collector.ts +0 -113
  435. package/src/services/tx_collection/slow_tx_collection.ts +0 -266
@@ -1,4 +1,5 @@
1
1
  import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { FifoSet } from '@aztec/foundation/fifo-set';
2
3
  import type { Logger } from '@aztec/foundation/log';
3
4
  import type { DateProvider } from '@aztec/foundation/timer';
4
5
  import type { AztecAsyncKVStore, AztecAsyncMap } from '@aztec/kv-store';
@@ -17,6 +18,7 @@ import {
17
18
  EvictionManager,
18
19
  FeePayerBalanceEvictionRule,
19
20
  FeePayerBalancePreAddRule,
21
+ InsufficientFeePerGasEvictionRule,
20
22
  InvalidTxsAfterMiningRule,
21
23
  InvalidTxsAfterReorgRule,
22
24
  LowPriorityEvictionRule,
@@ -39,13 +41,28 @@ import {
39
41
  import { type TxMetaData, type TxState, buildTxMetaData, checkNullifierConflict } from './tx_metadata.js';
40
42
  import { TxPoolIndices } from './tx_pool_indices.js';
41
43
 
44
+ /**
45
+ * Maximum number of full transactions to load into memory at once when finalizing a block.
46
+ * Bounds peak memory while archiving and hard-deleting mined txs (~23k txs/epoch at 10 TPS would
47
+ * otherwise OOM the node).
48
+ */
49
+ const FINALIZE_BLOCK_CHUNK_SIZE = 100;
50
+
42
51
  /**
43
52
  * Callbacks for the implementation to notify the outer class about events and metrics.
44
53
  */
54
+ /** A tx that has just transitioned to mined, with the time it spent in the pool. */
55
+ export interface MinedTxInfo {
56
+ txHash: string;
57
+ /** Wall-clock ms from receipt into the pool to being marked mined. Undefined when the
58
+ * receive time is unknown (e.g. a tx hydrated from the DB on restart, receivedAt === 0). */
59
+ minedDelayMs?: number;
60
+ }
61
+
45
62
  export interface TxPoolV2Callbacks {
46
63
  onTxsAdded: (txs: Tx[], opts: { source?: string }) => void;
47
64
  onTxsRemoved: (txHashes: string[] | bigint[]) => void;
48
- onTxsMined: (txHashes: string[]) => void;
65
+ onTxsMined: (minedTxs: MinedTxInfo[]) => void;
49
66
  }
50
67
 
51
68
  /**
@@ -56,12 +73,16 @@ export interface TxPoolV2Callbacks {
56
73
  export class TxPoolV2Impl {
57
74
  // === Persistence ===
58
75
  #store: AztecAsyncKVStore;
76
+ /** Tx data without its proof. Proofs live in #proofsDB so a tx can be read without loading its proof. */
59
77
  #txsDB: AztecAsyncMap<string, Buffer>;
78
+ /** Tx proofs, keyed by tx hash. Written and deleted in lockstep with #txsDB. */
79
+ #proofsDB: AztecAsyncMap<string, Buffer>;
60
80
 
61
81
  // === Dependencies ===
62
82
  #l2BlockSource: L2BlockSource;
63
83
  #worldStateSynchronizer: WorldStateSynchronizer;
64
84
  #createTxValidator: TxPoolV2Dependencies['createTxValidator'];
85
+ #checkAllowedSetupCalls: TxPoolV2Dependencies['checkAllowedSetupCalls'];
65
86
 
66
87
  // === In-Memory Indices ===
67
88
  #indices: TxPoolIndices = new TxPoolIndices();
@@ -73,7 +94,7 @@ export class TxPoolV2Impl {
73
94
  #evictionManager: EvictionManager;
74
95
  #dateProvider: DateProvider;
75
96
  #instrumentation: TxPoolV2Instrumentation;
76
- #evictedTxHashes: Set<string> = new Set();
97
+ #evictedTxHashes: FifoSet<string>;
77
98
  #log: Logger;
78
99
  #callbacks: TxPoolV2Callbacks;
79
100
 
@@ -89,14 +110,17 @@ export class TxPoolV2Impl {
89
110
  ) {
90
111
  this.#store = store;
91
112
  this.#txsDB = store.openMap('txs');
113
+ this.#proofsDB = store.openMap('tx_proofs');
92
114
 
93
115
  this.#l2BlockSource = deps.l2BlockSource;
94
116
  this.#worldStateSynchronizer = deps.worldStateSynchronizer;
95
117
  this.#createTxValidator = deps.createTxValidator;
118
+ this.#checkAllowedSetupCalls = deps.checkAllowedSetupCalls;
96
119
 
97
120
  this.#config = { ...DEFAULT_TX_POOL_V2_CONFIG, ...config };
121
+ this.#evictedTxHashes = FifoSet.withLimit<string>(this.#config.evictedTxCacheSize);
98
122
  this.#archive = new TxArchive(archiveStore, this.#config.archivedTxLimit, log);
99
- this.#deletedPool = new DeletedPool(store, this.#txsDB, log);
123
+ this.#deletedPool = new DeletedPool(store, txHashStr => this.#deleteTxData(txHashStr), log);
100
124
  this.#dateProvider = dateProvider;
101
125
  this.#instrumentation = new TxPoolV2Instrumentation(telemetry, () => this.#indices.getTotalMetadataBytes());
102
126
  this.#log = log;
@@ -114,6 +138,7 @@ export class TxPoolV2Impl {
114
138
 
115
139
  // Post-event eviction rules (run after events to check ALL pending txs)
116
140
  this.#evictionManager.registerRule(new InvalidTxsAfterMiningRule());
141
+ this.#evictionManager.registerRule(new InsufficientFeePerGasEvictionRule(deps.blockMinFeesProvider));
117
142
  this.#evictionManager.registerRule(new InvalidTxsAfterReorgRule(deps.worldStateSynchronizer));
118
143
  this.#evictionManager.registerRule(new FeePayerBalanceEvictionRule(deps.worldStateSynchronizer));
119
144
  // LowPriorityEvictionRule handles cases where txs become pending via prepareForSlot (unprotect)
@@ -136,46 +161,74 @@ export class TxPoolV2Impl {
136
161
  // Step 0: Hydrate deleted pool state
137
162
  await this.#deletedPool.hydrateFromDatabase();
138
163
 
139
- // Step 1: Load all transactions from DB (excluding soft-deleted)
140
- const { loaded, errors: deserializationErrors } = await this.#loadAllTxsFromDb();
164
+ // Step 1: Stream txs from DB, building metadata and mined status one at a time.
165
+ const minedMetas: TxMetaData[] = [];
166
+ const pendingMetas: TxMetaData[] = [];
167
+ const deserializationErrors: string[] = [];
168
+
169
+ for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
170
+ // Skip soft-deleted transactions - they stay in DB but not in indices
171
+ if (this.#deletedPool.isSoftDeleted(txHashStr)) {
172
+ continue;
173
+ }
174
+
175
+ let meta: TxMetaData;
176
+ let txEffect: Awaited<ReturnType<L2BlockSource['getTxEffect']>>;
177
+ try {
178
+ const tx = Tx.fromBuffer(buffer);
179
+ // Resolve allowed-setup-calls and the tx effect concurrently
180
+ // getTxEffect failures are non-fatal (we just treat the tx as not-yet-mined), so
181
+ // its rejection is swallowed before the Promise.all so it can't fail-fast the batch.
182
+ const txEffectPromise = this.#l2BlockSource.getTxEffect(tx.getTxHash()).catch(err => {
183
+ this.#log.warn(`Failed to check mined status for tx ${txHashStr}`, { err });
184
+ return undefined;
185
+ });
186
+ const [allowedSetupCalls, fetchedTxEffect] = await Promise.all([
187
+ this.#checkAllowedSetupCalls(tx),
188
+ txEffectPromise,
189
+ ]);
190
+ meta = await buildTxMetaData(tx, allowedSetupCalls);
191
+ txEffect = fetchedTxEffect;
192
+ } catch (err) {
193
+ this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
194
+ deserializationErrors.push(txHashStr);
195
+ continue;
196
+ }
141
197
 
142
- // Step 2: Check mined status for each tx
143
- await this.#markMinedStatusBatch(loaded.map(l => l.meta));
198
+ if (txEffect) {
199
+ meta.minedL2BlockId = {
200
+ number: txEffect.l2BlockNumber,
201
+ hash: txEffect.l2BlockHash.toString(),
202
+ };
203
+ }
144
204
 
145
- // Step 3: Partition by mined status
146
- const mined: TxMetaData[] = [];
147
- const nonMined: { tx: Tx; meta: TxMetaData }[] = [];
148
- for (const entry of loaded) {
149
- if (entry.meta.minedL2BlockId !== undefined) {
150
- mined.push(entry.meta);
205
+ if (meta.minedL2BlockId !== undefined) {
206
+ minedMetas.push(meta);
151
207
  } else {
152
- nonMined.push(entry);
208
+ pendingMetas.push(meta);
153
209
  }
154
210
  }
155
211
 
156
- // Step 4: Validate non-mined transactions
157
- const { valid, invalid } = await this.#revalidateMetadata(
158
- nonMined.map(e => e.meta),
159
- 'on startup',
160
- );
212
+ // Step 2: Validate non-mined transactions
213
+ const { valid, invalid } = await this.#revalidateMetadata(pendingMetas, 'on startup');
161
214
 
162
- // Step 5: Populate mined indices (these don't need conflict resolution)
163
- for (const meta of mined) {
215
+ // Step 3: Populate mined indices (these don't need conflict resolution)
216
+ for (const meta of minedMetas) {
164
217
  this.#indices.addMined(meta);
165
218
  }
166
219
 
167
- // Step 6: Rebuild pending pool by running pre-add rules for each tx
220
+ // Step 4: Rebuild pending pool by running pre-add rules for each tx
168
221
  // This resolves nullifier conflicts, fee payer balance issues, and pool size limits
169
222
  const { rejected } = await this.#rebuildPendingPool(valid);
170
223
 
171
- // Step 7: Delete invalid and rejected txs from DB only (indices were never populated for these)
224
+ // Step 5: Delete invalid and rejected txs from DB only (indices were never populated for these)
172
225
  const toDelete = [...deserializationErrors, ...invalid, ...rejected];
173
226
  if (toDelete.length === 0) {
174
227
  return;
175
228
  }
176
229
  await this.#store.transactionAsync(async () => {
177
230
  for (const txHashStr of toDelete) {
178
- await this.#txsDB.delete(txHashStr);
231
+ await this.#deleteTxData(txHashStr);
179
232
  }
180
233
  });
181
234
  this.#log.info(`Deleted ${toDelete.length} invalid/rejected transactions on startup`, { txHashes: toDelete });
@@ -375,20 +428,25 @@ export class TxPoolV2Impl {
375
428
  async addProtectedTxs(txs: Tx[], block: BlockHeader, opts: { source?: string }): Promise<void> {
376
429
  const slotNumber = block.globalVariables.slotNumber;
377
430
 
431
+ // Precompute setup-call allow-list flags outside the store transaction
432
+ const allowedFlags = await Promise.all(txs.map(tx => this.#checkAllowedSetupCalls(tx)));
433
+
378
434
  await this.#store.transactionAsync(async () => {
379
- for (const tx of txs) {
435
+ for (let i = 0; i < txs.length; i++) {
436
+ const tx = txs[i];
380
437
  const txHash = tx.getTxHash();
381
438
  const txHashStr = txHash.toString();
382
439
  const isNew = !this.#indices.has(txHashStr);
383
440
  const minedBlockId = await this.#getMinedBlockId(txHash);
384
441
 
385
442
  if (isNew) {
443
+ const meta = await buildTxMetaData(tx, allowedFlags[i]);
386
444
  // New tx - add as mined or protected (callback emitted by #addTx)
387
445
  if (minedBlockId) {
388
- await this.#addTx(tx, { mined: minedBlockId }, opts);
446
+ await this.#addTx(tx, { mined: minedBlockId }, opts, meta);
389
447
  this.#indices.setProtection(txHashStr, slotNumber);
390
448
  } else {
391
- await this.#addTx(tx, { protected: slotNumber }, opts);
449
+ await this.#addTx(tx, { protected: slotNumber }, opts, meta);
392
450
  }
393
451
  } else {
394
452
  // Existing tx - update protection and mined status
@@ -416,10 +474,11 @@ export class TxPoolV2Impl {
416
474
  // Update protection for existing tx
417
475
  this.#indices.updateProtection(txHashStr, slotNumber);
418
476
  } else if (this.#deletedPool.isSoftDeleted(txHashStr)) {
419
- // Resurrect soft-deleted tx as protected
477
+ // Resurrect soft-deleted tx as protected. Load the proof too: #addTx rewrites both entries, so re-adding
478
+ // a proofless tx would wipe the stored proof.
420
479
  const buffer = await this.#txsDB.getAsync(txHashStr);
421
480
  if (buffer) {
422
- const tx = Tx.fromBuffer(buffer);
481
+ const tx = await this.#loadTxWithProof(txHashStr, buffer);
423
482
  await this.#addTx(tx, { protected: slotNumber });
424
483
  softDeletedHits++;
425
484
  } else {
@@ -509,7 +568,15 @@ export class TxPoolV2Impl {
509
568
  });
510
569
 
511
570
  if (found.length > 0) {
512
- this.#callbacks.onTxsMined(found.map(m => m.txHash));
571
+ // receivedAt is 0 for txs hydrated from the DB on restart (true receive time lost) — leave
572
+ // their delay undefined so the metric isn't polluted by epoch-sized values.
573
+ const now = this.#dateProvider.now();
574
+ this.#callbacks.onTxsMined(
575
+ found.map(m => ({
576
+ txHash: m.txHash,
577
+ minedDelayMs: m.receivedAt > 0 ? now - m.receivedAt : undefined,
578
+ })),
579
+ );
513
580
  }
514
581
 
515
582
  this.#log.info(`Marked ${found.length} txs as mined in block ${blockId.number}`);
@@ -534,29 +601,62 @@ export class TxPoolV2Impl {
534
601
  }
535
602
 
536
603
  this.#log.info(`Preparing for slot ${slotNumber}: unprotecting ${txsToRestore.length} txs`);
604
+ await this.#restoreUnprotectedToPending(txsToRestore, 'during prepareForSlot');
605
+ });
606
+ }
537
607
 
538
- // Step 4: Validate for pending pool
539
- const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, 'during prepareForSlot');
608
+ async unprotectTxs(txHashes: TxHash[], slotNumber: SlotNumber): Promise<void> {
609
+ const hashStrs = txHashes.map(h => h.toString());
540
610
 
541
- // Step 5: Resolve nullifier conflicts and add winners to pending indices
542
- const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
611
+ await this.#store.transactionAsync(async () => {
612
+ // Only release entries still recorded at this exact slot. A tx that another, still-live proposal
613
+ // raised to a higher slot via updateProtection must keep that protection. Mined txs have no
614
+ // protection entry and so are never matched here.
615
+ const matching = this.#indices.findProtectedTxsAtSlot(hashStrs, slotNumber);
616
+ if (matching.length === 0) {
617
+ this.#log.debug(`Unprotecting txs for slot ${slotNumber}: no matching protections to release`);
618
+ return;
619
+ }
543
620
 
544
- // Step 6: Delete invalid txs and evict conflict losers
545
- await this.#deleteTxsBatch(invalid);
546
- await this.#evictTxs(toEvict, 'NullifierConflict');
621
+ this.#indices.clearProtection(matching);
547
622
 
548
- // Step 7: Run eviction rules (enforce pool size limit)
549
- if (added.length > 0) {
550
- const feePayers = added.map(meta => meta.feePayer);
551
- const uniqueFeePayers = new Set<string>(feePayers);
552
- await this.#evictionManager.evictAfterNewTxs(
553
- added.map(m => m.txHash),
554
- [...uniqueFeePayers],
555
- );
623
+ const txsToRestore = this.#indices.filterRestorable(matching);
624
+ if (txsToRestore.length === 0) {
625
+ return;
556
626
  }
627
+
628
+ this.#log.info(`Unprotecting ${txsToRestore.length} txs from failed proposal at slot ${slotNumber}`);
629
+ await this.#restoreUnprotectedToPending(txsToRestore, 'during unprotectTxs');
557
630
  });
558
631
  }
559
632
 
633
+ /**
634
+ * Returns just-unprotected txs to the pending pool: revalidates them, resolves nullifier
635
+ * conflicts, deletes losers, then enforces the pool size limit. Must run inside a store
636
+ * transaction; callers clear the protection entries before invoking.
637
+ */
638
+ async #restoreUnprotectedToPending(txsToRestore: TxMetaData[], context: string): Promise<void> {
639
+ // Step 1: Validate for pending pool
640
+ const { valid, invalid } = await this.#revalidateMetadata(txsToRestore, context);
641
+
642
+ // Step 2: Resolve nullifier conflicts and add winners to pending indices
643
+ const { added, toEvict } = this.#applyNullifierConflictResolution(valid);
644
+
645
+ // Step 3: Delete invalid txs and evict conflict losers
646
+ await this.#deleteTxsBatch(invalid);
647
+ await this.#evictTxs(toEvict, 'NullifierConflict');
648
+
649
+ // Step 4: Run eviction rules (enforce pool size limit)
650
+ if (added.length > 0) {
651
+ const feePayers = added.map(meta => meta.feePayer);
652
+ const uniqueFeePayers = new Set<string>(feePayers);
653
+ await this.#evictionManager.evictAfterNewTxs(
654
+ added.map(m => m.txHash),
655
+ [...uniqueFeePayers],
656
+ );
657
+ }
658
+ }
659
+
560
660
  async handlePrunedBlocks(latestBlock: L2BlockId, options?: { deleteAllTxs?: boolean }): Promise<void> {
561
661
  // Step 1: Find transactions mined after the prune point
562
662
  const txsToUnmine = this.#indices.findTxsMinedAfter(latestBlock.number);
@@ -628,56 +728,113 @@ export class TxPoolV2Impl {
628
728
  async handleFinalizedBlock(block: BlockHeader): Promise<void> {
629
729
  const blockNumber = block.globalVariables.blockNumber;
630
730
 
631
- // Step 1: Find mined txs at or before finalized block
632
- const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(blockNumber);
731
+ // Hold finalized txs for a configurable margin behind the finalized tip so a prover still
732
+ // proving an epoch with already-finalized blocks isn't starved of its txs. 0 deletes at the finalized tip.
733
+ const cutoffBlock = await this.#finalizationCutoffBlock(block);
633
734
 
634
- await this.#store.transactionAsync(async () => {
635
- // Step 2: Collect mined txs for archiving (before deletion)
636
- const txsToArchive: Tx[] = [];
637
- if (this.#archive.isEnabled()) {
638
- for (const txHashStr of minedTxsToFinalize) {
735
+ // Step 1: Find mined txs at or before the cutoff block
736
+ const minedTxsToFinalize = this.#indices.findTxsMinedAtOrBefore(cutoffBlock);
737
+
738
+ // Step 2: Archive in chunks if archiving is enabled. Hydrating an entire epoch's worth of
739
+ // mined txs at once would OOM under load. When archiving is disabled there is no need to hydrate the txs at all.
740
+ if (this.#archive.isEnabled()) {
741
+ for (let i = 0; i < minedTxsToFinalize.length; i += FINALIZE_BLOCK_CHUNK_SIZE) {
742
+ const chunk = minedTxsToFinalize.slice(i, i + FINALIZE_BLOCK_CHUNK_SIZE);
743
+ const txsToArchive: Tx[] = [];
744
+ for (const txHashStr of chunk) {
639
745
  const buffer = await this.#txsDB.getAsync(txHashStr);
640
746
  if (buffer) {
641
747
  txsToArchive.push(Tx.fromBuffer(buffer));
642
748
  }
643
749
  }
750
+ if (txsToArchive.length > 0) {
751
+ await this.#archive.archiveTxs(txsToArchive);
752
+ }
644
753
  }
754
+ }
645
755
 
646
- // Step 3: Delete mined txs from active pool
756
+ // Step 3: Delete mined txs from the active pool and finalize soft-deleted txs in one
757
+ // transaction. Only tx hashes are touched here, so memory is bounded and atomicity is preserved.
758
+ await this.#store.transactionAsync(async () => {
647
759
  await this.#deleteTxsBatch(minedTxsToFinalize);
648
-
649
- // Step 4: Finalize soft-deleted txs
650
- await this.#deletedPool.finalizeBlock(blockNumber);
651
-
652
- // Step 5: Archive mined txs
653
- if (txsToArchive.length > 0) {
654
- await this.#archive.archiveTxs(txsToArchive);
655
- }
760
+ await this.#deletedPool.finalizeBlock(cutoffBlock);
656
761
  });
657
762
 
658
763
  if (minedTxsToFinalize.length > 0) {
659
- this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${blockNumber}`, {
764
+ this.#log.info(`Finalized ${minedTxsToFinalize.length} mined txs from blocks up to ${cutoffBlock}`, {
660
765
  txHashes: minedTxsToFinalize,
766
+ finalizedBlockNumber: blockNumber,
767
+ cutoffBlock,
661
768
  });
662
769
  }
663
770
  }
664
771
 
772
+ /**
773
+ * Resolves the block up to which finalized txs may be deleted, given `keepFinalizedTxsForSlots`.
774
+ * With a margin of 0 this is just the finalized block. Otherwise we keep txs whose block is within
775
+ * the margin (in slots) of the finalized tip: take the target slot `finalizedSlot - margin`, find the
776
+ * latest checkpoint at or before it with a single reverse range query (`limit: 1`), and use that
777
+ * checkpoint's last block as the cutoff. This rounds to a checkpoint boundary, so it can retain slightly
778
+ * more than the configured margin but never less, and never deletes past the finalized block.
779
+ */
780
+ async #finalizationCutoffBlock(block: BlockHeader): Promise<BlockNumber> {
781
+ const keepSlots = this.#config.keepFinalizedTxsForSlots;
782
+ if (keepSlots <= 0) {
783
+ return block.globalVariables.blockNumber;
784
+ }
785
+
786
+ // The goal here really is to ensure we keep transactions long enough for them to be proven.
787
+ // So we could be smart and calculate the number of slots until the end of the proof submission window.
788
+ // Our approach here is a lot simpler however and we just keep transactions for the configured number
789
+ // of slots past L1 finalisation. This means we may keep transactions in the mined pool for longer
790
+ // than strictly necessary.
791
+ const targetSlot = block.getSlot() - keepSlots;
792
+ if (targetSlot < 0) {
793
+ // The margin reaches past genesis: keep everything.
794
+ return BlockNumber(0);
795
+ }
796
+
797
+ const [checkpoint] = await this.#l2BlockSource.getCheckpointsData({
798
+ fromSlot: SlotNumber(targetSlot),
799
+ limit: 1,
800
+ reverse: true,
801
+ });
802
+ // No checkpoint at or before the target slot (e.g. early chain): keep everything.
803
+ return checkpoint ? BlockNumber(checkpoint.startBlock + checkpoint.blockCount - 1) : BlockNumber(0);
804
+ }
805
+
665
806
  // === Query Methods ===
666
807
 
667
- async getTxByHash(txHash: TxHash): Promise<Tx | undefined> {
668
- const buffer = await this.#txsDB.getAsync(txHash.toString());
669
- return buffer ? Tx.fromBuffer(buffer) : undefined;
808
+ async getTxByHash(txHash: TxHash, opts: { includeProof?: boolean } = {}): Promise<Tx | undefined> {
809
+ const txHashStr = txHash.toString();
810
+ const buffer = await this.#txsDB.getAsync(txHashStr);
811
+ if (!buffer) {
812
+ return undefined;
813
+ }
814
+ return opts.includeProof === false ? Tx.fromBuffer(buffer) : this.#loadTxWithProof(txHashStr, buffer);
670
815
  }
671
816
 
672
- async getTxsByHash(txHashes: TxHash[]): Promise<(Tx | undefined)[]> {
817
+ async getTxsByHash(txHashes: TxHash[], opts: { includeProof?: boolean } = {}): Promise<(Tx | undefined)[]> {
673
818
  const results: (Tx | undefined)[] = [];
674
819
  for (const h of txHashes) {
675
- const buffer = await this.#txsDB.getAsync(h.toString());
676
- results.push(buffer ? Tx.fromBuffer(buffer) : undefined);
820
+ results.push(await this.getTxByHash(h, opts));
677
821
  }
678
822
  return results;
679
823
  }
680
824
 
825
+ /** Deserializes a tx blob loaded from #txsDB together with its separately-stored proof. */
826
+ async #loadTxWithProof(txHashStr: string, buffer: Buffer): Promise<Tx> {
827
+ const proofBuffer = await this.#proofsDB.getAsync(txHashStr);
828
+ if (!proofBuffer) {
829
+ // #addTx always writes a proof entry (an empty proof serializes to a 4-byte sentinel), so a missing entry
830
+ // means the blob/proof invariant is broken. Return the proofless tx but flag it, since a consumer that needs
831
+ // the proof (eg serving peers) would otherwise fail far away from the root cause.
832
+ this.#log.warn(`Missing stored proof for tx ${txHashStr}`, { txHash: txHashStr });
833
+ return Tx.fromBuffer(buffer);
834
+ }
835
+ return Tx.fromBuffers(buffer, proofBuffer);
836
+ }
837
+
681
838
  hasTxs(txHashes: TxHash[]): boolean[] {
682
839
  return txHashes.map(h => {
683
840
  const hashStr = h.toString();
@@ -713,6 +870,11 @@ export class TxPoolV2Impl {
713
870
  return this.#indices.getPendingTxCount();
714
871
  }
715
872
 
873
+ hasEligiblePendingTxs(minCount: number): boolean {
874
+ const maxReceivedAt = this.#dateProvider.now() - this.#config.minTxPoolAgeMs;
875
+ return this.#indices.hasEligiblePendingTxs(maxReceivedAt, minCount);
876
+ }
877
+
716
878
  getMinedTxHashes(): [TxHash, L2BlockId][] {
717
879
  return this.#indices.getMinedTxs().map(([hash, blockId]) => [TxHash.fromString(hash), blockId]);
718
880
  }
@@ -756,6 +918,9 @@ export class TxPoolV2Impl {
756
918
  if (config.minTxPoolAgeMs !== undefined) {
757
919
  this.#config.minTxPoolAgeMs = config.minTxPoolAgeMs;
758
920
  }
921
+ if (config.keepFinalizedTxsForSlots !== undefined) {
922
+ this.#config.keepFinalizedTxsForSlots = config.keepFinalizedTxsForSlots;
923
+ }
759
924
  // Update eviction rules with new config
760
925
  this.#evictionManager.updateConfig(config);
761
926
  }
@@ -804,7 +969,8 @@ export class TxPoolV2Impl {
804
969
  const meta = precomputedMeta ?? (await buildTxMetaData(tx));
805
970
  meta.receivedAt = this.#dateProvider.now();
806
971
 
807
- await this.#txsDB.set(txHashStr, tx.toBuffer());
972
+ await this.#txsDB.set(txHashStr, tx.withoutProof().toBuffer());
973
+ await this.#proofsDB.set(txHashStr, tx.chonkProof.toBuffer());
808
974
  await this.#deletedPool.clearSoftDeleted(txHashStr);
809
975
  this.#callbacks.onTxsAdded([tx], opts);
810
976
 
@@ -843,6 +1009,12 @@ export class TxPoolV2Impl {
843
1009
  await this.#deletedPool.deleteTx(txHashStr);
844
1010
  }
845
1011
 
1012
+ /** Hard-deletes a tx's stored data (tx blob and proof) from the DB. */
1013
+ async #deleteTxData(txHashStr: string): Promise<void> {
1014
+ await this.#txsDB.delete(txHashStr);
1015
+ await this.#proofsDB.delete(txHashStr);
1016
+ }
1017
+
846
1018
  /** Deletes a batch of transactions, emitting callbacks individually for each. */
847
1019
  async #deleteTxsBatch(txHashes: string[]): Promise<void> {
848
1020
  for (const txHashStr of txHashes) {
@@ -858,21 +1030,11 @@ export class TxPoolV2Impl {
858
1030
  this.#instrumentation.recordEvictions(txHashes.length, reason);
859
1031
  for (const txHashStr of txHashes) {
860
1032
  this.#log.debug(`Evicting tx ${txHashStr}`, { txHash: txHashStr, reason });
861
- this.#addToEvictedCache(txHashStr);
1033
+ this.#evictedTxHashes.add(txHashStr);
862
1034
  }
863
1035
  await this.#deleteTxsBatch(txHashes);
864
1036
  }
865
1037
 
866
- /** Adds a tx hash to the bounded evicted cache, evicting the oldest entry if at capacity. */
867
- #addToEvictedCache(txHashStr: string): void {
868
- if (this.#evictedTxHashes.size >= this.#config.evictedTxCacheSize) {
869
- // FIFO eviction: remove the first (oldest) entry
870
- const oldest = this.#evictedTxHashes.values().next().value!;
871
- this.#evictedTxHashes.delete(oldest);
872
- }
873
- this.#evictedTxHashes.add(txHashStr);
874
- }
875
-
876
1038
  // ============================================================================
877
1039
  // PRIVATE HELPERS - Validation & Conflict Resolution
878
1040
  // ============================================================================
@@ -967,50 +1129,6 @@ export class TxPoolV2Impl {
967
1129
  };
968
1130
  }
969
1131
 
970
- /** Loads all transactions from the database, returning loaded txs and deserialization errors */
971
- async #loadAllTxsFromDb(): Promise<{
972
- loaded: { tx: Tx; meta: TxMetaData }[];
973
- errors: string[];
974
- }> {
975
- const loaded: { tx: Tx; meta: TxMetaData }[] = [];
976
- const errors: string[] = [];
977
-
978
- for await (const [txHashStr, buffer] of this.#txsDB.entriesAsync()) {
979
- // Skip soft-deleted transactions - they stay in DB but not in indices
980
- if (this.#deletedPool.isSoftDeleted(txHashStr)) {
981
- continue;
982
- }
983
-
984
- try {
985
- const tx = Tx.fromBuffer(buffer);
986
- const meta = await buildTxMetaData(tx);
987
- loaded.push({ tx, meta });
988
- } catch (err) {
989
- this.#log.warn(`Failed to deserialize tx ${txHashStr}, deleting`, { err });
990
- errors.push(txHashStr);
991
- }
992
- }
993
-
994
- return { loaded, errors };
995
- }
996
-
997
- /** Queries block source and marks mined status on transaction metadata */
998
- async #markMinedStatusBatch(metas: TxMetaData[]): Promise<void> {
999
- for (const meta of metas) {
1000
- try {
1001
- const txEffect = await this.#l2BlockSource.getTxEffect(TxHash.fromString(meta.txHash));
1002
- if (txEffect) {
1003
- meta.minedL2BlockId = {
1004
- number: txEffect.l2BlockNumber,
1005
- hash: txEffect.l2BlockHash.toString(),
1006
- };
1007
- }
1008
- } catch (err) {
1009
- this.#log.warn(`Failed to check mined status for tx ${meta.txHash}`, { err });
1010
- }
1011
- }
1012
- }
1013
-
1014
1132
  /**
1015
1133
  * Rebuilds the pending pool by processing each tx through pre-add rules.
1016
1134
  * Starts with an empty pending pool and adds txs one by one, resolving conflicts.
@@ -1085,7 +1203,7 @@ export class TxPoolV2Impl {
1085
1203
  const publicStateSource = new DatabasePublicStateSource(db);
1086
1204
  const balance = await publicStateSource.storageRead(
1087
1205
  ProtocolContractAddress.FeeJuice,
1088
- await computeFeePayerBalanceStorageSlot(AztecAddress.fromString(feePayer)),
1206
+ await computeFeePayerBalanceStorageSlot(AztecAddress.fromStringUnsafe(feePayer)),
1089
1207
  );
1090
1208
  return balance.toBigInt();
1091
1209
  },
@@ -0,0 +1,49 @@
1
+ # Attestation Validation
2
+
3
+ This module validates `CheckpointAttestation` gossipsub messages. Attestations are signatures from committee members endorsing a checkpoint proposal.
4
+
5
+ **Topic**: `checkpoint_attestation` | **Snappy size limit**: 5 KB
6
+
7
+ ## Stage 1: AttestationValidator (Gossipsub Validation)
8
+
9
+ | # | Rule | Consequence | Severity | File |
10
+ |---|------|-------------|----------|------|
11
+ | 1 | **Slot timeliness**: `currentSlot` or `nextSlot`. Previous slot within 500ms: IGNORE. Older: REJECT. | REJECT or IGNORE | HighToleranceError | `attestation_validator.ts` |
12
+ | 2 | **Attester signature**: `getSender()` must recover valid address | REJECT | LowToleranceError | same |
13
+ | 3 | **Attester in committee**: recovered address in committee for slot | REJECT | HighToleranceError | same |
14
+ | 4 | **Proposer exists**: `getProposerAttesterAddressInSlot` must return defined | REJECT | HighToleranceError | same |
15
+ | 5 | **Proposer signature**: `getProposer()` must recover valid address | REJECT | LowToleranceError | same |
16
+ | 6 | **Proposer matches expected**: recovered proposer = expected for slot | REJECT | HighToleranceError | same |
17
+ | 7 | **NoCommitteeError**: committee unavailable | REJECT | LowToleranceError | same |
18
+
19
+ **Fisherman mode extension** (`FishermanAttestationValidator`): if a checkpoint proposal for the same archive exists in pool, the attestation's `ConsensusPayload` must `.equals()` the stored proposal's payload. On mismatch: REJECT + LowToleranceError.
20
+
21
+ ## Stage 2: Pool Admission
22
+
23
+ | # | Rule | Consequence |
24
+ |---|------|-------------|
25
+ | 8 | Sender recoverable (pool-side) | Silent drop |
26
+ | 9 | Not a duplicate (same slot + proposalId + signer) | IGNORE |
27
+ | 10 | Per-signer cap: `MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER` = 2 | IGNORE |
28
+
29
+ Own attestations added via `addOwnCheckpointAttestations` bypass the per-signer cap.
30
+
31
+ ## Stage 3: Equivocation Detection
32
+
33
+ When a signer's attestation count for a slot reaches exactly 2 (different proposals): `duplicateAttestationCallback` fires -> `WANT_TO_SLASH_EVENT` with `OffenseType.DUPLICATE_ATTESTATION`. Attestation still ACCEPTED and rebroadcast. Callback fires once (not again at count 3+).
34
+
35
+ ## Validation at L1 Checkpoint Submission (Archiver)
36
+
37
+ | Rule | Consequence | File |
38
+ |------|-------------|------|
39
+ | Each attestation must have recoverable signature (or address-only is allowed but does not count toward quorum) | Checkpoint rejected as invalid | `archiver/src/modules/validation.ts` |
40
+ | Attestation at index `i` must correspond to committee member at index `i` | Checkpoint rejected as invalid | same |
41
+ | Valid attestation count >= floor(committee * 2/3) + 1 | Checkpoint rejected as invalid | same |
42
+ | No committee / escape hatch open | Accepted unconditionally | same |
43
+
44
+ Note: `skipValidateCheckpointAttestations` config flag bypasses all archiver attestation validation.
45
+
46
+ ## Gossipsub Topic Scoring
47
+
48
+ P3 enabled with expected messages per slot = `targetCommitteeSize`. Conservative threshold (30% of convergence value). Max P3 penalty = -34 per topic.
49
+