@aztec/p2p 0.0.1-commit.6c91f13 → 0.0.1-commit.6d63667d

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 (437) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +4 -3
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +4 -4
  4. package/dest/client/factory.d.ts +1 -1
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +9 -6
  7. package/dest/client/interface.d.ts +18 -5
  8. package/dest/client/interface.d.ts.map +1 -1
  9. package/dest/client/p2p_client.d.ts +13 -14
  10. package/dest/client/p2p_client.d.ts.map +1 -1
  11. package/dest/client/p2p_client.js +462 -120
  12. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
  13. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
  14. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
  15. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
  16. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
  17. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
  18. package/dest/config.d.ts +14 -2
  19. package/dest/config.d.ts.map +1 -1
  20. package/dest/config.js +7 -3
  21. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +61 -42
  22. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  23. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  24. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +237 -263
  26. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -18
  27. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  28. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +113 -108
  29. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -16
  30. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  31. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +89 -128
  32. package/dest/mem_pools/attestation_pool/mocks.d.ts +9 -6
  33. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  34. package/dest/mem_pools/attestation_pool/mocks.js +16 -12
  35. package/dest/mem_pools/instrumentation.d.ts +1 -1
  36. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  37. package/dest/mem_pools/instrumentation.js +5 -14
  38. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +15 -10
  39. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  40. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +91 -50
  41. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +19 -5
  42. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -1
  43. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +59 -3
  44. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +79 -5
  45. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -1
  46. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +47 -0
  47. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
  48. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  49. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
  50. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +2 -2
  51. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -1
  52. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +4 -4
  53. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
  54. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +2 -0
  55. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +2 -2
  56. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -1
  57. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
  58. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
  59. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
  60. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
  61. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
  62. package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
  63. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +43 -0
  64. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
  65. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +103 -0
  66. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +47 -0
  67. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
  68. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +119 -0
  69. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
  70. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  71. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +90 -0
  72. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
  73. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
  74. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +89 -0
  75. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +10 -0
  76. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
  77. package/dest/mem_pools/tx_pool_v2/eviction/index.js +11 -0
  78. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +131 -0
  79. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
  80. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +17 -0
  81. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
  82. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  83. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +63 -0
  84. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
  85. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  86. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +91 -0
  87. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
  88. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  89. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +70 -0
  90. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
  91. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
  92. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +63 -0
  93. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
  94. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
  95. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
  96. package/dest/mem_pools/tx_pool_v2/index.d.ts +5 -0
  97. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
  98. package/dest/mem_pools/tx_pool_v2/index.js +4 -0
  99. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +197 -0
  100. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
  101. package/dest/mem_pools/tx_pool_v2/interfaces.js +6 -0
  102. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +71 -0
  103. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -0
  104. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +95 -0
  105. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
  106. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
  107. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
  108. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +99 -0
  109. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
  110. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +332 -0
  111. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +55 -0
  112. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
  113. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +156 -0
  114. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +69 -0
  115. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
  116. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +748 -0
  117. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -4
  118. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  119. package/dest/msg_validators/attestation_validator/attestation_validator.js +51 -18
  120. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +5 -5
  121. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  122. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +22 -13
  123. package/dest/msg_validators/clock_tolerance.d.ts +21 -0
  124. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  125. package/dest/msg_validators/clock_tolerance.js +37 -0
  126. package/dest/msg_validators/index.d.ts +2 -2
  127. package/dest/msg_validators/index.d.ts.map +1 -1
  128. package/dest/msg_validators/index.js +1 -1
  129. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
  130. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  131. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
  132. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
  133. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  134. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
  135. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  136. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  137. package/dest/msg_validators/proposal_validator/index.js +3 -0
  138. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
  139. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  140. package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
  141. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
  142. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
  143. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
  144. package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
  145. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  146. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  147. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +5 -4
  148. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  149. package/dest/msg_validators/tx_validator/block_header_validator.js +3 -2
  150. package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
  151. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  152. package/dest/msg_validators/tx_validator/data_validator.js +4 -1
  153. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +3 -2
  154. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  155. package/dest/msg_validators/tx_validator/double_spend_validator.js +3 -2
  156. package/dest/msg_validators/tx_validator/factory.d.ts +8 -3
  157. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  158. package/dest/msg_validators/tx_validator/factory.js +21 -11
  159. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  160. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  161. package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
  162. package/dest/msg_validators/tx_validator/gas_validator.d.ts +3 -2
  163. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  164. package/dest/msg_validators/tx_validator/gas_validator.js +11 -16
  165. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  166. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  167. package/dest/msg_validators/tx_validator/index.js +1 -0
  168. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -2
  169. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  170. package/dest/msg_validators/tx_validator/metadata_validator.js +2 -2
  171. package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
  172. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  173. package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
  174. package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
  175. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  176. package/dest/msg_validators/tx_validator/size_validator.js +23 -0
  177. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
  178. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  179. package/dest/msg_validators/tx_validator/timestamp_validator.js +2 -2
  180. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
  181. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  182. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
  183. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
  184. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  185. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -2
  186. package/dest/services/data_store.d.ts +1 -1
  187. package/dest/services/data_store.d.ts.map +1 -1
  188. package/dest/services/data_store.js +10 -6
  189. package/dest/services/discv5/discV5_service.js +1 -1
  190. package/dest/services/dummy_service.d.ts +18 -2
  191. package/dest/services/dummy_service.d.ts.map +1 -1
  192. package/dest/services/dummy_service.js +42 -0
  193. package/dest/services/encoding.d.ts +1 -1
  194. package/dest/services/encoding.d.ts.map +1 -1
  195. package/dest/services/encoding.js +6 -5
  196. package/dest/services/index.d.ts +2 -1
  197. package/dest/services/index.d.ts.map +1 -1
  198. package/dest/services/index.js +1 -0
  199. package/dest/services/libp2p/instrumentation.d.ts +1 -1
  200. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  201. package/dest/services/libp2p/instrumentation.js +30 -72
  202. package/dest/services/libp2p/libp2p_service.d.ts +38 -15
  203. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  204. package/dest/services/libp2p/libp2p_service.js +747 -183
  205. package/dest/services/peer-manager/metrics.d.ts +2 -2
  206. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  207. package/dest/services/peer-manager/metrics.js +21 -26
  208. package/dest/services/peer-manager/peer_manager.d.ts +2 -2
  209. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  210. package/dest/services/peer-manager/peer_manager.js +0 -10
  211. package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
  212. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  213. package/dest/services/peer-manager/peer_scoring.js +7 -4
  214. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +47 -0
  215. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  216. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +566 -0
  217. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  218. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  219. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  220. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
  221. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  222. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  223. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +37 -0
  224. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  225. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +151 -0
  226. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
  227. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  228. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
  229. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
  230. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  231. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
  232. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +22 -3
  233. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  234. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +63 -4
  235. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -1
  236. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  237. package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
  238. package/dest/services/reqresp/constants.d.ts +12 -0
  239. package/dest/services/reqresp/constants.d.ts.map +1 -0
  240. package/dest/services/reqresp/constants.js +7 -0
  241. package/dest/services/reqresp/interface.d.ts +3 -1
  242. package/dest/services/reqresp/interface.d.ts.map +1 -1
  243. package/dest/services/reqresp/metrics.d.ts +6 -5
  244. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  245. package/dest/services/reqresp/metrics.js +17 -21
  246. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +5 -1
  247. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  248. package/dest/services/reqresp/protocols/block_txs/bitvector.js +12 -0
  249. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +6 -5
  250. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  251. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +27 -9
  252. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +23 -6
  253. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  254. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +44 -13
  255. package/dest/services/reqresp/protocols/status.d.ts +1 -1
  256. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  257. package/dest/services/reqresp/protocols/status.js +4 -1
  258. package/dest/services/reqresp/reqresp.d.ts +6 -1
  259. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  260. package/dest/services/reqresp/reqresp.js +460 -46
  261. package/dest/services/service.d.ts +19 -3
  262. package/dest/services/service.d.ts.map +1 -1
  263. package/dest/services/tx_collection/config.d.ts +4 -1
  264. package/dest/services/tx_collection/config.d.ts.map +1 -1
  265. package/dest/services/tx_collection/config.js +9 -1
  266. package/dest/services/tx_collection/fast_tx_collection.d.ts +5 -4
  267. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  268. package/dest/services/tx_collection/fast_tx_collection.js +17 -10
  269. package/dest/services/tx_collection/index.d.ts +2 -1
  270. package/dest/services/tx_collection/index.d.ts.map +1 -1
  271. package/dest/services/tx_collection/index.js +1 -0
  272. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  273. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  274. package/dest/services/tx_collection/instrumentation.js +10 -13
  275. package/dest/services/tx_collection/proposal_tx_collector.d.ts +48 -0
  276. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
  277. package/dest/services/tx_collection/proposal_tx_collector.js +49 -0
  278. package/dest/services/tx_collection/slow_tx_collection.d.ts +3 -3
  279. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  280. package/dest/services/tx_collection/tx_collection.d.ts +8 -8
  281. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  282. package/dest/services/tx_collection/tx_collection.js +5 -5
  283. package/dest/services/tx_file_store/config.d.ts +18 -0
  284. package/dest/services/tx_file_store/config.d.ts.map +1 -0
  285. package/dest/services/tx_file_store/config.js +26 -0
  286. package/dest/services/tx_file_store/index.d.ts +4 -0
  287. package/dest/services/tx_file_store/index.d.ts.map +1 -0
  288. package/dest/services/tx_file_store/index.js +3 -0
  289. package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
  290. package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
  291. package/dest/services/tx_file_store/instrumentation.js +29 -0
  292. package/dest/services/tx_file_store/tx_file_store.d.ts +47 -0
  293. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
  294. package/dest/services/tx_file_store/tx_file_store.js +149 -0
  295. package/dest/services/tx_provider.d.ts +3 -3
  296. package/dest/services/tx_provider.d.ts.map +1 -1
  297. package/dest/services/tx_provider_instrumentation.d.ts +1 -1
  298. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  299. package/dest/services/tx_provider_instrumentation.js +7 -20
  300. package/dest/test-helpers/index.d.ts +3 -1
  301. package/dest/test-helpers/index.d.ts.map +1 -1
  302. package/dest/test-helpers/index.js +2 -0
  303. package/dest/test-helpers/test_tx_provider.d.ts +40 -0
  304. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  305. package/dest/test-helpers/test_tx_provider.js +41 -0
  306. package/dest/test-helpers/testbench-utils.d.ts +158 -0
  307. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  308. package/dest/test-helpers/testbench-utils.js +297 -0
  309. package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
  310. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  311. package/dest/testbench/p2p_client_testbench_worker.js +218 -124
  312. package/dest/testbench/worker_client_manager.d.ts +51 -6
  313. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  314. package/dest/testbench/worker_client_manager.js +226 -39
  315. package/package.json +16 -16
  316. package/src/bootstrap/bootstrap.ts +7 -4
  317. package/src/client/factory.ts +10 -10
  318. package/src/client/interface.ts +19 -4
  319. package/src/client/p2p_client.ts +95 -133
  320. package/src/client/test/tx_proposal_collector/README.md +227 -0
  321. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +336 -0
  322. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
  323. package/src/config.ts +15 -3
  324. package/src/mem_pools/attestation_pool/attestation_pool.ts +68 -41
  325. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +239 -287
  326. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +162 -140
  327. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +141 -164
  328. package/src/mem_pools/attestation_pool/mocks.ts +19 -13
  329. package/src/mem_pools/instrumentation.ts +10 -18
  330. package/src/mem_pools/tx_pool/README.md +28 -13
  331. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +130 -75
  332. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +66 -5
  333. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +119 -4
  334. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
  335. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +4 -2
  336. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  337. package/src/mem_pools/tx_pool_v2/README.md +209 -0
  338. package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
  339. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +120 -0
  340. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +147 -0
  341. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +118 -0
  342. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +111 -0
  343. package/src/mem_pools/tx_pool_v2/eviction/index.ts +23 -0
  344. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +164 -0
  345. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
  346. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
  347. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +86 -0
  348. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +72 -0
  349. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -0
  350. package/src/mem_pools/tx_pool_v2/index.ts +11 -0
  351. package/src/mem_pools/tx_pool_v2/interfaces.ts +227 -0
  352. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +161 -0
  353. package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
  354. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +417 -0
  355. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +212 -0
  356. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +882 -0
  357. package/src/msg_validators/attestation_validator/attestation_validator.ts +36 -21
  358. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +19 -16
  359. package/src/msg_validators/clock_tolerance.ts +51 -0
  360. package/src/msg_validators/index.ts +1 -1
  361. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
  362. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
  363. package/src/msg_validators/proposal_validator/index.ts +3 -0
  364. package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
  365. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
  366. package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
  367. package/src/msg_validators/tx_validator/block_header_validator.ts +6 -5
  368. package/src/msg_validators/tx_validator/data_validator.ts +18 -6
  369. package/src/msg_validators/tx_validator/double_spend_validator.ts +4 -3
  370. package/src/msg_validators/tx_validator/factory.ts +64 -23
  371. package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
  372. package/src/msg_validators/tx_validator/gas_validator.ts +17 -28
  373. package/src/msg_validators/tx_validator/index.ts +1 -0
  374. package/src/msg_validators/tx_validator/metadata_validator.ts +18 -7
  375. package/src/msg_validators/tx_validator/phases_validator.ts +5 -3
  376. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  377. package/src/msg_validators/tx_validator/timestamp_validator.ts +9 -4
  378. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
  379. package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
  380. package/src/services/data_store.ts +10 -7
  381. package/src/services/discv5/discV5_service.ts +1 -1
  382. package/src/services/dummy_service.ts +51 -0
  383. package/src/services/encoding.ts +5 -4
  384. package/src/services/index.ts +1 -0
  385. package/src/services/libp2p/instrumentation.ts +32 -73
  386. package/src/services/libp2p/libp2p_service.ts +420 -166
  387. package/src/services/peer-manager/metrics.ts +22 -26
  388. package/src/services/peer-manager/peer_manager.ts +1 -2
  389. package/src/services/peer-manager/peer_scoring.ts +3 -4
  390. package/src/services/reqresp/batch-tx-requester/README.md +305 -0
  391. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
  392. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  393. package/src/services/reqresp/batch-tx-requester/interface.ts +57 -0
  394. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +209 -0
  395. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
  396. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
  397. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
  398. package/src/services/reqresp/connection-sampler/connection_sampler.ts +19 -1
  399. package/src/services/reqresp/constants.ts +14 -0
  400. package/src/services/reqresp/interface.ts +3 -0
  401. package/src/services/reqresp/metrics.ts +36 -27
  402. package/src/services/reqresp/protocols/block_txs/bitvector.ts +16 -0
  403. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +34 -12
  404. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +57 -9
  405. package/src/services/reqresp/protocols/status.ts +7 -4
  406. package/src/services/reqresp/reqresp.ts +66 -19
  407. package/src/services/service.ts +23 -4
  408. package/src/services/tx_collection/config.ts +15 -1
  409. package/src/services/tx_collection/fast_tx_collection.ts +30 -17
  410. package/src/services/tx_collection/index.ts +5 -0
  411. package/src/services/tx_collection/instrumentation.ts +5 -13
  412. package/src/services/tx_collection/proposal_tx_collector.ts +112 -0
  413. package/src/services/tx_collection/slow_tx_collection.ts +2 -2
  414. package/src/services/tx_collection/tx_collection.ts +8 -8
  415. package/src/services/tx_file_store/config.ts +43 -0
  416. package/src/services/tx_file_store/index.ts +3 -0
  417. package/src/services/tx_file_store/instrumentation.ts +36 -0
  418. package/src/services/tx_file_store/tx_file_store.ts +173 -0
  419. package/src/services/tx_provider.ts +2 -2
  420. package/src/services/tx_provider_instrumentation.ts +13 -20
  421. package/src/test-helpers/index.ts +2 -0
  422. package/src/test-helpers/test_tx_provider.ts +64 -0
  423. package/src/test-helpers/testbench-utils.ts +374 -0
  424. package/src/testbench/p2p_client_testbench_worker.ts +337 -119
  425. package/src/testbench/worker_client_manager.ts +304 -42
  426. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +0 -15
  427. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +0 -1
  428. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +0 -88
  429. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
  430. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  431. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -82
  432. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  433. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  434. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  435. package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +0 -108
  436. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -97
  437. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
@@ -1,30 +1,29 @@
1
- import { GENESIS_BLOCK_HEADER_HASH, INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
1
+ import { GENESIS_BLOCK_HEADER_HASH } from '@aztec/constants';
2
2
  import { BlockNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
3
  import { createLogger } from '@aztec/foundation/log';
4
4
  import { DateProvider } from '@aztec/foundation/timer';
5
- import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncSingleton } from '@aztec/kv-store';
6
- import type {
7
- EthAddress,
8
- L2BlockId,
9
- L2BlockNew,
10
- L2BlockSource,
5
+ import type { AztecAsyncKVStore, AztecAsyncSingleton } from '@aztec/kv-store';
6
+ import { L2TipsKVStore } from '@aztec/kv-store/stores';
7
+ import {
8
+ type EthAddress,
9
+ type L2Block,
10
+ type L2BlockSource,
11
11
  L2BlockStream,
12
- L2BlockStreamEvent,
13
- L2Tips,
12
+ type L2BlockStreamEvent,
13
+ type L2Tips,
14
+ type L2TipsStore,
14
15
  } from '@aztec/stdlib/block';
15
16
  import type { ContractDataSource } from '@aztec/stdlib/contract';
16
17
  import { getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
17
18
  import { type PeerInfo, tryStop } from '@aztec/stdlib/interfaces/server';
18
- import { BlockAttestation, type BlockProposal, type P2PClientType } from '@aztec/stdlib/p2p';
19
- import type { Tx, TxHash } from '@aztec/stdlib/tx';
20
19
  import {
21
- Attributes,
22
- type TelemetryClient,
23
- TraceableL2BlockStream,
24
- WithTracer,
25
- getTelemetryClient,
26
- trackSpan,
27
- } from '@aztec/telemetry-client';
20
+ type BlockProposal,
21
+ CheckpointAttestation,
22
+ type CheckpointProposal,
23
+ type P2PClientType,
24
+ } from '@aztec/stdlib/p2p';
25
+ import type { Tx, TxHash } from '@aztec/stdlib/tx';
26
+ import { Attributes, type TelemetryClient, WithTracer, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
28
27
 
29
28
  import type { PeerId } from '@libp2p/interface';
30
29
  import type { ENR } from '@nethermindeth/enr';
@@ -40,8 +39,9 @@ import {
40
39
  type ReqRespSubProtocolValidators,
41
40
  } from '../services/reqresp/interface.js';
42
41
  import { chunkTxHashesRequest } from '../services/reqresp/protocols/tx.js';
43
- import type { P2PBlockReceivedCallback, P2PService } from '../services/service.js';
42
+ import type { P2PBlockReceivedCallback, P2PCheckpointReceivedCallback, P2PService } from '../services/service.js';
44
43
  import { TxCollection } from '../services/tx_collection/tx_collection.js';
44
+ import type { TxFileStore } from '../services/tx_file_store/tx_file_store.js';
45
45
  import { TxProvider } from '../services/tx_provider.js';
46
46
  import { type P2P, P2PClientState, type P2PSyncState } from './interface.js';
47
47
 
@@ -62,10 +62,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
62
62
  private provenBlockNumberAtStart = -1;
63
63
  private finalizedBlockNumberAtStart = -1;
64
64
 
65
- private synchedBlockHashes: AztecAsyncMap<BlockNumber, string>;
66
- private synchedLatestBlockNumber: AztecAsyncSingleton<BlockNumber>;
67
- private synchedProvenBlockNumber: AztecAsyncSingleton<BlockNumber>;
68
- private synchedFinalizedBlockNumber: AztecAsyncSingleton<BlockNumber>;
65
+ private l2Tips: L2TipsStore;
69
66
  private synchedLatestSlot: AztecAsyncSingleton<bigint>;
70
67
 
71
68
  private txPool: TxPool;
@@ -94,6 +91,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
94
91
  mempools: MemPools,
95
92
  private p2pService: P2PService,
96
93
  private txCollection: TxCollection,
94
+ private txFileStore: TxFileStore | undefined,
97
95
  config: Partial<P2PConfig> = {},
98
96
  private _dateProvider: DateProvider = new DateProvider(),
99
97
  private telemetry: TelemetryClient = getTelemetryClient(),
@@ -114,7 +112,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
114
112
  );
115
113
 
116
114
  // Default to collecting all txs when we see a valid proposal
117
- // This can be overridden by the validator client to attest, and it will call getTxsForBlockProposal on its own
115
+ // This can be overridden by the validator client to validate, and it will call getTxsForBlockProposal on its own
116
+ // Note: Validators do NOT attest to individual blocks - attestations are only for checkpoint proposals.
118
117
  // TODO(palla/txs): We should not trigger a request for txs on a proposal before fully validating it. We need to bring
119
118
  // validator-client code into here so we can validate a proposal is reasonable.
120
119
  this.registerBlockProposalHandler(async (block, sender) => {
@@ -123,21 +122,17 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
123
122
  const constants = this.txCollection.getConstants();
124
123
  const nextSlotTimestampSeconds = Number(getTimestampForSlot(SlotNumber(block.slotNumber + 1), constants));
125
124
  const deadline = new Date(nextSlotTimestampSeconds * 1000);
126
- const parentBlock = await this.l2BlockSource.getBlockHeaderByArchive(block.payload.header.lastArchiveRoot);
125
+ const parentBlock = await this.l2BlockSource.getBlockHeaderByArchive(block.blockHeader.lastArchive.root);
127
126
  if (!parentBlock) {
128
127
  this.log.debug(`Cannot collect txs for proposal as parent block not found`);
129
- return;
128
+ return false;
130
129
  }
131
130
  const blockNumber = BlockNumber(parentBlock.getBlockNumber() + 1);
132
131
  await this.txProvider.getTxsForBlockProposal(block, blockNumber, { pinnedPeer: sender, deadline });
133
- return undefined;
132
+ return true;
134
133
  });
135
134
 
136
- // REFACTOR: Try replacing these with an L2TipsStore
137
- this.synchedBlockHashes = store.openMap('p2p_pool_block_hashes');
138
- this.synchedLatestBlockNumber = store.openSingleton('p2p_pool_last_l2_block');
139
- this.synchedProvenBlockNumber = store.openSingleton('p2p_pool_last_proven_l2_block');
140
- this.synchedFinalizedBlockNumber = store.openSingleton('p2p_pool_last_finalized_l2_block');
135
+ this.l2Tips = new L2TipsKVStore(store, 'p2p_client');
141
136
  this.synchedLatestSlot = store.openSingleton('p2p_pool_last_l2_slot');
142
137
  }
143
138
 
@@ -163,7 +158,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
163
158
  }
164
159
 
165
160
  public getL2BlockHash(number: BlockNumber): Promise<string | undefined> {
166
- return this.synchedBlockHashes.getAsync(number);
161
+ return this.l2Tips.getL2BlockHash(number);
167
162
  }
168
163
 
169
164
  public updateP2PConfig(config: Partial<P2PConfig>): Promise<void> {
@@ -172,85 +167,45 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
172
167
  return Promise.resolve();
173
168
  }
174
169
 
175
- public async getL2Tips(): Promise<L2Tips> {
176
- const latestBlockNumber = await this.getSyncedLatestBlockNum();
177
- let latestBlockHash: string | undefined;
178
-
179
- const provenBlockNumber = await this.getSyncedProvenBlockNum();
180
- let provenBlockHash: string | undefined;
181
-
182
- const finalizedBlockNumber = await this.getSyncedFinalizedBlockNum();
183
- let finalizedBlockHash: string | undefined;
184
-
185
- if (latestBlockNumber > 0) {
186
- latestBlockHash = await this.synchedBlockHashes.getAsync(latestBlockNumber);
187
- if (typeof latestBlockHash === 'undefined') {
188
- throw new Error(`Block hash for latest block ${latestBlockNumber} not found in p2p client`);
189
- }
190
- }
191
-
192
- if (provenBlockNumber > 0) {
193
- provenBlockHash = await this.synchedBlockHashes.getAsync(provenBlockNumber);
194
- if (typeof provenBlockHash === 'undefined') {
195
- throw new Error(`Block hash for proven block ${provenBlockNumber} not found in p2p client`);
196
- }
197
- }
198
-
199
- if (finalizedBlockNumber > 0) {
200
- finalizedBlockHash = await this.synchedBlockHashes.getAsync(finalizedBlockNumber);
201
- if (typeof finalizedBlockHash === 'undefined') {
202
- throw new Error(`Block hash for finalized block ${finalizedBlockNumber} not found in p2p client`);
203
- }
204
- }
205
-
206
- const genesisHash = GENESIS_BLOCK_HEADER_HASH.toString();
207
-
208
- return {
209
- latest: { hash: latestBlockHash ?? genesisHash, number: latestBlockNumber },
210
- proven: { hash: provenBlockHash ?? genesisHash, number: provenBlockNumber },
211
- finalized: { hash: finalizedBlockHash ?? genesisHash, number: finalizedBlockNumber },
212
- };
170
+ public getL2Tips(): Promise<L2Tips> {
171
+ return this.l2Tips.getL2Tips();
213
172
  }
214
173
 
215
174
  public async handleBlockStreamEvent(event: L2BlockStreamEvent): Promise<void> {
216
175
  this.log.debug(`Handling block stream event ${event.type}`);
176
+
217
177
  switch (event.type) {
218
178
  case 'blocks-added':
219
- await this.handleLatestL2Blocks(event.blocks.map(b => b.block.toL2Block()));
179
+ await this.handleLatestL2Blocks(event.blocks);
220
180
  break;
221
181
  case 'chain-finalized': {
222
- // TODO (alexg): I think we can prune the block hashes map here
223
- await this.setBlockHash(event.block);
224
- const from = BlockNumber((await this.getSyncedFinalizedBlockNum()) + 1);
182
+ const oldFinalizedBlockNum = await this.getSyncedFinalizedBlockNum();
183
+ const from = BlockNumber(oldFinalizedBlockNum + 1);
225
184
  const limit = event.block.number - from + 1;
226
185
  if (limit > 0) {
227
186
  const oldBlocks = await this.l2BlockSource.getBlocks(from, limit);
228
- await this.handleFinalizedL2Blocks(oldBlocks.map(b => b.toL2Block()));
187
+ await this.handleFinalizedL2Blocks(oldBlocks);
229
188
  }
230
189
  break;
231
190
  }
232
- case 'chain-proven': {
233
- await this.setBlockHash(event.block);
191
+ case 'chain-proven':
234
192
  this.txCollection.stopCollectingForBlocksUpTo(event.block.number);
235
- await this.synchedProvenBlockNumber.set(event.block.number);
236
193
  break;
237
- }
238
194
  case 'chain-pruned':
239
- await this.setBlockHash(event.block);
240
195
  this.txCollection.stopCollectingForBlocksAfter(event.block.number);
241
196
  await this.handlePruneL2Blocks(event.block.number);
242
197
  break;
198
+ case 'chain-checkpointed':
199
+ break;
243
200
  default: {
244
201
  const _: never = event;
245
202
  break;
246
203
  }
247
204
  }
248
- }
249
205
 
250
- private async setBlockHash(block: L2BlockId): Promise<void> {
251
- if (block.hash !== undefined) {
252
- await this.synchedBlockHashes.set(block.number, block.hash.toString());
253
- }
206
+ // Pass the event through to our l2 tips store
207
+ await this.l2Tips.handleBlockStreamEvent(event);
208
+ await this.startServiceIfSynched();
254
209
  }
255
210
 
256
211
  #assertIsReady() {
@@ -274,9 +229,9 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
274
229
 
275
230
  // get the current latest block numbers
276
231
  const latestBlockNumbers = await this.l2BlockSource.getL2Tips();
277
- this.latestBlockNumberAtStart = latestBlockNumbers.latest.number;
278
- this.provenBlockNumberAtStart = latestBlockNumbers.proven.number;
279
- this.finalizedBlockNumberAtStart = latestBlockNumbers.finalized.number;
232
+ this.latestBlockNumberAtStart = latestBlockNumbers.proposed.number;
233
+ this.provenBlockNumberAtStart = latestBlockNumbers.proven.block.number;
234
+ this.finalizedBlockNumberAtStart = latestBlockNumbers.finalized.block.number;
280
235
 
281
236
  const syncedLatestBlock = (await this.getSyncedLatestBlockNum()) + 1;
282
237
  const syncedProvenBlock = (await this.getSyncedProvenBlockNum()) + 1;
@@ -321,6 +276,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
321
276
 
322
277
  this.blockStream!.start();
323
278
  await this.txCollection.start();
279
+ this.txFileStore?.start();
324
280
  return this.syncPromise;
325
281
  }
326
282
 
@@ -335,12 +291,10 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
335
291
  private initBlockStream(startingBlock?: BlockNumber) {
336
292
  if (!this.blockStream) {
337
293
  const { blockRequestBatchSize: batchSize, blockCheckIntervalMS: pollIntervalMS } = this.config;
338
- this.blockStream = new TraceableL2BlockStream(
294
+ this.blockStream = new L2BlockStream(
339
295
  this.l2BlockSource,
340
296
  this,
341
297
  this,
342
- this.telemetry.getTracer('P2PL2BlockStream'),
343
- 'P2PL2BlockStream',
344
298
  createLogger(`${this.log.module}:l2-block-stream`),
345
299
  { batchSize, pollIntervalMS, startingBlock },
346
300
  );
@@ -355,6 +309,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
355
309
  this.log.debug('Stopping p2p client...');
356
310
  await tryStop(this.txCollection);
357
311
  this.log.debug('Stopped tx collection service');
312
+ await this.txFileStore?.stop();
313
+ this.log.debug('Stopped tx file store');
358
314
  await this.p2pService.stop();
359
315
  this.log.debug('Stopped p2p service');
360
316
  await this.blockStream?.stop();
@@ -375,28 +331,44 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
375
331
  [Attributes.BLOCK_ARCHIVE]: proposal.archive.toString(),
376
332
  [Attributes.P2P_ID]: (await proposal.p2pMessageLoggingIdentifier()).toString(),
377
333
  }))
378
- public broadcastProposal(proposal: BlockProposal): Promise<void> {
334
+ public async broadcastProposal(proposal: BlockProposal): Promise<void> {
379
335
  this.log.verbose(`Broadcasting proposal for slot ${proposal.slotNumber} to peers`);
336
+ // Store our own proposal so we can respond to req/resp requests for it
337
+ await this.attestationPool.addBlockProposal(proposal);
380
338
  return this.p2pService.propagate(proposal);
381
339
  }
382
340
 
383
- public async broadcastAttestations(attestations: BlockAttestation[]): Promise<void> {
384
- this.log.verbose(`Broadcasting ${attestations.length} attestations to peers`);
385
- await Promise.all(attestations.map(att => this.p2pService.propagate(att)));
341
+ @trackSpan('p2pClient.broadcastCheckpointProposal', async proposal => ({
342
+ [Attributes.SLOT_NUMBER]: proposal.slotNumber,
343
+ [Attributes.BLOCK_ARCHIVE]: proposal.archive.toString(),
344
+ [Attributes.P2P_ID]: (await proposal.p2pMessageLoggingIdentifier()).toString(),
345
+ }))
346
+ public async broadcastCheckpointProposal(proposal: CheckpointProposal): Promise<void> {
347
+ this.log.verbose(`Broadcasting checkpoint proposal for slot ${proposal.slotNumber} to peers`);
348
+ const blockProposal = proposal.getBlockProposal();
349
+ if (blockProposal) {
350
+ // Store our own last-block proposal so we can respond to req/resp requests for it.
351
+ await this.attestationPool.addBlockProposal(blockProposal);
352
+ }
353
+ return this.p2pService.propagate(proposal);
386
354
  }
387
355
 
388
- public async getAttestationsForSlot(slot: SlotNumber, proposalId?: string): Promise<BlockAttestation[]> {
389
- return await (proposalId
390
- ? this.attestationPool.getAttestationsForSlotAndProposal(slot, proposalId)
391
- : this.attestationPool.getAttestationsForSlot(slot));
356
+ public async broadcastCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void> {
357
+ this.log.verbose(`Broadcasting ${attestations.length} checkpoint attestations to peers`);
358
+ await Promise.all(attestations.map(att => this.p2pService.propagate(att)));
392
359
  }
393
360
 
394
- public addAttestations(attestations: BlockAttestation[]): Promise<void> {
395
- return this.attestationPool.addAttestations(attestations);
361
+ public async getCheckpointAttestationsForSlot(
362
+ slot: SlotNumber,
363
+ proposalId?: string,
364
+ ): Promise<CheckpointAttestation[]> {
365
+ return await (proposalId
366
+ ? this.attestationPool.getCheckpointAttestationsForSlotAndProposal(slot, proposalId)
367
+ : this.attestationPool.getCheckpointAttestationsForSlot(slot));
396
368
  }
397
369
 
398
- public deleteAttestation(attestation: BlockAttestation): Promise<void> {
399
- return this.attestationPool.deleteAttestations([attestation]);
370
+ public addCheckpointAttestations(attestations: CheckpointAttestation[]): Promise<void> {
371
+ return this.attestationPool.addCheckpointAttestations(attestations);
400
372
  }
401
373
 
402
374
  // REVIEW: https://github.com/AztecProtocol/aztec-packages/issues/7963
@@ -405,6 +377,10 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
405
377
  this.p2pService.registerBlockReceivedCallback(handler);
406
378
  }
407
379
 
380
+ public registerCheckpointProposalHandler(handler: P2PCheckpointReceivedCallback): void {
381
+ this.p2pService.registerCheckpointReceivedCallback(handler);
382
+ }
383
+
408
384
  /**
409
385
  * Uses the batched Request Response protocol to request a set of transactions from the network.
410
386
  */
@@ -647,7 +623,8 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
647
623
  * @returns Block number of latest L2 Block we've synced with.
648
624
  */
649
625
  public async getSyncedLatestBlockNum(): Promise<BlockNumber> {
650
- return (await this.synchedLatestBlockNumber.getAsync()) ?? BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
626
+ const tips = await this.l2Tips.getL2Tips();
627
+ return tips.proposed.number;
651
628
  }
652
629
 
653
630
  /**
@@ -655,11 +632,13 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
655
632
  * @returns Block number of latest proven L2 Block we've synced with.
656
633
  */
657
634
  public async getSyncedProvenBlockNum(): Promise<BlockNumber> {
658
- return (await this.synchedProvenBlockNumber.getAsync()) ?? BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
635
+ const tips = await this.l2Tips.getL2Tips();
636
+ return tips.proven.block.number;
659
637
  }
660
638
 
661
639
  public async getSyncedFinalizedBlockNum(): Promise<BlockNumber> {
662
- return (await this.synchedFinalizedBlockNumber.getAsync()) ?? BlockNumber(INITIAL_L2_BLOCK_NUM - 1);
640
+ const tips = await this.l2Tips.getL2Tips();
641
+ return tips.finalized.block.number;
663
642
  }
664
643
 
665
644
  /** Returns latest L2 slot for which we have seen an L2 block. */
@@ -692,7 +671,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
692
671
  * @param blocks - A list of existing blocks with txs that the P2P client needs to ensure the tx pool is reconciled with.
693
672
  * @returns Empty promise.
694
673
  */
695
- private async markTxsAsMinedFromBlocks(blocks: L2BlockNew[]): Promise<void> {
674
+ private async markTxsAsMinedFromBlocks(blocks: L2Block[]): Promise<void> {
696
675
  for (const block of blocks) {
697
676
  const txHashes = block.body.txEffects.map(txEffect => txEffect.txHash);
698
677
  await this.txPool.markAsMined(txHashes, block.header);
@@ -704,7 +683,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
704
683
  * @param blocks - A list of existing blocks with txs that the P2P client needs to ensure the tx pool is reconciled with.
705
684
  * @returns Empty promise.
706
685
  */
707
- private async handleLatestL2Blocks(blocks: L2BlockNew[]): Promise<void> {
686
+ private async handleLatestL2Blocks(blocks: L2Block[]): Promise<void> {
708
687
  if (!blocks.length) {
709
688
  return Promise.resolve();
710
689
  }
@@ -714,24 +693,12 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
714
693
  await this.startCollectingMissingTxs(blocks);
715
694
 
716
695
  const lastBlock = blocks.at(-1)!;
717
-
718
- await Promise.all(
719
- blocks.map(async block =>
720
- this.setBlockHash({
721
- number: block.number,
722
- hash: await block.hash().then(h => h.toString()),
723
- }),
724
- ),
725
- );
726
-
727
- await this.synchedLatestBlockNumber.set(lastBlock.number);
728
696
  await this.synchedLatestSlot.set(BigInt(lastBlock.header.getSlot()));
729
697
  this.log.verbose(`Synched to latest block ${lastBlock.number}`);
730
- await this.startServiceIfSynched();
731
698
  }
732
699
 
733
700
  /** Request txs for unproven blocks so the prover node has more chances to get them. */
734
- private async startCollectingMissingTxs(blocks: L2BlockNew[]): Promise<void> {
701
+ private async startCollectingMissingTxs(blocks: L2Block[]): Promise<void> {
735
702
  try {
736
703
  // TODO(#15435): If the archiver has lagged behind L1, the reported proven block number may
737
704
  // be much lower than the actual one, and it does not update until the pending chain is
@@ -764,7 +731,7 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
764
731
  * @param blocks - A list of finalized L2 blocks.
765
732
  * @returns Empty promise.
766
733
  */
767
- private async handleFinalizedL2Blocks(blocks: L2BlockNew[]): Promise<void> {
734
+ private async handleFinalizedL2Blocks(blocks: L2Block[]): Promise<void> {
768
735
  if (!blocks.length) {
769
736
  return Promise.resolve();
770
737
  }
@@ -778,12 +745,9 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
778
745
  await this.txPool.deleteTxs(txHashes, { permanently: true });
779
746
  await this.txPool.cleanupDeletedMinedTxs(lastBlockNum);
780
747
 
781
- await this.attestationPool.deleteAttestationsOlderThan(lastBlockSlot);
748
+ await this.attestationPool.deleteCheckpointAttestationsOlderThan(lastBlockSlot);
782
749
 
783
- await this.synchedFinalizedBlockNumber.set(lastBlockNum);
784
750
  this.log.debug(`Synched to finalized block ${lastBlockNum} at slot ${lastBlockSlot}`);
785
-
786
- await this.startServiceIfSynched();
787
751
  }
788
752
 
789
753
  /**
@@ -831,18 +795,16 @@ export class P2PClient<T extends P2PClientType = P2PClientType.Full>
831
795
  } else {
832
796
  await this.txPool.markMinedAsPending(minedTxsFromReorg, latestBlock);
833
797
  }
834
-
835
- await this.synchedLatestBlockNumber.set(latestBlock);
836
- // no need to update block hashes, as they will be updated as new blocks are added
837
798
  }
838
799
 
839
800
  private async startServiceIfSynched() {
840
801
  if (this.currentState !== P2PClientState.SYNCHING) {
841
802
  return;
842
803
  }
843
- const syncedFinalizedBlock = await this.getSyncedFinalizedBlockNum();
844
- const syncedProvenBlock = await this.getSyncedProvenBlockNum();
845
- const syncedLatestBlock = await this.getSyncedLatestBlockNum();
804
+ const tips = await this.l2Tips.getL2Tips();
805
+ const syncedFinalizedBlock = tips.finalized.block.number;
806
+ const syncedProvenBlock = tips.proven.block.number;
807
+ const syncedLatestBlock = tips.proposed.number;
846
808
 
847
809
  if (
848
810
  syncedLatestBlock >= this.latestBlockNumberAtStart &&
@@ -0,0 +1,227 @@
1
+ # ProposalTxCollector Benchmarks
2
+
3
+ This benchmark suite measures **how quickly a proposer node can fetch missing transactions from P2P peers** when building a block proposal. It compares two alternative transaction-collection implementations under several controlled "who-has-which-txs" distributions.
4
+
5
+ ## Purpose
6
+
7
+ When proposing a block, the node may have a block proposal containing a list of `txHashes`, but may be **missing the full `Tx` objects** locally. The node must fetch those missing txs from peers via the P2P req/resp layer.
8
+
9
+ This benchmark answers:
10
+
11
+ - How long does it take to fetch **N missing txs** (N ∈ **{10, 50, 100, 500}**)?
12
+ - How do different **peer availability patterns** affect performance?
13
+ - Which collector strategy performs better under each pattern?
14
+
15
+ The suite compares two collectors:
16
+
17
+ - **`BatchTxRequesterCollector`** (collector type: `batch-requester`)
18
+ - **`SendBatchRequestCollector`** (collector type: `send-batch-request`)
19
+
20
+ ## Architecture
21
+
22
+ The benchmark runs a small simulated network on localhost:
23
+
24
+ ```
25
+ ┌─────────────────────────────────────────────────────────────────────┐
26
+ │ Test Process (Driver) │
27
+ │ p2p_client.proposal_tx_collector.bench.test.ts │
28
+ │ ┌─────────────────────────────────────────────────────────────┐ │
29
+ │ │ WorkerClientManager │ │
30
+ │ │ (src/testbench/worker_client_manager.ts) │ │
31
+ │ └─────────────────────────────────────────────────────────────┘ │
32
+ │ │ IPC │
33
+ │ ┌────────────────────┼────────────────────┐ │
34
+ │ ▼ ▼ ▼ │
35
+ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
36
+ │ │ Worker 0 │◄──────►│ Worker 1 │◄──────►│ Worker N-1│ │
37
+ │ │ (Collector│ P2P │(Responder)│ P2P │(Responder)│ │
38
+ │ │ Node) │ │ │ │ │ │
39
+ │ │ TxPool:[] │ │ TxPool: │ │ TxPool: │ │
40
+ │ │ │ │ [txs...] │ │ [txs...] │ │
41
+ │ └───────────┘ └───────────┘ └───────────┘ │
42
+ └─────────────────────────────────────────────────────────────────────┘
43
+ ```
44
+
45
+ - **N worker processes** are spawned using Node's **`child_process.fork()`**
46
+ - Each worker runs a "light" **`P2PClient.Full`** node (enough to exercise the real P2P req/resp machinery)
47
+ - Workers communicate with the test process via **IPC messages** defined in `p2p_client_testbench_worker.ts`
48
+
49
+ ### Why multiple processes?
50
+
51
+ Using separate OS processes makes the setup closer to real networking behavior (independent event loops, scheduling, IPC boundaries), and avoids many artifacts you'd get by running everything in one process.
52
+
53
+ ### Worker roles
54
+
55
+ The network is intentionally asymmetric:
56
+
57
+ - **Worker 0 is the collector/proposer node**
58
+ - Starts with an **empty tx pool** (`[]`)
59
+ - Is the only worker instructed to run the collector for each `BENCH_REQRESP` command
60
+ - **Workers 1..N-1 are responder peers**
61
+ - Locally generate and filter txs according to the distribution pattern
62
+ - Respond to req/resp queries made by Worker 0's collector
63
+
64
+ This models a proposer that has only `txHashes` in a proposal and must fetch the full tx bodies from the network.
65
+
66
+ ## Transaction Distribution Patterns
67
+
68
+ Each benchmark case generates `missingTxCount` mock txs and assigns them to peers using one of these patterns:
69
+
70
+ ### `uniform`
71
+
72
+ **Every responder peer has every transaction.**
73
+
74
+ - Simulates the best-case: high replication / high gossip success
75
+ - Expectation: collector should quickly succeed; differences mostly reflect collector overhead and batching strategy
76
+
77
+ ### `sparse`
78
+
79
+ **Each transaction exists on only a small subset of peers.**
80
+
81
+ Each responder is bucketed and holds txs whose index falls into its bucket or the "next" bucket (striped by tx index).
82
+
83
+ - Simulates partial propagation, churn, or uneven mempool convergence
84
+ - Expectation: collector must query multiple peers and cope with "misses"
85
+
86
+ ### `pinned-only`
87
+
88
+ **Only a single "pinned" peer has the transactions; all other peers have none.**
89
+
90
+ - Simulates "I know exactly who has the txs" (or a topology where one peer is the source of truth)
91
+ - Useful to test whether "pinned peer" fast-paths work as intended
92
+
93
+ > **Guardrail:** the pinned peer index must be within `(0, numberOfPeers)` (Worker 0 cannot be pinned).
94
+
95
+ ## Collectors Under Test
96
+
97
+ ### `BatchTxRequesterCollector` (`batch-requester`)
98
+
99
+ ```typescript
100
+ new BatchTxRequesterCollector(p2pService, logger, new DateProvider())
101
+ ```
102
+
103
+ Uses the P2P service plus internal logic to fetch missing txs, coordinating requests in a batched or staged way.
104
+
105
+ ### `SendBatchRequestCollector` (`send-batch-request`)
106
+
107
+ ```typescript
108
+ const maxPeers = 10;
109
+ const maxRetryAttempts = Math.max(peerIds.length, 3);
110
+ new SendBatchRequestCollector(p2pService, maxPeers, maxRetryAttempts)
111
+ ```
112
+
113
+ Explicitly caps the number of peers it will involve (`maxPeers`) and uses a retry budget derived from peer count.
114
+
115
+ ## Test Parameters
116
+
117
+ | Parameter | Value | Description |
118
+ |-----------|-------|-------------|
119
+ | `PEERS_PER_RUN` | 30 | Number of worker processes spawned |
120
+ | `MISSING_TX_COUNTS` | 10, 50, 100, 500 | Number of missing transactions to fetch |
121
+ | `TIMEOUT_MS` | 30,000 ms | Collector timeout per case |
122
+ | `TEST_TIMEOUT_MS` | 600,000 ms | Overall Jest timeout (10 minutes) |
123
+
124
+ ## Running
125
+
126
+ From the p2p package:
127
+
128
+ ```bash
129
+ cd yarn-project/p2p
130
+ yarn test src/client/test/tx_proposal_collector/p2p_client.proposal_tx_collector.bench.test.ts
131
+ ```
132
+
133
+ Or from repo root:
134
+
135
+ ```bash
136
+ yarn test p2p_client.proposal_tx_collector.bench.test.ts
137
+ ```
138
+
139
+ The benchmark is intentionally long due to spawning many processes and running multiple cases.
140
+
141
+ ## Output Formats
142
+
143
+ ### Default: Markdown table to stdout
144
+
145
+ If no env vars are set, the suite prints a table:
146
+
147
+ ```
148
+ | Collector | Distribution | Missing | Duration (ms) | Fetched | Success |
149
+ |---------------------|--------------|---------|---------------|---------|---------|
150
+ | batch-requester | pinned-only | 10 | 123 | 10 | Yes |
151
+ | send-batch-request | pinned-only | 10 | 145 | 10 | Yes |
152
+ ```
153
+
154
+ Plus a comparison summary stating which collector was faster per `(distribution, missing)` pair.
155
+
156
+ ### JSON metrics (for CI/dashboards)
157
+
158
+ ```bash
159
+ BENCH_OUTPUT=/path/results.json yarn test ...
160
+ ```
161
+
162
+ Writes JSON metrics like:
163
+ - `ProposalTxCollector/<collector>/<distribution>/missing_<N>/duration` (ms)
164
+ - `ProposalTxCollector/<collector>/<distribution>/missing_<N>/fetched` (txs)
165
+
166
+ ### Markdown file output
167
+
168
+ ```bash
169
+ BENCH_OUTPUT_MD=/path/results.md yarn test ...
170
+ ```
171
+
172
+ Writes the pretty table + summary to disk.
173
+
174
+ ## Interpreting Results
175
+
176
+ For each case the benchmark records:
177
+
178
+ - `durationMs`: wall-clock time spent inside the collector call
179
+ - `fetchedCount`: how many txs were returned by the collector
180
+ - `success`: `fetchedCount === missingTxCount`
181
+
182
+ **Guidelines:**
183
+
184
+ - **Always check `Success` first.** A faster run that fetched fewer txs is not a win.
185
+ - Compare collectors **within the same distribution + missing count** only.
186
+ - Expect `pinned-only` to highlight pinned-peer behavior (fast if pinned peer is used effectively; slow if the algorithm wastes time sampling other peers).
187
+ - Expect `sparse` to be the most "network-like" stress case, since many peers won't have each requested tx.
188
+
189
+ ## Determinism / Noise Reduction
190
+
191
+ Inside each worker, the benchmark intentionally reduces variability:
192
+
193
+ - **Unlimited rate limits** are installed so the req/resp rate limiter doesn't dominate results
194
+ - **Deterministic tx generation** ensures all workers see the same tx set without large IPC payloads
195
+
196
+ This makes the benchmark better for *comparing collectors* (A vs B), but it is **not** a perfect model of production networking conditions.
197
+
198
+ ## Limitations
199
+
200
+ This benchmark does **not** measure:
201
+
202
+ - Real internet latency, NAT traversal, or adversarial peers (everything runs on localhost)
203
+ - End-to-end proposer behavior beyond tx fetching (block construction, proving, etc.)
204
+ - Gossip-based mempool convergence—tx availability is injected directly into each worker's in-memory tx pool
205
+
206
+ ## Files
207
+
208
+ | File | Purpose |
209
+ |------|---------|
210
+ | `p2p_client.proposal_tx_collector.bench.test.ts` | Test suite (cases, distributions, output formatting) |
211
+ | `proposal_tx_collector_worker.ts` | Collector-specific worker implementation |
212
+ | `proposal_tx_collector_worker_protocol.ts` | IPC message types and serialization |
213
+ | `src/testbench/worker_client_manager.ts` | Worker process manager (forking, IPC, orchestration) |
214
+ | `src/testbench/p2p_client_testbench_worker.ts` | General testbench worker implementation |
215
+ | `src/test-helpers/testbench-utils.ts` | Shared mocks and utilities (InMemoryTxPool, InMemoryAttestationPool, etc.) |
216
+
217
+ ## Implementation Notes
218
+
219
+ - Workers run TypeScript via `ts-node/esm` unless a compiled JS worker exists at `dest/testbench/p2p_client_testbench_worker.js`
220
+ - Request/response rate limits are overridden so the benchmark is not throttled
221
+ - Workers generate txs locally from a shared seed to avoid sending large tx payloads over IPC
222
+
223
+ ## Practical Tips
224
+
225
+ - Run on an otherwise idle machine; CPU scheduling noise matters when spawning 30 node processes
226
+ - If you see intermittent failures, increase `TIMEOUT_MS` or reduce `PEERS_PER_RUN` for local iteration
227
+ - Use `BENCH_OUTPUT` in CI to track performance regressions over time