@aztec/p2p 0.0.1-fake-ceab37513c → 0.0.6-commit.a2d1860fe9

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 (601) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +4 -3
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +4 -4
  4. package/dest/client/factory.d.ts +7 -6
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +52 -15
  7. package/dest/client/index.d.ts +1 -1
  8. package/dest/client/interface.d.ts +58 -23
  9. package/dest/client/interface.d.ts.map +1 -1
  10. package/dest/client/p2p_client.d.ts +51 -74
  11. package/dest/client/p2p_client.d.ts.map +1 -1
  12. package/dest/client/p2p_client.js +613 -264
  13. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
  14. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
  15. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
  16. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
  17. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
  18. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
  19. package/dest/config.d.ts +95 -61
  20. package/dest/config.d.ts.map +1 -1
  21. package/dest/config.js +42 -16
  22. package/dest/enr/generate-enr.d.ts +1 -1
  23. package/dest/enr/index.d.ts +1 -1
  24. package/dest/errors/attestation-pool.error.d.ts +7 -0
  25. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  26. package/dest/errors/attestation-pool.error.js +12 -0
  27. package/dest/errors/reqresp.error.d.ts +1 -1
  28. package/dest/errors/reqresp.error.d.ts.map +1 -1
  29. package/dest/errors/tx-pool.error.d.ts +8 -0
  30. package/dest/errors/tx-pool.error.d.ts.map +1 -0
  31. package/dest/errors/tx-pool.error.js +9 -0
  32. package/dest/index.d.ts +2 -1
  33. package/dest/index.d.ts.map +1 -1
  34. package/dest/index.js +1 -0
  35. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +114 -57
  36. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  37. package/dest/mem_pools/attestation_pool/attestation_pool.js +441 -3
  38. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
  39. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  40. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +529 -288
  41. package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
  42. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  43. package/dest/mem_pools/attestation_pool/index.js +1 -2
  44. package/dest/mem_pools/attestation_pool/mocks.d.ts +234 -10
  45. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  46. package/dest/mem_pools/attestation_pool/mocks.js +17 -13
  47. package/dest/mem_pools/index.d.ts +3 -2
  48. package/dest/mem_pools/index.d.ts.map +1 -1
  49. package/dest/mem_pools/index.js +1 -1
  50. package/dest/mem_pools/instrumentation.d.ts +9 -1
  51. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  52. package/dest/mem_pools/instrumentation.js +37 -10
  53. package/dest/mem_pools/interface.d.ts +6 -7
  54. package/dest/mem_pools/interface.d.ts.map +1 -1
  55. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +33 -58
  56. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  57. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +316 -337
  58. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
  59. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
  60. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
  61. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
  62. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
  63. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
  64. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
  65. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  66. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
  67. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
  68. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  69. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
  70. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
  71. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  72. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
  73. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
  74. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  75. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
  76. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
  77. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
  78. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
  79. package/dest/mem_pools/tx_pool/index.d.ts +1 -2
  80. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
  81. package/dest/mem_pools/tx_pool/index.js +0 -1
  82. package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
  83. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  84. package/dest/mem_pools/tx_pool/priority.js +6 -1
  85. package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -6
  86. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  87. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  88. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  89. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +30 -24
  90. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
  91. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
  92. package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
  93. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +43 -0
  94. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
  95. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +103 -0
  96. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
  97. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
  98. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
  99. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +47 -0
  100. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
  101. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +128 -0
  102. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
  103. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  104. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +93 -0
  105. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
  106. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
  107. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +95 -0
  108. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +10 -0
  109. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
  110. package/dest/mem_pools/tx_pool_v2/eviction/index.js +11 -0
  111. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +174 -0
  112. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
  113. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +25 -0
  114. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
  115. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  116. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +65 -0
  117. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
  118. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  119. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +93 -0
  120. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
  121. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  122. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +74 -0
  123. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
  124. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
  125. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +73 -0
  126. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
  127. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
  128. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
  129. package/dest/mem_pools/tx_pool_v2/index.d.ts +6 -0
  130. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
  131. package/dest/mem_pools/tx_pool_v2/index.js +5 -0
  132. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  133. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  134. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  135. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +209 -0
  136. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
  137. package/dest/mem_pools/tx_pool_v2/interfaces.js +8 -0
  138. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +97 -0
  139. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -0
  140. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +152 -0
  141. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
  142. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
  143. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
  144. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +108 -0
  145. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
  146. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +355 -0
  147. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +60 -0
  148. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
  149. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +161 -0
  150. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +77 -0
  151. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
  152. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +878 -0
  153. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +7 -6
  154. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  155. package/dest/msg_validators/attestation_validator/attestation_validator.js +57 -24
  156. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  157. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  158. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +76 -0
  159. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  160. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  161. package/dest/msg_validators/attestation_validator/index.js +1 -0
  162. package/dest/msg_validators/clock_tolerance.d.ts +21 -0
  163. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  164. package/dest/msg_validators/clock_tolerance.js +37 -0
  165. package/dest/msg_validators/index.d.ts +2 -2
  166. package/dest/msg_validators/index.d.ts.map +1 -1
  167. package/dest/msg_validators/index.js +1 -1
  168. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
  169. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
  170. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
  171. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  172. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
  173. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
  174. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  175. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
  176. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  177. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  178. package/dest/msg_validators/proposal_validator/index.js +3 -0
  179. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
  180. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  181. package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
  182. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
  183. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
  184. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
  185. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +3 -3
  186. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  187. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +1 -1
  188. package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
  189. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  190. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  191. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +20 -6
  192. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  193. package/dest/msg_validators/tx_validator/block_header_validator.js +5 -4
  194. package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
  195. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  196. package/dest/msg_validators/tx_validator/data_validator.js +4 -1
  197. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +15 -4
  198. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  199. package/dest/msg_validators/tx_validator/double_spend_validator.js +7 -6
  200. package/dest/msg_validators/tx_validator/factory.d.ts +10 -4
  201. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  202. package/dest/msg_validators/tx_validator/factory.js +30 -14
  203. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  204. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  205. package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
  206. package/dest/msg_validators/tx_validator/gas_validator.d.ts +3 -2
  207. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  208. package/dest/msg_validators/tx_validator/gas_validator.js +11 -16
  209. package/dest/msg_validators/tx_validator/index.d.ts +3 -1
  210. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  211. package/dest/msg_validators/tx_validator/index.js +2 -0
  212. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +5 -7
  213. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  214. package/dest/msg_validators/tx_validator/metadata_validator.js +8 -26
  215. package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
  216. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  217. package/dest/msg_validators/tx_validator/phases_validator.js +6 -4
  218. package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
  219. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  220. package/dest/msg_validators/tx_validator/size_validator.js +23 -0
  221. package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
  222. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
  223. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +30 -0
  224. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  225. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  226. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
  227. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  228. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
  229. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
  230. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  231. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -2
  232. package/dest/services/data_store.d.ts +1 -1
  233. package/dest/services/data_store.d.ts.map +1 -1
  234. package/dest/services/data_store.js +10 -6
  235. package/dest/services/discv5/discV5_service.d.ts +1 -1
  236. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  237. package/dest/services/discv5/discV5_service.js +1 -1
  238. package/dest/services/dummy_service.d.ts +28 -3
  239. package/dest/services/dummy_service.d.ts.map +1 -1
  240. package/dest/services/dummy_service.js +51 -0
  241. package/dest/services/encoding.d.ts +2 -2
  242. package/dest/services/encoding.d.ts.map +1 -1
  243. package/dest/services/encoding.js +10 -8
  244. package/dest/services/gossipsub/index.d.ts +3 -0
  245. package/dest/services/gossipsub/index.d.ts.map +1 -0
  246. package/dest/services/gossipsub/index.js +2 -0
  247. package/dest/services/gossipsub/scoring.d.ts +21 -3
  248. package/dest/services/gossipsub/scoring.d.ts.map +1 -1
  249. package/dest/services/gossipsub/scoring.js +24 -7
  250. package/dest/services/gossipsub/topic_score_params.d.ts +173 -0
  251. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
  252. package/dest/services/gossipsub/topic_score_params.js +346 -0
  253. package/dest/services/index.d.ts +2 -1
  254. package/dest/services/index.d.ts.map +1 -1
  255. package/dest/services/index.js +1 -0
  256. package/dest/services/libp2p/instrumentation.d.ts +3 -1
  257. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  258. package/dest/services/libp2p/instrumentation.js +36 -71
  259. package/dest/services/libp2p/libp2p_service.d.ts +111 -84
  260. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  261. package/dest/services/libp2p/libp2p_service.js +1160 -284
  262. package/dest/services/peer-manager/interface.d.ts +1 -1
  263. package/dest/services/peer-manager/metrics.d.ts +9 -2
  264. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  265. package/dest/services/peer-manager/metrics.js +39 -16
  266. package/dest/services/peer-manager/peer_manager.d.ts +2 -33
  267. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  268. package/dest/services/peer-manager/peer_manager.js +6 -12
  269. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  270. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  271. package/dest/services/peer-manager/peer_scoring.js +68 -4
  272. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +48 -0
  273. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  274. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +562 -0
  275. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  276. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  277. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  278. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +46 -0
  279. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  280. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  281. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +34 -0
  282. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  283. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +130 -0
  284. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
  285. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  286. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
  287. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
  288. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  289. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
  290. package/dest/services/reqresp/config.d.ts +1 -1
  291. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +22 -3
  292. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  293. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +63 -4
  294. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -4
  295. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  296. package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
  297. package/dest/services/reqresp/constants.d.ts +12 -0
  298. package/dest/services/reqresp/constants.d.ts.map +1 -0
  299. package/dest/services/reqresp/constants.js +7 -0
  300. package/dest/services/reqresp/index.d.ts +1 -1
  301. package/dest/services/reqresp/interface.d.ts +13 -2
  302. package/dest/services/reqresp/interface.d.ts.map +1 -1
  303. package/dest/services/reqresp/interface.js +16 -2
  304. package/dest/services/reqresp/metrics.d.ts +6 -5
  305. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  306. package/dest/services/reqresp/metrics.js +17 -21
  307. package/dest/services/reqresp/protocols/auth.d.ts +2 -2
  308. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  309. package/dest/services/reqresp/protocols/auth.js +2 -2
  310. package/dest/services/reqresp/protocols/block.d.ts +1 -1
  311. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  312. package/dest/services/reqresp/protocols/block.js +3 -2
  313. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +5 -1
  314. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  315. package/dest/services/reqresp/protocols/block_txs/bitvector.js +12 -0
  316. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +7 -5
  317. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  318. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +27 -9
  319. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +30 -9
  320. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  321. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +60 -14
  322. package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
  323. package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
  324. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  325. package/dest/services/reqresp/protocols/index.d.ts +1 -1
  326. package/dest/services/reqresp/protocols/ping.d.ts +1 -1
  327. package/dest/services/reqresp/protocols/status.d.ts +6 -5
  328. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  329. package/dest/services/reqresp/protocols/status.js +7 -3
  330. package/dest/services/reqresp/protocols/tx.d.ts +8 -3
  331. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  332. package/dest/services/reqresp/protocols/tx.js +20 -0
  333. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  334. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +2 -2
  335. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  336. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  337. package/dest/services/reqresp/reqresp.d.ts +6 -41
  338. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  339. package/dest/services/reqresp/reqresp.js +471 -50
  340. package/dest/services/reqresp/status.d.ts +2 -2
  341. package/dest/services/reqresp/status.d.ts.map +1 -1
  342. package/dest/services/service.d.ts +55 -3
  343. package/dest/services/service.d.ts.map +1 -1
  344. package/dest/services/tx_collection/config.d.ts +22 -1
  345. package/dest/services/tx_collection/config.d.ts.map +1 -1
  346. package/dest/services/tx_collection/config.js +56 -2
  347. package/dest/services/tx_collection/fast_tx_collection.d.ts +10 -12
  348. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  349. package/dest/services/tx_collection/fast_tx_collection.js +71 -44
  350. package/dest/services/tx_collection/file_store_tx_collection.d.ts +53 -0
  351. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
  352. package/dest/services/tx_collection/file_store_tx_collection.js +167 -0
  353. package/dest/services/tx_collection/file_store_tx_source.d.ts +37 -0
  354. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
  355. package/dest/services/tx_collection/file_store_tx_source.js +90 -0
  356. package/dest/services/tx_collection/index.d.ts +3 -1
  357. package/dest/services/tx_collection/index.d.ts.map +1 -1
  358. package/dest/services/tx_collection/index.js +2 -0
  359. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  360. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  361. package/dest/services/tx_collection/instrumentation.js +11 -13
  362. package/dest/services/tx_collection/missing_txs_tracker.d.ts +32 -0
  363. package/dest/services/tx_collection/missing_txs_tracker.d.ts.map +1 -0
  364. package/dest/services/tx_collection/missing_txs_tracker.js +27 -0
  365. package/dest/services/tx_collection/proposal_tx_collector.d.ts +49 -0
  366. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
  367. package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
  368. package/dest/services/tx_collection/slow_tx_collection.d.ts +9 -6
  369. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  370. package/dest/services/tx_collection/slow_tx_collection.js +61 -26
  371. package/dest/services/tx_collection/tx_collection.d.ts +31 -18
  372. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  373. package/dest/services/tx_collection/tx_collection.js +79 -7
  374. package/dest/services/tx_collection/tx_collection_sink.d.ts +19 -9
  375. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  376. package/dest/services/tx_collection/tx_collection_sink.js +47 -20
  377. package/dest/services/tx_collection/tx_source.d.ts +8 -3
  378. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  379. package/dest/services/tx_collection/tx_source.js +21 -4
  380. package/dest/services/tx_file_store/config.d.ts +16 -0
  381. package/dest/services/tx_file_store/config.d.ts.map +1 -0
  382. package/dest/services/tx_file_store/config.js +22 -0
  383. package/dest/services/tx_file_store/index.d.ts +4 -0
  384. package/dest/services/tx_file_store/index.d.ts.map +1 -0
  385. package/dest/services/tx_file_store/index.js +3 -0
  386. package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
  387. package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
  388. package/dest/services/tx_file_store/instrumentation.js +29 -0
  389. package/dest/services/tx_file_store/tx_file_store.d.ts +48 -0
  390. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
  391. package/dest/services/tx_file_store/tx_file_store.js +152 -0
  392. package/dest/services/tx_provider.d.ts +6 -4
  393. package/dest/services/tx_provider.d.ts.map +1 -1
  394. package/dest/services/tx_provider.js +16 -6
  395. package/dest/services/tx_provider_instrumentation.d.ts +5 -2
  396. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  397. package/dest/services/tx_provider_instrumentation.js +14 -14
  398. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  399. package/dest/test-helpers/get-ports.d.ts +1 -1
  400. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  401. package/dest/test-helpers/index.d.ts +3 -1
  402. package/dest/test-helpers/index.d.ts.map +1 -1
  403. package/dest/test-helpers/index.js +2 -0
  404. package/dest/test-helpers/make-enrs.d.ts +1 -1
  405. package/dest/test-helpers/make-test-p2p-clients.d.ts +4 -4
  406. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  407. package/dest/test-helpers/mock-pubsub.d.ts +31 -4
  408. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  409. package/dest/test-helpers/mock-pubsub.js +103 -2
  410. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  411. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  412. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  413. package/dest/test-helpers/reqresp-nodes.d.ts +2 -2
  414. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  415. package/dest/test-helpers/reqresp-nodes.js +2 -1
  416. package/dest/test-helpers/test_tx_provider.d.ts +40 -0
  417. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  418. package/dest/test-helpers/test_tx_provider.js +41 -0
  419. package/dest/test-helpers/testbench-utils.d.ts +163 -0
  420. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  421. package/dest/test-helpers/testbench-utils.js +366 -0
  422. package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
  423. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  424. package/dest/testbench/p2p_client_testbench_worker.js +221 -123
  425. package/dest/testbench/parse_log_file.d.ts +1 -1
  426. package/dest/testbench/testbench.d.ts +1 -1
  427. package/dest/testbench/testbench.js +2 -2
  428. package/dest/testbench/worker_client_manager.d.ts +51 -6
  429. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  430. package/dest/testbench/worker_client_manager.js +226 -39
  431. package/dest/types/index.d.ts +1 -1
  432. package/dest/util.d.ts +3 -2
  433. package/dest/util.d.ts.map +1 -1
  434. package/dest/util.js +11 -2
  435. package/dest/versioning.d.ts +1 -1
  436. package/dest/versioning.js +2 -2
  437. package/package.json +19 -18
  438. package/src/bootstrap/bootstrap.ts +7 -4
  439. package/src/client/factory.ts +97 -31
  440. package/src/client/interface.ts +77 -23
  441. package/src/client/p2p_client.ts +291 -309
  442. package/src/client/test/tx_proposal_collector/README.md +227 -0
  443. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +346 -0
  444. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
  445. package/src/config.ts +76 -21
  446. package/src/errors/attestation-pool.error.ts +13 -0
  447. package/src/errors/tx-pool.error.ts +12 -0
  448. package/src/index.ts +1 -0
  449. package/src/mem_pools/attestation_pool/attestation_pool.ts +514 -58
  450. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +614 -309
  451. package/src/mem_pools/attestation_pool/index.ts +9 -2
  452. package/src/mem_pools/attestation_pool/mocks.ts +22 -15
  453. package/src/mem_pools/index.ts +4 -1
  454. package/src/mem_pools/instrumentation.ts +48 -10
  455. package/src/mem_pools/interface.ts +5 -7
  456. package/src/mem_pools/tx_pool/README.md +270 -0
  457. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +369 -373
  458. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
  459. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
  460. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
  461. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  462. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
  463. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  464. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  465. package/src/mem_pools/tx_pool/index.ts +0 -1
  466. package/src/mem_pools/tx_pool/priority.ts +8 -1
  467. package/src/mem_pools/tx_pool/tx_pool.ts +11 -5
  468. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +23 -17
  469. package/src/mem_pools/tx_pool_v2/README.md +275 -0
  470. package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
  471. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +120 -0
  472. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  473. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +160 -0
  474. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +121 -0
  475. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +122 -0
  476. package/src/mem_pools/tx_pool_v2/eviction/index.ts +27 -0
  477. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +209 -0
  478. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
  479. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
  480. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +87 -0
  481. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +90 -0
  482. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -0
  483. package/src/mem_pools/tx_pool_v2/index.ts +12 -0
  484. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  485. package/src/mem_pools/tx_pool_v2/interfaces.ts +239 -0
  486. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +242 -0
  487. package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
  488. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +444 -0
  489. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +223 -0
  490. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1052 -0
  491. package/src/msg_validators/attestation_validator/attestation_validator.ts +45 -32
  492. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +94 -0
  493. package/src/msg_validators/attestation_validator/index.ts +1 -0
  494. package/src/msg_validators/clock_tolerance.ts +51 -0
  495. package/src/msg_validators/index.ts +1 -1
  496. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
  497. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
  498. package/src/msg_validators/proposal_validator/index.ts +3 -0
  499. package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
  500. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
  501. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +2 -2
  502. package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
  503. package/src/msg_validators/tx_validator/block_header_validator.ts +22 -9
  504. package/src/msg_validators/tx_validator/data_validator.ts +18 -6
  505. package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
  506. package/src/msg_validators/tx_validator/factory.ts +72 -24
  507. package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
  508. package/src/msg_validators/tx_validator/gas_validator.ts +17 -28
  509. package/src/msg_validators/tx_validator/index.ts +2 -0
  510. package/src/msg_validators/tx_validator/metadata_validator.ts +25 -48
  511. package/src/msg_validators/tx_validator/phases_validator.ts +8 -4
  512. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  513. package/src/msg_validators/tx_validator/test_utils.ts +1 -1
  514. package/src/msg_validators/tx_validator/timestamp_validator.ts +57 -0
  515. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
  516. package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
  517. package/src/services/data_store.ts +10 -7
  518. package/src/services/discv5/discV5_service.ts +1 -1
  519. package/src/services/dummy_service.ts +68 -1
  520. package/src/services/encoding.ts +9 -7
  521. package/src/services/gossipsub/README.md +641 -0
  522. package/src/services/gossipsub/index.ts +2 -0
  523. package/src/services/gossipsub/scoring.ts +29 -5
  524. package/src/services/gossipsub/topic_score_params.ts +487 -0
  525. package/src/services/index.ts +1 -0
  526. package/src/services/libp2p/instrumentation.ts +39 -71
  527. package/src/services/libp2p/libp2p_service.ts +883 -286
  528. package/src/services/peer-manager/metrics.ts +44 -16
  529. package/src/services/peer-manager/peer_manager.ts +7 -4
  530. package/src/services/peer-manager/peer_scoring.ts +70 -3
  531. package/src/services/reqresp/batch-tx-requester/README.md +305 -0
  532. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
  533. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  534. package/src/services/reqresp/batch-tx-requester/interface.ts +53 -0
  535. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +161 -0
  536. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
  537. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
  538. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
  539. package/src/services/reqresp/connection-sampler/connection_sampler.ts +19 -1
  540. package/src/services/reqresp/constants.ts +14 -0
  541. package/src/services/reqresp/interface.ts +30 -2
  542. package/src/services/reqresp/metrics.ts +36 -27
  543. package/src/services/reqresp/protocols/auth.ts +2 -2
  544. package/src/services/reqresp/protocols/block.ts +3 -2
  545. package/src/services/reqresp/protocols/block_txs/bitvector.ts +16 -0
  546. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +35 -12
  547. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +75 -10
  548. package/src/services/reqresp/protocols/status.ts +16 -12
  549. package/src/services/reqresp/protocols/tx.ts +23 -2
  550. package/src/services/reqresp/reqresp.ts +79 -22
  551. package/src/services/service.ts +72 -4
  552. package/src/services/tx_collection/config.ts +84 -2
  553. package/src/services/tx_collection/fast_tx_collection.ts +96 -49
  554. package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
  555. package/src/services/tx_collection/file_store_tx_source.ts +117 -0
  556. package/src/services/tx_collection/index.ts +6 -0
  557. package/src/services/tx_collection/instrumentation.ts +11 -13
  558. package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
  559. package/src/services/tx_collection/proposal_tx_collector.ts +113 -0
  560. package/src/services/tx_collection/slow_tx_collection.ts +70 -36
  561. package/src/services/tx_collection/tx_collection.ts +122 -24
  562. package/src/services/tx_collection/tx_collection_sink.ts +48 -21
  563. package/src/services/tx_collection/tx_source.ts +24 -5
  564. package/src/services/tx_file_store/config.ts +37 -0
  565. package/src/services/tx_file_store/index.ts +3 -0
  566. package/src/services/tx_file_store/instrumentation.ts +36 -0
  567. package/src/services/tx_file_store/tx_file_store.ts +175 -0
  568. package/src/services/tx_provider.ts +27 -10
  569. package/src/services/tx_provider_instrumentation.ts +24 -14
  570. package/src/test-helpers/index.ts +2 -0
  571. package/src/test-helpers/make-test-p2p-clients.ts +3 -3
  572. package/src/test-helpers/mock-pubsub.ts +144 -4
  573. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  574. package/src/test-helpers/reqresp-nodes.ts +3 -2
  575. package/src/test-helpers/test_tx_provider.ts +64 -0
  576. package/src/test-helpers/testbench-utils.ts +430 -0
  577. package/src/testbench/p2p_client_testbench_worker.ts +349 -120
  578. package/src/testbench/testbench.ts +2 -2
  579. package/src/testbench/worker_client_manager.ts +304 -42
  580. package/src/util.ts +19 -3
  581. package/src/versioning.ts +2 -2
  582. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -30
  583. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
  584. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -190
  585. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -25
  586. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
  587. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -197
  588. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -80
  589. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  590. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -238
  591. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
  592. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  593. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -62
  594. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  595. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  596. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  597. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -256
  598. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -253
  599. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -283
  600. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -72
  601. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
@@ -1,21 +1,24 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
- import { randomInt } from '@aztec/foundation/crypto';
2
+ import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
4
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
4
- import { SerialQueue } from '@aztec/foundation/queue';
5
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
6
6
  import { Timer } from '@aztec/foundation/timer';
7
7
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
8
- import { protocolContractTreeRoot } from '@aztec/protocol-contracts';
9
- import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
8
+ import { protocolContractsHash } from '@aztec/protocol-contracts';
9
+ import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
10
10
  import type { ContractDataSource } from '@aztec/stdlib/contract';
11
11
  import { GasFees } from '@aztec/stdlib/gas';
12
12
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
13
13
  import {
14
- BlockAttestation,
15
14
  BlockProposal,
15
+ CheckpointAttestation,
16
+ CheckpointProposal,
17
+ type CheckpointProposalCore,
16
18
  type Gossipable,
17
19
  P2PClientType,
18
20
  P2PMessage,
21
+ type ValidationResult as P2PValidationResult,
19
22
  PeerErrorSeverity,
20
23
  TopicType,
21
24
  createTopicString,
@@ -23,10 +26,17 @@ import {
23
26
  metricsTopicStrToLabels,
24
27
  } from '@aztec/stdlib/p2p';
25
28
  import { MerkleTreeId } from '@aztec/stdlib/trees';
26
- import { Tx, type TxHash, type TxValidationResult } from '@aztec/stdlib/tx';
29
+ import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
27
30
  import type { UInt64 } from '@aztec/stdlib/types';
28
31
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
29
- import { Attributes, OtelMetricsAdapter, type TelemetryClient, WithTracer, trackSpan } from '@aztec/telemetry-client';
32
+ import {
33
+ Attributes,
34
+ OtelMetricsAdapter,
35
+ SpanStatusCode,
36
+ type TelemetryClient,
37
+ WithTracer,
38
+ trackSpan,
39
+ } from '@aztec/telemetry-client';
30
40
 
31
41
  import {
32
42
  type GossipSub,
@@ -34,7 +44,7 @@ import {
34
44
  type GossipsubMessage,
35
45
  gossipsub,
36
46
  } from '@chainsafe/libp2p-gossipsub';
37
- import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
47
+ import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
38
48
  import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
39
49
  import { noise } from '@chainsafe/libp2p-noise';
40
50
  import { yamux } from '@chainsafe/libp2p-yamux';
@@ -49,44 +59,64 @@ import { createLibp2p } from 'libp2p';
49
59
 
50
60
  import type { P2PConfig } from '../../config.js';
51
61
  import type { MemPools } from '../../mem_pools/interface.js';
52
- import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
62
+ import {
63
+ BlockProposalValidator,
64
+ CheckpointAttestationValidator,
65
+ CheckpointProposalValidator,
66
+ DoubleSpendTxValidator,
67
+ FishermanAttestationValidator,
68
+ getDefaultAllowedSetupFunctions,
69
+ } from '../../msg_validators/index.js';
53
70
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
54
- import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
55
- import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
56
- import { DoubleSpendTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
71
+ import {
72
+ type MessageValidator,
73
+ createTxMessageValidators,
74
+ createTxReqRespValidator,
75
+ } from '../../msg_validators/tx_validator/factory.js';
57
76
  import { GossipSubEvent } from '../../types/index.js';
58
77
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
59
78
  import { getVersions } from '../../versioning.js';
60
79
  import { AztecDatastore } from '../data_store.js';
61
80
  import { DiscV5Service } from '../discv5/discV5_service.js';
62
81
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
63
- import { gossipScoreThresholds } from '../gossipsub/scoring.js';
82
+ import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
83
+ import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
64
84
  import type { PeerManagerInterface } from '../peer-manager/interface.js';
65
85
  import { PeerManager } from '../peer-manager/peer_manager.js';
66
86
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
87
+ import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
67
88
  import type { P2PReqRespConfig } from '../reqresp/config.js';
68
89
  import {
69
90
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
70
91
  type ReqRespInterface,
92
+ type ReqRespResponse,
71
93
  ReqRespSubProtocol,
72
94
  type ReqRespSubProtocolHandler,
73
95
  type ReqRespSubProtocolHandlers,
74
96
  type ReqRespSubProtocolValidators,
75
97
  type SubProtocolMap,
76
98
  ValidationError,
77
- } from '../reqresp/interface.js';
78
- import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
79
- import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
99
+ } from '../reqresp/index.js';
80
100
  import {
81
101
  AuthRequest,
102
+ BlockTxsRequest,
103
+ BlockTxsResponse,
82
104
  StatusMessage,
83
105
  pingHandler,
106
+ reqGoodbyeHandler,
84
107
  reqRespBlockHandler,
108
+ reqRespBlockTxsHandler,
85
109
  reqRespStatusHandler,
86
110
  reqRespTxHandler,
87
- } from '../reqresp/protocols/index.js';
111
+ } from '../reqresp/index.js';
88
112
  import { ReqResp } from '../reqresp/reqresp.js';
89
- import type { P2PBlockReceivedCallback, P2PService, PeerDiscoveryService } from '../service.js';
113
+ import type {
114
+ P2PBlockReceivedCallback,
115
+ P2PCheckpointReceivedCallback,
116
+ P2PDuplicateAttestationCallback,
117
+ P2PService,
118
+ PeerDiscoveryService,
119
+ } from '../service.js';
90
120
  import { P2PInstrumentation } from './instrumentation.js';
91
121
 
92
122
  interface ValidationResult {
@@ -98,26 +128,36 @@ interface ValidationResult {
98
128
  type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
99
129
 
100
130
  // REFACTOR: Unify with the type above
101
- type ReceivedMessageValidationResult<T> =
102
- | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject> }
103
- | { obj?: undefined; result: TopicValidatorResult.Reject };
131
+ type ReceivedMessageValidationResult<T, M = undefined> =
132
+ | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
133
+ | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
104
134
 
105
135
  /**
106
136
  * Lib P2P implementation of the P2PService interface.
107
137
  */
108
138
  export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
109
- private jobQueue: SerialQueue = new SerialQueue();
110
139
  private discoveryRunningPromise?: RunningPromise;
111
140
  private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
112
141
 
113
142
  // Message validators
114
- private attestationValidator: AttestationValidator;
115
143
  private blockProposalValidator: BlockProposalValidator;
144
+ private checkpointProposalValidator: CheckpointProposalValidator;
145
+ private checkpointAttestationValidator: CheckpointAttestationValidator;
116
146
 
117
147
  private protocolVersion = '';
118
148
  private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
119
149
 
120
- private feesCache: { blockNumber: number; gasFees: GasFees } | undefined;
150
+ private feesCache: { blockNumber: BlockNumber; gasFees: GasFees } | undefined;
151
+
152
+ /** Callback invoked when a duplicate proposal is detected (triggers slashing). */
153
+ private duplicateProposalCallback?: (info: {
154
+ slot: SlotNumber;
155
+ proposer: EthAddress;
156
+ type: 'checkpoint' | 'block';
157
+ }) => void;
158
+
159
+ /** Callback invoked when a duplicate attestation is detected (triggers slashing). */
160
+ private duplicateAttestationCallback?: P2PDuplicateAttestationCallback;
121
161
 
122
162
  /**
123
163
  * Callback for when a block is received from a peer.
@@ -126,32 +166,48 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
126
166
  */
127
167
  private blockReceivedCallback: P2PBlockReceivedCallback;
128
168
 
169
+ /**
170
+ * Callback for when a checkpoint proposal is received from a peer.
171
+ * @param checkpoint - The checkpoint proposal received from the peer.
172
+ * @returns The attestations for the checkpoint, if any.
173
+ */
174
+ private checkpointReceivedCallback: P2PCheckpointReceivedCallback;
175
+
129
176
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
130
177
 
131
178
  private instrumentation: P2PInstrumentation;
132
179
 
180
+ private telemetry: TelemetryClient;
181
+
182
+ protected logger: Logger;
183
+
133
184
  constructor(
134
185
  private clientType: T,
135
186
  private config: P2PConfig,
136
187
  protected node: PubSubLibp2p,
137
188
  private peerDiscoveryService: PeerDiscoveryService,
138
189
  private reqresp: ReqRespInterface,
139
- private peerManager: PeerManagerInterface,
140
- protected mempools: MemPools<T>,
141
- private archiver: L2BlockSource & ContractDataSource,
190
+ protected peerManager: PeerManagerInterface,
191
+ protected mempools: MemPools,
192
+ protected archiver: L2BlockSource & ContractDataSource,
142
193
  private epochCache: EpochCacheInterface,
143
194
  private proofVerifier: ClientProtocolCircuitVerifier,
144
195
  private worldStateSynchronizer: WorldStateSynchronizer,
145
196
  telemetry: TelemetryClient,
146
- protected logger = createLogger('p2p:libp2p_service'),
197
+ logger: Logger = createLogger('p2p:libp2p_service'),
147
198
  ) {
148
199
  super(telemetry, 'LibP2PService');
200
+ this.telemetry = telemetry;
201
+
202
+ // Create child logger with fisherman prefix if in fisherman mode
203
+ this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
149
204
 
150
205
  this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
151
206
 
152
207
  this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
153
208
  this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
154
- this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
209
+ this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
210
+ this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
155
211
 
156
212
  const versions = getVersions(config);
157
213
  this.protocolVersion = compressComponentVersions(versions);
@@ -159,22 +215,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
159
215
 
160
216
  this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
161
217
  this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
162
- this.topicStrings[TopicType.block_attestation] = createTopicString(
163
- TopicType.block_attestation,
218
+ this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(
219
+ TopicType.checkpoint_proposal,
220
+ this.protocolVersion,
221
+ );
222
+ this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(
223
+ TopicType.checkpoint_attestation,
164
224
  this.protocolVersion,
165
225
  );
166
226
 
167
- this.attestationValidator = new AttestationValidator(epochCache);
168
227
  this.blockProposalValidator = new BlockProposalValidator(epochCache, { txsPermitted: !config.disableTransactions });
228
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
229
+ txsPermitted: !config.disableTransactions,
230
+ });
231
+ this.checkpointAttestationValidator = config.fishermanMode
232
+ ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry)
233
+ : new CheckpointAttestationValidator(epochCache);
169
234
 
170
235
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
171
236
 
172
- this.blockReceivedCallback = async (block: BlockProposal): Promise<BlockAttestation[] | undefined> => {
237
+ this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
173
238
  this.logger.debug(
174
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`,
175
- { p2pMessageIdentifier: await block.p2pMessageIdentifier() },
239
+ `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`,
240
+ { p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier() },
176
241
  );
177
- return undefined;
242
+ return false;
243
+ };
244
+
245
+ this.checkpointReceivedCallback = (
246
+ checkpoint: CheckpointProposalCore,
247
+ ): Promise<CheckpointAttestation[] | undefined> => {
248
+ this.logger.debug(
249
+ `Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`,
250
+ );
251
+ return Promise.resolve(undefined);
178
252
  };
179
253
  }
180
254
 
@@ -193,7 +267,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
193
267
  config: P2PConfig,
194
268
  peerId: PeerId,
195
269
  deps: {
196
- mempools: MemPools<T>;
270
+ mempools: MemPools;
197
271
  l2BlockSource: L2BlockSource & ContractDataSource;
198
272
  epochCache: EpochCacheInterface;
199
273
  proofVerifier: ClientProtocolCircuitVerifier;
@@ -220,14 +294,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
220
294
 
221
295
  const datastore = new AztecDatastore(peerStore);
222
296
 
223
- const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
297
+ const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
224
298
 
225
299
  const peerDiscoveryService = new DiscV5Service(
226
300
  peerId,
227
301
  config,
228
302
  packageVersion,
229
303
  telemetry,
230
- createLogger(`${logger.module}:discv5_service`),
304
+ createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
231
305
  );
232
306
 
233
307
  // Seed libp2p's bootstrap discovery with private and trusted peers
@@ -241,10 +315,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
241
315
  const versions = getVersions(config);
242
316
  const protocolVersion = compressComponentVersions(versions);
243
317
 
244
- const txTopic = createTopicString(TopicType.tx, protocolVersion);
245
- const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
246
- const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
247
-
248
318
  const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
249
319
  const directPeers = (
250
320
  await Promise.all(
@@ -264,6 +334,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
264
334
 
265
335
  const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
266
336
 
337
+ // Create dynamic topic score params based on network configuration
338
+ const l1Constants = epochCache.getL1Constants();
339
+ const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
340
+ slotDurationMs: l1Constants.slotDuration * 1000,
341
+ heartbeatIntervalMs: config.gossipsubInterval,
342
+ targetCommitteeSize: l1Constants.targetCommitteeSize,
343
+ blockDurationMs: config.blockDurationMs,
344
+ expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot,
345
+ });
346
+
267
347
  const node = await createLibp2p({
268
348
  start: false,
269
349
  peerId,
@@ -359,33 +439,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
359
439
  scoreParams: createPeerScoreParams({
360
440
  // IPColocation factor can be disabled for local testing - default to -5
361
441
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
362
- topics: {
363
- [txTopic]: createTopicScoreParams({
364
- topicWeight: 1,
365
- invalidMessageDeliveriesWeight: -20,
366
- invalidMessageDeliveriesDecay: 0.5,
367
- }),
368
- [blockAttestationTopic]: createTopicScoreParams({
369
- topicWeight: 1,
370
- invalidMessageDeliveriesWeight: -20,
371
- invalidMessageDeliveriesDecay: 0.5,
372
- }),
373
- [blockProposalTopic]: createTopicScoreParams({
374
- topicWeight: 1,
375
- invalidMessageDeliveriesWeight: -20,
376
- invalidMessageDeliveriesDecay: 0.5,
377
- }),
378
- },
442
+ topics: topicScoreParams,
379
443
  }),
380
444
  }) as (components: GossipSubComponents) => GossipSub,
381
445
  components: (components: { connectionManager: ConnectionManager }) => ({
382
446
  connectionManager: components.connectionManager,
383
447
  }),
384
448
  },
385
- logger: createLibp2pComponentLogger(logger.module),
449
+ logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
386
450
  });
387
451
 
388
- const peerScoring = new PeerScoring(config);
452
+ const peerScoring = new PeerScoring(config, telemetry);
389
453
  const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
390
454
 
391
455
  const peerManager = new PeerManager(
@@ -401,8 +465,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
401
465
  epochCache,
402
466
  );
403
467
 
404
- // Update gossipsub score params
405
- node.services.pubsub.score.params.appSpecificWeight = 10;
468
+ // Configure application-specific scoring for gossipsub.
469
+ // The weight scales app score to align with gossipsub thresholds:
470
+ // - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
471
+ // - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
472
+ // Note: positive topic scores can offset penalties, so alignment is best-effort.
473
+ node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
406
474
  node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
407
475
  peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
408
476
 
@@ -440,20 +508,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
440
508
  }
441
509
  const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
442
510
 
443
- // Start job queue, peer discovery service and libp2p node
444
- this.jobQueue.start();
445
-
446
- await this.peerManager.initializePeers();
447
- if (!this.config.p2pDiscoveryDisabled) {
448
- await this.peerDiscoveryService.start();
449
- }
450
- await this.node.start();
451
-
452
- // Subscribe to standard GossipSub topics by default
453
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
454
- this.subscribeToTopic(this.topicStrings[topic]);
455
- }
456
-
457
511
  // Create request response protocol handlers
458
512
  const txHandler = reqRespTxHandler(this.mempools);
459
513
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
@@ -467,9 +521,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
467
521
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
468
522
  };
469
523
 
470
- // Only handle block transactions request if attestation pool is available to the client
471
- if (this.mempools.attestationPool) {
472
- const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
524
+ if (!this.config.disableTransactions) {
525
+ const blockTxsHandler = reqRespBlockTxsHandler(
526
+ this.mempools.attestationPool,
527
+ this.archiver,
528
+ this.mempools.txPool,
529
+ );
473
530
  requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
474
531
  }
475
532
 
@@ -477,24 +534,41 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
477
534
  requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
478
535
  }
479
536
 
537
+ // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
538
+ const reqrespSubProtocolValidators = {
539
+ ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
540
+ [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
541
+ [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
542
+ [ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this),
543
+ };
544
+
545
+ await this.peerManager.initializePeers();
546
+
547
+ await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
548
+
549
+ await this.node.start();
550
+
551
+ // Subscribe to standard GossipSub topics by default
552
+ for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
553
+ this.subscribeToTopic(this.topicStrings[topic]);
554
+ }
555
+
480
556
  // add GossipSub listener
481
557
  this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
482
558
 
483
- // Start running promise for peer discovery
559
+ // Start running promise for peer discovery and metrics collection
560
+ if (!this.config.p2pDiscoveryDisabled) {
561
+ await this.peerDiscoveryService.start();
562
+ }
484
563
  this.discoveryRunningPromise = new RunningPromise(
485
- () => this.peerManager.heartbeat(),
564
+ async () => {
565
+ await this.peerManager.heartbeat();
566
+ },
486
567
  this.logger,
487
568
  this.config.peerCheckIntervalMS,
488
569
  );
489
570
  this.discoveryRunningPromise.start();
490
571
 
491
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
492
- const reqrespSubProtocolValidators = {
493
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
494
- // TODO(#11336): A request validator for blocks
495
- [ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this),
496
- };
497
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
498
572
  this.logger.info(`Started P2P service`, {
499
573
  listen: this.config.listenAddress,
500
574
  port: this.config.p2pPort,
@@ -514,9 +588,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
514
588
  // Stop peer manager
515
589
  this.logger.debug('Stopping peer manager...');
516
590
  await this.peerManager.stop();
517
-
518
- this.logger.debug('Stopping job queue...');
519
- await this.jobQueue.end();
520
591
  this.logger.debug('Stopping running promise...');
521
592
  await this.discoveryRunningPromise?.stop();
522
593
  this.logger.debug('Stopping peer discovery service...');
@@ -544,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
544
615
  return this.peerManager.getPeers(includePending);
545
616
  }
546
617
 
618
+ public getGossipMeshPeerCount(topicType: TopicType): number {
619
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
620
+ }
621
+
547
622
  private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
548
623
  this.logger.trace(`Received PUBSUB message.`);
549
624
 
@@ -571,6 +646,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
571
646
  return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
572
647
  }
573
648
 
649
+ public sendRequestToPeer(
650
+ peerId: PeerId,
651
+ subProtocol: ReqRespSubProtocol,
652
+ payload: Buffer,
653
+ dialTimeout?: number,
654
+ ): Promise<ReqRespResponse> {
655
+ return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
656
+ }
657
+
574
658
  /**
575
659
  * Get the ENR of the node
576
660
  * @returns The ENR of the node
@@ -583,6 +667,29 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
583
667
  this.blockReceivedCallback = callback;
584
668
  }
585
669
 
670
+ public registerCheckpointReceivedCallback(callback: P2PCheckpointReceivedCallback) {
671
+ this.checkpointReceivedCallback = callback;
672
+ }
673
+
674
+ /**
675
+ * Registers a callback to be invoked when a duplicate proposal is detected.
676
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
677
+ */
678
+ public registerDuplicateProposalCallback(
679
+ callback: (info: { slot: SlotNumber; proposer: EthAddress; type: 'checkpoint' | 'block' }) => void,
680
+ ): void {
681
+ this.duplicateProposalCallback = callback;
682
+ }
683
+
684
+ /**
685
+ * Registers a callback to be invoked when a duplicate attestation is detected.
686
+ * A validator signing attestations for different proposals at the same slot.
687
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
688
+ */
689
+ public registerDuplicateAttestationCallback(callback: P2PDuplicateAttestationCallback): void {
690
+ this.duplicateAttestationCallback = callback;
691
+ }
692
+
586
693
  /**
587
694
  * Subscribes to a topic.
588
695
  * @param topic - The topic to subscribe to.
@@ -604,7 +711,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
604
711
  if (!this.node.services.pubsub) {
605
712
  throw new Error('Pubsub service not available.');
606
713
  }
607
- const p2pMessage = P2PMessage.fromGossipable(message);
714
+ const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
715
+ const traceContext =
716
+ this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
717
+ const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
608
718
  const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
609
719
  return result.recipients.length;
610
720
  }
@@ -625,12 +735,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
625
735
  case this.topicStrings[TopicType.tx]:
626
736
  topicType = TopicType.tx;
627
737
  break;
628
- case this.topicStrings[TopicType.block_attestation]:
629
- topicType = TopicType.block_attestation;
630
- break;
631
738
  case this.topicStrings[TopicType.block_proposal]:
632
739
  topicType = TopicType.block_proposal;
633
740
  break;
741
+ case this.topicStrings[TopicType.checkpoint_proposal]:
742
+ topicType = TopicType.checkpoint_proposal;
743
+ break;
744
+ case this.topicStrings[TopicType.checkpoint_attestation]:
745
+ topicType = TopicType.checkpoint_attestation;
746
+ break;
634
747
  default:
635
748
  this.logger.error(`Received message on unknown topic: ${msg.topic}`);
636
749
  break;
@@ -649,13 +762,39 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
649
762
  return { result: true, topicType };
650
763
  }
651
764
 
765
+ /**
766
+ * Safely deserializes a P2PMessage from raw message data.
767
+ * @param msgId - The message ID.
768
+ * @param source - The peer ID of the message source.
769
+ * @param data - The raw message data.
770
+ * @returns The deserialized P2PMessage or undefined if deserialization fails.
771
+ */
772
+ private safelyDeserializeP2PMessage(msgId: string, source: PeerId, data: Uint8Array): P2PMessage | undefined {
773
+ try {
774
+ return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
775
+ } catch (err) {
776
+ this.logger.error(`Error deserializing P2PMessage`, err, {
777
+ msgId,
778
+ source: source.toString(),
779
+ });
780
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
781
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
782
+ return undefined;
783
+ }
784
+ }
785
+
652
786
  /**
653
787
  * Handles a new gossip message that was received by the client.
654
788
  * @param topic - The message's topic.
655
789
  * @param data - The message data
656
790
  */
657
791
  protected async handleNewGossipMessage(msg: Message, msgId: string, source: PeerId) {
658
- const p2pMessage = P2PMessage.fromMessageData(Buffer.from(msg.data));
792
+ const msgReceivedTime = Date.now();
793
+ let topicType: TopicType | undefined;
794
+ const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
795
+ if (!p2pMessage) {
796
+ return;
797
+ }
659
798
 
660
799
  const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
661
800
 
@@ -663,30 +802,92 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
663
802
  return;
664
803
  }
665
804
 
805
+ // Determine topic type for attributes
666
806
  if (msg.topic === this.topicStrings[TopicType.tx]) {
667
- await this.handleGossipedTx(p2pMessage.payload, msgId, source);
807
+ topicType = TopicType.tx;
808
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
809
+ topicType = TopicType.checkpoint_attestation;
810
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
811
+ topicType = TopicType.block_proposal;
812
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
813
+ topicType = TopicType.checkpoint_proposal;
668
814
  }
669
- if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
670
- await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
815
+
816
+ // Process the message, optionally within a linked span for trace propagation
817
+ const processMessage = async () => {
818
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
819
+ await this.handleGossipedTx(p2pMessage.payload, msgId, source);
820
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
821
+ if (this.clientType === P2PClientType.Full) {
822
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
823
+ }
824
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
825
+ await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
826
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
827
+ await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
828
+ } else {
829
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
830
+ }
831
+ };
832
+
833
+ const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
834
+ const propagatedContext = p2pMessage.traceContext
835
+ ? this.telemetry.extractPropagatedContext(p2pMessage.traceContext)
836
+ : undefined;
837
+
838
+ if (propagatedContext) {
839
+ await this.tracer.startActiveSpan(
840
+ 'LibP2PService.processMessage',
841
+ {
842
+ attributes: {
843
+ [Attributes.TOPIC_NAME]: topicType!,
844
+ [Attributes.PEER_ID]: source.toString(),
845
+ },
846
+ },
847
+ propagatedContext,
848
+ async span => {
849
+ try {
850
+ await processMessage();
851
+ span.setStatus({
852
+ code: SpanStatusCode.OK,
853
+ });
854
+ } catch (err) {
855
+ span.setStatus({
856
+ code: SpanStatusCode.ERROR,
857
+ message: String(err),
858
+ });
859
+ if (typeof err === 'string' || (err && err instanceof Error)) {
860
+ span.recordException(err);
861
+ }
862
+ throw err;
863
+ } finally {
864
+ span.end();
865
+ }
866
+ },
867
+ );
868
+ } else {
869
+ await processMessage();
671
870
  }
672
- if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
673
- await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
871
+
872
+ if (latency !== undefined && topicType !== undefined) {
873
+ this.instrumentation.recordMessageLatency(topicType, latency);
674
874
  }
675
875
 
676
876
  return;
677
877
  }
678
878
 
679
- protected async validateReceivedMessage<T>(
680
- validationFunc: () => Promise<ReceivedMessageValidationResult<T>>,
879
+ protected async validateReceivedMessage<T, M = undefined>(
880
+ validationFunc: () => Promise<ReceivedMessageValidationResult<T, M>>,
681
881
  msgId: string,
682
882
  source: PeerId,
683
883
  topicType: TopicType,
684
- ): Promise<ReceivedMessageValidationResult<T>> {
685
- let resultAndObj: ReceivedMessageValidationResult<T> = { result: TopicValidatorResult.Reject };
884
+ ): Promise<ReceivedMessageValidationResult<T, M>> {
885
+ let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
686
886
  const timer = new Timer();
687
887
  try {
688
888
  resultAndObj = await validationFunc();
689
889
  } catch (err) {
890
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
690
891
  this.logger.error(`Error deserializing and validating gossipsub message`, err, {
691
892
  msgId,
692
893
  source: source.toString(),
@@ -706,20 +907,33 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
706
907
  const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
707
908
  const tx = Tx.fromBuffer(payloadData);
708
909
  const isValid = await this.validatePropagatedTx(tx, source);
709
- const exists = isValid && (await this.mempools.txPool.hasTx(tx.getTxHash()));
910
+ if (!isValid) {
911
+ this.logger.trace(`Rejecting invalid propagated tx`, {
912
+ [Attributes.P2P_ID]: source.toString(),
913
+ });
914
+ return { result: TopicValidatorResult.Reject };
915
+ }
916
+
917
+ // Propagate only on pool acceptance
918
+ const txHash = tx.getTxHash();
919
+ const addResult = await this.mempools.txPool.addPendingTxs([tx], { source: 'gossip' });
920
+
921
+ const wasAccepted = addResult.accepted.some(h => h.equals(txHash));
922
+ const wasIgnored = addResult.ignored.some(h => h.equals(txHash));
710
923
 
711
924
  this.logger.trace(`Validate propagated tx`, {
712
925
  isValid,
713
- exists,
926
+ wasAccepted,
927
+ wasIgnored,
714
928
  [Attributes.P2P_ID]: source.toString(),
715
929
  });
716
930
 
717
- if (!isValid) {
718
- return { result: TopicValidatorResult.Reject };
719
- } else if (exists) {
931
+ if (wasAccepted) {
932
+ return { result: TopicValidatorResult.Accept, obj: tx };
933
+ } else if (wasIgnored) {
720
934
  return { result: TopicValidatorResult.Ignore, obj: tx };
721
935
  } else {
722
- return { result: TopicValidatorResult.Accept, obj: tx };
936
+ return { result: TopicValidatorResult.Reject };
723
937
  }
724
938
  };
725
939
 
@@ -728,6 +942,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
728
942
  return;
729
943
  }
730
944
 
945
+ // Tx was accepted into pool and will be propagated - just log and record metrics
731
946
  const txHash = tx.getTxHash();
732
947
  const txHashString = txHash.toString();
733
948
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
@@ -735,152 +950,386 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
735
950
  txHash: txHashString,
736
951
  });
737
952
 
738
- if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
739
- this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
740
- return;
741
- }
742
-
743
- await this.mempools.txPool.addTxs([tx]);
953
+ this.instrumentation.incrementTxReceived(1);
744
954
  }
745
955
 
746
956
  /**
747
- * Process Attestation From Peer
748
- * When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
749
- *
750
- * @param attestation - The attestation to process.
957
+ * Process a checkpoint attestation from a peer.
958
+ * Validates the attestation and adds it to the pool.
751
959
  */
752
- private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
753
- const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockAttestation>> = async () => {
754
- const attestation = BlockAttestation.fromBuffer(payloadData);
755
- const isValid = await this.validateAttestation(source, attestation);
756
- const exists = isValid && (await this.mempools.attestationPool!.hasAttestation(attestation));
757
-
758
- this.logger.trace(`Validate propagated block attestation`, {
759
- isValid,
760
- exists,
761
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
762
- [Attributes.P2P_ID]: source.toString(),
763
- });
764
-
765
- if (!isValid) {
766
- return { result: TopicValidatorResult.Reject };
767
- } else if (exists) {
768
- return { result: TopicValidatorResult.Ignore, obj: attestation };
769
- } else {
770
- return { result: TopicValidatorResult.Accept, obj: attestation };
771
- }
772
- };
773
-
774
- const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
775
- validationFunc,
960
+ private async processCheckpointAttestationFromPeer(
961
+ payloadData: Buffer,
962
+ msgId: string,
963
+ source: PeerId,
964
+ ): Promise<void> {
965
+ const { result, obj: attestation } = await this.validateReceivedMessage<CheckpointAttestation>(
966
+ () => this.validateAndStoreCheckpointAttestation(source, CheckpointAttestation.fromBuffer(payloadData)),
776
967
  msgId,
777
968
  source,
778
- TopicType.block_attestation,
969
+ TopicType.checkpoint_attestation,
779
970
  );
780
971
 
781
972
  if (result !== TopicValidatorResult.Accept || !attestation) {
782
973
  return;
783
974
  }
784
975
 
785
- this.logger.debug(
786
- `Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`,
976
+ this.logger.verbose(
977
+ `Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
787
978
  {
788
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
789
- slot: attestation.slotNumber.toNumber(),
979
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
980
+ slot: attestation.slotNumber,
790
981
  archive: attestation.archive.toString(),
791
982
  source: source.toString(),
792
983
  },
793
984
  );
794
-
795
- await this.mempools.attestationPool!.addAttestations([attestation]);
796
985
  }
797
986
 
798
- private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
799
- const validationFunc: () => Promise<ReceivedMessageValidationResult<BlockProposal>> = async () => {
800
- const block = BlockProposal.fromBuffer(payloadData);
801
- const isValid = await this.validateBlockProposal(source, block);
802
- const exists = isValid && (await this.mempools.attestationPool!.hasBlockProposal(block));
987
+ /** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */
988
+ @trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation) => ({
989
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
990
+ }))
991
+ protected async validateAndStoreCheckpointAttestation(
992
+ peerId: PeerId,
993
+ attestation: CheckpointAttestation,
994
+ ): Promise<ReceivedMessageValidationResult<CheckpointAttestation>> {
995
+ const validationResult = await this.checkpointAttestationValidator.validate(attestation);
996
+
997
+ if (validationResult.result === 'reject') {
998
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
999
+ this.peerManager.penalizePeer(peerId, validationResult.severity);
1000
+ return { result: TopicValidatorResult.Reject };
1001
+ }
803
1002
 
804
- this.logger.trace(`Validate propagated block proposal`, {
805
- isValid,
806
- exists,
807
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
808
- [Attributes.P2P_ID]: source.toString(),
1003
+ if (validationResult.result === 'ignore') {
1004
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
1005
+ }
1006
+
1007
+ // Try to add the attestation: this handles existence check, cap check, and adding in one call
1008
+ // count is the number of attestations by this signer for this slot (for duplicate detection)
1009
+ const slot = attestation.payload.header.slotNumber;
1010
+ const { added, alreadyExists, count } =
1011
+ await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
1012
+
1013
+ this.logger.trace(`Validate propagated checkpoint attestation`, {
1014
+ added,
1015
+ alreadyExists,
1016
+ count,
1017
+ [Attributes.SLOT_NUMBER]: slot.toString(),
1018
+ [Attributes.P2P_ID]: peerId.toString(),
1019
+ });
1020
+
1021
+ // Exact same attestation received, no need to re-broadcast
1022
+ if (alreadyExists) {
1023
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
1024
+ }
1025
+
1026
+ // Could not add (cap reached for signer), no need to re-broadcast
1027
+ if (!added) {
1028
+ this.logger.warn(`Dropping checkpoint attestation due to cap`, {
1029
+ slot: slot.toString(),
1030
+ archive: attestation.archive.toString(),
1031
+ source: peerId.toString(),
1032
+ attester: attestation.getSender()?.toString(),
1033
+ count,
809
1034
  });
1035
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
1036
+ }
810
1037
 
811
- if (!isValid) {
812
- return { result: TopicValidatorResult.Reject };
813
- } else if (exists) {
814
- return { result: TopicValidatorResult.Ignore, obj: block };
815
- } else {
816
- return { result: TopicValidatorResult.Accept, obj: block };
1038
+ // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
1039
+ // count is the number of attestations by this signer for this slot
1040
+ if (count === 2) {
1041
+ const attester = attestation.getSender();
1042
+ if (attester) {
1043
+ this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
1044
+ slot: slot.toString(),
1045
+ archive: attestation.archive.toString(),
1046
+ source: peerId.toString(),
1047
+ attester: attester.toString(),
1048
+ });
1049
+ this.duplicateAttestationCallback?.({ slot, attester });
817
1050
  }
818
- };
1051
+ }
1052
+
1053
+ // Attestation was added successfully - accept it so other nodes can also detect the equivocation
1054
+ return { result: TopicValidatorResult.Accept, obj: attestation };
1055
+ }
819
1056
 
820
- const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
821
- validationFunc,
1057
+ protected async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
1058
+ const {
1059
+ result,
1060
+ obj: block,
1061
+ metadata: { isEquivocated } = {},
1062
+ } = await this.validateReceivedMessage<BlockProposal, { isEquivocated: boolean }>(
1063
+ () => this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)),
822
1064
  msgId,
823
1065
  source,
824
1066
  TopicType.block_proposal,
825
1067
  );
826
1068
 
827
- if (!result || !block) {
1069
+ // If not accepted or equivocated, return
1070
+ if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
828
1071
  return;
829
1072
  }
830
1073
 
831
1074
  await this.processValidBlockProposal(block, source);
832
1075
  }
833
1076
 
834
- // REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
1077
+ /** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */
1078
+ @trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block) => ({
1079
+ [Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
1080
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
1081
+ }))
1082
+ protected async validateAndStoreBlockProposal(
1083
+ peerId: PeerId,
1084
+ block: BlockProposal,
1085
+ ): Promise<ReceivedMessageValidationResult<BlockProposal, { isEquivocated: boolean }>> {
1086
+ const validationResult = await this.blockProposalValidator.validate(block);
1087
+
1088
+ if (validationResult.result === 'reject') {
1089
+ this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1090
+ this.peerManager.penalizePeer(peerId, validationResult.severity);
1091
+ return { result: TopicValidatorResult.Reject };
1092
+ }
1093
+
1094
+ if (validationResult.result === 'ignore') {
1095
+ return { result: TopicValidatorResult.Ignore, obj: block };
1096
+ }
1097
+
1098
+ // Try to add the proposal: this handles existence check, cap check, and adding in one call
1099
+ const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1100
+ const isEquivocated = count !== undefined && count > 1;
1101
+
1102
+ // Duplicate proposal received, no need to re-broadcast
1103
+ if (alreadyExists) {
1104
+ this.logger.debug(`Ignoring duplicate block proposal received`, {
1105
+ ...block.toBlockInfo(),
1106
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1107
+ proposer: block.getSender()?.toString(),
1108
+ source: peerId.toString(),
1109
+ });
1110
+ return { result: TopicValidatorResult.Ignore, obj: block, metadata: { isEquivocated } };
1111
+ }
1112
+
1113
+ // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1114
+ if (!added) {
1115
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1116
+ this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1117
+ ...block.toBlockInfo(),
1118
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1119
+ count,
1120
+ proposer: block.getSender()?.toString(),
1121
+ source: peerId.toString(),
1122
+ });
1123
+ return { result: TopicValidatorResult.Reject, metadata: { isEquivocated } };
1124
+ }
1125
+
1126
+ // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
1127
+ // and do re-broadcast it so other nodes in the network know to slash the proposer
1128
+ if (isEquivocated) {
1129
+ const proposer = block.getSender();
1130
+ this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
1131
+ ...block.toBlockInfo(),
1132
+ source: peerId.toString(),
1133
+ proposer: proposer?.toString(),
1134
+ });
1135
+ // Invoke the duplicate callback on the first duplicate spotted only
1136
+ if (proposer && count === 2) {
1137
+ this.duplicateProposalCallback?.({ slot: block.slotNumber, proposer, type: 'block' });
1138
+ }
1139
+ return { result: TopicValidatorResult.Accept, obj: block, metadata: { isEquivocated } };
1140
+ }
1141
+
1142
+ // Otherwise, we're good to go!
1143
+ return { result: TopicValidatorResult.Accept, obj: block };
1144
+ }
1145
+
1146
+ // REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
1147
+ // should not be here as it does not deal with p2p networking.
835
1148
  @trackSpan('Libp2pService.processValidBlockProposal', async block => ({
836
- [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
1149
+ [Attributes.SLOT_NUMBER]: block.slotNumber,
837
1150
  [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
838
- [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then(i => i.toString()),
1151
+ [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
839
1152
  }))
840
- private async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
841
- const slot = block.slotNumber.toBigInt();
842
- const previousSlot = slot - 1n;
1153
+ protected async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
1154
+ const slot = block.slotNumber;
843
1155
  this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
844
- p2pMessageIdentifier: await block.p2pMessageIdentifier(),
845
- slot: block.slotNumber.toNumber(),
846
- archive: block.archive.toString(),
1156
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
847
1157
  source: sender.toString(),
1158
+ ...block.toBlockInfo(),
848
1159
  });
849
- const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
850
- if (attestationsForPreviousSlot !== undefined) {
851
- this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
1160
+
1161
+ // Mark the txs in this proposal as protected
1162
+ await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
1163
+
1164
+ // Call the block received callback to validate the proposal.
1165
+ // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1166
+ const isValid = await this.blockReceivedCallback(block, sender);
1167
+ if (!isValid) {
1168
+ this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
852
1169
  }
1170
+ }
853
1171
 
854
- // Mark the txs in this proposal as non-evictable
855
- await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
856
- await this.mempools.attestationPool?.addBlockProposal(block);
857
- const attestations = await this.blockReceivedCallback(block, sender);
1172
+ /**
1173
+ * Handle a gossiped checkpoint proposal.
1174
+ * Validates and processes the checkpoint proposal, then triggers the callback for attestation.
1175
+ */
1176
+ protected async handleGossipedCheckpointProposal(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
1177
+ const {
1178
+ result,
1179
+ obj: checkpoint,
1180
+ metadata: { isEquivocated, processBlock } = {},
1181
+ } = await this.validateReceivedMessage<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>(
1182
+ () => this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)),
1183
+ msgId,
1184
+ source,
1185
+ TopicType.checkpoint_proposal,
1186
+ );
858
1187
 
859
- // TODO: fix up this pattern - the abstraction is not nice
860
- // The attestation can be undefined if no handler is registered / the validator deems the block invalid
861
- if (attestations?.length) {
862
- for (const attestation of attestations) {
863
- this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber.toNumber()}`, {
864
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
865
- slot: attestation.slotNumber.toNumber(),
866
- archive: attestation.archive.toString(),
1188
+ // If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
1189
+ // TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
1190
+ if (processBlock && checkpoint?.getBlockProposal()) {
1191
+ await this.processValidBlockProposal(checkpoint.getBlockProposal()!, source);
1192
+ }
1193
+
1194
+ if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
1195
+ return;
1196
+ }
1197
+
1198
+ await this.processValidCheckpointProposal(checkpoint.toCore(), source);
1199
+ }
1200
+
1201
+ /**
1202
+ * Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
1203
+ * its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
1204
+ */
1205
+ @trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint) => ({
1206
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1207
+ }))
1208
+ protected async validateAndStoreCheckpointProposal(
1209
+ peerId: PeerId,
1210
+ checkpoint: CheckpointProposal,
1211
+ ): Promise<ReceivedMessageValidationResult<CheckpointProposal, { isEquivocated: boolean; processBlock: boolean }>> {
1212
+ const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
1213
+
1214
+ if (validationResult.result === 'reject') {
1215
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1216
+ this.peerManager.penalizePeer(peerId, validationResult.severity);
1217
+ return { result: TopicValidatorResult.Reject };
1218
+ }
1219
+
1220
+ if (validationResult.result === 'ignore') {
1221
+ return { result: TopicValidatorResult.Ignore, obj: checkpoint };
1222
+ }
1223
+
1224
+ // Extract and try to add the block proposal first if present
1225
+ const blockProposal = checkpoint.getBlockProposal();
1226
+ let processBlock = false;
1227
+ if (blockProposal) {
1228
+ this.logger.debug(`Validating block proposal from propagated checkpoint`, {
1229
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1230
+ [Attributes.P2P_ID]: peerId.toString(),
1231
+ });
1232
+ const {
1233
+ result,
1234
+ obj,
1235
+ metadata: { isEquivocated } = {},
1236
+ } = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1237
+ if (result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1238
+ this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1239
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1240
+ [Attributes.P2P_ID]: peerId.toString(),
1241
+ isEquivocated,
1242
+ result,
867
1243
  });
868
- await this.broadcastAttestation(attestation);
1244
+ return { result: TopicValidatorResult.Reject };
1245
+ } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1246
+ processBlock = true;
869
1247
  }
870
1248
  }
1249
+
1250
+ // Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
1251
+ const checkpointCore = checkpoint.toCore();
1252
+ const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
1253
+ const { added, alreadyExists, count } = tryAddResult;
1254
+ const isEquivocated = count !== undefined && count > 1;
1255
+
1256
+ // Duplicate proposal received, do not re-broadcast
1257
+ if (alreadyExists) {
1258
+ this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
1259
+ ...checkpoint.toCheckpointInfo(),
1260
+ source: peerId.toString(),
1261
+ });
1262
+ return {
1263
+ result: TopicValidatorResult.Ignore,
1264
+ obj: checkpoint,
1265
+ metadata: { isEquivocated, processBlock },
1266
+ };
1267
+ }
1268
+
1269
+ // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1270
+ // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1271
+ if (!added) {
1272
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.HighToleranceError);
1273
+ this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1274
+ ...checkpoint.toCheckpointInfo(),
1275
+ count,
1276
+ source: peerId.toString(),
1277
+ });
1278
+ return { result: TopicValidatorResult.Reject, obj: checkpoint, metadata: { isEquivocated, processBlock } };
1279
+ }
1280
+
1281
+ // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
1282
+ // and do re-broadcast it so other nodes in the network know to slash the proposer
1283
+ if (isEquivocated) {
1284
+ const proposer = checkpoint.getSender();
1285
+ this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
1286
+ ...checkpoint.toCheckpointInfo(),
1287
+ source: peerId.toString(),
1288
+ proposer: proposer?.toString(),
1289
+ });
1290
+ // Invoke the duplicate callback on the first duplicate spotted only
1291
+ if (proposer && count === 2) {
1292
+ this.duplicateProposalCallback?.({ slot: checkpoint.slotNumber, proposer, type: 'checkpoint' });
1293
+ }
1294
+ return {
1295
+ result: TopicValidatorResult.Accept,
1296
+ obj: checkpoint,
1297
+ metadata: { isEquivocated, processBlock },
1298
+ };
1299
+ }
1300
+
1301
+ // Otherwise, we're good to go!
1302
+ return { result: TopicValidatorResult.Accept, obj: checkpoint, metadata: { processBlock, isEquivocated } };
871
1303
  }
872
1304
 
873
1305
  /**
874
- * Broadcast an attestation to all peers.
875
- * @param attestation - The attestation to broadcast.
1306
+ * Process a validated checkpoint proposal.
1307
+ * Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
876
1308
  */
877
- @trackSpan('Libp2pService.broadcastAttestation', async attestation => ({
878
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
879
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
880
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
1309
+ @trackSpan('Libp2pService.processValidCheckpointProposal', async checkpoint => ({
1310
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
1311
+ [Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
1312
+ [Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then(i => i.toString()),
881
1313
  }))
882
- private async broadcastAttestation(attestation: BlockAttestation) {
883
- await this.propagate(attestation);
1314
+ protected async processValidCheckpointProposal(checkpoint: CheckpointProposalCore, sender: PeerId) {
1315
+ const slot = checkpoint.slotNumber;
1316
+ this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
1317
+ p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
1318
+ slot: checkpoint.slotNumber,
1319
+ archive: checkpoint.archive.toString(),
1320
+ source: sender.toString(),
1321
+ });
1322
+
1323
+ // Call the checkpoint received callback with the core version (without lastBlock)
1324
+ // to validate and potentially generate attestations
1325
+ const attestations = await this.checkpointReceivedCallback(checkpoint, sender);
1326
+ if (attestations && attestations.length > 0) {
1327
+ // If the callback returned attestations, add them to the pool and propagate them
1328
+ await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
1329
+ for (const attestation of attestations) {
1330
+ await this.propagate(attestation);
1331
+ }
1332
+ }
884
1333
  }
885
1334
 
886
1335
  /**
@@ -888,15 +1337,100 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
888
1337
  * @param message - The message to propagate.
889
1338
  */
890
1339
  public async propagate<T extends Gossipable>(message: T) {
891
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
1340
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
892
1341
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, { p2pMessageIdentifier });
893
- void this.jobQueue
894
- .put(async () => {
895
- await this.sendToPeers(message);
896
- })
897
- .catch(error => {
898
- this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
899
- });
1342
+ void this.sendToPeers(message).catch(error => {
1343
+ this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
1344
+ });
1345
+ }
1346
+
1347
+ /**
1348
+ * Validate the requested block transactions. Allow partial returns.
1349
+ * @param request - The block transactions request.
1350
+ * @param response - The block transactions response.
1351
+ * @param peerId - The ID of the peer that made the request.
1352
+ * @returns True if the requested block transactions are valid, false otherwise.
1353
+ */
1354
+ @trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
1355
+ [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
1356
+ }))
1357
+ protected async validateRequestedBlockTxs(
1358
+ request: BlockTxsRequest,
1359
+ response: BlockTxsResponse,
1360
+ peerId: PeerId,
1361
+ ): Promise<boolean> {
1362
+ const requestedTxValidator = this.createRequestedTxValidator();
1363
+
1364
+ try {
1365
+ if (!response.archiveRoot.equals(request.archiveRoot)) {
1366
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1367
+ throw new ValidationError(
1368
+ `Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`,
1369
+ );
1370
+ }
1371
+
1372
+ if (response.txIndices.getLength() !== request.txIndices.getLength()) {
1373
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1374
+ throw new ValidationError(
1375
+ `Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`,
1376
+ );
1377
+ }
1378
+
1379
+ // Check no duplicates and not exceeding returnable count
1380
+ const requestedIndices = new Set(request.txIndices.getTrueIndices());
1381
+ const availableIndices = new Set(response.txIndices.getTrueIndices());
1382
+ const maxReturnable = [...requestedIndices].filter(i => availableIndices.has(i)).length;
1383
+
1384
+ const returnedHashes = await Promise.all(response.txs.map(tx => tx.getTxHash().toString()));
1385
+ const uniqueReturned = new Set(returnedHashes.map(h => h.toString()));
1386
+ if (uniqueReturned.size !== returnedHashes.length) {
1387
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1388
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1389
+ }
1390
+ if (response.txs.length > maxReturnable) {
1391
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1392
+ throw new ValidationError(
1393
+ `Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`,
1394
+ );
1395
+ }
1396
+
1397
+ // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1398
+ const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
1399
+ if (proposal) {
1400
+ // Build intersected indices
1401
+ const intersectIdx = request.txIndices.getTrueIndices().filter(i => response.txIndices.isSet(i));
1402
+
1403
+ // Enforce subset membership and preserve increasing order by index.
1404
+ const hashToIndexInProposal = new Map<string, number>(
1405
+ proposal.txHashes.map((h, i) => [h.toString(), i] as [string, number]),
1406
+ );
1407
+ const allowedIndexSet = new Set(intersectIdx);
1408
+ const indices = returnedHashes.map(h => hashToIndexInProposal.get(h));
1409
+ const allAllowed = indices.every(idx => idx !== undefined && allowedIndexSet.has(idx));
1410
+ const strictlyIncreasing = indices.every((idx, i) => (i === 0 ? idx !== undefined : idx! > indices[i - 1]!));
1411
+ if (!allAllowed || !strictlyIncreasing) {
1412
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1413
+ throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
1414
+ }
1415
+ } else {
1416
+ // No local proposal, cannot check the membership/order of the returned txs
1417
+ this.logger.warn(
1418
+ `Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`,
1419
+ );
1420
+ return false;
1421
+ }
1422
+
1423
+ await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
1424
+ return true;
1425
+ } catch (e: any) {
1426
+ if (e instanceof ValidationError) {
1427
+ this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
1428
+ } else {
1429
+ this.logger.error(`Error during validation of requested block txs`, e);
1430
+ }
1431
+
1432
+ return false;
1433
+ }
900
1434
  }
901
1435
 
902
1436
  /**
@@ -909,54 +1443,113 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
909
1443
  * ReqRespSubProtocol.TX subprotocol validation.
910
1444
  *
911
1445
  * @param requestedTxHash - The collection of the txs that was requested.
912
- * @param responseTx - The collectin of txs that was received as a response to the request.
1446
+ * @param responseTx - The collection of txs that was received as a response to the request.
913
1447
  * @param peerId - The peer ID of the peer that sent the tx.
914
1448
  * @returns True if the whole collection of txs is valid, false otherwise.
915
1449
  */
916
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
917
- // I think we should still extract the valid txs and return them, so that we can still use the response.
918
1450
  @trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx) => ({
919
1451
  [Attributes.TX_HASH]: requestedTxHash.toString(),
920
1452
  }))
921
- private async validateRequestedTx(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
1453
+ private async validateRequestedTxs(requestedTxHash: TxHash[], responseTx: Tx[], peerId: PeerId): Promise<boolean> {
922
1454
  const requested = new Set(requestedTxHash.map(h => h.toString()));
1455
+ const requestedTxValidator = this.createRequestedTxValidator();
923
1456
 
924
- const proofValidator = new TxProofValidator(this.proofVerifier);
925
-
1457
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
1458
+ // I think we should still extract the valid txs and return them, so that we can still use the response.
926
1459
  try {
927
- await Promise.all(
928
- responseTx.map(async tx => {
929
- if (!requested.has(tx.getTxHash().toString())) {
930
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
931
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
932
- }
933
-
934
- const { result } = await proofValidator.validateTx(tx);
935
- if (result === 'invalid') {
936
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
937
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
938
- }
939
- }),
940
- );
1460
+ await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
941
1461
  return true;
942
1462
  } catch (e: any) {
943
1463
  if (e instanceof ValidationError) {
944
- this.logger.debug(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
1464
+ this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
945
1465
  } else {
946
- this.logger.warn(`Error during validation of requested txs`, e);
1466
+ this.logger.error(`Error during validation of requested txs`, e);
947
1467
  }
948
1468
 
949
1469
  return false;
950
1470
  }
951
1471
  }
952
1472
 
1473
+ /**
1474
+ * Validates a BLOCK response.
1475
+ *
1476
+ * If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
1477
+ * Penalizes on block number mismatch or hash mismatch.
1478
+ *
1479
+ * @param requestedBlockNumber - The requested block number.
1480
+ * @param responseBlock - The block returned by the peer.
1481
+ * @param peerId - The peer that returned the block.
1482
+ * @returns True if the response is valid, false otherwise.
1483
+ */
1484
+ @trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock) => ({
1485
+ [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString(),
1486
+ }))
1487
+ protected async validateRequestedBlock(
1488
+ requestedBlockNumber: Fr,
1489
+ responseBlock: L2Block,
1490
+ peerId: PeerId,
1491
+ ): Promise<boolean> {
1492
+ try {
1493
+ const reqNum = Number(requestedBlockNumber.toString());
1494
+ if (responseBlock.number !== reqNum) {
1495
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1496
+ return false;
1497
+ }
1498
+
1499
+ const local = await this.archiver.getBlock(BlockNumber(reqNum));
1500
+ if (!local) {
1501
+ // We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
1502
+ // TODO: Consider extending this validator to accept an expected hash or
1503
+ // performing quorum-based checks when using P2P syncing prior to L1 sync.
1504
+ this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
1505
+ return false;
1506
+ }
1507
+ const [localHash, respHash] = await Promise.all([local.hash(), responseBlock.hash()]);
1508
+ if (!localHash.equals(respHash)) {
1509
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1510
+ return false;
1511
+ }
1512
+
1513
+ return true;
1514
+ } catch (e) {
1515
+ this.logger.warn(`Error validating requested block`, e);
1516
+ return false;
1517
+ }
1518
+ }
1519
+
1520
+ protected async validateRequestedTx(
1521
+ tx: Tx,
1522
+ peerId: PeerId,
1523
+ txValidator: TxValidator,
1524
+ requested?: Set<`0x${string}`>,
1525
+ ) {
1526
+ const penalize = (severity: PeerErrorSeverity) => this.peerManager.penalizePeer(peerId, severity);
1527
+ if (requested && !requested.has(tx.getTxHash().toString())) {
1528
+ penalize(PeerErrorSeverity.MidToleranceError);
1529
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
1530
+ }
1531
+
1532
+ const { result } = await txValidator.validateTx(tx);
1533
+ if (result === 'invalid') {
1534
+ penalize(PeerErrorSeverity.LowToleranceError);
1535
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
1536
+ }
1537
+ }
1538
+
1539
+ protected createRequestedTxValidator(): TxValidator {
1540
+ return createTxReqRespValidator(this.proofVerifier, {
1541
+ l1ChainId: this.config.l1ChainId,
1542
+ rollupVersion: this.config.rollupVersion,
1543
+ });
1544
+ }
1545
+
953
1546
  @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
954
1547
  [Attributes.TX_HASH]: tx.getTxHash().toString(),
955
1548
  }))
956
- private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
1549
+ protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
957
1550
  const currentBlockNumber = await this.archiver.getBlockNumber();
958
1551
 
959
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1552
+ // We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
960
1553
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
961
1554
  const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
962
1555
 
@@ -971,7 +1564,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
971
1564
 
972
1565
  // Double spend validator has a special case handler
973
1566
  if (name === 'doubleSpendValidator') {
974
- const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
1567
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
975
1568
  severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
976
1569
  }
977
1570
 
@@ -981,7 +1574,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
981
1574
  return true;
982
1575
  }
983
1576
 
984
- private async getGasFees(blockNumber: number): Promise<GasFees> {
1577
+ private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
985
1578
  if (blockNumber === this.feesCache?.blockNumber) {
986
1579
  return this.feesCache.gasFees;
987
1580
  }
@@ -992,10 +1585,26 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
992
1585
  return gasFees;
993
1586
  }
994
1587
 
1588
+ /**
1589
+ * Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
1590
+ */
1591
+ public getBatchTxRequesterService(): BatchTxRequesterLibP2PService {
1592
+ return {
1593
+ reqResp: this.reqresp,
1594
+ connectionSampler: this.reqresp.getConnectionSampler(),
1595
+ txValidatorConfig: {
1596
+ l1ChainId: this.config.l1ChainId,
1597
+ rollupVersion: this.config.rollupVersion,
1598
+ proofVerifier: this.proofVerifier,
1599
+ },
1600
+ peerScoring: this.peerManager,
1601
+ };
1602
+ }
1603
+
995
1604
  public async validate(txs: Tx[]): Promise<void> {
996
1605
  const currentBlockNumber = await this.archiver.getBlockNumber();
997
1606
 
998
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1607
+ // We accept transactions if they are not expired by the next slot (checked based on the ExpirationTimestamp field)
999
1608
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1000
1609
  const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1001
1610
 
@@ -1022,13 +1631,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1022
1631
  * @returns The message validators.
1023
1632
  */
1024
1633
  private async createMessageValidators(
1025
- currentBlockNumber: number,
1634
+ currentBlockNumber: BlockNumber,
1026
1635
  nextSlotTimestamp: UInt64,
1027
1636
  ): Promise<Record<string, MessageValidator>[]> {
1028
1637
  const gasFees = await this.getGasFees(currentBlockNumber);
1029
1638
  const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1030
1639
 
1031
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
1640
+ const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1032
1641
 
1033
1642
  return createTxMessageValidators(
1034
1643
  nextSlotTimestamp,
@@ -1037,11 +1646,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1037
1646
  gasFees,
1038
1647
  this.config.l1ChainId,
1039
1648
  this.config.rollupVersion,
1040
- protocolContractTreeRoot,
1649
+ protocolContractsHash,
1041
1650
  this.archiver,
1042
1651
  this.proofVerifier,
1043
1652
  !this.config.disableTransactions,
1044
1653
  allowedInSetup,
1654
+ this.logger.getBindings(),
1045
1655
  );
1046
1656
  }
1047
1657
 
@@ -1090,20 +1700,23 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1090
1700
  * @param peerId - The peer ID of the peer that sent the tx.
1091
1701
  * @returns Severity
1092
1702
  */
1093
- private async handleDoubleSpendFailure(tx: Tx, blockNumber: number): Promise<PeerErrorSeverity> {
1703
+ private async handleDoubleSpendFailure(tx: Tx, blockNumber: BlockNumber): Promise<PeerErrorSeverity> {
1094
1704
  if (blockNumber <= this.config.doubleSpendSeverePeerPenaltyWindow) {
1095
1705
  return PeerErrorSeverity.HighToleranceError;
1096
1706
  }
1097
1707
 
1098
- const snapshotValidator = new DoubleSpendTxValidator({
1099
- nullifiersExist: async (nullifiers: Buffer[]) => {
1100
- const merkleTree = this.worldStateSynchronizer.getSnapshot(
1101
- blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow,
1102
- );
1103
- const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1104
- return indices.map(index => index !== undefined);
1708
+ const snapshotValidator = new DoubleSpendTxValidator(
1709
+ {
1710
+ nullifiersExist: async (nullifiers: Buffer[]) => {
1711
+ const merkleTree = this.worldStateSynchronizer.getSnapshot(
1712
+ BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow),
1713
+ );
1714
+ const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1715
+ return indices.map(index => index !== undefined);
1716
+ },
1105
1717
  },
1106
- });
1718
+ this.logger.getBindings(),
1719
+ );
1107
1720
 
1108
1721
  const validSnapshot = await snapshotValidator.validateTx(tx);
1109
1722
  if (validSnapshot.result !== 'valid') {
@@ -1114,44 +1727,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1114
1727
  }
1115
1728
 
1116
1729
  /**
1117
- * Validate an attestation.
1730
+ * Validate a checkpoint attestation.
1118
1731
  *
1119
- * @param attestation - The attestation to validate.
1120
- * @returns True if the attestation is valid, false otherwise.
1732
+ * @param attestation - The checkpoint attestation to validate.
1733
+ * @returns True if the checkpoint attestation is valid, false otherwise.
1121
1734
  */
1122
- @trackSpan('Libp2pService.validateAttestation', async (_, attestation) => ({
1123
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
1735
+ @trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
1736
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1124
1737
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1125
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
1738
+ [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1126
1739
  }))
1127
- public async validateAttestation(peerId: PeerId, attestation: BlockAttestation): Promise<boolean> {
1128
- const severity = await this.attestationValidator.validate(attestation);
1129
- if (severity) {
1130
- this.peerManager.penalizePeer(peerId, severity);
1131
- return false;
1132
- }
1133
-
1134
- return true;
1135
- }
1740
+ public async validateCheckpointAttestation(
1741
+ peerId: PeerId,
1742
+ attestation: CheckpointAttestation,
1743
+ ): Promise<P2PValidationResult> {
1744
+ const result = await this.checkpointAttestationValidator.validate(attestation);
1136
1745
 
1137
- /**
1138
- * Validate a block proposal.
1139
- *
1140
- * @param block - The block proposal to validate.
1141
- * @returns True if the block proposal is valid, false otherwise.
1142
- */
1143
- @trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
1144
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
1145
- }))
1146
- public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
1147
- const severity = await this.blockProposalValidator.validate(block);
1148
- if (severity) {
1149
- this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
1150
- this.peerManager.penalizePeer(peerId, severity);
1151
- return false;
1746
+ if (result.result === 'reject') {
1747
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1748
+ this.peerManager.penalizePeer(peerId, result.severity);
1152
1749
  }
1153
1750
 
1154
- return true;
1751
+ return result;
1155
1752
  }
1156
1753
 
1157
1754
  public getPeerScore(peerId: PeerId): number {
@@ -1165,7 +1762,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1165
1762
  private async sendToPeers<T extends Gossipable>(message: T) {
1166
1763
  const parent = message.constructor as typeof Gossipable;
1167
1764
 
1168
- const identifier = await message.p2pMessageIdentifier().then(i => i.toString());
1765
+ const identifier = await message.p2pMessageLoggingIdentifier().then(i => i.toString());
1169
1766
  this.logger.trace(`Sending message ${identifier}`, { p2pMessageIdentifier: identifier });
1170
1767
 
1171
1768
  const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);