@aztec/p2p 0.0.0-test.0 → 0.0.1-commit.24de95ac

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 (339) hide show
  1. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  2. package/dest/bootstrap/bootstrap.js +22 -9
  3. package/dest/client/factory.d.ts +13 -3
  4. package/dest/client/factory.d.ts.map +1 -1
  5. package/dest/client/factory.js +60 -24
  6. package/dest/client/index.d.ts +1 -0
  7. package/dest/client/index.d.ts.map +1 -1
  8. package/dest/client/index.js +1 -0
  9. package/dest/client/interface.d.ts +155 -0
  10. package/dest/client/interface.d.ts.map +1 -0
  11. package/dest/client/interface.js +9 -0
  12. package/dest/client/p2p_client.d.ts +72 -169
  13. package/dest/client/p2p_client.d.ts.map +1 -1
  14. package/dest/client/p2p_client.js +365 -174
  15. package/dest/config.d.ts +123 -103
  16. package/dest/config.d.ts.map +1 -1
  17. package/dest/config.js +173 -34
  18. package/dest/enr/generate-enr.d.ts +10 -2
  19. package/dest/enr/generate-enr.d.ts.map +1 -1
  20. package/dest/enr/generate-enr.js +27 -5
  21. package/dest/index.d.ts +3 -0
  22. package/dest/index.d.ts.map +1 -1
  23. package/dest/index.js +2 -0
  24. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +42 -4
  25. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  26. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +204 -54
  28. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +10 -2
  29. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  30. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +93 -15
  31. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +10 -2
  32. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  33. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +86 -18
  34. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
  35. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  36. package/dest/mem_pools/attestation_pool/mocks.js +9 -15
  37. package/dest/mem_pools/instrumentation.d.ts +7 -11
  38. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  39. package/dest/mem_pools/instrumentation.js +25 -37
  40. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +93 -9
  41. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  42. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +469 -97
  43. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +33 -9
  44. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  45. package/dest/mem_pools/tx_pool/memory_tx_pool.js +133 -36
  46. package/dest/mem_pools/tx_pool/priority.js +1 -1
  47. package/dest/mem_pools/tx_pool/tx_pool.d.ts +64 -8
  48. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  49. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  50. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +264 -39
  51. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +1 -0
  52. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  53. package/dest/msg_validators/attestation_validator/attestation_validator.js +45 -9
  54. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +5 -1
  55. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
  56. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +61 -12
  57. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +10 -0
  58. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -0
  59. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.js +36 -0
  60. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +3 -0
  61. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -0
  62. package/dest/msg_validators/tx_validator/allowed_public_setup.js +27 -0
  63. package/dest/msg_validators/tx_validator/archive_cache.d.ts +14 -0
  64. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -0
  65. package/dest/msg_validators/tx_validator/archive_cache.js +22 -0
  66. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  67. package/dest/msg_validators/tx_validator/block_header_validator.js +4 -4
  68. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  69. package/dest/msg_validators/tx_validator/data_validator.js +56 -86
  70. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +0 -2
  71. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  72. package/dest/msg_validators/tx_validator/double_spend_validator.js +21 -27
  73. package/dest/msg_validators/tx_validator/factory.d.ts +15 -0
  74. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -0
  75. package/dest/msg_validators/tx_validator/factory.js +74 -0
  76. package/dest/msg_validators/tx_validator/gas_validator.d.ts +11 -0
  77. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -0
  78. package/dest/msg_validators/tx_validator/gas_validator.js +115 -0
  79. package/dest/msg_validators/tx_validator/index.d.ts +7 -0
  80. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  81. package/dest/msg_validators/tx_validator/index.js +7 -0
  82. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +7 -3
  83. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  84. package/dest/msg_validators/tx_validator/metadata_validator.js +39 -20
  85. package/dest/msg_validators/tx_validator/phases_validator.d.ts +14 -0
  86. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -0
  87. package/dest/msg_validators/tx_validator/phases_validator.js +91 -0
  88. package/dest/msg_validators/tx_validator/test_utils.d.ts +17 -0
  89. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -0
  90. package/dest/msg_validators/tx_validator/test_utils.js +22 -0
  91. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +12 -0
  92. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  93. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  94. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +8 -0
  95. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -0
  96. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +24 -0
  97. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/tx_proof_validator.js +6 -5
  99. package/dest/services/discv5/discV5_service.d.ts +9 -8
  100. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  101. package/dest/services/discv5/discV5_service.js +63 -36
  102. package/dest/services/dummy_service.d.ts +49 -10
  103. package/dest/services/dummy_service.d.ts.map +1 -1
  104. package/dest/services/dummy_service.js +88 -5
  105. package/dest/services/encoding.d.ts +25 -6
  106. package/dest/services/encoding.d.ts.map +1 -1
  107. package/dest/services/encoding.js +73 -5
  108. package/dest/services/index.d.ts +4 -0
  109. package/dest/services/index.d.ts.map +1 -1
  110. package/dest/services/index.js +4 -0
  111. package/dest/services/libp2p/instrumentation.d.ts +18 -0
  112. package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
  113. package/dest/services/libp2p/instrumentation.js +157 -0
  114. package/dest/services/libp2p/libp2p_service.d.ts +87 -42
  115. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  116. package/dest/services/libp2p/libp2p_service.js +500 -218
  117. package/dest/services/peer-manager/interface.d.ts +23 -0
  118. package/dest/services/peer-manager/interface.d.ts.map +1 -0
  119. package/dest/services/peer-manager/interface.js +1 -0
  120. package/dest/services/peer-manager/metrics.d.ts +3 -1
  121. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  122. package/dest/services/peer-manager/metrics.js +11 -2
  123. package/dest/services/peer-manager/peer_manager.d.ts +126 -15
  124. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  125. package/dest/services/peer-manager/peer_manager.js +547 -72
  126. package/dest/services/reqresp/config.d.ts +10 -8
  127. package/dest/services/reqresp/config.d.ts.map +1 -1
  128. package/dest/services/reqresp/config.js +18 -4
  129. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +1 -1
  130. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  131. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +10 -6
  132. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +30 -13
  133. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  134. package/dest/services/reqresp/connection-sampler/connection_sampler.js +142 -84
  135. package/dest/services/reqresp/index.d.ts +2 -1
  136. package/dest/services/reqresp/index.d.ts.map +1 -1
  137. package/dest/services/reqresp/index.js +2 -1
  138. package/dest/services/reqresp/interface.d.ts +72 -23
  139. package/dest/services/reqresp/interface.d.ts.map +1 -1
  140. package/dest/services/reqresp/interface.js +45 -26
  141. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  142. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  143. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  144. package/dest/services/reqresp/protocols/auth.js +71 -0
  145. package/dest/services/reqresp/protocols/block.d.ts +5 -0
  146. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  147. package/dest/services/reqresp/protocols/block.js +28 -5
  148. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
  149. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  150. package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
  151. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
  152. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  153. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
  154. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -0
  155. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  156. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
  157. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  158. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  159. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  160. package/dest/services/reqresp/protocols/goodbye.d.ts +2 -4
  161. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  162. package/dest/services/reqresp/protocols/goodbye.js +7 -7
  163. package/dest/services/reqresp/protocols/index.d.ts +2 -0
  164. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  165. package/dest/services/reqresp/protocols/index.js +2 -0
  166. package/dest/services/reqresp/protocols/ping.d.ts +0 -2
  167. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
  168. package/dest/services/reqresp/protocols/status.d.ts +38 -6
  169. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  170. package/dest/services/reqresp/protocols/status.js +72 -5
  171. package/dest/services/reqresp/protocols/tx.d.ts +12 -1
  172. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  173. package/dest/services/reqresp/protocols/tx.js +34 -6
  174. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +4 -2
  175. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  176. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -2
  177. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  178. package/dest/services/reqresp/rate-limiter/rate_limits.js +21 -1
  179. package/dest/services/reqresp/reqresp.d.ts +45 -47
  180. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  181. package/dest/services/reqresp/reqresp.js +298 -207
  182. package/dest/services/reqresp/status.d.ts +9 -3
  183. package/dest/services/reqresp/status.d.ts.map +1 -1
  184. package/dest/services/reqresp/status.js +9 -2
  185. package/dest/services/service.d.ts +22 -18
  186. package/dest/services/service.d.ts.map +1 -1
  187. package/dest/services/tx_collection/config.d.ts +25 -0
  188. package/dest/services/tx_collection/config.d.ts.map +1 -0
  189. package/dest/services/tx_collection/config.js +58 -0
  190. package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
  191. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
  192. package/dest/services/tx_collection/fast_tx_collection.js +300 -0
  193. package/dest/services/tx_collection/index.d.ts +3 -0
  194. package/dest/services/tx_collection/index.d.ts.map +1 -0
  195. package/dest/services/tx_collection/index.js +2 -0
  196. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  197. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  198. package/dest/services/tx_collection/instrumentation.js +34 -0
  199. package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
  200. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
  201. package/dest/services/tx_collection/slow_tx_collection.js +176 -0
  202. package/dest/services/tx_collection/tx_collection.d.ts +110 -0
  203. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  204. package/dest/services/tx_collection/tx_collection.js +128 -0
  205. package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
  206. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  207. package/dest/services/tx_collection/tx_collection_sink.js +111 -0
  208. package/dest/services/tx_collection/tx_source.d.ts +18 -0
  209. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  210. package/dest/services/tx_collection/tx_source.js +31 -0
  211. package/dest/services/tx_provider.d.ts +49 -0
  212. package/dest/services/tx_provider.d.ts.map +1 -0
  213. package/dest/services/tx_provider.js +210 -0
  214. package/dest/services/tx_provider_instrumentation.d.ts +13 -0
  215. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  216. package/dest/services/tx_provider_instrumentation.js +34 -0
  217. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  218. package/dest/test-helpers/index.d.ts +1 -0
  219. package/dest/test-helpers/index.d.ts.map +1 -1
  220. package/dest/test-helpers/index.js +1 -0
  221. package/dest/test-helpers/make-enrs.d.ts.map +1 -1
  222. package/dest/test-helpers/make-enrs.js +4 -5
  223. package/dest/test-helpers/make-test-p2p-clients.d.ts +32 -4
  224. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  225. package/dest/test-helpers/make-test-p2p-clients.js +86 -16
  226. package/dest/test-helpers/mock-pubsub.d.ts +59 -0
  227. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -0
  228. package/dest/test-helpers/mock-pubsub.js +130 -0
  229. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  230. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  231. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  232. package/dest/test-helpers/reqresp-nodes.d.ts +14 -10
  233. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  234. package/dest/test-helpers/reqresp-nodes.js +62 -28
  235. package/dest/testbench/p2p_client_testbench_worker.js +96 -25
  236. package/dest/testbench/parse_log_file.js +4 -4
  237. package/dest/testbench/testbench.js +4 -4
  238. package/dest/testbench/worker_client_manager.d.ts +0 -5
  239. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  240. package/dest/testbench/worker_client_manager.js +11 -19
  241. package/dest/types/index.d.ts +3 -1
  242. package/dest/types/index.d.ts.map +1 -1
  243. package/dest/types/index.js +2 -0
  244. package/dest/util.d.ts +22 -15
  245. package/dest/util.d.ts.map +1 -1
  246. package/dest/util.js +64 -67
  247. package/dest/versioning.d.ts +3 -3
  248. package/dest/versioning.d.ts.map +1 -1
  249. package/dest/versioning.js +8 -3
  250. package/package.json +28 -24
  251. package/src/bootstrap/bootstrap.ts +27 -11
  252. package/src/client/factory.ts +136 -45
  253. package/src/client/index.ts +1 -0
  254. package/src/client/interface.ts +195 -0
  255. package/src/client/p2p_client.ts +460 -327
  256. package/src/config.ts +288 -134
  257. package/src/enr/generate-enr.ts +39 -6
  258. package/src/index.ts +4 -0
  259. package/src/mem_pools/attestation_pool/attestation_pool.ts +48 -4
  260. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +241 -55
  261. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +117 -20
  262. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +114 -22
  263. package/src/mem_pools/attestation_pool/mocks.ts +11 -10
  264. package/src/mem_pools/instrumentation.ts +32 -46
  265. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +549 -108
  266. package/src/mem_pools/tx_pool/memory_tx_pool.ts +153 -44
  267. package/src/mem_pools/tx_pool/priority.ts +1 -1
  268. package/src/mem_pools/tx_pool/tx_pool.ts +67 -8
  269. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +217 -34
  270. package/src/msg_validators/attestation_validator/attestation_validator.ts +55 -10
  271. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +66 -14
  272. package/src/msg_validators/msg_seen_validator/msg_seen_validator.ts +36 -0
  273. package/src/msg_validators/tx_validator/allowed_public_setup.ts +35 -0
  274. package/src/msg_validators/tx_validator/archive_cache.ts +28 -0
  275. package/src/msg_validators/tx_validator/block_header_validator.ts +4 -4
  276. package/src/msg_validators/tx_validator/data_validator.ts +81 -69
  277. package/src/msg_validators/tx_validator/double_spend_validator.ts +19 -17
  278. package/src/msg_validators/tx_validator/factory.ts +109 -0
  279. package/src/msg_validators/tx_validator/gas_validator.ts +134 -0
  280. package/src/msg_validators/tx_validator/index.ts +7 -0
  281. package/src/msg_validators/tx_validator/metadata_validator.ts +58 -21
  282. package/src/msg_validators/tx_validator/phases_validator.ts +114 -0
  283. package/src/msg_validators/tx_validator/test_utils.ts +43 -0
  284. package/src/msg_validators/tx_validator/timestamp_validator.ts +46 -0
  285. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +17 -0
  286. package/src/msg_validators/tx_validator/tx_proof_validator.ts +6 -5
  287. package/src/services/discv5/discV5_service.ts +84 -38
  288. package/src/services/dummy_service.ts +147 -9
  289. package/src/services/encoding.ts +80 -5
  290. package/src/services/index.ts +4 -0
  291. package/src/services/libp2p/instrumentation.ts +158 -0
  292. package/src/services/libp2p/libp2p_service.ts +646 -263
  293. package/src/services/peer-manager/interface.ts +29 -0
  294. package/src/services/peer-manager/metrics.ts +16 -1
  295. package/src/services/peer-manager/peer_manager.ts +652 -78
  296. package/src/services/reqresp/config.ts +26 -9
  297. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +12 -6
  298. package/src/services/reqresp/connection-sampler/connection_sampler.ts +148 -95
  299. package/src/services/reqresp/index.ts +2 -0
  300. package/src/services/reqresp/interface.ts +91 -36
  301. package/src/services/reqresp/metrics.ts +4 -1
  302. package/src/services/reqresp/protocols/auth.ts +83 -0
  303. package/src/services/reqresp/protocols/block.ts +24 -3
  304. package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
  305. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
  306. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
  307. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  308. package/src/services/reqresp/protocols/goodbye.ts +9 -7
  309. package/src/services/reqresp/protocols/index.ts +2 -0
  310. package/src/services/reqresp/protocols/status.ts +117 -5
  311. package/src/services/reqresp/protocols/tx.ts +35 -6
  312. package/src/services/reqresp/rate-limiter/rate_limiter.ts +12 -3
  313. package/src/services/reqresp/rate-limiter/rate_limits.ts +21 -1
  314. package/src/services/reqresp/reqresp.ts +387 -256
  315. package/src/services/reqresp/status.ts +12 -3
  316. package/src/services/service.ts +45 -21
  317. package/src/services/tx_collection/config.ts +84 -0
  318. package/src/services/tx_collection/fast_tx_collection.ts +340 -0
  319. package/src/services/tx_collection/index.ts +2 -0
  320. package/src/services/tx_collection/instrumentation.ts +43 -0
  321. package/src/services/tx_collection/slow_tx_collection.ts +232 -0
  322. package/src/services/tx_collection/tx_collection.ts +215 -0
  323. package/src/services/tx_collection/tx_collection_sink.ts +129 -0
  324. package/src/services/tx_collection/tx_source.ts +37 -0
  325. package/src/services/tx_provider.ts +216 -0
  326. package/src/services/tx_provider_instrumentation.ts +44 -0
  327. package/src/test-helpers/index.ts +1 -0
  328. package/src/test-helpers/make-enrs.ts +4 -5
  329. package/src/test-helpers/make-test-p2p-clients.ts +111 -21
  330. package/src/test-helpers/mock-pubsub.ts +188 -0
  331. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  332. package/src/test-helpers/reqresp-nodes.ts +86 -35
  333. package/src/testbench/p2p_client_testbench_worker.ts +145 -22
  334. package/src/testbench/parse_log_file.ts +4 -4
  335. package/src/testbench/testbench.ts +4 -4
  336. package/src/testbench/worker_client_manager.ts +17 -23
  337. package/src/types/index.ts +2 -0
  338. package/src/util.ts +93 -89
  339. package/src/versioning.ts +11 -4
@@ -4,13 +4,19 @@ function _ts_decorate(decorators, target, key, desc) {
4
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
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  }
7
+ import { randomInt } from '@aztec/foundation/crypto';
7
8
  import { Fr } from '@aztec/foundation/fields';
8
9
  import { createLibp2pComponentLogger, createLogger } from '@aztec/foundation/log';
9
10
  import { SerialQueue } from '@aztec/foundation/queue';
10
11
  import { RunningPromise } from '@aztec/foundation/running-promise';
11
- import { BlockAttestation, BlockProposal, P2PClientType, PeerErrorSeverity, TopicTypeMap, getTopicTypeForClientType, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
12
+ import { Timer } from '@aztec/foundation/timer';
13
+ import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
14
+ import { protocolContractsHash } from '@aztec/protocol-contracts';
15
+ import { GasFees } from '@aztec/stdlib/gas';
16
+ import { BlockAttestation, BlockProposal, P2PClientType, P2PMessage, PeerErrorSeverity, TopicType, createTopicString, getTopicsForClientAndConfig, metricsTopicStrToLabels } from '@aztec/stdlib/p2p';
12
17
  import { MerkleTreeId } from '@aztec/stdlib/trees';
13
18
  import { Tx } from '@aztec/stdlib/tx';
19
+ import { compressComponentVersions } from '@aztec/stdlib/versioning';
14
20
  import { Attributes, OtelMetricsAdapter, WithTracer, trackSpan } from '@aztec/telemetry-client';
15
21
  import { gossipsub } from '@chainsafe/libp2p-gossipsub';
16
22
  import { createPeerScoreParams, createTopicScoreParams } from '@chainsafe/libp2p-gossipsub/score';
@@ -20,23 +26,30 @@ import { yamux } from '@chainsafe/libp2p-yamux';
20
26
  import { bootstrap } from '@libp2p/bootstrap';
21
27
  import { identify } from '@libp2p/identify';
22
28
  import { TopicValidatorResult } from '@libp2p/interface';
23
- import '@libp2p/kad-dht';
24
29
  import { mplex } from '@libp2p/mplex';
25
30
  import { tcp } from '@libp2p/tcp';
31
+ import { ENR } from '@nethermindeth/enr';
26
32
  import { createLibp2p } from 'libp2p';
27
33
  import { AttestationValidator, BlockProposalValidator } from '../../msg_validators/index.js';
28
- import { DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
34
+ import { MessageSeenValidator } from '../../msg_validators/msg_seen_validator/msg_seen_validator.js';
35
+ import { getDefaultAllowedSetupFunctions } from '../../msg_validators/tx_validator/allowed_public_setup.js';
36
+ import { createTxMessageValidators } from '../../msg_validators/tx_validator/factory.js';
37
+ import { AggregateTxValidator, DataTxValidator, DoubleSpendTxValidator, MetadataTxValidator, TxProofValidator } from '../../msg_validators/tx_validator/index.js';
29
38
  import { GossipSubEvent } from '../../types/index.js';
30
39
  import { convertToMultiaddr } from '../../util.js';
40
+ import { getVersions } from '../../versioning.js';
31
41
  import { AztecDatastore } from '../data_store.js';
42
+ import { DiscV5Service } from '../discv5/discV5_service.js';
32
43
  import { SnappyTransform, fastMsgIdFn, getMsgIdFn, msgIdToStrFn } from '../encoding.js';
33
44
  import { gossipScoreThresholds } from '../gossipsub/scoring.js';
34
45
  import { PeerManager } from '../peer-manager/peer_manager.js';
35
46
  import { PeerScoring } from '../peer-manager/peer_scoring.js';
36
- import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol } from '../reqresp/interface.js';
47
+ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, ValidationError } from '../reqresp/interface.js';
48
+ import { reqRespBlockTxsHandler } from '../reqresp/protocols/block_txs/block_txs_handler.js';
37
49
  import { reqGoodbyeHandler } from '../reqresp/protocols/goodbye.js';
38
- import { pingHandler, reqRespBlockHandler, reqRespTxHandler, statusHandler } from '../reqresp/protocols/index.js';
50
+ import { pingHandler, reqRespBlockHandler, reqRespStatusHandler, reqRespTxHandler } from '../reqresp/protocols/index.js';
39
51
  import { ReqResp } from '../reqresp/reqresp.js';
52
+ import { P2PInstrumentation } from './instrumentation.js';
40
53
  /**
41
54
  * Lib P2P implementation of the P2PService interface.
42
55
  */ export class LibP2PService extends WithTracer {
@@ -44,36 +57,47 @@ import { ReqResp } from '../reqresp/reqresp.js';
44
57
  config;
45
58
  node;
46
59
  peerDiscoveryService;
60
+ reqresp;
61
+ peerManager;
47
62
  mempools;
48
- l2BlockSource;
63
+ archiver;
64
+ epochCache;
49
65
  proofVerifier;
50
66
  worldStateSynchronizer;
51
67
  logger;
52
68
  jobQueue;
53
- peerManager;
54
69
  discoveryRunningPromise;
70
+ msgIdSeenValidators;
55
71
  // Message validators
56
72
  attestationValidator;
57
73
  blockProposalValidator;
58
- // Request and response sub service
59
- reqresp;
74
+ protocolVersion;
75
+ topicStrings;
76
+ feesCache;
60
77
  /**
61
78
  * Callback for when a block is received from a peer.
62
79
  * @param block - The block received from the peer.
63
80
  * @returns The attestation for the block, if any.
64
81
  */ 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;
82
+ gossipSubEventHandler;
83
+ instrumentation;
84
+ constructor(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, archiver, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger = createLogger('p2p:libp2p_service')){
85
+ super(telemetry, 'LibP2PService'), this.clientType = clientType, this.config = config, this.node = node, this.peerDiscoveryService = peerDiscoveryService, this.reqresp = reqresp, this.peerManager = peerManager, this.mempools = mempools, this.archiver = archiver, this.epochCache = epochCache, this.proofVerifier = proofVerifier, this.worldStateSynchronizer = worldStateSynchronizer, this.logger = logger, this.jobQueue = new SerialQueue(), this.msgIdSeenValidators = {}, this.protocolVersion = '', this.topicStrings = {};
86
+ this.instrumentation = new P2PInstrumentation(telemetry, 'LibP2PService');
87
+ this.msgIdSeenValidators[TopicType.tx] = new MessageSeenValidator(config.seenMessageCacheSize);
88
+ this.msgIdSeenValidators[TopicType.block_proposal] = new MessageSeenValidator(config.seenMessageCacheSize);
89
+ this.msgIdSeenValidators[TopicType.block_attestation] = new MessageSeenValidator(config.seenMessageCacheSize);
90
+ const versions = getVersions(config);
91
+ this.protocolVersion = compressComponentVersions(versions);
92
+ logger.info(`Started libp2p service with protocol version ${this.protocolVersion}`);
93
+ this.topicStrings[TopicType.tx] = createTopicString(TopicType.tx, this.protocolVersion);
94
+ this.topicStrings[TopicType.block_proposal] = createTopicString(TopicType.block_proposal, this.protocolVersion);
95
+ this.topicStrings[TopicType.block_attestation] = createTopicString(TopicType.block_attestation, this.protocolVersion);
75
96
  this.attestationValidator = new AttestationValidator(epochCache);
76
- this.blockProposalValidator = new BlockProposalValidator(epochCache);
97
+ this.blockProposalValidator = new BlockProposalValidator(epochCache, {
98
+ txsPermitted: !config.disableTransactions
99
+ });
100
+ this.gossipSubEventHandler = this.handleGossipSubEvent.bind(this);
77
101
  this.blockReceivedCallback = async (block)=>{
78
102
  this.logger.debug(`Handler not yet registered: Block received callback not set. Received block for slot ${block.slotNumber.toNumber()} from peer.`, {
79
103
  p2pMessageIdentifier: await block.p2pMessageIdentifier()
@@ -81,25 +105,54 @@ import { ReqResp } from '../reqresp/reqresp.js';
81
105
  return undefined;
82
106
  };
83
107
  }
108
+ updateConfig(config) {
109
+ this.reqresp.updateConfig(config);
110
+ }
84
111
  /**
85
112
  * Creates an instance of the LibP2P service.
86
113
  * @param config - The configuration to use when creating the service.
87
114
  * @param txPool - The transaction pool to be accessed by the service.
88
115
  * @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);
116
+ */ static async new(clientType, config, peerId, deps) {
117
+ const { worldStateSynchronizer, epochCache, l2BlockSource, mempools, proofVerifier, peerStore, telemetry, logger, packageVersion } = deps;
118
+ const { p2pPort, maxPeerCount, listenAddress } = config;
119
+ const bindAddrTcp = convertToMultiaddr(listenAddress, p2pPort, 'tcp');
120
+ const datastore = new AztecDatastore(peerStore);
95
121
  const otelMetricsAdapter = new OtelMetricsAdapter(telemetry);
96
- // If bootstrap nodes are provided, also provide them to the p2p service
122
+ const peerDiscoveryService = new DiscV5Service(peerId, config, packageVersion, telemetry, createLogger(`${logger.module}:discv5_service`));
123
+ // Seed libp2p's bootstrap discovery with private and trusted peers
124
+ const bootstrapNodes = [
125
+ ...config.privatePeers,
126
+ ...config.trustedPeers
127
+ ];
97
128
  const peerDiscovery = [];
98
- if (peerDiscoveryService.bootstrapNodes.length > 0) {
129
+ if (bootstrapNodes.length > 0) {
99
130
  peerDiscovery.push(bootstrap({
100
- list: peerDiscoveryService.bootstrapNodes
131
+ list: bootstrapNodes
101
132
  }));
102
133
  }
134
+ const versions = getVersions(config);
135
+ const protocolVersion = compressComponentVersions(versions);
136
+ const txTopic = createTopicString(TopicType.tx, protocolVersion);
137
+ const blockProposalTopic = createTopicString(TopicType.block_proposal, protocolVersion);
138
+ const blockAttestationTopic = createTopicString(TopicType.block_attestation, protocolVersion);
139
+ const preferredPeersEnrs = config.preferredPeers.map((enr)=>ENR.decodeTxt(enr));
140
+ const directPeers = (await Promise.all(preferredPeersEnrs.map(async (enr)=>{
141
+ const peerId = await enr.peerId();
142
+ const address = enr.getLocationMultiaddr('tcp');
143
+ if (address === undefined) {
144
+ throw new Error(`Direct peer ${peerId.toString()} has no TCP address, ENR: ${enr.encodeTxt()}`);
145
+ }
146
+ return {
147
+ id: peerId,
148
+ addrs: [
149
+ address
150
+ ]
151
+ };
152
+ }))).filter((peer)=>peer !== undefined);
153
+ const announceTcpMultiaddr = config.p2pIp ? [
154
+ convertToMultiaddr(config.p2pIp, p2pPort, 'tcp')
155
+ ] : [];
103
156
  const node = await createLibp2p({
104
157
  start: false,
105
158
  peerId,
@@ -107,44 +160,76 @@ import { ReqResp } from '../reqresp/reqresp.js';
107
160
  listen: [
108
161
  bindAddrTcp
109
162
  ],
110
- announce: [
111
- announceAddrTcp
112
- ]
163
+ announce: announceTcpMultiaddr
113
164
  },
114
165
  transports: [
115
166
  tcp({
116
- maxConnections: config.maxPeerCount,
167
+ // It's better to have this number a bit higher than our maxPeerCount because it's sets the limit on transport (TCP) layer
168
+ // 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
169
+ // If we hit the limit, the connection will be temporarily accepted and immediately dropped.
170
+ // Docs: https://nodejs.org/api/net.html#servermaxconnections
171
+ maxConnections: maxPeerCount * 2,
117
172
  // socket option: the maximum length of the queue of pending connections
118
- // https://nodejs.org/dist/latest-v18.x/docs/api/net.html#serverlisten
173
+ // https://nodejs.org/dist/latest-v22.x/docs/api/net.html#serverlisten
119
174
  // it's not safe if we increase this number
120
175
  backlog: 5,
121
176
  closeServerOnMaxConnections: {
122
- closeAbove: maxPeerCount ?? Infinity,
123
- listenBelow: maxPeerCount ?? Infinity
177
+ // The property `maxConnections` will protect us against the most DDOS attack
178
+ // This property protects us in case of burst of new connections where server is not able to close them quickly enough
179
+ // In case closeAbove is reached, the server stops listening altogether
180
+ // It's important that there is enough difference between closeAbove and listenAbove,
181
+ // otherwise the server.listener will flap between being closed and open potentially degrading perf even more
182
+ closeAbove: maxPeerCount * 3,
183
+ listenBelow: Math.floor(maxPeerCount * 0.9)
124
184
  }
125
185
  })
126
186
  ],
127
187
  datastore,
128
188
  peerDiscovery,
129
189
  streamMuxers: [
130
- mplex(),
131
- yamux()
190
+ yamux(),
191
+ mplex()
132
192
  ],
133
193
  connectionEncryption: [
134
194
  noise()
135
195
  ],
136
196
  connectionManager: {
137
197
  minConnections: 0,
198
+ // We set maxConnections above maxPeerCount because if we hit limit of maxPeerCount
199
+ // libp2p will start aggressively rejecting all new connections, preventing network discovery and crawling.
200
+ maxConnections: maxPeerCount * 2,
138
201
  maxParallelDials: 100,
139
202
  dialTimeout: 30_000,
140
203
  maxPeerAddrsToDial: 5,
141
204
  maxIncomingPendingConnections: 5
142
205
  },
206
+ connectionGater: {
207
+ denyInboundConnection: (maConn)=>{
208
+ const allowed = peerManager.isNodeAllowedToConnect(maConn.remoteAddr.nodeAddress().address);
209
+ if (allowed) {
210
+ return false;
211
+ }
212
+ logger.debug(`Connection gater: Denying inbound connection from ${maConn.remoteAddr.toString()}`);
213
+ return true;
214
+ },
215
+ denyInboundEncryptedConnection: (peerId, _maConn)=>{
216
+ //NOTE: it is not necessary to check address here because this was already done by
217
+ // denyInboundConnection
218
+ const allowed = peerManager.isNodeAllowedToConnect(peerId);
219
+ if (allowed) {
220
+ return false;
221
+ }
222
+ logger.debug(`Connection gater: Denying inbound encrypted connection from ${peerId.toString()}`);
223
+ return true;
224
+ }
225
+ },
143
226
  services: {
144
227
  identify: identify({
145
- protocolPrefix: 'aztec'
228
+ protocolPrefix: 'aztec',
229
+ runOnConnectionOpen: true
146
230
  }),
147
231
  pubsub: gossipsub({
232
+ directPeers,
148
233
  debugName: 'gossipsub',
149
234
  globalSignaturePolicy: SignaturePolicy.StrictNoSign,
150
235
  allowPublishToZeroTopicPeers: true,
@@ -156,29 +241,30 @@ import { ReqResp } from '../reqresp/reqresp.js';
156
241
  heartbeatInterval: config.gossipsubInterval,
157
242
  mcacheLength: config.gossipsubMcacheLength,
158
243
  mcacheGossip: config.gossipsubMcacheGossip,
244
+ seenTTL: config.gossipsubSeenTTL,
159
245
  msgIdFn: getMsgIdFn,
160
246
  msgIdToStrFn: msgIdToStrFn,
161
247
  fastMsgIdFn: fastMsgIdFn,
162
248
  dataTransform: new SnappyTransform(),
163
249
  metricsRegister: otelMetricsAdapter,
164
- metricsTopicStrToLabel: metricsTopicStrToLabels(),
250
+ metricsTopicStrToLabel: metricsTopicStrToLabels(protocolVersion),
165
251
  asyncValidation: true,
166
252
  scoreThresholds: gossipScoreThresholds,
167
253
  scoreParams: createPeerScoreParams({
168
254
  // IPColocation factor can be disabled for local testing - default to -5
169
255
  IPColocationFactorWeight: config.debugDisableColocationPenalty ? 0 : -5.0,
170
256
  topics: {
171
- [Tx.p2pTopic]: createTopicScoreParams({
257
+ [txTopic]: createTopicScoreParams({
172
258
  topicWeight: 1,
173
259
  invalidMessageDeliveriesWeight: -20,
174
260
  invalidMessageDeliveriesDecay: 0.5
175
261
  }),
176
- [BlockAttestation.p2pTopic]: createTopicScoreParams({
262
+ [blockAttestationTopic]: createTopicScoreParams({
177
263
  topicWeight: 1,
178
264
  invalidMessageDeliveriesWeight: -20,
179
265
  invalidMessageDeliveriesDecay: 0.5
180
266
  }),
181
- [BlockProposal.p2pTopic]: createTopicScoreParams({
267
+ [blockProposalTopic]: createTopicScoreParams({
182
268
  topicWeight: 1,
183
269
  invalidMessageDeliveriesWeight: -20,
184
270
  invalidMessageDeliveriesDecay: 0.5
@@ -192,7 +278,13 @@ import { ReqResp } from '../reqresp/reqresp.js';
192
278
  },
193
279
  logger: createLibp2pComponentLogger(logger.module)
194
280
  });
195
- return new LibP2PService(clientType, config, node, peerDiscoveryService, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
281
+ const peerScoring = new PeerScoring(config);
282
+ const reqresp = new ReqResp(config, node, peerScoring, createLogger(`${logger.module}:reqresp`));
283
+ const peerManager = new PeerManager(node, peerDiscoveryService, config, telemetry, createLogger(`${logger.module}:peer_manager`), peerScoring, reqresp, worldStateSynchronizer, protocolVersion, epochCache);
284
+ // Update gossipsub score params
285
+ node.services.pubsub.score.params.appSpecificWeight = 10;
286
+ node.services.pubsub.score.params.appSpecificScore = (peerId)=>peerManager.shouldDisableP2PGossip(peerId) ? -Infinity : peerManager.getPeerScore(peerId);
287
+ return new LibP2PService(clientType, config, node, peerDiscoveryService, reqresp, peerManager, mempools, l2BlockSource, epochCache, proofVerifier, worldStateSynchronizer, telemetry, logger);
196
288
  }
197
289
  /**
198
290
  * Starts the LibP2P service.
@@ -203,32 +295,43 @@ import { ReqResp } from '../reqresp/reqresp.js';
203
295
  throw new Error('P2P service already started');
204
296
  }
205
297
  // Get listen & announce addresses for logging
206
- const { tcpListenAddress, tcpAnnounceAddress } = this.config;
207
- if (!tcpAnnounceAddress) {
298
+ const { p2pIp, p2pPort } = this.config;
299
+ if (!p2pIp) {
208
300
  throw new Error('Announce address not provided.');
209
301
  }
210
- const announceTcpMultiaddr = convertToMultiaddr(tcpAnnounceAddress, 'tcp');
302
+ const announceTcpMultiaddr = convertToMultiaddr(p2pIp, p2pPort, 'tcp');
211
303
  // Start job queue, peer discovery service and libp2p node
212
304
  this.jobQueue.start();
213
- await this.peerDiscoveryService.start();
305
+ await this.peerManager.initializePeers();
306
+ if (!this.config.p2pDiscoveryDisabled) {
307
+ await this.peerDiscoveryService.start();
308
+ }
214
309
  await this.node.start();
215
310
  // Subscribe to standard GossipSub topics by default
216
- for (const topic of getTopicTypeForClientType(this.clientType)){
217
- this.subscribeToTopic(TopicTypeMap[topic].p2pTopic);
311
+ for (const topic of getTopicsForClientAndConfig(this.clientType, this.config.disableTransactions)){
312
+ this.subscribeToTopic(this.topicStrings[topic]);
218
313
  }
219
314
  // Create request response protocol handlers
220
315
  const txHandler = reqRespTxHandler(this.mempools);
221
316
  const goodbyeHandler = reqGoodbyeHandler(this.peerManager);
222
- const blockHandler = reqRespBlockHandler(this.l2BlockSource);
317
+ const blockHandler = reqRespBlockHandler(this.archiver);
318
+ const statusHandler = reqRespStatusHandler(this.protocolVersion, this.worldStateSynchronizer, this.logger);
223
319
  const requestResponseHandlers = {
224
320
  [ReqRespSubProtocol.PING]: pingHandler,
225
- [ReqRespSubProtocol.STATUS]: statusHandler,
226
- [ReqRespSubProtocol.TX]: txHandler.bind(this),
321
+ [ReqRespSubProtocol.STATUS]: statusHandler.bind(this),
227
322
  [ReqRespSubProtocol.GOODBYE]: goodbyeHandler.bind(this),
228
323
  [ReqRespSubProtocol.BLOCK]: blockHandler.bind(this)
229
324
  };
325
+ // Only handle block transactions request if attestation pool is available to the client
326
+ if (this.mempools.attestationPool && !this.config.disableTransactions) {
327
+ const blockTxsHandler = reqRespBlockTxsHandler(this.mempools.attestationPool, this.mempools.txPool);
328
+ requestResponseHandlers[ReqRespSubProtocol.BLOCK_TXS] = blockTxsHandler.bind(this);
329
+ }
330
+ if (!this.config.disableTransactions) {
331
+ requestResponseHandlers[ReqRespSubProtocol.TX] = txHandler.bind(this);
332
+ }
230
333
  // add GossipSub listener
231
- this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
334
+ this.node.services.pubsub.addEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
232
335
  // Start running promise for peer discovery
233
336
  this.discoveryRunningPromise = new RunningPromise(()=>this.peerManager.heartbeat(), this.logger, this.config.peerCheckIntervalMS);
234
337
  this.discoveryRunningPromise.start();
@@ -236,11 +339,13 @@ import { ReqResp } from '../reqresp/reqresp.js';
236
339
  const reqrespSubProtocolValidators = {
237
340
  ...DEFAULT_SUB_PROTOCOL_VALIDATORS,
238
341
  // TODO(#11336): A request validator for blocks
239
- [ReqRespSubProtocol.TX]: this.validateRequestedTx.bind(this)
342
+ [ReqRespSubProtocol.TX]: this.validateRequestedTxs.bind(this),
343
+ [ReqRespSubProtocol.BLOCK_TXS]: this.validateRequestedBlockTxs.bind(this)
240
344
  };
241
345
  await this.reqresp.start(requestResponseHandlers, reqrespSubProtocolValidators);
242
346
  this.logger.info(`Started P2P service`, {
243
- listen: tcpListenAddress,
347
+ listen: this.config.listenAddress,
348
+ port: this.config.p2pPort,
244
349
  announce: announceTcpMultiaddr,
245
350
  peerId: this.node.peerId.toString()
246
351
  });
@@ -250,7 +355,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
250
355
  * @returns An empty promise.
251
356
  */ async stop() {
252
357
  // Remove gossip sub listener
253
- this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.handleGossipSubEvent.bind(this));
358
+ this.node.services.pubsub.removeEventListener(GossipSubEvent.MESSAGE, this.gossipSubEventHandler);
254
359
  // Stop peer manager
255
360
  this.logger.debug('Stopping peer manager...');
256
361
  await this.peerManager.stop();
@@ -266,6 +371,12 @@ import { ReqResp } from '../reqresp/reqresp.js';
266
371
  await this.stopLibP2P();
267
372
  this.logger.info('LibP2P service stopped');
268
373
  }
374
+ addReqRespSubProtocol(subProtocol, handler, validator) {
375
+ return this.reqresp.addSubProtocol(subProtocol, handler, validator);
376
+ }
377
+ registerThisValidatorAddresses(address) {
378
+ this.peerManager.registerThisValidatorAddresses(address);
379
+ }
269
380
  getPeers(includePending) {
270
381
  return this.peerManager.getPeers(includePending);
271
382
  }
@@ -281,24 +392,12 @@ import { ReqResp } from '../reqresp/reqresp.js';
281
392
  setImmediate(()=>void safeJob());
282
393
  }
283
394
  /**
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
395
  * Send a batch of requests to peers, and return the responses
297
396
  * @param protocol - The request response protocol to use
298
397
  * @param requests - The requests to send to the peers
299
398
  * @returns The responses to the requests
300
- */ sendBatchRequest(protocol, requests) {
301
- return this.reqresp.sendBatchRequest(protocol, requests);
399
+ */ sendBatchRequest(protocol, requests, pinnedPeerId) {
400
+ return this.reqresp.sendBatchRequest(protocol, requests, pinnedPeerId);
302
401
  }
303
402
  /**
304
403
  * Get the ENR of the node
@@ -308,7 +407,6 @@ import { ReqResp } from '../reqresp/reqresp.js';
308
407
  }
309
408
  registerBlockReceivedCallback(callback) {
310
409
  this.blockReceivedCallback = callback;
311
- this.logger.verbose('Block received callback registered');
312
410
  }
313
411
  /**
314
412
  * Subscribes to a topic.
@@ -322,133 +420,246 @@ import { ReqResp } from '../reqresp/reqresp.js';
322
420
  /**
323
421
  * Publishes data to a topic.
324
422
  * @param topic - The topic to publish to.
325
- * @param data - The data to publish.
423
+ * @param data - The message to publish.
326
424
  * @returns The number of recipients the data was sent to.
327
- */ async publishToTopic(topic, data) {
425
+ */ async publishToTopic(topic, message) {
328
426
  if (!this.node.services.pubsub) {
329
427
  throw new Error('Pubsub service not available.');
330
428
  }
331
- const result = await this.node.services.pubsub.publish(topic, data);
429
+ const p2pMessage = P2PMessage.fromGossipable(message);
430
+ const result = await this.node.services.pubsub.publish(topic, p2pMessage.toMessageData());
332
431
  return result.recipients.length;
333
432
  }
334
433
  /**
434
+ * Checks if this message has already been seen, based on its msgId computed from hashing the message data.
435
+ * Note that we do not rely on the seenCache from gossipsub since we want to keep a longer history of seen
436
+ * messages to avoid tx echoes across the network.
437
+ */ preValidateReceivedMessage(msg, msgId, source) {
438
+ let topicType;
439
+ switch(msg.topic){
440
+ case this.topicStrings[TopicType.tx]:
441
+ topicType = TopicType.tx;
442
+ break;
443
+ case this.topicStrings[TopicType.block_attestation]:
444
+ topicType = TopicType.block_attestation;
445
+ break;
446
+ case this.topicStrings[TopicType.block_proposal]:
447
+ topicType = TopicType.block_proposal;
448
+ break;
449
+ default:
450
+ this.logger.error(`Received message on unknown topic: ${msg.topic}`);
451
+ break;
452
+ }
453
+ const validator = topicType ? this.msgIdSeenValidators[topicType] : undefined;
454
+ if (!validator || !validator.addMessage(msgId)) {
455
+ this.instrumentation.incMessagePrevalidationStatus(false, topicType);
456
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), TopicValidatorResult.Ignore);
457
+ return {
458
+ result: false,
459
+ topicType
460
+ };
461
+ }
462
+ this.instrumentation.incMessagePrevalidationStatus(true, topicType);
463
+ return {
464
+ result: true,
465
+ topicType
466
+ };
467
+ }
468
+ /**
335
469
  * Handles a new gossip message that was received by the client.
336
470
  * @param topic - The message's topic.
337
471
  * @param data - The message data
338
472
  */ async handleNewGossipMessage(msg, msgId, source) {
339
- if (msg.topic === Tx.p2pTopic) {
340
- await this.handleGossipedTx(msg, msgId, source);
473
+ const p2pMessage = P2PMessage.fromMessageData(Buffer.from(msg.data));
474
+ const preValidationResult = this.preValidateReceivedMessage(msg, msgId, source);
475
+ if (!preValidationResult.result) {
476
+ return;
477
+ }
478
+ if (msg.topic === this.topicStrings[TopicType.tx]) {
479
+ await this.handleGossipedTx(p2pMessage.payload, msgId, source);
341
480
  }
342
- if (msg.topic === BlockAttestation.p2pTopic && this.clientType === P2PClientType.Full) {
343
- await this.processAttestationFromPeer(msg, msgId, source);
481
+ if (msg.topic === this.topicStrings[TopicType.block_attestation] && this.clientType === P2PClientType.Full) {
482
+ await this.processAttestationFromPeer(p2pMessage.payload, msgId, source);
344
483
  }
345
- if (msg.topic == BlockProposal.p2pTopic) {
346
- await this.processBlockFromPeer(msg, msgId, source);
484
+ if (msg.topic === this.topicStrings[TopicType.block_proposal]) {
485
+ await this.processBlockFromPeer(p2pMessage.payload, msgId, source);
347
486
  }
348
487
  return;
349
488
  }
350
- async validateReceivedMessage(validationFunc, msgId, source) {
489
+ async validateReceivedMessage(validationFunc, msgId, source, topicType) {
351
490
  let resultAndObj = {
352
- result: false,
353
- obj: undefined
491
+ result: TopicValidatorResult.Reject
354
492
  };
493
+ const timer = new Timer();
355
494
  try {
356
495
  resultAndObj = await validationFunc();
357
496
  } catch (err) {
358
- this.logger.error(`Error deserialising and validating message `, err);
497
+ this.logger.error(`Error deserializing and validating gossipsub message`, err, {
498
+ msgId,
499
+ source: source.toString(),
500
+ topicType
501
+ });
502
+ }
503
+ if (resultAndObj.result === TopicValidatorResult.Accept) {
504
+ this.instrumentation.recordMessageValidation(topicType, timer);
359
505
  }
360
- this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result && resultAndObj.obj ? TopicValidatorResult.Accept : TopicValidatorResult.Reject);
506
+ this.node.services.pubsub.reportMessageValidationResult(msgId, source.toString(), resultAndObj.result);
361
507
  return resultAndObj;
362
508
  }
363
- async handleGossipedTx(msg, msgId, source) {
509
+ async handleGossipedTx(payloadData, msgId, source) {
364
510
  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
- };
511
+ const tx = Tx.fromBuffer(payloadData);
512
+ const isValid = await this.validatePropagatedTx(tx, source);
513
+ const exists = isValid && await this.mempools.txPool.hasTx(tx.getTxHash());
514
+ this.logger.trace(`Validate propagated tx`, {
515
+ isValid,
516
+ exists,
517
+ [Attributes.P2P_ID]: source.toString()
518
+ });
519
+ if (!isValid) {
520
+ return {
521
+ result: TopicValidatorResult.Reject
522
+ };
523
+ } else if (exists) {
524
+ return {
525
+ result: TopicValidatorResult.Ignore,
526
+ obj: tx
527
+ };
528
+ } else {
529
+ return {
530
+ result: TopicValidatorResult.Accept,
531
+ obj: tx
532
+ };
533
+ }
371
534
  };
372
- const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source);
373
- if (!result || !tx) {
535
+ const { result, obj: tx } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.tx);
536
+ if (result !== TopicValidatorResult.Accept || !tx) {
374
537
  return;
375
538
  }
376
- const txHash = await tx.getTxHash();
539
+ const txHash = tx.getTxHash();
377
540
  const txHashString = txHash.toString();
378
- this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()}.`);
541
+ this.logger.verbose(`Received tx ${txHashString} from external peer ${source.toString()} via gossip`, {
542
+ source: source.toString(),
543
+ txHash: txHashString
544
+ });
545
+ if (this.config.dropTransactions && randomInt(1000) < this.config.dropTransactionsProbability * 1000) {
546
+ this.logger.warn(`Intentionally dropping tx ${txHashString} (probability rule)`);
547
+ return;
548
+ }
379
549
  await this.mempools.txPool.addTxs([
380
550
  tx
381
551
  ]);
382
552
  }
383
- /**Process Attestation From Peer
553
+ /**
554
+ * Process Attestation From Peer
384
555
  * When a proposal is received from a peer, we add it to the attestation pool, so it can be accessed by other services.
385
556
  *
386
557
  * @param attestation - The attestation to process.
387
- */ async processAttestationFromPeer(msg, msgId, source) {
558
+ */ async processAttestationFromPeer(payloadData, msgId, source) {
388
559
  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(),
560
+ const attestation = BlockAttestation.fromBuffer(payloadData);
561
+ const isValid = await this.validateAttestation(source, attestation);
562
+ const exists = isValid && await this.mempools.attestationPool.hasAttestation(attestation);
563
+ this.logger.trace(`Validate propagated block attestation`, {
564
+ isValid,
565
+ exists,
566
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toString(),
393
567
  [Attributes.P2P_ID]: source.toString()
394
568
  });
395
- return {
396
- result,
397
- obj: attestation
398
- };
569
+ if (!isValid) {
570
+ return {
571
+ result: TopicValidatorResult.Reject
572
+ };
573
+ } else if (exists) {
574
+ return {
575
+ result: TopicValidatorResult.Ignore,
576
+ obj: attestation
577
+ };
578
+ } else {
579
+ return {
580
+ result: TopicValidatorResult.Accept,
581
+ obj: attestation
582
+ };
583
+ }
399
584
  };
400
- const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source);
401
- if (!result || !attestation) {
585
+ const { result, obj: attestation } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_attestation);
586
+ if (result !== TopicValidatorResult.Accept || !attestation) {
402
587
  return;
403
588
  }
404
- this.logger.debug(`Received attestation for block ${attestation.blockNumber.toNumber()} slot ${attestation.slotNumber.toNumber()} from external peer.`, {
589
+ this.logger.debug(`Received attestation for slot ${attestation.slotNumber.toNumber()} from external peer ${source.toString()}`, {
405
590
  p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
406
591
  slot: attestation.slotNumber.toNumber(),
407
592
  archive: attestation.archive.toString(),
408
- block: attestation.blockNumber.toNumber()
593
+ source: source.toString()
409
594
  });
410
595
  await this.mempools.attestationPool.addAttestations([
411
596
  attestation
412
597
  ]);
413
598
  }
414
- async processBlockFromPeer(msg, msgId, source) {
599
+ async processBlockFromPeer(payloadData, msgId, source) {
415
600
  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(),
601
+ const block = BlockProposal.fromBuffer(payloadData);
602
+ const isValid = await this.validateBlockProposal(source, block);
603
+ // Note that we dont have an attestation pool if we're a prover node, but we still
604
+ // subscribe to block proposal topics in order to prevent their txs from being cleared.
605
+ const exists = isValid && await this.mempools.attestationPool?.hasBlockProposal(block);
606
+ this.logger.trace(`Validate propagated block proposal`, {
607
+ isValid,
608
+ exists,
609
+ [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString(),
420
610
  [Attributes.P2P_ID]: source.toString()
421
611
  });
422
- return {
423
- result,
424
- obj: block
425
- };
612
+ if (!isValid) {
613
+ return {
614
+ result: TopicValidatorResult.Reject
615
+ };
616
+ } else if (exists) {
617
+ return {
618
+ result: TopicValidatorResult.Ignore,
619
+ obj: block
620
+ };
621
+ } else {
622
+ return {
623
+ result: TopicValidatorResult.Accept,
624
+ obj: block
625
+ };
626
+ }
426
627
  };
427
- const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source);
628
+ const { result, obj: block } = await this.validateReceivedMessage(validationFunc, msgId, source, TopicType.block_proposal);
428
629
  if (!result || !block) {
429
630
  return;
430
631
  }
431
- await this.processValidBlockProposal(block);
632
+ await this.processValidBlockProposal(block, source);
432
633
  }
433
634
  // 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.`, {
635
+ async processValidBlockProposal(block, sender) {
636
+ const slot = block.slotNumber.toBigInt();
637
+ const previousSlot = slot - 1n;
638
+ this.logger.verbose(`Received block proposal for slot ${slot} from external peer ${sender.toString()}.`, {
436
639
  p2pMessageIdentifier: await block.p2pMessageIdentifier(),
437
640
  slot: block.slotNumber.toNumber(),
438
641
  archive: block.archive.toString(),
439
- block: block.blockNumber.toNumber()
642
+ source: sender.toString()
440
643
  });
441
- const attestation = await this.blockReceivedCallback(block);
644
+ const attestationsForPreviousSlot = await this.mempools.attestationPool?.getAttestationsForSlot(previousSlot);
645
+ if (attestationsForPreviousSlot !== undefined) {
646
+ this.logger.verbose(`Received ${attestationsForPreviousSlot.length} attestations for slot ${previousSlot}`);
647
+ }
648
+ // Mark the txs in this proposal as non-evictable
649
+ await this.mempools.txPool.markTxsAsNonEvictable(block.txHashes);
650
+ await this.mempools.attestationPool?.addBlockProposal(block);
651
+ const attestations = await this.blockReceivedCallback(block, sender);
442
652
  // TODO: fix up this pattern - the abstraction is not nice
443
653
  // 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()
450
- });
451
- await this.broadcastAttestation(attestation);
654
+ if (attestations?.length) {
655
+ for (const attestation of attestations){
656
+ this.logger.verbose(`Broadcasting attestation for slot ${attestation.slotNumber.toNumber()}`, {
657
+ p2pMessageIdentifier: await attestation.p2pMessageIdentifier(),
658
+ slot: attestation.slotNumber.toNumber(),
659
+ archive: attestation.archive.toString()
660
+ });
661
+ await this.broadcastAttestation(attestation);
662
+ }
452
663
  }
453
664
  }
454
665
  /**
@@ -474,83 +685,145 @@ import { ReqResp } from '../reqresp/reqresp.js';
474
685
  });
475
686
  }
476
687
  /**
477
- * Validate a tx that has been requested from a peer.
688
+ * Validate the requested block transactions.
689
+ * @param request - The block transactions request.
690
+ * @param response - The block transactions response.
691
+ * @param peerId - The ID of the peer that made the request.
692
+ * @returns True if the requested block transactions are valid, false otherwise.
693
+ */ async validateRequestedBlockTxs(_request, response, peerId) {
694
+ const requestedTxValidator = this.createRequestedTxValidator();
695
+ try {
696
+ // TODO(palla/txs): Validate that this tx belongs to the block hash being requested
697
+ await Promise.all(response.txs.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator)));
698
+ return true;
699
+ } catch (e) {
700
+ if (e instanceof ValidationError) {
701
+ this.logger.warn(`Failed validation for requested block txs from peer ${peerId.toString()}`);
702
+ } else {
703
+ this.logger.error(`Error during validation of requested block txs`, e);
704
+ }
705
+ return false;
706
+ }
707
+ }
708
+ /**
709
+ * Validate a collection of txs that has been requested from a peer.
478
710
  *
479
- * The core component of this validator is that the tx hash MUST match the requested tx hash,
711
+ * The core component of this validator is that each tx hash MUST match the requested tx hash,
480
712
  * In order to perform this check, the tx proof must be verified.
481
713
  *
482
714
  * Note: This function is called from within `ReqResp.sendRequest` as part of the
483
715
  * ReqRespSubProtocol.TX subprotocol validation.
484
716
  *
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.
717
+ * @param requestedTxHash - The collection of the txs that was requested.
718
+ * @param responseTx - The collectin of txs that was received as a response to the request.
487
719
  * @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);
720
+ * @returns True if the whole collection of txs is valid, false otherwise.
721
+ */ async validateRequestedTxs(requestedTxHash, responseTx, peerId) {
722
+ const requested = new Set(requestedTxHash.map((h)=>h.toString()));
723
+ const requestedTxValidator = this.createRequestedTxValidator();
724
+ //TODO: (mralj) - this is somewhat naive implementation, if single tx is invlid we consider the whole response invalid.
725
+ // I think we should still extract the valid txs and return them, so that we can still use the response.
726
+ try {
727
+ await Promise.all(responseTx.map((tx)=>this.validateRequestedTx(tx, peerId, requestedTxValidator, requested)));
728
+ return true;
729
+ } catch (e) {
730
+ if (e instanceof ValidationError) {
731
+ this.logger.warn(`Failed to validate requested txs from peer ${peerId.toString()}, reason ${e.message}`);
732
+ } else {
733
+ this.logger.error(`Error during validation of requested txs`, e);
734
+ }
496
735
  return false;
497
736
  }
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
737
+ }
738
+ createRequestedTxValidator() {
739
+ return new AggregateTxValidator(new DataTxValidator(), new MetadataTxValidator({
740
+ l1ChainId: new Fr(this.config.l1ChainId),
741
+ rollupVersion: new Fr(this.config.rollupVersion),
742
+ protocolContractsHash,
743
+ vkTreeRoot: getVKTreeRoot()
744
+ }), new TxProofValidator(this.proofVerifier));
745
+ }
746
+ async validateRequestedTx(tx, peerId, txValidator, requested) {
747
+ if (!await tx.validateTxHash()) {
748
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
749
+ throw new ValidationError(`Received tx with invalid hash ${tx.getTxHash().toString()}.`);
750
+ }
751
+ if (requested && !requested.has(tx.getTxHash().toString())) {
752
+ this.peerManager.penalizePeer(peerId, PeerErrorSeverity.MidToleranceError);
753
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that was not requested.`);
754
+ }
755
+ const { result } = await txValidator.validateTx(tx);
756
+ if (result === 'invalid') {
500
757
  this.peerManager.penalizePeer(peerId, PeerErrorSeverity.LowToleranceError);
501
- return false;
758
+ throw new ValidationError(`Received tx with hash ${tx.getTxHash().toString()} that is invalid.`);
502
759
  }
503
- return true;
504
760
  }
505
761
  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;
762
+ const currentBlockNumber = await this.archiver.getBlockNumber();
763
+ // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
764
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
765
+ const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
766
+ for (const validator of messageValidators){
767
+ const outcome = await this.runValidations(tx, validator);
768
+ if (outcome.allPassed) {
769
+ continue;
770
+ }
771
+ const { name } = outcome.failure;
772
+ let { severity } = outcome.failure;
773
+ // Double spend validator has a special case handler
774
+ if (name === 'doubleSpendValidator') {
775
+ const txBlockNumber = currentBlockNumber + 1; // tx is expected to be in the next block
776
+ severity = await this.handleDoubleSpendFailure(tx, txBlockNumber);
777
+ }
778
+ this.peerManager.penalizePeer(peerId, severity);
779
+ return false;
511
780
  }
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);
781
+ return true;
782
+ }
783
+ async getGasFees(blockNumber) {
784
+ if (blockNumber === this.feesCache?.blockNumber) {
785
+ return this.feesCache.gasFees;
517
786
  }
518
- this.peerManager.penalizePeer(peerId, severity);
519
- return false;
787
+ const header = await this.archiver.getBlockHeader(blockNumber);
788
+ const gasFees = header?.globalVariables.gasFees ?? GasFees.empty();
789
+ this.feesCache = {
790
+ blockNumber,
791
+ gasFees
792
+ };
793
+ return gasFees;
794
+ }
795
+ async validate(txs) {
796
+ const currentBlockNumber = await this.archiver.getBlockNumber();
797
+ // We accept transactions if they are not expired by the next slot (checked based on the IncludeByTimestamp field)
798
+ const { ts: nextSlotTimestamp } = this.epochCache.getEpochAndSlotInNextL1Slot();
799
+ const messageValidators = await this.createMessageValidators(currentBlockNumber, nextSlotTimestamp);
800
+ await Promise.all(txs.map(async (tx)=>{
801
+ for (const validator of messageValidators){
802
+ const outcome = await this.runValidations(tx, validator);
803
+ if (!outcome.allPassed) {
804
+ throw new Error('Invalid tx detected', {
805
+ cause: {
806
+ outcome
807
+ }
808
+ });
809
+ }
810
+ }
811
+ }));
520
812
  }
521
813
  /**
522
- * Create message validators for the given block number.
814
+ * Create message validators for the given block number and timestamp.
523
815
  *
524
816
  * Each validator is a pair of a validator and a severity.
525
817
  * If a validator fails, the peer is penalized with the severity of the validator.
526
818
  *
527
- * @param blockNumber - The block number to create validators for.
819
+ * @param currentBlockNumber - The current synced block number.
820
+ * @param nextSlotTimestamp - The timestamp of the next slot (used to validate txs are not expired).
528
821
  * @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
- };
822
+ */ async createMessageValidators(currentBlockNumber, nextSlotTimestamp) {
823
+ const gasFees = await this.getGasFees(currentBlockNumber);
824
+ const allowedInSetup = this.config.txPublicSetupAllowList ?? await getDefaultAllowedSetupFunctions();
825
+ const blockNumberInWhichTheTxIsConsideredToBeIncluded = currentBlockNumber + 1;
826
+ return createTxMessageValidators(nextSlotTimestamp, blockNumberInWhichTheTxIsConsideredToBeIncluded, this.worldStateSynchronizer, gasFees, this.config.l1ChainId, this.config.rollupVersion, protocolContractsHash, this.archiver, this.proofVerifier, !this.config.disableTransactions, allowedInSetup);
554
827
  }
555
828
  /**
556
829
  * Run validations on a tx.
@@ -562,29 +835,32 @@ import { ReqResp } from '../reqresp/reqresp.js';
562
835
  const { result } = await validator.validateTx(tx);
563
836
  return {
564
837
  name,
565
- isValid: result === 'valid',
838
+ isValid: result !== 'invalid',
566
839
  severity
567
840
  };
568
841
  });
569
842
  // 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;
843
+ const allValidations = await Promise.all(validationPromises);
844
+ const failed = allValidations.find((x)=>!x.isValid);
845
+ if (failed) {
846
+ return {
847
+ allPassed: false,
848
+ failure: {
849
+ isValid: {
850
+ result: 'invalid',
851
+ reason: [
852
+ 'Failed validation'
853
+ ]
854
+ },
855
+ name: failed.name,
856
+ severity: failed.severity
857
+ }
858
+ };
859
+ } else {
860
+ return {
861
+ allPassed: true
862
+ };
863
+ }
588
864
  }
589
865
  /**
590
866
  * Handle a double spend failure.
@@ -634,6 +910,7 @@ import { ReqResp } from '../reqresp/reqresp.js';
634
910
  */ async validateBlockProposal(peerId, block) {
635
911
  const severity = await this.blockProposalValidator.validate(block);
636
912
  if (severity) {
913
+ this.logger.debug(`Penalizing peer ${peerId} for block proposal validation failure`);
637
914
  this.peerManager.penalizePeer(peerId, severity);
638
915
  return false;
639
916
  }
@@ -642,13 +919,16 @@ import { ReqResp } from '../reqresp/reqresp.js';
642
919
  getPeerScore(peerId) {
643
920
  return this.node.services.pubsub.score.score(peerId.toString());
644
921
  }
922
+ handleAuthRequestFromPeer(authRequest, peerId) {
923
+ return this.peerManager.handleAuthRequestFromPeer(authRequest, peerId);
924
+ }
645
925
  async sendToPeers(message) {
646
926
  const parent = message.constructor;
647
927
  const identifier = await message.p2pMessageIdentifier().then((i)=>i.toString());
648
928
  this.logger.trace(`Sending message ${identifier}`, {
649
929
  p2pMessageIdentifier: identifier
650
930
  });
651
- const recipientsNum = await this.publishToTopic(parent.p2pTopic, message.toBuffer());
931
+ const recipientsNum = await this.publishToTopic(this.topicStrings[parent.p2pTopic], message);
652
932
  this.logger.debug(`Sent message ${identifier} to ${recipientsNum} peers`, {
653
933
  p2pMessageIdentifier: identifier,
654
934
  sourcePeer: this.node.peerId.toString()
@@ -673,7 +953,6 @@ import { ReqResp } from '../reqresp/reqresp.js';
673
953
  }
674
954
  _ts_decorate([
675
955
  trackSpan('Libp2pService.processValidBlockProposal', async (block)=>({
676
- [Attributes.BLOCK_NUMBER]: block.blockNumber.toNumber(),
677
956
  [Attributes.SLOT_NUMBER]: block.slotNumber.toNumber(),
678
957
  [Attributes.BLOCK_ARCHIVE]: block.archive.toString(),
679
958
  [Attributes.P2P_ID]: await block.p2pMessageIdentifier().then((i)=>i.toString())
@@ -681,32 +960,35 @@ _ts_decorate([
681
960
  ], LibP2PService.prototype, "processValidBlockProposal", null);
682
961
  _ts_decorate([
683
962
  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(),
963
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
686
964
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
687
965
  [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
688
966
  }))
689
967
  ], LibP2PService.prototype, "broadcastAttestation", null);
968
+ _ts_decorate([
969
+ trackSpan('Libp2pService.validateRequestedBlockTxs', (request)=>({
970
+ [Attributes.BLOCK_HASH]: request.blockHash.toString()
971
+ }))
972
+ ], LibP2PService.prototype, "validateRequestedBlockTxs", null);
690
973
  _ts_decorate([
691
974
  trackSpan('Libp2pService.validateRequestedTx', (requestedTxHash, _responseTx)=>({
692
975
  [Attributes.TX_HASH]: requestedTxHash.toString()
693
976
  }))
694
- ], LibP2PService.prototype, "validateRequestedTx", null);
977
+ ], LibP2PService.prototype, "validateRequestedTxs", null);
695
978
  _ts_decorate([
696
- trackSpan('Libp2pService.validatePropagatedTx', async (tx)=>({
697
- [Attributes.TX_HASH]: (await tx.getTxHash()).toString()
979
+ trackSpan('Libp2pService.validatePropagatedTx', (tx)=>({
980
+ [Attributes.TX_HASH]: tx.getTxHash().toString()
698
981
  }))
699
982
  ], LibP2PService.prototype, "validatePropagatedTx", null);
700
983
  _ts_decorate([
701
984
  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(),
985
+ [Attributes.SLOT_NUMBER]: attestation.payload.header.slotNumber.toNumber(),
704
986
  [Attributes.BLOCK_ARCHIVE]: attestation.archive.toString(),
705
987
  [Attributes.P2P_ID]: await attestation.p2pMessageIdentifier().then((i)=>i.toString())
706
988
  }))
707
989
  ], LibP2PService.prototype, "validateAttestation", null);
708
990
  _ts_decorate([
709
991
  trackSpan('Libp2pService.validateBlockProposal', (_peerId, block)=>({
710
- [Attributes.SLOT_NUMBER]: block.payload.header.globalVariables.slotNumber.toString()
992
+ [Attributes.SLOT_NUMBER]: block.payload.header.slotNumber.toString()
711
993
  }))
712
994
  ], LibP2PService.prototype, "validateBlockProposal", null);