@aztec/p2p 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108

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 (334) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +14 -4
  4. package/dest/client/factory.d.ts +3 -2
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +9 -5
  7. package/dest/client/index.d.ts +1 -1
  8. package/dest/client/interface.d.ts +8 -6
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +13 -36
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +460 -63
  13. package/dest/config.d.ts +67 -61
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +28 -15
  16. package/dest/enr/generate-enr.d.ts +2 -2
  17. package/dest/enr/generate-enr.d.ts.map +1 -1
  18. package/dest/enr/generate-enr.js +1 -1
  19. package/dest/enr/index.d.ts +1 -1
  20. package/dest/errors/attestation-pool.error.d.ts +7 -0
  21. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  22. package/dest/errors/attestation-pool.error.js +12 -0
  23. package/dest/errors/reqresp.error.d.ts +1 -1
  24. package/dest/errors/reqresp.error.d.ts.map +1 -1
  25. package/dest/index.d.ts +1 -1
  26. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +43 -6
  27. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  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 +72 -46
  31. package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
  32. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +15 -6
  33. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  34. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +73 -18
  35. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +13 -6
  36. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  37. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +69 -11
  38. package/dest/mem_pools/attestation_pool/mocks.d.ts +226 -5
  39. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  40. package/dest/mem_pools/attestation_pool/mocks.js +9 -7
  41. package/dest/mem_pools/index.d.ts +1 -1
  42. package/dest/mem_pools/instrumentation.d.ts +9 -1
  43. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  44. package/dest/mem_pools/instrumentation.js +38 -2
  45. package/dest/mem_pools/interface.d.ts +3 -4
  46. package/dest/mem_pools/interface.d.ts.map +1 -1
  47. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +39 -58
  48. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  49. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +314 -317
  50. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +18 -0
  51. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
  52. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +56 -0
  53. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +83 -0
  54. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
  55. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +5 -0
  56. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts +15 -0
  57. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.d.ts.map +1 -0
  58. package/dest/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.js +88 -0
  59. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
  60. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  61. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
  62. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
  63. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  64. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +76 -0
  65. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
  66. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  67. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
  68. package/dest/mem_pools/tx_pool/index.d.ts +1 -2
  69. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
  70. package/dest/mem_pools/tx_pool/index.js +0 -1
  71. package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
  72. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  73. package/dest/mem_pools/tx_pool/priority.js +6 -1
  74. package/dest/mem_pools/tx_pool/tx_pool.d.ts +28 -9
  75. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  76. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  77. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  78. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +155 -25
  79. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -2
  80. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  81. package/dest/msg_validators/attestation_validator/attestation_validator.js +32 -5
  82. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  83. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  84. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +67 -0
  85. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  86. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  87. package/dest/msg_validators/attestation_validator/index.js +1 -0
  88. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +5 -2
  89. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
  90. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +44 -12
  91. package/dest/msg_validators/block_proposal_validator/index.d.ts +1 -1
  92. package/dest/msg_validators/index.d.ts +1 -1
  93. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
  94. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  96. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  97. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  98. package/dest/msg_validators/tx_validator/archive_cache.d.ts +2 -2
  99. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  100. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +2 -2
  101. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  102. package/dest/msg_validators/tx_validator/block_header_validator.js +1 -1
  103. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  104. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  105. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +1 -1
  106. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  107. package/dest/msg_validators/tx_validator/double_spend_validator.js +1 -1
  108. package/dest/msg_validators/tx_validator/factory.d.ts +4 -3
  109. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  110. package/dest/msg_validators/tx_validator/factory.js +11 -5
  111. package/dest/msg_validators/tx_validator/gas_validator.d.ts +1 -1
  112. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  113. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  114. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  115. package/dest/msg_validators/tx_validator/index.js +1 -0
  116. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -6
  117. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  118. package/dest/msg_validators/tx_validator/metadata_validator.js +6 -24
  119. package/dest/msg_validators/tx_validator/phases_validator.d.ts +1 -1
  120. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  121. package/dest/msg_validators/tx_validator/phases_validator.js +3 -1
  122. package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
  123. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
  124. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +13 -0
  125. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  126. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  127. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +1 -1
  128. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  129. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
  130. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  131. package/dest/services/data_store.d.ts +1 -1
  132. package/dest/services/data_store.d.ts.map +1 -1
  133. package/dest/services/discv5/discV5_service.d.ts +3 -3
  134. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  135. package/dest/services/discv5/discV5_service.js +2 -2
  136. package/dest/services/dummy_service.d.ts +2 -2
  137. package/dest/services/dummy_service.d.ts.map +1 -1
  138. package/dest/services/encoding.d.ts +25 -4
  139. package/dest/services/encoding.d.ts.map +1 -1
  140. package/dest/services/encoding.js +74 -6
  141. package/dest/services/gossipsub/scoring.d.ts +1 -1
  142. package/dest/services/index.d.ts +1 -1
  143. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  144. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  145. package/dest/services/libp2p/instrumentation.js +9 -2
  146. package/dest/services/libp2p/libp2p_service.d.ts +33 -72
  147. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  148. package/dest/services/libp2p/libp2p_service.js +841 -175
  149. package/dest/services/peer-manager/interface.d.ts +1 -1
  150. package/dest/services/peer-manager/metrics.d.ts +8 -1
  151. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  152. package/dest/services/peer-manager/metrics.js +28 -0
  153. package/dest/services/peer-manager/peer_manager.d.ts +2 -33
  154. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  155. package/dest/services/peer-manager/peer_manager.js +29 -22
  156. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  157. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  158. package/dest/services/peer-manager/peer_scoring.js +40 -2
  159. package/dest/services/reqresp/config.d.ts +1 -1
  160. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
  161. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  162. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +1 -4
  163. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  164. package/dest/services/reqresp/index.d.ts +1 -1
  165. package/dest/services/reqresp/interface.d.ts +2 -11
  166. package/dest/services/reqresp/interface.d.ts.map +1 -1
  167. package/dest/services/reqresp/interface.js +1 -18
  168. package/dest/services/reqresp/metrics.d.ts +1 -1
  169. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  170. package/dest/services/reqresp/protocols/auth.d.ts +2 -2
  171. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  172. package/dest/services/reqresp/protocols/auth.js +2 -2
  173. package/dest/services/reqresp/protocols/block.d.ts +1 -1
  174. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  175. package/dest/services/reqresp/protocols/block.js +3 -2
  176. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +1 -1
  177. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  178. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  179. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +4 -6
  180. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  181. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +1 -1
  182. package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
  183. package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
  184. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  185. package/dest/services/reqresp/protocols/index.d.ts +1 -1
  186. package/dest/services/reqresp/protocols/ping.d.ts +1 -1
  187. package/dest/services/reqresp/protocols/status.d.ts +6 -5
  188. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  189. package/dest/services/reqresp/protocols/status.js +4 -3
  190. package/dest/services/reqresp/protocols/tx.d.ts +2 -3
  191. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  192. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  193. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
  194. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  195. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  196. package/dest/services/reqresp/reqresp.d.ts +1 -41
  197. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  198. package/dest/services/reqresp/reqresp.js +416 -34
  199. package/dest/services/reqresp/status.d.ts +2 -2
  200. package/dest/services/reqresp/status.d.ts.map +1 -1
  201. package/dest/services/service.d.ts +2 -2
  202. package/dest/services/service.d.ts.map +1 -1
  203. package/dest/services/tx_collection/config.d.ts +1 -1
  204. package/dest/services/tx_collection/config.js +1 -1
  205. package/dest/services/tx_collection/fast_tx_collection.d.ts +4 -9
  206. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  207. package/dest/services/tx_collection/fast_tx_collection.js +6 -1
  208. package/dest/services/tx_collection/index.d.ts +1 -1
  209. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  210. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  211. package/dest/services/tx_collection/slow_tx_collection.d.ts +6 -7
  212. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  213. package/dest/services/tx_collection/slow_tx_collection.js +2 -1
  214. package/dest/services/tx_collection/tx_collection.d.ts +12 -11
  215. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  216. package/dest/services/tx_collection/tx_collection.js +3 -2
  217. package/dest/services/tx_collection/tx_collection_sink.d.ts +3 -3
  218. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  219. package/dest/services/tx_collection/tx_collection_sink.js +34 -4
  220. package/dest/services/tx_collection/tx_source.d.ts +1 -1
  221. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  222. package/dest/services/tx_collection/tx_source.js +2 -2
  223. package/dest/services/tx_provider.d.ts +6 -4
  224. package/dest/services/tx_provider.d.ts.map +1 -1
  225. package/dest/services/tx_provider.js +19 -6
  226. package/dest/services/tx_provider_instrumentation.d.ts +5 -2
  227. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  228. package/dest/services/tx_provider_instrumentation.js +14 -1
  229. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  230. package/dest/test-helpers/get-ports.d.ts +1 -1
  231. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  232. package/dest/test-helpers/index.d.ts +1 -1
  233. package/dest/test-helpers/make-enrs.d.ts +1 -1
  234. package/dest/test-helpers/make-enrs.js +1 -1
  235. package/dest/test-helpers/make-test-p2p-clients.d.ts +2 -2
  236. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  237. package/dest/test-helpers/mock-pubsub.d.ts +4 -4
  238. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  239. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  240. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  241. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  242. package/dest/test-helpers/reqresp-nodes.d.ts +3 -3
  243. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  244. package/dest/test-helpers/reqresp-nodes.js +4 -3
  245. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  246. package/dest/testbench/p2p_client_testbench_worker.js +17 -9
  247. package/dest/testbench/parse_log_file.d.ts +1 -1
  248. package/dest/testbench/testbench.d.ts +1 -1
  249. package/dest/testbench/testbench.js +2 -2
  250. package/dest/testbench/worker_client_manager.d.ts +1 -1
  251. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  252. package/dest/types/index.d.ts +1 -1
  253. package/dest/util.d.ts +2 -1
  254. package/dest/util.d.ts.map +1 -1
  255. package/dest/util.js +11 -2
  256. package/dest/versioning.d.ts +2 -2
  257. package/dest/versioning.d.ts.map +1 -1
  258. package/dest/versioning.js +2 -2
  259. package/package.json +21 -21
  260. package/src/bootstrap/bootstrap.ts +15 -4
  261. package/src/client/factory.ts +21 -12
  262. package/src/client/interface.ts +8 -5
  263. package/src/client/p2p_client.ts +106 -106
  264. package/src/config.ts +42 -21
  265. package/src/enr/generate-enr.ts +1 -1
  266. package/src/errors/attestation-pool.error.ts +13 -0
  267. package/src/mem_pools/attestation_pool/attestation_pool.ts +46 -5
  268. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +89 -48
  269. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +107 -24
  270. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +98 -19
  271. package/src/mem_pools/attestation_pool/mocks.ts +11 -8
  272. package/src/mem_pools/instrumentation.ts +46 -0
  273. package/src/mem_pools/interface.ts +2 -4
  274. package/src/mem_pools/tx_pool/README.md +255 -0
  275. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +368 -360
  276. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +71 -0
  277. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +93 -0
  278. package/src/mem_pools/tx_pool/eviction/insufficient_fee_payer_balance_rule.ts +108 -0
  279. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  280. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +91 -0
  281. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  282. package/src/mem_pools/tx_pool/index.ts +0 -1
  283. package/src/mem_pools/tx_pool/priority.ts +8 -1
  284. package/src/mem_pools/tx_pool/tx_pool.ts +28 -8
  285. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +131 -18
  286. package/src/msg_validators/attestation_validator/attestation_validator.ts +41 -6
  287. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +91 -0
  288. package/src/msg_validators/attestation_validator/index.ts +1 -0
  289. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +53 -12
  290. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  291. package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
  292. package/src/msg_validators/tx_validator/double_spend_validator.ts +1 -1
  293. package/src/msg_validators/tx_validator/factory.ts +13 -6
  294. package/src/msg_validators/tx_validator/index.ts +1 -0
  295. package/src/msg_validators/tx_validator/metadata_validator.ts +8 -42
  296. package/src/msg_validators/tx_validator/phases_validator.ts +3 -1
  297. package/src/msg_validators/tx_validator/test_utils.ts +1 -1
  298. package/src/msg_validators/tx_validator/timestamp_validator.ts +47 -0
  299. package/src/services/discv5/discV5_service.ts +2 -2
  300. package/src/services/dummy_service.ts +1 -1
  301. package/src/services/encoding.ts +81 -6
  302. package/src/services/libp2p/instrumentation.ts +10 -1
  303. package/src/services/libp2p/libp2p_service.ts +494 -169
  304. package/src/services/peer-manager/metrics.ts +32 -0
  305. package/src/services/peer-manager/peer_manager.ts +25 -16
  306. package/src/services/peer-manager/peer_scoring.ts +46 -3
  307. package/src/services/reqresp/interface.ts +1 -22
  308. package/src/services/reqresp/protocols/auth.ts +2 -2
  309. package/src/services/reqresp/protocols/block.ts +3 -2
  310. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +1 -1
  311. package/src/services/reqresp/protocols/status.ts +9 -8
  312. package/src/services/reqresp/protocols/tx.ts +1 -2
  313. package/src/services/reqresp/reqresp.ts +15 -11
  314. package/src/services/service.ts +1 -1
  315. package/src/services/tx_collection/config.ts +1 -1
  316. package/src/services/tx_collection/fast_tx_collection.ts +8 -5
  317. package/src/services/tx_collection/slow_tx_collection.ts +7 -6
  318. package/src/services/tx_collection/tx_collection.ts +12 -10
  319. package/src/services/tx_collection/tx_collection_sink.ts +34 -3
  320. package/src/services/tx_collection/tx_source.ts +2 -2
  321. package/src/services/tx_provider.ts +26 -9
  322. package/src/services/tx_provider_instrumentation.ts +19 -2
  323. package/src/test-helpers/make-enrs.ts +1 -1
  324. package/src/test-helpers/mock-pubsub.ts +1 -1
  325. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  326. package/src/test-helpers/reqresp-nodes.ts +4 -3
  327. package/src/testbench/p2p_client_testbench_worker.ts +14 -6
  328. package/src/testbench/testbench.ts +2 -2
  329. package/src/util.ts +12 -2
  330. package/src/versioning.ts +3 -3
  331. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -68
  332. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  333. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -160
  334. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -199
@@ -1,3 +1,4 @@
1
+ import type { SlotNumber } from '@aztec/foundation/branded-types';
1
2
  import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
2
3
 
3
4
  /**
@@ -21,6 +22,15 @@ export interface AttestationPool {
21
22
  */
22
23
  getBlockProposal(id: string): Promise<BlockProposal | undefined>;
23
24
 
25
+ /**
26
+ * Check if a block proposal exists in the pool
27
+ *
28
+ * @param idOrProposal - The ID of the block proposal or the block proposal itself to check. The ID is proposal.payload.archive
29
+ *
30
+ * @return True if the block proposal exists, false otherwise.
31
+ */
32
+ hasBlockProposal(idOrProposal: string | BlockProposal): Promise<boolean>;
33
+
24
34
  /**
25
35
  * AddAttestations
26
36
  *
@@ -42,7 +52,7 @@ export interface AttestationPool {
42
52
  *
43
53
  * @param slot - The oldest slot to keep.
44
54
  */
45
- deleteAttestationsOlderThan(slot: bigint): Promise<void>;
55
+ deleteAttestationsOlderThan(slot: SlotNumber): Promise<void>;
46
56
 
47
57
  /**
48
58
  * Delete Attestations for slot
@@ -51,7 +61,7 @@ export interface AttestationPool {
51
61
  *
52
62
  * @param slot - The slot to delete.
53
63
  */
54
- deleteAttestationsForSlot(slot: bigint): Promise<void>;
64
+ deleteAttestationsForSlot(slot: SlotNumber): Promise<void>;
55
65
 
56
66
  /**
57
67
  * Delete Attestations for slot and proposal
@@ -61,7 +71,7 @@ export interface AttestationPool {
61
71
  * @param slot - The slot to delete.
62
72
  * @param proposalId - The proposal to delete.
63
73
  */
64
- deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void>;
74
+ deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void>;
65
75
 
66
76
  /**
67
77
  * Get all Attestations for all proposals for a given slot
@@ -71,7 +81,7 @@ export interface AttestationPool {
71
81
  * @param slot - The slot to query
72
82
  * @return BlockAttestations
73
83
  */
74
- getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]>;
84
+ getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]>;
75
85
 
76
86
  /**
77
87
  * Get Attestations for slot and given proposal
@@ -82,7 +92,38 @@ export interface AttestationPool {
82
92
  * @param proposalId - The proposal to query
83
93
  * @return BlockAttestations
84
94
  */
85
- getAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<BlockAttestation[]>;
95
+ getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]>;
96
+
97
+ /**
98
+ * Check if a specific attestation exists in the pool
99
+ *
100
+ * @param attestation - The attestation to check
101
+ * @return True if the attestation exists, false otherwise
102
+ */
103
+ hasAttestation(attestation: BlockAttestation): Promise<boolean>;
104
+
105
+ /**
106
+ * Returns whether adding this proposal is permitted at current capacity:
107
+ * - True if the proposal already exists, allow overwrite to keep parity with tests.
108
+ * - True if the slot is below the proposal cap.
109
+ * - False if the slot is at/above cap and this would be a new unique proposal.
110
+ *
111
+ * @param block - The block proposal to check
112
+ * @returns True if the proposal can be added (or already exists), false otherwise.
113
+ */
114
+ canAddProposal(block: BlockProposal): Promise<boolean>;
115
+
116
+ /**
117
+ * Returns whether an attestation would be accepted for (slot, proposalId):
118
+ * - True if the attestation already exists for this sender.
119
+ * - True if the attestation cap for (slot, proposalId) has not been reached.
120
+ * - False if the cap is reached and this attestation would be a new unique entry.
121
+ *
122
+ * @param attestation - The attestation to check
123
+ * @param committeeSize - Committee size for the attestation's slot, implementation may add a small buffer
124
+ * @returns True if the attestation can be added, false otherwise.
125
+ */
126
+ canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean>;
86
127
 
87
128
  /** Returns whether the pool is empty. */
88
129
  isEmpty(): Promise<boolean>;
@@ -1,5 +1,6 @@
1
- import { Secp256k1Signer } from '@aztec/foundation/crypto';
2
- import { Fr } from '@aztec/foundation/fields';
1
+ import { SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { Secp256k1Signer } from '@aztec/foundation/crypto/secp256k1-signer';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
4
5
  import {
5
6
  BlockProposal as BlockProposalClass,
@@ -7,7 +8,7 @@ import {
7
8
  SignatureDomainSeparator,
8
9
  getHashedSignaturePayloadEthSignedMessage,
9
10
  } from '@aztec/stdlib/p2p';
10
- import { makeHeader } from '@aztec/stdlib/testing';
11
+ import { makeL2BlockHeader } from '@aztec/stdlib/testing';
11
12
  import { TxHash } from '@aztec/stdlib/tx';
12
13
 
13
14
  import { jest } from '@jest/globals';
@@ -41,16 +42,15 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
41
42
  };
42
43
 
43
44
  const mockBlockProposal = (signer: Secp256k1Signer, slotNumber: number, archive: Fr = Fr.random()): BlockProposal => {
44
- const blockNumber = 1;
45
- const header = makeHeader(1, 2, slotNumber);
46
- const payload = new ConsensusPayload(header.toPropose(), archive, header.state);
45
+ const header = makeL2BlockHeader(1, 2, slotNumber);
46
+ const payload = new ConsensusPayload(header.toCheckpointHeader(), archive);
47
47
 
48
48
  const hash = getHashedSignaturePayloadEthSignedMessage(payload, SignatureDomainSeparator.blockProposal);
49
49
  const signature = signer.sign(hash);
50
50
 
51
51
  const txHashes = [TxHash.random(), TxHash.random()]; // Mock tx hashes
52
52
 
53
- return new BlockProposalClass(blockNumber, payload, signature, txHashes);
53
+ return new BlockProposalClass(payload, signature, txHashes);
54
54
  };
55
55
 
56
56
  // We compare buffers as the objects can have cached values attached to them which are not serialised
@@ -69,11 +69,19 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
69
69
 
70
70
  await ap.addAttestations(attestations);
71
71
 
72
- const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString());
72
+ const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(
73
+ SlotNumber(slotNumber),
74
+ archive.toString(),
75
+ );
73
76
  expect(retrievedAttestations.length).toBe(attestations.length);
74
77
  compareAttestations(retrievedAttestations, attestations);
75
78
 
76
- const retrievedAttestationsForSlot = await ap.getAttestationsForSlot(BigInt(slotNumber));
79
+ // Check hasAttestation for added attestations
80
+ for (const attestation of attestations) {
81
+ expect(await ap.hasAttestation(attestation)).toBe(true);
82
+ }
83
+
84
+ const retrievedAttestationsForSlot = await ap.getAttestationsForSlot(SlotNumber(slotNumber));
77
85
  expect(retrievedAttestationsForSlot.length).toBe(attestations.length);
78
86
  compareAttestations(retrievedAttestationsForSlot, attestations);
79
87
 
@@ -81,23 +89,29 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
81
89
  const newAttestation = mockAttestation(signers[NUMBER_OF_SIGNERS_PER_TEST - 1], slotNumber, archive);
82
90
  await ap.addAttestations([newAttestation]);
83
91
  const retrievedAttestationsAfterAdd = await ap.getAttestationsForSlotAndProposal(
84
- BigInt(slotNumber),
92
+ SlotNumber(slotNumber),
85
93
  archive.toString(),
86
94
  );
87
95
  expect(retrievedAttestationsAfterAdd.length).toBe(attestations.length + 1);
88
96
  compareAttestations(retrievedAttestationsAfterAdd, [...attestations, newAttestation]);
89
- const retrievedAttestationsForSlotAfterAdd = await ap.getAttestationsForSlot(BigInt(slotNumber));
97
+ expect(await ap.hasAttestation(newAttestation)).toBe(true);
98
+ const retrievedAttestationsForSlotAfterAdd = await ap.getAttestationsForSlot(SlotNumber(slotNumber));
90
99
  expect(retrievedAttestationsForSlotAfterAdd.length).toBe(attestations.length + 1);
91
100
  compareAttestations(retrievedAttestationsForSlotAfterAdd, [...attestations, newAttestation]);
92
101
 
93
102
  // Delete by slot
94
- await ap.deleteAttestationsForSlot(BigInt(slotNumber));
103
+ await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
95
104
 
96
105
  const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
97
- BigInt(slotNumber),
106
+ SlotNumber(slotNumber),
98
107
  archive.toString(),
99
108
  );
100
109
  expect(retreivedAttestationsAfterDelete.length).toBe(0);
110
+ // Check hasAttestation after deletion
111
+ for (const attestation of attestations) {
112
+ expect(await ap.hasAttestation(attestation)).toBe(false);
113
+ }
114
+ expect(await ap.hasAttestation(newAttestation)).toBe(false);
101
115
  });
102
116
 
103
117
  it('should handle duplicate proposals in a slot', async () => {
@@ -114,14 +128,17 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
114
128
  // Add them to store and check we end up with only one
115
129
  await ap.addAttestations(attestations);
116
130
 
117
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString());
131
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(
132
+ SlotNumber(slotNumber),
133
+ archive.toString(),
134
+ );
118
135
  expect(retreivedAttestations.length).toBe(1);
119
136
  expect(retreivedAttestations[0].toBuffer()).toEqual(attestations[0].toBuffer());
120
- expect(retreivedAttestations[0].getSender().toString()).toEqual(signer.address.toString());
137
+ expect(retreivedAttestations[0].getSender()?.toString()).toEqual(signer.address.toString());
121
138
 
122
139
  // Try adding them on another operation and check they are still not duplicated
123
140
  await ap.addAttestations([attestations[0]]);
124
- expect(await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), archive.toString())).toHaveLength(1);
141
+ expect(await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), archive.toString())).toHaveLength(1);
125
142
  });
126
143
 
127
144
  it('should store attestations by differing slot', async () => {
@@ -134,7 +151,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
134
151
  const slot = attestation.payload.header.slotNumber;
135
152
  const archive = attestation.archive.toString();
136
153
 
137
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot.toBigInt(), archive);
154
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot, archive);
138
155
  expect(retreivedAttestations.length).toBe(1);
139
156
  expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
140
157
  expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
@@ -152,7 +169,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
152
169
  const slot = attestation.payload.header.slotNumber;
153
170
  const proposalId = attestation.archive.toString();
154
171
 
155
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot.toBigInt(), proposalId);
172
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(slot, proposalId);
156
173
  expect(retreivedAttestations.length).toBe(1);
157
174
  expect(retreivedAttestations[0].toBuffer()).toEqual(attestation.toBuffer());
158
175
  expect(retreivedAttestations[0].payload.header.slotNumber).toEqual(slot);
@@ -167,14 +184,24 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
167
184
 
168
185
  await ap.addAttestations(attestations);
169
186
 
170
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
187
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
171
188
  expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
172
189
  compareAttestations(retreivedAttestations, attestations);
173
190
 
191
+ // Check hasAttestation before deletion
192
+ for (const attestation of attestations) {
193
+ expect(await ap.hasAttestation(attestation)).toBe(true);
194
+ }
195
+
174
196
  await ap.deleteAttestations(attestations);
175
197
 
176
- const gottenAfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
198
+ const gottenAfterDelete = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
177
199
  expect(gottenAfterDelete.length).toBe(0);
200
+
201
+ // Check hasAttestation after deletion
202
+ for (const attestation of attestations) {
203
+ expect(await ap.hasAttestation(attestation)).toBe(false);
204
+ }
178
205
  });
179
206
 
180
207
  it('should blanket delete attestations per slot', async () => {
@@ -185,13 +212,16 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
185
212
 
186
213
  await ap.addAttestations(attestations);
187
214
 
188
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
215
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
189
216
  expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
190
217
  compareAttestations(retreivedAttestations, attestations);
191
218
 
192
- await ap.deleteAttestationsForSlot(BigInt(slotNumber));
219
+ await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
193
220
 
194
- const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
221
+ const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
222
+ SlotNumber(slotNumber),
223
+ proposalId,
224
+ );
195
225
  expect(retreivedAttestationsAfterDelete.length).toBe(0);
196
226
  });
197
227
 
@@ -209,17 +239,20 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
209
239
  await ap.addAttestations(attestations);
210
240
  await ap.addAttestations(attestations2);
211
241
 
212
- const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
242
+ const retreivedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
213
243
  expect(retreivedAttestations.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
214
244
  compareAttestations(retreivedAttestations, attestations);
215
245
 
216
- await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
246
+ await ap.deleteAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
217
247
 
218
- const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
248
+ const retreivedAttestationsAfterDelete = await ap.getAttestationsForSlotAndProposal(
249
+ SlotNumber(slotNumber),
250
+ proposalId,
251
+ );
219
252
  expect(retreivedAttestationsAfterDelete.length).toBe(0);
220
253
 
221
254
  const retreivedAttestationsAfterDeleteForOtherProposal = await ap.getAttestationsForSlotAndProposal(
222
- BigInt(slotNumber),
255
+ SlotNumber(slotNumber),
223
256
  proposalId2,
224
257
  );
225
258
  expect(retreivedAttestationsAfterDeleteForOtherProposal.length).toBe(NUMBER_OF_SIGNERS_PER_TEST);
@@ -235,22 +268,22 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
235
268
 
236
269
  await ap.addAttestations(attestations);
237
270
 
238
- const attestationsForSlot1 = await ap.getAttestationsForSlotAndProposal(BigInt(1), proposalId);
271
+ const attestationsForSlot1 = await ap.getAttestationsForSlotAndProposal(SlotNumber(1), proposalId);
239
272
  expect(attestationsForSlot1.length).toBe(signers.length);
240
273
 
241
274
  const deleteAttestationsSpy = jest.spyOn(ap, 'deleteAttestationsForSlot');
242
275
 
243
- await ap.deleteAttestationsOlderThan(BigInt(73));
276
+ await ap.deleteAttestationsOlderThan(SlotNumber(73));
244
277
 
245
- const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlotAndProposal(BigInt(1), proposalId);
278
+ const attestationsForSlot1AfterDelete = await ap.getAttestationsForSlotAndProposal(SlotNumber(1), proposalId);
246
279
  expect(attestationsForSlot1AfterDelete.length).toBe(0);
247
280
 
248
281
  expect(deleteAttestationsSpy).toHaveBeenCalledTimes(5);
249
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(1));
250
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(2));
251
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(3));
252
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(69));
253
- expect(deleteAttestationsSpy).toHaveBeenCalledWith(BigInt(72));
282
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(1));
283
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(2));
284
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(3));
285
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(69));
286
+ expect(deleteAttestationsSpy).toHaveBeenCalledWith(SlotNumber(72));
254
287
  });
255
288
 
256
289
  describe('BlockProposal in attestation pool', () => {
@@ -264,18 +297,21 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
264
297
 
265
298
  const retrievedProposal = await ap.getBlockProposal(proposalId);
266
299
 
267
- // This are cached values, so we need to call them to ensure they are not undefined
268
- retrievedProposal!.payload.getSize();
269
- retrievedProposal!.signature.getSize();
270
-
271
300
  expect(retrievedProposal).toBeDefined();
272
301
  expect(retrievedProposal!).toEqual(proposal);
302
+
303
+ // Check hasBlockProposal with both id and object
304
+ expect(await ap.hasBlockProposal(proposalId)).toBe(true);
305
+ expect(await ap.hasBlockProposal(proposal)).toBe(true);
273
306
  });
274
307
 
275
308
  it('should return undefined for non-existent block proposal', async () => {
276
309
  const nonExistentId = Fr.random().toString();
277
310
  const retrievedProposal = await ap.getBlockProposal(nonExistentId);
278
311
  expect(retrievedProposal).toBeUndefined();
312
+
313
+ // Check hasBlockProposal returns false for non-existent proposal
314
+ expect(await ap.hasBlockProposal(nonExistentId)).toBe(false);
279
315
  });
280
316
 
281
317
  it('should update block proposal if added twice with same id', async () => {
@@ -295,7 +331,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
295
331
  expect(retrievedProposal).toBeDefined();
296
332
  // Should have the second proposal
297
333
  expect(retrievedProposal!.toBuffer()).toEqual(proposal2.toBuffer());
298
- expect(retrievedProposal!.getSender().toString()).toBe(signers[1].address.toString());
334
+ expect(retrievedProposal!.getSender()?.toString()).toBe(signers[1].address.toString());
299
335
  });
300
336
 
301
337
  it('should handle block proposals with different slots and same archive', async () => {
@@ -311,7 +347,7 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
311
347
  const retrievedProposal = await ap.getBlockProposal(proposalId);
312
348
  expect(retrievedProposal).toBeDefined();
313
349
  expect(retrievedProposal!.toBuffer()).toEqual(proposal2.toBuffer());
314
- expect(retrievedProposal!.slotNumber.toBigInt()).toBe(BigInt(200));
350
+ expect(retrievedProposal!.slotNumber).toBe(SlotNumber(200));
315
351
  });
316
352
 
317
353
  it('should delete block proposal when deleting attestations for slot and proposal', async () => {
@@ -328,13 +364,15 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
328
364
  // Verify proposal exists
329
365
  let retrievedProposal = await ap.getBlockProposal(proposalId);
330
366
  expect(retrievedProposal).toBeDefined();
367
+ expect(await ap.hasBlockProposal(proposalId)).toBe(true);
331
368
 
332
369
  // Delete attestations for slot and proposal
333
- await ap.deleteAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
370
+ await ap.deleteAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
334
371
 
335
372
  // Proposal should be deleted
336
373
  retrievedProposal = await ap.getBlockProposal(proposalId);
337
374
  expect(retrievedProposal).toBeUndefined();
375
+ expect(await ap.hasBlockProposal(proposalId)).toBe(false);
338
376
  });
339
377
 
340
378
  it('should delete block proposal when deleting attestations for slot', async () => {
@@ -349,13 +387,15 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
349
387
  // Verify proposal exists
350
388
  let retrievedProposal = await ap.getBlockProposal(proposalId);
351
389
  expect(retrievedProposal).toBeDefined();
390
+ expect(await ap.hasBlockProposal(proposal)).toBe(true);
352
391
 
353
392
  // Delete attestations for slot
354
- await ap.deleteAttestationsForSlot(BigInt(slotNumber));
393
+ await ap.deleteAttestationsForSlot(SlotNumber(slotNumber));
355
394
 
356
395
  // Proposal should be deleted
357
396
  retrievedProposal = await ap.getBlockProposal(proposalId);
358
397
  expect(retrievedProposal).toBeUndefined();
398
+ expect(await ap.hasBlockProposal(proposal)).toBe(false);
359
399
  });
360
400
 
361
401
  it('should be able to fetch both block proposal and attestations', async () => {
@@ -373,16 +413,17 @@ export function describeAttestationPool(getAttestationPool: () => AttestationPoo
373
413
 
374
414
  // Retrieve both proposal and attestations
375
415
  const retrievedProposal = await ap.getBlockProposal(proposalId);
376
- const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(BigInt(slotNumber), proposalId);
416
+ const retrievedAttestations = await ap.getAttestationsForSlotAndProposal(SlotNumber(slotNumber), proposalId);
377
417
 
378
418
  expect(retrievedProposal).toBeDefined();
379
- // This are cached values, so we need to call them to ensure they are not undefined
380
- retrievedProposal!.payload.getSize();
381
- retrievedProposal!.signature.getSize();
382
-
383
419
  expect(retrievedProposal).toEqual(proposal);
420
+ expect(await ap.hasBlockProposal(proposalId)).toBe(true);
384
421
 
385
422
  compareAttestations(retrievedAttestations, attestations);
423
+ // Check hasAttestation for all attestations
424
+ for (const attestation of attestations) {
425
+ expect(await ap.hasAttestation(attestation)).toBe(true);
426
+ }
386
427
  });
387
428
  });
388
429
  }
@@ -1,13 +1,18 @@
1
- import { Fr } from '@aztec/foundation/fields';
1
+ import { SlotNumber } from '@aztec/foundation/branded-types';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import { toArray } from '@aztec/foundation/iterable';
3
4
  import { createLogger } from '@aztec/foundation/log';
4
5
  import type { AztecAsyncKVStore, AztecAsyncMap, AztecAsyncMultiMap } from '@aztec/kv-store';
5
6
  import { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
6
7
  import { type TelemetryClient, getTelemetryClient } from '@aztec/telemetry-client';
7
8
 
9
+ import { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
8
10
  import { PoolInstrumentation, PoolName, type PoolStatsCallback } from '../instrumentation.js';
9
11
  import type { AttestationPool } from './attestation_pool.js';
10
12
 
13
+ export const MAX_PROPOSALS_PER_SLOT = 5;
14
+ export const ATTESTATION_CAP_BUFFER = 10;
15
+
11
16
  export class KvAttestationPool implements AttestationPool {
12
17
  private metrics: PoolInstrumentation<BlockAttestation>;
13
18
 
@@ -16,7 +21,7 @@ export class KvAttestationPool implements AttestationPool {
16
21
  /* proposal.payload.archive */ string,
17
22
  /* buffer representation of proposal */ Buffer
18
23
  >;
19
- private proposalsForSlot: AztecAsyncMultiMap<string, string>;
24
+ private proposalsForSlot: AztecAsyncMultiMap<number, string>;
20
25
  private attestationsForProposal: AztecAsyncMultiMap<string, string>;
21
26
 
22
27
  constructor(
@@ -66,17 +71,29 @@ export class KvAttestationPool implements AttestationPool {
66
71
  for (const attestation of attestations) {
67
72
  const slotNumber = attestation.payload.header.slotNumber;
68
73
  const proposalId = attestation.archive;
69
- const address = attestation.getSender().toString();
74
+ const sender = attestation.getSender();
75
+
76
+ // Skip attestations with invalid signatures
77
+ if (!sender) {
78
+ this.log.warn(`Skipping attestation with invalid signature for slot ${slotNumber}`, {
79
+ signature: attestation.signature.toString(),
80
+ slotNumber,
81
+ proposalId,
82
+ });
83
+ continue;
84
+ }
85
+
86
+ const address = sender.toString();
70
87
 
71
88
  await this.attestations.set(this.getAttestationKey(slotNumber, proposalId, address), attestation.toBuffer());
72
89
 
73
- await this.proposalsForSlot.set(slotNumber.toString(), proposalId.toString());
90
+ await this.proposalsForSlot.set(slotNumber, proposalId.toString());
74
91
  await this.attestationsForProposal.set(
75
92
  this.getProposalKey(slotNumber, proposalId),
76
93
  this.getAttestationKey(slotNumber, proposalId, address),
77
94
  );
78
95
 
79
- this.log.verbose(`Added attestation for slot ${slotNumber.toBigInt()} from ${address}`, {
96
+ this.log.verbose(`Added attestation for slot ${slotNumber} from ${address}`, {
80
97
  signature: attestation.signature.toString(),
81
98
  slotNumber,
82
99
  address,
@@ -86,9 +103,8 @@ export class KvAttestationPool implements AttestationPool {
86
103
  });
87
104
  }
88
105
 
89
- public async getAttestationsForSlot(slot: bigint): Promise<BlockAttestation[]> {
90
- const slotFr = new Fr(slot);
91
- const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slotFr.toString()));
106
+ public async getAttestationsForSlot(slot: SlotNumber): Promise<BlockAttestation[]> {
107
+ const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
92
108
  const attestations: BlockAttestation[] = [];
93
109
 
94
110
  for (const proposalId of proposalIds) {
@@ -98,7 +114,7 @@ export class KvAttestationPool implements AttestationPool {
98
114
  return attestations;
99
115
  }
100
116
 
101
- public async getAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<BlockAttestation[]> {
117
+ public async getAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<BlockAttestation[]> {
102
118
  const attestationIds = await toArray(
103
119
  this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
104
120
  );
@@ -120,21 +136,20 @@ export class KvAttestationPool implements AttestationPool {
120
136
  return attestations;
121
137
  }
122
138
 
123
- public async deleteAttestationsOlderThan(oldestSlot: bigint): Promise<void> {
124
- const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: new Fr(oldestSlot).toString() }));
139
+ public async deleteAttestationsOlderThan(oldestSlot: SlotNumber): Promise<void> {
140
+ const olderThan = await toArray(this.proposalsForSlot.keysAsync({ end: oldestSlot }));
125
141
  for (const oldSlot of olderThan) {
126
- await this.deleteAttestationsForSlot(BigInt(oldSlot));
142
+ await this.deleteAttestationsForSlot(SlotNumber(oldSlot));
127
143
  }
128
144
  }
129
145
 
130
- public async deleteAttestationsForSlot(slot: bigint): Promise<void> {
131
- const slotFr = new Fr(slot);
146
+ public async deleteAttestationsForSlot(slot: SlotNumber): Promise<void> {
132
147
  let numberOfAttestations = 0;
133
148
  await this.store.transactionAsync(async () => {
134
- const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slotFr.toString()));
149
+ const proposalIds = await toArray(this.proposalsForSlot.getValuesAsync(slot));
135
150
  for (const proposalId of proposalIds) {
136
151
  const attestations = await toArray(
137
- this.attestationsForProposal.getValuesAsync(this.getProposalKey(slotFr, proposalId)),
152
+ this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
138
153
  );
139
154
 
140
155
  numberOfAttestations += attestations.length;
@@ -143,17 +158,19 @@ export class KvAttestationPool implements AttestationPool {
143
158
  }
144
159
 
145
160
  await this.proposals.delete(proposalId);
146
- await this.attestationsForProposal.delete(this.getProposalKey(slotFr, proposalId));
161
+ await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
147
162
  }
148
163
 
164
+ // Delete from proposalsForSlot
165
+ await this.proposalsForSlot.delete(slot);
166
+
149
167
  this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot}`);
150
168
  });
151
169
  }
152
170
 
153
- public async deleteAttestationsForSlotAndProposal(slot: bigint, proposalId: string): Promise<void> {
171
+ public async deleteAttestationsForSlotAndProposal(slot: SlotNumber, proposalId: string): Promise<void> {
154
172
  let numberOfAttestations = 0;
155
173
  await this.store.transactionAsync(async () => {
156
- const slotString = new Fr(slot).toString();
157
174
  const attestations = await toArray(
158
175
  this.attestationsForProposal.getValuesAsync(this.getProposalKey(slot, proposalId)),
159
176
  );
@@ -164,8 +181,8 @@ export class KvAttestationPool implements AttestationPool {
164
181
  }
165
182
 
166
183
  await this.proposals.delete(proposalId);
167
- await this.proposalsForSlot.deleteValue(slotString, proposalId);
168
- await this.attestationsForProposal.delete(this.getProposalKey(slotString, proposalId));
184
+ await this.proposalsForSlot.deleteValue(slot, proposalId);
185
+ await this.attestationsForProposal.delete(this.getProposalKey(slot, proposalId));
169
186
 
170
187
  this.log.verbose(`Removed ${numberOfAttestations} attestations for slot ${slot} and proposal ${proposalId}`);
171
188
  });
@@ -176,7 +193,15 @@ export class KvAttestationPool implements AttestationPool {
176
193
  for (const attestation of attestations) {
177
194
  const slotNumber = attestation.payload.header.slotNumber;
178
195
  const proposalId = attestation.archive;
179
- const address = attestation.getSender().toString();
196
+ const sender = attestation.getSender();
197
+
198
+ // Skip attestations with invalid signatures
199
+ if (!sender) {
200
+ this.log.warn(`Skipping deletion of attestation with invalid signature for slot ${slotNumber}`);
201
+ continue;
202
+ }
203
+
204
+ const address = sender.toString();
180
205
  const key = this.getAttestationKey(slotNumber, proposalId, address);
181
206
 
182
207
  if (await this.attestations.hasAsync(key)) {
@@ -193,6 +218,22 @@ export class KvAttestationPool implements AttestationPool {
193
218
  });
194
219
  }
195
220
 
221
+ public async hasAttestation(attestation: BlockAttestation): Promise<boolean> {
222
+ const slotNumber = attestation.payload.header.slotNumber;
223
+ const proposalId = attestation.archive;
224
+ const sender = attestation.getSender();
225
+
226
+ // Attestations with invalid signatures are never in the pool
227
+ if (!sender) {
228
+ return false;
229
+ }
230
+
231
+ const address = sender.toString();
232
+ const key = this.getAttestationKey(slotNumber, proposalId, address);
233
+
234
+ return await this.attestations.hasAsync(key);
235
+ }
236
+
196
237
  public async getBlockProposal(id: string): Promise<BlockProposal | undefined> {
197
238
  const buffer = await this.proposals.getAsync(id);
198
239
  try {
@@ -206,10 +247,52 @@ export class KvAttestationPool implements AttestationPool {
206
247
  return Promise.resolve(undefined);
207
248
  }
208
249
 
250
+ public async hasBlockProposal(idOrProposal: string | BlockProposal): Promise<boolean> {
251
+ const id = typeof idOrProposal === 'string' ? idOrProposal : idOrProposal.payload.archive.toString();
252
+ return await this.proposals.hasAsync(id);
253
+ }
254
+
209
255
  public async addBlockProposal(blockProposal: BlockProposal): Promise<void> {
210
256
  await this.store.transactionAsync(async () => {
211
- await this.proposalsForSlot.set(blockProposal.slotNumber.toString(), blockProposal.archive.toString());
212
- await this.proposals.set(blockProposal.payload.archive.toString(), blockProposal.toBuffer());
257
+ const slotKey = blockProposal.slotNumber;
258
+ const proposalId = blockProposal.archive.toString();
259
+
260
+ if (!(await this.canAddProposal(blockProposal))) {
261
+ throw new ProposalSlotCapExceededError(
262
+ `Maximum proposals per slot reached: slot=${slotKey} cap=${MAX_PROPOSALS_PER_SLOT} proposal=${proposalId}`,
263
+ );
264
+ }
265
+
266
+ await this.proposalsForSlot.set(slotKey, proposalId);
267
+ // Always update the stored proposal buffer so re-adds overwrite with latest data
268
+ await this.proposals.set(proposalId, blockProposal.toBuffer());
213
269
  });
214
270
  }
271
+
272
+ public async hasReachedProposalCap(slot: SlotNumber): Promise<boolean> {
273
+ const uniqueProposalCount = await this.proposalsForSlot.getValueCountAsync(slot);
274
+ return uniqueProposalCount >= MAX_PROPOSALS_PER_SLOT;
275
+ }
276
+
277
+ public async hasReachedAttestationCap(slot: SlotNumber, proposalId: string, committeeSize: number): Promise<boolean> {
278
+ const limit = committeeSize + ATTESTATION_CAP_BUFFER;
279
+ return (await this.attestationsForProposal.getValueCountAsync(this.getProposalKey(slot, proposalId))) >= limit;
280
+ }
281
+
282
+ public async canAddProposal(block: BlockProposal): Promise<boolean> {
283
+ return (
284
+ (await this.proposals.hasAsync(block.archive.toString())) || !(await this.hasReachedProposalCap(block.slotNumber))
285
+ );
286
+ }
287
+
288
+ public async canAddAttestation(attestation: BlockAttestation, committeeSize: number): Promise<boolean> {
289
+ return (
290
+ (await this.hasAttestation(attestation)) ||
291
+ !(await this.hasReachedAttestationCap(
292
+ attestation.payload.header.slotNumber,
293
+ attestation.archive.toString(),
294
+ committeeSize,
295
+ ))
296
+ );
297
+ }
215
298
  }