@aztec/p2p 0.0.0-test.0 → 0.0.1-commit.023c3e5

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 (512) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +4 -3
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +26 -13
  4. package/dest/client/factory.d.ts +15 -5
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +61 -25
  7. package/dest/client/index.d.ts +2 -1
  8. package/dest/client/index.d.ts.map +1 -1
  9. package/dest/client/index.js +1 -0
  10. package/dest/client/interface.d.ts +170 -0
  11. package/dest/client/interface.d.ts.map +1 -0
  12. package/dest/client/interface.js +9 -0
  13. package/dest/client/p2p_client.d.ts +75 -193
  14. package/dest/client/p2p_client.d.ts.map +1 -1
  15. package/dest/client/p2p_client.js +765 -229
  16. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
  17. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
  18. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
  19. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
  20. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
  21. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
  22. package/dest/config.d.ts +154 -125
  23. package/dest/config.d.ts.map +1 -1
  24. package/dest/config.js +182 -34
  25. package/dest/enr/generate-enr.d.ts +11 -3
  26. package/dest/enr/generate-enr.d.ts.map +1 -1
  27. package/dest/enr/generate-enr.js +27 -5
  28. package/dest/enr/index.d.ts +1 -1
  29. package/dest/errors/attestation-pool.error.d.ts +7 -0
  30. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  31. package/dest/errors/attestation-pool.error.js +12 -0
  32. package/dest/errors/reqresp.error.d.ts +1 -1
  33. package/dest/errors/reqresp.error.d.ts.map +1 -1
  34. package/dest/index.d.ts +4 -1
  35. package/dest/index.d.ts.map +1 -1
  36. package/dest/index.js +2 -0
  37. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +104 -25
  38. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  39. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  40. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  41. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +299 -174
  42. package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
  43. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +29 -11
  44. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  45. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +168 -62
  46. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +24 -10
  47. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  48. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +133 -82
  49. package/dest/mem_pools/attestation_pool/mocks.d.ts +234 -11
  50. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  51. package/dest/mem_pools/attestation_pool/mocks.js +19 -21
  52. package/dest/mem_pools/index.d.ts +1 -1
  53. package/dest/mem_pools/instrumentation.d.ts +16 -12
  54. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  55. package/dest/mem_pools/instrumentation.js +56 -41
  56. package/dest/mem_pools/interface.d.ts +3 -4
  57. package/dest/mem_pools/interface.d.ts.map +1 -1
  58. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +75 -16
  59. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  60. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +493 -142
  61. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +32 -0
  62. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -0
  63. package/dest/mem_pools/tx_pool/eviction/eviction_manager.js +112 -0
  64. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +157 -0
  65. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -0
  66. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.js +52 -0
  67. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +16 -0
  68. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -0
  69. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +122 -0
  70. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts +17 -0
  71. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.d.ts.map +1 -0
  72. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.js +84 -0
  73. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +19 -0
  74. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -0
  75. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +78 -0
  76. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts +26 -0
  77. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.d.ts.map +1 -0
  78. package/dest/mem_pools/tx_pool/eviction/low_priority_eviction_rule.js +84 -0
  79. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts +25 -0
  80. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.d.ts.map +1 -0
  81. package/dest/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.js +57 -0
  82. package/dest/mem_pools/tx_pool/index.d.ts +1 -2
  83. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -1
  84. package/dest/mem_pools/tx_pool/index.js +0 -1
  85. package/dest/mem_pools/tx_pool/priority.d.ts +5 -1
  86. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -1
  87. package/dest/mem_pools/tx_pool/priority.js +7 -2
  88. package/dest/mem_pools/tx_pool/tx_pool.d.ts +72 -11
  89. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  90. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  91. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  92. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +276 -45
  93. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +7 -5
  94. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/attestation_validator/attestation_validator.js +79 -10
  96. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  97. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  98. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +76 -0
  99. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  100. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  101. package/dest/msg_validators/attestation_validator/index.js +1 -0
  102. package/dest/msg_validators/clock_tolerance.d.ts +21 -0
  103. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  104. package/dest/msg_validators/clock_tolerance.js +37 -0
  105. package/dest/msg_validators/index.d.ts +2 -2
  106. package/dest/msg_validators/index.d.ts.map +1 -1
  107. package/dest/msg_validators/index.js +1 -1
  108. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +10 -0
  109. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -0
  110. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.js +36 -0
  111. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts +9 -0
  112. package/dest/msg_validators/proposal_validator/block_proposal_validator.d.ts.map +1 -0
  113. package/dest/msg_validators/proposal_validator/block_proposal_validator.js +6 -0
  114. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts +9 -0
  115. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.d.ts.map +1 -0
  116. package/dest/msg_validators/proposal_validator/checkpoint_proposal_validator.js +6 -0
  117. package/dest/msg_validators/proposal_validator/index.d.ts +4 -0
  118. package/dest/msg_validators/proposal_validator/index.d.ts.map +1 -0
  119. package/dest/msg_validators/proposal_validator/index.js +3 -0
  120. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +13 -0
  121. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -0
  122. package/dest/msg_validators/proposal_validator/proposal_validator.js +104 -0
  123. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +23 -0
  124. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -0
  125. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +212 -0
  126. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  127. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  128. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +3 -0
  129. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -0
  130. package/dest/msg_validators/tx_validator/allowed_public_setup.js +27 -0
  131. package/dest/msg_validators/tx_validator/archive_cache.d.ts +14 -0
  132. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -0
  133. package/dest/msg_validators/tx_validator/archive_cache.js +22 -0
  134. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +5 -4
  135. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  136. package/dest/msg_validators/tx_validator/block_header_validator.js +7 -6
  137. package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
  138. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  139. package/dest/msg_validators/tx_validator/data_validator.js +60 -87
  140. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +3 -4
  141. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  142. package/dest/msg_validators/tx_validator/double_spend_validator.js +24 -29
  143. package/dest/msg_validators/tx_validator/factory.d.ts +21 -0
  144. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -0
  145. package/dest/msg_validators/tx_validator/factory.js +84 -0
  146. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts +10 -0
  147. package/dest/msg_validators/tx_validator/fee_payer_balance.d.ts.map +1 -0
  148. package/dest/msg_validators/tx_validator/fee_payer_balance.js +20 -0
  149. package/dest/msg_validators/tx_validator/gas_validator.d.ts +12 -0
  150. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -0
  151. package/dest/msg_validators/tx_validator/gas_validator.js +110 -0
  152. package/dest/msg_validators/tx_validator/index.d.ts +9 -1
  153. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  154. package/dest/msg_validators/tx_validator/index.js +8 -0
  155. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -5
  156. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  157. package/dest/msg_validators/tx_validator/metadata_validator.js +40 -21
  158. package/dest/msg_validators/tx_validator/phases_validator.d.ts +15 -0
  159. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -0
  160. package/dest/msg_validators/tx_validator/phases_validator.js +93 -0
  161. package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
  162. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  163. package/dest/msg_validators/tx_validator/size_validator.js +23 -0
  164. package/dest/msg_validators/tx_validator/test_utils.d.ts +17 -0
  165. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -0
  166. package/dest/msg_validators/tx_validator/test_utils.js +22 -0
  167. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +14 -0
  168. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  169. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  170. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +9 -0
  171. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -0
  172. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +24 -0
  173. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
  174. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  175. package/dest/msg_validators/tx_validator/tx_proof_validator.js +8 -7
  176. package/dest/services/data_store.d.ts +1 -1
  177. package/dest/services/data_store.d.ts.map +1 -1
  178. package/dest/services/data_store.js +10 -6
  179. package/dest/services/discv5/discV5_service.d.ts +10 -9
  180. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  181. package/dest/services/discv5/discV5_service.js +64 -37
  182. package/dest/services/dummy_service.d.ts +66 -11
  183. package/dest/services/dummy_service.d.ts.map +1 -1
  184. package/dest/services/dummy_service.js +130 -5
  185. package/dest/services/encoding.d.ts +26 -7
  186. package/dest/services/encoding.d.ts.map +1 -1
  187. package/dest/services/encoding.js +75 -6
  188. package/dest/services/gossipsub/scoring.d.ts +1 -1
  189. package/dest/services/index.d.ts +5 -1
  190. package/dest/services/index.d.ts.map +1 -1
  191. package/dest/services/index.js +4 -0
  192. package/dest/services/libp2p/instrumentation.d.ts +20 -0
  193. package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
  194. package/dest/services/libp2p/instrumentation.js +122 -0
  195. package/dest/services/libp2p/libp2p_service.d.ts +107 -95
  196. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  197. package/dest/services/libp2p/libp2p_service.js +1328 -313
  198. package/dest/services/peer-manager/interface.d.ts +23 -0
  199. package/dest/services/peer-manager/interface.d.ts.map +1 -0
  200. package/dest/services/peer-manager/interface.js +1 -0
  201. package/dest/services/peer-manager/metrics.d.ts +12 -3
  202. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  203. package/dest/services/peer-manager/metrics.js +44 -12
  204. package/dest/services/peer-manager/peer_manager.d.ts +103 -23
  205. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  206. package/dest/services/peer-manager/peer_manager.js +551 -82
  207. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  208. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  209. package/dest/services/peer-manager/peer_scoring.js +43 -2
  210. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +47 -0
  211. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  212. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +566 -0
  213. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  214. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  215. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  216. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
  217. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  218. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  219. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +37 -0
  220. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  221. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +151 -0
  222. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
  223. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  224. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
  225. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
  226. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  227. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
  228. package/dest/services/reqresp/config.d.ts +11 -9
  229. package/dest/services/reqresp/config.d.ts.map +1 -1
  230. package/dest/services/reqresp/config.js +18 -4
  231. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +23 -4
  232. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  233. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +73 -10
  234. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +32 -17
  235. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  236. package/dest/services/reqresp/connection-sampler/connection_sampler.js +154 -84
  237. package/dest/services/reqresp/constants.d.ts +12 -0
  238. package/dest/services/reqresp/constants.d.ts.map +1 -0
  239. package/dest/services/reqresp/constants.js +7 -0
  240. package/dest/services/reqresp/index.d.ts +3 -2
  241. package/dest/services/reqresp/index.d.ts.map +1 -1
  242. package/dest/services/reqresp/index.js +2 -1
  243. package/dest/services/reqresp/interface.d.ts +75 -24
  244. package/dest/services/reqresp/interface.d.ts.map +1 -1
  245. package/dest/services/reqresp/interface.js +46 -27
  246. package/dest/services/reqresp/metrics.d.ts +6 -5
  247. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  248. package/dest/services/reqresp/metrics.js +17 -21
  249. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  250. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  251. package/dest/services/reqresp/protocols/auth.js +71 -0
  252. package/dest/services/reqresp/protocols/block.d.ts +6 -1
  253. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  254. package/dest/services/reqresp/protocols/block.js +30 -6
  255. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +34 -0
  256. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  257. package/dest/services/reqresp/protocols/block_txs/bitvector.js +87 -0
  258. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
  259. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  260. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +52 -0
  261. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +59 -0
  262. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  263. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +105 -0
  264. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  265. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  266. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  267. package/dest/services/reqresp/protocols/goodbye.d.ts +3 -5
  268. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  269. package/dest/services/reqresp/protocols/goodbye.js +7 -7
  270. package/dest/services/reqresp/protocols/index.d.ts +3 -1
  271. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  272. package/dest/services/reqresp/protocols/index.js +2 -0
  273. package/dest/services/reqresp/protocols/ping.d.ts +1 -3
  274. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
  275. package/dest/services/reqresp/protocols/status.d.ts +40 -7
  276. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  277. package/dest/services/reqresp/protocols/status.js +76 -5
  278. package/dest/services/reqresp/protocols/tx.d.ts +14 -4
  279. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  280. package/dest/services/reqresp/protocols/tx.js +34 -6
  281. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  282. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +6 -4
  283. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  284. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -2
  285. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  286. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  287. package/dest/services/reqresp/rate-limiter/rate_limits.js +21 -1
  288. package/dest/services/reqresp/reqresp.d.ts +29 -66
  289. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  290. package/dest/services/reqresp/reqresp.js +753 -248
  291. package/dest/services/reqresp/status.d.ts +10 -4
  292. package/dest/services/reqresp/status.d.ts.map +1 -1
  293. package/dest/services/reqresp/status.js +9 -2
  294. package/dest/services/service.d.ts +40 -20
  295. package/dest/services/service.d.ts.map +1 -1
  296. package/dest/services/tx_collection/config.d.ts +28 -0
  297. package/dest/services/tx_collection/config.d.ts.map +1 -0
  298. package/dest/services/tx_collection/config.js +66 -0
  299. package/dest/services/tx_collection/fast_tx_collection.d.ts +53 -0
  300. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
  301. package/dest/services/tx_collection/fast_tx_collection.js +311 -0
  302. package/dest/services/tx_collection/index.d.ts +4 -0
  303. package/dest/services/tx_collection/index.d.ts.map +1 -0
  304. package/dest/services/tx_collection/index.js +3 -0
  305. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  306. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  307. package/dest/services/tx_collection/instrumentation.js +31 -0
  308. package/dest/services/tx_collection/proposal_tx_collector.d.ts +48 -0
  309. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
  310. package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
  311. package/dest/services/tx_collection/slow_tx_collection.d.ts +53 -0
  312. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
  313. package/dest/services/tx_collection/slow_tx_collection.js +177 -0
  314. package/dest/services/tx_collection/tx_collection.d.ts +110 -0
  315. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  316. package/dest/services/tx_collection/tx_collection.js +128 -0
  317. package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
  318. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  319. package/dest/services/tx_collection/tx_collection_sink.js +111 -0
  320. package/dest/services/tx_collection/tx_source.d.ts +18 -0
  321. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  322. package/dest/services/tx_collection/tx_source.js +31 -0
  323. package/dest/services/tx_provider.d.ts +51 -0
  324. package/dest/services/tx_provider.d.ts.map +1 -0
  325. package/dest/services/tx_provider.js +219 -0
  326. package/dest/services/tx_provider_instrumentation.d.ts +16 -0
  327. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  328. package/dest/services/tx_provider_instrumentation.js +34 -0
  329. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  330. package/dest/test-helpers/get-ports.d.ts +1 -1
  331. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  332. package/dest/test-helpers/index.d.ts +4 -1
  333. package/dest/test-helpers/index.d.ts.map +1 -1
  334. package/dest/test-helpers/index.js +3 -0
  335. package/dest/test-helpers/make-enrs.d.ts +1 -1
  336. package/dest/test-helpers/make-enrs.d.ts.map +1 -1
  337. package/dest/test-helpers/make-enrs.js +4 -5
  338. package/dest/test-helpers/make-test-p2p-clients.d.ts +33 -5
  339. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  340. package/dest/test-helpers/make-test-p2p-clients.js +86 -16
  341. package/dest/test-helpers/mock-pubsub.d.ts +59 -0
  342. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -0
  343. package/dest/test-helpers/mock-pubsub.js +130 -0
  344. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  345. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  346. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  347. package/dest/test-helpers/reqresp-nodes.d.ts +15 -11
  348. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  349. package/dest/test-helpers/reqresp-nodes.js +62 -28
  350. package/dest/test-helpers/test_tx_provider.d.ts +40 -0
  351. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  352. package/dest/test-helpers/test_tx_provider.js +41 -0
  353. package/dest/test-helpers/testbench-utils.d.ts +158 -0
  354. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  355. package/dest/test-helpers/testbench-utils.js +297 -0
  356. package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
  357. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  358. package/dest/testbench/p2p_client_testbench_worker.js +259 -90
  359. package/dest/testbench/parse_log_file.d.ts +1 -1
  360. package/dest/testbench/parse_log_file.js +4 -4
  361. package/dest/testbench/testbench.d.ts +1 -1
  362. package/dest/testbench/testbench.js +4 -4
  363. package/dest/testbench/worker_client_manager.d.ts +51 -11
  364. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  365. package/dest/testbench/worker_client_manager.js +232 -53
  366. package/dest/types/index.d.ts +4 -2
  367. package/dest/types/index.d.ts.map +1 -1
  368. package/dest/types/index.js +2 -0
  369. package/dest/util.d.ts +24 -16
  370. package/dest/util.d.ts.map +1 -1
  371. package/dest/util.js +75 -69
  372. package/dest/versioning.d.ts +4 -4
  373. package/dest/versioning.d.ts.map +1 -1
  374. package/dest/versioning.js +8 -3
  375. package/package.json +32 -27
  376. package/src/bootstrap/bootstrap.ts +34 -15
  377. package/src/client/factory.ts +135 -53
  378. package/src/client/index.ts +1 -0
  379. package/src/client/interface.ts +213 -0
  380. package/src/client/p2p_client.ts +476 -383
  381. package/src/client/test/tx_proposal_collector/README.md +227 -0
  382. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +336 -0
  383. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
  384. package/src/config.ts +304 -134
  385. package/src/enr/generate-enr.ts +39 -6
  386. package/src/errors/attestation-pool.error.ts +13 -0
  387. package/src/index.ts +4 -0
  388. package/src/mem_pools/attestation_pool/attestation_pool.ts +119 -24
  389. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +352 -201
  390. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +233 -72
  391. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +199 -96
  392. package/src/mem_pools/attestation_pool/mocks.ts +24 -17
  393. package/src/mem_pools/instrumentation.ts +72 -48
  394. package/src/mem_pools/interface.ts +2 -4
  395. package/src/mem_pools/tx_pool/README.md +270 -0
  396. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +580 -143
  397. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +132 -0
  398. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +208 -0
  399. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +162 -0
  400. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_mining_rule.ts +104 -0
  401. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +93 -0
  402. package/src/mem_pools/tx_pool/eviction/low_priority_eviction_rule.ts +106 -0
  403. package/src/mem_pools/tx_pool/eviction/nullifier_conflict_pre_add_rule.ts +75 -0
  404. package/src/mem_pools/tx_pool/index.ts +0 -1
  405. package/src/mem_pools/tx_pool/priority.ts +9 -2
  406. package/src/mem_pools/tx_pool/tx_pool.ts +75 -10
  407. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +225 -36
  408. package/src/msg_validators/attestation_validator/attestation_validator.ts +72 -14
  409. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +94 -0
  410. package/src/msg_validators/attestation_validator/index.ts +1 -0
  411. package/src/msg_validators/clock_tolerance.ts +51 -0
  412. package/src/msg_validators/index.ts +1 -1
  413. package/src/msg_validators/msg_seen_validator/msg_seen_validator.ts +36 -0
  414. package/src/msg_validators/proposal_validator/block_proposal_validator.ts +10 -0
  415. package/src/msg_validators/proposal_validator/checkpoint_proposal_validator.ts +13 -0
  416. package/src/msg_validators/proposal_validator/index.ts +3 -0
  417. package/src/msg_validators/proposal_validator/proposal_validator.ts +92 -0
  418. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +230 -0
  419. package/src/msg_validators/tx_validator/allowed_public_setup.ts +35 -0
  420. package/src/msg_validators/tx_validator/archive_cache.ts +28 -0
  421. package/src/msg_validators/tx_validator/block_header_validator.ts +10 -9
  422. package/src/msg_validators/tx_validator/data_validator.ts +95 -71
  423. package/src/msg_validators/tx_validator/double_spend_validator.ts +23 -20
  424. package/src/msg_validators/tx_validator/factory.ts +151 -0
  425. package/src/msg_validators/tx_validator/fee_payer_balance.ts +40 -0
  426. package/src/msg_validators/tx_validator/gas_validator.ts +123 -0
  427. package/src/msg_validators/tx_validator/index.ts +8 -0
  428. package/src/msg_validators/tx_validator/metadata_validator.ts +72 -24
  429. package/src/msg_validators/tx_validator/phases_validator.ts +118 -0
  430. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  431. package/src/msg_validators/tx_validator/test_utils.ts +43 -0
  432. package/src/msg_validators/tx_validator/timestamp_validator.ts +52 -0
  433. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +22 -0
  434. package/src/msg_validators/tx_validator/tx_proof_validator.ts +14 -8
  435. package/src/services/data_store.ts +10 -7
  436. package/src/services/discv5/discV5_service.ts +85 -39
  437. package/src/services/dummy_service.ts +198 -9
  438. package/src/services/encoding.ts +82 -6
  439. package/src/services/index.ts +4 -0
  440. package/src/services/libp2p/instrumentation.ts +126 -0
  441. package/src/services/libp2p/libp2p_service.ts +1170 -353
  442. package/src/services/peer-manager/interface.ts +29 -0
  443. package/src/services/peer-manager/metrics.ts +55 -12
  444. package/src/services/peer-manager/peer_manager.ts +657 -80
  445. package/src/services/peer-manager/peer_scoring.ts +45 -3
  446. package/src/services/reqresp/batch-tx-requester/README.md +305 -0
  447. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
  448. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  449. package/src/services/reqresp/batch-tx-requester/interface.ts +57 -0
  450. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +209 -0
  451. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
  452. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
  453. package/src/services/reqresp/config.ts +26 -9
  454. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +77 -10
  455. package/src/services/reqresp/connection-sampler/connection_sampler.ts +166 -95
  456. package/src/services/reqresp/constants.ts +14 -0
  457. package/src/services/reqresp/index.ts +2 -0
  458. package/src/services/reqresp/interface.ts +95 -37
  459. package/src/services/reqresp/metrics.ts +40 -28
  460. package/src/services/reqresp/protocols/auth.ts +83 -0
  461. package/src/services/reqresp/protocols/block.ts +26 -4
  462. package/src/services/reqresp/protocols/block_txs/bitvector.ts +106 -0
  463. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +67 -0
  464. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +121 -0
  465. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  466. package/src/services/reqresp/protocols/goodbye.ts +9 -7
  467. package/src/services/reqresp/protocols/index.ts +2 -0
  468. package/src/services/reqresp/protocols/status.ts +121 -5
  469. package/src/services/reqresp/protocols/tx.ts +36 -8
  470. package/src/services/reqresp/rate-limiter/rate_limiter.ts +12 -3
  471. package/src/services/reqresp/rate-limiter/rate_limits.ts +21 -1
  472. package/src/services/reqresp/reqresp.ts +449 -271
  473. package/src/services/reqresp/status.ts +12 -3
  474. package/src/services/service.ts +65 -22
  475. package/src/services/tx_collection/config.ts +98 -0
  476. package/src/services/tx_collection/fast_tx_collection.ts +364 -0
  477. package/src/services/tx_collection/index.ts +7 -0
  478. package/src/services/tx_collection/instrumentation.ts +35 -0
  479. package/src/services/tx_collection/proposal_tx_collector.ts +114 -0
  480. package/src/services/tx_collection/slow_tx_collection.ts +233 -0
  481. package/src/services/tx_collection/tx_collection.ts +216 -0
  482. package/src/services/tx_collection/tx_collection_sink.ts +129 -0
  483. package/src/services/tx_collection/tx_source.ts +37 -0
  484. package/src/services/tx_provider.ts +232 -0
  485. package/src/services/tx_provider_instrumentation.ts +54 -0
  486. package/src/test-helpers/index.ts +3 -0
  487. package/src/test-helpers/make-enrs.ts +4 -5
  488. package/src/test-helpers/make-test-p2p-clients.ts +111 -21
  489. package/src/test-helpers/mock-pubsub.ts +188 -0
  490. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  491. package/src/test-helpers/reqresp-nodes.ts +87 -36
  492. package/src/test-helpers/test_tx_provider.ts +64 -0
  493. package/src/test-helpers/testbench-utils.ts +374 -0
  494. package/src/testbench/p2p_client_testbench_worker.ts +434 -89
  495. package/src/testbench/parse_log_file.ts +4 -4
  496. package/src/testbench/testbench.ts +4 -4
  497. package/src/testbench/worker_client_manager.ts +315 -59
  498. package/src/types/index.ts +2 -0
  499. package/src/util.ts +105 -91
  500. package/src/versioning.ts +11 -4
  501. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +0 -56
  502. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +0 -1
  503. package/dest/mem_pools/tx_pool/memory_tx_pool.js +0 -141
  504. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +0 -8
  505. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +0 -1
  506. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +0 -21
  507. package/dest/msg_validators/block_proposal_validator/index.d.ts +0 -2
  508. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +0 -1
  509. package/dest/msg_validators/block_proposal_validator/index.js +0 -1
  510. package/src/mem_pools/tx_pool/memory_tx_pool.ts +0 -174
  511. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +0 -29
  512. package/src/msg_validators/block_proposal_validator/index.ts +0 -1
@@ -1,17 +1,388 @@
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, _dec6, _dec7, _dec8, _initProto;
374
+ import { BlockNumber } from '@aztec/foundation/branded-types';
375
+ import { randomInt } from '@aztec/foundation/crypto/random';
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 { GasFees } from '@aztec/stdlib/gas';
381
+ import { BlockProposal, CheckpointAttestation, CheckpointProposal, P2PClientType, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicsForClientAndConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
12
382
  import { MerkleTreeId } from '@aztec/stdlib/trees';
13
383
  import { Tx } from '@aztec/stdlib/tx';
14
- import { Attributes, OtelMetricsAdapter, WithTracer, trackSpan } from '@aztec/telemetry-client';
384
+ import { compressComponentVersions } from '@aztec/stdlib/versioning';
385
+ import { Attributes, OtelMetricsAdapter, SpanStatusCode, WithTracer, trackSpan } from '@aztec/telemetry-client';
15
386
  import { gossipsub } from '@chainsafe/libp2p-gossipsub';
16
387
  import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
17
388
  import { SignaturePolicy } from '@chainsafe/libp2p-gossipsub/types';
@@ -20,23 +391,56 @@ import { yamux } from '@chainsafe/libp2p-yamux';
20
391
  import { bootstrap } from '@libp2p/bootstrap';
21
392
  import { identify } from '@libp2p/identify';
22
393
  import { TopicValidatorResult } from '@libp2p/interface';
23
- import '@libp2p/kad-dht';
24
394
  import { mplex } from '@libp2p/mplex';
25
395
  import { tcp } from '@libp2p/tcp';
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 { ProposalSlotCapExceededError } from '../../errors/attestation-pool.error.js';
399
+ import { BlockProposalValidator, CheckpointAttestationValidator, CheckpointProposalValidator, FishermanAttestationValidator } from '../../msg_validators/index.js';
400
+ import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
401
+ import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
402
+ import { createTxMessageValidators, createTxReqRespValidator } from '../../msg_validators/tx_validator/factory.js';
403
+ import { DoubleSpendTxValidator } from '../../msg_validators/tx_validator/index.js';
29
404
  import { GossipSubEvent } from '../../types/index.js';
30
405
  import { convertToMultiaddr } from '../../util.js';
406
+ import { getVersions } from '../../versioning.js';
31
407
  import { AztecDatastore } from '../data_store.js';
408
+ import { DiscV5Service } from '../discv5/discV5_service.js';
32
409
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
33
410
  import { gossipScoreThresholds } from '../gossipsub/scoring.js';
34
411
  import { PeerManager } from '../peer-manager/peer_manager.js';
35
412
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
36
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol } from '../reqresp/interface.js';
413
+ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/interface.js';
414
+ import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
37
415
  import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
38
- import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
416
+ import { pingHandler, reqRespBlockHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/protocols/index.js';
39
417
  import { ReqResp } from '../reqresp/reqresp.js';
418
+ import { P2PInstrumentation } from './instrumentation.js';
419
+ _dec = trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
420
+ [Attributes.SLOT_NUMBER]: block.slotNumber,
421
+ [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
422
+ [Attributes.P2P_ID]: await block.p2pMessageLoggingIdentifier().then((i)=>i.toString())
423
+ })), _dec1 = trackSpan('Libp2pService.processValidCheckpointProposal', async (checkpoint)=>({
424
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber,
425
+ [Attributes.BLOCK_ARCHIVE]: checkpoint.archive.toString(),
426
+ [Attributes.P2P_ID]: await checkpoint.p2pMessageLoggingIdentifier().then((i)=>i.toString())
427
+ })), _dec2 = trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
428
+ [Attributes.BLOCK_ARCHIVE]: request.archiveRoot.toString()
429
+ })), _dec3 = trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
430
+ [Attributes.TX_HASH]: requestedTxHash.toString()
431
+ })), _dec4 = trackSpan('Libp2pService.validateRequestedBlock', (requestedBlockNumber, _responseBlock)=>({
432
+ [Attributes.BLOCK_NUMBER]: requestedBlockNumber.toString()
433
+ })), _dec5 = trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
434
+ [Attributes.TX_HASH]: tx.getTxHash().toString()
435
+ })), _dec6 = trackSpan('Libp2pService.validateCheckpointAttestation', async (_, attestation)=>({
436
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber,
437
+ [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
438
+ [Attributes.P2P_ID]: await attestation.p2pMessageLoggingIdentifier().then((i)=>i.toString())
439
+ })), _dec7 = trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
440
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString()
441
+ })), _dec8 = trackSpan('Libp2pService.validateCheckpointProposal', (_peerId, checkpoint)=>({
442
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString()
443
+ }));
40
444
  /**
41
445
  * Lib P2P implementation of the P2PService interface.
42
446
  */ export class LibP2PService extends WithTracer {
@@ -44,62 +448,170 @@ import { ReqResp } from '../reqresp/reqresp.js';
44
448
  config;
45
449
  node;
46
450
  peerDiscoveryService;
451
+ reqresp;
452
+ peerManager;
47
453
  mempools;
48
- l2BlockSource;
454
+ archiver;
455
+ epochCache;
49
456
  proofVerifier;
50
457
  worldStateSynchronizer;
51
- logger;
52
- jobQueue;
53
- peerManager;
458
+ static{
459
+ ({ e: [_initProto] } = _apply_decs_2203_r(this, [
460
+ [
461
+ _dec,
462
+ 2,
463
+ "processValidBlockProposal"
464
+ ],
465
+ [
466
+ _dec1,
467
+ 2,
468
+ "processValidCheckpointProposal"
469
+ ],
470
+ [
471
+ _dec2,
472
+ 2,
473
+ "validateRequestedBlockTxs"
474
+ ],
475
+ [
476
+ _dec3,
477
+ 2,
478
+ "validateRequestedTxs"
479
+ ],
480
+ [
481
+ _dec4,
482
+ 2,
483
+ "validateRequestedBlock"
484
+ ],
485
+ [
486
+ _dec5,
487
+ 2,
488
+ "validatePropagatedTx"
489
+ ],
490
+ [
491
+ _dec6,
492
+ 2,
493
+ "validateCheckpointAttestation"
494
+ ],
495
+ [
496
+ _dec7,
497
+ 2,
498
+ "validateBlockProposal"
499
+ ],
500
+ [
501
+ _dec8,
502
+ 2,
503
+ "validateCheckpointProposal"
504
+ ]
505
+ ], []));
506
+ }
54
507
  discoveryRunningPromise;
508
+ msgIdSeenValidators;
55
509
  // Message validators
56
- attestationValidator;
57
510
  blockProposalValidator;
58
- // Request and response sub service
59
- reqresp;
511
+ checkpointProposalValidator;
512
+ checkpointAttestationValidator;
513
+ protocolVersion;
514
+ topicStrings;
515
+ feesCache;
60
516
  /**
61
517
  * Callback for when a block is received from a peer.
62
518
  * @param block - The block received from the peer.
63
519
  * @returns The attestation for the block, if any.
64
520
  */ 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);
73
- };
74
- this.node.services.pubsub.score.params.appSpecificWeight = 10;
75
- this.attestationValidator = new AttestationValidator(epochCache);
76
- this.blockProposalValidator = new BlockProposalValidator(epochCache);
521
+ /**
522
+ * Callback for when a checkpoint proposal is received from a peer.
523
+ * @param checkpoint - The checkpoint proposal received from the peer.
524
+ * @returns The attestations for the checkpoint, if any.
525
+ */ checkpointReceivedCallback;
526
+ gossipSubEventHandler;
527
+ instrumentation;
528
+ telemetry;
529
+ logger;
530
+ constructor(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
531
+ super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.msgIdSeenValidators = (_initProto(this), {}), this.protocolVersion = '', this.topicStrings = {};
532
+ this.telemetry = telemetry;
533
+ // Create child logger with fisherman prefix if in fisherman mode
534
+ this.logger = config.fishermanMode ? logger.createChild('[FISHERMAN]') : logger;
535
+ this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
536
+ this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
537
+ this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
538
+ this.msgIdSeenValidators[TopicType.checkpoint_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
539
+ this.msgIdSeenValidators[TopicType.checkpoint_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
540
+ const versions = getVersions(config);
541
+ this.protocolVersion = compressComponentVersions(versions);
542
+ logger.info(`Started libp2p service with protocol version ${this.protocolVersion}`);
543
+ this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
544
+ this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
545
+ this.topicStrings[TopicType.checkpoint_proposal] = createTopicString(TopicType.checkpoint_proposal, this.protocolVersion);
546
+ this.topicStrings[TopicType.checkpoint_attestation] = createTopicString(TopicType.checkpoint_attestation, this.protocolVersion);
547
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, {
548
+ txsPermitted: !config.disableTransactions
549
+ });
550
+ this.checkpointProposalValidator = new CheckpointProposalValidator(epochCache, {
551
+ txsPermitted: !config.disableTransactions
552
+ });
553
+ this.checkpointAttestationValidator = config.fishermanMode ? new FishermanAttestationValidator(epochCache, mempools.attestationPool, telemetry) : new CheckpointAttestationValidator(epochCache);
554
+ this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
77
555
  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()
556
+ this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber} from peer.`, {
557
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier()
80
558
  });
81
- return undefined;
559
+ return false;
560
+ };
561
+ this.checkpointReceivedCallback = (checkpoint)=>{
562
+ this.logger.debug(`Handler not yet registered: Checkpoint received callback not set. Received checkpoint for slot ${checkpoint.slotNumber} from peer.`);
563
+ return Promise.resolve(undefined);
82
564
  };
83
565
  }
566
+ updateConfig(config) {
567
+ this.reqresp.updateConfig(config);
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(clientType, config, peerId, deps) {
575
+ const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = 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 txTopic = createTopicString(TopicType.tx, protocolVersion);
595
+ const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
596
+ const checkpointProposalTopic = createTopicString(TopicType.checkpoint_proposal, protocolVersion);
597
+ const checkpointAttestationTopic = createTopicString(TopicType.checkpoint_attestation, protocolVersion);
598
+ const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
599
+ const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
600
+ const peerId = await enr.peerId();
601
+ const address = enr.getLocationMultiaddr('tcp');
602
+ if (address === undefined) {
603
+ throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
604
+ }
605
+ return {
606
+ id: peerId,
607
+ addrs: [
608
+ address
609
+ ]
610
+ };
611
+ }))).filter((peer)=>peer !== undefined);
612
+ const announceTcpMultiaddr = config.p2pIp ? [
613
+ convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
614
+ ] : [];
103
615
  const node = await createLibp2p({
104
616
  start: false,
105
617
  peerId,
@@ -107,44 +619,76 @@ import { ReqResp } from '../reqresp/reqresp.js';
107
619
  listen: [
108
620
  bindAddrTcp
109
621
  ],
110
- announce: [
111
- announceAddrTcp
112
- ]
622
+ announce: announceTcpMultiaddr
113
623
  },
114
624
  transports: [
115
625
  tcp({
116
- maxConnections: config.maxPeerCount,
626
+ // It's better to have this number a bit higher than our maxPeerCount because it's sets the limit on transport (TCP) layer
627
+ // 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
628
+ // If we hit the limit, the connection will be temporarily accepted and immediately dropped.
629
+ // Docs: https://nodejs.org/api/net.html#servermaxconnections
630
+ maxConnections: maxPeerCount * 2,
117
631
  // socket option: the maximum length of the queue of pending connections
118
- // https://nodejs.org/dist/latest-v18.x/docs/api/net.html#serverlisten
632
+ // https://nodejs.org/dist/latest-v22.x/docs/api/net.html#serverlisten
119
633
  // it's not safe if we increase this number
120
634
  backlog: 5,
121
635
  closeServerOnMaxConnections: {
122
- closeAbove: maxPeerCount ?? Infinity,
123
- listenBelow: maxPeerCount ?? Infinity
636
+ // The property `maxConnections` will protect us against the most DDOS attack
637
+ // This property protects us in case of burst of new connections where server is not able to close them quickly enough
638
+ // In case closeAbove is reached, the server stops listening altogether
639
+ // It's important that there is enough difference between closeAbove and listenAbove,
640
+ // otherwise the server.listener will flap between being closed and open potentially degrading perf even more
641
+ closeAbove: maxPeerCount * 3,
642
+ listenBelow: Math.floor(maxPeerCount * 0.9)
124
643
  }
125
644
  })
126
645
  ],
127
646
  datastore,
128
647
  peerDiscovery,
129
648
  streamMuxers: [
130
- mplex(),
131
- yamux()
649
+ yamux(),
650
+ mplex()
132
651
  ],
133
652
  connectionEncryption: [
134
653
  noise()
135
654
  ],
136
655
  connectionManager: {
137
656
  minConnections: 0,
657
+ // We set maxConnections above maxPeerCount because if we hit limit of maxPeerCount
658
+ // libp2p will start aggressively rejecting all new connections, preventing network discovery and crawling.
659
+ maxConnections: maxPeerCount * 2,
138
660
  maxParallelDials: 100,
139
661
  dialTimeout: 30_000,
140
662
  maxPeerAddrsToDial: 5,
141
663
  maxIncomingPendingConnections: 5
142
664
  },
665
+ connectionGater: {
666
+ denyInboundConnection: (maConn)=>{
667
+ const allowed = peerManager.isNodeAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
668
+ if (allowed) {
669
+ return false;
670
+ }
671
+ logger.debug(`Connection gater: Denying inbound connection from ${maConn.remoteAddr.toString()}`);
672
+ return true;
673
+ },
674
+ denyInboundEncryptedConnection: (peerId, _maConn)=>{
675
+ //NOTE: it is not necessary to check address here because this was already done by
676
+ // denyInboundConnection
677
+ const allowed = peerManager.isNodeAllowedToConnect(peerId);
678
+ if (allowed) {
679
+ return false;
680
+ }
681
+ logger.debug(`Connection gater: Denying inbound encrypted connection from ${peerId.toString()}`);
682
+ return true;
683
+ }
684
+ },
143
685
  services: {
144
686
  identify: identify({
145
- protocolPrefix: 'aztec'
687
+ protocolPrefix: 'aztec',
688
+ runOnConnectionOpen: true
146
689
  }),
147
690
  pubsub: gossipsub({
691
+ directPeers,
148
692
  debugName: 'gossipsub',
149
693
  globalSignaturePolicy: SignaturePolicy.StrictNoSign,
150
694
  allowPublishToZeroTopicPeers: true,
@@ -156,29 +700,35 @@ import { ReqResp } from '../reqresp/reqresp.js';
156
700
  heartbeatInterval: config.gossipsubInterval,
157
701
  mcacheLength: config.gossipsubMcacheLength,
158
702
  mcacheGossip: config.gossipsubMcacheGossip,
703
+ seenTTL: config.gossipsubSeenTTL,
159
704
  msgIdFn: getMsgIdFn,
160
705
  msgIdToStrFn: msgIdToStrFn,
161
706
  fastMsgIdFn: fastMsgIdFn,
162
707
  dataTransform: new SnappyTransform(),
163
708
  metricsRegister: otelMetricsAdapter,
164
- metricsTopicStrToLabel: metricsTopicStrToLabels(),
709
+ metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
165
710
  asyncValidation: true,
166
711
  scoreThresholds: gossipScoreThresholds,
167
712
  scoreParams: createPeerScoreParams({
168
713
  // IPColocation factor can be disabled for local testing - default to -5
169
714
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
170
715
  topics: {
171
- [Tx.p2pTopic]: createTopicScoreParams({
716
+ [txTopic]: createTopicScoreParams({
717
+ topicWeight: 1,
718
+ invalidMessageDeliveriesWeight: -20,
719
+ invalidMessageDeliveriesDecay: 0.5
720
+ }),
721
+ [blockProposalTopic]: createTopicScoreParams({
172
722
  topicWeight: 1,
173
723
  invalidMessageDeliveriesWeight: -20,
174
724
  invalidMessageDeliveriesDecay: 0.5
175
725
  }),
176
- [BlockAttestation.p2pTopic]: createTopicScoreParams({
726
+ [checkpointProposalTopic]: createTopicScoreParams({
177
727
  topicWeight: 1,
178
728
  invalidMessageDeliveriesWeight: -20,
179
729
  invalidMessageDeliveriesDecay: 0.5
180
730
  }),
181
- [BlockProposal.p2pTopic]: createTopicScoreParams({
731
+ [checkpointAttestationTopic]: createTopicScoreParams({
182
732
  topicWeight: 1,
183
733
  invalidMessageDeliveriesWeight: -20,
184
734
  invalidMessageDeliveriesDecay: 0.5
@@ -190,9 +740,15 @@ import { ReqResp } from '../reqresp/reqresp.js';
190
740
  connectionManager: components.connectionManager
191
741
  })
192
742
  },
193
- logger: createLibp2pComponentLogger(logger.module)
743
+ logger: createLibp2pComponentLogger(logger.module, logger.getBindings())
194
744
  });
195
- return new LibP2PService(clientType, config, node, peerDiscoveryService, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
745
+ const peerScoring = new PeerScoring(config, telemetry);
746
+ const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
747
+ const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
748
+ // Update gossipsub score params
749
+ node.services.pubsub.score.params.appSpecificWeight = 10;
750
+ node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
751
+ return new LibP2PService(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
196
752
  }
197
753
  /**
198
754
  * Starts the LibP2P service.
@@ -203,44 +759,56 @@ import { ReqResp } from '../reqresp/reqresp.js';
203
759
  throw new Error('P2P service already started');
204
760
  }
205
761
  // Get listen & announce addresses for logging
206
- const { tcpListenAddress, tcpAnnounceAddress } = this.config;
207
- if (!tcpAnnounceAddress) {
762
+ const { p2pIp, p2pPort } = this.config;
763
+ if (!p2pIp) {
208
764
  throw new Error('Announce address not provided.');
209
765
  }
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);
218
- }
766
+ const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
219
767
  // Create request response protocol handlers
220
768
  const txHandler = reqRespTxHandler(this.mempools);
221
769
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
222
- const blockHandler = reqRespBlockHandler(this.l2BlockSource);
770
+ const blockHandler = reqRespBlockHandler(this.archiver);
771
+ const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
223
772
  const requestResponseHandlers = {
224
773
  [ReqRespSubProtocol.PING]: pingHandler,
225
- [ReqRespSubProtocol.STATUS]: statusHandler,
226
- [ReqRespSubProtocol.TX]: txHandler.bind(this),
774
+ [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
227
775
  [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
228
776
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
229
777
  };
230
- // 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);
234
- this.discoveryRunningPromise.start();
778
+ if (!this.config.disableTransactions) {
779
+ const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
780
+ requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
781
+ }
782
+ if (!this.config.disableTransactions) {
783
+ requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
784
+ }
235
785
  // Define the sub protocol validators - This is done within this start() method to gain a callback to the existing validateTx function
236
786
  const reqrespSubProtocolValidators = {
237
787
  ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
238
- // TODO(#11336): A request validator for blocks
239
- [ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this)
788
+ [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
789
+ [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this),
790
+ [ReqRespSubProtocol.BLOCK]: this.validateRequestedBlock.bind(this)
240
791
  };
792
+ await this.peerManager.initializePeers();
241
793
  await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
794
+ await this.node.start();
795
+ // Subscribe to standard GossipSub topics by default
796
+ for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)){
797
+ this.subscribeToTopic(this.topicStrings[topic]);
798
+ }
799
+ // add GossipSub listener
800
+ this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
801
+ // Start running promise for peer discovery and metrics collection
802
+ if (!this.config.p2pDiscoveryDisabled) {
803
+ await this.peerDiscoveryService.start();
804
+ }
805
+ this.discoveryRunningPromise = new RunningPromise(async ()=>{
806
+ await this.peerManager.heartbeat();
807
+ }, this.logger, this.config.peerCheckIntervalMS);
808
+ this.discoveryRunningPromise.start();
242
809
  this.logger.info(`Started P2P service`, {
243
- listen: tcpListenAddress,
810
+ listen: this.config.listenAddress,
811
+ port: this.config.p2pPort,
244
812
  announce: announceTcpMultiaddr,
245
813
  peerId: this.node.peerId.toString()
246
814
  });
@@ -250,12 +818,10 @@ import { ReqResp } from '../reqresp/reqresp.js';
250
818
  * @returns An empty promise.
251
819
  */ async stop() {
252
820
  // Remove gossip sub listener
253
- this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
821
+ this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
254
822
  // Stop peer manager
255
823
  this.logger.debug('Stopping peer manager...');
256
824
  await this.peerManager.stop();
257
- this.logger.debug('Stopping job queue...');
258
- await this.jobQueue.end();
259
825
  this.logger.debug('Stopping running promise...');
260
826
  await this.discoveryRunningPromise?.stop();
261
827
  this.logger.debug('Stopping peer discovery service...');
@@ -266,6 +832,12 @@ import { ReqResp } from '../reqresp/reqresp.js';
266
832
  await this.stopLibP2P();
267
833
  this.logger.info('LibP2P service stopped');
268
834
  }
835
+ addReqRespSubProtocol(subProtocol, handler, validator) {
836
+ return this.reqresp.addSubProtocol(subProtocol, handler, validator);
837
+ }
838
+ registerThisValidatorAddresses(address) {
839
+ this.peerManager.registerThisValidatorAddresses(address);
840
+ }
269
841
  getPeers(includePending) {
270
842
  return this.peerManager.getPeers(includePending);
271
843
  }
@@ -281,24 +853,15 @@ import { ReqResp } from '../reqresp/reqresp.js';
281
853
  setImmediate(()=>void safeJob());
282
854
  }
283
855
  /**
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
856
  * Send a batch of requests to peers, and return the responses
297
857
  * @param protocol - The request response protocol to use
298
858
  * @param requests - The requests to send to the peers
299
859
  * @returns The responses to the requests
300
- */ sendBatchRequest(protocol, requests) {
301
- return this.reqresp.sendBatchRequest(protocol, requests);
860
+ */ sendBatchRequest(protocol, requests, pinnedPeerId) {
861
+ return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
862
+ }
863
+ sendRequestToPeer(peerId, subProtocol, payload, dialTimeout) {
864
+ return this.reqresp.sendRequestToPeer(peerId, subProtocol, payload, dialTimeout);
302
865
  }
303
866
  /**
304
867
  * Get the ENR of the node
@@ -308,7 +871,9 @@ import { ReqResp } from '../reqresp/reqresp.js';
308
871
  }
309
872
  registerBlockReceivedCallback(callback) {
310
873
  this.blockReceivedCallback = callback;
311
- this.logger.verbose('Block received callback registered');
874
+ }
875
+ registerCheckpointReceivedCallback(callback) {
876
+ this.checkpointReceivedCallback = callback;
312
877
  }
313
878
  /**
314
879
  * Subscribes to a topic.
@@ -322,235 +887,705 @@ import { ReqResp } from '../reqresp/reqresp.js';
322
887
  /**
323
888
  * Publishes data to a topic.
324
889
  * @param topic - The topic to publish to.
325
- * @param data - The data to publish.
890
+ * @param data - The message to publish.
326
891
  * @returns The number of recipients the data was sent to.
327
- */ async publishToTopic(topic, data) {
892
+ */ async publishToTopic(topic, message) {
328
893
  if (!this.node.services.pubsub) {
329
894
  throw new Error('Pubsub service not available.');
330
895
  }
331
- const result = await this.node.services.pubsub.publish(topic, data);
896
+ const isBlockProposal = topic === this.topicStrings[TopicType.block_proposal];
897
+ const traceContext = this.config.debugP2PInstrumentMessages && isBlockProposal ? this.telemetry.getTraceContext() : undefined;
898
+ const p2pMessage = P2PMessage.fromGossipable(message, this.config.debugP2PInstrumentMessages, traceContext);
899
+ const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
332
900
  return result.recipients.length;
333
901
  }
334
902
  /**
903
+ * Checks if this message has already been seen, based on its msgId computed from hashing the message data.
904
+ * Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
905
+ * messages to avoid tx echoes across the network.
906
+ */ preValidateReceivedMessage(msg, msgId, source) {
907
+ let topicType;
908
+ switch(msg.topic){
909
+ case this.topicStrings[TopicType.tx]:
910
+ topicType = TopicType.tx;
911
+ break;
912
+ case this.topicStrings[TopicType.block_proposal]:
913
+ topicType = TopicType.block_proposal;
914
+ break;
915
+ case this.topicStrings[TopicType.checkpoint_proposal]:
916
+ topicType = TopicType.checkpoint_proposal;
917
+ break;
918
+ case this.topicStrings[TopicType.checkpoint_attestation]:
919
+ topicType = TopicType.checkpoint_attestation;
920
+ break;
921
+ default:
922
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
923
+ break;
924
+ }
925
+ const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
926
+ if (!validator || !validator.addMessage(msgId)) {
927
+ this.instrumentation.incMessagePrevalidationStatus(false, topicType);
928
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
929
+ return {
930
+ result: false,
931
+ topicType
932
+ };
933
+ }
934
+ this.instrumentation.incMessagePrevalidationStatus(true, topicType);
935
+ return {
936
+ result: true,
937
+ topicType
938
+ };
939
+ }
940
+ /**
941
+ * Safely deserializes a P2PMessage from raw message data.
942
+ * @param msgId - The message ID.
943
+ * @param source - The peer ID of the message source.
944
+ * @param data - The raw message data.
945
+ * @returns The deserialized P2PMessage or undefined if deserialization fails.
946
+ */ safelyDeserializeP2PMessage(msgId, source, data) {
947
+ try {
948
+ return P2PMessage.fromMessageData(Buffer.from(data), this.config.debugP2PInstrumentMessages);
949
+ } catch (err) {
950
+ this.logger.error(`Error deserializing P2PMessage`, err, {
951
+ msgId,
952
+ source: source.toString()
953
+ });
954
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Reject);
955
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
956
+ return undefined;
957
+ }
958
+ }
959
+ /**
335
960
  * Handles a new gossip message that was received by the client.
336
961
  * @param topic - The message's topic.
337
962
  * @param data - The message data
338
963
  */ async handleNewGossipMessage(msg, msgId, source) {
339
- if (msg.topic === Tx.p2pTopic) {
340
- await this.handleGossipedTx(msg, msgId, source);
964
+ const msgReceivedTime = Date.now();
965
+ let topicType;
966
+ const p2pMessage = this.safelyDeserializeP2PMessage(msgId, source, msg.data);
967
+ if (!p2pMessage) {
968
+ return;
969
+ }
970
+ const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
971
+ if (!preValidationResult.result) {
972
+ return;
973
+ }
974
+ // Determine topic type for attributes
975
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
976
+ topicType = TopicType.tx;
977
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
978
+ topicType = TopicType.checkpoint_attestation;
979
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
980
+ topicType = TopicType.block_proposal;
981
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
982
+ topicType = TopicType.checkpoint_proposal;
341
983
  }
342
- if (msg.topic === BlockAttestation.p2pTopic && this.clientType === P2PClientType.Full) {
343
- await this.processAttestationFromPeer(msg, msgId, source);
984
+ // Process the message, optionally within a linked span for trace propagation
985
+ const processMessage = async ()=>{
986
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
987
+ await this.handleGossipedTx(p2pMessage.payload, msgId, source);
988
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_attestation]) {
989
+ if (this.clientType === P2PClientType.Full) {
990
+ await this.processCheckpointAttestationFromPeer(p2pMessage.payload, msgId, source);
991
+ }
992
+ } else if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
993
+ await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
994
+ } else if (msg.topic === this.topicStrings[TopicType.checkpoint_proposal]) {
995
+ await this.handleGossipedCheckpointProposal(p2pMessage.payload, msgId, source);
996
+ } else {
997
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
998
+ }
999
+ };
1000
+ const latency = p2pMessage.timestamp !== undefined ? msgReceivedTime - p2pMessage.timestamp.getTime() : undefined;
1001
+ const propagatedContext = p2pMessage.traceContext ? this.telemetry.extractPropagatedContext(p2pMessage.traceContext) : undefined;
1002
+ if (propagatedContext) {
1003
+ await this.tracer.startActiveSpan('LibP2PService.processMessage', {
1004
+ attributes: {
1005
+ [Attributes.TOPIC_NAME]: topicType,
1006
+ [Attributes.PEER_ID]: source.toString()
1007
+ }
1008
+ }, propagatedContext, async (span)=>{
1009
+ try {
1010
+ await processMessage();
1011
+ span.setStatus({
1012
+ code: SpanStatusCode.OK
1013
+ });
1014
+ } catch (err) {
1015
+ span.setStatus({
1016
+ code: SpanStatusCode.ERROR,
1017
+ message: String(err)
1018
+ });
1019
+ if (typeof err === 'string' || err && err instanceof Error) {
1020
+ span.recordException(err);
1021
+ }
1022
+ throw err;
1023
+ } finally{
1024
+ span.end();
1025
+ }
1026
+ });
1027
+ } else {
1028
+ await processMessage();
344
1029
  }
345
- if (msg.topic == BlockProposal.p2pTopic) {
346
- await this.processBlockFromPeer(msg, msgId, source);
1030
+ if (latency !== undefined && topicType !== undefined) {
1031
+ this.instrumentation.recordMessageLatency(topicType, latency);
347
1032
  }
348
1033
  return;
349
1034
  }
350
- async validateReceivedMessage(validationFunc, msgId, source) {
1035
+ async validateReceivedMessage(validationFunc, msgId, source, topicType) {
351
1036
  let resultAndObj = {
352
- result: false,
353
- obj: undefined
1037
+ result: TopicValidatorResult.Reject
354
1038
  };
1039
+ const timer = new Timer();
355
1040
  try {
356
1041
  resultAndObj = await validationFunc();
357
1042
  } catch (err) {
358
- this.logger.error(`Error deserialising and validating message `, err);
1043
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.LowToleranceError);
1044
+ this.logger.error(`Error deserializing and validating gossipsub message`, err, {
1045
+ msgId,
1046
+ source: source.toString(),
1047
+ topicType
1048
+ });
1049
+ }
1050
+ if (resultAndObj.result === TopicValidatorResult.Accept) {
1051
+ this.instrumentation.recordMessageValidation(topicType, timer);
359
1052
  }
360
- this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject);
1053
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
361
1054
  return resultAndObj;
362
1055
  }
363
- async handleGossipedTx(msg, msgId, source) {
1056
+ async handleGossipedTx(payloadData, msgId, source) {
364
1057
  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
- };
1058
+ const tx = Tx.fromBuffer(payloadData);
1059
+ const isValid = await this.validatePropagatedTx(tx, source);
1060
+ const exists = isValid && await this.mempools.txPool.hasTx(tx.getTxHash());
1061
+ this.logger.trace(`Validate propagated tx`, {
1062
+ isValid,
1063
+ exists,
1064
+ [Attributes.P2P_ID]: source.toString()
1065
+ });
1066
+ if (!isValid) {
1067
+ return {
1068
+ result: TopicValidatorResult.Reject
1069
+ };
1070
+ } else if (exists) {
1071
+ return {
1072
+ result: TopicValidatorResult.Ignore,
1073
+ obj: tx
1074
+ };
1075
+ } else {
1076
+ return {
1077
+ result: TopicValidatorResult.Accept,
1078
+ obj: tx
1079
+ };
1080
+ }
371
1081
  };
372
- const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source);
373
- if (!result || !tx) {
1082
+ const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.tx);
1083
+ if (result !== TopicValidatorResult.Accept || !tx) {
374
1084
  return;
375
1085
  }
376
- const txHash = await tx.getTxHash();
1086
+ const txHash = tx.getTxHash();
377
1087
  const txHashString = txHash.toString();
378
- this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()}.`);
1088
+ this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
1089
+ source: source.toString(),
1090
+ txHash: txHashString
1091
+ });
1092
+ if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
1093
+ this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
1094
+ return;
1095
+ }
1096
+ this.instrumentation.incrementTxReceived(1);
379
1097
  await this.mempools.txPool.addTxs([
380
1098
  tx
381
1099
  ]);
382
1100
  }
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) {
1101
+ /**
1102
+ * Process a checkpoint attestation from a peer.
1103
+ * Validates the attestation and adds it to the pool.
1104
+ */ async processCheckpointAttestationFromPeer(payloadData, msgId, source) {
388
1105
  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(),
1106
+ const attestation = CheckpointAttestation.fromBuffer(payloadData);
1107
+ const pool = this.mempools.attestationPool;
1108
+ const validationResult = await this.validateCheckpointAttestation(source, attestation);
1109
+ const isValid = validationResult.result === 'accept';
1110
+ const exists = isValid && await pool.hasCheckpointAttestation(attestation);
1111
+ let canAdd = true;
1112
+ if (isValid && !exists) {
1113
+ const slot = attestation.payload.header.slotNumber;
1114
+ const { committee } = await this.epochCache.getCommittee(slot);
1115
+ const committeeSize = committee?.length ?? 0;
1116
+ canAdd = await pool.canAddCheckpointAttestation(attestation, committeeSize);
1117
+ }
1118
+ this.logger.trace(`Validate propagated checkpoint attestation`, {
1119
+ isValid,
1120
+ exists,
1121
+ canAdd,
1122
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
393
1123
  [Attributes.P2P_ID]: source.toString()
394
1124
  });
395
- return {
396
- result,
397
- obj: attestation
398
- };
1125
+ if (validationResult.result === 'reject') {
1126
+ return {
1127
+ result: TopicValidatorResult.Reject
1128
+ };
1129
+ } else if (validationResult.result === 'ignore' || exists) {
1130
+ return {
1131
+ result: TopicValidatorResult.Ignore,
1132
+ obj: attestation
1133
+ };
1134
+ } else if (!canAdd) {
1135
+ this.logger.warn(`Dropping checkpoint attestation due to per-(slot, proposalId) attestation cap`, {
1136
+ slot: attestation.payload.header.slotNumber.toString(),
1137
+ archive: attestation.archive.toString(),
1138
+ source: source.toString()
1139
+ });
1140
+ return {
1141
+ result: TopicValidatorResult.Ignore,
1142
+ obj: attestation
1143
+ };
1144
+ } else {
1145
+ return {
1146
+ result: TopicValidatorResult.Accept,
1147
+ obj: attestation
1148
+ };
1149
+ }
399
1150
  };
400
- const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source);
401
- if (!result || !attestation) {
1151
+ const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.checkpoint_attestation);
1152
+ if (result !== TopicValidatorResult.Accept || !attestation) {
402
1153
  return;
403
1154
  }
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(),
1155
+ this.logger.debug(`Received checkpoint attestation for slot ${attestation.slotNumber} from external peer ${source.toString()}`, {
1156
+ p2pMessageIdentifier: await attestation.p2pMessageLoggingIdentifier(),
1157
+ slot: attestation.slotNumber,
407
1158
  archive: attestation.archive.toString(),
408
- block: attestation.blockNumber.toNumber()
1159
+ source: source.toString()
409
1160
  });
410
- await this.mempools.attestationPool.addAttestations([
1161
+ await this.mempools.attestationPool.addCheckpointAttestations([
411
1162
  attestation
412
1163
  ]);
413
1164
  }
414
- async processBlockFromPeer(msg, msgId, source) {
1165
+ async processBlockFromPeer(payloadData, msgId, source) {
415
1166
  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(),
1167
+ const block = BlockProposal.fromBuffer(payloadData);
1168
+ const validationResult = await this.validateBlockProposal(source, block);
1169
+ const isValid = validationResult.result === 'accept';
1170
+ const pool = this.mempools.attestationPool;
1171
+ const exists = isValid && await pool.hasBlockProposal(block);
1172
+ const canAdd = isValid && await pool.canAddProposal(block);
1173
+ this.logger.trace(`Validate propagated block proposal`, {
1174
+ isValid,
1175
+ exists,
1176
+ canAdd,
1177
+ [Attributes.SLOT_NUMBER]: block.slotNumber.toString(),
420
1178
  [Attributes.P2P_ID]: source.toString()
421
1179
  });
422
- return {
423
- result,
424
- obj: block
425
- };
1180
+ if (validationResult.result === 'reject') {
1181
+ return {
1182
+ result: TopicValidatorResult.Reject
1183
+ };
1184
+ } else if (validationResult.result === 'ignore' || exists) {
1185
+ return {
1186
+ result: TopicValidatorResult.Ignore,
1187
+ obj: block
1188
+ };
1189
+ } else if (!canAdd) {
1190
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
1191
+ this.logger.warn(`Penalizing peer for block proposal exceeding per-slot cap`, {
1192
+ slot: block.slotNumber.toString(),
1193
+ archive: block.archive.toString(),
1194
+ source: source.toString()
1195
+ });
1196
+ return {
1197
+ result: TopicValidatorResult.Reject
1198
+ };
1199
+ } else {
1200
+ return {
1201
+ result: TopicValidatorResult.Accept,
1202
+ obj: block
1203
+ };
1204
+ }
426
1205
  };
427
- const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source);
1206
+ const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_proposal);
428
1207
  if (!result || !block) {
429
1208
  return;
430
1209
  }
431
- await this.processValidBlockProposal(block);
1210
+ await this.processValidBlockProposal(block, source);
432
1211
  }
433
1212
  // 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()
1213
+ // REFACTOR(palla): This method should be moved to the p2p_client or to a separate component,
1214
+ // should not be here as it does not deal with p2p networking.
1215
+ async processValidBlockProposal(block, sender) {
1216
+ const slot = block.slotNumber;
1217
+ this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
1218
+ p2pMessageIdentifier: await block.p2pMessageLoggingIdentifier(),
1219
+ source: sender.toString(),
1220
+ ...block.toBlockInfo()
440
1221
  });
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()
1222
+ // Attempt to add proposal
1223
+ try {
1224
+ await this.mempools.attestationPool.addBlockProposal(block);
1225
+ } catch (err) {
1226
+ // Drop proposals if we hit per-slot cap in the attestation pool; rethrow unknown errors
1227
+ if (err instanceof ProposalSlotCapExceededError) {
1228
+ this.logger.warn(`Dropping block proposal due to per-slot proposal cap`, {
1229
+ slot: String(slot),
1230
+ archive: block.archive.toString(),
1231
+ error: err.message
1232
+ });
1233
+ return;
1234
+ }
1235
+ throw err;
1236
+ }
1237
+ // Mark the txs in this proposal as non-evictable
1238
+ await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
1239
+ // Call the block received callback to validate the proposal.
1240
+ // Note: Validators do NOT attest to individual blocks, only to checkpoint proposals.
1241
+ const isValid = await this.blockReceivedCallback(block, sender);
1242
+ if (!isValid) {
1243
+ this.logger.warn(`Block proposal validation failed for block ${block.blockNumber}`, block.toBlockInfo());
1244
+ }
1245
+ }
1246
+ /**
1247
+ * Handle a gossiped checkpoint proposal.
1248
+ * Validates and processes the checkpoint proposal, then triggers the callback for attestation.
1249
+ */ async handleGossipedCheckpointProposal(payloadData, msgId, source) {
1250
+ // TODO(palla/mbps): This pattern is repeated across multiple message handlers, consider abstracting it.
1251
+ const validationFunc = async ()=>{
1252
+ const checkpoint = CheckpointProposal.fromBuffer(payloadData);
1253
+ const validationResult = await this.validateCheckpointProposal(source, checkpoint);
1254
+ const isValid = validationResult.result === 'accept';
1255
+ const pool = this.mempools.attestationPool;
1256
+ const exists = isValid && await pool.hasCheckpointProposal(checkpoint);
1257
+ const canAdd = isValid && await pool.canAddCheckpointProposal(checkpoint);
1258
+ this.logger.trace(`Validate propagated checkpoint proposal`, {
1259
+ isValid,
1260
+ exists,
1261
+ canAdd,
1262
+ [Attributes.SLOT_NUMBER]: checkpoint.slotNumber.toString(),
1263
+ [Attributes.P2P_ID]: source.toString()
450
1264
  });
451
- await this.broadcastAttestation(attestation);
1265
+ if (validationResult.result === 'reject') {
1266
+ return {
1267
+ result: TopicValidatorResult.Reject
1268
+ };
1269
+ } else if (validationResult.result === 'ignore' || exists) {
1270
+ return {
1271
+ result: TopicValidatorResult.Ignore,
1272
+ obj: checkpoint
1273
+ };
1274
+ } else if (!canAdd) {
1275
+ this.peerManager.penalizePeer(source, PeerErrorSeverity.MidToleranceError);
1276
+ this.logger.warn(`Penalizing peer for checkpoint proposal exceeding per-slot cap`, {
1277
+ slot: checkpoint.slotNumber.toString(),
1278
+ archive: checkpoint.archive.toString(),
1279
+ source: source.toString()
1280
+ });
1281
+ return {
1282
+ result: TopicValidatorResult.Reject
1283
+ };
1284
+ } else {
1285
+ return {
1286
+ result: TopicValidatorResult.Accept,
1287
+ obj: checkpoint
1288
+ };
1289
+ }
1290
+ };
1291
+ const { result, obj: checkpoint } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.checkpoint_proposal);
1292
+ if (result !== TopicValidatorResult.Accept || !checkpoint) {
1293
+ return;
452
1294
  }
1295
+ await this.processValidCheckpointProposal(checkpoint, source);
453
1296
  }
454
1297
  /**
455
- * Broadcast an attestation to all peers.
456
- * @param attestation - The attestation to broadcast.
457
- */ async broadcastAttestation(attestation) {
458
- await this.propagate(attestation);
1298
+ * Process a validated checkpoint proposal.
1299
+ * Extracts and processes the last block proposal (if present) first, then processes the checkpoint.
1300
+ * The block callback is invoked before the checkpoint callback.
1301
+ */ async processValidCheckpointProposal(checkpoint, sender) {
1302
+ const slot = checkpoint.slotNumber;
1303
+ this.logger.verbose(`Received checkpoint proposal for slot ${slot} from external peer ${sender.toString()}.`, {
1304
+ p2pMessageIdentifier: await checkpoint.p2pMessageLoggingIdentifier(),
1305
+ slot: checkpoint.slotNumber,
1306
+ archive: checkpoint.archive.toString(),
1307
+ source: sender.toString()
1308
+ });
1309
+ // Extract block proposal before adding to pool (pool stores them separately)
1310
+ const blockProposal = checkpoint.getBlockProposal();
1311
+ // Add proposal to the pool (this extracts and stores block proposal separately)
1312
+ await this.mempools.attestationPool.addCheckpointProposal(checkpoint);
1313
+ // Mark txs as non-evictable if present (from the last block)
1314
+ if (checkpoint.txHashes.length > 0) {
1315
+ await this.mempools.txPool.markTxsAsNonEvictable(checkpoint.txHashes);
1316
+ }
1317
+ // If there was a last block proposal, invoke the block callback first for validation.
1318
+ // Note: The block proposal is already stored in the pool by addCheckpointProposal.
1319
+ if (blockProposal) {
1320
+ const isValid = await this.blockReceivedCallback(blockProposal, sender);
1321
+ if (!isValid) {
1322
+ this.logger.warn(`Block proposal from checkpoint failed validation`, {
1323
+ slot: slot.toString(),
1324
+ archive: checkpoint.archive.toString(),
1325
+ blockNumber: blockProposal.blockNumber.toString()
1326
+ });
1327
+ return;
1328
+ }
1329
+ }
1330
+ // Call the checkpoint received callback with the core version (without lastBlock)
1331
+ // to validate and potentially generate attestations
1332
+ const attestations = await this.checkpointReceivedCallback(checkpoint.toCore(), sender);
1333
+ if (attestations && attestations.length > 0) {
1334
+ // If the callback returned attestations, add them to the pool and propagate them
1335
+ await this.mempools.attestationPool.addCheckpointAttestations(attestations);
1336
+ for (const attestation of attestations){
1337
+ await this.propagate(attestation);
1338
+ }
1339
+ }
459
1340
  }
460
1341
  /**
461
1342
  * Propagates provided message to peers.
462
1343
  * @param message - The message to propagate.
463
1344
  */ async propagate(message) {
464
- const p2pMessageIdentifier = await message.p2pMessageIdentifier();
1345
+ const p2pMessageIdentifier = await message.p2pMessageLoggingIdentifier();
465
1346
  this.logger.trace(`Message ${p2pMessageIdentifier} queued`, {
466
1347
  p2pMessageIdentifier
467
1348
  });
468
- void this.jobQueue.put(async ()=>{
469
- await this.sendToPeers(message);
470
- }).catch((error)=>{
1349
+ void this.sendToPeers(message).catch((error)=>{
471
1350
  this.logger.error(`Error propagating message ${p2pMessageIdentifier}`, {
472
1351
  error
473
1352
  });
474
1353
  });
475
1354
  }
476
1355
  /**
477
- * Validate a tx that has been requested from a peer.
1356
+ * Validate the requested block transactions. Allow partial returns.
1357
+ * @param request - The block transactions request.
1358
+ * @param response - The block transactions response.
1359
+ * @param peerId - The ID of the peer that made the request.
1360
+ * @returns True if the requested block transactions are valid, false otherwise.
1361
+ */ async validateRequestedBlockTxs(request, response, peerId) {
1362
+ const requestedTxValidator = this.createRequestedTxValidator();
1363
+ try {
1364
+ if (!response.archiveRoot.equals(request.archiveRoot)) {
1365
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1366
+ throw new ValidationError(`Received block txs for unexpected archive root: expected ${request.archiveRoot.toString()}, got ${response.archiveRoot.toString()}`);
1367
+ }
1368
+ if (response.txIndices.getLength() !== request.txIndices.getLength()) {
1369
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1370
+ throw new ValidationError(`Received block txs with mismatched bitvector length: expected ${request.txIndices.getLength()}, got ${response.txIndices.getLength()}`);
1371
+ }
1372
+ // Check no duplicates and not exceeding returnable count
1373
+ const requestedIndices = new Set(request.txIndices.getTrueIndices());
1374
+ const availableIndices = new Set(response.txIndices.getTrueIndices());
1375
+ const maxReturnable = [
1376
+ ...requestedIndices
1377
+ ].filter((i)=>availableIndices.has(i)).length;
1378
+ const returnedHashes = await Promise.all(response.txs.map((tx)=>tx.getTxHash().toString()));
1379
+ const uniqueReturned = new Set(returnedHashes.map((h)=>h.toString()));
1380
+ if (uniqueReturned.size !== returnedHashes.length) {
1381
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1382
+ throw new ValidationError(`Received duplicate txs in block txs response`);
1383
+ }
1384
+ if (response.txs.length > maxReturnable) {
1385
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1386
+ throw new ValidationError(`Received more txs (${response.txs.length}) than requested-and-available (${maxReturnable})`);
1387
+ }
1388
+ // Given proposal (should have locally), ensure returned txs are valid subset and match request indices
1389
+ const proposal = await this.mempools.attestationPool.getBlockProposal(request.archiveRoot.toString());
1390
+ if (proposal) {
1391
+ // Build intersected indices
1392
+ const intersectIdx = request.txIndices.getTrueIndices().filter((i)=>response.txIndices.isSet(i));
1393
+ // Enforce subset membership and preserve increasing order by index.
1394
+ const hashToIndexInProposal = new Map(proposal.txHashes.map((h, i)=>[
1395
+ h.toString(),
1396
+ i
1397
+ ]));
1398
+ const allowedIndexSet = new Set(intersectIdx);
1399
+ const indices = returnedHashes.map((h)=>hashToIndexInProposal.get(h));
1400
+ const allAllowed = indices.every((idx)=>idx !== undefined && allowedIndexSet.has(idx));
1401
+ const strictlyIncreasing = indices.every((idx, i)=>i === 0 ? idx !== undefined : idx > indices[i - 1]);
1402
+ if (!allAllowed || !strictlyIncreasing) {
1403
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1404
+ throw new ValidationError('Returned txs do not match expected subset/order for requested indices');
1405
+ }
1406
+ } else {
1407
+ // No local proposal, cannot check the membership/order of the returned txs
1408
+ this.logger.warn(`Block proposal not found for archive root ${request.archiveRoot.toString()}; cannot validate membership/order of returned txs`);
1409
+ return false;
1410
+ }
1411
+ await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
1412
+ return true;
1413
+ } catch (e) {
1414
+ if (e instanceof ValidationError) {
1415
+ this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
1416
+ } else {
1417
+ this.logger.error(`Error during validation of requested block txs`, e);
1418
+ }
1419
+ return false;
1420
+ }
1421
+ }
1422
+ /**
1423
+ * Validate a collection of txs that has been requested from a peer.
478
1424
  *
479
- * The core component of this validator is that the tx hash MUST match the requested tx hash,
1425
+ * The core component of this validator is that each tx hash MUST match the requested tx hash,
480
1426
  * In order to perform this check, the tx proof must be verified.
481
1427
  *
482
1428
  * Note: This function is called from within `ReqResp.sendRequest` as part of the
483
1429
  * ReqRespSubProtocol.TX subprotocol validation.
484
1430
  *
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.
1431
+ * @param requestedTxHash - The collection of the txs that was requested.
1432
+ * @param responseTx - The collection of txs that was received as a response to the request.
487
1433
  * @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);
1434
+ * @returns True if the whole collection of txs is valid, false otherwise.
1435
+ */ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
1436
+ const requested = new Set(requestedTxHash.map((h)=>h.toString()));
1437
+ const requestedTxValidator = this.createRequestedTxValidator();
1438
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invalid we consider the whole response invalid.
1439
+ // I think we should still extract the valid txs and return them, so that we can still use the response.
1440
+ try {
1441
+ await Promise.all(responseTx.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
1442
+ return true;
1443
+ } catch (e) {
1444
+ if (e instanceof ValidationError) {
1445
+ this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
1446
+ } else {
1447
+ this.logger.error(`Error during validation of requested txs`, e);
1448
+ }
496
1449
  return false;
497
1450
  }
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);
1451
+ }
1452
+ /**
1453
+ * Validates a BLOCK response.
1454
+ *
1455
+ * If a local copy exists, enforces hash equality. If missing, rejects (no penalty) since the hash cannot be verified.
1456
+ * Penalizes on block number mismatch or hash mismatch.
1457
+ *
1458
+ * @param requestedBlockNumber - The requested block number.
1459
+ * @param responseBlock - The block returned by the peer.
1460
+ * @param peerId - The peer that returned the block.
1461
+ * @returns True if the response is valid, false otherwise.
1462
+ */ async validateRequestedBlock(requestedBlockNumber, responseBlock, peerId) {
1463
+ try {
1464
+ const reqNum = Number(requestedBlockNumber.toString());
1465
+ if (responseBlock.number !== reqNum) {
1466
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
1467
+ return false;
1468
+ }
1469
+ const local = await this.archiver.getBlock(BlockNumber(reqNum));
1470
+ if (!local) {
1471
+ // We are missing the local block; we cannot verify the hash yet. Reject without penalizing.
1472
+ // TODO: Consider extending this validator to accept an expected hash or
1473
+ // performing quorum-based checks when using P2P syncing prior to L1 sync.
1474
+ this.logger.warn(`Local block ${reqNum} not found; rejecting BLOCK response without hash verification`);
1475
+ return false;
1476
+ }
1477
+ const [localHash, respHash] = await Promise.all([
1478
+ local.hash(),
1479
+ responseBlock.hash()
1480
+ ]);
1481
+ if (!localHash.equals(respHash)) {
1482
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
1483
+ return false;
1484
+ }
1485
+ return true;
1486
+ } catch (e) {
1487
+ this.logger.warn(`Error validating requested block`, e);
501
1488
  return false;
502
1489
  }
503
- return true;
1490
+ }
1491
+ async validateRequestedTx(tx, peerId, txValidator, requested) {
1492
+ const penalize = (severity)=>this.peerManager.penalizePeer(peerId, severity);
1493
+ if (requested && !requested.has(tx.getTxHash().toString())) {
1494
+ penalize(PeerErrorSeverity.MidToleranceError);
1495
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
1496
+ }
1497
+ const { result } = await txValidator.validateTx(tx);
1498
+ if (result === 'invalid') {
1499
+ penalize(PeerErrorSeverity.LowToleranceError);
1500
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
1501
+ }
1502
+ }
1503
+ createRequestedTxValidator() {
1504
+ return createTxReqRespValidator(this.proofVerifier, {
1505
+ l1ChainId: this.config.l1ChainId,
1506
+ rollupVersion: this.config.rollupVersion
1507
+ });
504
1508
  }
505
1509
  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;
1510
+ const currentBlockNumber = await this.archiver.getBlockNumber();
1511
+ // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1512
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1513
+ const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1514
+ for (const validator of messageValidators){
1515
+ const outcome = await this.runValidations(tx, validator);
1516
+ if (outcome.allPassed) {
1517
+ continue;
1518
+ }
1519
+ const { name } = outcome.failure;
1520
+ let { severity } = outcome.failure;
1521
+ // Double spend validator has a special case handler
1522
+ if (name === 'doubleSpendValidator') {
1523
+ const txBlockNumber = BlockNumber(currentBlockNumber + 1); // tx is expected to be in the next block
1524
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
1525
+ }
1526
+ this.peerManager.penalizePeer(peerId, severity);
1527
+ return false;
511
1528
  }
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);
1529
+ return true;
1530
+ }
1531
+ async getGasFees(blockNumber) {
1532
+ if (blockNumber === this.feesCache?.blockNumber) {
1533
+ return this.feesCache.gasFees;
517
1534
  }
518
- this.peerManager.penalizePeer(peerId, severity);
519
- return false;
1535
+ const header = await this.archiver.getBlockHeader(blockNumber);
1536
+ const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
1537
+ this.feesCache = {
1538
+ blockNumber,
1539
+ gasFees
1540
+ };
1541
+ return gasFees;
1542
+ }
1543
+ /**
1544
+ * Get the BatchTxRequesterLibP2PService dependencies for creating BatchTxRequester instances
1545
+ */ getBatchTxRequesterService() {
1546
+ return {
1547
+ reqResp: this.reqresp,
1548
+ connectionSampler: this.reqresp.getConnectionSampler(),
1549
+ txValidatorConfig: {
1550
+ l1ChainId: this.config.l1ChainId,
1551
+ rollupVersion: this.config.rollupVersion,
1552
+ proofVerifier: this.proofVerifier
1553
+ },
1554
+ peerScoring: this.peerManager
1555
+ };
1556
+ }
1557
+ async validate(txs) {
1558
+ const currentBlockNumber = await this.archiver.getBlockNumber();
1559
+ // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
1560
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
1561
+ const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
1562
+ await Promise.all(txs.map(async (tx)=>{
1563
+ for (const validator of messageValidators){
1564
+ const outcome = await this.runValidations(tx, validator);
1565
+ if (!outcome.allPassed) {
1566
+ throw new Error('Invalid tx detected', {
1567
+ cause: {
1568
+ outcome
1569
+ }
1570
+ });
1571
+ }
1572
+ }
1573
+ }));
520
1574
  }
521
1575
  /**
522
- * Create message validators for the given block number.
1576
+ * Create message validators for the given block number and timestamp.
523
1577
  *
524
1578
  * Each validator is a pair of a validator and a severity.
525
1579
  * If a validator fails, the peer is penalized with the severity of the validator.
526
1580
  *
527
- * @param blockNumber - The block number to create validators for.
1581
+ * @param currentBlockNumber - The current synced block number.
1582
+ * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
528
1583
  * @returns The message validators.
529
- */ createMessageValidators(blockNumber) {
530
- 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
542
- },
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
- }
553
- };
1584
+ */ async createMessageValidators(currentBlockNumber, nextSlotTimestamp) {
1585
+ const gasFees = await this.getGasFees(currentBlockNumber);
1586
+ const allowedInSetup = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
1587
+ const blockNumberInWhichTheTxIsConsideredToBeIncluded = BlockNumber(currentBlockNumber + 1);
1588
+ return createTxMessageValidators(nextSlotTimestamp, blockNumberInWhichTheTxIsConsideredToBeIncluded, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, this.proofVerifier, !this.config.disableTransactions, allowedInSetup, this.logger.getBindings());
554
1589
  }
555
1590
  /**
556
1591
  * Run validations on a tx.
@@ -562,29 +1597,32 @@ import { ReqResp } from '../reqresp/reqresp.js';
562
1597
  const { result } = await validator.validateTx(tx);
563
1598
  return {
564
1599
  name,
565
- isValid: result === 'valid',
1600
+ isValid: result !== 'invalid',
566
1601
  severity
567
1602
  };
568
1603
  });
569
1604
  // 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;
1605
+ const allValidations = await Promise.all(validationPromises);
1606
+ const failed = allValidations.find((x)=>!x.isValid);
1607
+ if (failed) {
1608
+ return {
1609
+ allPassed: false,
1610
+ failure: {
1611
+ isValid: {
1612
+ result: 'invalid',
1613
+ reason: [
1614
+ 'Failed validation'
1615
+ ]
1616
+ },
1617
+ name: failed.name,
1618
+ severity: failed.severity
1619
+ }
1620
+ };
1621
+ } else {
1622
+ return {
1623
+ allPassed: true
1624
+ };
1625
+ }
588
1626
  }
589
1627
  /**
590
1628
  * Handle a double spend failure.
@@ -602,11 +1640,11 @@ import { ReqResp } from '../reqresp/reqresp.js';
602
1640
  }
603
1641
  const snapshotValidator = new DoubleSpendTxValidator({
604
1642
  nullifiersExist: async (nullifiers)=>{
605
- const merkleTree = this.worldStateSynchronizer.getSnapshot(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow);
1643
+ const merkleTree = this.worldStateSynchronizer.getSnapshot(BlockNumber(blockNumber - this.config.doubleSpendSeverePeerPenaltyWindow));
606
1644
  const indices = await merkleTree.findLeafIndices(MerkleTreeId.NULLIFIER_TREE, nullifiers);
607
1645
  return indices.map((index)=>index !== undefined);
608
1646
  }
609
- });
1647
+ }, this.logger.getBindings());
610
1648
  const validSnapshot = await snapshotValidator.validateTx(tx);
611
1649
  if (validSnapshot.result !== 'valid') {
612
1650
  return PeerErrorSeverity.LowToleranceError;
@@ -614,17 +1652,17 @@ import { ReqResp } from '../reqresp/reqresp.js';
614
1652
  return PeerErrorSeverity.HighToleranceError;
615
1653
  }
616
1654
  /**
617
- * Validate an attestation.
1655
+ * Validate a checkpoint attestation.
618
1656
  *
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;
1657
+ * @param attestation - The checkpoint attestation to validate.
1658
+ * @returns True if the checkpoint attestation is valid, false otherwise.
1659
+ */ async validateCheckpointAttestation(peerId, attestation) {
1660
+ const result = await this.checkpointAttestationValidator.validate(attestation);
1661
+ if (result.result === 'reject') {
1662
+ this.logger.debug(`Penalizing peer ${peerId} for checkpoint attestation validation failure`);
1663
+ this.peerManager.penalizePeer(peerId, result.severity);
626
1664
  }
627
- return true;
1665
+ return result;
628
1666
  }
629
1667
  /**
630
1668
  * Validate a block proposal.
@@ -632,23 +1670,39 @@ import { ReqResp } from '../reqresp/reqresp.js';
632
1670
  * @param block - The block proposal to validate.
633
1671
  * @returns True if the block proposal is valid, false otherwise.
634
1672
  */ async validateBlockProposal(peerId, block) {
635
- const severity = await this.blockProposalValidator.validate(block);
636
- if (severity) {
637
- this.peerManager.penalizePeer(peerId, severity);
638
- return false;
1673
+ const result = await this.blockProposalValidator.validate(block);
1674
+ if (result.result === 'reject') {
1675
+ this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
1676
+ this.peerManager.penalizePeer(peerId, result.severity);
639
1677
  }
640
- return true;
1678
+ return result;
1679
+ }
1680
+ /**
1681
+ * Validate a checkpoint proposal.
1682
+ *
1683
+ * @param checkpoint - The checkpoint proposal to validate.
1684
+ * @returns True if the checkpoint proposal is valid, false otherwise.
1685
+ */ async validateCheckpointProposal(peerId, checkpoint) {
1686
+ const result = await this.checkpointProposalValidator.validate(checkpoint);
1687
+ if (result.result === 'reject') {
1688
+ this.logger.debug(`Penalizing peer ${peerId} for checkpoint proposal validation failure`);
1689
+ this.peerManager.penalizePeer(peerId, result.severity);
1690
+ }
1691
+ return result;
641
1692
  }
642
1693
  getPeerScore(peerId) {
643
1694
  return this.node.services.pubsub.score.score(peerId.toString());
644
1695
  }
1696
+ handleAuthRequestFromPeer(authRequest, peerId) {
1697
+ return this.peerManager.handleAuthRequestFromPeer(authRequest, peerId);
1698
+ }
645
1699
  async sendToPeers(message) {
646
1700
  const parent = message.constructor;
647
- const identifier = await message.p2pMessageIdentifier().then((i)=>i.toString());
1701
+ const identifier = await message.p2pMessageLoggingIdentifier().then((i)=>i.toString());
648
1702
  this.logger.trace(`Sending message ${identifier}`, {
649
1703
  p2pMessageIdentifier: identifier
650
1704
  });
651
- const recipientsNum = await this.publishToTopic(parent.p2pTopic, message.toBuffer());
1705
+ const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);
652
1706
  this.logger.debug(`Sent message ${identifier} to ${recipientsNum} peers`, {
653
1707
  p2pMessageIdentifier: identifier,
654
1708
  sourcePeer: this.node.peerId.toString()
@@ -671,42 +1725,3 @@ import { ReqResp } from '../reqresp/reqresp.js';
671
1725
  }
672
1726
  }
673
1727
  }
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);