@aztec/p2p 0.0.1-commit.04852196a → 0.0.1-commit.04d373f

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 (406) hide show
  1. package/README.md +129 -3
  2. package/dest/bootstrap/bootstrap.d.ts +1 -1
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  4. package/dest/bootstrap/bootstrap.js +9 -1
  5. package/dest/client/factory.d.ts +4 -3
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +31 -14
  8. package/dest/client/interface.d.ts +14 -5
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +13 -9
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +94 -26
  13. package/dest/config.d.ts +139 -97
  14. package/dest/config.d.ts.map +1 -1
  15. package/dest/config.js +70 -5
  16. package/dest/errors/p2p-service.error.d.ts +9 -0
  17. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  18. package/dest/errors/p2p-service.error.js +10 -0
  19. package/dest/errors/reqresp.error.d.ts +1 -20
  20. package/dest/errors/reqresp.error.d.ts.map +1 -1
  21. package/dest/errors/reqresp.error.js +0 -21
  22. package/dest/index.d.ts +1 -2
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +0 -1
  25. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +99 -59
  26. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool.js +265 -199
  28. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  29. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +181 -65
  31. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -1
  32. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  33. package/dest/mem_pools/attestation_pool/mocks.js +6 -4
  34. package/dest/mem_pools/index.d.ts +1 -2
  35. package/dest/mem_pools/index.d.ts.map +1 -1
  36. package/dest/mem_pools/instrumentation.d.ts +1 -1
  37. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  38. package/dest/mem_pools/instrumentation.js +17 -1
  39. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +1 -1
  40. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  41. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +2 -1
  42. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +2 -1
  43. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -1
  44. package/dest/mem_pools/tx_pool_v2/eviction/index.js +1 -0
  45. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  46. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  47. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  48. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +2 -2
  49. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +10 -5
  50. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -1
  51. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +13 -3
  52. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +20 -7
  54. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +4 -2
  55. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -1
  56. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +3 -0
  57. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +1 -1
  58. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +92 -87
  60. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +9 -3
  61. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  62. package/dest/msg_validators/attestation_validator/attestation_validator.js +37 -12
  63. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +7 -3
  64. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  65. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +4 -5
  66. package/dest/msg_validators/clock_tolerance.d.ts +12 -1
  67. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -1
  68. package/dest/msg_validators/clock_tolerance.js +61 -3
  69. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +6 -2
  70. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -1
  71. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +6 -2
  72. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -1
  73. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +10 -2
  74. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  75. package/dest/msg_validators/proposal_validator/proposal_validator.js +46 -12
  76. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  77. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  78. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +8 -15
  79. package/dest/msg_validators/tx_validator/allowed_public_setup.js +3 -3
  80. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  81. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  82. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  83. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  84. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  85. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  86. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  87. package/dest/msg_validators/tx_validator/data_validator.d.ts +2 -1
  88. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  89. package/dest/msg_validators/tx_validator/data_validator.js +36 -2
  90. package/dest/msg_validators/tx_validator/factory.d.ts +27 -7
  91. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  92. package/dest/msg_validators/tx_validator/factory.js +47 -17
  93. package/dest/msg_validators/tx_validator/gas_validator.d.ts +48 -7
  94. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/gas_validator.js +88 -41
  96. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  97. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/index.js +2 -0
  99. package/dest/msg_validators/tx_validator/phases_validator.d.ts +21 -1
  100. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  101. package/dest/msg_validators/tx_validator/phases_validator.js +28 -1
  102. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +2 -1
  103. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  104. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -0
  105. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  106. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  107. package/dest/msg_validators/tx_validator/tx_validation_cache.js +69 -0
  108. package/dest/services/data_store.d.ts +1 -1
  109. package/dest/services/data_store.d.ts.map +1 -1
  110. package/dest/services/data_store.js +5 -5
  111. package/dest/services/discv5/discV5_service.d.ts +2 -1
  112. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  113. package/dest/services/discv5/discV5_service.js +35 -8
  114. package/dest/services/dummy_service.d.ts +11 -15
  115. package/dest/services/dummy_service.d.ts.map +1 -1
  116. package/dest/services/dummy_service.js +12 -16
  117. package/dest/services/encoding.d.ts +5 -1
  118. package/dest/services/encoding.d.ts.map +1 -1
  119. package/dest/services/encoding.js +7 -1
  120. package/dest/services/gossipsub/topic_score_params.d.ts +13 -2
  121. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -1
  122. package/dest/services/gossipsub/topic_score_params.js +21 -4
  123. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  124. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  125. package/dest/services/libp2p/instrumentation.js +14 -0
  126. package/dest/services/libp2p/libp2p_service.d.ts +36 -46
  127. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  128. package/dest/services/libp2p/libp2p_service.js +282 -236
  129. package/dest/services/peer-manager/peer_manager.d.ts +6 -2
  130. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  131. package/dest/services/peer-manager/peer_manager.js +38 -10
  132. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  133. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  134. package/dest/services/peer-manager/peer_scoring.js +32 -10
  135. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +11 -8
  136. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -1
  137. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +84 -71
  138. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +10 -6
  139. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -1
  140. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +5 -4
  141. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -1
  142. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +13 -7
  143. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +3 -1
  144. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -1
  145. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +3 -0
  146. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +5 -14
  147. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -1
  148. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +6 -20
  149. package/dest/services/reqresp/config.d.ts +3 -3
  150. package/dest/services/reqresp/config.d.ts.map +1 -1
  151. package/dest/services/reqresp/interface.d.ts +16 -18
  152. package/dest/services/reqresp/interface.d.ts.map +1 -1
  153. package/dest/services/reqresp/interface.js +10 -20
  154. package/dest/services/reqresp/metrics.d.ts +1 -1
  155. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  156. package/dest/services/reqresp/metrics.js +0 -1
  157. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  158. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  159. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +4 -2
  160. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  161. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  162. package/dest/services/reqresp/protocols/index.js +0 -1
  163. package/dest/services/reqresp/protocols/tx.d.ts +1 -1
  164. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  165. package/dest/services/reqresp/protocols/tx.js +1 -3
  166. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +5 -4
  167. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  168. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  169. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  170. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  171. package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
  172. package/dest/services/reqresp/reqresp.d.ts +7 -29
  173. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  174. package/dest/services/reqresp/reqresp.js +41 -214
  175. package/dest/services/service.d.ts +9 -12
  176. package/dest/services/service.d.ts.map +1 -1
  177. package/dest/services/tx_collection/config.d.ts +2 -23
  178. package/dest/services/tx_collection/config.d.ts.map +1 -1
  179. package/dest/services/tx_collection/config.js +2 -55
  180. package/dest/services/tx_collection/file_store_tx_collection.d.ts +12 -28
  181. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -1
  182. package/dest/services/tx_collection/file_store_tx_collection.js +43 -83
  183. package/dest/services/tx_collection/file_store_tx_source.d.ts +5 -4
  184. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -1
  185. package/dest/services/tx_collection/file_store_tx_source.js +39 -29
  186. package/dest/services/tx_collection/index.d.ts +2 -3
  187. package/dest/services/tx_collection/index.d.ts.map +1 -1
  188. package/dest/services/tx_collection/index.js +0 -1
  189. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  190. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  191. package/dest/services/tx_collection/instrumentation.js +0 -2
  192. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  193. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  194. package/dest/services/tx_collection/request_tracker.js +84 -0
  195. package/dest/services/tx_collection/tx_collection.d.ts +36 -55
  196. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  197. package/dest/services/tx_collection/tx_collection.js +275 -119
  198. package/dest/services/tx_collection/tx_collection_sink.d.ts +1 -1
  199. package/dest/services/tx_collection/tx_collection_sink.js +2 -2
  200. package/dest/services/tx_collection/tx_source.d.ts +6 -5
  201. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  202. package/dest/services/tx_collection/tx_source.js +9 -7
  203. package/dest/services/tx_file_store/tx_file_store.d.ts +1 -3
  204. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -1
  205. package/dest/services/tx_file_store/tx_file_store.js +4 -14
  206. package/dest/services/tx_provider.d.ts +3 -1
  207. package/dest/services/tx_provider.d.ts.map +1 -1
  208. package/dest/services/tx_provider.js +3 -0
  209. package/dest/test-helpers/make-test-p2p-clients.d.ts +1 -1
  210. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  211. package/dest/test-helpers/make-test-p2p-clients.js +5 -2
  212. package/dest/test-helpers/mock-pubsub.d.ts +23 -9
  213. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  214. package/dest/test-helpers/mock-pubsub.js +44 -44
  215. package/dest/test-helpers/reqresp-nodes.d.ts +4 -5
  216. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  217. package/dest/test-helpers/reqresp-nodes.js +16 -18
  218. package/dest/test-helpers/test_tx_provider.d.ts +3 -1
  219. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -1
  220. package/dest/test-helpers/test_tx_provider.js +3 -0
  221. package/dest/test-helpers/testbench-utils.d.ts +12 -14
  222. package/dest/test-helpers/testbench-utils.d.ts.map +1 -1
  223. package/dest/test-helpers/testbench-utils.js +42 -15
  224. package/dest/testbench/p2p_client_testbench_worker.d.ts +3 -5
  225. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  226. package/dest/testbench/p2p_client_testbench_worker.js +83 -38
  227. package/dest/testbench/worker_client_manager.d.ts +10 -6
  228. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  229. package/dest/testbench/worker_client_manager.js +51 -9
  230. package/dest/util.d.ts +11 -6
  231. package/dest/util.d.ts.map +1 -1
  232. package/dest/util.js +35 -14
  233. package/dest/versioning.d.ts +3 -6
  234. package/dest/versioning.d.ts.map +1 -1
  235. package/dest/versioning.js +3 -24
  236. package/package.json +15 -14
  237. package/src/bootstrap/bootstrap.ts +9 -1
  238. package/src/client/factory.ts +55 -7
  239. package/src/client/interface.ts +15 -11
  240. package/src/client/p2p_client.ts +107 -49
  241. package/src/client/test/{tx_proposal_collector/README.md → p2p_client.batch_tx_requester.bench.README.md} +23 -53
  242. package/src/config.ts +137 -4
  243. package/src/errors/p2p-service.error.ts +11 -0
  244. package/src/errors/reqresp.error.ts +0 -25
  245. package/src/index.ts +0 -1
  246. package/src/mem_pools/attestation_pool/attestation_pool.ts +316 -241
  247. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +204 -68
  248. package/src/mem_pools/attestation_pool/mocks.ts +13 -8
  249. package/src/mem_pools/index.ts +0 -3
  250. package/src/mem_pools/instrumentation.ts +5 -1
  251. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +2 -1
  252. package/src/mem_pools/tx_pool_v2/eviction/index.ts +1 -0
  253. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  254. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +3 -3
  255. package/src/mem_pools/tx_pool_v2/interfaces.ts +9 -4
  256. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +31 -9
  257. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +13 -1
  258. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +93 -93
  259. package/src/msg_validators/attestation_validator/README.md +49 -0
  260. package/src/msg_validators/attestation_validator/attestation_validator.ts +41 -9
  261. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +14 -7
  262. package/src/msg_validators/clock_tolerance.ts +79 -3
  263. package/src/msg_validators/proposal_validator/README.md +123 -0
  264. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +12 -2
  265. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +17 -2
  266. package/src/msg_validators/proposal_validator/proposal_validator.ts +54 -10
  267. package/src/msg_validators/tx_validator/README.md +15 -3
  268. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +3 -12
  269. package/src/msg_validators/tx_validator/allowed_public_setup.ts +3 -3
  270. package/src/msg_validators/tx_validator/archive_cache.ts +1 -1
  271. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  272. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  273. package/src/msg_validators/tx_validator/data_validator.ts +44 -1
  274. package/src/msg_validators/tx_validator/factory.ts +61 -10
  275. package/src/msg_validators/tx_validator/gas_validator.ts +121 -39
  276. package/src/msg_validators/tx_validator/index.ts +2 -0
  277. package/src/msg_validators/tx_validator/phases_validator.ts +31 -1
  278. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -0
  279. package/src/msg_validators/tx_validator/tx_validation_cache.ts +102 -0
  280. package/src/services/data_store.ts +5 -13
  281. package/src/services/discv5/discV5_service.ts +38 -5
  282. package/src/services/dummy_service.ts +14 -39
  283. package/src/services/encoding.ts +9 -1
  284. package/src/services/gossipsub/topic_score_params.ts +36 -4
  285. package/src/services/libp2p/instrumentation.ts +14 -0
  286. package/src/services/libp2p/libp2p_service.ts +308 -272
  287. package/src/services/peer-manager/peer_manager.ts +44 -10
  288. package/src/services/peer-manager/peer_scoring.ts +27 -5
  289. package/src/services/reqresp/README.md +215 -0
  290. package/src/services/reqresp/batch-tx-requester/README.md +46 -7
  291. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +83 -77
  292. package/src/services/reqresp/batch-tx-requester/interface.ts +13 -5
  293. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +13 -6
  294. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +5 -0
  295. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +12 -25
  296. package/src/services/reqresp/config.ts +2 -2
  297. package/src/services/reqresp/interface.ts +21 -47
  298. package/src/services/reqresp/metrics.ts +0 -1
  299. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +4 -2
  300. package/src/services/reqresp/protocols/index.ts +0 -1
  301. package/src/services/reqresp/protocols/tx.ts +1 -3
  302. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  303. package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
  304. package/src/services/reqresp/reqresp.ts +45 -260
  305. package/src/services/service.ts +12 -28
  306. package/src/services/tx_collection/config.ts +3 -80
  307. package/src/services/tx_collection/file_store_tx_collection.ts +54 -103
  308. package/src/services/tx_collection/file_store_tx_source.ts +43 -31
  309. package/src/services/tx_collection/index.ts +1 -6
  310. package/src/services/tx_collection/instrumentation.ts +1 -7
  311. package/src/services/tx_collection/request_tracker.ts +127 -0
  312. package/src/services/tx_collection/tx_collection.ts +331 -176
  313. package/src/services/tx_collection/tx_collection_sink.ts +2 -2
  314. package/src/services/tx_collection/tx_source.ts +8 -7
  315. package/src/services/tx_file_store/tx_file_store.ts +5 -17
  316. package/src/services/tx_provider.ts +5 -0
  317. package/src/test-helpers/make-test-p2p-clients.ts +3 -0
  318. package/src/test-helpers/mock-pubsub.ts +46 -60
  319. package/src/test-helpers/reqresp-nodes.ts +12 -22
  320. package/src/test-helpers/test_tx_provider.ts +5 -0
  321. package/src/test-helpers/testbench-utils.ts +53 -28
  322. package/src/testbench/p2p_client_testbench_worker.ts +87 -54
  323. package/src/testbench/worker_client_manager.ts +59 -20
  324. package/src/util.ts +32 -17
  325. package/src/versioning.ts +3 -33
  326. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +0 -2
  327. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +0 -1
  328. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +0 -304
  329. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +0 -73
  330. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +0 -1
  331. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +0 -8
  332. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -125
  333. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  334. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -596
  335. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +0 -32
  336. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +0 -1
  337. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +0 -112
  338. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +0 -157
  339. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +0 -1
  340. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +0 -52
  341. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +0 -16
  342. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +0 -1
  343. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +0 -122
  344. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +0 -17
  345. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +0 -1
  346. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +0 -84
  347. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +0 -19
  348. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +0 -1
  349. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +0 -78
  350. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +0 -26
  351. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +0 -1
  352. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +0 -84
  353. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +0 -25
  354. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +0 -1
  355. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +0 -57
  356. package/dest/mem_pools/tx_pool/index.d.ts +0 -3
  357. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  358. package/dest/mem_pools/tx_pool/index.js +0 -2
  359. package/dest/mem_pools/tx_pool/priority.d.ts +0 -12
  360. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  361. package/dest/mem_pools/tx_pool/priority.js +0 -15
  362. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -127
  363. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  364. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  365. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  366. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  367. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -400
  368. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -64
  369. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  370. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -151
  371. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  372. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  373. package/dest/services/reqresp/protocols/block.js +0 -32
  374. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -54
  375. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  376. package/dest/services/tx_collection/fast_tx_collection.js +0 -327
  377. package/dest/services/tx_collection/missing_txs_tracker.d.ts +0 -32
  378. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +0 -1
  379. package/dest/services/tx_collection/missing_txs_tracker.js +0 -27
  380. package/dest/services/tx_collection/proposal_tx_collector.d.ts +0 -49
  381. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +0 -1
  382. package/dest/services/tx_collection/proposal_tx_collector.js +0 -50
  383. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -57
  384. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  385. package/dest/services/tx_collection/slow_tx_collection.js +0 -211
  386. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +0 -345
  387. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +0 -43
  388. package/src/mem_pools/tx_pool/README.md +0 -270
  389. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -746
  390. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +0 -132
  391. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +0 -208
  392. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +0 -162
  393. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +0 -104
  394. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +0 -93
  395. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +0 -106
  396. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +0 -75
  397. package/src/mem_pools/tx_pool/index.ts +0 -2
  398. package/src/mem_pools/tx_pool/priority.ts +0 -20
  399. package/src/mem_pools/tx_pool/tx_pool.ts +0 -141
  400. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -319
  401. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -161
  402. package/src/services/reqresp/protocols/block.ts +0 -37
  403. package/src/services/tx_collection/fast_tx_collection.ts +0 -387
  404. package/src/services/tx_collection/missing_txs_tracker.ts +0 -52
  405. package/src/services/tx_collection/proposal_tx_collector.ts +0 -113
  406. package/src/services/tx_collection/slow_tx_collection.ts +0 -266
@@ -1,125 +1,156 @@
1
- import { Fr } from '@aztec/foundation/curves/bn254';
2
1
  import { toArray } from '@aztec/foundation/iterable';
3
2
  import { createLogger } from '@aztec/foundation/log';
4
3
  import { BlockProposal, CheckpointAttestation, CheckpointProposal } from '@aztec/stdlib/p2p';
5
4
  import { getTelemetryClient } from '@aztec/telemetry-client';
6
5
  import { PoolInstrumentation, PoolName } from '../instrumentation.js';
7
- export const MAX_CHECKPOINT_PROPOSALS_PER_SLOT = 5;
8
- export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
9
- /** Maximum attestations a single signer can make per slot before being rejected. */ export const MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER = 3;
6
+ export const MAX_CHECKPOINT_PROPOSALS_PER_SLOT = 2;
7
+ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 2;
8
+ /** Maximum attestations a single signer can make per slot before being rejected. */ export const MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER = 2;
10
9
  /**
11
10
  * Pool for storing attestations and proposals collected by a validator.
12
11
  *
13
12
  * Attestations and proposals observed via the p2p network are stored for requests
14
13
  * from the validator to produce a block, or to serve to other peers.
14
+ *
15
+ * Equivocation detection: distinct *signed payload hashes* arriving at the same
16
+ * position are tracked in the matching index multimap so the equivocation count
17
+ * reaches 2 even when archive collides on `feeAssetPriceModifier` variants.
18
+ * Proposal bytes are retained per accepted payload hash, up to the same equivocation
19
+ * caps, for slashing watchers that need signed P2P proposals.
15
20
  */ export class AttestationPool {
16
21
  store;
17
22
  log;
18
23
  metrics;
19
- // Checkpoint attestations from attestation key (slot-proposalId-signer) to serialized CheckpointAttestation
20
- // Keys are lexicographically sortable allowing range queries by slot or by (slot, proposalId)
21
- checkpointAttestations;
22
- // Checkpoint proposals from proposal archive to serialized CheckpointProposal
23
- checkpointProposals;
24
- // Checkpoint proposals indexed by slot for querying all proposals in a slot
25
- // Key: slot number, Value: proposal archive strings
26
- checkpointProposalsForSlot;
27
- // Block proposals from proposal archive to serialized BlockProposal
28
- blockProposals;
29
- // Block proposals indexed by slot and index-within-checkpoint for duplicate detection
30
- // Key: (slot << 10) | indexWithinCheckpoint, Value: archive string
31
- blockProposalsForSlotAndIndex;
32
- // Checkpoint attestations indexed by (slot, signer) for tracking attestations per (slot, signer) for duplicate detection
33
- // Key: `${Fr(slot).toString()}-${signerAddress}` string (padded for lexicographic ordering), Value: `proposalId` strings
34
- checkpointAttestationsPerSlotAndSigner;
24
+ // Checkpoint attestations from `${paddedSlot}-${signer}` to serialized CheckpointAttestation.
25
+ // Stores the first attestation seen per (slot, signer); subsequent distinct payload
26
+ // hashes from the same signer are tracked only in `attestationHashesPerSlotAndSigner`
27
+ // for equivocation detection.
28
+ attestationPerSlotAndSigner;
29
+ // Distinct payload hashes seen per (slot, signer) for tracking attestation equivocations.
30
+ // Key: `${paddedSlot}-${signerAddress}`, Value: CheckpointProposalHash (`0x`-prefixed hex)
31
+ attestationHashesPerSlotAndSigner;
32
+ // Checkpoint proposals from `${paddedSlot}-${payloadHash}` to serialized CheckpointProposalCore.
33
+ // Stores every accepted distinct payload up to MAX_CHECKPOINT_PROPOSALS_PER_SLOT.
34
+ checkpointProposalsPerSlotAndHash;
35
+ // Distinct payload hashes seen per slot. Hash collision = duplicate.
36
+ // Hash count reaching 2 = equivocation.
37
+ // Key: slot number, Value: CheckpointProposalHash (`0x`-prefixed hex)
38
+ checkpointProposalHashesPerSlot;
39
+ // Block proposals from `${paddedSlot}-${paddedIndex}-${payloadHash}` to serialized BlockProposal.
40
+ // Stores every accepted distinct payload up to MAX_BLOCK_PROPOSALS_PER_POSITION.
41
+ blockProposalsPerSlotIndexAndHash;
42
+ // Distinct payload hashes seen per (slot, indexWithinCheckpoint).
43
+ // Key: slot * (1 << INDEX_BITS) + indexWithinCheckpoint, Value: BlockProposalHash (`0x`-prefixed hex)
44
+ blockProposalHashesPerSlotAndIndex;
45
+ // Secondary index from archive root to all retained block proposal keys.
46
+ blockProposalKeysPerArchive;
35
47
  constructor(store, telemetry = getTelemetryClient(), log = createLogger('aztec:attestation_pool')){
36
48
  this.store = store;
37
49
  this.log = log;
38
50
  this.poolStats = async ()=>{
39
51
  return {
40
- itemCount: await this.checkpointAttestations.sizeAsync()
52
+ itemCount: await this.attestationPerSlotAndSigner.sizeAsync()
41
53
  };
42
54
  };
43
55
  // Initialize block proposal storage
44
- this.blockProposals = store.openMap('proposals');
45
- this.blockProposalsForSlotAndIndex = store.openMultiMap('block_proposals_for_slot_and_index');
56
+ this.blockProposalsPerSlotIndexAndHash = store.openMap('block_proposals_by_slot_index_and_hash');
57
+ this.blockProposalHashesPerSlotAndIndex = store.openMultiMap('block_proposals_for_slot_and_index');
58
+ this.blockProposalKeysPerArchive = store.openMultiMap('block_proposals_by_archive');
46
59
  // Initialize checkpoint attestations storage
47
- this.checkpointAttestations = store.openMap('checkpoint_attestations');
48
- this.checkpointAttestationsPerSlotAndSigner = store.openMultiMap('checkpoint_attestations_per_slot_and_signer');
60
+ this.attestationPerSlotAndSigner = store.openMap('checkpoint_attestations');
61
+ this.attestationHashesPerSlotAndSigner = store.openMultiMap('checkpoint_attestations_per_slot_and_signer');
49
62
  // Initialize checkpoint proposal storage
50
- this.checkpointProposals = store.openMap('checkpoint_proposals');
51
- this.checkpointProposalsForSlot = store.openMultiMap('checkpoint_proposals_for_slot');
63
+ this.checkpointProposalsPerSlotAndHash = store.openMap('checkpoint_proposals_by_slot_and_hash');
64
+ this.checkpointProposalHashesPerSlot = store.openMultiMap('checkpoint_proposals_for_slot');
52
65
  this.metrics = new PoolInstrumentation(telemetry, PoolName.ATTESTATION_POOL, this.poolStats);
53
66
  }
54
67
  poolStats;
55
68
  /** Returns whether the pool is empty. */ async isEmpty() {
56
- for await (const _ of this.checkpointAttestations.entriesAsync()){
57
- return false;
58
- }
59
- for await (const _ of this.blockProposals.entriesAsync()){
60
- return false;
61
- }
62
- return true;
69
+ const [attestationCount, blockProposalCount, checkpointProposalCount] = await Promise.all([
70
+ this.attestationPerSlotAndSigner.sizeAsync(),
71
+ this.blockProposalsPerSlotIndexAndHash.sizeAsync(),
72
+ this.checkpointProposalsPerSlotAndHash.sizeAsync()
73
+ ]);
74
+ return attestationCount === 0 && blockProposalCount === 0 && checkpointProposalCount === 0;
75
+ }
76
+ /** Number of bits reserved for indexWithinCheckpoint in position keys. */ static INDEX_BITS = 10;
77
+ /** Maximum indexWithinCheckpoint value (2^10 - 1 = 1023). */ static MAX_INDEX = (1 << AttestationPool.INDEX_BITS) - 1;
78
+ /** Decimal digits used to left-pad slot numbers in string keys.
79
+ * 10 digits ≈ 3500 years at 36 s/slot, leaving ample headroom. */ static SLOT_PAD_DIGITS = 10;
80
+ /** Fixed-width decimal slot string for use in composite string keys. */ slotPaddedKey(slot) {
81
+ return slot.toString().padStart(AttestationPool.SLOT_PAD_DIGITS, '0');
63
82
  }
64
- getProposalKey(slot, proposalId) {
65
- const slotStr = typeof slot === 'string' ? slot : new Fr(slot).toString();
66
- const proposalIdStr = typeof proposalId === 'string' ? proposalId : Buffer.isBuffer(proposalId) ? Fr.fromBuffer(proposalId).toString() : proposalId.toString();
67
- return `${slotStr}-${proposalIdStr}`;
83
+ /** Fixed-width decimal index string for use in composite string keys. */ indexPaddedKey(indexWithinCheckpoint) {
84
+ return indexWithinCheckpoint.toString().padStart(4, '0');
68
85
  }
69
- getAttestationKey(slot, proposalId, address) {
70
- return `${this.getProposalKey(slot, proposalId)}-${address}`;
86
+ /** Key for retained block proposals. */ getBlockProposalKey(slot, indexWithinCheckpoint, payloadHash) {
87
+ return `${this.slotPaddedKey(slot)}-${this.indexPaddedKey(indexWithinCheckpoint)}-${payloadHash}`;
71
88
  }
72
- /** Returns range bounds for querying all attestations for a given slot. */ getAttestationKeyRangeForSlot(slot) {
73
- const slotStr = new Fr(slot).toString();
89
+ /** Range bounds for all retained block proposals in a slot. */ getBlockProposalKeyRangeForSlot(slot) {
74
90
  return {
75
- start: `${slotStr}-`,
76
- end: `${slotStr}-Z`
77
- }; // 'Z' sorts after any hex character
91
+ start: `${this.slotPaddedKey(slot)}-`,
92
+ end: `${this.slotPaddedKey(slot + 1)}-`
93
+ };
94
+ }
95
+ /** Key for retained checkpoint proposals. */ getCheckpointProposalKey(slot, payloadHash) {
96
+ return `${this.slotPaddedKey(slot)}-${payloadHash}`;
78
97
  }
79
- /** Returns range bounds for querying all attestations for a given (slot, proposalId). */ getAttestationKeyRangeForProposal(slot, proposalId) {
80
- const proposalKey = this.getProposalKey(slot, proposalId);
98
+ /** Range bounds for all retained checkpoint proposals in a slot. */ getCheckpointProposalKeyRangeForSlot(slot) {
81
99
  return {
82
- start: `${proposalKey}-`,
83
- end: `${proposalKey}-Z`
100
+ start: `${this.slotPaddedKey(slot)}-`,
101
+ end: `${this.slotPaddedKey(slot + 1)}-`
84
102
  };
85
103
  }
86
- /** Creates a key for the per-signer-per-slot attestation index. Uses padded slot for lexicographic ordering. */ getSlotSignerKey(slot, signerAddress) {
87
- const slotStr = new Fr(slot).toString();
88
- return `${slotStr}-${signerAddress}`;
104
+ /** Key for the per-(slot, signer) attestation main store and equivocation index. */ getSlotSignerKey(slot, signerAddress) {
105
+ return `${this.slotPaddedKey(slot)}-${signerAddress}`;
89
106
  }
90
- /** Number of bits reserved for indexWithinCheckpoint in position keys. */ static INDEX_BITS = 10;
91
- /** Maximum indexWithinCheckpoint value (2^10 - 1 = 1023). */ static MAX_INDEX = (1 << AttestationPool.INDEX_BITS) - 1;
92
- /** Creates a position key for block proposals: (slot << 10) | indexWithinCheckpoint. */ getBlockPositionKey(slot, indexWithinCheckpoint) {
107
+ /**
108
+ * Returns range bounds for querying all attestations for a given slot.
109
+ * Fixed-width padding ensures the slot prefix sorts cleanly, so using the next
110
+ * slot's prefix as the upper bound captures exactly the current slot's entries.
111
+ */ getAttestationKeyRangeForSlot(slot) {
112
+ return {
113
+ start: `${this.slotPaddedKey(slot)}-`,
114
+ end: `${this.slotPaddedKey(slot + 1)}-`
115
+ };
116
+ }
117
+ /** Creates a position key for block proposals: slot * 1024 + indexWithinCheckpoint.
118
+ * Uses multiplication instead of bit-shift to avoid 32-bit signed integer overflow
119
+ * (bit-shift overflows after slot ~2^21, roughly 278 days of uptime). */ getBlockPositionKey(slot, indexWithinCheckpoint) {
93
120
  if (indexWithinCheckpoint > AttestationPool.MAX_INDEX) {
94
121
  throw new Error(`Value for indexWithinCheckpoint ${indexWithinCheckpoint} exceeds maximum ${AttestationPool.MAX_INDEX}`);
95
122
  }
96
- return slot << AttestationPool.INDEX_BITS | indexWithinCheckpoint;
123
+ return slot * (1 << AttestationPool.INDEX_BITS) + indexWithinCheckpoint;
124
+ }
125
+ /** Returns true if the multimap already contains the given value for the given key. */ async multimapHasValue(map, key, value) {
126
+ const values = await toArray(map.getValuesAsync(key));
127
+ return values.includes(value);
97
128
  }
98
129
  /**
99
130
  * Attempts to add a block proposal to the pool.
100
131
  *
101
- * This method performs validation and addition in a single call:
102
- * - Checks if the proposal already exists (returns alreadyExists: true if so)
103
- * - Checks if the position has reached the proposal cap (returns added: false if so)
104
- * - Adds the proposal if validation passes
132
+ * - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
133
+ * exact same signed payload returns `alreadyExists: true`.
134
+ * - Distinct payload hashes at the same `(slot, indexWithinCheckpoint)` are tracked
135
+ * in the equivocation index and retained up to the cap.
105
136
  *
106
137
  * @param blockProposal - The block proposal to add
107
138
  * @returns Result indicating whether the proposal was added and duplicate detection info
108
139
  */ async tryAddBlockProposal(blockProposal) {
109
140
  return await this.store.transactionAsync(async ()=>{
110
- const proposalId = blockProposal.archive.toString();
111
- // Check if already exists
112
- const alreadyExists = await this.blockProposals.hasAsync(proposalId);
113
- if (alreadyExists) {
114
- const count = await this.getBlockProposalCountForPosition(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
141
+ const positionKey = this.getBlockPositionKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
142
+ const payloadHash = blockProposal.getPayloadHash();
143
+ // Hash already tracked => exact same signed payload was already received.
144
+ if (await this.multimapHasValue(this.blockProposalHashesPerSlotAndIndex, positionKey, payloadHash)) {
145
+ const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
115
146
  return {
116
147
  added: false,
117
148
  alreadyExists: true,
118
149
  count
119
150
  };
120
151
  }
121
- // Get current count for position and check cap, do not add if exceeded
122
- const count = await this.getBlockProposalCountForPosition(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
152
+ // Cap reached for this position (no more new payload hashes accepted).
153
+ const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
123
154
  if (count >= MAX_BLOCK_PROPOSALS_PER_POSITION) {
124
155
  return {
125
156
  added: false,
@@ -127,10 +158,14 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
127
158
  count
128
159
  };
129
160
  }
130
- // Add the proposal
131
- await this.addBlockProposal(blockProposal);
161
+ // Track the new payload hash for equivocation detection.
162
+ await this.blockProposalHashesPerSlotAndIndex.set(positionKey, payloadHash);
163
+ const proposalKey = this.getBlockProposalKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint, payloadHash);
164
+ await this.blockProposalsPerSlotIndexAndHash.set(proposalKey, blockProposal.withoutSignedTxs().toBuffer());
165
+ await this.blockProposalKeysPerArchive.set(blockProposal.archive.toString(), proposalKey);
132
166
  this.log.debug(`Added block proposal for slot ${blockProposal.slotNumber} and index ${blockProposal.indexWithinCheckpoint}`, {
133
- proposalId,
167
+ archive: blockProposal.archive.toString(),
168
+ payloadHash,
134
169
  slotNumber: blockProposal.slotNumber,
135
170
  indexWithinCheckpoint: blockProposal.indexWithinCheckpoint
136
171
  });
@@ -141,47 +176,67 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
141
176
  };
142
177
  });
143
178
  }
144
- /** Gets the count of block proposals for a given position (slot, indexWithinCheckpoint). */ getBlockProposalCountForPosition(slot, indexWithinCheckpoint) {
145
- const positionKey = this.getBlockPositionKey(slot, indexWithinCheckpoint);
146
- return this.blockProposalsForSlotAndIndex.getValueCountAsync(positionKey);
147
- }
148
- /** Internal method - must be called within a transaction. */ async addBlockProposal(blockProposal) {
149
- const proposalId = blockProposal.archive.toString();
150
- // Strip signedTxs before storing to avoid persisting full tx data
151
- await this.blockProposals.set(proposalId, blockProposal.withoutSignedTxs().toBuffer());
152
- // Index by slot and position for duplicate detection
153
- const positionKey = this.getBlockPositionKey(blockProposal.slotNumber, blockProposal.indexWithinCheckpoint);
154
- await this.blockProposalsForSlotAndIndex.set(positionKey, proposalId);
155
- }
156
179
  /**
157
- * Get block proposal by its ID.
180
+ * Get block proposal by archive root.
158
181
  *
159
- * @param id - The ID of the block proposal to retrieve. The ID is proposal.payload.archive
182
+ * Resolves the archive root through the archive index and returns the first
183
+ * retained proposal for that archive. This lookup is used by block-txs req/resp,
184
+ * where any retained proposal for the requested archive gives the tx hash list.
160
185
  *
161
- * @return The block proposal if it exists, otherwise undefined.
162
- */ async getBlockProposal(id) {
163
- const buffer = await this.blockProposals.getAsync(id);
164
- try {
165
- if (buffer && buffer.length > 0) {
166
- return BlockProposal.fromBuffer(buffer);
186
+ * @param archiveRoot - The archive root to look up
187
+ * @return The block proposal if it exists and its archive matches, otherwise undefined.
188
+ */ async getBlockProposalByArchive(archiveRoot) {
189
+ for await (const proposalKey of this.blockProposalKeysPerArchive.getValuesAsync(archiveRoot)){
190
+ const buffer = await this.blockProposalsPerSlotIndexAndHash.getAsync(proposalKey);
191
+ if (!buffer || buffer.length === 0) {
192
+ continue;
193
+ }
194
+ try {
195
+ const proposal = BlockProposal.fromBuffer(buffer);
196
+ if (proposal.archive.toString() === archiveRoot) {
197
+ return proposal;
198
+ }
199
+ } catch {
200
+ continue;
167
201
  }
168
- } catch {
169
- return undefined;
170
202
  }
171
203
  return undefined;
172
204
  }
205
+ /** Returns retained signed proposals for a slot. */ async getProposalsForSlot(slot) {
206
+ const blockProposals = [];
207
+ const checkpointProposals = [];
208
+ for await (const [_, buffer] of this.blockProposalsPerSlotIndexAndHash.entriesAsync(this.getBlockProposalKeyRangeForSlot(slot))){
209
+ try {
210
+ blockProposals.push(BlockProposal.fromBuffer(buffer));
211
+ } catch {
212
+ continue;
213
+ }
214
+ }
215
+ for await (const [_, buffer] of this.checkpointProposalsPerSlotAndHash.entriesAsync(this.getCheckpointProposalKeyRangeForSlot(slot))){
216
+ try {
217
+ checkpointProposals.push(CheckpointProposal.fromBuffer(buffer));
218
+ } catch {
219
+ continue;
220
+ }
221
+ }
222
+ return {
223
+ blockProposals,
224
+ checkpointProposals
225
+ };
226
+ }
173
227
  /** Checks if any block proposals exist for a given slot (at index 0). */ async hasBlockProposalsForSlot(slot) {
174
228
  const positionKey = this.getBlockPositionKey(slot, 0);
175
- const count = await this.blockProposalsForSlotAndIndex.getValueCountAsync(positionKey);
229
+ const count = await this.blockProposalHashesPerSlotAndIndex.getValueCountAsync(positionKey);
176
230
  return count > 0;
177
231
  }
178
232
  /**
179
233
  * Attempts to add a checkpoint proposal to the pool.
180
234
  *
181
- * This method performs validation and addition in a single call:
182
- * - Checks if the proposal already exists (returns alreadyExists: true if so)
183
- * - Checks if the slot has reached the proposal cap (returns added: false if so)
184
- * - Adds the proposal if validation passes
235
+ * - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
236
+ * exact same signed payload returns `alreadyExists: true`.
237
+ * - Distinct payload hashes at the same slot are tracked in the equivocation index.
238
+ * Distinct payload bytes are retained up to the same cap so slashing watchers
239
+ * can recover signed proposals.
185
240
  *
186
241
  * Note: This method only handles the CheckpointProposalCore. If the original
187
242
  * CheckpointProposal contains a lastBlock, the caller should extract it via
@@ -191,19 +246,17 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
191
246
  * @returns Result indicating whether the proposal was added and duplicate detection info
192
247
  */ async tryAddCheckpointProposal(proposal) {
193
248
  return await this.store.transactionAsync(async ()=>{
194
- const proposalId = proposal.archive.toString();
195
- // Check if already exists
196
- const alreadyExists = await this.checkpointProposals.hasAsync(proposalId);
197
- if (alreadyExists) {
198
- const count = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
249
+ const slot = proposal.slotNumber;
250
+ const payloadHash = proposal.getPayloadHash();
251
+ if (await this.multimapHasValue(this.checkpointProposalHashesPerSlot, slot, payloadHash)) {
252
+ const count = await this.checkpointProposalHashesPerSlot.getValueCountAsync(slot);
199
253
  return {
200
254
  added: false,
201
255
  alreadyExists: true,
202
256
  count
203
257
  };
204
258
  }
205
- // Get current count for slot and check cap
206
- const count = await this.checkpointProposalsForSlot.getValueCountAsync(proposal.slotNumber);
259
+ const count = await this.checkpointProposalHashesPerSlot.getValueCountAsync(slot);
207
260
  if (count >= MAX_CHECKPOINT_PROPOSALS_PER_SLOT) {
208
261
  return {
209
262
  added: false,
@@ -211,11 +264,13 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
211
264
  count
212
265
  };
213
266
  }
214
- // Add the proposal if cap not exceeded
215
- await this.addCheckpointProposal(proposal);
216
- this.log.debug(`Added checkpoint proposal for slot ${proposal.slotNumber}`, {
217
- proposalId,
218
- slotNumber: proposal.slotNumber
267
+ // Track the new payload hash for equivocation detection.
268
+ await this.checkpointProposalHashesPerSlot.set(slot, payloadHash);
269
+ await this.checkpointProposalsPerSlotAndHash.set(this.getCheckpointProposalKey(slot, payloadHash), proposal.toBuffer());
270
+ this.log.debug(`Added checkpoint proposal for slot ${slot}`, {
271
+ archive: proposal.archive.toString(),
272
+ payloadHash,
273
+ slotNumber: slot
219
274
  });
220
275
  return {
221
276
  added: true,
@@ -224,58 +279,62 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
224
279
  };
225
280
  });
226
281
  }
227
- /** Internal method - must be called within a transaction. */ async addCheckpointProposal(proposal) {
228
- const slotKey = proposal.slotNumber;
229
- const proposalId = proposal.archive.toString();
230
- await this.checkpointProposalsForSlot.set(slotKey, proposalId);
231
- await this.checkpointProposals.set(proposalId, proposal.toBuffer());
232
- }
233
282
  /**
234
- * Get checkpoint proposal by its ID.
283
+ * Get a retained checkpoint proposal stored for the given slot.
284
+ * If multiple proposals were retained for an equivocation, returns the lowest
285
+ * payload hash deterministically.
235
286
  *
236
287
  * Returns a CheckpointProposalCore (without lastBlock info) since the lastBlock
237
288
  * is extracted and stored separately as a BlockProposal when added.
238
289
  *
239
- * @param id - The ID of the checkpoint proposal to retrieve (proposal.archive)
240
- * @return The checkpoint proposal core if it exists, otherwise undefined.
241
- */ async getCheckpointProposal(id) {
242
- const buffer = await this.checkpointProposals.getAsync(id);
243
- try {
244
- if (buffer && buffer.length > 0) {
245
- return CheckpointProposal.fromBuffer(buffer);
290
+ * @param slot - The slot to look up
291
+ * @return The checkpoint proposal core if one is stored, otherwise undefined.
292
+ */ async getCheckpointProposal(slot) {
293
+ for await (const [_, buffer] of this.checkpointProposalsPerSlotAndHash.entriesAsync(this.getCheckpointProposalKeyRangeForSlot(slot))){
294
+ try {
295
+ if (buffer && buffer.length > 0) {
296
+ return CheckpointProposal.fromBuffer(buffer);
297
+ }
298
+ } catch {
299
+ continue;
246
300
  }
247
- } catch {
248
- return undefined;
249
301
  }
250
302
  return undefined;
251
303
  }
252
304
  /**
253
305
  * Adds own checkpoint attestations to the pool.
254
- * Skips validations on number of checkpoint attestations stored for the given slot.
306
+ * Skips per-signer cap and equivocation tracking; the caller is trusted.
307
+ * Each (slot, signer) gets a single stored attestation; later additions overwrite.
255
308
  */ async addOwnCheckpointAttestations(attestations) {
256
309
  await this.store.transactionAsync(async ()=>{
257
310
  for (const attestation of attestations){
258
311
  const slotNumber = attestation.payload.header.slotNumber;
259
- const proposalId = attestation.archive;
260
312
  const sender = attestation.getSender();
261
313
  // Skip attestations with invalid signatures
262
314
  if (!sender) {
263
315
  this.log.warn(`Skipping own checkpoint attestation with invalid signature for slot ${slotNumber}`, {
264
316
  signature: attestation.signature.toString(),
265
317
  slotNumber,
266
- proposalId
318
+ archive: attestation.archive.toString()
267
319
  });
268
320
  continue;
269
321
  }
270
322
  const address = sender.toString();
271
- const ownKey = this.getAttestationKey(slotNumber, proposalId, address);
272
- await this.checkpointAttestations.set(ownKey, attestation.toBuffer());
323
+ const ownKey = this.getSlotSignerKey(slotNumber, address);
324
+ const payloadHash = attestation.getPayloadHash();
325
+ await this.attestationPerSlotAndSigner.set(ownKey, attestation.toBuffer());
273
326
  this.metrics.trackMempoolItemAdded(ownKey);
327
+ // Track our own payload hash so that an equivocating attestation from another
328
+ // peer at the same (slot, signer) is detected as a duplicate.
329
+ if (!await this.multimapHasValue(this.attestationHashesPerSlotAndSigner, ownKey, payloadHash)) {
330
+ await this.attestationHashesPerSlotAndSigner.set(ownKey, payloadHash);
331
+ }
274
332
  this.log.debug(`Added own checkpoint attestation for slot ${slotNumber} from ${address}`, {
275
333
  signature: attestation.signature.toString(),
276
334
  slotNumber,
277
335
  address,
278
- proposalId
336
+ archive: attestation.archive.toString(),
337
+ payloadHash
279
338
  });
280
339
  }
281
340
  });
@@ -283,29 +342,30 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
283
342
  /**
284
343
  * Get all checkpoint attestations for a given slot.
285
344
  *
345
+ * Returns one attestation per (slot, signer) — the first seen for each signer.
346
+ * Later equivocating attestations from the same signer are tracked in the index
347
+ * but their bytes are not retained.
348
+ *
286
349
  * @param slot - The slot to query
287
350
  * @return CheckpointAttestations
288
351
  */ async getCheckpointAttestationsForSlot(slot) {
289
352
  const range = this.getAttestationKeyRangeForSlot(slot);
290
353
  const attestations = [];
291
- for await (const [_, buf] of this.checkpointAttestations.entriesAsync(range)){
354
+ for await (const [_, buf] of this.attestationPerSlotAndSigner.entriesAsync(range)){
292
355
  attestations.push(CheckpointAttestation.fromBuffer(buf));
293
356
  }
294
357
  return attestations;
295
358
  }
296
359
  /**
297
- * Get checkpoint attestations for slot and given proposal.
360
+ * Get checkpoint attestations for a slot whose signed payload matches the given
361
+ * proposal payload hash.
298
362
  *
299
363
  * @param slot - The slot to query
300
- * @param proposalId - The proposal to query
301
- * @return CheckpointAttestations
302
- */ async getCheckpointAttestationsForSlotAndProposal(slot, proposalId) {
303
- const range = this.getAttestationKeyRangeForProposal(slot, proposalId);
304
- const attestations = [];
305
- for await (const [_, buf] of this.checkpointAttestations.entriesAsync(range)){
306
- attestations.push(CheckpointAttestation.fromBuffer(buf));
307
- }
308
- return attestations;
364
+ * @param proposalPayloadHash - Hex-encoded keccak256 of the target proposal's signed payload
365
+ * @return CheckpointAttestations whose `getPayloadHash()` matches `proposalPayloadHash`
366
+ */ async getCheckpointAttestationsForSlotAndProposal(slot, proposalPayloadHash) {
367
+ const all = await this.getCheckpointAttestationsForSlot(slot);
368
+ return all.filter((att)=>att.getPayloadHash() === proposalPayloadHash);
309
369
  }
310
370
  /**
311
371
  * Delete all pool data (attestations, proposals) older than the given slot.
@@ -316,48 +376,53 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
316
376
  let numberOfCheckpointProposals = 0;
317
377
  let numberOfBlockProposals = 0;
318
378
  await this.store.transactionAsync(async ()=>{
319
- // Delete checkpoint attestations with slot < oldestSlot
320
- // Attestation keys start with Fr(slot).toString(), so we use end bound of Fr(oldestSlot).toString()
321
- const attestationEndKey = new Fr(oldestSlot).toString();
322
- for await (const key of this.checkpointAttestations.keysAsync({
323
- end: attestationEndKey
379
+ const oldestSlotPadded = this.slotPaddedKey(oldestSlot);
380
+ // Delete checkpoint attestations whose key < `${oldestSlotPadded}-`. Fixed-width
381
+ // decimal padding means the slot prefix sorts strictly before any key at that slot.
382
+ for await (const key of this.attestationPerSlotAndSigner.keysAsync({
383
+ end: `${oldestSlotPadded}-`
324
384
  })){
325
- await this.checkpointAttestations.delete(key);
385
+ await this.attestationPerSlotAndSigner.delete(key);
326
386
  this.metrics.trackMempoolItemRemoved(key);
327
387
  numberOfAttestations++;
328
388
  }
329
- // Clean up per-signer-per-slot index. Keys are formatted as `${Fr(slot).toString()}-${signerAddress}`.
330
- // Since Fr pads to fixed-width hex, Fr(oldestSlot) is lexicographically greater than any key with
331
- // a smaller slot (even with the signer suffix), so using it as the exclusive end bound is correct.
332
- const slotSignerEndKey = new Fr(oldestSlot).toString();
333
- for await (const key of this.checkpointAttestationsPerSlotAndSigner.keysAsync({
334
- end: slotSignerEndKey
389
+ // Clean up per-signer-per-slot index using the same end bound.
390
+ for await (const key of this.attestationHashesPerSlotAndSigner.keysAsync({
391
+ end: `${oldestSlotPadded}-`
335
392
  })){
336
- await this.checkpointAttestationsPerSlotAndSigner.delete(key);
393
+ await this.attestationHashesPerSlotAndSigner.delete(key);
337
394
  }
338
- // Delete checkpoint proposals for slots < oldestSlot, using checkpointProposalsForSlot as index
339
- for await (const slot of this.checkpointProposalsForSlot.keysAsync({
395
+ // Delete checkpoint proposals for slots < oldestSlot.
396
+ for await (const slot of this.checkpointProposalHashesPerSlot.keysAsync({
340
397
  end: oldestSlot
341
398
  })){
342
- const proposalIds = await toArray(this.checkpointProposalsForSlot.getValuesAsync(slot));
343
- for (const proposalId of proposalIds){
344
- await this.checkpointProposals.delete(proposalId);
345
- numberOfCheckpointProposals++;
346
- }
347
- await this.checkpointProposalsForSlot.delete(slot);
399
+ await this.checkpointProposalHashesPerSlot.delete(slot);
348
400
  }
349
- // Delete block proposals for slots < oldestSlot, using blockProposalsForSlotAndIndex as index
350
- // Key format: (slot << INDEX_BITS) | indexWithinCheckpoint
351
- const blockPositionEndKey = oldestSlot << AttestationPool.INDEX_BITS;
352
- for await (const positionKey of this.blockProposalsForSlotAndIndex.keysAsync({
401
+ for await (const key of this.checkpointProposalsPerSlotAndHash.keysAsync({
402
+ end: `${oldestSlotPadded}-`
403
+ })){
404
+ await this.checkpointProposalsPerSlotAndHash.delete(key);
405
+ numberOfCheckpointProposals++;
406
+ }
407
+ // Delete block proposals for slots < oldestSlot, using blockProposalHashesPerSlotAndIndex as index.
408
+ // Key format: slot * (1 << INDEX_BITS) + indexWithinCheckpoint
409
+ const blockPositionEndKey = oldestSlot * (1 << AttestationPool.INDEX_BITS);
410
+ for await (const positionKey of this.blockProposalHashesPerSlotAndIndex.keysAsync({
353
411
  end: blockPositionEndKey
354
412
  })){
355
- const proposalIds = await toArray(this.blockProposalsForSlotAndIndex.getValuesAsync(positionKey));
356
- for (const proposalId of proposalIds){
357
- await this.blockProposals.delete(proposalId);
358
- numberOfBlockProposals++;
413
+ await this.blockProposalHashesPerSlotAndIndex.delete(positionKey);
414
+ }
415
+ for await (const [key, buffer] of this.blockProposalsPerSlotIndexAndHash.entriesAsync({
416
+ end: `${oldestSlotPadded}-`
417
+ })){
418
+ try {
419
+ const proposal = BlockProposal.fromBuffer(buffer);
420
+ await this.blockProposalKeysPerArchive.deleteValue(proposal.archive.toString(), key);
421
+ } catch {
422
+ // ignore decode errors when cleaning up
359
423
  }
360
- await this.blockProposalsForSlotAndIndex.delete(positionKey);
424
+ await this.blockProposalsPerSlotIndexAndHash.delete(key);
425
+ numberOfBlockProposals++;
361
426
  }
362
427
  });
363
428
  this.log.verbose(`Deleted old pool data`, {
@@ -370,17 +435,18 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
370
435
  /**
371
436
  * Attempts to add a checkpoint attestation to the pool.
372
437
  *
373
- * This method performs validation and addition in a single call:
374
- * - Checks if the attestation already exists (returns alreadyExists: true if so)
375
- * - Checks if this signer has reached the per-signer attestation cap for this slot
376
- * - Adds the attestation if validation passes
438
+ * - Detects duplicates by signed-payload hash (not archive); a re-broadcast of the
439
+ * exact same signed payload from the same signer returns `alreadyExists: true`.
440
+ * - Distinct payload hashes from the same (slot, signer) are tracked in the
441
+ * equivocation index. The first one's bytes are stored; later distinct hashes
442
+ * bump `count` so libp2p can fire its duplicate callback.
377
443
  *
378
444
  * @param attestation - The checkpoint attestation to add
379
- * @returns Result indicating whether the attestation was added, existence info, and count of
380
- * attestations by this signer for this slot (for equivocation detection)
445
+ * @returns Result indicating whether the attestation was added, existence info,
446
+ * and number of distinct payload hashes by this signer for this slot
447
+ * (for equivocation detection).
381
448
  */ async tryAddCheckpointAttestation(attestation) {
382
449
  const slotNumber = attestation.payload.header.slotNumber;
383
- const proposalId = attestation.archive.toString();
384
450
  const sender = attestation.getSender();
385
451
  if (!sender) {
386
452
  return {
@@ -390,24 +456,24 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
390
456
  };
391
457
  }
392
458
  const signerAddress = sender.toString();
459
+ const slotSignerKey = this.getSlotSignerKey(slotNumber, signerAddress);
460
+ const payloadHash = attestation.getPayloadHash();
393
461
  return await this.store.transactionAsync(async ()=>{
394
- const key = this.getAttestationKey(slotNumber, proposalId, signerAddress);
395
- const alreadyExists = await this.checkpointAttestations.hasAsync(key);
396
- // Get count of attestations by this signer for this slot (for duplicate detection)
397
- const signerAttestationCount = await this.getSignerAttestationCountForSlot(slotNumber, signerAddress);
398
- if (alreadyExists) {
462
+ if (await this.multimapHasValue(this.attestationHashesPerSlotAndSigner, slotSignerKey, payloadHash)) {
463
+ const count = await this.attestationHashesPerSlotAndSigner.getValueCountAsync(slotSignerKey);
399
464
  return {
400
465
  added: false,
401
466
  alreadyExists: true,
402
- count: signerAttestationCount
467
+ count
403
468
  };
404
469
  }
405
- // Check if this signer has exceeded the per-signer cap for this slot
470
+ const signerAttestationCount = await this.attestationHashesPerSlotAndSigner.getValueCountAsync(slotSignerKey);
406
471
  if (signerAttestationCount >= MAX_ATTESTATIONS_PER_SLOT_AND_SIGNER) {
407
472
  this.log.debug(`Rejecting attestation: signer ${signerAddress} exceeded per-slot cap for slot ${slotNumber}`, {
408
473
  slotNumber,
409
474
  signerAddress,
410
- proposalId,
475
+ archive: attestation.archive.toString(),
476
+ payloadHash,
411
477
  signerAttestationCount
412
478
  });
413
479
  return {
@@ -416,19 +482,23 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
416
482
  count: signerAttestationCount
417
483
  };
418
484
  }
419
- // Add the attestation
420
- await this.checkpointAttestations.set(key, attestation.toBuffer());
421
- this.metrics.trackMempoolItemAdded(key);
422
- // Track this attestation in the per-signer-per-slot index for duplicate detection
423
- const slotSignerKey = this.getSlotSignerKey(slotNumber, signerAddress);
424
- await this.checkpointAttestationsPerSlotAndSigner.set(slotSignerKey, proposalId);
485
+ // Track the new payload hash for equivocation detection.
486
+ await this.attestationHashesPerSlotAndSigner.set(slotSignerKey, payloadHash);
487
+ // Only the first distinct payload at (slot, signer) is stored; later
488
+ // equivocations are detected via the multimap but their bytes are not retained.
489
+ const alreadyHasStored = await this.attestationPerSlotAndSigner.hasAsync(slotSignerKey);
490
+ if (!alreadyHasStored) {
491
+ await this.attestationPerSlotAndSigner.set(slotSignerKey, attestation.toBuffer());
492
+ this.metrics.trackMempoolItemAdded(slotSignerKey);
493
+ }
425
494
  this.log.debug(`Added checkpoint attestation for slot ${slotNumber} from ${signerAddress}`, {
426
495
  signature: attestation.signature.toString(),
427
496
  slotNumber,
428
497
  address: signerAddress,
429
- proposalId
498
+ archive: attestation.archive.toString(),
499
+ payloadHash,
500
+ stored: !alreadyHasStored
430
501
  });
431
- // Return the new count
432
502
  return {
433
503
  added: true,
434
504
  alreadyExists: false,
@@ -436,10 +506,6 @@ export const MAX_BLOCK_PROPOSALS_PER_POSITION = 3;
436
506
  };
437
507
  });
438
508
  }
439
- /** Gets the count of attestations by a specific signer for a given slot. */ async getSignerAttestationCountForSlot(slot, signerAddress) {
440
- const slotSignerKey = this.getSlotSignerKey(slot, signerAddress);
441
- return await this.checkpointAttestationsPerSlotAndSigner.getValueCountAsync(slotSignerKey);
442
- }
443
509
  }
444
510
  /** Creates an AttestationPool backed by a temporary store for testing. */ export async function createTestAttestationPool(telemetry) {
445
511
  const { openTmpStore } = await import('@aztec/kv-store/lmdb-v2');