@aztec/p2p 0.0.1-fake-c83136db25 → 0.0.2-commit.217f559981

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 (597) 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 +53 -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 -64
  20. package/dest/config.d.ts.map +1 -1
  21. package/dest/config.js +42 -21
  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 +117 -45
  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 +530 -257
  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 +34 -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 +320 -335
  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 +17 -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 +78 -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 +211 -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 +9 -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 +896 -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 +4 -3
  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 +22 -12
  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 +2 -1
  210. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  211. package/dest/msg_validators/tx_validator/index.js +1 -0
  212. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +4 -3
  213. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  214. package/dest/msg_validators/tx_validator/metadata_validator.js +2 -2
  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 +23 -5
  224. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  225. package/dest/msg_validators/tx_validator/timestamp_validator.js +8 -8
  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 +25 -4
  242. package/dest/services/encoding.d.ts.map +1 -1
  243. package/dest/services/encoding.js +76 -6
  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 +116 -92
  260. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  261. package/dest/services/libp2p/libp2p_service.js +1153 -267
  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 +472 -51
  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 +26 -29
  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 +19 -2
  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 +2 -2
  411. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
  412. package/dest/test-helpers/mock-tx-helpers.js +1 -1
  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 -120
  425. package/dest/testbench/parse_log_file.d.ts +1 -1
  426. package/dest/testbench/testbench.d.ts +1 -1
  427. package/dest/testbench/worker_client_manager.d.ts +51 -6
  428. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  429. package/dest/testbench/worker_client_manager.js +226 -39
  430. package/dest/types/index.d.ts +1 -1
  431. package/dest/util.d.ts +3 -2
  432. package/dest/util.d.ts.map +1 -1
  433. package/dest/util.js +11 -2
  434. package/dest/versioning.d.ts +1 -1
  435. package/package.json +19 -18
  436. package/src/bootstrap/bootstrap.ts +7 -4
  437. package/src/client/factory.ts +98 -31
  438. package/src/client/interface.ts +77 -23
  439. package/src/client/p2p_client.ts +291 -309
  440. package/src/client/test/tx_proposal_collector/README.md +227 -0
  441. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +346 -0
  442. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
  443. package/src/config.ts +77 -30
  444. package/src/errors/attestation-pool.error.ts +13 -0
  445. package/src/errors/tx-pool.error.ts +12 -0
  446. package/src/index.ts +1 -0
  447. package/src/mem_pools/attestation_pool/attestation_pool.ts +518 -45
  448. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +618 -276
  449. package/src/mem_pools/attestation_pool/index.ts +9 -2
  450. package/src/mem_pools/attestation_pool/mocks.ts +22 -15
  451. package/src/mem_pools/index.ts +4 -1
  452. package/src/mem_pools/instrumentation.ts +48 -10
  453. package/src/mem_pools/interface.ts +5 -7
  454. package/src/mem_pools/tx_pool/README.md +270 -0
  455. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +372 -371
  456. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
  457. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
  458. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
  459. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  460. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
  461. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  462. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  463. package/src/mem_pools/tx_pool/index.ts +0 -1
  464. package/src/mem_pools/tx_pool/priority.ts +8 -1
  465. package/src/mem_pools/tx_pool/tx_pool.ts +18 -5
  466. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +23 -17
  467. package/src/mem_pools/tx_pool_v2/README.md +275 -0
  468. package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
  469. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +120 -0
  470. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  471. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +160 -0
  472. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +121 -0
  473. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +122 -0
  474. package/src/mem_pools/tx_pool_v2/eviction/index.ts +27 -0
  475. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +209 -0
  476. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
  477. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
  478. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +91 -0
  479. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +90 -0
  480. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +31 -0
  481. package/src/mem_pools/tx_pool_v2/index.ts +12 -0
  482. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  483. package/src/mem_pools/tx_pool_v2/interfaces.ts +242 -0
  484. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +242 -0
  485. package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
  486. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +444 -0
  487. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +223 -0
  488. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1069 -0
  489. package/src/msg_validators/attestation_validator/attestation_validator.ts +45 -32
  490. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +94 -0
  491. package/src/msg_validators/attestation_validator/index.ts +1 -0
  492. package/src/msg_validators/clock_tolerance.ts +51 -0
  493. package/src/msg_validators/index.ts +1 -1
  494. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
  495. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
  496. package/src/msg_validators/proposal_validator/index.ts +3 -0
  497. package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
  498. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
  499. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +2 -2
  500. package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
  501. package/src/msg_validators/tx_validator/block_header_validator.ts +21 -8
  502. package/src/msg_validators/tx_validator/data_validator.ts +18 -6
  503. package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
  504. package/src/msg_validators/tx_validator/factory.ts +67 -25
  505. package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
  506. package/src/msg_validators/tx_validator/gas_validator.ts +17 -28
  507. package/src/msg_validators/tx_validator/index.ts +1 -0
  508. package/src/msg_validators/tx_validator/metadata_validator.ts +19 -8
  509. package/src/msg_validators/tx_validator/phases_validator.ts +8 -4
  510. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  511. package/src/msg_validators/tx_validator/test_utils.ts +1 -1
  512. package/src/msg_validators/tx_validator/timestamp_validator.ts +30 -19
  513. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
  514. package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
  515. package/src/services/data_store.ts +10 -7
  516. package/src/services/discv5/discV5_service.ts +1 -1
  517. package/src/services/dummy_service.ts +68 -1
  518. package/src/services/encoding.ts +83 -6
  519. package/src/services/gossipsub/README.md +641 -0
  520. package/src/services/gossipsub/index.ts +2 -0
  521. package/src/services/gossipsub/scoring.ts +29 -5
  522. package/src/services/gossipsub/topic_score_params.ts +487 -0
  523. package/src/services/index.ts +1 -0
  524. package/src/services/libp2p/instrumentation.ts +39 -71
  525. package/src/services/libp2p/libp2p_service.ts +865 -277
  526. package/src/services/peer-manager/metrics.ts +44 -16
  527. package/src/services/peer-manager/peer_manager.ts +7 -4
  528. package/src/services/peer-manager/peer_scoring.ts +70 -3
  529. package/src/services/reqresp/batch-tx-requester/README.md +305 -0
  530. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
  531. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  532. package/src/services/reqresp/batch-tx-requester/interface.ts +53 -0
  533. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +161 -0
  534. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
  535. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
  536. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
  537. package/src/services/reqresp/connection-sampler/connection_sampler.ts +19 -1
  538. package/src/services/reqresp/constants.ts +14 -0
  539. package/src/services/reqresp/interface.ts +30 -2
  540. package/src/services/reqresp/metrics.ts +36 -27
  541. package/src/services/reqresp/protocols/auth.ts +2 -2
  542. package/src/services/reqresp/protocols/block.ts +3 -2
  543. package/src/services/reqresp/protocols/block_txs/bitvector.ts +16 -0
  544. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +35 -12
  545. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +75 -10
  546. package/src/services/reqresp/protocols/status.ts +16 -12
  547. package/src/services/reqresp/protocols/tx.ts +23 -2
  548. package/src/services/reqresp/reqresp.ts +80 -23
  549. package/src/services/service.ts +72 -4
  550. package/src/services/tx_collection/config.ts +84 -2
  551. package/src/services/tx_collection/fast_tx_collection.ts +96 -49
  552. package/src/services/tx_collection/file_store_tx_collection.ts +202 -0
  553. package/src/services/tx_collection/file_store_tx_source.ts +117 -0
  554. package/src/services/tx_collection/index.ts +6 -0
  555. package/src/services/tx_collection/instrumentation.ts +11 -13
  556. package/src/services/tx_collection/missing_txs_tracker.ts +52 -0
  557. package/src/services/tx_collection/proposal_tx_collector.ts +113 -0
  558. package/src/services/tx_collection/slow_tx_collection.ts +70 -36
  559. package/src/services/tx_collection/tx_collection.ts +122 -24
  560. package/src/services/tx_collection/tx_collection_sink.ts +30 -34
  561. package/src/services/tx_collection/tx_source.ts +22 -3
  562. package/src/services/tx_file_store/config.ts +37 -0
  563. package/src/services/tx_file_store/index.ts +3 -0
  564. package/src/services/tx_file_store/instrumentation.ts +36 -0
  565. package/src/services/tx_file_store/tx_file_store.ts +175 -0
  566. package/src/services/tx_provider.ts +27 -10
  567. package/src/services/tx_provider_instrumentation.ts +24 -14
  568. package/src/test-helpers/index.ts +2 -0
  569. package/src/test-helpers/make-test-p2p-clients.ts +3 -3
  570. package/src/test-helpers/mock-pubsub.ts +144 -4
  571. package/src/test-helpers/mock-tx-helpers.ts +1 -1
  572. package/src/test-helpers/reqresp-nodes.ts +3 -2
  573. package/src/test-helpers/test_tx_provider.ts +64 -0
  574. package/src/test-helpers/testbench-utils.ts +430 -0
  575. package/src/testbench/p2p_client_testbench_worker.ts +349 -117
  576. package/src/testbench/worker_client_manager.ts +304 -42
  577. package/src/util.ts +19 -3
  578. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -28
  579. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
  580. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -174
  581. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -23
  582. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
  583. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -175
  584. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -79
  585. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  586. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -232
  587. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
  588. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  589. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -70
  590. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  591. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  592. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  593. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -235
  594. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -225
  595. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -278
  596. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -81
  597. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
@@ -1,23 +1,24 @@
1
1
  import type { EpochCacheInterface } from '@aztec/epoch-cache';
2
- import { randomInt } from '@aztec/foundation/crypto';
3
- import { Fr } from '@aztec/foundation/fields';
2
+ import { BlockNumber, type SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { Fr } from '@aztec/foundation/curves/bn254';
4
4
  import { type Logger, createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
5
- import { SerialQueue } from '@aztec/foundation/queue';
6
5
  import { RunningPromise } from '@aztec/foundation/running-promise';
7
6
  import { Timer } from '@aztec/foundation/timer';
8
7
  import type { AztecAsyncKVStore } from '@aztec/kv-store';
9
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
10
8
  import { protocolContractsHash } from '@aztec/protocol-contracts';
11
- import type { EthAddress, L2BlockSource } from '@aztec/stdlib/block';
9
+ import type { EthAddress, L2Block, L2BlockSource } from '@aztec/stdlib/block';
12
10
  import type { ContractDataSource } from '@aztec/stdlib/contract';
13
11
  import { GasFees } from '@aztec/stdlib/gas';
14
12
  import type { ClientProtocolCircuitVerifier, PeerInfo, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
15
13
  import {
16
- BlockAttestation,
17
14
  BlockProposal,
15
+ CheckpointAttestation,
16
+ CheckpointProposal,
17
+ type CheckpointProposalCore,
18
18
  type Gossipable,
19
19
  P2PClientType,
20
20
  P2PMessage,
21
+ type ValidationResult as P2PValidationResult,
21
22
  PeerErrorSeverity,
22
23
  TopicType,
23
24
  createTopicString,
@@ -28,7 +29,14 @@ import { MerkleTreeId } from '@aztec/stdlib/trees';
28
29
  import { Tx, type TxHash, type TxValidationResult, type TxValidator } from '@aztec/stdlib/tx';
29
30
  import type { UInt64 } from '@aztec/stdlib/types';
30
31
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
31
- 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';
32
40
 
33
41
  import {
34
42
  type GossipSub,
@@ -36,7 +44,7 @@ import {
36
44
  type GossipsubMessage,
37
45
  gossipsub,
38
46
  } from '@chainsafe/libp2p-gossipsub';
39
- import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
47
+ import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
40
48
  import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
41
49
  import { noise } from '@chainsafe/libp2p-noise';
42
50
  import { yamux } from '@chainsafe/libp2p-yamux';
@@ -51,52 +59,64 @@ import { createLibp2p } from 'libp2p';
51
59
 
52
60
  import type { P2PConfig } from '../../config.js';
53
61
  import type { MemPools } from '../../mem_pools/interface.js';
54
- import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
55
- import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
56
- import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
57
- import { type MessageValidator, createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
58
62
  import {
59
- AggregateTxValidator,
60
- DataTxValidator,
63
+ BlockProposalValidator,
64
+ CheckpointAttestationValidator,
65
+ CheckpointProposalValidator,
61
66
  DoubleSpendTxValidator,
62
- MetadataTxValidator,
63
- TxProofValidator,
64
- } from '../../msg_validators/tx_validator/index.js';
67
+ FishermanAttestationValidator,
68
+ getDefaultAllowedSetupFunctions,
69
+ } from '../../msg_validators/index.js';
70
+ import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
71
+ import {
72
+ type MessageValidator,
73
+ createTxMessageValidators,
74
+ createTxReqRespValidator,
75
+ } from '../../msg_validators/tx_validator/factory.js';
65
76
  import { GossipSubEvent } from '../../types/index.js';
66
77
  import { type PubSubLibp2p, convertToMultiaddr } from '../../util.js';
67
78
  import { getVersions } from '../../versioning.js';
68
79
  import { AztecDatastore } from '../data_store.js';
69
80
  import { DiscV5Service } from '../discv5/discV5_service.js';
70
81
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
71
- 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';
72
84
  import type { PeerManagerInterface } from '../peer-manager/interface.js';
73
85
  import { PeerManager } from '../peer-manager/peer_manager.js';
74
86
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
87
+ import type { BatchTxRequesterLibP2PService } from '../reqresp/batch-tx-requester/interface.js';
75
88
  import type { P2PReqRespConfig } from '../reqresp/config.js';
76
89
  import {
77
90
  DEFAULT_SUB_PROTOCOL_VALIDATORS,
78
91
  type ReqRespInterface,
92
+ type ReqRespResponse,
79
93
  ReqRespSubProtocol,
80
94
  type ReqRespSubProtocolHandler,
81
95
  type ReqRespSubProtocolHandlers,
82
96
  type ReqRespSubProtocolValidators,
83
97
  type SubProtocolMap,
84
98
  ValidationError,
85
- } from '../reqresp/interface.js';
86
- import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
87
- import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
99
+ } from '../reqresp/index.js';
88
100
  import {
89
101
  AuthRequest,
90
102
  BlockTxsRequest,
91
103
  BlockTxsResponse,
92
104
  StatusMessage,
93
105
  pingHandler,
106
+ reqGoodbyeHandler,
94
107
  reqRespBlockHandler,
108
+ reqRespBlockTxsHandler,
95
109
  reqRespStatusHandler,
96
110
  reqRespTxHandler,
97
- } from '../reqresp/protocols/index.js';
111
+ } from '../reqresp/index.js';
98
112
  import { ReqResp } from '../reqresp/reqresp.js';
99
- 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';
100
120
  import { P2PInstrumentation } from './instrumentation.js';
101
121
 
102
122
  interface ValidationResult {
@@ -107,22 +127,37 @@ interface ValidationResult {
107
127
 
108
128
  type ValidationOutcome = { allPassed: true } | { allPassed: false; failure: ValidationResult };
109
129
 
130
+ // REFACTOR: Unify with the type above
131
+ type ReceivedMessageValidationResult<T, M = undefined> =
132
+ | { obj: T; result: Exclude<TopicValidatorResult, TopicValidatorResult.Reject>; metadata?: M }
133
+ | { obj?: T; result: TopicValidatorResult.Reject; metadata?: M };
134
+
110
135
  /**
111
136
  * Lib P2P implementation of the P2PService interface.
112
137
  */
113
138
  export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends WithTracer implements P2PService {
114
- private jobQueue: SerialQueue = new SerialQueue();
115
139
  private discoveryRunningPromise?: RunningPromise;
116
140
  private msgIdSeenValidators: Record<TopicType, MessageSeenValidator> = {} as Record<TopicType, MessageSeenValidator>;
117
141
 
118
142
  // Message validators
119
- private attestationValidator: AttestationValidator;
120
143
  private blockProposalValidator: BlockProposalValidator;
144
+ private checkpointProposalValidator: CheckpointProposalValidator;
145
+ private checkpointAttestationValidator: CheckpointAttestationValidator;
121
146
 
122
147
  private protocolVersion = '';
123
148
  private topicStrings: Record<TopicType, string> = {} as Record<TopicType, string>;
124
149
 
125
- 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;
126
161
 
127
162
  /**
128
163
  * Callback for when a block is received from a peer.
@@ -131,32 +166,48 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
131
166
  */
132
167
  private blockReceivedCallback: P2PBlockReceivedCallback;
133
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
+
134
176
  private gossipSubEventHandler: (e: CustomEvent<GossipsubMessage>) => void;
135
177
 
136
178
  private instrumentation: P2PInstrumentation;
137
179
 
180
+ private telemetry: TelemetryClient;
181
+
182
+ protected logger: Logger;
183
+
138
184
  constructor(
139
185
  private clientType: T,
140
186
  private config: P2PConfig,
141
187
  protected node: PubSubLibp2p,
142
188
  private peerDiscoveryService: PeerDiscoveryService,
143
189
  private reqresp: ReqRespInterface,
144
- private peerManager: PeerManagerInterface,
145
- protected mempools: MemPools<T>,
146
- private archiver: L2BlockSource & ContractDataSource,
190
+ protected peerManager: PeerManagerInterface,
191
+ protected mempools: MemPools,
192
+ protected archiver: L2BlockSource & ContractDataSource,
147
193
  private epochCache: EpochCacheInterface,
148
194
  private proofVerifier: ClientProtocolCircuitVerifier,
149
195
  private worldStateSynchronizer: WorldStateSynchronizer,
150
196
  telemetry: TelemetryClient,
151
- protected logger = createLogger('p2p:libp2p_service'),
197
+ logger: Logger = createLogger('p2p:libp2p_service'),
152
198
  ) {
153
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;
154
204
 
155
205
  this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
156
206
 
157
207
  this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
158
208
  this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
159
- 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);
160
211
 
161
212
  const versions = getVersions(config);
162
213
  this.protocolVersion = compressComponentVersions(versions);
@@ -164,22 +215,40 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
164
215
 
165
216
  this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
166
217
  this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
167
- this.topicStrings[TopicType.block_attestation] = createTopicString(
168
- 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,
169
224
  this.protocolVersion,
170
225
  );
171
226
 
172
- this.attestationValidator = new AttestationValidator(epochCache);
173
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);
174
234
 
175
235
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
176
236
 
177
- this.blockReceivedCallback = async (block: BlockProposal): Promise<BlockAttestation[] | undefined> => {
237
+ this.blockReceivedCallback = async (block: BlockProposal): Promise<boolean> => {
178
238
  this.logger.debug(
179
- `Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`,
180
- { 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() },
181
241
  );
182
- 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);
183
252
  };
184
253
  }
185
254
 
@@ -198,7 +267,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
198
267
  config: P2PConfig,
199
268
  peerId: PeerId,
200
269
  deps: {
201
- mempools: MemPools<T>;
270
+ mempools: MemPools;
202
271
  l2BlockSource: L2BlockSource & ContractDataSource;
203
272
  epochCache: EpochCacheInterface;
204
273
  proofVerifier: ClientProtocolCircuitVerifier;
@@ -225,14 +294,14 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
225
294
 
226
295
  const datastore = new AztecDatastore(peerStore);
227
296
 
228
- const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
297
+ const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
229
298
 
230
299
  const peerDiscoveryService = new DiscV5Service(
231
300
  peerId,
232
301
  config,
233
302
  packageVersion,
234
303
  telemetry,
235
- createLogger(`${logger.module}:discv5_service`),
304
+ createLogger(`${logger.module}:discv5_service`, logger.getBindings()),
236
305
  );
237
306
 
238
307
  // Seed libp2p's bootstrap discovery with private and trusted peers
@@ -246,10 +315,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
246
315
  const versions = getVersions(config);
247
316
  const protocolVersion = compressComponentVersions(versions);
248
317
 
249
- const txTopic = createTopicString(TopicType.tx, protocolVersion);
250
- const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
251
- const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
252
-
253
318
  const preferredPeersEnrs: ENR[] = config.preferredPeers.map(enr => ENR.decodeTxt(enr));
254
319
  const directPeers = (
255
320
  await Promise.all(
@@ -269,6 +334,16 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
269
334
 
270
335
  const announceTcpMultiaddr = config.p2pIp ? [convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')] : [];
271
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
+
272
347
  const node = await createLibp2p({
273
348
  start: false,
274
349
  peerId,
@@ -364,33 +439,17 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
364
439
  scoreParams: createPeerScoreParams({
365
440
  // IPColocation factor can be disabled for local testing - default to -5
366
441
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
367
- topics: {
368
- [txTopic]: createTopicScoreParams({
369
- topicWeight: 1,
370
- invalidMessageDeliveriesWeight: -20,
371
- invalidMessageDeliveriesDecay: 0.5,
372
- }),
373
- [blockAttestationTopic]: createTopicScoreParams({
374
- topicWeight: 1,
375
- invalidMessageDeliveriesWeight: -20,
376
- invalidMessageDeliveriesDecay: 0.5,
377
- }),
378
- [blockProposalTopic]: createTopicScoreParams({
379
- topicWeight: 1,
380
- invalidMessageDeliveriesWeight: -20,
381
- invalidMessageDeliveriesDecay: 0.5,
382
- }),
383
- },
442
+ topics: topicScoreParams,
384
443
  }),
385
444
  }) as (components: GossipSubComponents) => GossipSub,
386
445
  components: (components: { connectionManager: ConnectionManager }) => ({
387
446
  connectionManager: components.connectionManager,
388
447
  }),
389
448
  },
390
- logger: createLibp2pComponentLogger(logger.module),
449
+ logger: createLibp2pComponentLogger(logger.module, logger.getBindings()),
391
450
  });
392
451
 
393
- const peerScoring = new PeerScoring(config);
452
+ const peerScoring = new PeerScoring(config, telemetry);
394
453
  const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
395
454
 
396
455
  const peerManager = new PeerManager(
@@ -406,8 +465,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
406
465
  epochCache,
407
466
  );
408
467
 
409
- // Update gossipsub score params
410
- 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;
411
474
  node.services.pubsub.score.params.appSpecificScore = (peerId: string) =>
412
475
  peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
413
476
 
@@ -445,20 +508,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
445
508
  }
446
509
  const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
447
510
 
448
- // Start job queue, peer discovery service and libp2p node
449
- this.jobQueue.start();
450
-
451
- await this.peerManager.initializePeers();
452
- if (!this.config.p2pDiscoveryDisabled) {
453
- await this.peerDiscoveryService.start();
454
- }
455
- await this.node.start();
456
-
457
- // Subscribe to standard GossipSub topics by default
458
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)) {
459
- this.subscribeToTopic(this.topicStrings[topic]);
460
- }
461
-
462
511
  // Create request response protocol handlers
463
512
  const txHandler = reqRespTxHandler(this.mempools);
464
513
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
@@ -472,9 +521,12 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
472
521
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this),
473
522
  };
474
523
 
475
- // Only handle block transactions request if attestation pool is available to the client
476
- if (this.mempools.attestationPool) {
477
- 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
+ );
478
530
  requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
479
531
  }
480
532
 
@@ -482,25 +534,41 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
482
534
  requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
483
535
  }
484
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
+
485
556
  // add GossipSub listener
486
557
  this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
487
558
 
488
- // 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
+ }
489
563
  this.discoveryRunningPromise = new RunningPromise(
490
- () => this.peerManager.heartbeat(),
564
+ async () => {
565
+ await this.peerManager.heartbeat();
566
+ },
491
567
  this.logger,
492
568
  this.config.peerCheckIntervalMS,
493
569
  );
494
570
  this.discoveryRunningPromise.start();
495
571
 
496
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
497
- const reqrespSubProtocolValidators = {
498
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
499
- // TODO(#11336): A request validator for blocks
500
- [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
501
- [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
502
- };
503
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
504
572
  this.logger.info(`Started P2P service`, {
505
573
  listen: this.config.listenAddress,
506
574
  port: this.config.p2pPort,
@@ -520,9 +588,6 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
520
588
  // Stop peer manager
521
589
  this.logger.debug('Stopping peer manager...');
522
590
  await this.peerManager.stop();
523
-
524
- this.logger.debug('Stopping job queue...');
525
- await this.jobQueue.end();
526
591
  this.logger.debug('Stopping running promise...');
527
592
  await this.discoveryRunningPromise?.stop();
528
593
  this.logger.debug('Stopping peer discovery service...');
@@ -550,6 +615,10 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
550
615
  return this.peerManager.getPeers(includePending);
551
616
  }
552
617
 
618
+ public getGossipMeshPeerCount(topicType: TopicType): number {
619
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
620
+ }
621
+
553
622
  private handleGossipSubEvent(e: CustomEvent<GossipsubMessage>) {
554
623
  this.logger.trace(`Received PUBSUB message.`);
555
624
 
@@ -577,6 +646,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
577
646
  return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
578
647
  }
579
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
+
580
658
  /**
581
659
  * Get the ENR of the node
582
660
  * @returns The ENR of the node
@@ -589,6 +667,29 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
589
667
  this.blockReceivedCallback = callback;
590
668
  }
591
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
+
592
693
  /**
593
694
  * Subscribes to a topic.
594
695
  * @param topic - The topic to subscribe to.
@@ -610,11 +711,19 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
610
711
  if (!this.node.services.pubsub) {
611
712
  throw new Error('Pubsub service not available.');
612
713
  }
613
- 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);
614
718
  const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
615
719
  return result.recipients.length;
616
720
  }
617
721
 
722
+ /**
723
+ * Checks if this message has already been seen, based on its msgId computed from hashing the message data.
724
+ * Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
725
+ * messages to avoid tx echoes across the network.
726
+ */
618
727
  protected preValidateReceivedMessage(
619
728
  msg: Message,
620
729
  msgId: string,
@@ -626,12 +735,15 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
626
735
  case this.topicStrings[TopicType.tx]:
627
736
  topicType = TopicType.tx;
628
737
  break;
629
- case this.topicStrings[TopicType.block_attestation]:
630
- topicType = TopicType.block_attestation;
631
- break;
632
738
  case this.topicStrings[TopicType.block_proposal]:
633
739
  topicType = TopicType.block_proposal;
634
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;
635
747
  default:
636
748
  this.logger.error(`Received message on unknown topic: ${msg.topic}`);
637
749
  break;
@@ -650,13 +762,39 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
650
762
  return { result: true, topicType };
651
763
  }
652
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
+
653
786
  /**
654
787
  * Handles a new gossip message that was received by the client.
655
788
  * @param topic - The message's topic.
656
789
  * @param data - The message data
657
790
  */
658
791
  protected async handleNewGossipMessage(msg: Message, msgId: string, source: PeerId) {
659
- 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
+ }
660
798
 
661
799
  const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
662
800
 
@@ -664,56 +802,147 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
664
802
  return;
665
803
  }
666
804
 
805
+ // Determine topic type for attributes
667
806
  if (msg.topic === this.topicStrings[TopicType.tx]) {
668
- 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;
669
814
  }
670
- if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
671
- 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();
672
870
  }
673
- if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
674
- await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
871
+
872
+ if (latency !== undefined && topicType !== undefined) {
873
+ this.instrumentation.recordMessageLatency(topicType, latency);
675
874
  }
676
875
 
677
876
  return;
678
877
  }
679
878
 
680
- protected async validateReceivedMessage<T>(
681
- validationFunc: () => Promise<{ result: boolean; obj: T }>,
879
+ protected async validateReceivedMessage<T, M = undefined>(
880
+ validationFunc: () => Promise<ReceivedMessageValidationResult<T, M>>,
682
881
  msgId: string,
683
882
  source: PeerId,
684
883
  topicType: TopicType,
685
- ): Promise<{ result: boolean; obj: T | undefined }> {
686
- let resultAndObj: { result: boolean; obj: T | undefined } = { result: false, obj: undefined };
884
+ ): Promise<ReceivedMessageValidationResult<T, M>> {
885
+ let resultAndObj: ReceivedMessageValidationResult<T, M> = { result: TopicValidatorResult.Reject };
687
886
  const timer = new Timer();
688
887
  try {
689
888
  resultAndObj = await validationFunc();
690
889
  } catch (err) {
691
- this.logger.error(`Error deserializing and validating message `, err);
890
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
891
+ this.logger.error(`Error deserializing and validating gossipsub message`, err, {
892
+ msgId,
893
+ source: source.toString(),
894
+ topicType,
895
+ });
692
896
  }
693
897
 
694
- if (resultAndObj.result) {
898
+ if (resultAndObj.result === TopicValidatorResult.Accept) {
695
899
  this.instrumentation.recordMessageValidation(topicType, timer);
696
900
  }
697
901
 
698
- this.node.services.pubsub.reportMessageValidationResult(
699
- msgId,
700
- source.toString(),
701
- resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject,
702
- );
902
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
703
903
  return resultAndObj;
704
904
  }
705
905
 
706
906
  protected async handleGossipedTx(payloadData: Buffer, msgId: string, source: PeerId) {
707
- const validationFunc = async () => {
907
+ const validationFunc: () => Promise<ReceivedMessageValidationResult<Tx>> = async () => {
708
908
  const tx = Tx.fromBuffer(payloadData);
709
- const result = await this.validatePropagatedTx(tx, source);
710
- return { result, obj: tx };
909
+ const isValid = await this.validatePropagatedTx(tx, source);
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));
923
+
924
+ this.logger.trace(`Validate propagated tx`, {
925
+ isValid,
926
+ wasAccepted,
927
+ wasIgnored,
928
+ [Attributes.P2P_ID]: source.toString(),
929
+ });
930
+
931
+ if (wasAccepted) {
932
+ return { result: TopicValidatorResult.Accept, obj: tx };
933
+ } else if (wasIgnored) {
934
+ return { result: TopicValidatorResult.Ignore, obj: tx };
935
+ } else {
936
+ return { result: TopicValidatorResult.Reject };
937
+ }
711
938
  };
712
939
 
713
940
  const { result, obj: tx } = await this.validateReceivedMessage<Tx>(validationFunc, msgId, source, TopicType.tx);
714
- if (!result || !tx) {
941
+ if (result !== TopicValidatorResult.Accept || !tx) {
715
942
  return;
716
943
  }
944
+
945
+ // Tx was accepted into pool and will be propagated - just log and record metrics
717
946
  const txHash = tx.getTxHash();
718
947
  const txHashString = txHash.toString();
719
948
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
@@ -721,126 +950,386 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
721
950
  txHash: txHashString,
722
951
  });
723
952
 
724
- if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
725
- this.logger.debug(`Intentionally dropping tx ${txHashString} (probability rule)`);
726
- return;
727
- }
728
-
729
- await this.mempools.txPool.addTxs([tx]);
953
+ this.instrumentation.incrementTxReceived(1);
730
954
  }
731
955
 
732
956
  /**
733
- * Process Attestation From Peer
734
- * When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
735
- *
736
- * @param attestation - The attestation to process.
957
+ * Process a checkpoint attestation from a peer.
958
+ * Validates the attestation and adds it to the pool.
737
959
  */
738
- private async processAttestationFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
739
- const validationFunc = async () => {
740
- const attestation = BlockAttestation.fromBuffer(payloadData);
741
- const result = await this.validateAttestation(source, attestation);
742
- this.logger.trace(`validatePropagatedAttestation: ${result}`, {
743
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
744
- [Attributes.P2P_ID]: source.toString(),
745
- });
746
- return { result, obj: attestation };
747
- };
748
-
749
- const { result, obj: attestation } = await this.validateReceivedMessage<BlockAttestation>(
750
- 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)),
751
967
  msgId,
752
968
  source,
753
- TopicType.block_attestation,
969
+ TopicType.checkpoint_attestation,
754
970
  );
755
- if (!result || !attestation) {
971
+
972
+ if (result !== TopicValidatorResult.Accept || !attestation) {
756
973
  return;
757
974
  }
758
- this.logger.debug(
759
- `Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`,
975
+
976
+ this.logger.verbose(
977
+ `Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`,
760
978
  {
761
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
762
- slot: attestation.slotNumber.toNumber(),
979
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
980
+ slot: attestation.slotNumber,
763
981
  archive: attestation.archive.toString(),
764
982
  source: source.toString(),
765
983
  },
766
984
  );
767
- await this.mempools.attestationPool!.addAttestations([attestation]);
768
985
  }
769
986
 
770
- private async processBlockFromPeer(payloadData: Buffer, msgId: string, source: PeerId): Promise<void> {
771
- const validationFunc = async () => {
772
- const block = BlockProposal.fromBuffer(payloadData);
773
- const result = await this.validateBlockProposal(source, block);
774
- this.logger.trace(`validatePropagatedBlock: ${result}`, {
775
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
776
- [Attributes.P2P_ID]: source.toString(),
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
+ }
1002
+
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,
777
1034
  });
778
- return { result, obj: block };
779
- };
1035
+ return { result: TopicValidatorResult.Ignore, obj: attestation };
1036
+ }
780
1037
 
781
- const { result, obj: block } = await this.validateReceivedMessage<BlockProposal>(
782
- validationFunc,
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 });
1050
+ }
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
+ }
1056
+
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)),
783
1064
  msgId,
784
1065
  source,
785
1066
  TopicType.block_proposal,
786
1067
  );
787
- if (!result || !block) {
1068
+
1069
+ // If not accepted or equivocated, return
1070
+ if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
788
1071
  return;
789
1072
  }
790
1073
 
791
1074
  await this.processValidBlockProposal(block, source);
792
1075
  }
793
1076
 
794
- // 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.
795
1148
  @trackSpan('Libp2pService.processValidBlockProposal', async block => ({
796
- [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
1149
+ [Attributes.SLOT_NUMBER]: block.slotNumber,
797
1150
  [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
798
- [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then(i => i.toString()),
1151
+ [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then(i => i.toString()),
799
1152
  }))
800
- private async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
801
- const slot = block.slotNumber.toBigInt();
802
- const previousSlot = slot - 1n;
1153
+ protected async processValidBlockProposal(block: BlockProposal, sender: PeerId) {
1154
+ const slot = block.slotNumber;
803
1155
  this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
804
- p2pMessageIdentifier: await block.p2pMessageIdentifier(),
805
- slot: block.slotNumber.toNumber(),
806
- archive: block.archive.toString(),
1156
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
807
1157
  source: sender.toString(),
1158
+ ...block.toBlockInfo(),
808
1159
  });
809
- const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
810
- if (attestationsForPreviousSlot !== undefined) {
811
- 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());
1169
+ }
1170
+ }
1171
+
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
+ );
1187
+
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);
812
1192
  }
813
1193
 
814
- // Mark the txs in this proposal as non-evictable
815
- await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
816
- await this.mempools.attestationPool?.addBlockProposal(block);
817
- const attestations = await this.blockReceivedCallback(block, sender);
1194
+ if (result !== TopicValidatorResult.Accept || !checkpoint || isEquivocated) {
1195
+ return;
1196
+ }
818
1197
 
819
- // TODO: fix up this pattern - the abstraction is not nice
820
- // The attestation can be undefined if no handler is registered / the validator deems the block invalid
821
- if (attestations?.length) {
822
- for (const attestation of attestations) {
823
- this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber.toNumber()}`, {
824
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
825
- slot: attestation.slotNumber.toNumber(),
826
- archive: attestation.archive.toString(),
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,
827
1243
  });
828
- await this.broadcastAttestation(attestation);
1244
+ return { result: TopicValidatorResult.Reject };
1245
+ } else if (result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1246
+ processBlock = true;
829
1247
  }
830
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 } };
831
1303
  }
832
1304
 
833
1305
  /**
834
- * Broadcast an attestation to all peers.
835
- * @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.
836
1308
  */
837
- @trackSpan('Libp2pService.broadcastAttestation', async attestation => ({
838
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
839
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
840
- [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()),
841
1313
  }))
842
- private async broadcastAttestation(attestation: BlockAttestation) {
843
- 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
+ }
844
1333
  }
845
1334
 
846
1335
  /**
@@ -848,36 +1337,89 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
848
1337
  * @param message - The message to propagate.
849
1338
  */
850
1339
  public async propagate<T extends Gossipable>(message: T) {
851
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
1340
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
852
1341
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, { p2pMessageIdentifier });
853
- void this.jobQueue
854
- .put(async () => {
855
- await this.sendToPeers(message);
856
- })
857
- .catch(error => {
858
- this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
859
- });
1342
+ void this.sendToPeers(message).catch(error => {
1343
+ this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, { error });
1344
+ });
860
1345
  }
861
1346
 
862
1347
  /**
863
- * Validate the requested block transactions.
1348
+ * Validate the requested block transactions. Allow partial returns.
864
1349
  * @param request - The block transactions request.
865
1350
  * @param response - The block transactions response.
866
1351
  * @param peerId - The ID of the peer that made the request.
867
1352
  * @returns True if the requested block transactions are valid, false otherwise.
868
1353
  */
869
1354
  @trackSpan('Libp2pService.validateRequestedBlockTxs', request => ({
870
- [Attributes.BLOCK_HASH]: request.blockHash.toString(),
1355
+ [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString(),
871
1356
  }))
872
- private async validateRequestedBlockTxs(
873
- _request: BlockTxsRequest,
1357
+ protected async validateRequestedBlockTxs(
1358
+ request: BlockTxsRequest,
874
1359
  response: BlockTxsResponse,
875
1360
  peerId: PeerId,
876
1361
  ): Promise<boolean> {
877
1362
  const requestedTxValidator = this.createRequestedTxValidator();
878
1363
 
879
1364
  try {
880
- // TODO(palla/txs): Validate that this tx belongs to the block hash being requested
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
+
881
1423
  await Promise.all(response.txs.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator)));
882
1424
  return true;
883
1425
  } catch (e: any) {
@@ -901,7 +1443,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
901
1443
  * ReqRespSubProtocol.TX subprotocol validation.
902
1444
  *
903
1445
  * @param requestedTxHash - The collection of the txs that was requested.
904
- * @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.
905
1447
  * @param peerId - The peer ID of the peer that sent the tx.
906
1448
  * @returns True if the whole collection of txs is valid, false otherwise.
907
1449
  */
@@ -912,7 +1454,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
912
1454
  const requested = new Set(requestedTxHash.map(h => h.toString()));
913
1455
  const requestedTxValidator = this.createRequestedTxValidator();
914
1456
 
915
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
1457
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
916
1458
  // I think we should still extract the valid txs and return them, so that we can still use the response.
917
1459
  try {
918
1460
  await Promise.all(responseTx.map(tx => this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
@@ -928,44 +1470,86 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
928
1470
  }
929
1471
  }
930
1472
 
931
- private createRequestedTxValidator(): TxValidator {
932
- return new AggregateTxValidator(
933
- new DataTxValidator(),
934
- new MetadataTxValidator({
935
- l1ChainId: new Fr(this.config.l1ChainId),
936
- rollupVersion: new Fr(this.config.rollupVersion),
937
- protocolContractsHash,
938
- vkTreeRoot: getVKTreeRoot(),
939
- }),
940
- new TxProofValidator(this.proofVerifier),
941
- );
942
- }
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
+ }
943
1498
 
944
- private async validateRequestedTx(tx: Tx, peerId: PeerId, txValidator: TxValidator, requested?: Set<`0x${string}`>) {
945
- if (!(await tx.validateTxHash())) {
946
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
947
- throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
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;
948
1517
  }
1518
+ }
949
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);
950
1527
  if (requested && !requested.has(tx.getTxHash().toString())) {
951
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1528
+ penalize(PeerErrorSeverity.MidToleranceError);
952
1529
  throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
953
1530
  }
954
1531
 
955
1532
  const { result } = await txValidator.validateTx(tx);
956
1533
  if (result === 'invalid') {
957
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1534
+ penalize(PeerErrorSeverity.LowToleranceError);
958
1535
  throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
959
1536
  }
960
1537
  }
961
1538
 
1539
+ protected createRequestedTxValidator(): TxValidator {
1540
+ return createTxReqRespValidator(this.proofVerifier, {
1541
+ l1ChainId: this.config.l1ChainId,
1542
+ rollupVersion: this.config.rollupVersion,
1543
+ });
1544
+ }
1545
+
962
1546
  @trackSpan('Libp2pService.validatePropagatedTx', tx => ({
963
1547
  [Attributes.TX_HASH]: tx.getTxHash().toString(),
964
1548
  }))
965
- private async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
1549
+ protected async validatePropagatedTx(tx: Tx, peerId: PeerId): Promise<boolean> {
966
1550
  const currentBlockNumber = await this.archiver.getBlockNumber();
967
1551
 
968
- // 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)
969
1553
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
970
1554
  const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
971
1555
 
@@ -980,7 +1564,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
980
1564
 
981
1565
  // Double spend validator has a special case handler
982
1566
  if (name === 'doubleSpendValidator') {
983
- 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
984
1568
  severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
985
1569
  }
986
1570
 
@@ -990,7 +1574,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
990
1574
  return true;
991
1575
  }
992
1576
 
993
- private async getGasFees(blockNumber: number): Promise<GasFees> {
1577
+ private async getGasFees(blockNumber: BlockNumber): Promise<GasFees> {
994
1578
  if (blockNumber === this.feesCache?.blockNumber) {
995
1579
  return this.feesCache.gasFees;
996
1580
  }
@@ -1001,10 +1585,26 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1001
1585
  return gasFees;
1002
1586
  }
1003
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
+
1004
1604
  public async validate(txs: Tx[]): Promise<void> {
1005
1605
  const currentBlockNumber = await this.archiver.getBlockNumber();
1006
1606
 
1007
- // 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)
1008
1608
  const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1009
1609
  const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1010
1610
 
@@ -1031,13 +1631,13 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1031
1631
  * @returns The message validators.
1032
1632
  */
1033
1633
  private async createMessageValidators(
1034
- currentBlockNumber: number,
1634
+ currentBlockNumber: BlockNumber,
1035
1635
  nextSlotTimestamp: UInt64,
1036
1636
  ): Promise<Record<string, MessageValidator>[]> {
1037
1637
  const gasFees = await this.getGasFees(currentBlockNumber);
1038
1638
  const allowedInSetup = this.config.txPublicSetupAllowList ?? (await getDefaultAllowedSetupFunctions());
1039
1639
 
1040
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
1640
+ const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1041
1641
 
1042
1642
  return createTxMessageValidators(
1043
1643
  nextSlotTimestamp,
@@ -1051,6 +1651,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1051
1651
  this.proofVerifier,
1052
1652
  !this.config.disableTransactions,
1053
1653
  allowedInSetup,
1654
+ this.logger.getBindings(),
1054
1655
  );
1055
1656
  }
1056
1657
 
@@ -1099,20 +1700,23 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1099
1700
  * @param peerId - The peer ID of the peer that sent the tx.
1100
1701
  * @returns Severity
1101
1702
  */
1102
- private async handleDoubleSpendFailure(tx: Tx, blockNumber: number): Promise<PeerErrorSeverity> {
1703
+ private async handleDoubleSpendFailure(tx: Tx, blockNumber: BlockNumber): Promise<PeerErrorSeverity> {
1103
1704
  if (blockNumber <= this.config.doubleSpendSeverePeerPenaltyWindow) {
1104
1705
  return PeerErrorSeverity.HighToleranceError;
1105
1706
  }
1106
1707
 
1107
- const snapshotValidator = new DoubleSpendTxValidator({
1108
- nullifiersExist: async (nullifiers: Buffer[]) => {
1109
- const merkleTree = this.worldStateSynchronizer.getSnapshot(
1110
- blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow,
1111
- );
1112
- const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
1113
- 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
+ },
1114
1717
  },
1115
- });
1718
+ this.logger.getBindings(),
1719
+ );
1116
1720
 
1117
1721
  const validSnapshot = await snapshotValidator.validateTx(tx);
1118
1722
  if (validSnapshot.result !== 'valid') {
@@ -1123,44 +1727,28 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1123
1727
  }
1124
1728
 
1125
1729
  /**
1126
- * Validate an attestation.
1730
+ * Validate a checkpoint attestation.
1127
1731
  *
1128
- * @param attestation - The attestation to validate.
1129
- * @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.
1130
1734
  */
1131
- @trackSpan('Libp2pService.validateAttestation', async (_, attestation) => ({
1132
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
1735
+ @trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation) => ({
1736
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
1133
1737
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
1134
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then(i => i.toString()),
1738
+ [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then(i => i.toString()),
1135
1739
  }))
1136
- public async validateAttestation(peerId: PeerId, attestation: BlockAttestation): Promise<boolean> {
1137
- const severity = await this.attestationValidator.validate(attestation);
1138
- if (severity) {
1139
- this.peerManager.penalizePeer(peerId, severity);
1140
- return false;
1141
- }
1142
-
1143
- return true;
1144
- }
1740
+ public async validateCheckpointAttestation(
1741
+ peerId: PeerId,
1742
+ attestation: CheckpointAttestation,
1743
+ ): Promise<P2PValidationResult> {
1744
+ const result = await this.checkpointAttestationValidator.validate(attestation);
1145
1745
 
1146
- /**
1147
- * Validate a block proposal.
1148
- *
1149
- * @param block - The block proposal to validate.
1150
- * @returns True if the block proposal is valid, false otherwise.
1151
- */
1152
- @trackSpan('Libp2pService.validateBlockProposal', (_peerId, block) => ({
1153
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
1154
- }))
1155
- public async validateBlockProposal(peerId: PeerId, block: BlockProposal): Promise<boolean> {
1156
- const severity = await this.blockProposalValidator.validate(block);
1157
- if (severity) {
1158
- this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
1159
- this.peerManager.penalizePeer(peerId, severity);
1160
- 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);
1161
1749
  }
1162
1750
 
1163
- return true;
1751
+ return result;
1164
1752
  }
1165
1753
 
1166
1754
  public getPeerScore(peerId: PeerId): number {
@@ -1174,7 +1762,7 @@ export class LibP2PService<T extends P2PClientType = P2PClientType.Full> extends
1174
1762
  private async sendToPeers<T extends Gossipable>(message: T) {
1175
1763
  const parent = message.constructor as typeof Gossipable;
1176
1764
 
1177
- const identifier = await message.p2pMessageIdentifier().then(i => i.toString());
1765
+ const identifier = await message.p2pMessageLoggingIdentifier().then(i => i.toString());
1178
1766
  this.logger.trace(`Sending message ${identifier}`, { p2pMessageIdentifier: identifier });
1179
1767
 
1180
1768
  const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);