@aztec/p2p 0.0.0-test.1 → 0.0.1-commit.017a351

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 (633) 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 +34 -13
  5. package/dest/client/factory.d.ts +23 -12
  6. package/dest/client/factory.d.ts.map +1 -1
  7. package/dest/client/factory.js +106 -26
  8. package/dest/client/index.d.ts +2 -1
  9. package/dest/client/index.d.ts.map +1 -1
  10. package/dest/client/index.js +1 -0
  11. package/dest/client/interface.d.ts +192 -0
  12. package/dest/client/interface.d.ts.map +1 -0
  13. package/dest/client/interface.js +9 -0
  14. package/dest/client/p2p_client.d.ts +97 -221
  15. package/dest/client/p2p_client.d.ts.map +1 -1
  16. package/dest/client/p2p_client.js +818 -289
  17. package/dest/config.d.ts +235 -133
  18. package/dest/config.d.ts.map +1 -1
  19. package/dest/config.js +295 -36
  20. package/dest/enr/generate-enr.d.ts +11 -3
  21. package/dest/enr/generate-enr.d.ts.map +1 -1
  22. package/dest/enr/generate-enr.js +27 -5
  23. package/dest/enr/index.d.ts +1 -1
  24. package/dest/errors/attestation-pool.error.d.ts +7 -0
  25. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  26. package/dest/errors/attestation-pool.error.js +12 -0
  27. package/dest/errors/p2p-service.error.d.ts +9 -0
  28. package/dest/errors/p2p-service.error.d.ts.map +1 -0
  29. package/dest/errors/p2p-service.error.js +10 -0
  30. package/dest/errors/reqresp.error.d.ts +1 -20
  31. package/dest/errors/reqresp.error.d.ts.map +1 -1
  32. package/dest/errors/reqresp.error.js +0 -21
  33. package/dest/errors/tx-pool.error.d.ts +8 -0
  34. package/dest/errors/tx-pool.error.d.ts.map +1 -0
  35. package/dest/errors/tx-pool.error.js +9 -0
  36. package/dest/index.d.ts +5 -2
  37. package/dest/index.d.ts.map +1 -1
  38. package/dest/index.js +3 -1
  39. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +165 -30
  40. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  41. package/dest/mem_pools/attestation_pool/attestation_pool.js +511 -3
  42. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +2 -2
  43. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  44. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +680 -173
  45. package/dest/mem_pools/attestation_pool/index.d.ts +2 -3
  46. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -1
  47. package/dest/mem_pools/attestation_pool/index.js +1 -2
  48. package/dest/mem_pools/attestation_pool/mocks.d.ts +234 -11
  49. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  50. package/dest/mem_pools/attestation_pool/mocks.js +21 -21
  51. package/dest/mem_pools/index.d.ts +3 -3
  52. package/dest/mem_pools/index.d.ts.map +1 -1
  53. package/dest/mem_pools/index.js +1 -1
  54. package/dest/mem_pools/instrumentation.d.ts +18 -12
  55. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  56. package/dest/mem_pools/instrumentation.js +74 -41
  57. package/dest/mem_pools/interface.d.ts +6 -7
  58. package/dest/mem_pools/interface.d.ts.map +1 -1
  59. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts +2 -0
  60. package/dest/mem_pools/tx_pool_v2/archive/index.d.ts.map +1 -0
  61. package/dest/mem_pools/tx_pool_v2/archive/index.js +1 -0
  62. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts +39 -0
  63. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.d.ts.map +1 -0
  64. package/dest/mem_pools/tx_pool_v2/archive/tx_archive.js +97 -0
  65. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts +104 -0
  66. package/dest/mem_pools/tx_pool_v2/deleted_pool.d.ts.map +1 -0
  67. package/dest/mem_pools/tx_pool_v2/deleted_pool.js +251 -0
  68. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts +47 -0
  69. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.d.ts.map +1 -0
  70. package/dest/mem_pools/tx_pool_v2/eviction/eviction_manager.js +128 -0
  71. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts +17 -0
  72. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  73. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.js +94 -0
  74. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts +19 -0
  75. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.d.ts.map +1 -0
  76. package/dest/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.js +97 -0
  77. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts +11 -0
  78. package/dest/mem_pools/tx_pool_v2/eviction/index.d.ts.map +1 -0
  79. package/dest/mem_pools/tx_pool_v2/eviction/index.js +12 -0
  80. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts +16 -0
  81. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.d.ts.map +1 -0
  82. package/dest/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.js +62 -0
  83. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts +180 -0
  84. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.d.ts.map +1 -0
  85. package/dest/mem_pools/tx_pool_v2/eviction/interfaces.js +25 -0
  86. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts +15 -0
  87. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  88. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.js +65 -0
  89. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts +17 -0
  90. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  91. package/dest/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.js +93 -0
  92. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts +16 -0
  93. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  94. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.js +78 -0
  95. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts +20 -0
  96. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.d.ts.map +1 -0
  97. package/dest/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.js +75 -0
  98. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts +15 -0
  99. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.d.ts.map +1 -0
  100. package/dest/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.js +19 -0
  101. package/dest/mem_pools/tx_pool_v2/index.d.ts +6 -0
  102. package/dest/mem_pools/tx_pool_v2/index.d.ts.map +1 -0
  103. package/dest/mem_pools/tx_pool_v2/index.js +5 -0
  104. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts +15 -0
  105. package/dest/mem_pools/tx_pool_v2/instrumentation.d.ts.map +1 -0
  106. package/dest/mem_pools/tx_pool_v2/instrumentation.js +43 -0
  107. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts +218 -0
  108. package/dest/mem_pools/tx_pool_v2/interfaces.d.ts.map +1 -0
  109. package/dest/mem_pools/tx_pool_v2/interfaces.js +10 -0
  110. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts +137 -0
  111. package/dest/mem_pools/tx_pool_v2/tx_metadata.d.ts.map +1 -0
  112. package/dest/mem_pools/tx_pool_v2/tx_metadata.js +223 -0
  113. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts +26 -0
  114. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.d.ts.map +1 -0
  115. package/dest/mem_pools/tx_pool_v2/tx_pool_bench_metrics.js +70 -0
  116. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts +108 -0
  117. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.d.ts.map +1 -0
  118. package/dest/mem_pools/tx_pool_v2/tx_pool_indices.js +337 -0
  119. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts +62 -0
  120. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.d.ts.map +1 -0
  121. package/dest/mem_pools/tx_pool_v2/tx_pool_v2.js +167 -0
  122. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts +78 -0
  123. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.d.ts.map +1 -0
  124. package/dest/mem_pools/tx_pool_v2/tx_pool_v2_impl.js +914 -0
  125. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +14 -6
  126. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  127. package/dest/msg_validators/attestation_validator/attestation_validator.js +106 -12
  128. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +24 -0
  129. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  130. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +75 -0
  131. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  132. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  133. package/dest/msg_validators/attestation_validator/index.js +1 -0
  134. package/dest/msg_validators/clock_tolerance.d.ts +32 -0
  135. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  136. package/dest/msg_validators/clock_tolerance.js +90 -0
  137. package/dest/msg_validators/index.d.ts +2 -2
  138. package/dest/msg_validators/index.d.ts.map +1 -1
  139. package/dest/msg_validators/index.js +1 -1
  140. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +10 -0
  141. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -0
  142. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.js +36 -0
  143. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +15 -0
  144. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  145. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +14 -0
  146. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +15 -0
  147. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  148. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +20 -0
  149. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  150. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  151. package/dest/msg_validators/proposal_validator/index.js +3 -0
  152. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +26 -0
  153. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  154. package/dest/msg_validators/proposal_validator/proposal_validator.js +150 -0
  155. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +4 -4
  156. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  157. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +11 -18
  158. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +4 -0
  159. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -0
  160. package/dest/msg_validators/tx_validator/allowed_public_setup.js +31 -0
  161. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts +17 -0
  162. package/dest/msg_validators/tx_validator/allowed_setup_helpers.d.ts.map +1 -0
  163. package/dest/msg_validators/tx_validator/allowed_setup_helpers.js +24 -0
  164. package/dest/msg_validators/tx_validator/archive_cache.d.ts +14 -0
  165. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -0
  166. package/dest/msg_validators/tx_validator/archive_cache.js +22 -0
  167. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +20 -6
  168. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  169. package/dest/msg_validators/tx_validator/block_header_validator.js +7 -6
  170. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts +15 -0
  171. package/dest/msg_validators/tx_validator/cached_tx_validator.d.ts.map +1 -0
  172. package/dest/msg_validators/tx_validator/cached_tx_validator.js +19 -0
  173. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts +9 -0
  174. package/dest/msg_validators/tx_validator/contract_instance_validator.d.ts.map +1 -0
  175. package/dest/msg_validators/tx_validator/contract_instance_validator.js +48 -0
  176. package/dest/msg_validators/tx_validator/data_validator.d.ts +4 -1
  177. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  178. package/dest/msg_validators/tx_validator/data_validator.js +94 -87
  179. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +15 -6
  180. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  181. package/dest/msg_validators/tx_validator/double_spend_validator.js +24 -29
  182. package/dest/msg_validators/tx_validator/factory.d.ts +149 -0
  183. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -0
  184. package/dest/msg_validators/tx_validator/factory.js +275 -0
  185. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  186. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  187. package/dest/msg_validators/tx_validator/fee_payer_balance.js +24 -0
  188. package/dest/msg_validators/tx_validator/gas_validator.d.ts +108 -0
  189. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -0
  190. package/dest/msg_validators/tx_validator/gas_validator.js +194 -0
  191. package/dest/msg_validators/tx_validator/index.d.ts +13 -1
  192. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  193. package/dest/msg_validators/tx_validator/index.js +12 -0
  194. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -5
  195. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  196. package/dest/msg_validators/tx_validator/metadata_validator.js +40 -21
  197. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts +14 -0
  198. package/dest/msg_validators/tx_validator/nullifier_cache.d.ts.map +1 -0
  199. package/dest/msg_validators/tx_validator/nullifier_cache.js +24 -0
  200. package/dest/msg_validators/tx_validator/phases_validator.d.ts +35 -0
  201. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -0
  202. package/dest/msg_validators/tx_validator/phases_validator.js +141 -0
  203. package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
  204. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  205. package/dest/msg_validators/tx_validator/size_validator.js +23 -0
  206. package/dest/msg_validators/tx_validator/test_utils.d.ts +17 -0
  207. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -0
  208. package/dest/msg_validators/tx_validator/test_utils.js +22 -0
  209. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +30 -0
  210. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  211. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  212. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +9 -0
  213. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -0
  214. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +24 -0
  215. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +4 -2
  216. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  217. package/dest/msg_validators/tx_validator/tx_proof_validator.js +10 -7
  218. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts +48 -0
  219. package/dest/msg_validators/tx_validator/tx_validation_cache.d.ts.map +1 -0
  220. package/dest/msg_validators/tx_validator/tx_validation_cache.js +68 -0
  221. package/dest/services/data_store.d.ts +1 -1
  222. package/dest/services/data_store.d.ts.map +1 -1
  223. package/dest/services/data_store.js +14 -10
  224. package/dest/services/discv5/discV5_service.d.ts +11 -9
  225. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  226. package/dest/services/discv5/discV5_service.js +92 -38
  227. package/dest/services/dummy_service.d.ts +77 -18
  228. package/dest/services/dummy_service.d.ts.map +1 -1
  229. package/dest/services/dummy_service.js +139 -12
  230. package/dest/services/encoding.d.ts +30 -7
  231. package/dest/services/encoding.d.ts.map +1 -1
  232. package/dest/services/encoding.js +88 -12
  233. package/dest/services/gossipsub/index.d.ts +3 -0
  234. package/dest/services/gossipsub/index.d.ts.map +1 -0
  235. package/dest/services/gossipsub/index.js +2 -0
  236. package/dest/services/gossipsub/scoring.d.ts +21 -3
  237. package/dest/services/gossipsub/scoring.d.ts.map +1 -1
  238. package/dest/services/gossipsub/scoring.js +24 -7
  239. package/dest/services/gossipsub/topic_score_params.d.ts +184 -0
  240. package/dest/services/gossipsub/topic_score_params.d.ts.map +1 -0
  241. package/dest/services/gossipsub/topic_score_params.js +363 -0
  242. package/dest/services/index.d.ts +6 -1
  243. package/dest/services/index.d.ts.map +1 -1
  244. package/dest/services/index.js +5 -0
  245. package/dest/services/libp2p/instrumentation.d.ts +22 -0
  246. package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
  247. package/dest/services/libp2p/instrumentation.js +136 -0
  248. package/dest/services/libp2p/libp2p_service.d.ts +165 -111
  249. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  250. package/dest/services/libp2p/libp2p_service.js +1517 -379
  251. package/dest/services/peer-manager/interface.d.ts +23 -0
  252. package/dest/services/peer-manager/interface.d.ts.map +1 -0
  253. package/dest/services/peer-manager/interface.js +1 -0
  254. package/dest/services/peer-manager/metrics.d.ts +14 -3
  255. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  256. package/dest/services/peer-manager/metrics.js +50 -12
  257. package/dest/services/peer-manager/peer_manager.d.ts +108 -24
  258. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  259. package/dest/services/peer-manager/peer_manager.js +583 -85
  260. package/dest/services/peer-manager/peer_scoring.d.ts +12 -2
  261. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  262. package/dest/services/peer-manager/peer_scoring.js +99 -13
  263. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +44 -0
  264. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  265. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +534 -0
  266. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  267. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  268. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  269. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
  270. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  271. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  272. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +35 -0
  273. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  274. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +136 -0
  275. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +62 -0
  276. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  277. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +176 -0
  278. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +11 -0
  279. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  280. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +7 -0
  281. package/dest/services/reqresp/config.d.ts +13 -11
  282. package/dest/services/reqresp/config.d.ts.map +1 -1
  283. package/dest/services/reqresp/config.js +18 -4
  284. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +32 -17
  285. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  286. package/dest/services/reqresp/connection-sampler/connection_sampler.js +154 -84
  287. package/dest/services/reqresp/constants.d.ts +12 -0
  288. package/dest/services/reqresp/constants.d.ts.map +1 -0
  289. package/dest/services/reqresp/constants.js +7 -0
  290. package/dest/services/reqresp/index.d.ts +3 -2
  291. package/dest/services/reqresp/index.d.ts.map +1 -1
  292. package/dest/services/reqresp/index.js +2 -1
  293. package/dest/services/reqresp/interface.d.ts +88 -30
  294. package/dest/services/reqresp/interface.d.ts.map +1 -1
  295. package/dest/services/reqresp/interface.js +61 -38
  296. package/dest/services/reqresp/metrics.d.ts +6 -5
  297. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  298. package/dest/services/reqresp/metrics.js +16 -21
  299. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  300. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  301. package/dest/services/reqresp/protocols/auth.js +71 -0
  302. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +35 -0
  303. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  304. package/dest/services/reqresp/protocols/block_txs/bitvector.js +88 -0
  305. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +13 -0
  306. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  307. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +60 -0
  308. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +75 -0
  309. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  310. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +139 -0
  311. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  312. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  313. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  314. package/dest/services/reqresp/protocols/goodbye.d.ts +3 -5
  315. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  316. package/dest/services/reqresp/protocols/goodbye.js +7 -7
  317. package/dest/services/reqresp/protocols/index.d.ts +3 -2
  318. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  319. package/dest/services/reqresp/protocols/index.js +2 -1
  320. package/dest/services/reqresp/protocols/ping.d.ts +1 -3
  321. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
  322. package/dest/services/reqresp/protocols/status.d.ts +40 -7
  323. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  324. package/dest/services/reqresp/protocols/status.js +76 -5
  325. package/dest/services/reqresp/protocols/tx.d.ts +20 -4
  326. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  327. package/dest/services/reqresp/protocols/tx.js +52 -6
  328. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  329. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +10 -7
  330. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  331. package/dest/services/reqresp/rate-limiter/rate_limiter.js +20 -10
  332. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  333. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  334. package/dest/services/reqresp/rate-limiter/rate_limits.js +16 -6
  335. package/dest/services/reqresp/reqresp.d.ts +32 -91
  336. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  337. package/dest/services/reqresp/reqresp.js +695 -355
  338. package/dest/services/reqresp/status.d.ts +10 -4
  339. package/dest/services/reqresp/status.d.ts.map +1 -1
  340. package/dest/services/reqresp/status.js +9 -2
  341. package/dest/services/service.d.ts +76 -23
  342. package/dest/services/service.d.ts.map +1 -1
  343. package/dest/services/tx_collection/config.d.ts +25 -0
  344. package/dest/services/tx_collection/config.d.ts.map +1 -0
  345. package/dest/services/tx_collection/config.js +59 -0
  346. package/dest/services/tx_collection/file_store_tx_collection.d.ts +37 -0
  347. package/dest/services/tx_collection/file_store_tx_collection.d.ts.map +1 -0
  348. package/dest/services/tx_collection/file_store_tx_collection.js +127 -0
  349. package/dest/services/tx_collection/file_store_tx_source.d.ts +38 -0
  350. package/dest/services/tx_collection/file_store_tx_source.d.ts.map +1 -0
  351. package/dest/services/tx_collection/file_store_tx_source.js +100 -0
  352. package/dest/services/tx_collection/index.d.ts +4 -0
  353. package/dest/services/tx_collection/index.d.ts.map +1 -0
  354. package/dest/services/tx_collection/index.js +3 -0
  355. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  356. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  357. package/dest/services/tx_collection/instrumentation.js +30 -0
  358. package/dest/services/tx_collection/request_tracker.d.ts +53 -0
  359. package/dest/services/tx_collection/request_tracker.d.ts.map +1 -0
  360. package/dest/services/tx_collection/request_tracker.js +84 -0
  361. package/dest/services/tx_collection/tx_collection.d.ts +104 -0
  362. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  363. package/dest/services/tx_collection/tx_collection.js +356 -0
  364. package/dest/services/tx_collection/tx_collection_sink.d.ts +40 -0
  365. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  366. package/dest/services/tx_collection/tx_collection_sink.js +108 -0
  367. package/dest/services/tx_collection/tx_source.d.ts +24 -0
  368. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  369. package/dest/services/tx_collection/tx_source.js +50 -0
  370. package/dest/services/tx_file_store/config.d.ts +16 -0
  371. package/dest/services/tx_file_store/config.d.ts.map +1 -0
  372. package/dest/services/tx_file_store/config.js +22 -0
  373. package/dest/services/tx_file_store/index.d.ts +4 -0
  374. package/dest/services/tx_file_store/index.d.ts.map +1 -0
  375. package/dest/services/tx_file_store/index.js +3 -0
  376. package/dest/services/tx_file_store/instrumentation.d.ts +15 -0
  377. package/dest/services/tx_file_store/instrumentation.d.ts.map +1 -0
  378. package/dest/services/tx_file_store/instrumentation.js +29 -0
  379. package/dest/services/tx_file_store/tx_file_store.d.ts +46 -0
  380. package/dest/services/tx_file_store/tx_file_store.d.ts.map +1 -0
  381. package/dest/services/tx_file_store/tx_file_store.js +142 -0
  382. package/dest/services/tx_provider.d.ts +53 -0
  383. package/dest/services/tx_provider.d.ts.map +1 -0
  384. package/dest/services/tx_provider.js +223 -0
  385. package/dest/services/tx_provider_instrumentation.d.ts +16 -0
  386. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  387. package/dest/services/tx_provider_instrumentation.js +34 -0
  388. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  389. package/dest/test-helpers/get-ports.d.ts +1 -1
  390. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  391. package/dest/test-helpers/index.d.ts +4 -1
  392. package/dest/test-helpers/index.d.ts.map +1 -1
  393. package/dest/test-helpers/index.js +3 -0
  394. package/dest/test-helpers/make-enrs.d.ts +1 -1
  395. package/dest/test-helpers/make-enrs.d.ts.map +1 -1
  396. package/dest/test-helpers/make-enrs.js +4 -5
  397. package/dest/test-helpers/make-test-p2p-clients.d.ts +35 -8
  398. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  399. package/dest/test-helpers/make-test-p2p-clients.js +89 -17
  400. package/dest/test-helpers/mock-pubsub.d.ts +99 -0
  401. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -0
  402. package/dest/test-helpers/mock-pubsub.js +231 -0
  403. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  404. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  405. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  406. package/dest/test-helpers/reqresp-nodes.d.ts +17 -15
  407. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  408. package/dest/test-helpers/reqresp-nodes.js +73 -40
  409. package/dest/test-helpers/test_tx_provider.d.ts +42 -0
  410. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  411. package/dest/test-helpers/test_tx_provider.js +44 -0
  412. package/dest/test-helpers/testbench-utils.d.ts +161 -0
  413. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  414. package/dest/test-helpers/testbench-utils.js +391 -0
  415. package/dest/testbench/p2p_client_testbench_worker.d.ts +26 -2
  416. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  417. package/dest/testbench/p2p_client_testbench_worker.js +310 -95
  418. package/dest/testbench/parse_log_file.d.ts +1 -1
  419. package/dest/testbench/parse_log_file.js +4 -4
  420. package/dest/testbench/testbench.d.ts +1 -1
  421. package/dest/testbench/testbench.js +4 -4
  422. package/dest/testbench/worker_client_manager.d.ts +57 -11
  423. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  424. package/dest/testbench/worker_client_manager.js +283 -58
  425. package/dest/types/index.d.ts +4 -2
  426. package/dest/types/index.d.ts.map +1 -1
  427. package/dest/types/index.js +2 -0
  428. package/dest/util.d.ts +33 -20
  429. package/dest/util.d.ts.map +1 -1
  430. package/dest/util.js +98 -71
  431. package/dest/versioning.d.ts +6 -9
  432. package/dest/versioning.d.ts.map +1 -1
  433. package/dest/versioning.js +9 -25
  434. package/package.json +33 -27
  435. package/src/bootstrap/bootstrap.ts +42 -15
  436. package/src/client/factory.ts +242 -60
  437. package/src/client/index.ts +1 -0
  438. package/src/client/interface.ts +239 -0
  439. package/src/client/p2p_client.ts +527 -460
  440. package/src/client/test/p2p_client.batch_tx_requester.bench.README.md +197 -0
  441. package/src/config.ts +518 -127
  442. package/src/enr/generate-enr.ts +39 -6
  443. package/src/errors/attestation-pool.error.ts +13 -0
  444. package/src/errors/p2p-service.error.ts +11 -0
  445. package/src/errors/reqresp.error.ts +0 -25
  446. package/src/errors/tx-pool.error.ts +12 -0
  447. package/src/index.ts +5 -1
  448. package/src/mem_pools/attestation_pool/attestation_pool.ts +605 -29
  449. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +828 -201
  450. package/src/mem_pools/attestation_pool/index.ts +9 -2
  451. package/src/mem_pools/attestation_pool/mocks.ts +32 -19
  452. package/src/mem_pools/index.ts +2 -2
  453. package/src/mem_pools/instrumentation.ts +79 -47
  454. package/src/mem_pools/interface.ts +5 -7
  455. package/src/mem_pools/tx_pool_v2/README.md +283 -0
  456. package/src/mem_pools/tx_pool_v2/archive/index.ts +1 -0
  457. package/src/mem_pools/tx_pool_v2/archive/tx_archive.ts +112 -0
  458. package/src/mem_pools/tx_pool_v2/deleted_pool.ts +321 -0
  459. package/src/mem_pools/tx_pool_v2/eviction/eviction_manager.ts +160 -0
  460. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_eviction_rule.ts +122 -0
  461. package/src/mem_pools/tx_pool_v2/eviction/fee_payer_balance_pre_add_rule.ts +125 -0
  462. package/src/mem_pools/tx_pool_v2/eviction/index.ts +28 -0
  463. package/src/mem_pools/tx_pool_v2/eviction/insufficient_fee_per_gas_eviction_rule.ts +65 -0
  464. package/src/mem_pools/tx_pool_v2/eviction/interfaces.ts +219 -0
  465. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_mining_rule.ts +74 -0
  466. package/src/mem_pools/tx_pool_v2/eviction/invalid_txs_after_reorg_rule.ts +101 -0
  467. package/src/mem_pools/tx_pool_v2/eviction/low_priority_eviction_rule.ts +91 -0
  468. package/src/mem_pools/tx_pool_v2/eviction/low_priority_pre_add_rule.ts +99 -0
  469. package/src/mem_pools/tx_pool_v2/eviction/nullifier_conflict_rule.ts +32 -0
  470. package/src/mem_pools/tx_pool_v2/index.ts +12 -0
  471. package/src/mem_pools/tx_pool_v2/instrumentation.ts +69 -0
  472. package/src/mem_pools/tx_pool_v2/interfaces.ts +250 -0
  473. package/src/mem_pools/tx_pool_v2/tx_metadata.ts +349 -0
  474. package/src/mem_pools/tx_pool_v2/tx_pool_bench_metrics.ts +77 -0
  475. package/src/mem_pools/tx_pool_v2/tx_pool_indices.ts +430 -0
  476. package/src/mem_pools/tx_pool_v2/tx_pool_v2.ts +238 -0
  477. package/src/mem_pools/tx_pool_v2/tx_pool_v2_impl.ts +1090 -0
  478. package/src/msg_validators/attestation_validator/README.md +49 -0
  479. package/src/msg_validators/attestation_validator/attestation_validator.ts +105 -15
  480. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +101 -0
  481. package/src/msg_validators/attestation_validator/index.ts +1 -0
  482. package/src/msg_validators/clock_tolerance.ts +121 -0
  483. package/src/msg_validators/index.ts +1 -1
  484. package/src/msg_validators/msg_seen_validator/msg_seen_validator.ts +36 -0
  485. package/src/msg_validators/proposal_validator/README.md +123 -0
  486. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +30 -0
  487. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +41 -0
  488. package/src/msg_validators/proposal_validator/index.ts +3 -0
  489. package/src/msg_validators/proposal_validator/proposal_validator.ts +159 -0
  490. package/src/msg_validators/tx_validator/README.md +127 -0
  491. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +8 -17
  492. package/src/msg_validators/tx_validator/allowed_public_setup.ts +30 -0
  493. package/src/msg_validators/tx_validator/allowed_setup_helpers.ts +31 -0
  494. package/src/msg_validators/tx_validator/archive_cache.ts +28 -0
  495. package/src/msg_validators/tx_validator/block_header_validator.ts +23 -10
  496. package/src/msg_validators/tx_validator/cached_tx_validator.ts +31 -0
  497. package/src/msg_validators/tx_validator/contract_instance_validator.ts +56 -0
  498. package/src/msg_validators/tx_validator/data_validator.ts +138 -71
  499. package/src/msg_validators/tx_validator/double_spend_validator.ts +31 -23
  500. package/src/msg_validators/tx_validator/factory.ts +478 -0
  501. package/src/msg_validators/tx_validator/fee_payer_balance.ts +44 -0
  502. package/src/msg_validators/tx_validator/gas_validator.ts +268 -0
  503. package/src/msg_validators/tx_validator/index.ts +12 -0
  504. package/src/msg_validators/tx_validator/metadata_validator.ts +80 -24
  505. package/src/msg_validators/tx_validator/nullifier_cache.ts +30 -0
  506. package/src/msg_validators/tx_validator/phases_validator.ts +173 -0
  507. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  508. package/src/msg_validators/tx_validator/test_utils.ts +43 -0
  509. package/src/msg_validators/tx_validator/timestamp_validator.ts +57 -0
  510. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +22 -0
  511. package/src/msg_validators/tx_validator/tx_proof_validator.ts +16 -8
  512. package/src/msg_validators/tx_validator/tx_validation_cache.ts +101 -0
  513. package/src/services/data_store.ts +14 -19
  514. package/src/services/discv5/discV5_service.ts +118 -39
  515. package/src/services/dummy_service.ts +196 -20
  516. package/src/services/encoding.ts +95 -11
  517. package/src/services/gossipsub/README.md +641 -0
  518. package/src/services/gossipsub/index.ts +2 -0
  519. package/src/services/gossipsub/scoring.ts +29 -5
  520. package/src/services/gossipsub/topic_score_params.ts +519 -0
  521. package/src/services/index.ts +5 -0
  522. package/src/services/libp2p/instrumentation.ts +140 -0
  523. package/src/services/libp2p/libp2p_service.ts +1373 -438
  524. package/src/services/peer-manager/interface.ts +29 -0
  525. package/src/services/peer-manager/metrics.ts +62 -12
  526. package/src/services/peer-manager/peer_manager.ts +695 -83
  527. package/src/services/peer-manager/peer_scoring.ts +96 -7
  528. package/src/services/reqresp/README.md +215 -0
  529. package/src/services/reqresp/batch-tx-requester/README.md +344 -0
  530. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +660 -0
  531. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  532. package/src/services/reqresp/batch-tx-requester/interface.ts +61 -0
  533. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +168 -0
  534. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +249 -0
  535. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +24 -0
  536. package/src/services/reqresp/config.ts +27 -10
  537. package/src/services/reqresp/connection-sampler/connection_sampler.ts +166 -95
  538. package/src/services/reqresp/constants.ts +14 -0
  539. package/src/services/reqresp/index.ts +2 -0
  540. package/src/services/reqresp/interface.ts +116 -59
  541. package/src/services/reqresp/metrics.ts +39 -28
  542. package/src/services/reqresp/protocols/auth.ts +83 -0
  543. package/src/services/reqresp/protocols/block_txs/bitvector.ts +107 -0
  544. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +80 -0
  545. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +171 -0
  546. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  547. package/src/services/reqresp/protocols/goodbye.ts +9 -7
  548. package/src/services/reqresp/protocols/index.ts +2 -1
  549. package/src/services/reqresp/protocols/status.ts +121 -5
  550. package/src/services/reqresp/protocols/tx.ts +56 -8
  551. package/src/services/reqresp/rate-limiter/rate_limiter.ts +25 -12
  552. package/src/services/reqresp/rate-limiter/rate_limits.ts +16 -6
  553. package/src/services/reqresp/reqresp.ts +397 -422
  554. package/src/services/reqresp/status.ts +12 -3
  555. package/src/services/service.ts +104 -28
  556. package/src/services/tx_collection/config.ts +89 -0
  557. package/src/services/tx_collection/file_store_tx_collection.ts +153 -0
  558. package/src/services/tx_collection/file_store_tx_source.ts +129 -0
  559. package/src/services/tx_collection/index.ts +3 -0
  560. package/src/services/tx_collection/instrumentation.ts +35 -0
  561. package/src/services/tx_collection/request_tracker.ts +127 -0
  562. package/src/services/tx_collection/tx_collection.ts +468 -0
  563. package/src/services/tx_collection/tx_collection_sink.ts +125 -0
  564. package/src/services/tx_collection/tx_source.ts +57 -0
  565. package/src/services/tx_file_store/config.ts +37 -0
  566. package/src/services/tx_file_store/index.ts +3 -0
  567. package/src/services/tx_file_store/instrumentation.ts +36 -0
  568. package/src/services/tx_file_store/tx_file_store.ts +163 -0
  569. package/src/services/tx_provider.ts +238 -0
  570. package/src/services/tx_provider_instrumentation.ts +54 -0
  571. package/src/test-helpers/index.ts +3 -0
  572. package/src/test-helpers/make-enrs.ts +4 -5
  573. package/src/test-helpers/make-test-p2p-clients.ts +117 -26
  574. package/src/test-helpers/mock-pubsub.ts +311 -0
  575. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  576. package/src/test-helpers/reqresp-nodes.ts +101 -62
  577. package/src/test-helpers/test_tx_provider.ts +69 -0
  578. package/src/test-helpers/testbench-utils.ts +453 -0
  579. package/src/testbench/p2p_client_testbench_worker.ts +477 -95
  580. package/src/testbench/parse_log_file.ts +4 -4
  581. package/src/testbench/testbench.ts +4 -4
  582. package/src/testbench/worker_client_manager.ts +366 -63
  583. package/src/types/index.ts +2 -0
  584. package/src/util.ts +128 -93
  585. package/src/versioning.ts +11 -34
  586. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +0 -22
  587. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +0 -1
  588. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +0 -112
  589. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +0 -17
  590. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +0 -1
  591. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +0 -129
  592. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +0 -66
  593. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +0 -1
  594. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +0 -245
  595. package/dest/mem_pools/tx_pool/index.d.ts +0 -4
  596. package/dest/mem_pools/tx_pool/index.d.ts.map +0 -1
  597. package/dest/mem_pools/tx_pool/index.js +0 -3
  598. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -56
  599. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  600. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -141
  601. package/dest/mem_pools/tx_pool/priority.d.ts +0 -8
  602. package/dest/mem_pools/tx_pool/priority.d.ts.map +0 -1
  603. package/dest/mem_pools/tx_pool/priority.js +0 -10
  604. package/dest/mem_pools/tx_pool/tx_pool.d.ts +0 -66
  605. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +0 -1
  606. package/dest/mem_pools/tx_pool/tx_pool.js +0 -3
  607. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +0 -7
  608. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +0 -1
  609. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +0 -169
  610. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -8
  611. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  612. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -21
  613. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  614. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  615. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  616. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +0 -45
  617. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +0 -1
  618. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +0 -88
  619. package/dest/services/reqresp/protocols/block.d.ts +0 -4
  620. package/dest/services/reqresp/protocols/block.d.ts.map +0 -1
  621. package/dest/services/reqresp/protocols/block.js +0 -8
  622. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +0 -159
  623. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +0 -161
  624. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +0 -309
  625. package/src/mem_pools/tx_pool/index.ts +0 -3
  626. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -174
  627. package/src/mem_pools/tx_pool/priority.ts +0 -13
  628. package/src/mem_pools/tx_pool/tx_pool.ts +0 -76
  629. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +0 -130
  630. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -29
  631. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
  632. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +0 -94
  633. package/src/services/reqresp/protocols/block.ts +0 -15
@@ -1,105 +1,625 @@
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
+ };
6
369
  }
7
- import { Fr } from '@aztec/foundation/fields';
370
+ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
371
+ return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
372
+ }
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';
8
376
  import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
9
- import { SerialQueue } from '@aztec/foundation/queue';
10
377
  import { RunningPromise } from '@aztec/foundation/running-promise';
11
- import { BlockAttestation, BlockProposal, P2PClientType, PeerErrorSeverity, TopicTypeMap, getTopicTypeForClientType, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
378
+ import { Timer } from '@aztec/foundation/timer';
379
+ import { protocolContractsHash } from '@aztec/protocol-contracts';
380
+ import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PMessage, PeerErrorSeverity, PeerErrorSeverityByHarshness, TopicType, createTopicString, getTopicsForConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
12
381
  import { MerkleTreeId } from '@aztec/stdlib/trees';
13
382
  import { Tx } from '@aztec/stdlib/tx';
14
- import { Attributes, OtelMetricsAdapter, WithTracer, trackSpan } from '@aztec/telemetry-client';
383
+ import { compressComponentVersions } from '@aztec/stdlib/versioning';
384
+ import { Attributes, OtelMetricsAdapter, SpanStatusCode, WithTracer, trackSpan } from '@aztec/telemetry-client';
15
385
  import { gossipsub } from '@chainsafe/libp2p-gossipsub';
16
- import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
386
+ import { createPeerScoreParams } from '@chainsafe/libp2p-gossipsub/score';
17
387
  import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
18
388
  import { noise } from '@chainsafe/libp2p-noise';
19
389
  import { yamux } from '@chainsafe/libp2p-yamux';
20
390
  import { bootstrap } from '@libp2p/bootstrap';
21
391
  import { identify } from '@libp2p/identify';
22
392
  import { TopicValidatorResult } from '@libp2p/interface';
23
- import '@libp2p/kad-dht';
24
393
  import { mplex } from '@libp2p/mplex';
25
394
  import { tcp } from '@libp2p/tcp';
395
+ import { multiaddr } from '@multiformats/multiaddr';
396
+ import { ENR } from '@nethermindeth/enr';
26
397
  import { createLibp2p } from 'libp2p';
27
- import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
28
- import { DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
398
+ import { CheckpointProposalReceivedCallbackNotRegisteredError } from '../../errors/p2p-service.error.js';
399
+ import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, DoubleSpendTxValidator, FishermanAttestationValidator, getDefaultAllowedSetupFunctions } from '../../msg_validators/index.js';
400
+ import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
401
+ import { createFirstStageTxValidationsForGossipedTransactions, createSecondStageTxValidationsForGossipedTransactions, createTxValidatorForBlockProposalReceivedTxs } from '../../msg_validators/tx_validator/factory.js';
29
402
  import { GossipSubEvent } from '../../types/index.js';
30
403
  import { convertToMultiaddr } from '../../util.js';
404
+ import { getVersions } from '../../versioning.js';
31
405
  import { AztecDatastore } from '../data_store.js';
406
+ import { DiscV5Service } from '../discv5/discV5_service.js';
32
407
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
33
- 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';
34
410
  import { PeerManager } from '../peer-manager/peer_manager.js';
35
411
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
36
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol } from '../reqresp/interface.js';
37
- import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
38
- import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
412
+ import { ReqRespSubProtocol, ValidationError, pingHandler, reqGoodbyeHandler, reqRespBlockTxsHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/index.js';
39
413
  import { ReqResp } from '../reqresp/reqresp.js';
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
+ }));
40
433
  /**
41
434
  * Lib P2P implementation of the P2PService interface.
42
435
  */ export class LibP2PService extends WithTracer {
43
- clientType;
44
436
  config;
45
437
  node;
46
438
  peerDiscoveryService;
439
+ reqresp;
440
+ peerManager;
47
441
  mempools;
48
- l2BlockSource;
442
+ archiver;
443
+ epochCache;
49
444
  proofVerifier;
50
445
  worldStateSynchronizer;
51
- logger;
52
- jobQueue;
53
- peerManager;
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
+ }
54
482
  discoveryRunningPromise;
483
+ msgIdSeenValidators;
55
484
  // Message validators
56
- attestationValidator;
57
485
  blockProposalValidator;
58
- // Request and response sub service
59
- reqresp;
486
+ checkpointProposalValidator;
487
+ checkpointAttestationValidator;
488
+ protocolVersion;
489
+ topicStrings;
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;
60
493
  /**
61
494
  * Callback for when a block is received from a peer.
62
495
  * @param block - The block received from the peer.
63
496
  * @returns The attestation for the block, if any.
64
497
  */ blockReceivedCallback;
65
- constructor(clientType, config, node, peerDiscoveryService, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
66
- super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.mempools = mempools, this.l2BlockSource = l2BlockSource, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.logger = logger, this.jobQueue = new SerialQueue();
67
- const peerScoring = new PeerScoring(config);
68
- this.reqresp = new ReqResp(config, node, peerScoring);
69
- this.peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, this.reqresp);
70
- // Update gossipsub score params
71
- this.node.services.pubsub.score.params.appSpecificScore = (peerId)=>{
72
- return this.peerManager.getPeerScore(peerId);
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;
508
+ gossipSubEventHandler;
509
+ ipChangedHandler;
510
+ discoveredP2pIp;
511
+ instrumentation;
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;
519
+ this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
520
+ this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
521
+ this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
522
+ this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
523
+ this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
524
+ const versions = getVersions(config);
525
+ this.protocolVersion = compressComponentVersions(versions);
526
+ logger.info(`Started libp2p service with protocol version ${this.protocolVersion}`);
527
+ this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
528
+ this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
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
73
549
  };
74
- this.node.services.pubsub.score.params.appSpecificWeight = 10;
75
- this.attestationValidator = new AttestationValidator(epochCache);
76
- this.blockProposalValidator = new BlockProposalValidator(epochCache);
550
+ this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry, attestationValidatorOpts) : new CheckpointAttestationValidator(epochCache, attestationValidatorOpts);
551
+ this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
77
552
  this.blockReceivedCallback = async (block)=>{
78
- this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`, {
79
- 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()
80
555
  });
81
- return undefined;
556
+ return true;
82
557
  };
558
+ this.allNodesCheckpointReceivedCallback = (_checkpoint)=>{
559
+ throw new CheckpointProposalReceivedCallbackNotRegisteredError();
560
+ };
561
+ this.validatorCheckpointReceivedCallback = (_checkpoint)=>{
562
+ return Promise.resolve(undefined);
563
+ };
564
+ }
565
+ updateConfig(config) {
566
+ this.reqresp.updateConfig(config);
567
+ this.config = merge(this.config, config);
83
568
  }
84
569
  /**
85
570
  * Creates an instance of the LibP2P service.
86
571
  * @param config - The configuration to use when creating the service.
87
572
  * @param txPool - The transaction pool to be accessed by the service.
88
573
  * @returns The new service.
89
- */ static async new(clientType, config, peerDiscoveryService, peerId, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, store, telemetry, logger = createLogger('p2p:libp2p_service')) {
90
- const { tcpListenAddress, tcpAnnounceAddress, maxPeerCount } = config;
91
- const bindAddrTcp = convertToMultiaddr(tcpListenAddress, 'tcp');
92
- // We know tcpAnnounceAddress cannot be null here because we set it or throw when setting up the service.
93
- const announceAddrTcp = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
94
- const datastore = new AztecDatastore(store);
95
- const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
96
- // If bootstrap nodes are provided, also provide them to the p2p service
574
+ */ static async new(config, peerId, deps) {
575
+ const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, blockMinFeesProvider, telemetry, logger, packageVersion, txValidationCache } = deps;
576
+ const { p2pPort, maxPeerCount, listenAddress } = config;
577
+ const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
578
+ const datastore = new AztecDatastore(peerStore);
579
+ const otelMetricsAdapter = new OtelMetricsAdapter(telemetry, logger.getBindings());
580
+ const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`, logger.getBindings()));
581
+ // Seed libp2p's bootstrap discovery with private and trusted peers
582
+ const bootstrapNodes = [
583
+ ...config.privatePeers,
584
+ ...config.trustedPeers
585
+ ];
97
586
  const peerDiscovery = [];
98
- if (peerDiscoveryService.bootstrapNodes.length > 0) {
587
+ if (bootstrapNodes.length > 0) {
99
588
  peerDiscovery.push(bootstrap({
100
- list: peerDiscoveryService.bootstrapNodes
589
+ list: bootstrapNodes
101
590
  }));
102
591
  }
592
+ const versions = getVersions(config);
593
+ const protocolVersion = compressComponentVersions(versions);
594
+ const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
595
+ const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
596
+ const peerId = await enr.peerId();
597
+ const address = enr.getLocationMultiaddr('tcp');
598
+ if (address === undefined) {
599
+ throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
600
+ }
601
+ return {
602
+ id: peerId,
603
+ addrs: [
604
+ address
605
+ ]
606
+ };
607
+ }))).filter((peer)=>peer !== undefined);
608
+ const announceTcpMultiaddr = config.p2pIp ? [
609
+ convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
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
+ });
103
623
  const node = await createLibp2p({
104
624
  start: false,
105
625
  peerId,
@@ -107,44 +627,76 @@ import { ReqResp } from '../reqresp/reqresp.js';
107
627
  listen: [
108
628
  bindAddrTcp
109
629
  ],
110
- announce: [
111
- announceAddrTcp
112
- ]
630
+ announce: announceTcpMultiaddr
113
631
  },
114
632
  transports: [
115
633
  tcp({
116
- maxConnections: config.maxPeerCount,
634
+ // It's better to have this number a bit higher than our maxPeerCount because it's sets the limit on transport (TCP) layer
635
+ // The connection attempts to the node on TCP layer are not necessarily valid Aztec peers so we want to have a bit of leeway here
636
+ // If we hit the limit, the connection will be temporarily accepted and immediately dropped.
637
+ // Docs: https://nodejs.org/api/net.html#servermaxconnections
638
+ maxConnections: maxPeerCount * 2,
117
639
  // socket option: the maximum length of the queue of pending connections
118
- // https://nodejs.org/dist/latest-v18.x/docs/api/net.html#serverlisten
640
+ // https://nodejs.org/dist/latest-v22.x/docs/api/net.html#serverlisten
119
641
  // it's not safe if we increase this number
120
642
  backlog: 5,
121
643
  closeServerOnMaxConnections: {
122
- closeAbove: maxPeerCount ?? Infinity,
123
- listenBelow: maxPeerCount ?? Infinity
644
+ // The property `maxConnections` will protect us against the most DDOS attack
645
+ // This property protects us in case of burst of new connections where server is not able to close them quickly enough
646
+ // In case closeAbove is reached, the server stops listening altogether
647
+ // It's important that there is enough difference between closeAbove and listenAbove,
648
+ // otherwise the server.listener will flap between being closed and open potentially degrading perf even more
649
+ closeAbove: maxPeerCount * 3,
650
+ listenBelow: Math.floor(maxPeerCount * 0.9)
124
651
  }
125
652
  })
126
653
  ],
127
654
  datastore,
128
655
  peerDiscovery,
129
656
  streamMuxers: [
130
- mplex(),
131
- yamux()
657
+ yamux(),
658
+ mplex()
132
659
  ],
133
660
  connectionEncryption: [
134
661
  noise()
135
662
  ],
136
663
  connectionManager: {
137
664
  minConnections: 0,
665
+ // We set maxConnections above maxPeerCount because if we hit limit of maxPeerCount
666
+ // libp2p will start aggressively rejecting all new connections, preventing network discovery and crawling.
667
+ maxConnections: maxPeerCount * 2,
138
668
  maxParallelDials: 100,
139
669
  dialTimeout: 30_000,
140
670
  maxPeerAddrsToDial: 5,
141
671
  maxIncomingPendingConnections: 5
142
672
  },
673
+ connectionGater: {
674
+ denyInboundConnection: (maConn)=>{
675
+ const allowed = peerManager.isNodeAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
676
+ if (allowed) {
677
+ return false;
678
+ }
679
+ logger.debug(`Connection gater: Denying inbound connection from ${maConn.remoteAddr.toString()}`);
680
+ return true;
681
+ },
682
+ denyInboundEncryptedConnection: (peerId, _maConn)=>{
683
+ //NOTE: it is not necessary to check address here because this was already done by
684
+ // denyInboundConnection
685
+ const allowed = peerManager.isNodeAllowedToConnect(peerId);
686
+ if (allowed) {
687
+ return false;
688
+ }
689
+ logger.debug(`Connection gater: Denying inbound encrypted connection from ${peerId.toString()}`);
690
+ return true;
691
+ }
692
+ },
143
693
  services: {
144
694
  identify: identify({
145
- protocolPrefix: 'aztec'
695
+ protocolPrefix: 'aztec',
696
+ runOnConnectionOpen: true
146
697
  }),
147
698
  pubsub: gossipsub({
699
+ directPeers,
148
700
  debugName: 'gossipsub',
149
701
  globalSignaturePolicy: SignaturePolicy.StrictNoSign,
150
702
  allowPublishToZeroTopicPeers: true,
@@ -156,43 +708,41 @@ import { ReqResp } from '../reqresp/reqresp.js';
156
708
  heartbeatInterval: config.gossipsubInterval,
157
709
  mcacheLength: config.gossipsubMcacheLength,
158
710
  mcacheGossip: config.gossipsubMcacheGossip,
711
+ seenTTL: config.gossipsubSeenTTL,
159
712
  msgIdFn: getMsgIdFn,
160
713
  msgIdToStrFn: msgIdToStrFn,
161
714
  fastMsgIdFn: fastMsgIdFn,
162
715
  dataTransform: new SnappyTransform(),
163
716
  metricsRegister: otelMetricsAdapter,
164
- metricsTopicStrToLabel: metricsTopicStrToLabels(),
717
+ metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
165
718
  asyncValidation: true,
166
719
  scoreThresholds: gossipScoreThresholds,
167
720
  scoreParams: createPeerScoreParams({
168
721
  // IPColocation factor can be disabled for local testing - default to -5
169
722
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
170
- topics: {
171
- [Tx.p2pTopic]: createTopicScoreParams({
172
- topicWeight: 1,
173
- invalidMessageDeliveriesWeight: -20,
174
- invalidMessageDeliveriesDecay: 0.5
175
- }),
176
- [BlockAttestation.p2pTopic]: createTopicScoreParams({
177
- topicWeight: 1,
178
- invalidMessageDeliveriesWeight: -20,
179
- invalidMessageDeliveriesDecay: 0.5
180
- }),
181
- [BlockProposal.p2pTopic]: createTopicScoreParams({
182
- topicWeight: 1,
183
- invalidMessageDeliveriesWeight: -20,
184
- invalidMessageDeliveriesDecay: 0.5
185
- })
186
- }
723
+ topics: topicScoreParams
187
724
  })
188
725
  }),
189
726
  components: (components)=>({
190
- connectionManager: components.connectionManager
727
+ connectionManager: components.connectionManager,
728
+ addressManager: components.addressManager
191
729
  })
192
730
  },
193
- logger: createLibp2pComponentLogger(logger.module)
731
+ logger: createLibp2pComponentLogger(logger.module, logger.getBindings())
194
732
  });
195
- return new LibP2PService(clientType, config, node, peerDiscoveryService, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
733
+ const peerScoring = new PeerScoring(config, telemetry);
734
+ const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
735
+ const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
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;
744
+ node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
745
+ return new LibP2PService(config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, blockMinFeesProvider, telemetry, logger, txValidationCache);
196
746
  }
197
747
  /**
198
748
  * Starts the LibP2P service.
@@ -202,45 +752,75 @@ import { ReqResp } from '../reqresp/reqresp.js';
202
752
  if (this.node.status === 'started') {
203
753
  throw new Error('P2P service already started');
204
754
  }
205
- // Get listen & announce addresses for logging
206
- const { tcpListenAddress, tcpAnnounceAddress } = this.config;
207
- if (!tcpAnnounceAddress) {
208
- throw new Error('Announce address not provided.');
209
- }
210
- const announceTcpMultiaddr = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
211
- // Start job queue, peer discovery service and libp2p node
212
- this.jobQueue.start();
213
- await this.peerDiscoveryService.start();
214
- await this.node.start();
215
- // Subscribe to standard GossipSub topics by default
216
- for (const topic of getTopicTypeForClientType(this.clientType)){
217
- this.subscribeToTopic(TopicTypeMap[topic].p2pTopic);
755
+ const { p2pIp, p2pPort } = this.config;
756
+ if (!p2pIp && !this.config.queryForIp) {
757
+ throw new Error('Announce address not provided and queryForIp is not enabled.');
218
758
  }
759
+ const announceTcpMultiaddr = p2pIp ? convertToMultiaddr(p2pIp, p2pPort, 'tcp') : undefined;
219
760
  // Create request response protocol handlers
220
761
  const txHandler = reqRespTxHandler(this.mempools);
221
762
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
222
- const blockHandler = reqRespBlockHandler(this.l2BlockSource);
763
+ const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
223
764
  const requestResponseHandlers = {
224
765
  [ReqRespSubProtocol.PING]: pingHandler,
225
- [ReqRespSubProtocol.STATUS]: statusHandler,
226
- [ReqRespSubProtocol.TX]: txHandler.bind(this),
227
- [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
228
- [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
766
+ [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
767
+ [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this)
229
768
  };
769
+ if (!this.config.disableTransactions) {
770
+ const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.archiver, this.mempools.txPool);
771
+ requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
772
+ }
773
+ if (!this.config.disableTransactions) {
774
+ requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
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
+ }
230
783
  // add GossipSub listener
231
- this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
232
- // Start running promise for peer discovery
233
- this.discoveryRunningPromise = new RunningPromise(()=>this.peerManager.heartbeat(), this.logger, this.config.peerCheckIntervalMS);
784
+ this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
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);
234
820
  this.discoveryRunningPromise.start();
235
- // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
236
- const reqrespSubProtocolValidators = {
237
- ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
238
- // TODO(#11336): A request validator for blocks
239
- [ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this)
240
- };
241
- await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
242
821
  this.logger.info(`Started P2P service`, {
243
- listen: tcpListenAddress,
822
+ listen: this.config.listenAddress,
823
+ port: this.config.p2pPort,
244
824
  announce: announceTcpMultiaddr,
245
825
  peerId: this.node.peerId.toString()
246
826
  });
@@ -250,12 +830,14 @@ import { ReqResp } from '../reqresp/reqresp.js';
250
830
  * @returns An empty promise.
251
831
  */ async stop() {
252
832
  // Remove gossip sub listener
253
- this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
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
+ }
254
838
  // Stop peer manager
255
839
  this.logger.debug('Stopping peer manager...');
256
840
  await this.peerManager.stop();
257
- this.logger.debug('Stopping job queue...');
258
- await this.jobQueue.end();
259
841
  this.logger.debug('Stopping running promise...');
260
842
  await this.discoveryRunningPromise?.stop();
261
843
  this.logger.debug('Stopping peer discovery service...');
@@ -266,9 +848,18 @@ import { ReqResp } from '../reqresp/reqresp.js';
266
848
  await this.stopLibP2P();
267
849
  this.logger.info('LibP2P service stopped');
268
850
  }
851
+ addReqRespSubProtocol(subProtocol, handler) {
852
+ return this.reqresp.addSubProtocol(subProtocol, handler);
853
+ }
854
+ registerThisValidatorAddresses(address) {
855
+ this.peerManager.registerThisValidatorAddresses(address);
856
+ }
269
857
  getPeers(includePending) {
270
858
  return this.peerManager.getPeers(includePending);
271
859
  }
860
+ getGossipMeshPeerCount(topicType) {
861
+ return this.node.services.pubsub.getMeshPeers(this.topicStrings[topicType]).length;
862
+ }
272
863
  handleGossipSubEvent(e) {
273
864
  this.logger.trace(`Received PUBSUB message.`);
274
865
  const safeJob = async ()=>{
@@ -280,25 +871,8 @@ import { ReqResp } from '../reqresp/reqresp.js';
280
871
  };
281
872
  setImmediate(()=>void safeJob());
282
873
  }
283
- /**
284
- * Send Request via the ReqResp service
285
- * The subprotocol defined will determine the request and response types
286
- *
287
- * See the subProtocolMap for the mapping of subprotocols to request/response types in `interface.ts`
288
- *
289
- * @param protocol The request response protocol to use
290
- * @param request The request type to send
291
- * @returns
292
- */ sendRequest(protocol, request) {
293
- return this.reqresp.sendRequest(protocol, request);
294
- }
295
- /**
296
- * Send a batch of requests to peers, and return the responses
297
- * @param protocol - The request response protocol to use
298
- * @param requests - The requests to send to the peers
299
- * @returns The responses to the requests
300
- */ sendBatchRequest(protocol, requests) {
301
- return this.reqresp.sendBatchRequest(protocol, requests);
874
+ sendRequestToPeer(peerId, subProtocol, payload, dialTimeout) {
875
+ return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
302
876
  }
303
877
  /**
304
878
  * Get the ENR of the node
@@ -308,7 +882,28 @@ import { ReqResp } from '../reqresp/reqresp.js';
308
882
  }
309
883
  registerBlockReceivedCallback(callback) {
310
884
  this.blockReceivedCallback = callback;
311
- this.logger.verbose('Block received callback registered');
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;
312
907
  }
313
908
  /**
314
909
  * Subscribes to a topic.
@@ -322,236 +917,836 @@ import { ReqResp } from '../reqresp/reqresp.js';
322
917
  /**
323
918
  * Publishes data to a topic.
324
919
  * @param topic - The topic to publish to.
325
- * @param data - The data to publish.
920
+ * @param data - The message to publish.
326
921
  * @returns The number of recipients the data was sent to.
327
- */ async publishToTopic(topic, data) {
922
+ */ async publishToTopic(topic, message) {
328
923
  if (!this.node.services.pubsub) {
329
924
  throw new Error('Pubsub service not available.');
330
925
  }
331
- const result = await this.node.services.pubsub.publish(topic, data);
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);
929
+ const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
332
930
  return result.recipients.length;
333
931
  }
334
932
  /**
933
+ * Checks if this message has already been seen, based on its msgId computed from hashing the message data.
934
+ * Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
935
+ * messages to avoid tx echoes across the network.
936
+ */ preValidateReceivedMessage(msg, msgId, source) {
937
+ let topicType;
938
+ switch(msg.topic){
939
+ case this.topicStrings[TopicType.tx]:
940
+ topicType = TopicType.tx;
941
+ break;
942
+ case this.topicStrings[TopicType.block_proposal]:
943
+ topicType = TopicType.block_proposal;
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;
951
+ default:
952
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
953
+ break;
954
+ }
955
+ const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
956
+ if (!validator || !validator.addMessage(msgId)) {
957
+ this.instrumentation.incMessagePrevalidationStatus(false, topicType);
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
+ }
965
+ return {
966
+ result: false,
967
+ topicType
968
+ };
969
+ }
970
+ this.instrumentation.incMessagePrevalidationStatus(true, topicType);
971
+ return {
972
+ result: true,
973
+ topicType
974
+ };
975
+ }
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
+ /**
335
996
  * Handles a new gossip message that was received by the client.
336
997
  * @param topic - The message's topic.
337
998
  * @param data - The message data
338
999
  */ async handleNewGossipMessage(msg, msgId, source) {
339
- if (msg.topic === Tx.p2pTopic) {
340
- await this.handleGossipedTx(msg, msgId, source);
1000
+ const msgReceivedTime = Date.now();
1001
+ let topicType;
1002
+ const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
1003
+ if (!p2pMessage) {
1004
+ return;
341
1005
  }
342
- if (msg.topic === BlockAttestation.p2pTopic && this.clientType === P2PClientType.Full) {
343
- await this.processAttestationFromPeer(msg, msgId, source);
1006
+ const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
1007
+ if (!preValidationResult.result) {
1008
+ return;
1009
+ }
1010
+ // Determine topic type for attributes
1011
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
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;
1019
+ }
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();
344
1070
  }
345
- if (msg.topic == BlockProposal.p2pTopic) {
346
- await this.processBlockFromPeer(msg, msgId, source);
1071
+ if (latency !== undefined && topicType !== undefined) {
1072
+ this.instrumentation.recordMessageLatency(topicType, latency);
347
1073
  }
348
1074
  return;
349
1075
  }
350
- async validateReceivedMessage(validationFunc, msgId, source) {
1076
+ async validateReceivedMessage(validationFunc, msgId, source, topicType) {
1077
+ // Default to reject result with a penalty if validation function throws an error
351
1078
  let resultAndObj = {
352
- result: false,
353
- obj: undefined
1079
+ result: TopicValidatorResult.Reject,
1080
+ severity: PeerErrorSeverity.MidToleranceError
354
1081
  };
1082
+ const timer = new Timer();
355
1083
  try {
356
1084
  resultAndObj = await validationFunc();
357
1085
  } catch (err) {
358
- this.logger.error(`Error deserialising and validating message `, err);
1086
+ this.logger.error(`Error validating gossipsub message`, err, {
1087
+ msgId,
1088
+ source: source.toString(),
1089
+ topicType
1090
+ });
359
1091
  }
360
- this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject);
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
+ }
1104
+ if (resultAndObj.result === TopicValidatorResult.Accept) {
1105
+ this.logger.debug(`Message ${topicType} accepted by validator`, {
1106
+ msgId,
1107
+ source: source.toString(),
1108
+ topicType
1109
+ });
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
+ });
1125
+ }
1126
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
361
1127
  return resultAndObj;
362
1128
  }
363
- async handleGossipedTx(msg, msgId, source) {
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
+ }
1141
+ async handleGossipedTx(payloadData, msgId, source) {
364
1142
  const validationFunc = async ()=>{
365
- const tx = Tx.fromBuffer(Buffer.from(msg.data));
366
- const result = await this.validatePropagatedTx(tx, source);
367
- return {
368
- result,
369
- obj: tx
370
- };
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,
1213
+ [Attributes.P2P_ID]: source.toString()
1214
+ });
1215
+ if (wasAccepted) {
1216
+ return {
1217
+ result: TopicValidatorResult.Accept,
1218
+ obj: tx
1219
+ };
1220
+ } else if (wasIgnored) {
1221
+ return {
1222
+ result: TopicValidatorResult.Ignore,
1223
+ obj: tx
1224
+ };
1225
+ } else {
1226
+ this.logger.warn(`Gossiped tx ${txHash.toString()} unexpectedly rejected by pool`, {
1227
+ source: source.toString(),
1228
+ txHash: txHash.toString()
1229
+ });
1230
+ return {
1231
+ result: TopicValidatorResult.Reject,
1232
+ severity: PeerErrorSeverity.HighToleranceError
1233
+ };
1234
+ }
371
1235
  };
372
- const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source);
373
- if (!result || !tx) {
1236
+ const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.tx);
1237
+ if (result !== TopicValidatorResult.Accept || !tx) {
374
1238
  return;
375
1239
  }
376
- const txHash = await tx.getTxHash();
1240
+ // Tx was accepted into pool and will be propagated - just log and record metrics
1241
+ const txHash = tx.getTxHash();
377
1242
  const txHashString = txHash.toString();
378
- this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()}.`);
379
- await this.mempools.txPool.addTxs([
380
- tx
381
- ]);
1243
+ this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
1244
+ source: source.toString(),
1245
+ txHash: txHashString
1246
+ });
1247
+ this.instrumentation.incrementTxReceived(1);
382
1248
  }
383
- /**Process Attestation From Peer
384
- * When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
385
- *
386
- * @param attestation - The attestation to process.
387
- */ async processAttestationFromPeer(msg, msgId, source) {
388
- const validationFunc = async ()=>{
389
- const attestation = BlockAttestation.fromBuffer(Buffer.from(msg.data));
390
- const result = await this.validateAttestation(source, attestation);
391
- this.logger.trace(`validatePropagatedAttestation: ${result}`, {
392
- [Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toString(),
393
- [Attributes.P2P_ID]: source.toString()
394
- });
1249
+ /**
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
+ });
1260
+ }
1261
+ return this.validateAndStoreCheckpointAttestation(source, attestation);
1262
+ }, msgId, source, TopicType.checkpoint_attestation);
1263
+ if (result !== TopicValidatorResult.Accept || !attestation) {
1264
+ return;
1265
+ }
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,
1269
+ archive: attestation.archive.toString(),
1270
+ source: source.toString()
1271
+ });
1272
+ }
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') {
395
1283
  return {
396
- result,
1284
+ result: TopicValidatorResult.Ignore,
397
1285
  obj: attestation
398
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
1314
+ });
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
+ });
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
399
1342
  };
400
- const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source);
401
- if (!result || !attestation) {
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) {
402
1348
  return;
403
1349
  }
404
- this.logger.debug(`Received attestation for block ${attestation.blockNumber.toNumber()} slot ${attestation.slotNumber.toNumber()} from external peer.`, {
405
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
406
- slot: attestation.slotNumber.toNumber(),
407
- archive: attestation.archive.toString(),
408
- block: attestation.blockNumber.toNumber()
409
- });
410
- await this.mempools.attestationPool.addAttestations([
411
- attestation
412
- ]);
1350
+ await this.processValidBlockProposal(block, source);
413
1351
  }
414
- async processBlockFromPeer(msg, msgId, source) {
415
- const validationFunc = async ()=>{
416
- const block = BlockProposal.fromBuffer(Buffer.from(msg.data));
417
- const result = await this.validateBlockProposal(source, block);
418
- this.logger.trace(`validatePropagatedBlock: ${result}`, {
419
- [Attributes.SLOT_NUMBER]: block.payload.header.globalVariables.slotNumber.toString(),
420
- [Attributes.P2P_ID]: source.toString()
421
- });
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') {
422
1362
  return {
423
- result,
1363
+ result: TopicValidatorResult.Ignore,
424
1364
  obj: block
425
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
426
1432
  };
427
- const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source);
428
- if (!result || !block) {
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.
1436
+ async processValidBlockProposal(block, sender) {
1437
+ const slot = block.slotNumber;
1438
+ this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
1439
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
1440
+ source: sender.toString(),
1441
+ ...block.toBlockInfo()
1442
+ });
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();
429
1470
  return;
430
1471
  }
431
- await this.processValidBlockProposal(block);
1472
+ // Process the block first, since it's required for the checkpoint proposal validation.
1473
+ await processBlockFn();
1474
+ await processCheckpointFn();
432
1475
  }
433
- // REVIEW: callback pattern https://github.com/AztecProtocol/aztec-packages/issues/7963
434
- async processValidBlockProposal(block) {
435
- this.logger.verbose(`Received block ${block.blockNumber.toNumber()} for slot ${block.slotNumber.toNumber()} from external peer.`, {
436
- p2pMessageIdentifier: await block.p2pMessageIdentifier(),
437
- slot: block.slotNumber.toNumber(),
438
- archive: block.archive.toString(),
439
- block: block.blockNumber.toNumber()
440
- });
441
- const attestation = await this.blockReceivedCallback(block);
442
- // TODO: fix up this pattern - the abstraction is not nice
443
- // The attestation can be undefined if no handler is registered / the validator deems the block invalid
444
- if (attestation != undefined) {
445
- this.logger.verbose(`Broadcasting attestation for block ${attestation.blockNumber.toNumber()} slot ${attestation.slotNumber.toNumber()}`, {
446
- p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
447
- slot: attestation.slotNumber.toNumber(),
448
- archive: attestation.archive.toString(),
449
- block: attestation.blockNumber.toNumber()
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
1510
+ });
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;
1517
+ }
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()
450
1546
  });
451
- await this.broadcastAttestation(attestation);
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
+ };
452
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
+ };
453
1592
  }
454
1593
  /**
455
- * Broadcast an attestation to all peers.
456
- * @param attestation - The attestation to broadcast.
457
- */ async broadcastAttestation(attestation) {
458
- 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
+ }
459
1615
  }
460
1616
  /**
461
1617
  * Propagates provided message to peers.
462
1618
  * @param message - The message to propagate.
463
1619
  */ async propagate(message) {
464
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
1620
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
465
1621
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, {
466
1622
  p2pMessageIdentifier
467
1623
  });
468
- void this.jobQueue.put(async ()=>{
469
- await this.sendToPeers(message);
470
- }).catch((error)=>{
1624
+ void this.sendToPeers(message).catch((error)=>{
471
1625
  this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, {
472
1626
  error
473
1627
  });
474
1628
  });
475
1629
  }
476
1630
  /**
477
- * Validate a tx that has been requested from a peer.
478
- *
479
- * The core component of this validator is that the tx hash MUST match the requested tx hash,
480
- * In order to perform this check, the tx proof must be verified.
481
- *
482
- * Note: This function is called from within `ReqResp.sendRequest` as part of the
483
- * ReqRespSubProtocol.TX subprotocol validation.
484
- *
485
- * @param requestedTxHash - The hash of the tx that was requested.
486
- * @param responseTx - The tx that was received as a response to the request.
487
- * @param peerId - The peer ID of the peer that sent the tx.
488
- * @returns True if the tx is valid, false otherwise.
489
- */ async validateRequestedTx(requestedTxHash, responseTx, peerId) {
490
- const proofValidator = new TxProofValidator(this.proofVerifier);
491
- const validProof = await proofValidator.validateTx(responseTx);
492
- // If the node returns the wrong data, we penalize it
493
- if (!requestedTxHash.equals(await responseTx.getTxHash())) {
494
- // Returning the wrong data is a low tolerance error
495
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
496
- return false;
497
- }
498
- if (validProof.result === 'invalid') {
499
- // If the proof is invalid, but the txHash is correct, then this is an active attack and we severly punish
500
- this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1631
+ * Validate the requested block transactions request-response consistency.
1632
+ * It does NOT validate the transactions themselves.
1633
+ * @param request - The block transactions request.
1634
+ * @param response - The block transactions response.
1635
+ * @param peerId - The ID of the peer that made the request.
1636
+ * @returns True if the request-response is consistent, false otherwise.
1637
+ */ async validateRequestedBlockTxsConsistency(request, response, peerId) {
1638
+ try {
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
+ }
1691
+ return true;
1692
+ } catch (e) {
1693
+ if (e instanceof ValidationError) {
1694
+ this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
1695
+ } else {
1696
+ this.logger.error(`Error during validation of requested block txs`, e);
1697
+ }
501
1698
  return false;
502
1699
  }
503
- return true;
504
1700
  }
505
- async validatePropagatedTx(tx, peerId) {
506
- const blockNumber = await this.l2BlockSource.getBlockNumber() + 1;
507
- const messageValidators = this.createMessageValidators(blockNumber);
508
- const outcome = await this.runValidations(tx, messageValidators);
509
- if (outcome.allPassed) {
510
- return true;
511
- }
512
- const { name } = outcome.failure;
513
- let { severity } = outcome.failure;
514
- // Double spend validator has a special case handler
515
- if (name === 'doubleSpendValidator') {
516
- severity = await this.handleDoubleSpendFailure(tx, blockNumber);
517
- }
518
- this.peerManager.penalizePeer(peerId, severity);
519
- return false;
1701
+ getGasFees() {
1702
+ return this.blockMinFeesProvider.getCurrentMinFees();
520
1703
  }
521
1704
  /**
522
- * Create message validators for the given block number.
523
- *
524
- * Each validator is a pair of a validator and a severity.
525
- * If a validator fails, the peer is penalized with the severity of the validator.
526
- *
527
- * @param blockNumber - The block number to create validators for.
528
- * @returns The message validators.
529
- */ createMessageValidators(blockNumber) {
1705
+ * Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
1706
+ */ getBatchTxRequesterService() {
530
1707
  return {
531
- dataValidator: {
532
- validator: new DataTxValidator(),
533
- severity: PeerErrorSeverity.HighToleranceError
534
- },
535
- metadataValidator: {
536
- validator: new MetadataTxValidator(new Fr(this.config.l1ChainId), new Fr(blockNumber)),
537
- severity: PeerErrorSeverity.HighToleranceError
538
- },
539
- proofValidator: {
540
- validator: new TxProofValidator(this.proofVerifier),
541
- severity: PeerErrorSeverity.MidToleranceError
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
542
1715
  },
543
- doubleSpendValidator: {
544
- validator: new DoubleSpendTxValidator({
545
- nullifiersExist: async (nullifiers)=>{
546
- const merkleTree = this.worldStateSynchronizer.getCommitted();
547
- const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
548
- return indices.map((index)=>index !== undefined);
549
- }
550
- }),
551
- severity: PeerErrorSeverity.HighToleranceError
552
- }
1716
+ peerScoring: this.peerManager,
1717
+ validateRequestedBlockTxsConsistency: this.validateRequestedBlockTxsConsistency.bind(this)
553
1718
  };
554
1719
  }
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');
1731
+ }
1732
+ }
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
+ });
1746
+ }
1747
+ /** Creates the second stage (expensive proof verification) validators for gossiped transactions. */ createSecondStageMessageValidators() {
1748
+ return createSecondStageTxValidationsForGossipedTransactions(this.proofVerifier, this.logger.getBindings());
1749
+ }
555
1750
  /**
556
1751
  * Run validations on a tx.
557
1752
  * @param tx - The tx to validate.
@@ -562,29 +1757,34 @@ import { ReqResp } from '../reqresp/reqresp.js';
562
1757
  const { result } = await validator.validateTx(tx);
563
1758
  return {
564
1759
  name,
565
- isValid: result === 'valid',
1760
+ isValid: result !== 'invalid',
566
1761
  severity
567
1762
  };
568
1763
  });
569
1764
  // A promise that resolves when all validations have been run
570
- const allValidations = Promise.all(validationPromises);
571
- // A promise that resolves when the first validation fails
572
- const firstFailure = Promise.race(validationPromises.map(async (promise)=>{
573
- const result = await promise;
574
- return result.isValid ? new Promise(()=>{}) : result;
575
- }));
576
- // Wait for the first validation to fail or all validations to pass
577
- const result = await Promise.race([
578
- allValidations.then(()=>({
579
- allPassed: true
580
- })),
581
- firstFailure.then((failure)=>({
582
- allPassed: false,
583
- failure: failure
584
- }))
585
- ]);
586
- // If all validations pass, allPassed will be true, if failed, then the failure will be the first validation to fail
587
- return result;
1765
+ const allValidations = await Promise.all(validationPromises);
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));
1770
+ return {
1771
+ allPassed: false,
1772
+ failure: {
1773
+ isValid: {
1774
+ result: 'invalid',
1775
+ reason: [
1776
+ 'Failed validation'
1777
+ ]
1778
+ },
1779
+ name: failed.name,
1780
+ severity: failed.severity
1781
+ }
1782
+ };
1783
+ } else {
1784
+ return {
1785
+ allPassed: true
1786
+ };
1787
+ }
588
1788
  }
589
1789
  /**
590
1790
  * Handle a double spend failure.
@@ -602,53 +1802,30 @@ import { ReqResp } from '../reqresp/reqresp.js';
602
1802
  }
603
1803
  const snapshotValidator = new DoubleSpendTxValidator({
604
1804
  nullifiersExist: async (nullifiers)=>{
605
- const merkleTree = this.worldStateSynchronizer.getSnapshot(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow);
1805
+ const merkleTree = this.worldStateSynchronizer.getSnapshot(BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow));
606
1806
  const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
607
1807
  return indices.map((index)=>index !== undefined);
608
1808
  }
609
- });
1809
+ }, this.logger.getBindings());
610
1810
  const validSnapshot = await snapshotValidator.validateTx(tx);
611
1811
  if (validSnapshot.result !== 'valid') {
612
1812
  return PeerErrorSeverity.LowToleranceError;
613
1813
  }
614
1814
  return PeerErrorSeverity.HighToleranceError;
615
1815
  }
616
- /**
617
- * Validate an attestation.
618
- *
619
- * @param attestation - The attestation to validate.
620
- * @returns True if the attestation is valid, false otherwise.
621
- */ async validateAttestation(peerId, attestation) {
622
- const severity = await this.attestationValidator.validate(attestation);
623
- if (severity) {
624
- this.peerManager.penalizePeer(peerId, severity);
625
- return false;
626
- }
627
- return true;
628
- }
629
- /**
630
- * Validate a block proposal.
631
- *
632
- * @param block - The block proposal to validate.
633
- * @returns True if the block proposal is valid, false otherwise.
634
- */ async validateBlockProposal(peerId, block) {
635
- const severity = await this.blockProposalValidator.validate(block);
636
- if (severity) {
637
- this.peerManager.penalizePeer(peerId, severity);
638
- return false;
639
- }
640
- return true;
641
- }
642
1816
  getPeerScore(peerId) {
643
1817
  return this.node.services.pubsub.score.score(peerId.toString());
644
1818
  }
1819
+ handleAuthRequestFromPeer(authRequest, peerId) {
1820
+ return this.peerManager.handleAuthRequestFromPeer(authRequest, peerId);
1821
+ }
645
1822
  async sendToPeers(message) {
646
1823
  const parent = message.constructor;
647
- const identifier = await message.p2pMessageIdentifier().then((i)=>i.toString());
1824
+ const identifier = await message.p2pMessageLoggingIdentifier().then((i)=>i.toString());
648
1825
  this.logger.trace(`Sending message ${identifier}`, {
649
1826
  p2pMessageIdentifier: identifier
650
1827
  });
651
- const recipientsNum = await this.publishToTopic(parent.p2pTopic, message.toBuffer());
1828
+ const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);
652
1829
  this.logger.debug(`Sent message ${identifier} to ${recipientsNum} peers`, {
653
1830
  p2pMessageIdentifier: identifier,
654
1831
  sourcePeer: this.node.peerId.toString()
@@ -671,42 +1848,3 @@ import { ReqResp } from '../reqresp/reqresp.js';
671
1848
  }
672
1849
  }
673
1850
  }
674
- _ts_decorate([
675
- trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
676
- [Attributes.BLOCK_NUMBER]: block.blockNumber.toNumber(),
677
- [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
678
- [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
679
- [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then((i)=>i.toString())
680
- }))
681
- ], LibP2PService.prototype, "processValidBlockProposal", null);
682
- _ts_decorate([
683
- trackSpan('Libp2pService.broadcastAttestation', async (attestation)=>({
684
- [Attributes.BLOCK_NUMBER]: attestation.payload.header.globalVariables.blockNumber.toNumber(),
685
- [Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
686
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
687
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
688
- }))
689
- ], LibP2PService.prototype, "broadcastAttestation", null);
690
- _ts_decorate([
691
- trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
692
- [Attributes.TX_HASH]: requestedTxHash.toString()
693
- }))
694
- ], LibP2PService.prototype, "validateRequestedTx", null);
695
- _ts_decorate([
696
- trackSpan('Libp2pService.validatePropagatedTx', async (tx)=>({
697
- [Attributes.TX_HASH]: (await tx.getTxHash()).toString()
698
- }))
699
- ], LibP2PService.prototype, "validatePropagatedTx", null);
700
- _ts_decorate([
701
- trackSpan('Libp2pService.validateAttestation', async (_, attestation)=>({
702
- [Attributes.BLOCK_NUMBER]: attestation.payload.header.globalVariables.blockNumber.toNumber(),
703
- [Attributes.SLOT_NUMBER]: attestation.payload.header.globalVariables.slotNumber.toNumber(),
704
- [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
705
- [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
706
- }))
707
- ], LibP2PService.prototype, "validateAttestation", null);
708
- _ts_decorate([
709
- trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
710
- [Attributes.SLOT_NUMBER]: block.payload.header.globalVariables.slotNumber.toString()
711
- }))
712
- ], LibP2PService.prototype, "validateBlockProposal", null);