@aztec/p2p 0.0.0-test.1 → 0.0.1-commit.5476d83

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 (385) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +1 -1
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +22 -9
  4. package/dest/client/factory.d.ts +14 -4
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +60 -24
  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 +157 -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 +72 -187
  14. package/dest/client/p2p_client.d.ts.map +1 -1
  15. package/dest/client/p2p_client.js +373 -177
  16. package/dest/config.d.ts +151 -125
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +183 -34
  19. package/dest/enr/generate-enr.d.ts +11 -3
  20. package/dest/enr/generate-enr.d.ts.map +1 -1
  21. package/dest/enr/generate-enr.js +27 -5
  22. package/dest/enr/index.d.ts +1 -1
  23. package/dest/errors/attestation-pool.error.d.ts +7 -0
  24. package/dest/errors/attestation-pool.error.d.ts.map +1 -0
  25. package/dest/errors/attestation-pool.error.js +12 -0
  26. package/dest/errors/reqresp.error.d.ts +1 -1
  27. package/dest/errors/reqresp.error.d.ts.map +1 -1
  28. package/dest/index.d.ts +4 -1
  29. package/dest/index.d.ts.map +1 -1
  30. package/dest/index.js +2 -0
  31. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +68 -8
  32. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  33. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +1 -1
  34. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  35. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +214 -63
  36. package/dest/mem_pools/attestation_pool/index.d.ts +1 -1
  37. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +21 -6
  38. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  39. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +126 -25
  40. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +19 -6
  41. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  42. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +111 -21
  43. package/dest/mem_pools/attestation_pool/mocks.d.ts +225 -5
  44. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  45. package/dest/mem_pools/attestation_pool/mocks.js +9 -15
  46. package/dest/mem_pools/index.d.ts +1 -1
  47. package/dest/mem_pools/instrumentation.d.ts +10 -12
  48. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  49. package/dest/mem_pools/instrumentation.js +35 -38
  50. package/dest/mem_pools/interface.d.ts +1 -1
  51. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +62 -13
  52. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  53. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +469 -97
  54. package/dest/mem_pools/tx_pool/index.d.ts +1 -1
  55. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +34 -10
  56. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  57. package/dest/mem_pools/tx_pool/memory_tx_pool.js +133 -36
  58. package/dest/mem_pools/tx_pool/priority.d.ts +1 -1
  59. package/dest/mem_pools/tx_pool/priority.js +1 -1
  60. package/dest/mem_pools/tx_pool/tx_pool.d.ts +65 -9
  61. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  62. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +1 -1
  63. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  64. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +264 -39
  65. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +4 -2
  66. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  67. package/dest/msg_validators/attestation_validator/attestation_validator.js +45 -9
  68. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +20 -0
  69. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -0
  70. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +67 -0
  71. package/dest/msg_validators/attestation_validator/index.d.ts +2 -1
  72. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -1
  73. package/dest/msg_validators/attestation_validator/index.js +1 -0
  74. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +6 -2
  75. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -1
  76. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +73 -12
  77. package/dest/msg_validators/block_proposal_validator/index.d.ts +1 -1
  78. package/dest/msg_validators/index.d.ts +1 -1
  79. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts +10 -0
  80. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.d.ts.map +1 -0
  81. package/dest/msg_validators/msg_seen_validator/msg_seen_validator.js +36 -0
  82. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +1 -1
  83. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -1
  84. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts +3 -0
  85. package/dest/msg_validators/tx_validator/allowed_public_setup.d.ts.map +1 -0
  86. package/dest/msg_validators/tx_validator/allowed_public_setup.js +27 -0
  87. package/dest/msg_validators/tx_validator/archive_cache.d.ts +14 -0
  88. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -0
  89. package/dest/msg_validators/tx_validator/archive_cache.js +22 -0
  90. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +1 -1
  91. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  92. package/dest/msg_validators/tx_validator/block_header_validator.js +4 -4
  93. package/dest/msg_validators/tx_validator/data_validator.d.ts +1 -1
  94. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  95. package/dest/msg_validators/tx_validator/data_validator.js +56 -86
  96. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +1 -3
  97. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  98. package/dest/msg_validators/tx_validator/double_spend_validator.js +21 -27
  99. package/dest/msg_validators/tx_validator/factory.d.ts +15 -0
  100. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -0
  101. package/dest/msg_validators/tx_validator/factory.js +74 -0
  102. package/dest/msg_validators/tx_validator/gas_validator.d.ts +11 -0
  103. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -0
  104. package/dest/msg_validators/tx_validator/gas_validator.js +115 -0
  105. package/dest/msg_validators/tx_validator/index.d.ts +8 -1
  106. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  107. package/dest/msg_validators/tx_validator/index.js +7 -0
  108. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +8 -4
  109. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  110. package/dest/msg_validators/tx_validator/metadata_validator.js +39 -20
  111. package/dest/msg_validators/tx_validator/phases_validator.d.ts +14 -0
  112. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -0
  113. package/dest/msg_validators/tx_validator/phases_validator.js +93 -0
  114. package/dest/msg_validators/tx_validator/test_utils.d.ts +17 -0
  115. package/dest/msg_validators/tx_validator/test_utils.d.ts.map +1 -0
  116. package/dest/msg_validators/tx_validator/test_utils.js +22 -0
  117. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +12 -0
  118. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -0
  119. package/dest/msg_validators/tx_validator/timestamp_validator.js +32 -0
  120. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +8 -0
  121. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -0
  122. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +24 -0
  123. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +1 -1
  124. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  125. package/dest/msg_validators/tx_validator/tx_proof_validator.js +6 -5
  126. package/dest/services/data_store.d.ts +1 -1
  127. package/dest/services/data_store.d.ts.map +1 -1
  128. package/dest/services/discv5/discV5_service.d.ts +10 -9
  129. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  130. package/dest/services/discv5/discV5_service.js +63 -36
  131. package/dest/services/dummy_service.d.ts +50 -11
  132. package/dest/services/dummy_service.d.ts.map +1 -1
  133. package/dest/services/dummy_service.js +88 -5
  134. package/dest/services/encoding.d.ts +26 -7
  135. package/dest/services/encoding.d.ts.map +1 -1
  136. package/dest/services/encoding.js +73 -5
  137. package/dest/services/gossipsub/scoring.d.ts +1 -1
  138. package/dest/services/index.d.ts +5 -1
  139. package/dest/services/index.d.ts.map +1 -1
  140. package/dest/services/index.js +4 -0
  141. package/dest/services/libp2p/instrumentation.d.ts +20 -0
  142. package/dest/services/libp2p/instrumentation.d.ts.map +1 -0
  143. package/dest/services/libp2p/instrumentation.js +164 -0
  144. package/dest/services/libp2p/libp2p_service.d.ts +78 -89
  145. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  146. package/dest/services/libp2p/libp2p_service.js +698 -246
  147. package/dest/services/peer-manager/interface.d.ts +23 -0
  148. package/dest/services/peer-manager/interface.d.ts.map +1 -0
  149. package/dest/services/peer-manager/interface.js +1 -0
  150. package/dest/services/peer-manager/metrics.d.ts +6 -2
  151. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  152. package/dest/services/peer-manager/metrics.js +22 -2
  153. package/dest/services/peer-manager/peer_manager.d.ts +102 -22
  154. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  155. package/dest/services/peer-manager/peer_manager.js +549 -72
  156. package/dest/services/peer-manager/peer_scoring.d.ts +7 -2
  157. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  158. package/dest/services/peer-manager/peer_scoring.js +40 -2
  159. package/dest/services/reqresp/config.d.ts +11 -9
  160. package/dest/services/reqresp/config.d.ts.map +1 -1
  161. package/dest/services/reqresp/config.js +18 -4
  162. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +2 -2
  163. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  164. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +10 -6
  165. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +31 -17
  166. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  167. package/dest/services/reqresp/connection-sampler/connection_sampler.js +142 -84
  168. package/dest/services/reqresp/index.d.ts +3 -2
  169. package/dest/services/reqresp/index.d.ts.map +1 -1
  170. package/dest/services/reqresp/index.js +2 -1
  171. package/dest/services/reqresp/interface.d.ts +73 -24
  172. package/dest/services/reqresp/interface.d.ts.map +1 -1
  173. package/dest/services/reqresp/interface.js +45 -26
  174. package/dest/services/reqresp/metrics.d.ts +1 -1
  175. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  176. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  177. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  178. package/dest/services/reqresp/protocols/auth.js +71 -0
  179. package/dest/services/reqresp/protocols/block.d.ts +6 -1
  180. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  181. package/dest/services/reqresp/protocols/block.js +28 -5
  182. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
  183. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  184. package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
  185. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
  186. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  187. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
  188. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +47 -0
  189. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  190. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
  191. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  192. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  193. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  194. package/dest/services/reqresp/protocols/goodbye.d.ts +3 -5
  195. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -1
  196. package/dest/services/reqresp/protocols/goodbye.js +7 -7
  197. package/dest/services/reqresp/protocols/index.d.ts +3 -1
  198. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  199. package/dest/services/reqresp/protocols/index.js +2 -0
  200. package/dest/services/reqresp/protocols/ping.d.ts +1 -3
  201. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -1
  202. package/dest/services/reqresp/protocols/status.d.ts +39 -7
  203. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  204. package/dest/services/reqresp/protocols/status.js +72 -5
  205. package/dest/services/reqresp/protocols/tx.d.ts +13 -2
  206. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  207. package/dest/services/reqresp/protocols/tx.js +34 -6
  208. package/dest/services/reqresp/rate-limiter/index.d.ts +1 -1
  209. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +6 -4
  210. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -1
  211. package/dest/services/reqresp/rate-limiter/rate_limiter.js +10 -2
  212. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +1 -1
  213. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  214. package/dest/services/reqresp/rate-limiter/rate_limits.js +21 -1
  215. package/dest/services/reqresp/reqresp.d.ts +24 -66
  216. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  217. package/dest/services/reqresp/reqresp.js +298 -207
  218. package/dest/services/reqresp/status.d.ts +10 -4
  219. package/dest/services/reqresp/status.d.ts.map +1 -1
  220. package/dest/services/reqresp/status.js +9 -2
  221. package/dest/services/service.d.ts +23 -19
  222. package/dest/services/service.d.ts.map +1 -1
  223. package/dest/services/tx_collection/config.d.ts +25 -0
  224. package/dest/services/tx_collection/config.d.ts.map +1 -0
  225. package/dest/services/tx_collection/config.js +58 -0
  226. package/dest/services/tx_collection/fast_tx_collection.d.ts +50 -0
  227. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
  228. package/dest/services/tx_collection/fast_tx_collection.js +300 -0
  229. package/dest/services/tx_collection/index.d.ts +3 -0
  230. package/dest/services/tx_collection/index.d.ts.map +1 -0
  231. package/dest/services/tx_collection/index.js +2 -0
  232. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  233. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  234. package/dest/services/tx_collection/instrumentation.js +34 -0
  235. package/dest/services/tx_collection/slow_tx_collection.d.ts +52 -0
  236. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
  237. package/dest/services/tx_collection/slow_tx_collection.js +177 -0
  238. package/dest/services/tx_collection/tx_collection.d.ts +109 -0
  239. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  240. package/dest/services/tx_collection/tx_collection.js +128 -0
  241. package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
  242. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  243. package/dest/services/tx_collection/tx_collection_sink.js +111 -0
  244. package/dest/services/tx_collection/tx_source.d.ts +18 -0
  245. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  246. package/dest/services/tx_collection/tx_source.js +31 -0
  247. package/dest/services/tx_provider.d.ts +49 -0
  248. package/dest/services/tx_provider.d.ts.map +1 -0
  249. package/dest/services/tx_provider.js +210 -0
  250. package/dest/services/tx_provider_instrumentation.d.ts +13 -0
  251. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  252. package/dest/services/tx_provider_instrumentation.js +34 -0
  253. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +1 -1
  254. package/dest/test-helpers/get-ports.d.ts +1 -1
  255. package/dest/test-helpers/get-ports.d.ts.map +1 -1
  256. package/dest/test-helpers/index.d.ts +2 -1
  257. package/dest/test-helpers/index.d.ts.map +1 -1
  258. package/dest/test-helpers/index.js +1 -0
  259. package/dest/test-helpers/make-enrs.d.ts +1 -1
  260. package/dest/test-helpers/make-enrs.d.ts.map +1 -1
  261. package/dest/test-helpers/make-enrs.js +4 -5
  262. package/dest/test-helpers/make-test-p2p-clients.d.ts +33 -5
  263. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  264. package/dest/test-helpers/make-test-p2p-clients.js +86 -16
  265. package/dest/test-helpers/mock-pubsub.d.ts +59 -0
  266. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -0
  267. package/dest/test-helpers/mock-pubsub.js +130 -0
  268. package/dest/test-helpers/mock-tx-helpers.d.ts +12 -0
  269. package/dest/test-helpers/mock-tx-helpers.d.ts.map +1 -0
  270. package/dest/test-helpers/mock-tx-helpers.js +19 -0
  271. package/dest/test-helpers/reqresp-nodes.d.ts +15 -11
  272. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  273. package/dest/test-helpers/reqresp-nodes.js +62 -28
  274. package/dest/testbench/p2p_client_testbench_worker.d.ts +1 -1
  275. package/dest/testbench/p2p_client_testbench_worker.js +103 -29
  276. package/dest/testbench/parse_log_file.d.ts +1 -1
  277. package/dest/testbench/parse_log_file.js +4 -4
  278. package/dest/testbench/testbench.d.ts +1 -1
  279. package/dest/testbench/testbench.js +4 -4
  280. package/dest/testbench/worker_client_manager.d.ts +1 -6
  281. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  282. package/dest/testbench/worker_client_manager.js +11 -19
  283. package/dest/types/index.d.ts +4 -2
  284. package/dest/types/index.d.ts.map +1 -1
  285. package/dest/types/index.js +2 -0
  286. package/dest/util.d.ts +24 -16
  287. package/dest/util.d.ts.map +1 -1
  288. package/dest/util.js +75 -69
  289. package/dest/versioning.d.ts +4 -4
  290. package/dest/versioning.d.ts.map +1 -1
  291. package/dest/versioning.js +8 -3
  292. package/package.json +32 -27
  293. package/src/bootstrap/bootstrap.ts +27 -11
  294. package/src/client/factory.ts +136 -45
  295. package/src/client/index.ts +1 -0
  296. package/src/client/interface.ts +198 -0
  297. package/src/client/p2p_client.ts +469 -330
  298. package/src/config.ts +305 -134
  299. package/src/enr/generate-enr.ts +39 -6
  300. package/src/errors/attestation-pool.error.ts +13 -0
  301. package/src/index.ts +4 -0
  302. package/src/mem_pools/attestation_pool/attestation_pool.ts +75 -7
  303. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +264 -65
  304. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +173 -34
  305. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +156 -30
  306. package/src/mem_pools/attestation_pool/mocks.ts +11 -10
  307. package/src/mem_pools/instrumentation.ts +43 -44
  308. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +549 -108
  309. package/src/mem_pools/tx_pool/memory_tx_pool.ts +153 -44
  310. package/src/mem_pools/tx_pool/priority.ts +1 -1
  311. package/src/mem_pools/tx_pool/tx_pool.ts +67 -8
  312. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +217 -34
  313. package/src/msg_validators/attestation_validator/attestation_validator.ts +54 -11
  314. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +91 -0
  315. package/src/msg_validators/attestation_validator/index.ts +1 -0
  316. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +82 -14
  317. package/src/msg_validators/msg_seen_validator/msg_seen_validator.ts +36 -0
  318. package/src/msg_validators/tx_validator/allowed_public_setup.ts +35 -0
  319. package/src/msg_validators/tx_validator/archive_cache.ts +28 -0
  320. package/src/msg_validators/tx_validator/block_header_validator.ts +4 -4
  321. package/src/msg_validators/tx_validator/data_validator.ts +81 -69
  322. package/src/msg_validators/tx_validator/double_spend_validator.ts +19 -17
  323. package/src/msg_validators/tx_validator/factory.ts +109 -0
  324. package/src/msg_validators/tx_validator/gas_validator.ts +134 -0
  325. package/src/msg_validators/tx_validator/index.ts +7 -0
  326. package/src/msg_validators/tx_validator/metadata_validator.ts +58 -21
  327. package/src/msg_validators/tx_validator/phases_validator.ts +116 -0
  328. package/src/msg_validators/tx_validator/test_utils.ts +43 -0
  329. package/src/msg_validators/tx_validator/timestamp_validator.ts +46 -0
  330. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +17 -0
  331. package/src/msg_validators/tx_validator/tx_proof_validator.ts +6 -5
  332. package/src/services/discv5/discV5_service.ts +84 -38
  333. package/src/services/dummy_service.ts +147 -9
  334. package/src/services/encoding.ts +80 -5
  335. package/src/services/index.ts +4 -0
  336. package/src/services/libp2p/instrumentation.ts +167 -0
  337. package/src/services/libp2p/libp2p_service.ts +866 -294
  338. package/src/services/peer-manager/interface.ts +29 -0
  339. package/src/services/peer-manager/metrics.ts +26 -1
  340. package/src/services/peer-manager/peer_manager.ts +654 -78
  341. package/src/services/peer-manager/peer_scoring.ts +46 -3
  342. package/src/services/reqresp/config.ts +26 -9
  343. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +12 -6
  344. package/src/services/reqresp/connection-sampler/connection_sampler.ts +148 -95
  345. package/src/services/reqresp/index.ts +2 -0
  346. package/src/services/reqresp/interface.ts +91 -36
  347. package/src/services/reqresp/metrics.ts +4 -1
  348. package/src/services/reqresp/protocols/auth.ts +83 -0
  349. package/src/services/reqresp/protocols/block.ts +24 -3
  350. package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
  351. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
  352. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
  353. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  354. package/src/services/reqresp/protocols/goodbye.ts +9 -7
  355. package/src/services/reqresp/protocols/index.ts +2 -0
  356. package/src/services/reqresp/protocols/status.ts +117 -5
  357. package/src/services/reqresp/protocols/tx.ts +35 -6
  358. package/src/services/reqresp/rate-limiter/rate_limiter.ts +12 -3
  359. package/src/services/reqresp/rate-limiter/rate_limits.ts +21 -1
  360. package/src/services/reqresp/reqresp.ts +387 -256
  361. package/src/services/reqresp/status.ts +12 -3
  362. package/src/services/service.ts +45 -21
  363. package/src/services/tx_collection/config.ts +84 -0
  364. package/src/services/tx_collection/fast_tx_collection.ts +340 -0
  365. package/src/services/tx_collection/index.ts +2 -0
  366. package/src/services/tx_collection/instrumentation.ts +43 -0
  367. package/src/services/tx_collection/slow_tx_collection.ts +233 -0
  368. package/src/services/tx_collection/tx_collection.ts +215 -0
  369. package/src/services/tx_collection/tx_collection_sink.ts +129 -0
  370. package/src/services/tx_collection/tx_source.ts +37 -0
  371. package/src/services/tx_provider.ts +216 -0
  372. package/src/services/tx_provider_instrumentation.ts +44 -0
  373. package/src/test-helpers/index.ts +1 -0
  374. package/src/test-helpers/make-enrs.ts +4 -5
  375. package/src/test-helpers/make-test-p2p-clients.ts +111 -21
  376. package/src/test-helpers/mock-pubsub.ts +188 -0
  377. package/src/test-helpers/mock-tx-helpers.ts +24 -0
  378. package/src/test-helpers/reqresp-nodes.ts +86 -35
  379. package/src/testbench/p2p_client_testbench_worker.ts +151 -25
  380. package/src/testbench/parse_log_file.ts +4 -4
  381. package/src/testbench/testbench.ts +4 -4
  382. package/src/testbench/worker_client_manager.ts +17 -23
  383. package/src/types/index.ts +2 -0
  384. package/src/util.ts +105 -91
  385. package/src/versioning.ts +11 -4
@@ -5,16 +5,19 @@ function _ts_decorate(decorators, target, key, desc) {
5
5
  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;
6
6
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
7
  }
8
+ import { compactArray } from '@aztec/foundation/collection';
9
+ import { AbortError, TimeoutError } from '@aztec/foundation/error';
8
10
  import { createLogger } from '@aztec/foundation/log';
9
11
  import { executeTimeout } from '@aztec/foundation/timer';
10
12
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
11
13
  import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
12
- import { pipe } from 'it-pipe';
14
+ import { pipeline } from 'node:stream/promises';
13
15
  import { CollectiveReqRespTimeoutError, IndividualReqRespTimeoutError, InvalidResponseError } from '../../errors/reqresp.error.js';
14
16
  import { SnappyTransform } from '../encoding.js';
17
+ import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS } from './config.js';
15
18
  import { BatchConnectionSampler } from './connection-sampler/batch_connection_sampler.js';
16
- import { ConnectionSampler } from './connection-sampler/connection_sampler.js';
17
- import { DEFAULT_SUB_PROTOCOL_HANDLERS, DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, subProtocolMap } from './interface.js';
19
+ import { ConnectionSampler, RandomSampler } from './connection-sampler/connection_sampler.js';
20
+ import { DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, responseFromBuffer } from './interface.js';
18
21
  import { ReqRespMetrics } from './metrics.js';
19
22
  import { RateLimitStatus, RequestResponseRateLimiter, prettyPrintRateLimitStatus } from './rate-limiter/rate_limiter.js';
20
23
  import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqRespStatus } from './status.js';
@@ -35,43 +38,58 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
35
38
  libp2p;
36
39
  peerScoring;
37
40
  logger;
38
- overallRequestTimeoutMs;
39
41
  individualRequestTimeoutMs;
40
- // Warning, if the `start` function is not called as the parent class constructor, then the default sub protocol handlers will be used ( not good )
42
+ dialTimeoutMs;
41
43
  subProtocolHandlers;
42
44
  subProtocolValidators;
43
45
  connectionSampler;
44
46
  rateLimiter;
45
47
  snappyTransform;
46
48
  metrics;
47
- constructor(config, libp2p, peerScoring, telemetryClient = getTelemetryClient()){
49
+ constructor(config, libp2p, peerScoring, logger = createLogger('p2p:reqresp'), rateLimits = {}, telemetryClient = getTelemetryClient()){
48
50
  this.libp2p = libp2p;
49
51
  this.peerScoring = peerScoring;
50
- this.subProtocolHandlers = DEFAULT_SUB_PROTOCOL_HANDLERS;
51
- this.subProtocolValidators = DEFAULT_SUB_PROTOCOL_VALIDATORS;
52
- this.logger = createLogger('p2p:reqresp');
53
- this.overallRequestTimeoutMs = config.overallRequestTimeoutMs;
54
- this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
55
- this.rateLimiter = new RequestResponseRateLimiter(peerScoring);
52
+ this.logger = logger;
53
+ this.individualRequestTimeoutMs = DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS;
54
+ this.dialTimeoutMs = DEFAULT_REQRESP_DIAL_TIMEOUT_MS;
55
+ this.subProtocolHandlers = {};
56
+ this.subProtocolValidators = {};
57
+ this.updateConfig(config);
58
+ this.rateLimiter = new RequestResponseRateLimiter(peerScoring, rateLimits);
56
59
  // Connection sampler is used to sample our connected peers
57
- this.connectionSampler = new ConnectionSampler(libp2p);
60
+ this.connectionSampler = new ConnectionSampler(libp2p, new RandomSampler(), createLogger(`${logger.module}:connection-sampler`), config);
58
61
  this.snappyTransform = new SnappyTransform();
59
62
  this.metrics = new ReqRespMetrics(telemetryClient);
60
63
  }
64
+ updateConfig(config) {
65
+ if (typeof config.individualRequestTimeoutMs === 'number') {
66
+ this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
67
+ }
68
+ if (typeof config.dialTimeoutMs === 'number') {
69
+ this.dialTimeoutMs = config.dialTimeoutMs;
70
+ }
71
+ }
61
72
  get tracer() {
62
73
  return this.metrics.tracer;
63
74
  }
64
75
  /**
65
76
  * Start the reqresp service
66
77
  */ async start(subProtocolHandlers, subProtocolValidators) {
67
- this.subProtocolHandlers = subProtocolHandlers;
68
- this.subProtocolValidators = subProtocolValidators;
78
+ Object.assign(this.subProtocolHandlers, subProtocolHandlers);
79
+ Object.assign(this.subProtocolValidators, subProtocolValidators);
69
80
  // Register all protocol handlers
70
- for (const subProtocol of Object.keys(this.subProtocolHandlers)){
81
+ for (const subProtocol of Object.keys(subProtocolHandlers)){
82
+ this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
71
83
  await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
72
84
  }
73
85
  this.rateLimiter.start();
74
86
  }
87
+ async addSubProtocol(subProtocol, handler, validator = DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol]) {
88
+ this.subProtocolHandlers[subProtocol] = handler;
89
+ this.subProtocolValidators[subProtocol] = validator;
90
+ this.logger.debug(`Registering handler for sub protocol ${subProtocol}`);
91
+ await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
92
+ }
75
93
  /**
76
94
  * Stop the reqresp service
77
95
  */ async stop() {
@@ -90,81 +108,6 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
90
108
  // NOTE: We assume libp2p instance is managed by the caller
91
109
  }
92
110
  /**
93
- * Send a request to peers, returns the first response
94
- *
95
- * @param subProtocol - The protocol being requested
96
- * @param request - The request to send
97
- * @returns - The response from the peer, otherwise undefined
98
- *
99
- * @description
100
- * This method attempts to send a request to all active peers using the specified sub-protocol.
101
- * It opens a stream with each peer, sends the request, and awaits a response.
102
- * If a valid response is received, it returns the response; otherwise, it continues to the next peer.
103
- * If no response is received from any peer, it returns undefined.
104
- *
105
- * The method performs the following steps:
106
- * - Sample a peer to send the request to.
107
- * - Opens a stream with the peer using the specified sub-protocol.
108
- *
109
- * When a response is received, it is validated using the given sub protocols response validator.
110
- * To see the interface for the response validator - see `interface.ts`
111
- *
112
- * Failing a response validation requests in a severe peer penalty, and will
113
- * prompt the node to continue to search to the next peer.
114
- * For example, a transaction request validator will check that the payload returned does in fact
115
- * match the txHash that was requested. A peer that fails this check an only be an extremely naughty peer.
116
- *
117
- * This entire operation is wrapped in an overall timeout, that is independent of the
118
- * peer it is requesting data from.
119
- *
120
- */ async sendRequest(subProtocol, request) {
121
- const responseValidator = this.subProtocolValidators[subProtocol];
122
- const requestBuffer = request.toBuffer();
123
- const requestFunction = async ()=>{
124
- // Attempt to ask all of our peers, but sampled in a random order
125
- // This function is wrapped in a timeout, so we will exit the loop if we have not received a response
126
- const numberOfPeers = this.libp2p.getPeers().length;
127
- if (numberOfPeers === 0) {
128
- this.logger.debug('No active peers to send requests to');
129
- return undefined;
130
- }
131
- const attemptedPeers = new Map();
132
- for(let i = 0; i < numberOfPeers; i++){
133
- // Sample a peer to make a request to
134
- const peer = this.connectionSampler.getPeer(attemptedPeers);
135
- this.logger.trace(`Attempting to send request to peer: ${peer?.toString()}`);
136
- if (!peer) {
137
- this.logger.debug('No peers available to send requests to');
138
- return undefined;
139
- }
140
- attemptedPeers.set(peer.toString(), true);
141
- this.logger.trace(`Sending request to peer: ${peer.toString()}`);
142
- const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffer);
143
- if (response && response.status !== ReqRespStatus.SUCCESS) {
144
- this.logger.debug(`Request to peer ${peer.toString()} failed with status ${prettyPrintReqRespStatus(response.status)}`);
145
- continue;
146
- }
147
- // If we get a response, return it, otherwise we iterate onto the next peer
148
- // We do not consider it a success if we have an empty buffer
149
- if (response && response.data.length > 0) {
150
- const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
151
- // The response validator handles peer punishment within
152
- const isValid = await responseValidator(request, object, peer);
153
- if (!isValid) {
154
- throw new InvalidResponseError();
155
- }
156
- return object;
157
- }
158
- }
159
- };
160
- try {
161
- return await executeTimeout(requestFunction, this.overallRequestTimeoutMs, ()=>new CollectiveReqRespTimeoutError());
162
- } catch (e) {
163
- this.logger.debug(`${e.message} | subProtocol: ${subProtocol}`);
164
- return undefined;
165
- }
166
- }
167
- /**
168
111
  * Request multiple messages over the same sub protocol, balancing the requests across peers.
169
112
  *
170
113
  * @devnote
@@ -185,17 +128,19 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
185
128
  * @returns
186
129
  *
187
130
  * @throws {CollectiveReqRespTimeoutError} - If the request batch exceeds the specified timeout (`timeoutMs`).
188
- */ async sendBatchRequest(subProtocol, requests, timeoutMs = 10000, maxPeers = Math.min(10, requests.length), maxRetryAttempts = 3) {
189
- const responseValidator = this.subProtocolValidators[subProtocol];
131
+ */ async sendBatchRequest(subProtocol, requests, pinnedPeer, timeoutMs = 10000, maxPeers = Math.max(10, Math.ceil(requests.length / 3)), maxRetryAttempts = 3) {
132
+ const responseValidator = this.subProtocolValidators[subProtocol] ?? DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol];
190
133
  const responses = new Array(requests.length);
191
134
  const requestBuffers = requests.map((req)=>req.toBuffer());
192
- const requestFunction = async ()=>{
135
+ const requestFunction = async (signal)=>{
193
136
  // Track which requests still need to be processed
194
137
  const pendingRequestIndices = new Set(requestBuffers.map((_, i)=>i));
195
138
  // Create batch sampler with the total number of requests and max peers
196
- const batchSampler = new BatchConnectionSampler(this.connectionSampler, requests.length, maxPeers);
197
- if (batchSampler.activePeerCount === 0) {
198
- this.logger.debug('No active peers to send requests to');
139
+ const batchSampler = new BatchConnectionSampler(this.connectionSampler, requests.length, maxPeers, compactArray([
140
+ pinnedPeer
141
+ ]), createLogger(`${this.logger.module}:batch-connection-sampler`));
142
+ if (batchSampler.activePeerCount === 0 && !pinnedPeer) {
143
+ this.logger.warn('No active peers to send requests to');
199
144
  return [];
200
145
  }
201
146
  // This is where it gets fun
@@ -206,7 +151,9 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
206
151
  // We will continue to retry until we have processed all indices, or we have reached the max retry attempts
207
152
  let retryAttempts = 0;
208
153
  while(pendingRequestIndices.size > 0 && batchSampler.activePeerCount > 0 && retryAttempts < maxRetryAttempts){
209
- // Process requests in parallel for each available peer
154
+ if (signal.aborted) {
155
+ throw new AbortError('Batch request aborted');
156
+ }
210
157
  const requestBatches = new Map();
211
158
  // Group requests by peer
212
159
  for (const requestIndex of pendingRequestIndices){
@@ -214,10 +161,23 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
214
161
  if (!peer) {
215
162
  break;
216
163
  }
217
- if (!requestBatches.has(peer)) {
218
- requestBatches.set(peer, []);
164
+ const peerAsString = peer.toString();
165
+ if (!requestBatches.has(peerAsString)) {
166
+ requestBatches.set(peerAsString, {
167
+ peerId: peer,
168
+ indices: []
169
+ });
219
170
  }
220
- requestBatches.get(peer).push(requestIndex);
171
+ requestBatches.get(peerAsString).indices.push(requestIndex);
172
+ }
173
+ // If there is a pinned peer, we will always send every request to that peer
174
+ // We use the default limits for the subprotocol to avoid hitting the rate limiter
175
+ if (pinnedPeer) {
176
+ const limit = this.rateLimiter.getRateLimits(subProtocol).peerLimit.quotaCount;
177
+ requestBatches.set(pinnedPeer.toString(), {
178
+ peerId: pinnedPeer,
179
+ indices: Array.from(pendingRequestIndices.values()).slice(0, limit)
180
+ });
221
181
  }
222
182
  // Make parallel requests for each peer's batch
223
183
  // A batch entry will look something like this:
@@ -225,15 +185,16 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
225
185
  // PeerId1: [4, 5, 6, 7]
226
186
  // Peer Id 0 will send requests 0, 1, 2, 3 in serial
227
187
  // while simultaneously Peer Id 1 will send requests 4, 5, 6, 7 in serial
228
- const batchResults = await Promise.all(Array.from(requestBatches.entries()).map(async ([peer, indices])=>{
188
+ const batchResults = await Promise.all(Array.from(requestBatches.entries()).map(async ([peerAsString, { peerId: peer, indices }])=>{
229
189
  try {
230
190
  // Requests all going to the same peer are sent synchronously
231
191
  const peerResults = [];
232
192
  for (const index of indices){
193
+ this.logger.trace(`Sending request ${index} to peer ${peerAsString}`);
233
194
  const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffers[index]);
234
195
  // Check the status of the response buffer
235
- if (response && response.status !== ReqRespStatus.SUCCESS) {
236
- this.logger.debug(`Request to peer ${peer.toString()} failed with status ${prettyPrintReqRespStatus(response.status)}`);
196
+ if (response.status !== ReqRespStatus.SUCCESS) {
197
+ this.logger.debug(`Request to peer ${peerAsString} failed with status ${prettyPrintReqRespStatus(response.status)}`);
237
198
  // If we hit a rate limit or some failure, we remove the peer and return the results,
238
199
  // they will be split among remaining peers and the new sampled peer
239
200
  batchSampler.removePeerAndReplace(peer);
@@ -243,7 +204,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
243
204
  };
244
205
  }
245
206
  if (response && response.data.length > 0) {
246
- const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
207
+ const object = responseFromBuffer(subProtocol, response.data);
247
208
  const isValid = await responseValidator(requests[index], object, peer);
248
209
  if (isValid) {
249
210
  peerResults.push({
@@ -258,7 +219,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
258
219
  results: peerResults
259
220
  };
260
221
  } catch (error) {
261
- this.logger.debug(`Failed batch request to peer ${peer.toString()}:`, error);
222
+ this.logger.debug(`Failed batch request to peer ${peerAsString}:`, error);
262
223
  batchSampler.removePeerAndReplace(peer);
263
224
  return {
264
225
  peer,
@@ -299,6 +260,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
299
260
  * @param peerId - The peer to send the request to
300
261
  * @param subProtocol - The protocol to use to request
301
262
  * @param payload - The payload to send
263
+ * @param dialTimeout - If establishing a stream takes longer than this an error will be thrown
302
264
  * @returns If the request is successful, the response is returned, otherwise undefined
303
265
  *
304
266
  * @description
@@ -312,24 +274,46 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
312
274
  *
313
275
  * If the stream is not closed by the dialled peer, and a timeout occurs, then
314
276
  * the stream is closed on the requester's end and sender (us) updates its peer score
315
- */ async sendRequestToPeer(peerId, subProtocol, payload) {
277
+ */ async sendRequestToPeer(peerId, subProtocol, payload, dialTimeout = this.dialTimeoutMs) {
316
278
  let stream;
317
279
  try {
318
280
  this.metrics.recordRequestSent(subProtocol);
319
- stream = await this.connectionSampler.dialProtocol(peerId, subProtocol);
320
- // Open the stream with a timeout
321
- const result = await executeTimeout(()=>pipe([
322
- payload
323
- ], stream, this.readMessage.bind(this)), this.individualRequestTimeoutMs, ()=>new IndividualReqRespTimeoutError());
324
- return result;
281
+ this.logger.trace(`Sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
282
+ stream = await this.connectionSampler.dialProtocol(peerId, subProtocol, dialTimeout);
283
+ this.logger.trace(`Opened stream ${stream.id} for sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
284
+ const timeoutErr = new IndividualReqRespTimeoutError();
285
+ const [_, resp] = await executeTimeout((signal)=>Promise.all([
286
+ pipeline([
287
+ payload
288
+ ], stream.sink, {
289
+ signal
290
+ }),
291
+ pipeline(stream.source, this.readMessage.bind(this), {
292
+ signal
293
+ })
294
+ ]), this.individualRequestTimeoutMs, ()=>timeoutErr);
295
+ return resp;
325
296
  } catch (e) {
297
+ // On error we immediately abort the stream, this is preferred way,
298
+ // because it signals to the sender that error happened, whereas
299
+ // closing the stream only closes our side and is much slower
300
+ if (stream) {
301
+ stream.abort(e);
302
+ }
326
303
  this.metrics.recordRequestError(subProtocol);
327
304
  this.handleResponseError(e, peerId, subProtocol);
305
+ // If there is an exception, we return an unknown response
306
+ this.logger.debug(`Error sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}: ${e}`);
307
+ return {
308
+ status: ReqRespStatus.FAILURE
309
+ };
328
310
  } finally{
329
311
  // Only close the stream if we created it
312
+ // Note even if we aborted the stream, calling close on it is ok, it's just a no-op
330
313
  if (stream) {
331
314
  try {
332
- await this.connectionSampler.close(stream.id);
315
+ this.logger.trace(`Closing stream ${stream.id} for request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
316
+ await this.connectionSampler.close(stream);
333
317
  } catch (closeError) {
334
318
  this.logger.error(`Error closing stream: ${closeError instanceof Error ? closeError.message : 'Unknown error'}`);
335
319
  }
@@ -346,75 +330,41 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
346
330
  * @param subProtocol - The sub protocol
347
331
  * @returns If the error is non pubishable, then undefined is returned, otherwise the peer is penalized
348
332
  */ handleResponseError(e, peerId, subProtocol) {
349
- const severity = this.categorizeError(e, peerId, subProtocol);
333
+ const severity = this.categorizeResponseError(e, peerId, subProtocol);
350
334
  if (severity) {
351
335
  this.peerScoring.penalizePeer(peerId, severity);
352
336
  }
353
337
  }
354
338
  /**
355
- * Categorize the error and log it.
356
- */ categorizeError(e, peerId, subProtocol) {
357
- // Non punishable errors - we do not expect a response for goodbye messages
358
- if (subProtocol === ReqRespSubProtocol.GOODBYE) {
359
- this.logger.debug('Error encountered on goodbye sub protocol, no penalty', {
360
- peerId: peerId.toString(),
361
- subProtocol
362
- });
363
- return undefined;
364
- }
365
- // We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
366
- const logTags = {
367
- peerId: peerId.toString(),
368
- subProtocol
369
- };
370
- if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
371
- this.logger.debug(`Non-punishable error: ${e.message} | peerId: ${peerId.toString()} | subProtocol: ${subProtocol}`, logTags);
372
- return undefined;
373
- }
374
- // Pubishable errors
375
- // Connection reset errors in the networking stack are punished with high severity
376
- // it just signals an unreliable peer
377
- // We assume that the requesting node has a functioning networking stack.
378
- if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
379
- this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
380
- return PeerErrorSeverity.HighToleranceError;
381
- }
382
- if (e?.code === 'ECONNREFUSED') {
383
- this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
384
- return PeerErrorSeverity.HighToleranceError;
385
- }
386
- // Timeout errors are punished with high tolerance, they can be due to a geogrpahically far away peer or an
387
- // overloaded peer
388
- if (e instanceof IndividualReqRespTimeoutError) {
389
- this.logger.debug(`Timeout error: ${e.message} | peerId: ${peerId.toString()} | subProtocol: ${subProtocol}`, logTags);
390
- return PeerErrorSeverity.HighToleranceError;
391
- }
392
- // Catch all error
393
- this.logger.error(`Unexpected error sending request to peer`, e, logTags);
394
- return PeerErrorSeverity.HighToleranceError;
395
- }
396
- /**
397
339
  * Read a message returned from a stream into a single buffer
398
340
  *
399
341
  * The message is split into two components
400
342
  * - The first chunk should contain a control byte, indicating the status of the response see `ReqRespStatus`
401
343
  * - The second chunk should contain the response data
402
344
  */ async readMessage(source) {
403
- let statusBuffer;
345
+ let status;
404
346
  const chunks = [];
405
347
  try {
406
348
  for await (const chunk of source){
407
- if (statusBuffer === undefined) {
408
- const firstChunkBuffer = chunk.subarray();
409
- statusBuffer = parseStatusChunk(firstChunkBuffer);
410
- } else {
349
+ const statusParsed = status !== undefined;
350
+ if (statusParsed) {
411
351
  chunks.push(chunk.subarray());
352
+ continue;
353
+ }
354
+ const firstChunkBuffer = chunk.subarray();
355
+ status = parseStatusChunk(firstChunkBuffer);
356
+ // In case status is not SUCCESS, we do not expect any data in the response
357
+ // we can return early
358
+ if (status !== ReqRespStatus.SUCCESS) {
359
+ return {
360
+ status
361
+ };
412
362
  }
413
363
  }
414
364
  const messageData = Buffer.concat(chunks);
415
- const message = this.snappyTransform.inboundTransformNoTopic(messageData);
365
+ const message = this.snappyTransform.inboundTransformData(messageData);
416
366
  return {
417
- status: statusBuffer ?? ReqRespStatus.UNKNOWN,
367
+ status: status ?? ReqRespStatus.UNKNOWN,
418
368
  data: message
419
369
  };
420
370
  } catch (e) {
@@ -424,8 +374,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
424
374
  status = e.status;
425
375
  }
426
376
  return {
427
- status,
428
- data: Buffer.from([])
377
+ status
429
378
  };
430
379
  }
431
380
  }
@@ -433,7 +382,8 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
433
382
  * Stream Handler
434
383
  * Reads the incoming stream, determines the protocol, then triggers the appropriate handler
435
384
  *
436
- * @param param0 - The incoming stream data
385
+ * @param protocol - The sub protocol to handle
386
+ * @param incomingStream - The incoming stream data containing the stream and connection
437
387
  *
438
388
  * @description
439
389
  * An individual stream handler will be bound to each sub protocol, and handles returning data back
@@ -444,56 +394,197 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
444
394
  *
445
395
  * We check rate limits for each peer, note the peer will be penalised within the rate limiter implementation
446
396
  * if they exceed their peer specific limits.
447
- */ async streamHandler(protocol, { stream, connection }) {
448
- this.metrics.recordRequestReceived(protocol);
397
+ */ async streamHandler(protocol, incomingStream) {
398
+ const { stream, connection } = incomingStream;
449
399
  try {
450
- // Store a reference to from this for the async generator
400
+ this.metrics.recordRequestReceived(protocol);
451
401
  const rateLimitStatus = this.rateLimiter.allow(protocol, connection.remotePeer);
452
- if (rateLimitStatus != RateLimitStatus.Allowed) {
453
- this.logger.warn(`Rate limit exceeded ${prettyPrintRateLimitStatus(rateLimitStatus)} for ${protocol} from ${connection.remotePeer}`);
402
+ if (rateLimitStatus !== RateLimitStatus.Allowed) {
403
+ this.logger.verbose(`Rate limit exceeded ${prettyPrintRateLimitStatus(rateLimitStatus)} for ${protocol} from ${connection.remotePeer}`);
454
404
  throw new ReqRespStatusError(ReqRespStatus.RATE_LIMIT_EXCEEDED);
455
405
  }
456
- const handler = this.subProtocolHandlers[protocol];
457
- const transform = this.snappyTransform;
458
- await pipe(stream, async function*(source) {
459
- for await (const chunkList of source){
460
- const msg = Buffer.from(chunkList.subarray());
461
- const response = await handler(connection.remotePeer, msg);
462
- if (protocol === ReqRespSubProtocol.GOODBYE) {
463
- // Don't respond
464
- await stream.close();
465
- return;
466
- }
467
- // Send success code first, then the response
468
- const successChunk = Buffer.from([
469
- ReqRespStatus.SUCCESS
470
- ]);
471
- yield new Uint8Array(successChunk);
472
- yield new Uint8Array(transform.outboundTransformNoTopic(response));
473
- }
474
- }, stream);
475
- } catch (e) {
476
- this.logger.warn('Reqresp Response error: ', e);
406
+ await this.processStream(protocol, incomingStream);
407
+ } catch (err) {
477
408
  this.metrics.recordResponseError(protocol);
478
- // If we receive a known error, we use the error status in the response chunk, otherwise we categorize as unknown
479
- let errorStatus = ReqRespStatus.UNKNOWN;
480
- if (e instanceof ReqRespStatusError) {
481
- errorStatus = e.status;
409
+ this.handleRequestError(err, connection.remotePeer, protocol);
410
+ if (err instanceof ReqRespStatusError) {
411
+ const errorSent = await this.trySendError(stream, connection.remotePeer, protocol, err.status);
412
+ const logMessage = errorSent ? 'Protocol error sent successfully.' : 'Stream already closed or poisoned, not sending error response.';
413
+ const isRateLimit = err.status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
414
+ const level = isRateLimit ? 'debug' : 'warn';
415
+ this.logger[level](logMessage + ` Status: ${ReqRespStatus[err.status]}`, {
416
+ protocol,
417
+ err,
418
+ errorStatus: err.status,
419
+ cause: err.cause ?? 'Cause unknown'
420
+ });
421
+ } else {
422
+ // In erroneous case we abort the stream, this will signal the peer that something went wrong
423
+ // and that this stream should be dropped
424
+ const isMessageToNotWarn = err instanceof Error && [
425
+ 'stream reset',
426
+ 'Cannot push value onto an ended pushable'
427
+ ].some((msg)=>err.message.includes(msg));
428
+ const level = isMessageToNotWarn ? 'debug' : 'warn';
429
+ this.logger[level]('Unknown stream error while handling the stream, aborting', {
430
+ protocol,
431
+ err
432
+ });
433
+ stream.abort(err);
482
434
  }
483
- const sendErrorChunk = this.sendErrorChunk(errorStatus);
484
- // Return and yield the response chunk
485
- await pipe(stream, async function*(_source) {
486
- yield* sendErrorChunk;
487
- }, stream);
488
435
  } finally{
436
+ //NOTE: This is idempotent action, so it's ok to call it even if stream was aborted
489
437
  await stream.close();
490
438
  }
491
439
  }
492
- async *sendErrorChunk(error) {
493
- const errorChunk = Buffer.from([
494
- error
495
- ]);
496
- yield new Uint8Array(errorChunk);
440
+ /**
441
+ * Reads incoming data from the stream, processes it according to the sub protocol,
442
+ * and puts response back into the stream.
443
+ *
444
+ * @param protocol - The sub protocol to use for processing the stream
445
+ * @param incomingStream - The incoming stream data containing the stream and connection
446
+ *
447
+ * */ async processStream(protocol, { stream, connection }) {
448
+ const handler = this.subProtocolHandlers[protocol];
449
+ if (!handler) {
450
+ throw new Error(`No handler defined for reqresp subprotocol ${protocol}`);
451
+ }
452
+ const snappy = this.snappyTransform;
453
+ const SUCCESS = Uint8Array.of(ReqRespStatus.SUCCESS);
454
+ await pipeline(stream.source, async function*(source) {
455
+ for await (const chunk of source){
456
+ const response = await handler(connection.remotePeer, chunk.subarray());
457
+ if (protocol === ReqRespSubProtocol.GOODBYE) {
458
+ // NOTE: The stream was already closed by Goodbye handler
459
+ // peerManager.goodbyeReceived(peerId, reason); will call libp2p.hangUp closing all active streams and connections
460
+ // Don't try to respond
461
+ return;
462
+ }
463
+ stream.metadata.written = true; // Mark the stream as written to;
464
+ yield SUCCESS;
465
+ yield snappy.outboundTransformData(response);
466
+ }
467
+ }, stream.sink);
468
+ }
469
+ /**
470
+ * Try to send error status to the peer. We say try, because the stream,
471
+ * might already be closed
472
+ * @param stream - The stream opened between us and the peer
473
+ * @param status - The error status to send back to the peer
474
+ * @returns true if error was sent successfully, otherwise false
475
+ *
476
+ */ async trySendError(stream, peerId, protocol, status) {
477
+ const canWriteToStream = // 'writing' is a bit weird naming, but it actually means that the stream is ready to write
478
+ // 'ready' means that stream ready to be opened for writing
479
+ stream.status === 'open' && (stream.writeStatus === 'writing' || stream.writeStatus === 'ready');
480
+ // Stream was already written to, we consider it poisoned, in a sense,
481
+ // that even if we write an error response, it will not be interpreted correctly by the peer
482
+ const streamPoisoned = stream.metadata.written === true;
483
+ const shouldWriteToStream = canWriteToStream && !streamPoisoned;
484
+ if (!shouldWriteToStream) {
485
+ return false;
486
+ }
487
+ try {
488
+ await pipeline(function*() {
489
+ yield Uint8Array.of(status);
490
+ }, stream.sink);
491
+ return true;
492
+ } catch (e) {
493
+ this.logger.warn('Error while sending error response', e);
494
+ stream.abort(e);
495
+ this.handleRequestError(e, peerId, protocol);
496
+ return false;
497
+ }
498
+ }
499
+ handleRequestError(e, peerId, subProtocol) {
500
+ const severity = this.categorizeRequestError(e, peerId, subProtocol);
501
+ if (severity) {
502
+ this.peerScoring.penalizePeer(peerId, severity);
503
+ }
504
+ }
505
+ /**
506
+ * Categorize the request error and log it.
507
+ *
508
+ * @returns Severity of the error, or undefined if the error is not punishable.
509
+ */ categorizeRequestError(e, peerId, subProtocol) {
510
+ const logTags = {
511
+ peerId: peerId.toString(),
512
+ subProtocol
513
+ };
514
+ //Punishable error - peer should never send badly formed request
515
+ if (e instanceof ReqRespStatusError && e.status === ReqRespStatus.BADLY_FORMED_REQUEST) {
516
+ this.logger.debug(`Punishable error in ${subProtocol}: ${e.cause}`, logTags);
517
+ return PeerErrorSeverity.LowToleranceError;
518
+ }
519
+ //TODO: (mralj): think if we should penalize peer here based on connection errors
520
+ return undefined;
521
+ }
522
+ /**
523
+ * Categorize the response error and log it.
524
+ *
525
+ * @returns Severity of the error, or undefined if the error is not punishable.
526
+ */ categorizeResponseError(e, peerId, subProtocol) {
527
+ const logTags = {
528
+ peerId: peerId.toString(),
529
+ subProtocol
530
+ };
531
+ // Non punishable errors - we do not expect a response for goodbye messages
532
+ if (subProtocol === ReqRespSubProtocol.GOODBYE) {
533
+ this.logger.debug('Error encountered on goodbye sub protocol, no penalty', logTags);
534
+ return undefined;
535
+ }
536
+ // We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
537
+ if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
538
+ this.logger.debug(`Non-punishable error in ${subProtocol}: ${e.message}`, logTags);
539
+ return undefined;
540
+ }
541
+ return this.categorizeConnectionErrors(e, peerId, subProtocol);
542
+ }
543
+ /*
544
+ * Errors specific to connection handling
545
+ * These can happen both when sending request and response*/ categorizeConnectionErrors(e, peerId, subProtocol) {
546
+ const logTags = {
547
+ peerId: peerId.toString(),
548
+ subProtocol
549
+ };
550
+ // Do not punish if we are stopping the service
551
+ if (e instanceof AbortError || e?.code == 'ABORT_ERR') {
552
+ this.logger.debug(`Request aborted: ${e.message}`, logTags);
553
+ return undefined;
554
+ }
555
+ // Do not punish if we are the ones closing the connection
556
+ if (e?.code === 'ERR_CONNECTION_BEING_CLOSED' || e?.code === 'ERR_CONNECTION_CLOSED' || e?.code === 'ERR_TRANSIENT_CONNECTION' || e?.message?.includes('Muxer already closed') || e?.message?.includes('muxer closed') || e?.message?.includes('ended pushable')) {
557
+ this.logger.debug(`Connection closed to peer from our side: ${peerId.toString()} (${e?.message ?? 'missing error message'})`, logTags);
558
+ return undefined;
559
+ }
560
+ // Pubishable errors
561
+ // Connection reset errors in the networking stack are punished with high severity
562
+ // it just signals an unreliable peer
563
+ // We assume that the requesting node has a functioning networking stack.
564
+ if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
565
+ this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
566
+ return PeerErrorSeverity.HighToleranceError;
567
+ }
568
+ if (e?.code === 'ECONNREFUSED') {
569
+ this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
570
+ return PeerErrorSeverity.HighToleranceError;
571
+ }
572
+ if (e?.code === 'ERR_UNEXPECTED_EOF') {
573
+ this.logger.debug(`Connection unexpected EOF: ${peerId.toString()}`, logTags);
574
+ return PeerErrorSeverity.HighToleranceError;
575
+ }
576
+ if (e?.code === 'ERR_UNSUPPORTED_PROTOCOL') {
577
+ this.logger.debug(`Sub protocol not supported by peer: ${peerId.toString()}`, logTags);
578
+ return PeerErrorSeverity.HighToleranceError;
579
+ }
580
+ // Timeout errors are punished with high tolerance, they can be due to a geographically far away or overloaded peer
581
+ if (e instanceof IndividualReqRespTimeoutError || e instanceof TimeoutError) {
582
+ this.logger.debug(`Timeout error in ${subProtocol}: ${e.message}`, logTags);
583
+ return PeerErrorSeverity.HighToleranceError;
584
+ }
585
+ // Catch all error
586
+ this.logger.error(`Unexpected error in ReqResp protocol`, e, logTags);
587
+ return PeerErrorSeverity.HighToleranceError;
497
588
  }
498
589
  }
499
590
  _ts_decorate([