@aztec/p2p 0.0.0-test.0

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 (311) hide show
  1. package/README.md +7 -0
  2. package/dest/bootstrap/bootstrap.d.ts +38 -0
  3. package/dest/bootstrap/bootstrap.d.ts.map +1 -0
  4. package/dest/bootstrap/bootstrap.js +123 -0
  5. package/dest/client/factory.d.ts +21 -0
  6. package/dest/client/factory.d.ts.map +1 -0
  7. package/dest/client/factory.js +37 -0
  8. package/dest/client/index.d.ts +3 -0
  9. package/dest/client/index.d.ts.map +1 -0
  10. package/dest/client/index.js +2 -0
  11. package/dest/client/p2p_client.d.ts +314 -0
  12. package/dest/client/p2p_client.d.ts.map +1 -0
  13. package/dest/client/p2p_client.js +505 -0
  14. package/dest/config.d.ts +180 -0
  15. package/dest/config.d.ts.map +1 -0
  16. package/dest/config.js +193 -0
  17. package/dest/enr/generate-enr.d.ts +9 -0
  18. package/dest/enr/generate-enr.d.ts.map +1 -0
  19. package/dest/enr/generate-enr.js +30 -0
  20. package/dest/enr/index.d.ts +2 -0
  21. package/dest/enr/index.d.ts.map +1 -0
  22. package/dest/enr/index.js +1 -0
  23. package/dest/errors/reqresp.error.d.ts +28 -0
  24. package/dest/errors/reqresp.error.d.ts.map +1 -0
  25. package/dest/errors/reqresp.error.js +30 -0
  26. package/dest/index.d.ts +8 -0
  27. package/dest/index.d.ts.map +1 -0
  28. package/dest/index.js +7 -0
  29. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +57 -0
  30. package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -0
  31. package/dest/mem_pools/attestation_pool/attestation_pool.js +6 -0
  32. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +3 -0
  33. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -0
  34. package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +195 -0
  35. package/dest/mem_pools/attestation_pool/index.d.ts +3 -0
  36. package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -0
  37. package/dest/mem_pools/attestation_pool/index.js +2 -0
  38. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +22 -0
  39. package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -0
  40. package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +112 -0
  41. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -0
  42. package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -0
  43. package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +129 -0
  44. package/dest/mem_pools/attestation_pool/mocks.d.ts +19 -0
  45. package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -0
  46. package/dest/mem_pools/attestation_pool/mocks.js +33 -0
  47. package/dest/mem_pools/index.d.ts +4 -0
  48. package/dest/mem_pools/index.d.ts.map +1 -0
  49. package/dest/mem_pools/index.js +1 -0
  50. package/dest/mem_pools/instrumentation.d.ts +30 -0
  51. package/dest/mem_pools/instrumentation.d.ts.map +1 -0
  52. package/dest/mem_pools/instrumentation.js +84 -0
  53. package/dest/mem_pools/interface.d.ts +11 -0
  54. package/dest/mem_pools/interface.d.ts.map +1 -0
  55. package/dest/mem_pools/interface.js +3 -0
  56. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +66 -0
  57. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
  58. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +245 -0
  59. package/dest/mem_pools/tx_pool/index.d.ts +4 -0
  60. package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
  61. package/dest/mem_pools/tx_pool/index.js +3 -0
  62. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +56 -0
  63. package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -0
  64. package/dest/mem_pools/tx_pool/memory_tx_pool.js +141 -0
  65. package/dest/mem_pools/tx_pool/priority.d.ts +8 -0
  66. package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
  67. package/dest/mem_pools/tx_pool/priority.js +10 -0
  68. package/dest/mem_pools/tx_pool/tx_pool.d.ts +66 -0
  69. package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
  70. package/dest/mem_pools/tx_pool/tx_pool.js +3 -0
  71. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +7 -0
  72. package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
  73. package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +169 -0
  74. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +8 -0
  75. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -0
  76. package/dest/msg_validators/attestation_validator/attestation_validator.js +19 -0
  77. package/dest/msg_validators/attestation_validator/index.d.ts +2 -0
  78. package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -0
  79. package/dest/msg_validators/attestation_validator/index.js +1 -0
  80. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +8 -0
  81. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -0
  82. package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -0
  83. package/dest/msg_validators/block_proposal_validator/index.d.ts +2 -0
  84. package/dest/msg_validators/block_proposal_validator/index.d.ts.map +1 -0
  85. package/dest/msg_validators/block_proposal_validator/index.js +1 -0
  86. package/dest/msg_validators/index.d.ts +4 -0
  87. package/dest/msg_validators/index.d.ts.map +1 -0
  88. package/dest/msg_validators/index.js +3 -0
  89. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +7 -0
  90. package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
  91. package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +31 -0
  92. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +11 -0
  93. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -0
  94. package/dest/msg_validators/tx_validator/block_header_validator.js +26 -0
  95. package/dest/msg_validators/tx_validator/data_validator.d.ts +6 -0
  96. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
  97. package/dest/msg_validators/tx_validator/data_validator.js +107 -0
  98. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +12 -0
  99. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
  100. package/dest/msg_validators/tx_validator/double_spend_validator.js +41 -0
  101. package/dest/msg_validators/tx_validator/index.d.ts +7 -0
  102. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
  103. package/dest/msg_validators/tx_validator/index.js +6 -0
  104. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -0
  105. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
  106. package/dest/msg_validators/tx_validator/metadata_validator.js +44 -0
  107. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +9 -0
  108. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
  109. package/dest/msg_validators/tx_validator/tx_proof_validator.js +25 -0
  110. package/dest/services/data_store.d.ts +27 -0
  111. package/dest/services/data_store.d.ts.map +1 -0
  112. package/dest/services/data_store.js +188 -0
  113. package/dest/services/discv5/discV5_service.d.ts +42 -0
  114. package/dest/services/discv5/discV5_service.d.ts.map +1 -0
  115. package/dest/services/discv5/discV5_service.js +214 -0
  116. package/dest/services/dummy_service.d.ts +85 -0
  117. package/dest/services/dummy_service.d.ts.map +1 -0
  118. package/dest/services/dummy_service.js +92 -0
  119. package/dest/services/encoding.d.ts +31 -0
  120. package/dest/services/encoding.d.ts.map +1 -0
  121. package/dest/services/encoding.js +66 -0
  122. package/dest/services/gossipsub/scoring.d.ts +7 -0
  123. package/dest/services/gossipsub/scoring.d.ts.map +1 -0
  124. package/dest/services/gossipsub/scoring.js +10 -0
  125. package/dest/services/index.d.ts +3 -0
  126. package/dest/services/index.d.ts.map +1 -0
  127. package/dest/services/index.js +2 -0
  128. package/dest/services/libp2p/libp2p_service.d.ts +186 -0
  129. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
  130. package/dest/services/libp2p/libp2p_service.js +712 -0
  131. package/dest/services/peer-manager/metrics.d.ts +12 -0
  132. package/dest/services/peer-manager/metrics.d.ts.map +1 -0
  133. package/dest/services/peer-manager/metrics.js +33 -0
  134. package/dest/services/peer-manager/peer_manager.d.ts +94 -0
  135. package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
  136. package/dest/services/peer-manager/peer_manager.js +445 -0
  137. package/dest/services/peer-manager/peer_scoring.d.ts +28 -0
  138. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
  139. package/dest/services/peer-manager/peer_scoring.js +86 -0
  140. package/dest/services/reqresp/config.d.ts +16 -0
  141. package/dest/services/reqresp/config.d.ts.map +1 -0
  142. package/dest/services/reqresp/config.js +20 -0
  143. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
  144. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
  145. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +88 -0
  146. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
  147. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
  148. package/dest/services/reqresp/connection-sampler/connection_sampler.js +181 -0
  149. package/dest/services/reqresp/index.d.ts +6 -0
  150. package/dest/services/reqresp/index.d.ts.map +1 -0
  151. package/dest/services/reqresp/index.js +4 -0
  152. package/dest/services/reqresp/interface.d.ts +116 -0
  153. package/dest/services/reqresp/interface.d.ts.map +1 -0
  154. package/dest/services/reqresp/interface.js +84 -0
  155. package/dest/services/reqresp/metrics.d.ts +15 -0
  156. package/dest/services/reqresp/metrics.d.ts.map +1 -0
  157. package/dest/services/reqresp/metrics.js +55 -0
  158. package/dest/services/reqresp/protocols/block.d.ts +4 -0
  159. package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
  160. package/dest/services/reqresp/protocols/block.js +8 -0
  161. package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
  162. package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
  163. package/dest/services/reqresp/protocols/goodbye.js +87 -0
  164. package/dest/services/reqresp/protocols/index.d.ts +9 -0
  165. package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
  166. package/dest/services/reqresp/protocols/index.js +7 -0
  167. package/dest/services/reqresp/protocols/ping.d.ts +9 -0
  168. package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
  169. package/dest/services/reqresp/protocols/ping.js +7 -0
  170. package/dest/services/reqresp/protocols/status.d.ts +9 -0
  171. package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
  172. package/dest/services/reqresp/protocols/status.js +7 -0
  173. package/dest/services/reqresp/protocols/tx.d.ts +13 -0
  174. package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
  175. package/dest/services/reqresp/protocols/tx.js +20 -0
  176. package/dest/services/reqresp/rate-limiter/index.d.ts +2 -0
  177. package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
  178. package/dest/services/reqresp/rate-limiter/index.js +1 -0
  179. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +102 -0
  180. package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -0
  181. package/dest/services/reqresp/rate-limiter/rate_limiter.js +184 -0
  182. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +3 -0
  183. package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
  184. package/dest/services/reqresp/rate-limiter/rate_limits.js +54 -0
  185. package/dest/services/reqresp/reqresp.d.ts +166 -0
  186. package/dest/services/reqresp/reqresp.d.ts.map +1 -0
  187. package/dest/services/reqresp/reqresp.js +516 -0
  188. package/dest/services/reqresp/status.d.ts +31 -0
  189. package/dest/services/reqresp/status.d.ts.map +1 -0
  190. package/dest/services/reqresp/status.js +51 -0
  191. package/dest/services/service.d.ts +87 -0
  192. package/dest/services/service.d.ts.map +1 -0
  193. package/dest/services/service.js +5 -0
  194. package/dest/test-helpers/generate-peer-id-private-keys.d.ts +7 -0
  195. package/dest/test-helpers/generate-peer-id-private-keys.d.ts.map +1 -0
  196. package/dest/test-helpers/generate-peer-id-private-keys.js +13 -0
  197. package/dest/test-helpers/get-ports.d.ts +7 -0
  198. package/dest/test-helpers/get-ports.d.ts.map +1 -0
  199. package/dest/test-helpers/get-ports.js +8 -0
  200. package/dest/test-helpers/index.d.ts +6 -0
  201. package/dest/test-helpers/index.d.ts.map +1 -0
  202. package/dest/test-helpers/index.js +5 -0
  203. package/dest/test-helpers/make-enrs.d.ts +16 -0
  204. package/dest/test-helpers/make-enrs.d.ts.map +1 -0
  205. package/dest/test-helpers/make-enrs.js +32 -0
  206. package/dest/test-helpers/make-test-p2p-clients.d.ts +36 -0
  207. package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -0
  208. package/dest/test-helpers/make-test-p2p-clients.js +68 -0
  209. package/dest/test-helpers/reqresp-nodes.d.ts +66 -0
  210. package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -0
  211. package/dest/test-helpers/reqresp-nodes.js +207 -0
  212. package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -0
  213. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -0
  214. package/dest/testbench/p2p_client_testbench_worker.js +132 -0
  215. package/dest/testbench/parse_log_file.d.ts +2 -0
  216. package/dest/testbench/parse_log_file.d.ts.map +1 -0
  217. package/dest/testbench/parse_log_file.js +131 -0
  218. package/dest/testbench/testbench.d.ts +2 -0
  219. package/dest/testbench/testbench.d.ts.map +1 -0
  220. package/dest/testbench/testbench.js +61 -0
  221. package/dest/testbench/worker_client_manager.d.ts +56 -0
  222. package/dest/testbench/worker_client_manager.d.ts.map +1 -0
  223. package/dest/testbench/worker_client_manager.js +266 -0
  224. package/dest/types/index.d.ts +32 -0
  225. package/dest/types/index.d.ts.map +1 -0
  226. package/dest/types/index.js +28 -0
  227. package/dest/util.d.ts +53 -0
  228. package/dest/util.d.ts.map +1 -0
  229. package/dest/util.js +140 -0
  230. package/dest/versioning.d.ts +12 -0
  231. package/dest/versioning.d.ts.map +1 -0
  232. package/dest/versioning.js +33 -0
  233. package/package.json +127 -0
  234. package/src/bootstrap/bootstrap.ts +146 -0
  235. package/src/client/factory.ts +89 -0
  236. package/src/client/index.ts +2 -0
  237. package/src/client/p2p_client.ts +754 -0
  238. package/src/config.ts +371 -0
  239. package/src/enr/generate-enr.ts +39 -0
  240. package/src/enr/index.ts +1 -0
  241. package/src/errors/reqresp.error.ts +35 -0
  242. package/src/index.ts +7 -0
  243. package/src/mem_pools/attestation_pool/attestation_pool.ts +62 -0
  244. package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +230 -0
  245. package/src/mem_pools/attestation_pool/index.ts +2 -0
  246. package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +159 -0
  247. package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +161 -0
  248. package/src/mem_pools/attestation_pool/mocks.ts +44 -0
  249. package/src/mem_pools/index.ts +3 -0
  250. package/src/mem_pools/instrumentation.ts +126 -0
  251. package/src/mem_pools/interface.ts +12 -0
  252. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +309 -0
  253. package/src/mem_pools/tx_pool/index.ts +3 -0
  254. package/src/mem_pools/tx_pool/memory_tx_pool.ts +174 -0
  255. package/src/mem_pools/tx_pool/priority.ts +13 -0
  256. package/src/mem_pools/tx_pool/tx_pool.ts +76 -0
  257. package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +130 -0
  258. package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -0
  259. package/src/msg_validators/attestation_validator/index.ts +1 -0
  260. package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +29 -0
  261. package/src/msg_validators/block_proposal_validator/index.ts +1 -0
  262. package/src/msg_validators/index.ts +3 -0
  263. package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +32 -0
  264. package/src/msg_validators/tx_validator/block_header_validator.ts +25 -0
  265. package/src/msg_validators/tx_validator/data_validator.ts +106 -0
  266. package/src/msg_validators/tx_validator/double_spend_validator.ts +38 -0
  267. package/src/msg_validators/tx_validator/index.ts +6 -0
  268. package/src/msg_validators/tx_validator/metadata_validator.ts +48 -0
  269. package/src/msg_validators/tx_validator/tx_proof_validator.ts +18 -0
  270. package/src/services/data_store.ts +235 -0
  271. package/src/services/discv5/discV5_service.ts +256 -0
  272. package/src/services/dummy_service.ts +134 -0
  273. package/src/services/encoding.ts +79 -0
  274. package/src/services/gossipsub/scoring.ts +13 -0
  275. package/src/services/index.ts +2 -0
  276. package/src/services/libp2p/libp2p_service.ts +871 -0
  277. package/src/services/peer-manager/metrics.ts +41 -0
  278. package/src/services/peer-manager/peer_manager.ts +530 -0
  279. package/src/services/peer-manager/peer_scoring.ts +105 -0
  280. package/src/services/reqresp/config.ts +35 -0
  281. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
  282. package/src/services/reqresp/connection-sampler/connection_sampler.ts +217 -0
  283. package/src/services/reqresp/index.ts +4 -0
  284. package/src/services/reqresp/interface.ts +185 -0
  285. package/src/services/reqresp/metrics.ts +57 -0
  286. package/src/services/reqresp/protocols/block.ts +15 -0
  287. package/src/services/reqresp/protocols/goodbye.ts +101 -0
  288. package/src/services/reqresp/protocols/index.ts +8 -0
  289. package/src/services/reqresp/protocols/ping.ts +8 -0
  290. package/src/services/reqresp/protocols/status.ts +8 -0
  291. package/src/services/reqresp/protocols/tx.ts +29 -0
  292. package/src/services/reqresp/rate-limiter/index.ts +1 -0
  293. package/src/services/reqresp/rate-limiter/rate_limiter.ts +228 -0
  294. package/src/services/reqresp/rate-limiter/rate_limits.ts +55 -0
  295. package/src/services/reqresp/reqresp.ts +661 -0
  296. package/src/services/reqresp/status.ts +59 -0
  297. package/src/services/service.ts +112 -0
  298. package/src/test-helpers/generate-peer-id-private-keys.ts +15 -0
  299. package/src/test-helpers/get-ports.ts +8 -0
  300. package/src/test-helpers/index.ts +5 -0
  301. package/src/test-helpers/make-enrs.ts +44 -0
  302. package/src/test-helpers/make-test-p2p-clients.ts +122 -0
  303. package/src/test-helpers/reqresp-nodes.ts +289 -0
  304. package/src/testbench/README.md +20 -0
  305. package/src/testbench/p2p_client_testbench_worker.ts +152 -0
  306. package/src/testbench/parse_log_file.ts +175 -0
  307. package/src/testbench/testbench.ts +66 -0
  308. package/src/testbench/worker_client_manager.ts +318 -0
  309. package/src/types/index.ts +36 -0
  310. package/src/util.ts +196 -0
  311. package/src/versioning.ts +50 -0
@@ -0,0 +1,132 @@
1
+ /**
2
+ * A testbench worker that creates a p2p client and listens for commands from the parent.
3
+ *
4
+ * Used when running testbench commands
5
+ */ import { MockL2BlockSource } from '@aztec/archiver/test';
6
+ import { EthAddress } from '@aztec/foundation/eth-address';
7
+ import { createLogger } from '@aztec/foundation/log';
8
+ import { sleep } from '@aztec/foundation/sleep';
9
+ import { openTmpStore } from '@aztec/kv-store/lmdb-v2';
10
+ import { P2PClientType } from '@aztec/stdlib/p2p';
11
+ import { Tx, TxStatus } from '@aztec/stdlib/tx';
12
+ import { createP2PClient } from '../index.js';
13
+ import { AlwaysTrueCircuitVerifier } from '../test-helpers/reqresp-nodes.js';
14
+ // Simple mock implementation
15
+ function mockTxPool() {
16
+ // Mock all methods
17
+ return {
18
+ addTxs: ()=>Promise.resolve(),
19
+ getTxByHash: ()=>Promise.resolve(undefined),
20
+ getArchivedTxByHash: ()=>Promise.resolve(undefined),
21
+ markAsMined: ()=>Promise.resolve(),
22
+ markMinedAsPending: ()=>Promise.resolve(),
23
+ deleteTxs: ()=>Promise.resolve(),
24
+ getAllTxs: ()=>Promise.resolve([]),
25
+ getAllTxHashes: ()=>Promise.resolve([]),
26
+ getPendingTxHashes: ()=>Promise.resolve([]),
27
+ getMinedTxHashes: ()=>Promise.resolve([]),
28
+ getTxStatus: ()=>Promise.resolve(TxStatus.PENDING)
29
+ };
30
+ }
31
+ function mockAttestationPool() {
32
+ return {
33
+ addAttestations: ()=>Promise.resolve(),
34
+ deleteAttestations: ()=>Promise.resolve(),
35
+ deleteAttestationsOlderThan: ()=>Promise.resolve(),
36
+ deleteAttestationsForSlot: ()=>Promise.resolve(),
37
+ deleteAttestationsForSlotAndProposal: ()=>Promise.resolve(),
38
+ getAttestationsForSlot: ()=>Promise.resolve([])
39
+ };
40
+ }
41
+ function mockEpochCache() {
42
+ return {
43
+ getCommittee: ()=>Promise.resolve([]),
44
+ getProposerIndexEncoding: ()=>'0x',
45
+ getEpochAndSlotNow: ()=>({
46
+ epoch: 0n,
47
+ slot: 0n,
48
+ ts: 0n
49
+ }),
50
+ computeProposerIndex: ()=>0n,
51
+ getProposerInCurrentOrNextSlot: ()=>Promise.resolve({
52
+ currentProposer: EthAddress.ZERO,
53
+ nextProposer: EthAddress.ZERO,
54
+ currentSlot: 0n,
55
+ nextSlot: 0n
56
+ }),
57
+ isInCommittee: ()=>Promise.resolve(false)
58
+ };
59
+ }
60
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
61
+ process.on('message', async (msg)=>{
62
+ const { type, config, clientIndex } = msg;
63
+ try {
64
+ if (type === 'START') {
65
+ const txPool = mockTxPool();
66
+ const attestationPool = mockAttestationPool();
67
+ const epochCache = mockEpochCache();
68
+ const worldState = {};
69
+ const l2BlockSource = new MockL2BlockSource();
70
+ await l2BlockSource.createBlocks(100);
71
+ const proofVerifier = new AlwaysTrueCircuitVerifier();
72
+ const kvStore = await openTmpStore(`test-${clientIndex}`);
73
+ const logger = createLogger(`p2p:${clientIndex}`);
74
+ const deps = {
75
+ txPool,
76
+ attestationPool,
77
+ store: kvStore,
78
+ logger
79
+ };
80
+ const client = await createP2PClient(P2PClientType.Full, config, l2BlockSource, proofVerifier, worldState, epochCache, undefined, deps);
81
+ // Create spy for gossip messages
82
+ let gossipMessageCount = 0;
83
+ client.p2pService.handleNewGossipMessage = (msg, msgId, source)=>{
84
+ gossipMessageCount++;
85
+ process.send({
86
+ type: 'GOSSIP_RECEIVED',
87
+ count: gossipMessageCount
88
+ });
89
+ return client.p2pService.constructor.prototype.handleNewGossipMessage.apply(client.p2pService, [
90
+ msg,
91
+ msgId,
92
+ source
93
+ ]);
94
+ };
95
+ await client.start();
96
+ // Wait until the client is ready
97
+ for(let i = 0; i < 100; i++){
98
+ const isReady = client.isReady();
99
+ logger.debug(`Client ${clientIndex} isReady: ${isReady}`);
100
+ if (isReady) {
101
+ break;
102
+ }
103
+ await sleep(1000);
104
+ }
105
+ // Listen for commands from parent
106
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
107
+ process.on('message', async (cmd)=>{
108
+ switch(cmd.type){
109
+ case 'STOP':
110
+ await client.stop();
111
+ process.exit(0);
112
+ break;
113
+ case 'SEND_TX':
114
+ await client.sendTx(Tx.fromBuffer(Buffer.from(cmd.tx)));
115
+ process.send({
116
+ type: 'TX_SENT'
117
+ });
118
+ break;
119
+ }
120
+ });
121
+ process.send({
122
+ type: 'READY'
123
+ });
124
+ }
125
+ } catch (err) {
126
+ process.send({
127
+ type: 'ERROR',
128
+ error: err.message
129
+ });
130
+ process.exit(1);
131
+ }
132
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parse_log_file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse_log_file.d.ts","sourceRoot":"","sources":["../../src/testbench/parse_log_file.ts"],"names":[],"mappings":""}
@@ -0,0 +1,131 @@
1
+ // Parse Log File
2
+ // 1. Determine when a message was sent from the Sent Message log
3
+ // 2. Parse all Received Tx logs, extracting the timestamp and peer ID
4
+ // 3. Compute the delay for each peer relative to the timestamp of the sent message
5
+ // 4. Print the delays
6
+ import { createLogger } from '@aztec/foundation/log';
7
+ import * as fs from 'fs';
8
+ const logger = createLogger('parse_log_file');
9
+ function getTimestamp(line) {
10
+ const timestampMatch = line.match(/"time":(\d+)/);
11
+ if (!timestampMatch) {
12
+ return null;
13
+ }
14
+ return parseInt(timestampMatch[1], 10);
15
+ }
16
+ /**
17
+ * Parses a single log line. If the line contains an "rpc.from" event,
18
+ * it extracts the timestamp and the peer ID.
19
+ */ function parseReceivedTx(line) {
20
+ if (!line.includes('Received tx')) {
21
+ return null;
22
+ }
23
+ // Extract timestamp from the line: e.g. {"time":1740142435845}
24
+ const timestamp = getTimestamp(line);
25
+ if (!timestamp) {
26
+ logger.error('No timestamp found in received tx log');
27
+ return null;
28
+ }
29
+ // TODO: this is not correct - it is just the tx hash for now
30
+ // Extract the peer ID after "Received tx"
31
+ const peerIdMatch = line.match(/p2p:(\d+):/);
32
+ if (!peerIdMatch) {
33
+ logger.error('No peer Number found in received tx log');
34
+ return null;
35
+ }
36
+ const peerId = peerIdMatch[1];
37
+ return {
38
+ timestamp,
39
+ peerId
40
+ };
41
+ }
42
+ function parseSentMessage(line) {
43
+ if (!line.includes('Sent message')) {
44
+ return null;
45
+ }
46
+ const timestamp = getTimestamp(line);
47
+ if (!timestamp) {
48
+ logger.error('No timestamp found in sent message log');
49
+ return null;
50
+ }
51
+ return timestamp;
52
+ }
53
+ /**
54
+ * Processes the given log file, extracts all rpc.from events, computes the
55
+ * propagation delay for each peer relative to the earliest event, and prints
56
+ * some benchmark statistics.
57
+ */ function processLogFile(logFilePath, outputJsonPath) {
58
+ const content = fs.readFileSync(logFilePath, 'utf-8');
59
+ const lines = content.split('\n');
60
+ const events = [];
61
+ let t0 = 0;
62
+ // We begin our search as soon as we see the Sent message log
63
+ let messageSent = false;
64
+ for (const line of lines){
65
+ // Look for Sent message log
66
+ if (line.includes('Sent message')) {
67
+ messageSent = true;
68
+ t0 = parseSentMessage(line);
69
+ }
70
+ if (!messageSent) {
71
+ continue;
72
+ }
73
+ // Once we see the sent message log, we begin parsing Received tx logs
74
+ const event = parseReceivedTx(line);
75
+ if (event) {
76
+ events.push(event);
77
+ }
78
+ }
79
+ if (events.length === 0) {
80
+ logger.error('No message received events found in log file.');
81
+ return;
82
+ }
83
+ // Sort events by timestamp (ascending)
84
+ events.sort((a, b)=>a.timestamp - b.timestamp);
85
+ // Compute delay for each event relative to t0
86
+ const numberReceived = events.length;
87
+ const delays = events.map((e)=>({
88
+ peerId: e.peerId,
89
+ delay: e.timestamp - t0
90
+ }));
91
+ logger.info('Propagation delays (in ms) per peer:');
92
+ for (const d of delays){
93
+ logger.info(`${d.peerId}: ${d.delay} ms`);
94
+ }
95
+ // Compute basic statistics
96
+ const delayValues = delays.map((d)=>d.delay);
97
+ const minDelay = Math.min(...delayValues);
98
+ const maxDelay = Math.max(...delayValues);
99
+ const sumDelay = delayValues.reduce((sum, val)=>sum + val, 0);
100
+ const avgDelay = sumDelay / delayValues.length;
101
+ const sortedDelays = delayValues.slice().sort((a, b)=>a - b);
102
+ const medianDelay = sortedDelays[Math.floor(sortedDelays.length / 2)];
103
+ logger.info('\nBenchmark Statistics:');
104
+ logger.info(`Number of messages received: ${numberReceived}`);
105
+ logger.info(`Min delay: ${minDelay} ms`);
106
+ logger.info(`Max delay: ${maxDelay} ms`);
107
+ logger.info(`Average delay: ${avgDelay.toFixed(2)} ms`);
108
+ logger.info(`Median delay: ${medianDelay} ms`);
109
+ // If output JSON path is provided, write results to file
110
+ if (outputJsonPath) {
111
+ const result = {
112
+ delays,
113
+ stats: {
114
+ numberReceived,
115
+ minDelay,
116
+ maxDelay,
117
+ averageDelay: Number(avgDelay.toFixed(2)),
118
+ medianDelay
119
+ }
120
+ };
121
+ fs.writeFileSync(outputJsonPath, JSON.stringify(result, null, 2));
122
+ logger.info(`\nResults written to ${outputJsonPath}`);
123
+ }
124
+ }
125
+ // Get the log file path and optional output JSON path from command-line arguments
126
+ const [logFilePath, outputJsonPath] = process.argv.slice(2);
127
+ if (!logFilePath) {
128
+ logger.error('Usage: ts-node parse_log_file.ts <logFilePath> [outputJsonPath]');
129
+ process.exit(1);
130
+ }
131
+ processLogFile(logFilePath, outputJsonPath);
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=testbench.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testbench.d.ts","sourceRoot":"","sources":["../../src/testbench/testbench.ts"],"names":[],"mappings":""}
@@ -0,0 +1,61 @@
1
+ import { createLogger } from '@aztec/foundation/log';
2
+ import { sleep } from '@aztec/foundation/sleep';
3
+ import { ClientIvcProof } from '@aztec/stdlib/proofs';
4
+ import { mockTx } from '@aztec/stdlib/testing';
5
+ import assert from 'assert';
6
+ import path from 'path';
7
+ import { fileURLToPath } from 'url';
8
+ import { WorkerClientManager, testChainConfig } from './worker_client_manager.js';
9
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
+ const logger = createLogger('testbench');
11
+ async function main() {
12
+ try {
13
+ // Read configuration file name from command line args
14
+ const configFile = process.argv[2];
15
+ if (!configFile) {
16
+ throw new Error('Configuration file must be provided as first argument');
17
+ }
18
+ const configPath = path.join(__dirname, '../../testbench/configurations', configFile);
19
+ const config = await import(configPath, {
20
+ assert: {
21
+ type: 'json'
22
+ }
23
+ });
24
+ const testConfig = {
25
+ ...testChainConfig,
26
+ ...config.default
27
+ };
28
+ const numberOfClients = config.default.numberOfClients;
29
+ // Setup clients in separate processes
30
+ const workerClientManager = new WorkerClientManager(logger, testConfig);
31
+ await workerClientManager.makeWorkerClients(numberOfClients);
32
+ // wait a bit longer for all peers to be ready
33
+ await sleep(5000);
34
+ logger.info('Workers Ready');
35
+ // Send tx from client 0
36
+ const tx = await mockTx(1, {
37
+ clientIvcProof: ClientIvcProof.random()
38
+ });
39
+ workerClientManager.processes[0].send({
40
+ type: 'SEND_TX',
41
+ tx: tx.toBuffer()
42
+ });
43
+ logger.info('Transaction sent from client 0');
44
+ // Give time for message propagation
45
+ await sleep(30000);
46
+ logger.info('Checking message propagation results');
47
+ // Check message propagation results
48
+ const numberOfClientsThatReceivedMessage = workerClientManager.numberOfClientsThatReceivedMessage();
49
+ logger.info(`Number of clients that received message: ${numberOfClientsThatReceivedMessage}`);
50
+ assert(numberOfClientsThatReceivedMessage === numberOfClients - 1);
51
+ logger.info('Test passed, cleaning up');
52
+ // cleanup
53
+ await workerClientManager.cleanup();
54
+ } catch (error) {
55
+ logger.error('Test failed with error:', error);
56
+ process.exit(1);
57
+ }
58
+ }
59
+ main().catch((error)=>{
60
+ logger.error('Unhandled error:', error);
61
+ });
@@ -0,0 +1,56 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import type { Logger } from '@aztec/foundation/log';
3
+ import type { ChainConfig } from '@aztec/stdlib/config';
4
+ import { type ChildProcess } from 'child_process';
5
+ import { type P2PConfig } from '../config.js';
6
+ declare const testChainConfig: ChainConfig;
7
+ declare class WorkerClientManager {
8
+ processes: ChildProcess[];
9
+ peerIdPrivateKeys: string[];
10
+ peerEnrs: string[];
11
+ ports: number[];
12
+ private p2pConfig;
13
+ private logger;
14
+ private messageReceivedByClient;
15
+ constructor(logger: Logger, p2pConfig: Partial<P2PConfig>);
16
+ destroy(): void;
17
+ /**
18
+ * Creates address strings from a port
19
+ */
20
+ private getAddresses;
21
+ /**
22
+ * Creates a client configuration object
23
+ */
24
+ private createClientConfig;
25
+ /**
26
+ * Spawns a worker process and returns a promise that resolves when the worker is ready
27
+ */
28
+ private spawnWorkerProcess;
29
+ /**
30
+ * Creates a number of worker clients in separate processes
31
+ * All are configured to connect to each other and overrided with the test specific config
32
+ *
33
+ * @param numberOfClients - The number of clients to create
34
+ * @returns The ENRs of the created clients
35
+ */
36
+ makeWorkerClients(numberOfClients: number): Promise<string[]>;
37
+ purgeMessageReceivedByClient(): void;
38
+ numberOfClientsThatReceivedMessage(): number;
39
+ /**
40
+ * Changes the port for a specific client
41
+ *
42
+ * @param clientIndex - The index of the client to change port for
43
+ * @param newPort - The new port to use
44
+ */
45
+ changePort(clientIndex: number, newPort: number): Promise<void>;
46
+ /**
47
+ * Terminate a single process with timeout and force kill if needed
48
+ */
49
+ private terminateProcess;
50
+ /**
51
+ * Cleans up all worker processes with timeout and force kill if needed
52
+ */
53
+ cleanup(): Promise<void>;
54
+ }
55
+ export { WorkerClientManager, testChainConfig };
56
+ //# sourceMappingURL=worker_client_manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker_client_manager.d.ts","sourceRoot":"","sources":["../../src/testbench/worker_client_manager.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,KAAK,YAAY,EAAQ,MAAM,eAAe,CAAC;AAIxD,OAAO,EAAE,KAAK,SAAS,EAAuB,MAAM,cAAc,CAAC;AAQnE,QAAA,MAAM,eAAe,EAAE,WAMtB,CAAC;AAEF,cAAM,mBAAmB;IAChB,SAAS,EAAE,YAAY,EAAE,CAAM;IAC/B,iBAAiB,EAAE,MAAM,EAAE,CAAM;IACjC,QAAQ,EAAE,MAAM,EAAE,CAAM;IACxB,KAAK,EAAE,MAAM,EAAE,CAAM;IAC5B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,uBAAuB,CAAgB;gBAEnC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC;IAKzD,OAAO;IAOP;;OAEG;IACH,OAAO,CAAC,YAAY;IAOpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAgB1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoD1B;;;;;;OAMG;IACG,iBAAiB,CAAC,eAAe,EAAE,MAAM;IA2C/C,4BAA4B;IAI5B,kCAAkC;IAIlC;;;;;OAKG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IA4CrD;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAsCxB;;OAEG;IACG,OAAO;CAiCd;AAED,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,266 @@
1
+ import { EthAddress } from '@aztec/foundation/eth-address';
2
+ import { sleep } from '@aztec/foundation/sleep';
3
+ import { fork } from 'child_process';
4
+ import path from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { getP2PDefaultConfig } from '../config.js';
7
+ import { generatePeerIdPrivateKeys } from '../test-helpers/generate-peer-id-private-keys.js';
8
+ import { getPorts } from '../test-helpers/get-ports.js';
9
+ import { makeEnr, makeEnrs } from '../test-helpers/make-enrs.js';
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const workerPath = path.join(__dirname, '../../dest/testbench/p2p_client_testbench_worker.js');
12
+ const testChainConfig = {
13
+ l1ChainId: 31337,
14
+ version: 1,
15
+ l1Contracts: {
16
+ rollupAddress: EthAddress.random()
17
+ }
18
+ };
19
+ class WorkerClientManager {
20
+ processes = [];
21
+ peerIdPrivateKeys = [];
22
+ peerEnrs = [];
23
+ ports = [];
24
+ p2pConfig;
25
+ logger;
26
+ messageReceivedByClient = [];
27
+ constructor(logger, p2pConfig){
28
+ this.logger = logger;
29
+ this.p2pConfig = p2pConfig;
30
+ }
31
+ destroy() {
32
+ this.cleanup().catch((error)=>{
33
+ this.logger.error('Failed to cleanup worker client manager', error);
34
+ process.exit(1);
35
+ });
36
+ }
37
+ /**
38
+ * Creates address strings from a port
39
+ */ getAddresses(port) {
40
+ return {
41
+ addr: `127.0.0.1:${port}`,
42
+ listenAddr: `0.0.0.0:${port}`
43
+ };
44
+ }
45
+ /**
46
+ * Creates a client configuration object
47
+ */ createClientConfig(clientIndex, port, otherNodes) {
48
+ const { addr, listenAddr } = this.getAddresses(port);
49
+ return {
50
+ ...getP2PDefaultConfig(),
51
+ p2pEnabled: true,
52
+ peerIdPrivateKey: this.peerIdPrivateKeys[clientIndex],
53
+ tcpListenAddress: listenAddr,
54
+ udpListenAddress: listenAddr,
55
+ tcpAnnounceAddress: addr,
56
+ udpAnnounceAddress: addr,
57
+ bootstrapNodes: [
58
+ ...otherNodes
59
+ ],
60
+ ...this.p2pConfig
61
+ };
62
+ }
63
+ /**
64
+ * Spawns a worker process and returns a promise that resolves when the worker is ready
65
+ */ spawnWorkerProcess(config, clientIndex) {
66
+ const childProcess = fork(workerPath);
67
+ childProcess.send({
68
+ type: 'START',
69
+ config,
70
+ clientIndex
71
+ });
72
+ // Handle unexpected child process exit
73
+ childProcess.on('exit', (code, signal)=>{
74
+ if (code !== 0) {
75
+ this.logger.warn(`Worker ${clientIndex} exited unexpectedly with code ${code} and signal ${signal}`);
76
+ }
77
+ });
78
+ childProcess.on('message', (msg)=>{
79
+ if (msg.type === 'GOSSIP_RECEIVED') {
80
+ this.messageReceivedByClient[clientIndex] = msg.count;
81
+ }
82
+ });
83
+ // Create ready signal promise
84
+ const readySignal = new Promise((resolve, reject)=>{
85
+ // Set a timeout to avoid hanging indefinitely
86
+ const timeout = setTimeout(()=>{
87
+ reject(new Error(`Timeout waiting for worker ${clientIndex} to be ready`));
88
+ }, 30000); // 30 second timeout
89
+ childProcess.once('message', (msg)=>{
90
+ clearTimeout(timeout);
91
+ if (msg.type === 'READY') {
92
+ resolve();
93
+ }
94
+ // For future use
95
+ if (msg.type === 'ERROR') {
96
+ reject(new Error(msg.error));
97
+ }
98
+ });
99
+ // Also resolve/reject if process exits before sending message
100
+ childProcess.once('exit', (code)=>{
101
+ clearTimeout(timeout);
102
+ if (code === 0) {
103
+ resolve();
104
+ } else {
105
+ reject(new Error(`Worker ${clientIndex} exited with code ${code} before becoming ready`));
106
+ }
107
+ });
108
+ });
109
+ return [
110
+ childProcess,
111
+ readySignal
112
+ ];
113
+ }
114
+ /**
115
+ * Creates a number of worker clients in separate processes
116
+ * All are configured to connect to each other and overrided with the test specific config
117
+ *
118
+ * @param numberOfClients - The number of clients to create
119
+ * @returns The ENRs of the created clients
120
+ */ async makeWorkerClients(numberOfClients) {
121
+ try {
122
+ this.messageReceivedByClient = new Array(numberOfClients).fill(0);
123
+ this.peerIdPrivateKeys = generatePeerIdPrivateKeys(numberOfClients);
124
+ this.ports = await getPorts(numberOfClients);
125
+ this.peerEnrs = await makeEnrs(this.peerIdPrivateKeys, this.ports, testChainConfig);
126
+ this.processes = [];
127
+ const readySignals = [];
128
+ for(let i = 0; i < numberOfClients; i++){
129
+ this.logger.info(`Creating client ${i}`);
130
+ // Maximum seed with 10 other peers to allow peer discovery to connect them at a smoother rate
131
+ const otherNodes = this.peerEnrs.filter((_, ind)=>ind < Math.min(i, 10));
132
+ const config = this.createClientConfig(i, this.ports[i], otherNodes);
133
+ const [childProcess, readySignal] = this.spawnWorkerProcess(config, i);
134
+ readySignals.push(readySignal);
135
+ this.processes.push(childProcess);
136
+ }
137
+ // Wait for peers to all connect with each other
138
+ await sleep(10000);
139
+ // Wait for all peers to be booted up with timeout
140
+ await Promise.race([
141
+ Promise.all(readySignals),
142
+ new Promise((_, reject)=>setTimeout(()=>reject(new Error('Timeout waiting for all workers to be ready')), 30000))
143
+ ]);
144
+ return this.peerEnrs;
145
+ } catch (error) {
146
+ // Clean up any processes that were created if there's an error
147
+ this.logger.error('Error during makeWorkerClients:', error);
148
+ await this.cleanup();
149
+ throw error;
150
+ }
151
+ }
152
+ purgeMessageReceivedByClient() {
153
+ this.messageReceivedByClient = new Array(this.processes.length).fill(0);
154
+ }
155
+ numberOfClientsThatReceivedMessage() {
156
+ return this.messageReceivedByClient.filter((count)=>count > 0).length;
157
+ }
158
+ /**
159
+ * Changes the port for a specific client
160
+ *
161
+ * @param clientIndex - The index of the client to change port for
162
+ * @param newPort - The new port to use
163
+ */ async changePort(clientIndex, newPort) {
164
+ try {
165
+ if (clientIndex < 0 || clientIndex >= this.processes.length) {
166
+ throw new Error(`Invalid client index: ${clientIndex}`);
167
+ }
168
+ this.processes[clientIndex].send({
169
+ type: 'STOP'
170
+ });
171
+ // Wait for the process to be ready with a timeout
172
+ await sleep(10000);
173
+ this.logger.info(`Changing port for client ${clientIndex} to ${newPort}`);
174
+ // Update the port in the ports array
175
+ this.ports[clientIndex] = newPort;
176
+ // Update the port in the peerEnrs array
177
+ this.peerEnrs[clientIndex] = await makeEnr(this.peerIdPrivateKeys[clientIndex], newPort, testChainConfig);
178
+ // Maximum seed with 10 other peers to allow peer discovery to connect them at a smoother rate
179
+ const otherNodes = this.peerEnrs.filter((_, ind)=>ind !== clientIndex && ind < Math.min(this.peerEnrs.length, 10));
180
+ const config = this.createClientConfig(clientIndex, newPort, otherNodes);
181
+ const [childProcess, readySignal] = this.spawnWorkerProcess(config, clientIndex);
182
+ this.processes[clientIndex] = childProcess;
183
+ // Wait for the process to be ready with a timeout
184
+ await Promise.race([
185
+ readySignal,
186
+ new Promise((_, reject)=>setTimeout(()=>reject(new Error(`Timeout waiting for client ${clientIndex} to be ready`)), 30000))
187
+ ]);
188
+ } catch (error) {
189
+ this.logger.error(`Error during changePort for client ${clientIndex}:`, error);
190
+ // Only clean up the specific process that had an issue
191
+ await this.terminateProcess(this.processes[clientIndex], clientIndex);
192
+ throw error;
193
+ }
194
+ }
195
+ /**
196
+ * Terminate a single process with timeout and force kill if needed
197
+ */ terminateProcess(process1, index) {
198
+ if (!process1 || process1.killed) {
199
+ return Promise.resolve();
200
+ }
201
+ return new Promise((resolve)=>{
202
+ // Set a timeout for the graceful exit
203
+ const forceKillTimeout = setTimeout(()=>{
204
+ this.logger.warn(`Process ${index} didn't exit gracefully, force killing...`);
205
+ try {
206
+ process1.kill('SIGKILL'); // Force kill
207
+ } catch (e) {
208
+ this.logger.error(`Error force killing process ${index}:`, e);
209
+ }
210
+ }, 10000); // 10 second timeout for graceful exit
211
+ // Listen for process exit
212
+ process1.once('exit', ()=>{
213
+ clearTimeout(forceKillTimeout);
214
+ resolve();
215
+ });
216
+ // Try to gracefully stop the process
217
+ try {
218
+ process1.send({
219
+ type: 'STOP'
220
+ });
221
+ } catch (e) {
222
+ // If sending the message fails, force kill immediately
223
+ clearTimeout(forceKillTimeout);
224
+ try {
225
+ process1.kill('SIGKILL');
226
+ } catch (killError) {
227
+ this.logger.error(`Error force killing process ${index}:`, killError);
228
+ }
229
+ resolve();
230
+ }
231
+ });
232
+ }
233
+ /**
234
+ * Cleans up all worker processes with timeout and force kill if needed
235
+ */ async cleanup() {
236
+ this.logger.info(`Cleaning up ${this.processes.length} worker processes`);
237
+ // Create array of promises for each process termination
238
+ const terminationPromises = this.processes.map((process1, index)=>this.terminateProcess(process1, index));
239
+ // Wait for all processes to terminate with a timeout
240
+ try {
241
+ await Promise.race([
242
+ Promise.all(terminationPromises),
243
+ new Promise((resolve)=>{
244
+ setTimeout(()=>{
245
+ this.logger.warn('Some processes did not terminate in time, force killing all remaining...');
246
+ this.processes.forEach((p)=>{
247
+ try {
248
+ if (!p.killed) {
249
+ p.kill('SIGKILL');
250
+ }
251
+ } catch (e) {
252
+ // Ignore errors when force killing
253
+ }
254
+ });
255
+ resolve();
256
+ }, 30000); // 30 second timeout for all processes
257
+ })
258
+ ]);
259
+ } catch (error) {
260
+ this.logger.error('Error during cleanup:', error);
261
+ }
262
+ this.processes = [];
263
+ this.logger.info('All worker processes cleaned up');
264
+ }
265
+ }
266
+ export { WorkerClientManager, testChainConfig };