@aztec/p2p 0.0.1-commit.b655e406 → 0.0.1-commit.b9865e97

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 (605) hide show
  1. package/README.md +129 -3
  2. package/dest/bootstrap/bootstrap.d.ts +4 -3
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  4. package/dest/bootstrap/bootstrap.js +13 -5
  5. package/dest/client/factory.d.ts +13 -12
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +65 -21
  8. package/dest/client/index.d.ts +1 -1
  9. package/dest/client/interface.d.ts +72 -35
  10. package/dest/client/interface.d.ts.map +1 -1
  11. package/dest/client/p2p_client.d.ts +59 -86
  12. package/dest/client/p2p_client.d.ts.map +1 -1
  13. package/dest/client/p2p_client.js +677 -339
  14. package/dest/config.d.ts +169 -87
  15. package/dest/config.d.ts.map +1 -1
  16. package/dest/config.js +176 -56
  17. package/dest/enr/generate-enr.d.ts +1 -1
  18. package/dest/enr/index.d.ts +1 -1
  19. package/dest/errors/attestation-pool.error.d.ts +7 -0
  20. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  21. package/dest/errors/attestation-pool.error.js +12 -0
  22. package/dest/errors/p2p-service.error.d.ts +9 -0
  23. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  24. package/dest/errors/p2p-service.error.js +10 -0
  25. package/dest/errors/reqresp.error.d.ts +1 -20
  26. package/dest/errors/reqresp.error.d.ts.map +1 -1
  27. package/dest/errors/reqresp.error.js +0 -21
  28. package/dest/errors/tx-pool.error.d.ts +8 -0
  29. package/dest/errors/tx-pool.error.d.ts.map +1 -0
  30. package/dest/errors/tx-pool.error.js +9 -0
  31. package/dest/index.d.ts +2 -2
  32. package/dest/index.d.ts.map +1 -1
  33. package/dest/index.js +1 -1
  34. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +154 -57
  35. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  36. package/dest/mem_pools/attestation_pool/attestation_pool.js +511 -3
  37. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
  38. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  39. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +651 -294
  40. package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
  41. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  42. package/dest/mem_pools/attestation_pool/index.js +1 -2
  43. package/dest/mem_pools/attestation_pool/mocks.d.ts +234 -10
  44. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  45. package/dest/mem_pools/attestation_pool/mocks.js +19 -13
  46. package/dest/mem_pools/index.d.ts +3 -3
  47. package/dest/mem_pools/index.d.ts.map +1 -1
  48. package/dest/mem_pools/index.js +1 -1
  49. package/dest/mem_pools/instrumentation.d.ts +11 -1
  50. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  51. package/dest/mem_pools/instrumentation.js +55 -10
  52. package/dest/mem_pools/interface.d.ts +6 -7
  53. package/dest/mem_pools/interface.d.ts.map +1 -1
  54. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
  55. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
  56. package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
  57. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +39 -0
  58. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
  59. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +97 -0
  60. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
  61. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
  62. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
  63. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +47 -0
  64. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
  65. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +128 -0
  66. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
  67. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  68. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +94 -0
  69. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
  70. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
  71. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +97 -0
  72. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +11 -0
  73. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
  74. package/dest/mem_pools/tx_pool_v2/eviction/index.js +12 -0
  75. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  76. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  77. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  78. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +180 -0
  79. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
  80. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +25 -0
  81. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
  82. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  83. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +65 -0
  84. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
  85. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  86. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +93 -0
  87. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
  88. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  89. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +78 -0
  90. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
  91. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
  92. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +75 -0
  93. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
  94. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
  95. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
  96. package/dest/mem_pools/tx_pool_v2/index.d.ts +6 -0
  97. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
  98. package/dest/mem_pools/tx_pool_v2/index.js +5 -0
  99. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  100. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  101. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  102. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +218 -0
  103. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
  104. package/dest/mem_pools/tx_pool_v2/interfaces.js +10 -0
  105. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +137 -0
  106. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -0
  107. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +223 -0
  108. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
  109. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
  110. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
  111. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +108 -0
  112. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
  113. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +337 -0
  114. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +62 -0
  115. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
  116. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +167 -0
  117. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +78 -0
  118. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
  119. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +914 -0
  120. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +14 -7
  121. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  122. package/dest/msg_validators/attestation_validator/attestation_validator.js +84 -26
  123. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +24 -0
  124. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  125. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +75 -0
  126. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  127. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  128. package/dest/msg_validators/attestation_validator/index.js +1 -0
  129. package/dest/msg_validators/clock_tolerance.d.ts +32 -0
  130. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  131. package/dest/msg_validators/clock_tolerance.js +90 -0
  132. package/dest/msg_validators/index.d.ts +2 -2
  133. package/dest/msg_validators/index.d.ts.map +1 -1
  134. package/dest/msg_validators/index.js +1 -1
  135. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +1 -1
  136. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -1
  137. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +15 -0
  138. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  139. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +14 -0
  140. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +15 -0
  141. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  142. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +20 -0
  143. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  144. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  145. package/dest/msg_validators/proposal_validator/index.js +3 -0
  146. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +26 -0
  147. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  148. package/dest/msg_validators/proposal_validator/proposal_validator.js +150 -0
  149. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +4 -4
  150. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  151. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +11 -18
  152. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +2 -1
  153. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -1
  154. package/dest/msg_validators/tx_validator/allowed_public_setup.js +25 -21
  155. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  156. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  157. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  158. package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
  159. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  160. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +20 -6
  161. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  162. package/dest/msg_validators/tx_validator/block_header_validator.js +4 -3
  163. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  164. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  165. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  166. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  167. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  168. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  169. package/dest/msg_validators/tx_validator/data_validator.d.ts +4 -1
  170. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  171. package/dest/msg_validators/tx_validator/data_validator.js +40 -3
  172. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +15 -4
  173. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  174. package/dest/msg_validators/tx_validator/double_spend_validator.js +7 -6
  175. package/dest/msg_validators/tx_validator/factory.d.ts +140 -6
  176. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  177. package/dest/msg_validators/tx_validator/factory.js +259 -58
  178. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  179. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  180. package/dest/msg_validators/tx_validator/fee_payer_balance.js +24 -0
  181. package/dest/msg_validators/tx_validator/gas_validator.d.ts +100 -3
  182. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  183. package/dest/msg_validators/tx_validator/gas_validator.js +146 -67
  184. package/dest/msg_validators/tx_validator/index.d.ts +6 -1
  185. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  186. package/dest/msg_validators/tx_validator/index.js +5 -0
  187. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +4 -3
  188. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  189. package/dest/msg_validators/tx_validator/metadata_validator.js +6 -6
  190. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  191. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  192. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  193. package/dest/msg_validators/tx_validator/phases_validator.d.ts +24 -3
  194. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  195. package/dest/msg_validators/tx_validator/phases_validator.js +78 -28
  196. package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
  197. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  198. package/dest/msg_validators/tx_validator/size_validator.js +23 -0
  199. package/dest/msg_validators/tx_validator/test_utils.d.ts +2 -2
  200. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -1
  201. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +23 -5
  202. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  203. package/dest/msg_validators/tx_validator/timestamp_validator.js +8 -8
  204. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
  205. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  206. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
  207. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +4 -2
  208. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  209. package/dest/msg_validators/tx_validator/tx_proof_validator.js +4 -2
  210. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  211. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  212. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  213. package/dest/services/data_store.d.ts +1 -1
  214. package/dest/services/data_store.d.ts.map +1 -1
  215. package/dest/services/data_store.js +14 -10
  216. package/dest/services/discv5/discV5_service.d.ts +2 -1
  217. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  218. package/dest/services/discv5/discV5_service.js +36 -9
  219. package/dest/services/dummy_service.d.ts +36 -16
  220. package/dest/services/dummy_service.d.ts.map +1 -1
  221. package/dest/services/dummy_service.js +58 -14
  222. package/dest/services/encoding.d.ts +7 -3
  223. package/dest/services/encoding.d.ts.map +1 -1
  224. package/dest/services/encoding.js +23 -15
  225. package/dest/services/gossipsub/index.d.ts +3 -0
  226. package/dest/services/gossipsub/index.d.ts.map +1 -0
  227. package/dest/services/gossipsub/index.js +2 -0
  228. package/dest/services/gossipsub/scoring.d.ts +21 -3
  229. package/dest/services/gossipsub/scoring.d.ts.map +1 -1
  230. package/dest/services/gossipsub/scoring.js +24 -7
  231. package/dest/services/gossipsub/topic_score_params.d.ts +184 -0
  232. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
  233. package/dest/services/gossipsub/topic_score_params.js +363 -0
  234. package/dest/services/index.d.ts +2 -1
  235. package/dest/services/index.d.ts.map +1 -1
  236. package/dest/services/index.js +1 -0
  237. package/dest/services/libp2p/instrumentation.d.ts +5 -1
  238. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  239. package/dest/services/libp2p/instrumentation.js +49 -70
  240. package/dest/services/libp2p/libp2p_service.d.ts +118 -109
  241. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  242. package/dest/services/libp2p/libp2p_service.js +1286 -430
  243. package/dest/services/peer-manager/interface.d.ts +1 -1
  244. package/dest/services/peer-manager/metrics.d.ts +11 -2
  245. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  246. package/dest/services/peer-manager/metrics.js +45 -16
  247. package/dest/services/peer-manager/peer_manager.d.ts +7 -34
  248. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  249. package/dest/services/peer-manager/peer_manager.js +46 -23
  250. package/dest/services/peer-manager/peer_scoring.d.ts +12 -2
  251. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  252. package/dest/services/peer-manager/peer_scoring.js +99 -13
  253. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +44 -0
  254. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  255. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +534 -0
  256. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  257. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  258. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  259. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
  260. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  261. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  262. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +35 -0
  263. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  264. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +136 -0
  265. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +62 -0
  266. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  267. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +176 -0
  268. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +11 -0
  269. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  270. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +7 -0
  271. package/dest/services/reqresp/config.d.ts +3 -3
  272. package/dest/services/reqresp/config.d.ts.map +1 -1
  273. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -4
  274. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  275. package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
  276. package/dest/services/reqresp/constants.d.ts +12 -0
  277. package/dest/services/reqresp/constants.d.ts.map +1 -0
  278. package/dest/services/reqresp/constants.js +7 -0
  279. package/dest/services/reqresp/index.d.ts +1 -1
  280. package/dest/services/reqresp/interface.d.ts +27 -18
  281. package/dest/services/reqresp/interface.d.ts.map +1 -1
  282. package/dest/services/reqresp/interface.js +23 -19
  283. package/dest/services/reqresp/metrics.d.ts +6 -5
  284. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  285. package/dest/services/reqresp/metrics.js +16 -21
  286. package/dest/services/reqresp/protocols/auth.d.ts +2 -2
  287. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -1
  288. package/dest/services/reqresp/protocols/auth.js +2 -2
  289. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +8 -3
  290. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  291. package/dest/services/reqresp/protocols/block_txs/bitvector.js +15 -2
  292. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +7 -5
  293. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  294. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +35 -14
  295. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +37 -11
  296. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  297. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +85 -21
  298. package/dest/services/reqresp/protocols/block_txs/index.d.ts +1 -1
  299. package/dest/services/reqresp/protocols/goodbye.d.ts +1 -1
  300. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  301. package/dest/services/reqresp/protocols/index.d.ts +1 -2
  302. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  303. package/dest/services/reqresp/protocols/index.js +0 -1
  304. package/dest/services/reqresp/protocols/ping.d.ts +1 -1
  305. package/dest/services/reqresp/protocols/status.d.ts +6 -5
  306. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  307. package/dest/services/reqresp/protocols/status.js +7 -3
  308. package/dest/services/reqresp/protocols/tx.d.ts +8 -3
  309. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  310. package/dest/services/reqresp/protocols/tx.js +21 -3
  311. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  312. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +6 -5
  313. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  314. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -8
  315. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  316. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  317. package/dest/services/reqresp/rate-limiter/rate_limits.js +0 -10
  318. package/dest/services/reqresp/reqresp.d.ts +12 -69
  319. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  320. package/dest/services/reqresp/reqresp.js +448 -199
  321. package/dest/services/reqresp/status.d.ts +2 -2
  322. package/dest/services/reqresp/status.d.ts.map +1 -1
  323. package/dest/services/service.d.ts +62 -13
  324. package/dest/services/service.d.ts.map +1 -1
  325. package/dest/services/tx_collection/config.d.ts +11 -11
  326. package/dest/services/tx_collection/config.d.ts.map +1 -1
  327. package/dest/services/tx_collection/config.js +28 -27
  328. package/dest/services/tx_collection/file_store_tx_collection.d.ts +37 -0
  329. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
  330. package/dest/services/tx_collection/file_store_tx_collection.js +127 -0
  331. package/dest/services/tx_collection/file_store_tx_source.d.ts +38 -0
  332. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
  333. package/dest/services/tx_collection/file_store_tx_source.js +100 -0
  334. package/dest/services/tx_collection/index.d.ts +3 -2
  335. package/dest/services/tx_collection/index.d.ts.map +1 -1
  336. package/dest/services/tx_collection/index.js +1 -0
  337. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  338. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  339. package/dest/services/tx_collection/instrumentation.js +9 -13
  340. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  341. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  342. package/dest/services/tx_collection/request_tracker.js +84 -0
  343. package/dest/services/tx_collection/tx_collection.d.ts +51 -57
  344. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  345. package/dest/services/tx_collection/tx_collection.js +298 -70
  346. package/dest/services/tx_collection/tx_collection_sink.d.ts +20 -10
  347. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -1
  348. package/dest/services/tx_collection/tx_collection_sink.js +28 -31
  349. package/dest/services/tx_collection/tx_source.d.ts +13 -7
  350. package/dest/services/tx_collection/tx_source.d.ts.map +1 -1
  351. package/dest/services/tx_collection/tx_source.js +26 -7
  352. package/dest/services/tx_file_store/config.d.ts +16 -0
  353. package/dest/services/tx_file_store/config.d.ts.map +1 -0
  354. package/dest/services/tx_file_store/config.js +22 -0
  355. package/dest/services/tx_file_store/index.d.ts +4 -0
  356. package/dest/services/tx_file_store/index.d.ts.map +1 -0
  357. package/dest/services/tx_file_store/index.js +3 -0
  358. package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
  359. package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
  360. package/dest/services/tx_file_store/instrumentation.js +29 -0
  361. package/dest/services/tx_file_store/tx_file_store.d.ts +46 -0
  362. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
  363. package/dest/services/tx_file_store/tx_file_store.js +142 -0
  364. package/dest/services/tx_provider.d.ts +9 -5
  365. package/dest/services/tx_provider.d.ts.map +1 -1
  366. package/dest/services/tx_provider.js +23 -10
  367. package/dest/services/tx_provider_instrumentation.d.ts +5 -2
  368. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  369. package/dest/services/tx_provider_instrumentation.js +14 -14
  370. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  371. package/dest/test-helpers/get-ports.d.ts +1 -1
  372. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  373. package/dest/test-helpers/index.d.ts +3 -1
  374. package/dest/test-helpers/index.d.ts.map +1 -1
  375. package/dest/test-helpers/index.js +2 -0
  376. package/dest/test-helpers/make-enrs.d.ts +1 -1
  377. package/dest/test-helpers/make-test-p2p-clients.d.ts +7 -8
  378. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  379. package/dest/test-helpers/make-test-p2p-clients.js +5 -3
  380. package/dest/test-helpers/mock-pubsub.d.ts +48 -8
  381. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  382. package/dest/test-helpers/mock-pubsub.js +115 -14
  383. package/dest/test-helpers/mock-tx-helpers.d.ts +2 -2
  384. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -1
  385. package/dest/test-helpers/mock-tx-helpers.js +1 -1
  386. package/dest/test-helpers/reqresp-nodes.d.ts +5 -7
  387. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  388. package/dest/test-helpers/reqresp-nodes.js +19 -20
  389. package/dest/test-helpers/test_tx_provider.d.ts +42 -0
  390. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  391. package/dest/test-helpers/test_tx_provider.js +44 -0
  392. package/dest/test-helpers/testbench-utils.d.ts +161 -0
  393. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  394. package/dest/test-helpers/testbench-utils.js +391 -0
  395. package/dest/testbench/p2p_client_testbench_worker.d.ts +26 -2
  396. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  397. package/dest/testbench/p2p_client_testbench_worker.js +275 -131
  398. package/dest/testbench/parse_log_file.d.ts +1 -1
  399. package/dest/testbench/testbench.d.ts +1 -1
  400. package/dest/testbench/worker_client_manager.d.ts +57 -6
  401. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  402. package/dest/testbench/worker_client_manager.js +277 -44
  403. package/dest/types/index.d.ts +1 -1
  404. package/dest/util.d.ts +14 -8
  405. package/dest/util.d.ts.map +1 -1
  406. package/dest/util.js +41 -11
  407. package/dest/versioning.d.ts +3 -6
  408. package/dest/versioning.d.ts.map +1 -1
  409. package/dest/versioning.js +3 -24
  410. package/package.json +20 -18
  411. package/src/bootstrap/bootstrap.ts +16 -5
  412. package/src/client/factory.ts +137 -46
  413. package/src/client/interface.ts +87 -43
  414. package/src/client/p2p_client.ts +352 -418
  415. package/src/client/test/p2p_client.batch_tx_requester.bench.README.md +197 -0
  416. package/src/config.ts +302 -65
  417. package/src/errors/attestation-pool.error.ts +13 -0
  418. package/src/errors/p2p-service.error.ts +11 -0
  419. package/src/errors/reqresp.error.ts +0 -25
  420. package/src/errors/tx-pool.error.ts +12 -0
  421. package/src/index.ts +1 -1
  422. package/src/mem_pools/attestation_pool/attestation_pool.ts +588 -56
  423. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +760 -319
  424. package/src/mem_pools/attestation_pool/index.ts +9 -2
  425. package/src/mem_pools/attestation_pool/mocks.ts +29 -17
  426. package/src/mem_pools/index.ts +2 -2
  427. package/src/mem_pools/instrumentation.ts +56 -10
  428. package/src/mem_pools/interface.ts +5 -7
  429. package/src/mem_pools/tx_pool_v2/README.md +283 -0
  430. package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
  431. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +112 -0
  432. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  433. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +160 -0
  434. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +122 -0
  435. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +125 -0
  436. package/src/mem_pools/tx_pool_v2/eviction/index.ts +28 -0
  437. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  438. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +219 -0
  439. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
  440. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
  441. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +91 -0
  442. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +99 -0
  443. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +32 -0
  444. package/src/mem_pools/tx_pool_v2/index.ts +12 -0
  445. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  446. package/src/mem_pools/tx_pool_v2/interfaces.ts +250 -0
  447. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +349 -0
  448. package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
  449. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +430 -0
  450. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +238 -0
  451. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1090 -0
  452. package/src/msg_validators/attestation_validator/README.md +49 -0
  453. package/src/msg_validators/attestation_validator/attestation_validator.ts +78 -33
  454. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +101 -0
  455. package/src/msg_validators/attestation_validator/index.ts +1 -0
  456. package/src/msg_validators/clock_tolerance.ts +121 -0
  457. package/src/msg_validators/index.ts +1 -1
  458. package/src/msg_validators/proposal_validator/README.md +123 -0
  459. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +30 -0
  460. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +41 -0
  461. package/src/msg_validators/proposal_validator/index.ts +3 -0
  462. package/src/msg_validators/proposal_validator/proposal_validator.ts +159 -0
  463. package/src/msg_validators/tx_validator/README.md +127 -0
  464. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +8 -17
  465. package/src/msg_validators/tx_validator/allowed_public_setup.ts +22 -27
  466. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  467. package/src/msg_validators/tx_validator/archive_cache.ts +2 -2
  468. package/src/msg_validators/tx_validator/block_header_validator.ts +21 -8
  469. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  470. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  471. package/src/msg_validators/tx_validator/data_validator.ts +62 -7
  472. package/src/msg_validators/tx_validator/double_spend_validator.ts +15 -9
  473. package/src/msg_validators/tx_validator/factory.ts +427 -58
  474. package/src/msg_validators/tx_validator/fee_payer_balance.ts +44 -0
  475. package/src/msg_validators/tx_validator/gas_validator.ts +211 -77
  476. package/src/msg_validators/tx_validator/index.ts +5 -0
  477. package/src/msg_validators/tx_validator/metadata_validator.ts +31 -12
  478. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  479. package/src/msg_validators/tx_validator/phases_validator.ts +90 -31
  480. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  481. package/src/msg_validators/tx_validator/test_utils.ts +1 -1
  482. package/src/msg_validators/tx_validator/timestamp_validator.ts +30 -19
  483. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
  484. package/src/msg_validators/tx_validator/tx_proof_validator.ts +10 -3
  485. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  486. package/src/services/data_store.ts +14 -19
  487. package/src/services/discv5/discV5_service.ts +39 -6
  488. package/src/services/dummy_service.ts +76 -38
  489. package/src/services/encoding.ts +22 -13
  490. package/src/services/gossipsub/README.md +641 -0
  491. package/src/services/gossipsub/index.ts +2 -0
  492. package/src/services/gossipsub/scoring.ts +29 -5
  493. package/src/services/gossipsub/topic_score_params.ts +519 -0
  494. package/src/services/index.ts +1 -0
  495. package/src/services/libp2p/instrumentation.ts +54 -72
  496. package/src/services/libp2p/libp2p_service.ts +1032 -480
  497. package/src/services/peer-manager/metrics.ts +51 -16
  498. package/src/services/peer-manager/peer_manager.ts +53 -15
  499. package/src/services/peer-manager/peer_scoring.ts +96 -7
  500. package/src/services/reqresp/README.md +215 -0
  501. package/src/services/reqresp/batch-tx-requester/README.md +344 -0
  502. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +660 -0
  503. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  504. package/src/services/reqresp/batch-tx-requester/interface.ts +61 -0
  505. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +168 -0
  506. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +249 -0
  507. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +24 -0
  508. package/src/services/reqresp/config.ts +2 -2
  509. package/src/services/reqresp/connection-sampler/connection_sampler.ts +19 -1
  510. package/src/services/reqresp/constants.ts +14 -0
  511. package/src/services/reqresp/interface.ts +48 -46
  512. package/src/services/reqresp/metrics.ts +35 -27
  513. package/src/services/reqresp/protocols/auth.ts +2 -2
  514. package/src/services/reqresp/protocols/block_txs/bitvector.ts +19 -2
  515. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +44 -17
  516. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +109 -17
  517. package/src/services/reqresp/protocols/index.ts +0 -1
  518. package/src/services/reqresp/protocols/status.ts +16 -12
  519. package/src/services/reqresp/protocols/tx.ts +24 -5
  520. package/src/services/reqresp/rate-limiter/rate_limiter.ts +13 -9
  521. package/src/services/reqresp/rate-limiter/rate_limits.ts +0 -10
  522. package/src/services/reqresp/reqresp.ts +68 -224
  523. package/src/services/service.ts +83 -31
  524. package/src/services/tx_collection/config.ts +42 -37
  525. package/src/services/tx_collection/file_store_tx_collection.ts +153 -0
  526. package/src/services/tx_collection/file_store_tx_source.ts +129 -0
  527. package/src/services/tx_collection/index.ts +2 -1
  528. package/src/services/tx_collection/instrumentation.ts +5 -13
  529. package/src/services/tx_collection/request_tracker.ts +127 -0
  530. package/src/services/tx_collection/tx_collection.ts +368 -115
  531. package/src/services/tx_collection/tx_collection_sink.ts +32 -36
  532. package/src/services/tx_collection/tx_source.ts +28 -8
  533. package/src/services/tx_file_store/config.ts +37 -0
  534. package/src/services/tx_file_store/index.ts +3 -0
  535. package/src/services/tx_file_store/instrumentation.ts +36 -0
  536. package/src/services/tx_file_store/tx_file_store.ts +163 -0
  537. package/src/services/tx_provider.ts +34 -12
  538. package/src/services/tx_provider_instrumentation.ts +24 -14
  539. package/src/test-helpers/index.ts +2 -0
  540. package/src/test-helpers/make-test-p2p-clients.ts +7 -6
  541. package/src/test-helpers/mock-pubsub.ts +138 -15
  542. package/src/test-helpers/mock-tx-helpers.ts +1 -1
  543. package/src/test-helpers/reqresp-nodes.ts +18 -30
  544. package/src/test-helpers/test_tx_provider.ts +69 -0
  545. package/src/test-helpers/testbench-utils.ts +453 -0
  546. package/src/testbench/p2p_client_testbench_worker.ts +387 -128
  547. package/src/testbench/worker_client_manager.ts +355 -46
  548. package/src/util.ts +47 -16
  549. package/src/versioning.ts +3 -33
  550. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -30
  551. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
  552. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -190
  553. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -25
  554. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
  555. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -197
  556. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -150
  557. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  558. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -617
  559. package/dest/mem_pools/tx_pool/index.d.ts +0 -4
  560. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  561. package/dest/mem_pools/tx_pool/index.js +0 -3
  562. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -80
  563. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  564. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -238
  565. package/dest/mem_pools/tx_pool/priority.d.ts +0 -8
  566. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  567. package/dest/mem_pools/tx_pool/priority.js +0 -10
  568. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -122
  569. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  570. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  571. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  572. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  573. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -394
  574. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -12
  575. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  576. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -70
  577. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  578. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  579. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  580. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -45
  581. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  582. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -92
  583. package/dest/services/reqresp/protocols/block.d.ts +0 -9
  584. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  585. package/dest/services/reqresp/protocols/block.js +0 -31
  586. package/dest/services/tx_collection/fast_tx_collection.d.ts +0 -56
  587. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +0 -1
  588. package/dest/services/tx_collection/fast_tx_collection.js +0 -300
  589. package/dest/services/tx_collection/slow_tx_collection.d.ts +0 -54
  590. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +0 -1
  591. package/dest/services/tx_collection/slow_tx_collection.js +0 -176
  592. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -256
  593. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -253
  594. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -750
  595. package/src/mem_pools/tx_pool/index.ts +0 -3
  596. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -283
  597. package/src/mem_pools/tx_pool/priority.ts +0 -13
  598. package/src/mem_pools/tx_pool/tx_pool.ts +0 -135
  599. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -313
  600. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -81
  601. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
  602. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -100
  603. package/src/services/reqresp/protocols/block.ts +0 -36
  604. package/src/services/tx_collection/fast_tx_collection.ts +0 -340
  605. package/src/services/tx_collection/slow_tx_collection.ts +0 -232
@@ -1,25 +1,389 @@
1
- function _ts_decorate(decorators, target, key, desc) {
2
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
- else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
- return c > 3 && r && Object.defineProperty(target, key, r), r;
1
+ function applyDecs2203RFactory() {
2
+ function createAddInitializerMethod(initializers, decoratorFinishedRef) {
3
+ return function addInitializer(initializer) {
4
+ assertNotFinished(decoratorFinishedRef, "addInitializer");
5
+ assertCallable(initializer, "An initializer");
6
+ initializers.push(initializer);
7
+ };
8
+ }
9
+ function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) {
10
+ var kindStr;
11
+ switch(kind){
12
+ case 1:
13
+ kindStr = "accessor";
14
+ break;
15
+ case 2:
16
+ kindStr = "method";
17
+ break;
18
+ case 3:
19
+ kindStr = "getter";
20
+ break;
21
+ case 4:
22
+ kindStr = "setter";
23
+ break;
24
+ default:
25
+ kindStr = "field";
26
+ }
27
+ var ctx = {
28
+ kind: kindStr,
29
+ name: isPrivate ? "#" + name : name,
30
+ static: isStatic,
31
+ private: isPrivate,
32
+ metadata: metadata
33
+ };
34
+ var decoratorFinishedRef = {
35
+ v: false
36
+ };
37
+ ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef);
38
+ var get, set;
39
+ if (kind === 0) {
40
+ if (isPrivate) {
41
+ get = desc.get;
42
+ set = desc.set;
43
+ } else {
44
+ get = function() {
45
+ return this[name];
46
+ };
47
+ set = function(v) {
48
+ this[name] = v;
49
+ };
50
+ }
51
+ } else if (kind === 2) {
52
+ get = function() {
53
+ return desc.value;
54
+ };
55
+ } else {
56
+ if (kind === 1 || kind === 3) {
57
+ get = function() {
58
+ return desc.get.call(this);
59
+ };
60
+ }
61
+ if (kind === 1 || kind === 4) {
62
+ set = function(v) {
63
+ desc.set.call(this, v);
64
+ };
65
+ }
66
+ }
67
+ ctx.access = get && set ? {
68
+ get: get,
69
+ set: set
70
+ } : get ? {
71
+ get: get
72
+ } : {
73
+ set: set
74
+ };
75
+ try {
76
+ return dec(value, ctx);
77
+ } finally{
78
+ decoratorFinishedRef.v = true;
79
+ }
80
+ }
81
+ function assertNotFinished(decoratorFinishedRef, fnName) {
82
+ if (decoratorFinishedRef.v) {
83
+ throw new Error("attempted to call " + fnName + " after decoration was finished");
84
+ }
85
+ }
86
+ function assertCallable(fn, hint) {
87
+ if (typeof fn !== "function") {
88
+ throw new TypeError(hint + " must be a function");
89
+ }
90
+ }
91
+ function assertValidReturnValue(kind, value) {
92
+ var type = typeof value;
93
+ if (kind === 1) {
94
+ if (type !== "object" || value === null) {
95
+ throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");
96
+ }
97
+ if (value.get !== undefined) {
98
+ assertCallable(value.get, "accessor.get");
99
+ }
100
+ if (value.set !== undefined) {
101
+ assertCallable(value.set, "accessor.set");
102
+ }
103
+ if (value.init !== undefined) {
104
+ assertCallable(value.init, "accessor.init");
105
+ }
106
+ } else if (type !== "function") {
107
+ var hint;
108
+ if (kind === 0) {
109
+ hint = "field";
110
+ } else if (kind === 10) {
111
+ hint = "class";
112
+ } else {
113
+ hint = "method";
114
+ }
115
+ throw new TypeError(hint + " decorators must return a function or void 0");
116
+ }
117
+ }
118
+ function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) {
119
+ var decs = decInfo[0];
120
+ var desc, init, value;
121
+ if (isPrivate) {
122
+ if (kind === 0 || kind === 1) {
123
+ desc = {
124
+ get: decInfo[3],
125
+ set: decInfo[4]
126
+ };
127
+ } else if (kind === 3) {
128
+ desc = {
129
+ get: decInfo[3]
130
+ };
131
+ } else if (kind === 4) {
132
+ desc = {
133
+ set: decInfo[3]
134
+ };
135
+ } else {
136
+ desc = {
137
+ value: decInfo[3]
138
+ };
139
+ }
140
+ } else if (kind !== 0) {
141
+ desc = Object.getOwnPropertyDescriptor(base, name);
142
+ }
143
+ if (kind === 1) {
144
+ value = {
145
+ get: desc.get,
146
+ set: desc.set
147
+ };
148
+ } else if (kind === 2) {
149
+ value = desc.value;
150
+ } else if (kind === 3) {
151
+ value = desc.get;
152
+ } else if (kind === 4) {
153
+ value = desc.set;
154
+ }
155
+ var newValue, get, set;
156
+ if (typeof decs === "function") {
157
+ newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
158
+ if (newValue !== void 0) {
159
+ assertValidReturnValue(kind, newValue);
160
+ if (kind === 0) {
161
+ init = newValue;
162
+ } else if (kind === 1) {
163
+ init = newValue.init;
164
+ get = newValue.get || value.get;
165
+ set = newValue.set || value.set;
166
+ value = {
167
+ get: get,
168
+ set: set
169
+ };
170
+ } else {
171
+ value = newValue;
172
+ }
173
+ }
174
+ } else {
175
+ for(var i = decs.length - 1; i >= 0; i--){
176
+ var dec = decs[i];
177
+ newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value);
178
+ if (newValue !== void 0) {
179
+ assertValidReturnValue(kind, newValue);
180
+ var newInit;
181
+ if (kind === 0) {
182
+ newInit = newValue;
183
+ } else if (kind === 1) {
184
+ newInit = newValue.init;
185
+ get = newValue.get || value.get;
186
+ set = newValue.set || value.set;
187
+ value = {
188
+ get: get,
189
+ set: set
190
+ };
191
+ } else {
192
+ value = newValue;
193
+ }
194
+ if (newInit !== void 0) {
195
+ if (init === void 0) {
196
+ init = newInit;
197
+ } else if (typeof init === "function") {
198
+ init = [
199
+ init,
200
+ newInit
201
+ ];
202
+ } else {
203
+ init.push(newInit);
204
+ }
205
+ }
206
+ }
207
+ }
208
+ }
209
+ if (kind === 0 || kind === 1) {
210
+ if (init === void 0) {
211
+ init = function(instance, init) {
212
+ return init;
213
+ };
214
+ } else if (typeof init !== "function") {
215
+ var ownInitializers = init;
216
+ init = function(instance, init) {
217
+ var value = init;
218
+ for(var i = 0; i < ownInitializers.length; i++){
219
+ value = ownInitializers[i].call(instance, value);
220
+ }
221
+ return value;
222
+ };
223
+ } else {
224
+ var originalInitializer = init;
225
+ init = function(instance, init) {
226
+ return originalInitializer.call(instance, init);
227
+ };
228
+ }
229
+ ret.push(init);
230
+ }
231
+ if (kind !== 0) {
232
+ if (kind === 1) {
233
+ desc.get = value.get;
234
+ desc.set = value.set;
235
+ } else if (kind === 2) {
236
+ desc.value = value;
237
+ } else if (kind === 3) {
238
+ desc.get = value;
239
+ } else if (kind === 4) {
240
+ desc.set = value;
241
+ }
242
+ if (isPrivate) {
243
+ if (kind === 1) {
244
+ ret.push(function(instance, args) {
245
+ return value.get.call(instance, args);
246
+ });
247
+ ret.push(function(instance, args) {
248
+ return value.set.call(instance, args);
249
+ });
250
+ } else if (kind === 2) {
251
+ ret.push(value);
252
+ } else {
253
+ ret.push(function(instance, args) {
254
+ return value.call(instance, args);
255
+ });
256
+ }
257
+ } else {
258
+ Object.defineProperty(base, name, desc);
259
+ }
260
+ }
261
+ }
262
+ function applyMemberDecs(Class, decInfos, metadata) {
263
+ var ret = [];
264
+ var protoInitializers;
265
+ var staticInitializers;
266
+ var existingProtoNonFields = new Map();
267
+ var existingStaticNonFields = new Map();
268
+ for(var i = 0; i < decInfos.length; i++){
269
+ var decInfo = decInfos[i];
270
+ if (!Array.isArray(decInfo)) continue;
271
+ var kind = decInfo[1];
272
+ var name = decInfo[2];
273
+ var isPrivate = decInfo.length > 3;
274
+ var isStatic = kind >= 5;
275
+ var base;
276
+ var initializers;
277
+ if (isStatic) {
278
+ base = Class;
279
+ kind = kind - 5;
280
+ staticInitializers = staticInitializers || [];
281
+ initializers = staticInitializers;
282
+ } else {
283
+ base = Class.prototype;
284
+ protoInitializers = protoInitializers || [];
285
+ initializers = protoInitializers;
286
+ }
287
+ if (kind !== 0 && !isPrivate) {
288
+ var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields;
289
+ var existingKind = existingNonFields.get(name) || 0;
290
+ if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) {
291
+ throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: " + name);
292
+ } else if (!existingKind && kind > 2) {
293
+ existingNonFields.set(name, kind);
294
+ } else {
295
+ existingNonFields.set(name, true);
296
+ }
297
+ }
298
+ applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata);
299
+ }
300
+ pushInitializers(ret, protoInitializers);
301
+ pushInitializers(ret, staticInitializers);
302
+ return ret;
303
+ }
304
+ function pushInitializers(ret, initializers) {
305
+ if (initializers) {
306
+ ret.push(function(instance) {
307
+ for(var i = 0; i < initializers.length; i++){
308
+ initializers[i].call(instance);
309
+ }
310
+ return instance;
311
+ });
312
+ }
313
+ }
314
+ function applyClassDecs(targetClass, classDecs, metadata) {
315
+ if (classDecs.length > 0) {
316
+ var initializers = [];
317
+ var newClass = targetClass;
318
+ var name = targetClass.name;
319
+ for(var i = classDecs.length - 1; i >= 0; i--){
320
+ var decoratorFinishedRef = {
321
+ v: false
322
+ };
323
+ try {
324
+ var nextNewClass = classDecs[i](newClass, {
325
+ kind: "class",
326
+ name: name,
327
+ addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef),
328
+ metadata
329
+ });
330
+ } finally{
331
+ decoratorFinishedRef.v = true;
332
+ }
333
+ if (nextNewClass !== undefined) {
334
+ assertValidReturnValue(10, nextNewClass);
335
+ newClass = nextNewClass;
336
+ }
337
+ }
338
+ return [
339
+ defineMetadata(newClass, metadata),
340
+ function() {
341
+ for(var i = 0; i < initializers.length; i++){
342
+ initializers[i].call(newClass);
343
+ }
344
+ }
345
+ ];
346
+ }
347
+ }
348
+ function defineMetadata(Class, metadata) {
349
+ return Object.defineProperty(Class, Symbol.metadata || Symbol.for("Symbol.metadata"), {
350
+ configurable: true,
351
+ enumerable: true,
352
+ value: metadata
353
+ });
354
+ }
355
+ return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) {
356
+ if (parentClass !== void 0) {
357
+ var parentMetadata = parentClass[Symbol.metadata || Symbol.for("Symbol.metadata")];
358
+ }
359
+ var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata);
360
+ var e = applyMemberDecs(targetClass, memberDecs, metadata);
361
+ if (!classDecs.length) defineMetadata(targetClass, metadata);
362
+ return {
363
+ e: e,
364
+ get c () {
365
+ return applyClassDecs(targetClass, classDecs, metadata);
366
+ }
367
+ };
368
+ };
369
+ }
370
+ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
371
+ return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
6
372
  }
7
- import { randomInt } from '@aztec/foundation/crypto';
8
- import { Fr } from '@aztec/foundation/fields';
373
+ var _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _initProto;
374
+ import { BlockNumber } from '@aztec/foundation/branded-types';
375
+ import { maxBy, merge } from '@aztec/foundation/collection';
9
376
  import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
10
- import { SerialQueue } from '@aztec/foundation/queue';
11
377
  import { RunningPromise } from '@aztec/foundation/running-promise';
12
378
  import { Timer } from '@aztec/foundation/timer';
13
- import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
14
379
  import { protocolContractsHash } from '@aztec/protocol-contracts';
15
- import { GasFees } from '@aztec/stdlib/gas';
16
- import { BlockAttestation, BlockProposal, P2PClientType, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicsForClientAndConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
380
+ import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PMessage, PeerErrorSeverity, PeerErrorSeverityByHarshness, TopicType, createTopicString, getTopicsForConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
17
381
  import { MerkleTreeId } from '@aztec/stdlib/trees';
18
382
  import { Tx } from '@aztec/stdlib/tx';
19
383
  import { compressComponentVersions } from '@aztec/stdlib/versioning';
20
- import { Attributes, OtelMetricsAdapter, WithTracer, trackSpan } from '@aztec/telemetry-client';
384
+ import { Attributes, OtelMetricsAdapter, SpanStatusCode, WithTracer, trackSpan } from '@aztec/telemetry-client';
21
385
  import { gossipsub } from '@chainsafe/libp2p-gossipsub';
22
- import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
386
+ import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
23
387
  import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
24
388
  import { noise } from '@chainsafe/libp2p-noise';
25
389
  import { yamux } from '@chainsafe/libp2p-yamux';
@@ -28,32 +392,47 @@ import { identify } from '@libp2p/identify';
28
392
  import { TopicValidatorResult } from '@libp2p/interface';
29
393
  import { mplex } from '@libp2p/mplex';
30
394
  import { tcp } from '@libp2p/tcp';
395
+ import { multiaddr } from '@multiformats/multiaddr';
31
396
  import { ENR } from '@nethermindeth/enr';
32
397
  import { createLibp2p } from 'libp2p';
33
- import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
398
+ import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
399
+ import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, DoubleSpendTxValidator, FishermanAttestationValidator, getDefaultAllowedSetupFunctions } from '../../msg_validators/index.js';
34
400
  import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
35
- import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
36
- import { createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
37
- import { AggregateTxValidator, DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
401
+ import { createFirstStageTxValidationsForGossipedTransactions, createSecondStageTxValidationsForGossipedTransactions, createTxValidatorForBlockProposalReceivedTxs } from '../../msg_validators/tx_validator/factory.js';
38
402
  import { GossipSubEvent } from '../../types/index.js';
39
403
  import { convertToMultiaddr } from '../../util.js';
40
404
  import { getVersions } from '../../versioning.js';
41
405
  import { AztecDatastore } from '../data_store.js';
42
406
  import { DiscV5Service } from '../discv5/discV5_service.js';
43
407
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
44
- import { gossipScoreThresholds } from '../gossipsub/scoring.js';
408
+ import { APP_SPECIFIC_WEIGHT, gossipScoreThresholds } from '../gossipsub/scoring.js';
409
+ import { createAllTopicScoreParams } from '../gossipsub/topic_score_params.js';
45
410
  import { PeerManager } from '../peer-manager/peer_manager.js';
46
411
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
47
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/interface.js';
48
- import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
49
- import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
50
- import { pingHandler, reqRespBlockHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/protocols/index.js';
412
+ import { ReqRespSubProtocol, ValidationError, pingHandler, reqGoodbyeHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
51
413
  import { ReqResp } from '../reqresp/reqresp.js';
52
414
  import { P2PInstrumentation } from './instrumentation.js';
415
+ _dec = trackSpan('Libp2pService.validateAndStoreCheckpointAttestation', (_peerId, attestation)=>({
416
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString()
417
+ })), _dec1 = trackSpan('Libp2pService.validateAndStoreBlockProposal', (_peerId, block)=>({
418
+ [Attributes.BLOCK_NUMBER]: block.blockNumber.toString(),
419
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString()
420
+ })), _dec2 = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
421
+ [Attributes.SLOT_NUMBER]: block.slotNumber,
422
+ [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
423
+ [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then((i)=>i.toString())
424
+ })), _dec3 = trackSpan('Libp2pService.validateAndStoreCheckpointProposal', (_peerId, checkpoint)=>({
425
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString()
426
+ })), _dec4 = trackSpan('Libp2pService.processValidCheckpointProposal', async (checkpoint)=>({
427
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
428
+ [Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
429
+ [Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then((i)=>i.toString())
430
+ })), _dec5 = trackSpan('Libp2pService.validateRequestedBlockTxsConsistency', (request)=>({
431
+ [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString()
432
+ }));
53
433
  /**
54
434
  * Lib P2P implementation of the P2PService interface.
55
435
  */ export class LibP2PService extends WithTracer {
56
- clientType;
57
436
  config;
58
437
  node;
59
438
  peerDiscoveryService;
@@ -64,62 +443,141 @@ import { P2PInstrumentation } from './instrumentation.js';
64
443
  epochCache;
65
444
  proofVerifier;
66
445
  worldStateSynchronizer;
67
- logger;
68
- jobQueue;
446
+ blockMinFeesProvider;
447
+ txValidationCache;
448
+ static{
449
+ ({ e: [_initProto] } = _apply_decs_2203_r(this, [
450
+ [
451
+ _dec,
452
+ 2,
453
+ "validateAndStoreCheckpointAttestation"
454
+ ],
455
+ [
456
+ _dec1,
457
+ 2,
458
+ "validateAndStoreBlockProposal"
459
+ ],
460
+ [
461
+ _dec2,
462
+ 2,
463
+ "processValidBlockProposal"
464
+ ],
465
+ [
466
+ _dec3,
467
+ 2,
468
+ "validateAndStoreCheckpointProposal"
469
+ ],
470
+ [
471
+ _dec4,
472
+ 2,
473
+ "processValidCheckpointProposal"
474
+ ],
475
+ [
476
+ _dec5,
477
+ 2,
478
+ "validateRequestedBlockTxsConsistency"
479
+ ]
480
+ ], []));
481
+ }
69
482
  discoveryRunningPromise;
70
483
  msgIdSeenValidators;
71
484
  // Message validators
72
- attestationValidator;
73
485
  blockProposalValidator;
486
+ checkpointProposalValidator;
487
+ checkpointAttestationValidator;
74
488
  protocolVersion;
75
489
  topicStrings;
76
- feesCache;
490
+ /** Callback invoked when a duplicate proposal is detected (triggers slashing). */ duplicateProposalCallback;
491
+ /** Callback invoked when a duplicate attestation is detected (triggers slashing). */ duplicateAttestationCallback;
492
+ /** Callback invoked when a valid checkpoint attestation is accepted into the pool. */ checkpointAttestationCallback;
77
493
  /**
78
494
  * Callback for when a block is received from a peer.
79
495
  * @param block - The block received from the peer.
80
496
  * @returns The attestation for the block, if any.
81
497
  */ blockReceivedCallback;
498
+ /**
499
+ * Callback for when a checkpoint proposal is received from a peer.
500
+ * @param checkpoint - The checkpoint proposal received from the peer.
501
+ * @returns The attestations for the checkpoint, if any.
502
+ */ allNodesCheckpointReceivedCallback;
503
+ /**
504
+ * Callback for when a checkpoint proposal is received - specifically for validators - from a peer.
505
+ * @param checkpoint - The checkpoint proposal received from the peer.
506
+ * @returns The attestations for the checkpoint, if any.
507
+ */ validatorCheckpointReceivedCallback;
82
508
  gossipSubEventHandler;
509
+ ipChangedHandler;
510
+ discoveredP2pIp;
83
511
  instrumentation;
84
- constructor(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
85
- super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.logger = logger, this.jobQueue = new SerialQueue(), this.msgIdSeenValidators = {}, this.protocolVersion = '', this.topicStrings = {};
512
+ telemetry;
513
+ logger;
514
+ constructor(config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, blockMinFeesProvider, telemetry, logger = createLogger('p2p:libp2p_service'), txValidationCache){
515
+ super(telemetry, 'LibP2PService'), this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.blockMinFeesProvider = blockMinFeesProvider, this.txValidationCache = txValidationCache, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
516
+ this.telemetry = telemetry;
517
+ // Create child logger with fisherman prefix if in fisherman mode
518
+ this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
86
519
  this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
87
520
  this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
88
521
  this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
89
- this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
522
+ this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
523
+ this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
90
524
  const versions = getVersions(config);
91
525
  this.protocolVersion = compressComponentVersions(versions);
92
526
  logger.info(`Started libp2p service with protocol version ${this.protocolVersion}`);
93
527
  this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
94
528
  this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
95
- this.topicStrings[TopicType.block_attestation] = createTopicString(TopicType.block_attestation, this.protocolVersion);
96
- this.attestationValidator = new AttestationValidator(epochCache);
97
- this.blockProposalValidator = new BlockProposalValidator(epochCache, {
98
- txsPermitted: !config.disableTransactions
99
- });
529
+ this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(TopicType.checkpoint_proposal, this.protocolVersion);
530
+ this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(TopicType.checkpoint_attestation, this.protocolVersion);
531
+ const p2pPropagationTime = config.attestationPropagationTime;
532
+ const proposalValidatorOpts = {
533
+ txsPermitted: !config.disableTransactions,
534
+ maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint,
535
+ maxBlocksPerCheckpoint: config.maxBlocksPerCheckpoint,
536
+ p2pPropagationTime,
537
+ skipSlotValidation: config.skipProposalSlotValidation,
538
+ signatureContext: {
539
+ chainId: config.l1ChainId,
540
+ rollupAddress: config.rollupAddress
541
+ }
542
+ };
543
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, proposalValidatorOpts);
544
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, proposalValidatorOpts);
545
+ const attestationValidatorOpts = {
546
+ l1PublishingTime: config.l1PublishingTime,
547
+ p2pPropagationTime,
548
+ signatureContext: proposalValidatorOpts.signatureContext
549
+ };
550
+ this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, attestationValidatorOpts) : new CheckpointAttestationValidator(epochCache, attestationValidatorOpts);
100
551
  this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
101
552
  this.blockReceivedCallback = async (block)=>{
102
- this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`, {
103
- p2pMessageIdentifier: await block.p2pMessageIdentifier()
553
+ this.logger.warn(`Handler for block received not yet registered on P2P service. Received block ${block.blockNumber} for slot ${block.slotNumber} from peer.`, {
554
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier()
104
555
  });
105
- return undefined;
556
+ return true;
557
+ };
558
+ this.allNodesCheckpointReceivedCallback = (_checkpoint)=>{
559
+ throw new CheckpointProposalReceivedCallbackNotRegisteredError();
560
+ };
561
+ this.validatorCheckpointReceivedCallback = (_checkpoint)=>{
562
+ return Promise.resolve(undefined);
106
563
  };
107
564
  }
108
565
  updateConfig(config) {
109
566
  this.reqresp.updateConfig(config);
567
+ this.config = merge(this.config, config);
110
568
  }
111
569
  /**
112
570
  * Creates an instance of the LibP2P service.
113
571
  * @param config - The configuration to use when creating the service.
114
572
  * @param txPool - The transaction pool to be accessed by the service.
115
573
  * @returns The new service.
116
- */ static async new(clientType, config, peerId, deps) {
117
- const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = deps;
574
+ */ static async new(config, peerId, deps) {
575
+ const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, blockMinFeesProvider, telemetry, logger, packageVersion, txValidationCache } = deps;
118
576
  const { p2pPort, maxPeerCount, listenAddress } = config;
119
577
  const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
120
578
  const datastore = new AztecDatastore(peerStore);
121
- const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
122
- const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`));
579
+ const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
580
+ const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()));
123
581
  // Seed libp2p's bootstrap discovery with private and trusted peers
124
582
  const bootstrapNodes = [
125
583
  ...config.privatePeers,
@@ -133,9 +591,6 @@ import { P2PInstrumentation } from './instrumentation.js';
133
591
  }
134
592
  const versions = getVersions(config);
135
593
  const protocolVersion = compressComponentVersions(versions);
136
- const txTopic = createTopicString(TopicType.tx, protocolVersion);
137
- const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
138
- const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
139
594
  const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
140
595
  const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
141
596
  const peerId = await enr.peerId();
@@ -153,6 +608,18 @@ import { P2PInstrumentation } from './instrumentation.js';
153
608
  const announceTcpMultiaddr = config.p2pIp ? [
154
609
  convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
155
610
  ] : [];
611
+ // Create dynamic topic score params based on network configuration
612
+ const l1Constants = epochCache.getL1Constants();
613
+ const topicScoreParams = createAllTopicScoreParams(protocolVersion, {
614
+ slotDurationMs: l1Constants.slotDuration * 1000,
615
+ ethereumSlotDuration: l1Constants.ethereumSlotDuration,
616
+ heartbeatIntervalMs: config.gossipsubInterval,
617
+ targetCommitteeSize: l1Constants.targetCommitteeSize,
618
+ blockDurationMs: config.blockDurationMs,
619
+ l1PublishingTime: config.l1PublishingTime,
620
+ p2pPropagationTime: config.attestationPropagationTime,
621
+ expectedBlockProposalsPerSlot: config.expectedBlockProposalsPerSlot
622
+ });
156
623
  const node = await createLibp2p({
157
624
  start: false,
158
625
  peerId,
@@ -253,38 +720,29 @@ import { P2PInstrumentation } from './instrumentation.js';
253
720
  scoreParams: createPeerScoreParams({
254
721
  // IPColocation factor can be disabled for local testing - default to -5
255
722
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
256
- topics: {
257
- [txTopic]: createTopicScoreParams({
258
- topicWeight: 1,
259
- invalidMessageDeliveriesWeight: -20,
260
- invalidMessageDeliveriesDecay: 0.5
261
- }),
262
- [blockAttestationTopic]: createTopicScoreParams({
263
- topicWeight: 1,
264
- invalidMessageDeliveriesWeight: -20,
265
- invalidMessageDeliveriesDecay: 0.5
266
- }),
267
- [blockProposalTopic]: createTopicScoreParams({
268
- topicWeight: 1,
269
- invalidMessageDeliveriesWeight: -20,
270
- invalidMessageDeliveriesDecay: 0.5
271
- })
272
- }
723
+ topics: topicScoreParams
273
724
  })
274
725
  }),
275
726
  components: (components)=>({
276
- connectionManager: components.connectionManager
727
+ connectionManager: components.connectionManager,
728
+ addressManager: components.addressManager
277
729
  })
278
730
  },
279
- logger: createLibp2pComponentLogger(logger.module)
731
+ logger: createLibp2pComponentLogger(logger.module, logger.getBindings())
280
732
  });
281
- const peerScoring = new PeerScoring(config);
733
+ const peerScoring = new PeerScoring(config, telemetry);
282
734
  const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
283
735
  const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
284
- // Update gossipsub score params
285
- node.services.pubsub.score.params.appSpecificWeight = 10;
736
+ // Gate req/resp data protocols for unauthenticated peers when p2pAllowOnlyValidators is enabled
737
+ reqresp.setShouldRejectPeer((peerId)=>peerManager.shouldDisableP2PGossip(peerId));
738
+ // Configure application-specific scoring for gossipsub.
739
+ // The weight scales app score to align with gossipsub thresholds:
740
+ // - Disconnect (-50) × 10 = -500 = gossipThreshold (stops receiving gossip)
741
+ // - Ban (-100) × 10 = -1000 = publishThreshold (cannot publish)
742
+ // Note: positive topic scores can offset penalties, so alignment is best-effort.
743
+ node.services.pubsub.score.params.appSpecificWeight = APP_SPECIFIC_WEIGHT;
286
744
  node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
287
- return new LibP2PService(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
745
+ return new LibP2PService(config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, blockMinFeesProvider, telemetry, logger, txValidationCache);
288
746
  }
289
747
  /**
290
748
  * Starts the LibP2P service.
@@ -294,55 +752,72 @@ import { P2PInstrumentation } from './instrumentation.js';
294
752
  if (this.node.status === 'started') {
295
753
  throw new Error('P2P service already started');
296
754
  }
297
- // Get listen & announce addresses for logging
298
755
  const { p2pIp, p2pPort } = this.config;
299
- if (!p2pIp) {
300
- throw new Error('Announce address not provided.');
301
- }
302
- const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
303
- // Start job queue, peer discovery service and libp2p node
304
- this.jobQueue.start();
305
- await this.peerManager.initializePeers();
306
- if (!this.config.p2pDiscoveryDisabled) {
307
- await this.peerDiscoveryService.start();
308
- }
309
- await this.node.start();
310
- // Subscribe to standard GossipSub topics by default
311
- for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)){
312
- this.subscribeToTopic(this.topicStrings[topic]);
756
+ if (!p2pIp && !this.config.queryForIp) {
757
+ throw new Error('Announce address not provided and queryForIp is not enabled.');
313
758
  }
759
+ const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
314
760
  // Create request response protocol handlers
315
761
  const txHandler = reqRespTxHandler(this.mempools);
316
762
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
317
- const blockHandler = reqRespBlockHandler(this.archiver);
318
763
  const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
319
764
  const requestResponseHandlers = {
320
765
  [ReqRespSubProtocol.PING]: pingHandler,
321
766
  [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
322
- [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
323
- [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
767
+ [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this)
324
768
  };
325
- // Only handle block transactions request if attestation pool is available to the client
326
- if (this.mempools.attestationPool && !this.config.disableTransactions) {
327
- const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
769
+ if (!this.config.disableTransactions) {
770
+ const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.archiver, this.mempools.txPool);
328
771
  requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
329
772
  }
330
773
  if (!this.config.disableTransactions) {
331
774
  requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
332
775
  }
776
+ await this.peerManager.initializePeers();
777
+ await this.reqresp.start(requestResponseHandlers);
778
+ await this.node.start();
779
+ // Subscribe to standard GossipSub topics by default
780
+ for (const topic of getTopicsForConfig(this.config.disableTransactions)){
781
+ this.subscribeToTopic(this.topicStrings[topic]);
782
+ }
333
783
  // add GossipSub listener
334
784
  this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
335
- // Start running promise for peer discovery
336
- this.discoveryRunningPromise = new RunningPromise(()=>this.peerManager.heartbeat(), this.logger, this.config.peerCheckIntervalMS);
785
+ // Start running promise for peer discovery and metrics collection
786
+ if (!this.config.p2pDiscoveryDisabled) {
787
+ await this.peerDiscoveryService.start();
788
+ }
789
+ // Bridge discv5 IP changes to libp2p's AddressManager so peers see the updated address
790
+ if (this.config.queryForIp) {
791
+ this.discoveredP2pIp = this.config.p2pIp;
792
+ this.logger.info('IP change tracking enabled, bridging discv5 IP updates to libp2p AddressManager');
793
+ this.ipChangedHandler = (ip)=>{
794
+ const addressManager = this.node.services.components.addressManager;
795
+ const newAddr = multiaddr(convertToMultiaddr(ip, this.config.p2pPort, 'tcp'));
796
+ const previousIp = this.discoveredP2pIp;
797
+ if (previousIp) {
798
+ const oldAddr = multiaddr(convertToMultiaddr(previousIp, this.config.p2pPort, 'tcp'));
799
+ addressManager.removeObservedAddr(oldAddr);
800
+ this.logger.info('Libp2p announce address updated due to IP change', {
801
+ previousIp,
802
+ newIp: ip,
803
+ newMultiaddr: newAddr.toString()
804
+ });
805
+ } else {
806
+ this.logger.info('Libp2p announce address set from initial discv5 IP discovery', {
807
+ ip,
808
+ multiaddr: newAddr.toString()
809
+ });
810
+ }
811
+ addressManager.addObservedAddr(newAddr);
812
+ addressManager.confirmObservedAddr(newAddr);
813
+ this.discoveredP2pIp = ip;
814
+ };
815
+ this.peerDiscoveryService.on('ip:changed', this.ipChangedHandler);
816
+ }
817
+ this.discoveryRunningPromise = new RunningPromise(async ()=>{
818
+ await this.peerManager.heartbeat();
819
+ }, this.logger, this.config.peerCheckIntervalMS);
337
820
  this.discoveryRunningPromise.start();
338
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
339
- const reqrespSubProtocolValidators = {
340
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
341
- // TODO(#11336): A request validator for blocks
342
- [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
343
- [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this)
344
- };
345
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
346
821
  this.logger.info(`Started P2P service`, {
347
822
  listen: this.config.listenAddress,
348
823
  port: this.config.p2pPort,
@@ -356,11 +831,13 @@ import { P2PInstrumentation } from './instrumentation.js';
356
831
  */ async stop() {
357
832
  // Remove gossip sub listener
358
833
  this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
834
+ if (this.ipChangedHandler) {
835
+ this.peerDiscoveryService.removeListener('ip:changed', this.ipChangedHandler);
836
+ this.ipChangedHandler = undefined;
837
+ }
359
838
  // Stop peer manager
360
839
  this.logger.debug('Stopping peer manager...');
361
840
  await this.peerManager.stop();
362
- this.logger.debug('Stopping job queue...');
363
- await this.jobQueue.end();
364
841
  this.logger.debug('Stopping running promise...');
365
842
  await this.discoveryRunningPromise?.stop();
366
843
  this.logger.debug('Stopping peer discovery service...');
@@ -371,8 +848,8 @@ import { P2PInstrumentation } from './instrumentation.js';
371
848
  await this.stopLibP2P();
372
849
  this.logger.info('LibP2P service stopped');
373
850
  }
374
- addReqRespSubProtocol(subProtocol, handler, validator) {
375
- return this.reqresp.addSubProtocol(subProtocol, handler, validator);
851
+ addReqRespSubProtocol(subProtocol, handler) {
852
+ return this.reqresp.addSubProtocol(subProtocol, handler);
376
853
  }
377
854
  registerThisValidatorAddresses(address) {
378
855
  this.peerManager.registerThisValidatorAddresses(address);
@@ -380,6 +857,9 @@ import { P2PInstrumentation } from './instrumentation.js';
380
857
  getPeers(includePending) {
381
858
  return this.peerManager.getPeers(includePending);
382
859
  }
860
+ getGossipMeshPeerCount(topicType) {
861
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
862
+ }
383
863
  handleGossipSubEvent(e) {
384
864
  this.logger.trace(`Received PUBSUB message.`);
385
865
  const safeJob = async ()=>{
@@ -391,13 +871,8 @@ import { P2PInstrumentation } from './instrumentation.js';
391
871
  };
392
872
  setImmediate(()=>void safeJob());
393
873
  }
394
- /**
395
- * Send a batch of requests to peers, and return the responses
396
- * @param protocol - The request response protocol to use
397
- * @param requests - The requests to send to the peers
398
- * @returns The responses to the requests
399
- */ sendBatchRequest(protocol, requests, pinnedPeerId) {
400
- return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
874
+ sendRequestToPeer(peerId, subProtocol, payload, dialTimeout) {
875
+ return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
401
876
  }
402
877
  /**
403
878
  * Get the ENR of the node
@@ -408,6 +883,28 @@ import { P2PInstrumentation } from './instrumentation.js';
408
883
  registerBlockReceivedCallback(callback) {
409
884
  this.blockReceivedCallback = callback;
410
885
  }
886
+ registerValidatorCheckpointReceivedCallback(callback) {
887
+ this.validatorCheckpointReceivedCallback = callback;
888
+ }
889
+ registerAllNodesCheckpointReceivedCallback(callback) {
890
+ this.allNodesCheckpointReceivedCallback = callback;
891
+ }
892
+ /**
893
+ * Registers a callback to be invoked when a duplicate proposal is detected.
894
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
895
+ */ registerDuplicateProposalCallback(callback) {
896
+ this.duplicateProposalCallback = callback;
897
+ }
898
+ /**
899
+ * Registers a callback to be invoked when a duplicate attestation is detected.
900
+ * A validator signing attestations for different proposals at the same slot.
901
+ * This callback is triggered on the first duplicate (when count goes from 1 to 2).
902
+ */ registerDuplicateAttestationCallback(callback) {
903
+ this.duplicateAttestationCallback = callback;
904
+ }
905
+ registerCheckpointAttestationCallback(callback) {
906
+ this.checkpointAttestationCallback = callback;
907
+ }
411
908
  /**
412
909
  * Subscribes to a topic.
413
910
  * @param topic - The topic to subscribe to.
@@ -426,7 +923,9 @@ import { P2PInstrumentation } from './instrumentation.js';
426
923
  if (!this.node.services.pubsub) {
427
924
  throw new Error('Pubsub service not available.');
428
925
  }
429
- const p2pMessage = P2PMessage.fromGossipable(message);
926
+ const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
927
+ const traceContext = this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
928
+ const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
430
929
  const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
431
930
  return result.recipients.length;
432
931
  }
@@ -440,12 +939,15 @@ import { P2PInstrumentation } from './instrumentation.js';
440
939
  case this.topicStrings[TopicType.tx]:
441
940
  topicType = TopicType.tx;
442
941
  break;
443
- case this.topicStrings[TopicType.block_attestation]:
444
- topicType = TopicType.block_attestation;
445
- break;
446
942
  case this.topicStrings[TopicType.block_proposal]:
447
943
  topicType = TopicType.block_proposal;
448
944
  break;
945
+ case this.topicStrings[TopicType.checkpoint_proposal]:
946
+ topicType = TopicType.checkpoint_proposal;
947
+ break;
948
+ case this.topicStrings[TopicType.checkpoint_attestation]:
949
+ topicType = TopicType.checkpoint_attestation;
950
+ break;
449
951
  default:
450
952
  this.logger.error(`Received message on unknown topic: ${msg.topic}`);
451
953
  break;
@@ -454,6 +956,12 @@ import { P2PInstrumentation } from './instrumentation.js';
454
956
  if (!validator || !validator.addMessage(msgId)) {
455
957
  this.instrumentation.incMessagePrevalidationStatus(false, topicType);
456
958
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
959
+ if (topicType === TopicType.tx) {
960
+ this.logger.verbose(`Ignoring already-seen tx gossip message`, {
961
+ msgId,
962
+ source: source.toString()
963
+ });
964
+ }
457
965
  return {
458
966
  result: false,
459
967
  topicType
@@ -466,69 +974,262 @@ import { P2PInstrumentation } from './instrumentation.js';
466
974
  };
467
975
  }
468
976
  /**
977
+ * Safely deserializes a P2PMessage from raw message data.
978
+ * @param msgId - The message ID.
979
+ * @param source - The peer ID of the message source.
980
+ * @param data - The raw message data.
981
+ * @returns The deserialized P2PMessage or undefined if deserialization fails.
982
+ */ safelyDeserializeP2PMessage(msgId, source, data) {
983
+ try {
984
+ return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
985
+ } catch (err) {
986
+ this.logger.error(`Error deserializing P2PMessage`, err, {
987
+ msgId,
988
+ source: source.toString()
989
+ });
990
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
991
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
992
+ return undefined;
993
+ }
994
+ }
995
+ /**
469
996
  * Handles a new gossip message that was received by the client.
470
997
  * @param topic - The message's topic.
471
998
  * @param data - The message data
472
999
  */ async handleNewGossipMessage(msg, msgId, source) {
473
- const p2pMessage = P2PMessage.fromMessageData(Buffer.from(msg.data));
1000
+ const msgReceivedTime = Date.now();
1001
+ let topicType;
1002
+ const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
1003
+ if (!p2pMessage) {
1004
+ return;
1005
+ }
474
1006
  const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
475
1007
  if (!preValidationResult.result) {
476
1008
  return;
477
1009
  }
1010
+ // Determine topic type for attributes
478
1011
  if (msg.topic === this.topicStrings[TopicType.tx]) {
479
- await this.handleGossipedTx(p2pMessage.payload, msgId, source);
1012
+ topicType = TopicType.tx;
1013
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
1014
+ topicType = TopicType.checkpoint_attestation;
1015
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
1016
+ topicType = TopicType.block_proposal;
1017
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
1018
+ topicType = TopicType.checkpoint_proposal;
480
1019
  }
481
- if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
482
- await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
1020
+ // Process the message, optionally within a linked span for trace propagation
1021
+ const processMessage = async ()=>{
1022
+ if (this.config.skipIncomingProposals && (msg.topic === this.topicStrings[TopicType.block_proposal] || msg.topic === this.topicStrings[TopicType.checkpoint_proposal])) {
1023
+ this.logger.warn(`Ignoring incoming proposal (skipIncomingProposals is set)`, {
1024
+ topic: msg.topic
1025
+ });
1026
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
1027
+ return;
1028
+ }
1029
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
1030
+ await this.handleGossipedTx(p2pMessage.payload, msgId, source);
1031
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
1032
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
1033
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
1034
+ await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
1035
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
1036
+ await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
1037
+ } else {
1038
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
1039
+ }
1040
+ };
1041
+ const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
1042
+ const propagatedContext = p2pMessage.traceContext ? this.telemetry.extractPropagatedContext(p2pMessage.traceContext) : undefined;
1043
+ if (propagatedContext) {
1044
+ await this.tracer.startActiveSpan('LibP2PService.processMessage', {
1045
+ attributes: {
1046
+ [Attributes.TOPIC_NAME]: topicType,
1047
+ [Attributes.PEER_ID]: source.toString()
1048
+ }
1049
+ }, propagatedContext, async (span)=>{
1050
+ try {
1051
+ await processMessage();
1052
+ span.setStatus({
1053
+ code: SpanStatusCode.OK
1054
+ });
1055
+ } catch (err) {
1056
+ span.setStatus({
1057
+ code: SpanStatusCode.ERROR,
1058
+ message: String(err)
1059
+ });
1060
+ if (typeof err === 'string' || err && err instanceof Error) {
1061
+ span.recordException(err);
1062
+ }
1063
+ throw err;
1064
+ } finally{
1065
+ span.end();
1066
+ }
1067
+ });
1068
+ } else {
1069
+ await processMessage();
483
1070
  }
484
- if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
485
- await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
1071
+ if (latency !== undefined && topicType !== undefined) {
1072
+ this.instrumentation.recordMessageLatency(topicType, latency);
486
1073
  }
487
1074
  return;
488
1075
  }
489
1076
  async validateReceivedMessage(validationFunc, msgId, source, topicType) {
1077
+ // Default to reject result with a penalty if validation function throws an error
490
1078
  let resultAndObj = {
491
- result: TopicValidatorResult.Reject
1079
+ result: TopicValidatorResult.Reject,
1080
+ severity: PeerErrorSeverity.MidToleranceError
492
1081
  };
493
1082
  const timer = new Timer();
494
1083
  try {
495
1084
  resultAndObj = await validationFunc();
496
1085
  } catch (err) {
497
- this.logger.error(`Error deserializing and validating gossipsub message`, err, {
1086
+ this.logger.error(`Error validating gossipsub message`, err, {
498
1087
  msgId,
499
1088
  source: source.toString(),
500
1089
  topicType
501
1090
  });
502
1091
  }
1092
+ const validationTimeMs = timer.ms();
1093
+ const mcacheWindowMs = this.config.gossipsubMcacheLength * this.config.gossipsubInterval;
1094
+ if (validationTimeMs > mcacheWindowMs * 0.75) {
1095
+ this.instrumentation.incSlowValidation(topicType);
1096
+ this.logger.warn(`Gossip validation for ${topicType} took ${validationTimeMs}ms, approaching mcache eviction window of ${mcacheWindowMs}ms. ` + `Message forwarding may be skipped if validation exceeds the window.`, {
1097
+ msgId,
1098
+ source: source.toString(),
1099
+ topicType,
1100
+ validationTimeMs,
1101
+ mcacheWindowMs
1102
+ });
1103
+ }
503
1104
  if (resultAndObj.result === TopicValidatorResult.Accept) {
1105
+ this.logger.debug(`Message ${topicType} accepted by validator`, {
1106
+ msgId,
1107
+ source: source.toString(),
1108
+ topicType
1109
+ });
504
1110
  this.instrumentation.recordMessageValidation(topicType, timer);
1111
+ } else if (resultAndObj.result === TopicValidatorResult.Reject) {
1112
+ this.logger.warn(`Message ${topicType} rejected by validator with severity ${resultAndObj.severity}`, {
1113
+ msgId,
1114
+ source: source.toString(),
1115
+ topicType,
1116
+ severity: resultAndObj.severity
1117
+ });
1118
+ this.peerManager.penalizePeer(source, resultAndObj.severity);
1119
+ } else {
1120
+ this.logger.trace(`Message ${topicType} ignored by validator`, {
1121
+ msgId,
1122
+ source: source.toString(),
1123
+ topicType
1124
+ });
505
1125
  }
506
1126
  this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
507
1127
  return resultAndObj;
508
1128
  }
1129
+ tryDeserialize(deserializeFunc, msgId, source) {
1130
+ try {
1131
+ return deserializeFunc();
1132
+ } catch (err) {
1133
+ this.logger.warn(`Failed to deserialize gossipsub message from buffer`, {
1134
+ err,
1135
+ msgId,
1136
+ source: source.toString()
1137
+ });
1138
+ return undefined;
1139
+ }
1140
+ }
509
1141
  async handleGossipedTx(payloadData, msgId, source) {
510
1142
  const validationFunc = async ()=>{
511
- const tx = Tx.fromBuffer(payloadData);
512
- const isValid = await this.validatePropagatedTx(tx, source);
513
- const exists = isValid && await this.mempools.txPool.hasTx(tx.getTxHash());
514
- this.logger.trace(`Validate propagated tx`, {
515
- isValid,
516
- exists,
1143
+ const tx = this.tryDeserialize(()=>Tx.fromBuffer(payloadData), msgId, source);
1144
+ if (!tx) {
1145
+ return {
1146
+ result: TopicValidatorResult.Reject,
1147
+ severity: PeerErrorSeverity.LowToleranceError
1148
+ };
1149
+ }
1150
+ const currentBlockNumber = await this.archiver.getBlockNumber();
1151
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1152
+ // Stage 1: fast validators (metadata, data, timestamps, double-spend, gas, phases, block header)
1153
+ const firstStageValidators = await this.createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp);
1154
+ const firstStageOutcome = await this.runValidations(tx, firstStageValidators);
1155
+ if (!firstStageOutcome.allPassed) {
1156
+ const { name } = firstStageOutcome.failure;
1157
+ let { severity } = firstStageOutcome.failure;
1158
+ // Double spend validator has a special case handler. We perform more detailed examination
1159
+ // as to how recently the nullifier was entered into the tree and if the transaction should
1160
+ // have 'known' the nullifier existed. This determines the severity of the penalty applied to the peer.
1161
+ if (name === 'doubleSpendValidator') {
1162
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1);
1163
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1164
+ }
1165
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 1 validation failed`, {
1166
+ validator: name,
1167
+ severity,
1168
+ source: source.toString()
1169
+ });
1170
+ return {
1171
+ result: TopicValidatorResult.Reject,
1172
+ severity
1173
+ };
1174
+ }
1175
+ // Pool pre-check: see if the pool would accept this tx before doing expensive proof verification
1176
+ const canAdd = await this.mempools.txPool.canAddPendingTx(tx);
1177
+ if (canAdd === 'ignored') {
1178
+ this.logger.verbose(`Ignoring gossiped tx ${tx.getTxHash().toString()}: pool pre-check returned ignored`, {
1179
+ source: source.toString()
1180
+ });
1181
+ return {
1182
+ result: TopicValidatorResult.Ignore,
1183
+ obj: tx
1184
+ };
1185
+ }
1186
+ // Stage 2: expensive proof verification
1187
+ const secondStageValidators = this.createSecondStageMessageValidators();
1188
+ const secondStageOutcome = await this.runValidations(tx, secondStageValidators);
1189
+ if (!secondStageOutcome.allPassed) {
1190
+ const { severity, name } = secondStageOutcome.failure;
1191
+ this.logger.verbose(`Rejecting gossiped tx ${tx.getTxHash().toString()}: stage 2 validation failed`, {
1192
+ validator: name,
1193
+ severity,
1194
+ source: source.toString()
1195
+ });
1196
+ return {
1197
+ result: TopicValidatorResult.Reject,
1198
+ severity
1199
+ };
1200
+ }
1201
+ // Pool add: persist the tx
1202
+ const txHash = tx.getTxHash();
1203
+ const addResult = await this.mempools.txPool.addPendingTxs([
1204
+ tx
1205
+ ], {
1206
+ source: 'gossip'
1207
+ });
1208
+ const wasAccepted = addResult.accepted.some((h)=>h.equals(txHash));
1209
+ const wasIgnored = addResult.ignored.some((h)=>h.equals(txHash));
1210
+ this.logger.verbose(`Validate propagated tx ${txHash.toString()}`, {
1211
+ wasAccepted,
1212
+ wasIgnored,
517
1213
  [Attributes.P2P_ID]: source.toString()
518
1214
  });
519
- if (!isValid) {
1215
+ if (wasAccepted) {
520
1216
  return {
521
- result: TopicValidatorResult.Reject
1217
+ result: TopicValidatorResult.Accept,
1218
+ obj: tx
522
1219
  };
523
- } else if (exists) {
1220
+ } else if (wasIgnored) {
524
1221
  return {
525
1222
  result: TopicValidatorResult.Ignore,
526
1223
  obj: tx
527
1224
  };
528
1225
  } else {
1226
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
1227
+ source: source.toString(),
1228
+ txHash: txHash.toString()
1229
+ });
529
1230
  return {
530
- result: TopicValidatorResult.Accept,
531
- obj: tx
1231
+ result: TopicValidatorResult.Reject,
1232
+ severity: PeerErrorSeverity.HighToleranceError
532
1233
  };
533
1234
  }
534
1235
  };
@@ -536,165 +1237,457 @@ import { P2PInstrumentation } from './instrumentation.js';
536
1237
  if (result !== TopicValidatorResult.Accept || !tx) {
537
1238
  return;
538
1239
  }
1240
+ // Tx was accepted into pool and will be propagated - just log and record metrics
539
1241
  const txHash = tx.getTxHash();
540
1242
  const txHashString = txHash.toString();
541
1243
  this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
542
1244
  source: source.toString(),
543
1245
  txHash: txHashString
544
1246
  });
545
- if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
546
- this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
547
- return;
548
- }
549
- await this.mempools.txPool.addTxs([
550
- tx
551
- ]);
1247
+ this.instrumentation.incrementTxReceived(1);
552
1248
  }
553
1249
  /**
554
- * Process Attestation From Peer
555
- * When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
556
- *
557
- * @param attestation - The attestation to process.
558
- */ async processAttestationFromPeer(payloadData, msgId, source) {
559
- const validationFunc = async ()=>{
560
- const attestation = BlockAttestation.fromBuffer(payloadData);
561
- const isValid = await this.validateAttestation(source, attestation);
562
- const exists = isValid && await this.mempools.attestationPool.hasAttestation(attestation);
563
- this.logger.trace(`Validate propagated block attestation`, {
564
- isValid,
565
- exists,
566
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
567
- [Attributes.P2P_ID]: source.toString()
568
- });
569
- if (!isValid) {
570
- return {
571
- result: TopicValidatorResult.Reject
572
- };
573
- } else if (exists) {
574
- return {
575
- result: TopicValidatorResult.Ignore,
576
- obj: attestation
577
- };
578
- } else {
579
- return {
580
- result: TopicValidatorResult.Accept,
581
- obj: attestation
582
- };
1250
+ * Process a checkpoint attestation from a peer.
1251
+ * Validates the attestation and adds it to the pool.
1252
+ */ async processCheckpointAttestationFromPeer(payloadData, msgId, source) {
1253
+ const { result, obj: attestation } = await this.validateReceivedMessage(()=>{
1254
+ const attestation = this.tryDeserialize(()=>CheckpointAttestation.fromBuffer(payloadData), msgId, source);
1255
+ if (!attestation) {
1256
+ return Promise.resolve({
1257
+ result: TopicValidatorResult.Reject,
1258
+ severity: PeerErrorSeverity.LowToleranceError
1259
+ });
583
1260
  }
584
- };
585
- const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_attestation);
1261
+ return this.validateAndStoreCheckpointAttestation(source, attestation);
1262
+ }, msgId, source, TopicType.checkpoint_attestation);
586
1263
  if (result !== TopicValidatorResult.Accept || !attestation) {
587
1264
  return;
588
1265
  }
589
- this.logger.debug(`Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`, {
590
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
591
- slot: attestation.slotNumber.toNumber(),
1266
+ this.logger.verbose(`Received valid checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`, {
1267
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
1268
+ slot: attestation.slotNumber,
592
1269
  archive: attestation.archive.toString(),
593
1270
  source: source.toString()
594
1271
  });
595
- await this.mempools.attestationPool.addAttestations([
596
- attestation
597
- ]);
598
1272
  }
599
- async processBlockFromPeer(payloadData, msgId, source) {
600
- const validationFunc = async ()=>{
601
- const block = BlockProposal.fromBuffer(payloadData);
602
- const isValid = await this.validateBlockProposal(source, block);
603
- // Note that we dont have an attestation pool if we're a prover node, but we still
604
- // subscribe to block proposal topics in order to prevent their txs from being cleared.
605
- const exists = isValid && await this.mempools.attestationPool?.hasBlockProposal(block);
606
- this.logger.trace(`Validate propagated block proposal`, {
607
- isValid,
608
- exists,
609
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
610
- [Attributes.P2P_ID]: source.toString()
1273
+ /** Validates a checkpoint attestation and adds it to the pool. Penalizes the peer if validation fails. */ async validateAndStoreCheckpointAttestation(peerId, attestation) {
1274
+ const validationResult = await this.checkpointAttestationValidator.validate(attestation);
1275
+ if (validationResult.result === 'reject') {
1276
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1277
+ return {
1278
+ result: TopicValidatorResult.Reject,
1279
+ severity: validationResult.severity
1280
+ };
1281
+ }
1282
+ if (validationResult.result === 'ignore') {
1283
+ return {
1284
+ result: TopicValidatorResult.Ignore,
1285
+ obj: attestation
1286
+ };
1287
+ }
1288
+ // Try to add the attestation: this handles existence check, cap check, and adding in one call
1289
+ // count is the number of attestations by this signer for this slot (for duplicate detection)
1290
+ const slot = attestation.payload.header.slotNumber;
1291
+ const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddCheckpointAttestation(attestation);
1292
+ this.logger.trace(`Validate propagated checkpoint attestation`, {
1293
+ added,
1294
+ alreadyExists,
1295
+ count,
1296
+ [Attributes.SLOT_NUMBER]: slot.toString(),
1297
+ [Attributes.P2P_ID]: peerId.toString()
1298
+ });
1299
+ // Exact same attestation received, no need to re-broadcast
1300
+ if (alreadyExists) {
1301
+ return {
1302
+ result: TopicValidatorResult.Ignore,
1303
+ obj: attestation
1304
+ };
1305
+ }
1306
+ // Could not add (cap reached for signer), penalize and do not re-broadcast
1307
+ if (!added) {
1308
+ this.logger.warn(`Rejecting checkpoint attestation due to cap`, {
1309
+ slot: slot.toString(),
1310
+ archive: attestation.archive.toString(),
1311
+ source: peerId.toString(),
1312
+ attester: attestation.getSender()?.toString(),
1313
+ count
611
1314
  });
612
- if (!isValid) {
613
- return {
614
- result: TopicValidatorResult.Reject
615
- };
616
- } else if (exists) {
617
- return {
618
- result: TopicValidatorResult.Ignore,
619
- obj: block
620
- };
621
- } else {
622
- return {
623
- result: TopicValidatorResult.Accept,
624
- obj: block
625
- };
1315
+ return {
1316
+ result: TopicValidatorResult.Reject,
1317
+ severity: PeerErrorSeverity.HighToleranceError
1318
+ };
1319
+ }
1320
+ // Check if this is a duplicate attestation (signer attested to a different proposal at the same slot)
1321
+ // count is the number of attestations by this signer for this slot
1322
+ if (count === 2) {
1323
+ const attester = attestation.getSender();
1324
+ if (attester) {
1325
+ this.logger.warn(`Detected duplicate attestation (equivocation) at slot ${slot}`, {
1326
+ slot: slot.toString(),
1327
+ archive: attestation.archive.toString(),
1328
+ source: peerId.toString(),
1329
+ attester: attester.toString()
1330
+ });
1331
+ this.duplicateAttestationCallback?.({
1332
+ slot,
1333
+ attester
1334
+ });
626
1335
  }
1336
+ }
1337
+ // Attestation was added successfully - accept it so other nodes can also detect the equivocation
1338
+ this.checkpointAttestationCallback?.(attestation);
1339
+ return {
1340
+ result: TopicValidatorResult.Accept,
1341
+ obj: attestation
627
1342
  };
628
- const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_proposal);
629
- if (!result || !block) {
1343
+ }
1344
+ async processBlockFromPeer(payloadData, msgId, source) {
1345
+ const { result, obj: block, metadata: { isEquivocated } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreBlockProposal(source, BlockProposal.fromBuffer(payloadData)), msgId, source, TopicType.block_proposal);
1346
+ // If not accepted or equivocated, return
1347
+ if (result !== TopicValidatorResult.Accept || !block || isEquivocated) {
630
1348
  return;
631
1349
  }
632
1350
  await this.processValidBlockProposal(block, source);
633
1351
  }
634
- // REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
1352
+ /** Validates a block proposal. Triggers a penalization to the peer that sent it if invalid. Adds to the mempool if valid. */ async validateAndStoreBlockProposal(peerId, block) {
1353
+ const validationResult = await this.blockProposalValidator.validate(block);
1354
+ if (validationResult.result === 'reject') {
1355
+ this.logger.warn(`Penalizing peer ${peerId} for block proposal validation failure`);
1356
+ return {
1357
+ result: TopicValidatorResult.Reject,
1358
+ severity: validationResult.severity
1359
+ };
1360
+ }
1361
+ if (validationResult.result === 'ignore') {
1362
+ return {
1363
+ result: TopicValidatorResult.Ignore,
1364
+ obj: block
1365
+ };
1366
+ }
1367
+ // Try to add the proposal: this handles existence check, cap check, and adding in one call
1368
+ const { added, alreadyExists, count } = await this.mempools.attestationPool.tryAddBlockProposal(block);
1369
+ const isEquivocated = count !== undefined && count > 1;
1370
+ // Duplicate proposal received, no need to re-broadcast
1371
+ if (alreadyExists) {
1372
+ this.logger.debug(`Ignoring duplicate block proposal received`, {
1373
+ ...block.toBlockInfo(),
1374
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1375
+ proposer: block.getSender()?.toString(),
1376
+ source: peerId.toString()
1377
+ });
1378
+ return {
1379
+ result: TopicValidatorResult.Ignore,
1380
+ obj: block,
1381
+ metadata: {
1382
+ isEquivocated
1383
+ }
1384
+ };
1385
+ }
1386
+ // Too many blocks received for this slot and index, penalize peer and do not re-broadcast
1387
+ if (!added) {
1388
+ this.logger.warn(`Penalizing peer for block proposal exceeding per-position cap`, {
1389
+ ...block.toBlockInfo(),
1390
+ indexWithinCheckpoint: block.indexWithinCheckpoint,
1391
+ count,
1392
+ proposer: block.getSender()?.toString(),
1393
+ source: peerId.toString()
1394
+ });
1395
+ return {
1396
+ result: TopicValidatorResult.Reject,
1397
+ metadata: {
1398
+ isEquivocated
1399
+ },
1400
+ severity: PeerErrorSeverity.HighToleranceError
1401
+ };
1402
+ }
1403
+ // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
1404
+ // and do re-broadcast it so other nodes in the network know to slash the proposer
1405
+ if (isEquivocated) {
1406
+ const proposer = block.getSender();
1407
+ this.logger.warn(`Detected duplicate block proposal (equivocation) at slot ${block.slotNumber}`, {
1408
+ ...block.toBlockInfo(),
1409
+ source: peerId.toString(),
1410
+ proposer: proposer?.toString()
1411
+ });
1412
+ // Invoke the duplicate callback on the first duplicate spotted only
1413
+ if (proposer && count === 2) {
1414
+ this.duplicateProposalCallback?.({
1415
+ slot: block.slotNumber,
1416
+ proposer,
1417
+ type: 'block'
1418
+ });
1419
+ }
1420
+ return {
1421
+ result: TopicValidatorResult.Accept,
1422
+ obj: block,
1423
+ metadata: {
1424
+ isEquivocated
1425
+ }
1426
+ };
1427
+ }
1428
+ // Otherwise, we're good to go!
1429
+ return {
1430
+ result: TopicValidatorResult.Accept,
1431
+ obj: block
1432
+ };
1433
+ }
1434
+ // REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
1435
+ // should not be here as it does not deal with p2p networking.
635
1436
  async processValidBlockProposal(block, sender) {
636
- const slot = block.slotNumber.toBigInt();
637
- const previousSlot = slot - 1n;
1437
+ const slot = block.slotNumber;
638
1438
  this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
639
- p2pMessageIdentifier: await block.p2pMessageIdentifier(),
640
- slot: block.slotNumber.toNumber(),
641
- archive: block.archive.toString(),
642
- source: sender.toString()
1439
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
1440
+ source: sender.toString(),
1441
+ ...block.toBlockInfo()
643
1442
  });
644
- const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
645
- if (attestationsForPreviousSlot !== undefined) {
646
- this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
647
- }
648
- // Mark the txs in this proposal as non-evictable
649
- await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
650
- await this.mempools.attestationPool?.addBlockProposal(block);
651
- const attestations = await this.blockReceivedCallback(block, sender);
652
- // TODO: fix up this pattern - the abstraction is not nice
653
- // The attestation can be undefined if no handler is registered / the validator deems the block invalid
654
- if (attestations?.length) {
655
- for (const attestation of attestations){
656
- this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber.toNumber()}`, {
657
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
658
- slot: attestation.slotNumber.toNumber(),
659
- archive: attestation.archive.toString()
1443
+ // Mark the txs in this proposal as protected
1444
+ await this.mempools.txPool.protectTxs(block.txHashes, block.blockHeader);
1445
+ // Call the block received callback to validate the proposal.
1446
+ // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1447
+ const isValid = await this.blockReceivedCallback(block, sender);
1448
+ if (!isValid) {
1449
+ this.logger.info(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1450
+ }
1451
+ }
1452
+ /**
1453
+ * Handle a gossiped checkpoint proposal.
1454
+ * Validates and processes the checkpoint proposal, then triggers the callback for attestation.
1455
+ */ async handleGossipedCheckpointProposal(payloadData, msgId, source) {
1456
+ const { result, obj: checkpoint, metadata: { isEquivocated, processBlock } = {} } = await this.validateReceivedMessage(()=>this.validateAndStoreCheckpointProposal(source, CheckpointProposal.fromBuffer(payloadData)), msgId, source, TopicType.checkpoint_proposal);
1457
+ // Process checkpoint proposal if valid and not equivocated.
1458
+ const processCheckpointFn = ()=>result === TopicValidatorResult.Accept && checkpoint && !isEquivocated ? this.processValidCheckpointProposal(checkpoint.toCore(), source) : Promise.resolve();
1459
+ // If the checkpoint contained a valid last block, we process it even if the checkpoint itself is to be rejected
1460
+ // TODO(palla/mbps): Is this ok? Should we be considering a block from a checkpoint that was equivocated?
1461
+ const processBlockFn = ()=>processBlock && checkpoint && checkpoint.getBlockProposal() ? this.processValidBlockProposal(checkpoint.getBlockProposal(), source) : Promise.resolve();
1462
+ // A node that skips checkpoint validation attests without re-executing the embedded last block, so run
1463
+ // the checkpoint callback first: this creates and broadcasts the attestation before the block is
1464
+ // processed. Otherwise the block's re-execution — which can stall until the re-execution deadline
1465
+ // waiting for a parent that may never arrive — would delay the attestation past the slot's attestation
1466
+ // window, after which peers reject it as stale.
1467
+ if (this.config.skipCheckpointProposalValidation) {
1468
+ await processCheckpointFn();
1469
+ await processBlockFn();
1470
+ return;
1471
+ }
1472
+ // Process the block first, since it's required for the checkpoint proposal validation.
1473
+ await processBlockFn();
1474
+ await processCheckpointFn();
1475
+ }
1476
+ /**
1477
+ * Validates a checkpoint proposal. Penalizes peer if validation fails. Adds the checkpoint and
1478
+ * its last block (if present) to the mempool if valid. Triggers equivocation detection on both.
1479
+ */ async validateAndStoreCheckpointProposal(peerId, checkpoint) {
1480
+ const validationResult = await this.checkpointProposalValidator.validate(checkpoint);
1481
+ if (validationResult.result === 'reject') {
1482
+ this.logger.warn(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1483
+ return {
1484
+ result: TopicValidatorResult.Reject,
1485
+ severity: validationResult.severity
1486
+ };
1487
+ }
1488
+ if (validationResult.result === 'ignore') {
1489
+ return {
1490
+ result: TopicValidatorResult.Ignore,
1491
+ obj: checkpoint
1492
+ };
1493
+ }
1494
+ // Extract and try to add the block proposal first if present
1495
+ const blockProposal = checkpoint.getBlockProposal();
1496
+ let processBlock = false;
1497
+ if (blockProposal) {
1498
+ this.logger.debug(`Validating block proposal from propagated checkpoint`, {
1499
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1500
+ [Attributes.P2P_ID]: peerId.toString()
1501
+ });
1502
+ const blockProposalResult = await this.validateAndStoreBlockProposal(peerId, blockProposal);
1503
+ const { obj, metadata: { isEquivocated } = {} } = blockProposalResult;
1504
+ if (blockProposalResult.result === TopicValidatorResult.Reject || !obj || isEquivocated) {
1505
+ this.logger.debug(`Rejecting checkpoint due to invalid last block proposal`, {
1506
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1507
+ [Attributes.P2P_ID]: peerId.toString(),
1508
+ isEquivocated,
1509
+ result: blockProposalResult.result
660
1510
  });
661
- await this.broadcastAttestation(attestation);
1511
+ return {
1512
+ result: TopicValidatorResult.Reject,
1513
+ severity: 'severity' in blockProposalResult ? blockProposalResult.severity : PeerErrorSeverity.MidToleranceError
1514
+ };
1515
+ } else if (blockProposalResult.result === TopicValidatorResult.Accept && obj && !isEquivocated) {
1516
+ processBlock = true;
662
1517
  }
663
1518
  }
1519
+ // Try to add the checkpoint proposal core: this handles existence check, cap check, and adding in one call
1520
+ const checkpointCore = checkpoint.toCore();
1521
+ const tryAddResult = await this.mempools.attestationPool.tryAddCheckpointProposal(checkpointCore);
1522
+ const { added, alreadyExists, count } = tryAddResult;
1523
+ const isEquivocated = count !== undefined && count > 1;
1524
+ // Duplicate proposal received, do not re-broadcast
1525
+ if (alreadyExists) {
1526
+ this.logger.debug(`Ignoring duplicate checkpoint proposal received`, {
1527
+ ...checkpoint.toCheckpointInfo(),
1528
+ source: peerId.toString()
1529
+ });
1530
+ return {
1531
+ result: TopicValidatorResult.Ignore,
1532
+ obj: checkpoint,
1533
+ metadata: {
1534
+ isEquivocated,
1535
+ processBlock
1536
+ }
1537
+ };
1538
+ }
1539
+ // Too many checkpoint proposals received for this slot, penalize peer and do not re-broadcast
1540
+ // Note: We still return the checkpoint obj so the lastBlock can be processed if valid
1541
+ if (!added) {
1542
+ this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1543
+ ...checkpoint.toCheckpointInfo(),
1544
+ count,
1545
+ source: peerId.toString()
1546
+ });
1547
+ return {
1548
+ result: TopicValidatorResult.Reject,
1549
+ obj: checkpoint,
1550
+ metadata: {
1551
+ isEquivocated,
1552
+ processBlock
1553
+ },
1554
+ severity: PeerErrorSeverity.HighToleranceError
1555
+ };
1556
+ }
1557
+ // If this was a duplicate proposal, do not process it, but do invoke the duplicate callback,
1558
+ // and do re-broadcast it so other nodes in the network know to slash the proposer
1559
+ if (isEquivocated) {
1560
+ const proposer = checkpoint.getSender();
1561
+ this.logger.warn(`Detected duplicate checkpoint proposal (equivocation) at slot ${checkpoint.slotNumber}`, {
1562
+ ...checkpoint.toCheckpointInfo(),
1563
+ source: peerId.toString(),
1564
+ proposer: proposer?.toString()
1565
+ });
1566
+ // Invoke the duplicate callback on the first duplicate spotted only
1567
+ if (proposer && count === 2) {
1568
+ this.duplicateProposalCallback?.({
1569
+ slot: checkpoint.slotNumber,
1570
+ proposer,
1571
+ type: 'checkpoint'
1572
+ });
1573
+ }
1574
+ return {
1575
+ result: TopicValidatorResult.Accept,
1576
+ obj: checkpoint,
1577
+ metadata: {
1578
+ isEquivocated,
1579
+ processBlock
1580
+ }
1581
+ };
1582
+ }
1583
+ // Otherwise, we're good to go!
1584
+ return {
1585
+ result: TopicValidatorResult.Accept,
1586
+ obj: checkpoint,
1587
+ metadata: {
1588
+ processBlock,
1589
+ isEquivocated
1590
+ }
1591
+ };
664
1592
  }
665
1593
  /**
666
- * Broadcast an attestation to all peers.
667
- * @param attestation - The attestation to broadcast.
668
- */ async broadcastAttestation(attestation) {
669
- await this.propagate(attestation);
1594
+ * Process a validated checkpoint proposal.
1595
+ * Note: The proposal was already added to the pool by tryAddCheckpointProposal in handleGossipedCheckpointProposal.
1596
+ */ async processValidCheckpointProposal(checkpoint, sender) {
1597
+ const slot = checkpoint.slotNumber;
1598
+ this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
1599
+ p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
1600
+ slot: checkpoint.slotNumber,
1601
+ archive: checkpoint.archive.toString(),
1602
+ source: sender.toString()
1603
+ });
1604
+ await this.allNodesCheckpointReceivedCallback(checkpoint, sender);
1605
+ // Call the checkpoint received callback with the core version (without lastBlock)
1606
+ // to validate and potentially generate attestations
1607
+ const attestations = await this.validatorCheckpointReceivedCallback(checkpoint, sender);
1608
+ if (attestations && attestations.length > 0) {
1609
+ // If the callback returned attestations, add them to the pool and propagate them
1610
+ await this.mempools.attestationPool.addOwnCheckpointAttestations(attestations);
1611
+ for (const attestation of attestations){
1612
+ await this.propagate(attestation);
1613
+ }
1614
+ }
670
1615
  }
671
1616
  /**
672
1617
  * Propagates provided message to peers.
673
1618
  * @param message - The message to propagate.
674
1619
  */ async propagate(message) {
675
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
1620
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
676
1621
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, {
677
1622
  p2pMessageIdentifier
678
1623
  });
679
- void this.jobQueue.put(async ()=>{
680
- await this.sendToPeers(message);
681
- }).catch((error)=>{
1624
+ void this.sendToPeers(message).catch((error)=>{
682
1625
  this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, {
683
1626
  error
684
1627
  });
685
1628
  });
686
1629
  }
687
1630
  /**
688
- * Validate the requested block transactions.
1631
+ * Validate the requested block transactions request-response consistency.
1632
+ * It does NOT validate the transactions themselves.
689
1633
  * @param request - The block transactions request.
690
1634
  * @param response - The block transactions response.
691
1635
  * @param peerId - The ID of the peer that made the request.
692
- * @returns True if the requested block transactions are valid, false otherwise.
693
- */ async validateRequestedBlockTxs(_request, response, peerId) {
694
- const requestedTxValidator = this.createRequestedTxValidator();
1636
+ * @returns True if the request-response is consistent, false otherwise.
1637
+ */ async validateRequestedBlockTxsConsistency(request, response, peerId) {
695
1638
  try {
696
- // TODO(palla/txs): Validate that this tx belongs to the block hash being requested
697
- await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
1639
+ // Check for duplicates txs (or hashes) in the response.
1640
+ const returnedHashes = response.txs.map((tx)=>tx.getTxHash().toString());
1641
+ const uniqueReturned = new Set(returnedHashes.map((h)=>h.toString()));
1642
+ if (uniqueReturned.size !== returnedHashes.length) {
1643
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1644
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1645
+ }
1646
+ // We get the block tx hashes from the proposal or the archiver.
1647
+ const proposal = await this.mempools.attestationPool.getBlockProposalByArchive(request.archiveRoot.toString());
1648
+ const blockTxHashes = proposal?.txHashes ?? (await this.archiver.getBlock({
1649
+ archive: request.archiveRoot
1650
+ }))?.body.txEffects.map((e)=>e.txHash);
1651
+ // If we don't have the block, we can't verify membership/order of the returned txs.
1652
+ if (!blockTxHashes) {
1653
+ // This shouldn't happen, since we asked for the block (proposal).
1654
+ // Neither a local proposal nor an archived block: we cannot verify membership/order of the
1655
+ // returned txs. This is a local-state gap, not a peer fault, so we do not penalize.
1656
+ this.logger.warn(`Block ${request.archiveRoot.toString()} not found in attestation pool or archiver; cannot validate membership/order of returned txs`);
1657
+ // NOTE: We mark the response as invalid, given the limitations of a true/false return value.
1658
+ return false;
1659
+ }
1660
+ // Verify that the returned tx hashes are a subset of (tx hashes by index) U (explicitly requested tx hashes).
1661
+ const uniqueRequestedHashes = new Set([
1662
+ // tx hashes requested by index.
1663
+ ...request.txIndices.getTrueIndices().map((i)=>blockTxHashes[i].toString()),
1664
+ // explicitly requested tx hashes.
1665
+ ...request.txHashes.map((h)=>h.toString())
1666
+ ]);
1667
+ if (!returnedHashes.every((h)=>uniqueRequestedHashes.has(h))) {
1668
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1669
+ throw new ValidationError('Returned txs should be a subset of (tx hashes by index) U (explicitly requested tx hashes)');
1670
+ }
1671
+ // Tx indices information is optional, but if present, we need to verify a few things.
1672
+ if (!response.peerHasBlock()) {
1673
+ this.logger.debug(`Peer ${peerId.toString()} signalled missing block`);
1674
+ return true;
1675
+ }
1676
+ // If the response has a non-empty bitvector, it needs to be consistent with the number of txs in the block.
1677
+ if (response.txIndices.getLength() !== blockTxHashes.length) {
1678
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1679
+ throw new ValidationError(`Received block txs with mismatched bitvector length: expected ${blockTxHashes.length}, got ${response.txIndices.getLength()}`);
1680
+ }
1681
+ // For every index we requested that the peer claims to have (per its bitvector), the
1682
+ // corresponding tx must be present in the response. A peer advertising availability but
1683
+ // withholding the tx is inconsistent.
1684
+ const returnedHashSet = new Set(returnedHashes);
1685
+ const expectedIndices = request.txIndices.getTrueIndices().filter((i)=>response.txIndices.isSet(i));
1686
+ const missingExpected = expectedIndices.some((i)=>!returnedHashSet.has(blockTxHashes[i].toString()));
1687
+ if (missingExpected) {
1688
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1689
+ throw new ValidationError('Peer advertised requested txs via indices but did not return them');
1690
+ }
698
1691
  return true;
699
1692
  } catch (e) {
700
1693
  if (e instanceof ValidationError) {
@@ -705,125 +1698,54 @@ import { P2PInstrumentation } from './instrumentation.js';
705
1698
  return false;
706
1699
  }
707
1700
  }
1701
+ getGasFees() {
1702
+ return this.blockMinFeesProvider.getCurrentMinFees();
1703
+ }
708
1704
  /**
709
- * Validate a collection of txs that has been requested from a peer.
710
- *
711
- * The core component of this validator is that each tx hash MUST match the requested tx hash,
712
- * In order to perform this check, the tx proof must be verified.
713
- *
714
- * Note: This function is called from within `ReqResp.sendRequest` as part of the
715
- * ReqRespSubProtocol.TX subprotocol validation.
716
- *
717
- * @param requestedTxHash - The collection of the txs that was requested.
718
- * @param responseTx - The collectin of txs that was received as a response to the request.
719
- * @param peerId - The peer ID of the peer that sent the tx.
720
- * @returns True if the whole collection of txs is valid, false otherwise.
721
- */ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
722
- const requested = new Set(requestedTxHash.map((h)=>h.toString()));
723
- const requestedTxValidator = this.createRequestedTxValidator();
724
- //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
725
- // I think we should still extract the valid txs and return them, so that we can still use the response.
726
- try {
727
- await Promise.all(responseTx.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
728
- return true;
729
- } catch (e) {
730
- if (e instanceof ValidationError) {
731
- this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
732
- } else {
733
- this.logger.error(`Error during validation of requested txs`, e);
734
- }
735
- return false;
736
- }
1705
+ * Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
1706
+ */ getBatchTxRequesterService() {
1707
+ return {
1708
+ reqResp: this.reqresp,
1709
+ connectionSampler: this.reqresp.getConnectionSampler(),
1710
+ txValidatorConfig: {
1711
+ l1ChainId: this.config.l1ChainId,
1712
+ rollupVersion: this.config.rollupVersion,
1713
+ proofVerifier: this.proofVerifier,
1714
+ txValidationCache: this.txValidationCache
1715
+ },
1716
+ peerScoring: this.peerManager,
1717
+ validateRequestedBlockTxsConsistency: this.validateRequestedBlockTxsConsistency.bind(this)
1718
+ };
737
1719
  }
738
- createRequestedTxValidator() {
739
- return new AggregateTxValidator(new DataTxValidator(), new MetadataTxValidator({
740
- l1ChainId: new Fr(this.config.l1ChainId),
741
- rollupVersion: new Fr(this.config.rollupVersion),
742
- protocolContractsHash,
743
- vkTreeRoot: getVKTreeRoot()
744
- }), new TxProofValidator(this.proofVerifier));
745
- }
746
- async validateRequestedTx(tx, peerId, txValidator, requested) {
747
- if (!await tx.validateTxHash()) {
748
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
749
- throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
750
- }
751
- if (requested && !requested.has(tx.getTxHash().toString())) {
752
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
753
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
754
- }
755
- const { result } = await txValidator.validateTx(tx);
756
- if (result === 'invalid') {
757
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
758
- throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
759
- }
760
- }
761
- async validatePropagatedTx(tx, peerId) {
762
- const currentBlockNumber = await this.archiver.getBlockNumber();
763
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
764
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
765
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
766
- for (const validator of messageValidators){
767
- const outcome = await this.runValidations(tx, validator);
768
- if (outcome.allPassed) {
769
- continue;
770
- }
771
- const { name } = outcome.failure;
772
- let { severity } = outcome.failure;
773
- // Double spend validator has a special case handler
774
- if (name === 'doubleSpendValidator') {
775
- const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
776
- severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
777
- }
778
- this.peerManager.penalizePeer(peerId, severity);
779
- return false;
1720
+ async validateTxsReceivedInBlockProposal(txs) {
1721
+ const validator = createTxValidatorForBlockProposalReceivedTxs(this.proofVerifier, {
1722
+ l1ChainId: this.config.l1ChainId,
1723
+ rollupVersion: this.config.rollupVersion
1724
+ }, this.logger.getBindings(), this.txValidationCache);
1725
+ const results = await Promise.all(txs.map(async (tx)=>{
1726
+ const result = await validator.validateTx(tx);
1727
+ return result.result !== 'invalid';
1728
+ }));
1729
+ if (results.some((value)=>value === false)) {
1730
+ throw new Error('Invalid tx detected');
780
1731
  }
781
- return true;
782
1732
  }
783
- async getGasFees(blockNumber) {
784
- if (blockNumber === this.feesCache?.blockNumber) {
785
- return this.feesCache.gasFees;
786
- }
787
- const header = await this.archiver.getBlockHeader(blockNumber);
788
- const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
789
- this.feesCache = {
790
- blockNumber,
791
- gasFees
792
- };
793
- return gasFees;
794
- }
795
- async validate(txs) {
796
- const currentBlockNumber = await this.archiver.getBlockNumber();
797
- // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
798
- const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
799
- const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
800
- await Promise.all(txs.map(async (tx)=>{
801
- for (const validator of messageValidators){
802
- const outcome = await this.runValidations(tx, validator);
803
- if (!outcome.allPassed) {
804
- throw new Error('Invalid tx detected', {
805
- cause: {
806
- outcome
807
- }
808
- });
809
- }
810
- }
811
- }));
1733
+ /** Creates the first stage (fast) validators for gossiped transactions. */ async createFirstStageMessageValidators(currentBlockNumber, nextSlotTimestamp) {
1734
+ const gasFees = await this.getGasFees();
1735
+ const allowedInSetup = [
1736
+ ...await getDefaultAllowedSetupFunctions(),
1737
+ ...this.config.txPublicSetupAllowListExtend ?? []
1738
+ ];
1739
+ const blockNumber = BlockNumber(currentBlockNumber + 1);
1740
+ const l1Constants = await this.archiver.getL1Constants();
1741
+ return createFirstStageTxValidationsForGossipedTransactions(nextSlotTimestamp, blockNumber, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, !this.config.disableTransactions, allowedInSetup, this.logger.getBindings(), {
1742
+ rollupManaLimit: l1Constants.rollupManaLimit,
1743
+ maxBlockL2Gas: this.config.validateMaxL2BlockGas,
1744
+ maxBlockDAGas: this.config.validateMaxDABlockGas
1745
+ });
812
1746
  }
813
- /**
814
- * Create message validators for the given block number and timestamp.
815
- *
816
- * Each validator is a pair of a validator and a severity.
817
- * If a validator fails, the peer is penalized with the severity of the validator.
818
- *
819
- * @param currentBlockNumber - The current synced block number.
820
- * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
821
- * @returns The message validators.
822
- */ async createMessageValidators(currentBlockNumber, nextSlotTimestamp) {
823
- const gasFees = await this.getGasFees(currentBlockNumber);
824
- const allowedInSetup = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
825
- const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
826
- return createTxMessageValidators(nextSlotTimestamp, blockNumberInWhichTheTxIsConsideredToBeIncluded, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, this.proofVerifier, !this.config.disableTransactions, allowedInSetup);
1747
+ /** Creates the second stage (expensive proof verification) validators for gossiped transactions. */ createSecondStageMessageValidators() {
1748
+ return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
827
1749
  }
828
1750
  /**
829
1751
  * Run validations on a tx.
@@ -841,8 +1763,10 @@ import { P2PInstrumentation } from './instrumentation.js';
841
1763
  });
842
1764
  // A promise that resolves when all validations have been run
843
1765
  const allValidations = await Promise.all(validationPromises);
844
- const failed = allValidations.find((x)=>!x.isValid);
845
- if (failed) {
1766
+ const failures = allValidations.filter((x)=>!x.isValid);
1767
+ if (failures.length > 0) {
1768
+ // Pick the most severe failure (lowest tolerance = harshest penalty)
1769
+ const failed = maxBy(failures, (f)=>PeerErrorSeverityByHarshness.indexOf(f.severity));
846
1770
  return {
847
1771
  allPassed: false,
848
1772
  failure: {
@@ -878,44 +1802,17 @@ import { P2PInstrumentation } from './instrumentation.js';
878
1802
  }
879
1803
  const snapshotValidator = new DoubleSpendTxValidator({
880
1804
  nullifiersExist: async (nullifiers)=>{
881
- const merkleTree = this.worldStateSynchronizer.getSnapshot(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow);
1805
+ const merkleTree = this.worldStateSynchronizer.getSnapshot(BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow));
882
1806
  const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
883
1807
  return indices.map((index)=>index !== undefined);
884
1808
  }
885
- });
1809
+ }, this.logger.getBindings());
886
1810
  const validSnapshot = await snapshotValidator.validateTx(tx);
887
1811
  if (validSnapshot.result !== 'valid') {
888
1812
  return PeerErrorSeverity.LowToleranceError;
889
1813
  }
890
1814
  return PeerErrorSeverity.HighToleranceError;
891
1815
  }
892
- /**
893
- * Validate an attestation.
894
- *
895
- * @param attestation - The attestation to validate.
896
- * @returns True if the attestation is valid, false otherwise.
897
- */ async validateAttestation(peerId, attestation) {
898
- const severity = await this.attestationValidator.validate(attestation);
899
- if (severity) {
900
- this.peerManager.penalizePeer(peerId, severity);
901
- return false;
902
- }
903
- return true;
904
- }
905
- /**
906
- * Validate a block proposal.
907
- *
908
- * @param block - The block proposal to validate.
909
- * @returns True if the block proposal is valid, false otherwise.
910
- */ async validateBlockProposal(peerId, block) {
911
- const severity = await this.blockProposalValidator.validate(block);
912
- if (severity) {
913
- this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
914
- this.peerManager.penalizePeer(peerId, severity);
915
- return false;
916
- }
917
- return true;
918
- }
919
1816
  getPeerScore(peerId) {
920
1817
  return this.node.services.pubsub.score.score(peerId.toString());
921
1818
  }
@@ -924,7 +1821,7 @@ import { P2PInstrumentation } from './instrumentation.js';
924
1821
  }
925
1822
  async sendToPeers(message) {
926
1823
  const parent = message.constructor;
927
- const identifier = await message.p2pMessageIdentifier().then((i)=>i.toString());
1824
+ const identifier = await message.p2pMessageLoggingIdentifier().then((i)=>i.toString());
928
1825
  this.logger.trace(`Sending message ${identifier}`, {
929
1826
  p2pMessageIdentifier: identifier
930
1827
  });
@@ -951,44 +1848,3 @@ import { P2PInstrumentation } from './instrumentation.js';
951
1848
  }
952
1849
  }
953
1850
  }
954
- _ts_decorate([
955
- trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
956
- [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
957
- [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
958
- [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then((i)=>i.toString())
959
- }))
960
- ], LibP2PService.prototype, "processValidBlockProposal", null);
961
- _ts_decorate([
962
- trackSpan('Libp2pService.broadcastAttestation', async (attestation)=>({
963
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
964
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
965
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
966
- }))
967
- ], LibP2PService.prototype, "broadcastAttestation", null);
968
- _ts_decorate([
969
- trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
970
- [Attributes.BLOCK_HASH]: request.blockHash.toString()
971
- }))
972
- ], LibP2PService.prototype, "validateRequestedBlockTxs", null);
973
- _ts_decorate([
974
- trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
975
- [Attributes.TX_HASH]: requestedTxHash.toString()
976
- }))
977
- ], LibP2PService.prototype, "validateRequestedTxs", null);
978
- _ts_decorate([
979
- trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
980
- [Attributes.TX_HASH]: tx.getTxHash().toString()
981
- }))
982
- ], LibP2PService.prototype, "validatePropagatedTx", null);
983
- _ts_decorate([
984
- trackSpan('Libp2pService.validateAttestation', async (_, attestation)=>({
985
- [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
986
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
987
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
988
- }))
989
- ], LibP2PService.prototype, "validateAttestation", null);
990
- _ts_decorate([
991
- trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
992
- [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString()
993
- }))
994
- ], LibP2PService.prototype, "validateBlockProposal", null);