@aztec/p2p 1.2.1 → 2.0.0-nightly.20250813

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 (221) hide show
  1. package/dest/client/factory.d.ts +5 -1
  2. package/dest/client/factory.d.ts.map +1 -1
  3. package/dest/client/factory.js +29 -12
  4. package/dest/client/interface.d.ts +8 -13
  5. package/dest/client/interface.d.ts.map +1 -1
  6. package/dest/client/p2p_client.d.ts +18 -22
  7. package/dest/client/p2p_client.d.ts.map +1 -1
  8. package/dest/client/p2p_client.js +86 -83
  9. package/dest/config.d.ts +30 -1
  10. package/dest/config.d.ts.map +1 -1
  11. package/dest/config.js +34 -1
  12. package/dest/index.d.ts +1 -0
  13. package/dest/index.d.ts.map +1 -1
  14. package/dest/index.js +1 -0
  15. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +13 -1
  16. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -1
  17. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -1
  18. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +117 -10
  19. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +4 -1
  20. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -1
  21. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +22 -1
  22. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +4 -1
  23. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -1
  24. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +21 -1
  25. package/dest/mem_pools/attestation_pool/mocks.d.ts +1 -2
  26. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -1
  27. package/dest/mem_pools/attestation_pool/mocks.js +2 -10
  28. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +8 -3
  29. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  30. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +64 -37
  31. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +8 -3
  32. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -1
  33. package/dest/mem_pools/tx_pool/memory_tx_pool.js +18 -10
  34. package/dest/mem_pools/tx_pool/tx_pool.d.ts +11 -2
  35. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -1
  36. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -1
  37. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +73 -44
  38. package/dest/msg_validators/attestation_validator/attestation_validator.js +1 -1
  39. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  40. package/dest/msg_validators/tx_validator/block_header_validator.js +2 -2
  41. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  42. package/dest/msg_validators/tx_validator/data_validator.js +35 -59
  43. package/dest/msg_validators/tx_validator/double_spend_validator.js +2 -2
  44. package/dest/msg_validators/tx_validator/gas_validator.js +4 -4
  45. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  46. package/dest/msg_validators/tx_validator/metadata_validator.js +21 -21
  47. package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
  48. package/dest/msg_validators/tx_validator/tx_proof_validator.js +3 -3
  49. package/dest/services/discv5/discV5_service.d.ts.map +1 -1
  50. package/dest/services/discv5/discV5_service.js +4 -1
  51. package/dest/services/dummy_service.d.ts +13 -3
  52. package/dest/services/dummy_service.d.ts.map +1 -1
  53. package/dest/services/dummy_service.js +26 -3
  54. package/dest/services/index.d.ts +3 -1
  55. package/dest/services/index.d.ts.map +1 -1
  56. package/dest/services/index.js +3 -1
  57. package/dest/services/libp2p/libp2p_service.d.ts +13 -20
  58. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  59. package/dest/services/libp2p/libp2p_service.js +123 -46
  60. package/dest/services/peer-manager/interface.d.ts +8 -1
  61. package/dest/services/peer-manager/interface.d.ts.map +1 -1
  62. package/dest/services/peer-manager/peer_manager.d.ts +70 -3
  63. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -1
  64. package/dest/services/peer-manager/peer_manager.js +369 -39
  65. package/dest/services/reqresp/config.d.ts +3 -3
  66. package/dest/services/reqresp/config.d.ts.map +1 -1
  67. package/dest/services/reqresp/config.js +3 -3
  68. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +3 -4
  69. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  70. package/dest/services/reqresp/connection-sampler/connection_sampler.js +35 -52
  71. package/dest/services/reqresp/index.d.ts +2 -1
  72. package/dest/services/reqresp/index.d.ts.map +1 -1
  73. package/dest/services/reqresp/index.js +2 -1
  74. package/dest/services/reqresp/interface.d.ts +61 -10
  75. package/dest/services/reqresp/interface.d.ts.map +1 -1
  76. package/dest/services/reqresp/interface.js +41 -6
  77. package/dest/services/reqresp/protocols/auth.d.ts +43 -0
  78. package/dest/services/reqresp/protocols/auth.d.ts.map +1 -0
  79. package/dest/services/reqresp/protocols/auth.js +71 -0
  80. package/dest/services/reqresp/protocols/block.d.ts +5 -0
  81. package/dest/services/reqresp/protocols/block.d.ts.map +1 -1
  82. package/dest/services/reqresp/protocols/block.js +28 -5
  83. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +30 -0
  84. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -0
  85. package/dest/services/reqresp/protocols/block_txs/bitvector.js +75 -0
  86. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +11 -0
  87. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -0
  88. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +39 -0
  89. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +49 -0
  90. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -0
  91. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +75 -0
  92. package/dest/services/reqresp/protocols/block_txs/index.d.ts +4 -0
  93. package/dest/services/reqresp/protocols/block_txs/index.d.ts.map +1 -0
  94. package/dest/services/reqresp/protocols/block_txs/index.js +3 -0
  95. package/dest/services/reqresp/protocols/goodbye.js +3 -5
  96. package/dest/services/reqresp/protocols/index.d.ts +2 -0
  97. package/dest/services/reqresp/protocols/index.d.ts.map +1 -1
  98. package/dest/services/reqresp/protocols/index.js +2 -0
  99. package/dest/services/reqresp/protocols/status.d.ts +2 -0
  100. package/dest/services/reqresp/protocols/status.d.ts.map +1 -1
  101. package/dest/services/reqresp/protocols/status.js +7 -0
  102. package/dest/services/reqresp/protocols/tx.d.ts +12 -1
  103. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -1
  104. package/dest/services/reqresp/protocols/tx.js +34 -6
  105. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -1
  106. package/dest/services/reqresp/rate-limiter/rate_limits.js +20 -0
  107. package/dest/services/reqresp/reqresp.d.ts +37 -39
  108. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  109. package/dest/services/reqresp/reqresp.js +220 -220
  110. package/dest/services/reqresp/status.d.ts +8 -3
  111. package/dest/services/reqresp/status.d.ts.map +1 -1
  112. package/dest/services/reqresp/status.js +6 -2
  113. package/dest/services/service.d.ts +10 -10
  114. package/dest/services/service.d.ts.map +1 -1
  115. package/dest/services/tx_collection/config.d.ts +25 -0
  116. package/dest/services/tx_collection/config.d.ts.map +1 -0
  117. package/dest/services/tx_collection/config.js +58 -0
  118. package/dest/services/tx_collection/fast_tx_collection.d.ts +56 -0
  119. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -0
  120. package/dest/services/tx_collection/fast_tx_collection.js +295 -0
  121. package/dest/services/tx_collection/index.d.ts +3 -0
  122. package/dest/services/tx_collection/index.d.ts.map +1 -0
  123. package/dest/services/tx_collection/index.js +2 -0
  124. package/dest/services/tx_collection/instrumentation.d.ts +10 -0
  125. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -0
  126. package/dest/services/tx_collection/instrumentation.js +34 -0
  127. package/dest/services/tx_collection/slow_tx_collection.d.ts +54 -0
  128. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -0
  129. package/dest/services/tx_collection/slow_tx_collection.js +176 -0
  130. package/dest/services/tx_collection/tx_collection.d.ts +109 -0
  131. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -0
  132. package/dest/services/tx_collection/tx_collection.js +127 -0
  133. package/dest/services/tx_collection/tx_collection_sink.d.ts +30 -0
  134. package/dest/services/tx_collection/tx_collection_sink.d.ts.map +1 -0
  135. package/dest/services/tx_collection/tx_collection_sink.js +81 -0
  136. package/dest/services/tx_collection/tx_source.d.ts +18 -0
  137. package/dest/services/tx_collection/tx_source.d.ts.map +1 -0
  138. package/dest/services/tx_collection/tx_source.js +31 -0
  139. package/dest/services/tx_provider.d.ts +49 -0
  140. package/dest/services/tx_provider.d.ts.map +1 -0
  141. package/dest/services/tx_provider.js +206 -0
  142. package/dest/services/{tx_collect_instrumentation.d.ts → tx_provider_instrumentation.d.ts} +2 -2
  143. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -0
  144. package/dest/services/{tx_collect_instrumentation.js → tx_provider_instrumentation.js} +5 -5
  145. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -1
  146. package/dest/test-helpers/make-test-p2p-clients.js +4 -3
  147. package/dest/test-helpers/mock-pubsub.d.ts +2 -1
  148. package/dest/test-helpers/mock-pubsub.d.ts.map +1 -1
  149. package/dest/test-helpers/mock-pubsub.js +2 -1
  150. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -1
  151. package/dest/test-helpers/reqresp-nodes.js +8 -4
  152. package/dest/testbench/p2p_client_testbench_worker.js +11 -5
  153. package/dest/util.d.ts +1 -1
  154. package/dest/util.d.ts.map +1 -1
  155. package/package.json +14 -15
  156. package/src/client/factory.ts +87 -12
  157. package/src/client/interface.ts +19 -15
  158. package/src/client/p2p_client.ts +108 -92
  159. package/src/config.ts +52 -1
  160. package/src/index.ts +1 -0
  161. package/src/mem_pools/attestation_pool/attestation_pool.ts +15 -1
  162. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +155 -4
  163. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +28 -1
  164. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +28 -2
  165. package/src/mem_pools/attestation_pool/mocks.ts +1 -3
  166. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +59 -41
  167. package/src/mem_pools/tx_pool/memory_tx_pool.ts +19 -9
  168. package/src/mem_pools/tx_pool/tx_pool.ts +7 -2
  169. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +63 -40
  170. package/src/msg_validators/attestation_validator/attestation_validator.ts +1 -1
  171. package/src/msg_validators/tx_validator/block_header_validator.ts +2 -2
  172. package/src/msg_validators/tx_validator/data_validator.ts +36 -27
  173. package/src/msg_validators/tx_validator/double_spend_validator.ts +2 -2
  174. package/src/msg_validators/tx_validator/gas_validator.ts +4 -4
  175. package/src/msg_validators/tx_validator/metadata_validator.ts +22 -28
  176. package/src/msg_validators/tx_validator/phases_validator.ts +2 -2
  177. package/src/msg_validators/tx_validator/tx_proof_validator.ts +2 -2
  178. package/src/services/discv5/discV5_service.ts +4 -1
  179. package/src/services/dummy_service.ts +44 -4
  180. package/src/services/index.ts +3 -1
  181. package/src/services/libp2p/libp2p_service.ts +147 -55
  182. package/src/services/peer-manager/interface.ts +10 -1
  183. package/src/services/peer-manager/peer_manager.ts +441 -41
  184. package/src/services/reqresp/config.ts +3 -3
  185. package/src/services/reqresp/connection-sampler/connection_sampler.ts +38 -63
  186. package/src/services/reqresp/index.ts +2 -0
  187. package/src/services/reqresp/interface.ts +63 -17
  188. package/src/services/reqresp/protocols/auth.ts +83 -0
  189. package/src/services/reqresp/protocols/block.ts +24 -3
  190. package/src/services/reqresp/protocols/block_txs/bitvector.ts +90 -0
  191. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +53 -0
  192. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +79 -0
  193. package/src/services/reqresp/protocols/block_txs/index.ts +3 -0
  194. package/src/services/reqresp/protocols/goodbye.ts +3 -3
  195. package/src/services/reqresp/protocols/index.ts +2 -0
  196. package/src/services/reqresp/protocols/status.ts +20 -0
  197. package/src/services/reqresp/protocols/tx.ts +35 -6
  198. package/src/services/reqresp/rate-limiter/rate_limits.ts +20 -0
  199. package/src/services/reqresp/reqresp.ts +294 -264
  200. package/src/services/reqresp/status.ts +9 -3
  201. package/src/services/service.ts +23 -14
  202. package/src/services/tx_collection/config.ts +84 -0
  203. package/src/services/tx_collection/fast_tx_collection.ts +338 -0
  204. package/src/services/tx_collection/index.ts +2 -0
  205. package/src/services/tx_collection/instrumentation.ts +43 -0
  206. package/src/services/tx_collection/slow_tx_collection.ts +232 -0
  207. package/src/services/tx_collection/tx_collection.ts +214 -0
  208. package/src/services/tx_collection/tx_collection_sink.ts +98 -0
  209. package/src/services/tx_collection/tx_source.ts +37 -0
  210. package/src/services/tx_provider.ts +215 -0
  211. package/src/services/{tx_collect_instrumentation.ts → tx_provider_instrumentation.ts} +5 -5
  212. package/src/test-helpers/make-test-p2p-clients.ts +4 -2
  213. package/src/test-helpers/mock-pubsub.ts +1 -0
  214. package/src/test-helpers/reqresp-nodes.ts +7 -1
  215. package/src/testbench/p2p_client_testbench_worker.ts +9 -2
  216. package/src/util.ts +1 -1
  217. package/dest/services/tx_collect_instrumentation.d.ts.map +0 -1
  218. package/dest/services/tx_collector.d.ts +0 -23
  219. package/dest/services/tx_collector.d.ts.map +0 -1
  220. package/dest/services/tx_collector.js +0 -95
  221. package/src/services/tx_collector.ts +0 -134
@@ -1 +1 @@
1
- {"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/reqresp.ts"],"names":[],"mappings":"AAMA,OAAO,EAAc,KAAK,eAAe,EAAiC,MAAM,yBAAyB,CAAC;AAE1G,OAAO,KAAK,EAAsB,MAAM,EAAU,MAAM,mBAAmB,CAAC;AAG5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AASrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAIL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,kBAAkB,EAClB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,cAAc,EAEpB,MAAM,gBAAgB,CAAC;AASxB;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAQ,YAAW,gBAAgB;IAkB5C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAnBhB,OAAO,CAAC,uBAAuB,CAA8C;IAC7E,OAAO,CAAC,0BAA0B,CAAiD;IACnF,OAAO,CAAC,aAAa,CAA2C;IAGhE,OAAO,CAAC,mBAAmB,CAA6D;IACxF,OAAO,CAAC,qBAAqB,CAAiE;IAE9F,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAA6B;IAEhD,OAAO,CAAC,eAAe,CAAkB;IAEzC,OAAO,CAAC,OAAO,CAAiB;gBAG9B,MAAM,EAAE,gBAAgB,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,yCAA8B,EAC5C,UAAU,GAAE,OAAO,CAAC,4BAA4B,CAAM,EACtD,eAAe,GAAE,eAAsC;IAkBlD,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAc5D,IAAI,MAAM,6CAET;IAED;;OAEG;IACG,KAAK,CAAC,mBAAmB,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,4BAA4B;IAiBhH;;OAEG;IACG,IAAI;IAoBV;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,WAAW,CAAC,WAAW,SAAS,kBAAkB,EACtD,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,GAC5D,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC;IAiE7E;;;;;;;;;;;;;;;;;;;;;OAqBG;IAQG,gBAAgB,CAAC,WAAW,SAAS,kBAAkB,EAC3D,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAChE,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,SAAQ,EACjB,QAAQ,SAA+C,EACvD,gBAAgB,SAAI,GACnB,OAAO,CAAC,CAAC,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC;IAgJjF;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IAKU,iBAAiB,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,eAAe,CAAC;IA4C3B;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;OAEG;IACH,OAAO,CAAC,eAAe;IAiEvB;;;;;;OAMG;YACW,WAAW;IAoCzB;;;;;;;;;;;;;;;OAeG;YAKW,aAAa;YAsFZ,cAAc;CAI9B"}
1
+ {"version":3,"file":"reqresp.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/reqresp.ts"],"names":[],"mappings":"AAMA,OAAO,EAAc,KAAK,eAAe,EAAiC,MAAM,yBAAyB,CAAC;AAE1G,OAAO,KAAK,EAAsB,MAAM,EAAU,MAAM,mBAAmB,CAAC;AAC5E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAUrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,aAAa,CAAC;AAGrB,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,cAAc,EAEpB,MAAM,gBAAgB,CAAC;AASxB;;;;;;;;;;;;;GAaG;AACH,qBAAa,OAAQ,YAAW,gBAAgB;IAiB5C,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,MAAM;IAlBhB,OAAO,CAAC,0BAA0B,CAAiD;IACnF,OAAO,CAAC,aAAa,CAA2C;IAGhE,OAAO,CAAC,mBAAmB,CAA6D;IACxF,OAAO,CAAC,qBAAqB,CAAiE;IAE9F,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,WAAW,CAA6B;IAEhD,OAAO,CAAC,eAAe,CAAkB;IAEzC,OAAO,CAAC,OAAO,CAAiB;gBAG9B,MAAM,EAAE,gBAAgB,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,MAAM,yCAA8B,EAC5C,UAAU,GAAE,OAAO,CAAC,4BAA4B,CAAM,EACtD,eAAe,GAAE,eAAsC;IAkBlD,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI;IAU5D,IAAI,MAAM,6CAET;IAED;;OAEG;IACG,KAAK,CAAC,mBAAmB,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,4BAA4B;IAiB1G,cAAc,CAClB,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,yBAAyB,EAClC,SAAS,GAAE,4BAA4B,CAAC,kBAAkB,CAAgD,GACzG,OAAO,CAAC,IAAI,CAAC;IAYhB;;OAEG;IACG,IAAI;IAoBV;;;;;;;;;;;;;;;;;;;;;OAqBG;IAQG,gBAAgB,CAAC,WAAW,SAAS,kBAAkB,EAC3D,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAChE,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,SAAQ,EACjB,QAAQ,SAA+C,EACvD,gBAAgB,SAAI,GACnB,OAAO,CAAC,YAAY,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC;IAgJnE;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IAKU,iBAAiB,CAC5B,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,kBAAkB,EAC/B,OAAO,EAAE,MAAM,EACf,WAAW,GAAE,MAA2B,GACvC,OAAO,CAAC,eAAe,CAAC;IAsD3B;;;;;;;;;OASG;IACH,OAAO,CAAC,mBAAmB;IAO3B;;;;;;OAMG;YACW,WAAW;IA6CzB;;;;;;;;;;;;;;;;OAgBG;YAKW,aAAa;IAuD3B;;;;;;;SAOK;YACS,aAAa;IA4B3B;;;;;;;OAOG;YACW,YAAY;IAmC1B,OAAO,CAAC,kBAAkB;IAO1B;;;;OAIG;IACH,OAAO,CAAC,sBAAsB;IAiB9B;;;;OAIG;IACH,OAAO,CAAC,uBAAuB;IAyB/B,OAAO,CAAC,0BAA0B;CA8DnC"}
@@ -11,14 +11,13 @@ import { createLogger } from '@aztec/foundation/log';
11
11
  import { executeTimeout } from '@aztec/foundation/timer';
12
12
  import { PeerErrorSeverity } from '@aztec/stdlib/p2p';
13
13
  import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
14
- import { abortableDuplex, abortableSink } from 'abortable-iterator';
15
- import { pipe } from 'it-pipe';
14
+ import { pipeline } from 'node:stream/promises';
16
15
  import { CollectiveReqRespTimeoutError, IndividualReqRespTimeoutError, InvalidResponseError } from '../../errors/reqresp.error.js';
17
16
  import { SnappyTransform } from '../encoding.js';
18
- import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_OVERALL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS } from './config.js';
17
+ import { DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS, DEFAULT_REQRESP_DIAL_TIMEOUT_MS } from './config.js';
19
18
  import { BatchConnectionSampler } from './connection-sampler/batch_connection_sampler.js';
20
19
  import { ConnectionSampler, RandomSampler } from './connection-sampler/connection_sampler.js';
21
- import { DEFAULT_SUB_PROTOCOL_HANDLERS, DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, subProtocolMap } from './interface.js';
20
+ import { DEFAULT_SUB_PROTOCOL_HANDLERS, DEFAULT_SUB_PROTOCOL_VALIDATORS, ReqRespSubProtocol, responseFromBuffer } from './interface.js';
22
21
  import { ReqRespMetrics } from './metrics.js';
23
22
  import { RateLimitStatus, RequestResponseRateLimiter, prettyPrintRateLimitStatus } from './rate-limiter/rate_limiter.js';
24
23
  import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqRespStatus } from './status.js';
@@ -39,7 +38,6 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
39
38
  libp2p;
40
39
  peerScoring;
41
40
  logger;
42
- overallRequestTimeoutMs;
43
41
  individualRequestTimeoutMs;
44
42
  dialTimeoutMs;
45
43
  // Warning, if the `start` function is not called as the parent class constructor, then the default sub protocol handlers will be used ( not good )
@@ -53,7 +51,6 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
53
51
  this.libp2p = libp2p;
54
52
  this.peerScoring = peerScoring;
55
53
  this.logger = logger;
56
- this.overallRequestTimeoutMs = DEFAULT_OVERALL_REQUEST_TIMEOUT_MS;
57
54
  this.individualRequestTimeoutMs = DEFAULT_INDIVIDUAL_REQUEST_TIMEOUT_MS;
58
55
  this.dialTimeoutMs = DEFAULT_REQRESP_DIAL_TIMEOUT_MS;
59
56
  this.subProtocolHandlers = DEFAULT_SUB_PROTOCOL_HANDLERS;
@@ -66,9 +63,6 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
66
63
  this.metrics = new ReqRespMetrics(telemetryClient);
67
64
  }
68
65
  updateConfig(config) {
69
- if (typeof config.overallRequestTimeoutMs === 'number') {
70
- this.overallRequestTimeoutMs = config.overallRequestTimeoutMs;
71
- }
72
66
  if (typeof config.individualRequestTimeoutMs === 'number') {
73
67
  this.individualRequestTimeoutMs = config.individualRequestTimeoutMs;
74
68
  }
@@ -90,6 +84,11 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
90
84
  }
91
85
  this.rateLimiter.start();
92
86
  }
87
+ async addSubProtocol(subProtocol, handler, validator = DEFAULT_SUB_PROTOCOL_VALIDATORS[subProtocol]) {
88
+ this.subProtocolHandlers[subProtocol] = handler;
89
+ this.subProtocolValidators[subProtocol] = validator;
90
+ await this.libp2p.handle(subProtocol, (data)=>void this.streamHandler(subProtocol, data).catch((err)=>this.logger.error(`Error on libp2p subprotocol ${subProtocol} handler`, err)));
91
+ }
93
92
  /**
94
93
  * Stop the reqresp service
95
94
  */ async stop() {
@@ -108,84 +107,6 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
108
107
  // NOTE: We assume libp2p instance is managed by the caller
109
108
  }
110
109
  /**
111
- * Send a request to peers, returns the first response
112
- *
113
- * @param subProtocol - The protocol being requested
114
- * @param request - The request to send
115
- * @returns - The response from the peer, otherwise undefined
116
- *
117
- * @description
118
- * This method attempts to send a request to all active peers using the specified sub-protocol.
119
- * It opens a stream with each peer, sends the request, and awaits a response.
120
- * If a valid response is received, it returns the response; otherwise, it continues to the next peer.
121
- * If no response is received from any peer, it returns undefined.
122
- *
123
- * The method performs the following steps:
124
- * - Sample a peer to send the request to.
125
- * - Opens a stream with the peer using the specified sub-protocol.
126
- *
127
- * When a response is received, it is validated using the given sub protocols response validator.
128
- * To see the interface for the response validator - see `interface.ts`
129
- *
130
- * Failing a response validation requests in a severe peer penalty, and will
131
- * prompt the node to continue to search to the next peer.
132
- * For example, a transaction request validator will check that the payload returned does in fact
133
- * match the txHash that was requested. A peer that fails this check an only be an extremely naughty peer.
134
- *
135
- * This entire operation is wrapped in an overall timeout, that is independent of the
136
- * peer it is requesting data from.
137
- *
138
- */ async sendRequest(subProtocol, request) {
139
- const responseValidator = this.subProtocolValidators[subProtocol];
140
- const requestBuffer = request.toBuffer();
141
- const requestFunction = async (signal)=>{
142
- // Attempt to ask all of our peers, but sampled in a random order
143
- // This function is wrapped in a timeout, so we will exit the loop if we have not received a response
144
- const numberOfPeers = this.libp2p.getPeers().length;
145
- if (numberOfPeers === 0) {
146
- this.logger.debug('No active peers to send requests to');
147
- return undefined;
148
- }
149
- const attemptedPeers = new Map();
150
- for(let i = 0; i < numberOfPeers; i++){
151
- if (signal.aborted) {
152
- throw new AbortError('Request has been aborted');
153
- }
154
- // Sample a peer to make a request to
155
- const peer = this.connectionSampler.getPeer(attemptedPeers);
156
- this.logger.trace(`Attempting to send request to peer: ${peer?.toString()}`);
157
- if (!peer) {
158
- this.logger.debug('No peers available to send requests to');
159
- return undefined;
160
- }
161
- attemptedPeers.set(peer.toString(), true);
162
- this.logger.trace(`Sending request to peer: ${peer.toString()}`);
163
- const response = await this.sendRequestToPeer(peer, subProtocol, requestBuffer);
164
- if (response.status !== ReqRespStatus.SUCCESS) {
165
- this.logger.debug(`Request to peer ${peer.toString()} failed with status ${prettyPrintReqRespStatus(response.status)}`);
166
- continue;
167
- }
168
- // If we get a response, return it, otherwise we iterate onto the next peer
169
- // We do not consider it a success if we have an empty buffer
170
- if (response && response.data.length > 0) {
171
- const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
172
- // The response validator handles peer punishment within
173
- const isValid = await responseValidator(request, object, peer);
174
- if (!isValid) {
175
- throw new InvalidResponseError();
176
- }
177
- return object;
178
- }
179
- }
180
- };
181
- try {
182
- return await executeTimeout(requestFunction, this.overallRequestTimeoutMs, ()=>new CollectiveReqRespTimeoutError());
183
- } catch (e) {
184
- this.logger.debug(`${e.message} | subProtocol: ${subProtocol}`);
185
- return undefined;
186
- }
187
- }
188
- /**
189
110
  * Request multiple messages over the same sub protocol, balancing the requests across peers.
190
111
  *
191
112
  * @devnote
@@ -282,7 +203,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
282
203
  };
283
204
  }
284
205
  if (response && response.data.length > 0) {
285
- const object = subProtocolMap[subProtocol].response.fromBuffer(response.data);
206
+ const object = responseFromBuffer(subProtocol, response.data);
286
207
  const isValid = await responseValidator(requests[index], object, peer);
287
208
  if (isValid) {
288
209
  peerResults.push({
@@ -359,22 +280,35 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
359
280
  this.logger.trace(`Sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
360
281
  stream = await this.connectionSampler.dialProtocol(peerId, subProtocol, dialTimeout);
361
282
  this.logger.trace(`Opened stream ${stream.id} for sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
362
- // Open the stream with a timeout
363
- const result = await executeTimeout((signal)=>pipe([
364
- payload
365
- ], abortableDuplex(stream, signal), abortableSink(this.readMessage.bind(this), signal)), this.individualRequestTimeoutMs, ()=>new IndividualReqRespTimeoutError());
366
- return result;
283
+ const timeoutErr = new IndividualReqRespTimeoutError();
284
+ const [_, resp] = await executeTimeout((signal)=>Promise.all([
285
+ pipeline([
286
+ payload
287
+ ], stream.sink, {
288
+ signal
289
+ }),
290
+ pipeline(stream.source, this.readMessage.bind(this), {
291
+ signal
292
+ })
293
+ ]), this.individualRequestTimeoutMs, ()=>timeoutErr);
294
+ return resp;
367
295
  } catch (e) {
296
+ // On error we immediately abort the stream, this is preferred way,
297
+ // because it signals to the sender that error happened, whereas
298
+ // closing the stream only closes our side and is much slower
299
+ if (stream) {
300
+ stream.abort(e);
301
+ }
368
302
  this.metrics.recordRequestError(subProtocol);
369
303
  this.handleResponseError(e, peerId, subProtocol);
370
304
  // If there is an exception, we return an unknown response
371
305
  this.logger.debug(`Error sending request to peer ${peerId.toString()} on sub protocol ${subProtocol}: ${e}`);
372
306
  return {
373
- status: ReqRespStatus.FAILURE,
374
- data: Buffer.from([])
307
+ status: ReqRespStatus.FAILURE
375
308
  };
376
309
  } finally{
377
310
  // Only close the stream if we created it
311
+ // Note even if we aborted the stream, calling close on it is ok, it's just a no-op
378
312
  if (stream) {
379
313
  try {
380
314
  this.logger.trace(`Closing stream ${stream.id} for request to peer ${peerId.toString()} on sub protocol ${subProtocol}`);
@@ -395,88 +329,41 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
395
329
  * @param subProtocol - The sub protocol
396
330
  * @returns If the error is non pubishable, then undefined is returned, otherwise the peer is penalized
397
331
  */ handleResponseError(e, peerId, subProtocol) {
398
- const severity = this.categorizeError(e, peerId, subProtocol);
332
+ const severity = this.categorizeResponseError(e, peerId, subProtocol);
399
333
  if (severity) {
400
334
  this.peerScoring.penalizePeer(peerId, severity);
401
335
  }
402
336
  }
403
337
  /**
404
- * Categorize the error and log it.
405
- */ categorizeError(e, peerId, subProtocol) {
406
- const logTags = {
407
- peerId: peerId.toString(),
408
- subProtocol
409
- };
410
- // Non punishable errors - we do not expect a response for goodbye messages
411
- if (subProtocol === ReqRespSubProtocol.GOODBYE) {
412
- this.logger.debug('Error encountered on goodbye sub protocol, no penalty', logTags);
413
- return undefined;
414
- }
415
- // We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
416
- if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
417
- this.logger.debug(`Non-punishable error in ${subProtocol}: ${e.message}`, logTags);
418
- return undefined;
419
- }
420
- // Do not punish if we are stopping the service
421
- if (e && (e instanceof AbortError || e.code === 'ABORT_ERR')) {
422
- this.logger.debug(`Request aborted: ${e.message}`, logTags);
423
- return undefined;
424
- }
425
- // Do not punish if we are the ones closing the connection
426
- if (e?.code === 'ERR_CONNECTION_BEING_CLOSED' || e?.code === 'ERR_CONNECTION_CLOSED' || e?.code === 'ERR_TRANSIENT_CONNECTION' || e?.message?.includes('Muxer already closed')) {
427
- this.logger.debug(`Connection closed to peer from our side: ${peerId.toString()} (${e?.message ?? 'missing error message'})`, logTags);
428
- return undefined;
429
- }
430
- // Pubishable errors
431
- // Connection reset errors in the networking stack are punished with high severity
432
- // it just signals an unreliable peer
433
- // We assume that the requesting node has a functioning networking stack.
434
- if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
435
- this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
436
- return PeerErrorSeverity.HighToleranceError;
437
- }
438
- if (e?.code === 'ECONNREFUSED') {
439
- this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
440
- return PeerErrorSeverity.HighToleranceError;
441
- }
442
- if (e?.code === 'ERR_UNEXPECTED_EOF') {
443
- this.logger.debug(`Connection unexpected EOF: ${peerId.toString()}`, logTags);
444
- return PeerErrorSeverity.HighToleranceError;
445
- }
446
- // Timeout errors are punished with high tolerance, they can be due to a geographically far away or overloaded peer
447
- if (e instanceof IndividualReqRespTimeoutError || e instanceof TimeoutError) {
448
- this.logger.debug(`Timeout error in ${subProtocol}: ${e.message}`, logTags);
449
- return PeerErrorSeverity.HighToleranceError;
450
- }
451
- // Catch all error
452
- this.logger.debug(`Unexpected error sending request to peer`, {
453
- err: e,
454
- logTags
455
- });
456
- return PeerErrorSeverity.HighToleranceError;
457
- }
458
- /**
459
338
  * Read a message returned from a stream into a single buffer
460
339
  *
461
340
  * The message is split into two components
462
341
  * - The first chunk should contain a control byte, indicating the status of the response see `ReqRespStatus`
463
342
  * - The second chunk should contain the response data
464
343
  */ async readMessage(source) {
465
- let statusBuffer;
344
+ let status;
466
345
  const chunks = [];
467
346
  try {
468
347
  for await (const chunk of source){
469
- if (statusBuffer === undefined) {
470
- const firstChunkBuffer = chunk.subarray();
471
- statusBuffer = parseStatusChunk(firstChunkBuffer);
472
- } else {
348
+ const statusParsed = status !== undefined;
349
+ if (statusParsed) {
473
350
  chunks.push(chunk.subarray());
351
+ continue;
352
+ }
353
+ const firstChunkBuffer = chunk.subarray();
354
+ status = parseStatusChunk(firstChunkBuffer);
355
+ // In case status is not SUCCESS, we do not expect any data in the response
356
+ // we can return early
357
+ if (status !== ReqRespStatus.SUCCESS) {
358
+ return {
359
+ status
360
+ };
474
361
  }
475
362
  }
476
363
  const messageData = Buffer.concat(chunks);
477
364
  const message = this.snappyTransform.inboundTransformNoTopic(messageData);
478
365
  return {
479
- status: statusBuffer ?? ReqRespStatus.UNKNOWN,
366
+ status: status ?? ReqRespStatus.UNKNOWN,
480
367
  data: message
481
368
  };
482
369
  } catch (e) {
@@ -486,8 +373,7 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
486
373
  status = e.status;
487
374
  }
488
375
  return {
489
- status,
490
- data: Buffer.from([])
376
+ status
491
377
  };
492
378
  }
493
379
  }
@@ -495,7 +381,8 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
495
381
  * Stream Handler
496
382
  * Reads the incoming stream, determines the protocol, then triggers the appropriate handler
497
383
  *
498
- * @param param0 - The incoming stream data
384
+ * @param protocol - The sub protocol to handle
385
+ * @param incomingStream - The incoming stream data containing the stream and connection
499
386
  *
500
387
  * @description
501
388
  * An individual stream handler will be bound to each sub protocol, and handles returning data back
@@ -506,81 +393,194 @@ import { ReqRespStatus, ReqRespStatusError, parseStatusChunk, prettyPrintReqResp
506
393
  *
507
394
  * We check rate limits for each peer, note the peer will be penalised within the rate limiter implementation
508
395
  * if they exceed their peer specific limits.
509
- */ async streamHandler(protocol, { stream, connection }) {
510
- this.metrics.recordRequestReceived(protocol);
396
+ */ async streamHandler(protocol, incomingStream) {
397
+ const { stream, connection } = incomingStream;
511
398
  try {
512
- // Store a reference to from this for the async generator
399
+ this.metrics.recordRequestReceived(protocol);
513
400
  const rateLimitStatus = this.rateLimiter.allow(protocol, connection.remotePeer);
514
- if (rateLimitStatus != RateLimitStatus.Allowed) {
401
+ if (rateLimitStatus !== RateLimitStatus.Allowed) {
515
402
  this.logger.verbose(`Rate limit exceeded ${prettyPrintRateLimitStatus(rateLimitStatus)} for ${protocol} from ${connection.remotePeer}`);
516
403
  throw new ReqRespStatusError(ReqRespStatus.RATE_LIMIT_EXCEEDED);
517
404
  }
518
- const handler = this.subProtocolHandlers[protocol];
519
- const transform = this.snappyTransform;
520
- await pipe(stream, async function*(source) {
521
- for await (const chunkList of source){
522
- const msg = Buffer.from(chunkList.subarray());
523
- const response = await handler(connection.remotePeer, msg);
524
- if (protocol === ReqRespSubProtocol.GOODBYE) {
525
- // NOTE: The stream was already closed by Goodbye handler
526
- // peerManager.goodbyeReceived(peerId, reason); will call libp2p.hangUp closing all active streams and connections
527
- // Don't respond
528
- return;
529
- }
530
- // Send success code first, then the response
531
- const successChunk = Buffer.from([
532
- ReqRespStatus.SUCCESS
533
- ]);
534
- yield new Uint8Array(successChunk);
535
- yield new Uint8Array(transform.outboundTransformNoTopic(response));
536
- }
537
- }, stream);
538
- } catch (e) {
539
- let level = 'warn';
540
- if (e && (e instanceof ReqRespStatusError && e.status === ReqRespStatus.RATE_LIMIT_EXCEEDED || e instanceof Error && [
541
- 'stream reset',
542
- 'Cannot push value onto an ended pushable'
543
- ].some((msg)=>e.message.includes(msg)))) {
544
- level = 'debug';
545
- }
546
- this.logger[level](`Reqresp response error: ${String(e)}`, e);
405
+ await this.processStream(protocol, incomingStream);
406
+ } catch (err) {
547
407
  this.metrics.recordResponseError(protocol);
548
- // If we receive a known error, we use the error status in the response chunk, otherwise we categorize as unknown
549
- let errorStatus = ReqRespStatus.UNKNOWN;
550
- if (e instanceof ReqRespStatusError) {
551
- errorStatus = e.status;
552
- }
553
- const canWriteToStream = stream.status === 'open' && (stream.writeStatus === 'writing' || stream.writeStatus === 'ready');
554
- if (!canWriteToStream) {
555
- this.logger.debug('Stream already closed, not sending error response', {
408
+ this.handleRequestError(err, connection.remotePeer, protocol);
409
+ if (err instanceof ReqRespStatusError) {
410
+ const errorSent = await this.trySendError(stream, connection.remotePeer, protocol, err.status);
411
+ const logMessage = errorSent ? 'Protocol error sent successfully.' : 'Stream already closed or poisoned, not sending error response.';
412
+ const isRateLimit = err.status === ReqRespStatus.RATE_LIMIT_EXCEEDED;
413
+ const level = isRateLimit ? 'debug' : 'warn';
414
+ this.logger[level](logMessage + ` Status: ${ReqRespStatus[err.status]}`, {
556
415
  protocol,
557
- err: e,
558
- errorStatus
416
+ err,
417
+ errorStatus: err.status,
418
+ cause: err.cause ?? 'Cause unknown'
559
419
  });
560
- return;
561
- }
562
- // Return and yield the response chunk
563
- try {
564
- const sendErrorChunk = this.sendErrorChunk(errorStatus);
565
- await pipe(stream, async function*(_source) {
566
- yield* sendErrorChunk;
567
- }, stream);
568
- } catch (e) {
569
- this.logger.warn('Error while sending error response', {
420
+ } else {
421
+ // In erroneous case we abort the stream, this will signal the peer that something went wrong
422
+ // and that this stream should be dropped
423
+ const isMessageToNotWarn = err instanceof Error && [
424
+ 'stream reset',
425
+ 'Cannot push value onto an ended pushable'
426
+ ].some((msg)=>err.message.includes(msg));
427
+ const level = isMessageToNotWarn ? 'debug' : 'warn';
428
+ this.logger[level]('Unknown stream error while handling the stream, aborting', {
570
429
  protocol,
571
- err: e,
572
- errorStatus
430
+ err
573
431
  });
432
+ stream.abort(err);
574
433
  }
575
434
  } finally{
435
+ //NOTE: This is idempotent action, so it's ok to call it even if stream was aborted
576
436
  await stream.close();
577
437
  }
578
438
  }
579
- async *sendErrorChunk(error) {
580
- const errorChunk = Buffer.from([
581
- error
582
- ]);
583
- yield new Uint8Array(errorChunk);
439
+ /**
440
+ * Reads incoming data from the stream, processes it according to the sub protocol,
441
+ * and puts response back into the stream.
442
+ *
443
+ * @param protocol - The sub protocol to use for processing the stream
444
+ * @param incomingStream - The incoming stream data containing the stream and connection
445
+ *
446
+ * */ async processStream(protocol, { stream, connection }) {
447
+ const handler = this.subProtocolHandlers[protocol];
448
+ const snappy = this.snappyTransform;
449
+ const SUCCESS = Uint8Array.of(ReqRespStatus.SUCCESS);
450
+ await pipeline(stream.source, async function*(source) {
451
+ for await (const chunk of source){
452
+ const response = await handler(connection.remotePeer, chunk.subarray());
453
+ if (protocol === ReqRespSubProtocol.GOODBYE) {
454
+ // NOTE: The stream was already closed by Goodbye handler
455
+ // peerManager.goodbyeReceived(peerId, reason); will call libp2p.hangUp closing all active streams and connections
456
+ // Don't try to respond
457
+ return;
458
+ }
459
+ stream.metadata.written = true; // Mark the stream as written to;
460
+ yield SUCCESS;
461
+ yield snappy.outboundTransformNoTopic(response);
462
+ }
463
+ }, stream.sink);
464
+ }
465
+ /**
466
+ * Try to send error status to the peer. We say try, because the stream,
467
+ * might already be closed
468
+ * @param stream - The stream opened between us and the peer
469
+ * @param status - The error status to send back to the peer
470
+ * @returns true if error was sent successfully, otherwise false
471
+ *
472
+ */ async trySendError(stream, peerId, protocol, status) {
473
+ const canWriteToStream = // 'writing' is a bit weird naming, but it actually means that the stream is ready to write
474
+ // 'ready' means that stream ready to be opened for writing
475
+ stream.status === 'open' && (stream.writeStatus === 'writing' || stream.writeStatus === 'ready');
476
+ // Stream was already written to, we consider it poisoned, in a sense,
477
+ // that even if we write an error response, it will not be interpreted correctly by the peer
478
+ const streamPoisoned = stream.metadata.written === true;
479
+ const shouldWriteToStream = canWriteToStream && !streamPoisoned;
480
+ if (!shouldWriteToStream) {
481
+ return false;
482
+ }
483
+ try {
484
+ await pipeline(function*() {
485
+ yield Uint8Array.of(status);
486
+ }, stream.sink);
487
+ return true;
488
+ } catch (e) {
489
+ this.logger.warn('Error while sending error response', e);
490
+ stream.abort(e);
491
+ this.handleRequestError(e, peerId, protocol);
492
+ return false;
493
+ }
494
+ }
495
+ handleRequestError(e, peerId, subProtocol) {
496
+ const severity = this.categorizeRequestError(e, peerId, subProtocol);
497
+ if (severity) {
498
+ this.peerScoring.penalizePeer(peerId, severity);
499
+ }
500
+ }
501
+ /**
502
+ * Categorize the request error and log it.
503
+ *
504
+ * @returns Severity of the error, or undefined if the error is not punishable.
505
+ */ categorizeRequestError(e, peerId, subProtocol) {
506
+ const logTags = {
507
+ peerId: peerId.toString(),
508
+ subProtocol
509
+ };
510
+ //Punishable error - peer should never send badly formed request
511
+ if (e instanceof ReqRespStatusError && e.status === ReqRespStatus.BADLY_FORMED_REQUEST) {
512
+ this.logger.debug(`Punishable error in ${subProtocol}: ${e.cause}`, logTags);
513
+ return PeerErrorSeverity.LowToleranceError;
514
+ }
515
+ //TODO: (mralj): think if we should penalize peer here based on connection errors
516
+ return undefined;
517
+ }
518
+ /**
519
+ * Categorize the response error and log it.
520
+ *
521
+ * @returns Severity of the error, or undefined if the error is not punishable.
522
+ */ categorizeResponseError(e, peerId, subProtocol) {
523
+ const logTags = {
524
+ peerId: peerId.toString(),
525
+ subProtocol
526
+ };
527
+ // Non punishable errors - we do not expect a response for goodbye messages
528
+ if (subProtocol === ReqRespSubProtocol.GOODBYE) {
529
+ this.logger.debug('Error encountered on goodbye sub protocol, no penalty', logTags);
530
+ return undefined;
531
+ }
532
+ // We do not punish a collective timeout, as the node triggers this interupt, independent of the peer's behaviour
533
+ if (e instanceof CollectiveReqRespTimeoutError || e instanceof InvalidResponseError) {
534
+ this.logger.debug(`Non-punishable error in ${subProtocol}: ${e.message}`, logTags);
535
+ return undefined;
536
+ }
537
+ return this.categorizeConnectionErrors(e, peerId, subProtocol);
538
+ }
539
+ /*
540
+ * Errors specific to connection handling
541
+ * These can happen both when sending request and response*/ categorizeConnectionErrors(e, peerId, subProtocol) {
542
+ const logTags = {
543
+ peerId: peerId.toString(),
544
+ subProtocol
545
+ };
546
+ // Do not punish if we are stopping the service
547
+ if (e instanceof AbortError || e?.code == 'ABORT_ERR') {
548
+ this.logger.debug(`Request aborted: ${e.message}`, logTags);
549
+ return undefined;
550
+ }
551
+ // Do not punish if we are the ones closing the connection
552
+ 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')) {
553
+ this.logger.debug(`Connection closed to peer from our side: ${peerId.toString()} (${e?.message ?? 'missing error message'})`, logTags);
554
+ return undefined;
555
+ }
556
+ // Pubishable errors
557
+ // Connection reset errors in the networking stack are punished with high severity
558
+ // it just signals an unreliable peer
559
+ // We assume that the requesting node has a functioning networking stack.
560
+ if (e?.code === 'ECONNRESET' || e?.code === 'EPIPE') {
561
+ this.logger.debug(`Connection reset: ${peerId.toString()}`, logTags);
562
+ return PeerErrorSeverity.HighToleranceError;
563
+ }
564
+ if (e?.code === 'ECONNREFUSED') {
565
+ this.logger.debug(`Connection refused: ${peerId.toString()}`, logTags);
566
+ return PeerErrorSeverity.HighToleranceError;
567
+ }
568
+ if (e?.code === 'ERR_UNEXPECTED_EOF') {
569
+ this.logger.debug(`Connection unexpected EOF: ${peerId.toString()}`, logTags);
570
+ return PeerErrorSeverity.HighToleranceError;
571
+ }
572
+ if (e?.code === 'ERR_UNSUPPORTED_PROTOCOL') {
573
+ this.logger.debug(`Sub protocol not supported by peer: ${peerId.toString()}`, logTags);
574
+ return PeerErrorSeverity.HighToleranceError;
575
+ }
576
+ // Timeout errors are punished with high tolerance, they can be due to a geographically far away or overloaded peer
577
+ if (e instanceof IndividualReqRespTimeoutError || e instanceof TimeoutError) {
578
+ this.logger.debug(`Timeout error in ${subProtocol}: ${e.message}`, logTags);
579
+ return PeerErrorSeverity.HighToleranceError;
580
+ }
581
+ // Catch all error
582
+ this.logger.error(`Unexpected error in ReqResp protocol`, e, logTags);
583
+ return PeerErrorSeverity.HighToleranceError;
584
584
  }
585
585
  }
586
586
  _ts_decorate([
@@ -5,15 +5,20 @@ export declare enum ReqRespStatus {
5
5
  SUCCESS = 0,
6
6
  RATE_LIMIT_EXCEEDED = 1,
7
7
  BADLY_FORMED_REQUEST = 2,
8
+ INTERNAL_ERROR = 3,
9
+ NOT_FOUND = 4,
8
10
  FAILURE = 126,
9
11
  UNKNOWN = 127
10
12
  }
13
+ export type UnsuccessfulReqRespStatus = Exclude<ReqRespStatus, ReqRespStatus.SUCCESS>;
11
14
  export declare class ReqRespStatusError extends Error {
12
15
  /**
13
16
  * The status code
14
17
  */
15
- status: ReqRespStatus;
16
- constructor(status: ReqRespStatus);
18
+ readonly status: UnsuccessfulReqRespStatus;
19
+ constructor(status: UnsuccessfulReqRespStatus, cause?: {
20
+ cause?: Error;
21
+ });
17
22
  }
18
23
  /**
19
24
  * Parse the status chunk
@@ -28,5 +33,5 @@ export declare function parseStatusChunk(chunk: Uint8Array): ReqRespStatus;
28
33
  * @param status
29
34
  * @returns
30
35
  */
31
- export declare function prettyPrintReqRespStatus(status: ReqRespStatus): "SUCCESS" | "RATE_LIMIT_EXCEEDED" | "BADLY_FORMED_REQUEST" | "FAILURE" | "UNKNOWN";
36
+ export declare function prettyPrintReqRespStatus(status: ReqRespStatus): "SUCCESS" | "RATE_LIMIT_EXCEEDED" | "BADLY_FORMED_REQUEST" | "FAILURE" | "INTERNAL_ERROR" | "UNKNOWN" | undefined;
32
37
  //# sourceMappingURL=status.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,aAAa;IACvB,OAAO,IAAI;IACX,mBAAmB,IAAI;IACvB,oBAAoB,IAAI;IACxB,OAAO,MAAM;IACb,OAAO,MAAM;CACd;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACH,MAAM,EAAE,aAAa,CAAC;gBAEV,MAAM,EAAE,aAAa;CAIlC;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,CAWjE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,sFAa7D"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/services/reqresp/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,oBAAY,aAAa;IACvB,OAAO,IAAI;IACX,mBAAmB,IAAI;IACvB,oBAAoB,IAAI;IACxB,cAAc,IAAI;IAClB,SAAS,IAAI;IACb,OAAO,MAAM;IACb,OAAO,MAAM;CACd;AAED,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;AAEtF,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,yBAAyB,CAAC;gBAE/B,MAAM,EAAE,yBAAyB,EAAE,KAAK,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE;CAIzE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,aAAa,CAWjE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,qHAe7D"}
@@ -4,6 +4,8 @@
4
4
  ReqRespStatus[ReqRespStatus["SUCCESS"] = 0] = "SUCCESS";
5
5
  ReqRespStatus[ReqRespStatus["RATE_LIMIT_EXCEEDED"] = 1] = "RATE_LIMIT_EXCEEDED";
6
6
  ReqRespStatus[ReqRespStatus["BADLY_FORMED_REQUEST"] = 2] = "BADLY_FORMED_REQUEST";
7
+ ReqRespStatus[ReqRespStatus["INTERNAL_ERROR"] = 3] = "INTERNAL_ERROR";
8
+ ReqRespStatus[ReqRespStatus["NOT_FOUND"] = 4] = "NOT_FOUND";
7
9
  ReqRespStatus[ReqRespStatus["FAILURE"] = 126] = "FAILURE";
8
10
  ReqRespStatus[ReqRespStatus["UNKNOWN"] = 127] = "UNKNOWN";
9
11
  return ReqRespStatus;
@@ -12,8 +14,8 @@ export class ReqRespStatusError extends Error {
12
14
  /**
13
15
  * The status code
14
16
  */ status;
15
- constructor(status){
16
- super(`ReqResp Error: ${prettyPrintReqRespStatus(status)}`);
17
+ constructor(status, cause){
18
+ super(`ReqResp Error: ${prettyPrintReqRespStatus(status)}`, cause);
17
19
  this.status = status;
18
20
  }
19
21
  }
@@ -48,6 +50,8 @@ export class ReqRespStatusError extends Error {
48
50
  return 'BADLY_FORMED_REQUEST';
49
51
  case 126:
50
52
  return 'FAILURE';
53
+ case 3:
54
+ return 'INTERNAL_ERROR';
51
55
  case 127:
52
56
  return 'UNKNOWN';
53
57
  }