@aztec/p2p 0.0.1-commit.f295ac2 → 0.0.1-commit.fc805bf

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 (263) hide show
  1. package/dest/bootstrap/bootstrap.d.ts +4 -3
  2. package/dest/bootstrap/bootstrap.d.ts.map +1 -1
  3. package/dest/bootstrap/bootstrap.js +4 -4
  4. package/dest/client/factory.d.ts +1 -1
  5. package/dest/client/factory.d.ts.map +1 -1
  6. package/dest/client/factory.js +6 -5
  7. package/dest/client/p2p_client.d.ts +1 -1
  8. package/dest/client/p2p_client.d.ts.map +1 -1
  9. package/dest/client/p2p_client.js +9 -2
  10. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts +2 -0
  11. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.d.ts.map +1 -0
  12. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker.js +305 -0
  13. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts +73 -0
  14. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.d.ts.map +1 -0
  15. package/dest/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.js +8 -0
  16. package/dest/config.d.ts +8 -2
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +2 -0
  19. package/dest/mem_pools/instrumentation.d.ts +1 -1
  20. package/dest/mem_pools/instrumentation.d.ts.map +1 -1
  21. package/dest/mem_pools/instrumentation.js +2 -2
  22. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +3 -3
  23. package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -1
  24. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts +3 -2
  25. package/dest/mem_pools/tx_pool/eviction/eviction_manager.d.ts.map +1 -1
  26. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts +3 -2
  27. package/dest/mem_pools/tx_pool/eviction/eviction_strategy.d.ts.map +1 -1
  28. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts +3 -3
  29. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.d.ts.map +1 -1
  30. package/dest/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.js +8 -1
  31. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts +3 -3
  32. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.d.ts.map +1 -1
  33. package/dest/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.js +2 -0
  34. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +3 -3
  35. package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -1
  36. package/dest/msg_validators/attestation_validator/attestation_validator.js +41 -10
  37. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts +3 -3
  38. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.d.ts.map +1 -1
  39. package/dest/msg_validators/attestation_validator/fisherman_attestation_validator.js +18 -6
  40. package/dest/msg_validators/clock_tolerance.d.ts +21 -0
  41. package/dest/msg_validators/clock_tolerance.d.ts.map +1 -0
  42. package/dest/msg_validators/clock_tolerance.js +37 -0
  43. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts +3 -3
  44. package/dest/msg_validators/proposal_validator/proposal_validator.d.ts.map +1 -1
  45. package/dest/msg_validators/proposal_validator/proposal_validator.js +55 -31
  46. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts +3 -3
  47. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.d.ts.map +1 -1
  48. package/dest/msg_validators/proposal_validator/proposal_validator_test_suite.js +93 -64
  49. package/dest/msg_validators/tx_validator/archive_cache.d.ts +3 -3
  50. package/dest/msg_validators/tx_validator/archive_cache.d.ts.map +1 -1
  51. package/dest/msg_validators/tx_validator/archive_cache.js +1 -1
  52. package/dest/msg_validators/tx_validator/block_header_validator.d.ts +5 -4
  53. package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -1
  54. package/dest/msg_validators/tx_validator/block_header_validator.js +3 -2
  55. package/dest/msg_validators/tx_validator/data_validator.d.ts +3 -1
  56. package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -1
  57. package/dest/msg_validators/tx_validator/data_validator.js +4 -1
  58. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +3 -2
  59. package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -1
  60. package/dest/msg_validators/tx_validator/double_spend_validator.js +3 -2
  61. package/dest/msg_validators/tx_validator/factory.d.ts +8 -3
  62. package/dest/msg_validators/tx_validator/factory.d.ts.map +1 -1
  63. package/dest/msg_validators/tx_validator/factory.js +21 -11
  64. package/dest/msg_validators/tx_validator/gas_validator.d.ts +3 -2
  65. package/dest/msg_validators/tx_validator/gas_validator.d.ts.map +1 -1
  66. package/dest/msg_validators/tx_validator/gas_validator.js +3 -2
  67. package/dest/msg_validators/tx_validator/index.d.ts +2 -1
  68. package/dest/msg_validators/tx_validator/index.d.ts.map +1 -1
  69. package/dest/msg_validators/tx_validator/index.js +1 -0
  70. package/dest/msg_validators/tx_validator/metadata_validator.d.ts +3 -2
  71. package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -1
  72. package/dest/msg_validators/tx_validator/metadata_validator.js +2 -2
  73. package/dest/msg_validators/tx_validator/phases_validator.d.ts +3 -2
  74. package/dest/msg_validators/tx_validator/phases_validator.d.ts.map +1 -1
  75. package/dest/msg_validators/tx_validator/phases_validator.js +3 -3
  76. package/dest/msg_validators/tx_validator/size_validator.d.ts +8 -0
  77. package/dest/msg_validators/tx_validator/size_validator.d.ts.map +1 -0
  78. package/dest/msg_validators/tx_validator/size_validator.js +23 -0
  79. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts +3 -2
  80. package/dest/msg_validators/tx_validator/timestamp_validator.d.ts.map +1 -1
  81. package/dest/msg_validators/tx_validator/timestamp_validator.js +2 -2
  82. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts +3 -2
  83. package/dest/msg_validators/tx_validator/tx_permitted_validator.d.ts.map +1 -1
  84. package/dest/msg_validators/tx_validator/tx_permitted_validator.js +2 -2
  85. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +3 -2
  86. package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -1
  87. package/dest/msg_validators/tx_validator/tx_proof_validator.js +2 -2
  88. package/dest/services/data_store.d.ts +1 -1
  89. package/dest/services/data_store.d.ts.map +1 -1
  90. package/dest/services/data_store.js +10 -6
  91. package/dest/services/discv5/discV5_service.js +1 -1
  92. package/dest/services/dummy_service.d.ts +13 -1
  93. package/dest/services/dummy_service.d.ts.map +1 -1
  94. package/dest/services/dummy_service.js +39 -0
  95. package/dest/services/encoding.d.ts +1 -1
  96. package/dest/services/encoding.d.ts.map +1 -1
  97. package/dest/services/encoding.js +2 -3
  98. package/dest/services/libp2p/instrumentation.d.ts +1 -1
  99. package/dest/services/libp2p/instrumentation.d.ts.map +1 -1
  100. package/dest/services/libp2p/instrumentation.js +14 -3
  101. package/dest/services/libp2p/libp2p_service.d.ts +13 -7
  102. package/dest/services/libp2p/libp2p_service.d.ts.map +1 -1
  103. package/dest/services/libp2p/libp2p_service.js +60 -51
  104. package/dest/services/peer-manager/metrics.d.ts +2 -2
  105. package/dest/services/peer-manager/metrics.d.ts.map +1 -1
  106. package/dest/services/peer-manager/metrics.js +20 -5
  107. package/dest/services/peer-manager/peer_scoring.d.ts +1 -1
  108. package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -1
  109. package/dest/services/peer-manager/peer_scoring.js +8 -2
  110. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts +47 -0
  111. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.d.ts.map +1 -0
  112. package/dest/services/reqresp/batch-tx-requester/batch_tx_requester.js +566 -0
  113. package/dest/services/reqresp/batch-tx-requester/config.d.ts +17 -0
  114. package/dest/services/reqresp/batch-tx-requester/config.d.ts.map +1 -0
  115. package/dest/services/reqresp/batch-tx-requester/config.js +27 -0
  116. package/dest/services/reqresp/batch-tx-requester/interface.d.ts +50 -0
  117. package/dest/services/reqresp/batch-tx-requester/interface.d.ts.map +1 -0
  118. package/dest/services/reqresp/batch-tx-requester/interface.js +1 -0
  119. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts +37 -0
  120. package/dest/services/reqresp/batch-tx-requester/missing_txs.d.ts.map +1 -0
  121. package/dest/services/reqresp/batch-tx-requester/missing_txs.js +151 -0
  122. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts +54 -0
  123. package/dest/services/reqresp/batch-tx-requester/peer_collection.d.ts.map +1 -0
  124. package/dest/services/reqresp/batch-tx-requester/peer_collection.js +139 -0
  125. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts +20 -0
  126. package/dest/services/reqresp/batch-tx-requester/tx_validator.d.ts.map +1 -0
  127. package/dest/services/reqresp/batch-tx-requester/tx_validator.js +21 -0
  128. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +22 -3
  129. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -1
  130. package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +63 -4
  131. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +2 -1
  132. package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -1
  133. package/dest/services/reqresp/connection-sampler/connection_sampler.js +12 -0
  134. package/dest/services/reqresp/interface.d.ts +5 -3
  135. package/dest/services/reqresp/interface.d.ts.map +1 -1
  136. package/dest/services/reqresp/interface.js +2 -2
  137. package/dest/services/reqresp/metrics.d.ts +6 -5
  138. package/dest/services/reqresp/metrics.d.ts.map +1 -1
  139. package/dest/services/reqresp/metrics.js +17 -5
  140. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts +5 -1
  141. package/dest/services/reqresp/protocols/block_txs/bitvector.d.ts.map +1 -1
  142. package/dest/services/reqresp/protocols/block_txs/bitvector.js +5 -0
  143. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts +1 -1
  144. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.d.ts.map +1 -1
  145. package/dest/services/reqresp/protocols/block_txs/block_txs_handler.js +16 -3
  146. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts +18 -6
  147. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.d.ts.map +1 -1
  148. package/dest/services/reqresp/protocols/block_txs/block_txs_reqresp.js +43 -13
  149. package/dest/services/reqresp/reqresp.d.ts +6 -1
  150. package/dest/services/reqresp/reqresp.d.ts.map +1 -1
  151. package/dest/services/reqresp/reqresp.js +58 -22
  152. package/dest/services/service.d.ts +4 -1
  153. package/dest/services/service.d.ts.map +1 -1
  154. package/dest/services/tx_collection/config.d.ts +4 -1
  155. package/dest/services/tx_collection/config.d.ts.map +1 -1
  156. package/dest/services/tx_collection/config.js +9 -1
  157. package/dest/services/tx_collection/fast_tx_collection.d.ts +6 -4
  158. package/dest/services/tx_collection/fast_tx_collection.d.ts.map +1 -1
  159. package/dest/services/tx_collection/fast_tx_collection.js +16 -5
  160. package/dest/services/tx_collection/index.d.ts +2 -1
  161. package/dest/services/tx_collection/index.d.ts.map +1 -1
  162. package/dest/services/tx_collection/index.js +1 -0
  163. package/dest/services/tx_collection/instrumentation.d.ts +1 -1
  164. package/dest/services/tx_collection/instrumentation.d.ts.map +1 -1
  165. package/dest/services/tx_collection/instrumentation.js +9 -2
  166. package/dest/services/tx_collection/proposal_tx_collector.d.ts +48 -0
  167. package/dest/services/tx_collection/proposal_tx_collector.d.ts.map +1 -0
  168. package/dest/services/tx_collection/proposal_tx_collector.js +50 -0
  169. package/dest/services/tx_collection/slow_tx_collection.d.ts +3 -3
  170. package/dest/services/tx_collection/slow_tx_collection.d.ts.map +1 -1
  171. package/dest/services/tx_collection/tx_collection.d.ts +8 -8
  172. package/dest/services/tx_collection/tx_collection.d.ts.map +1 -1
  173. package/dest/services/tx_collection/tx_collection.js +5 -5
  174. package/dest/services/tx_provider.d.ts +3 -3
  175. package/dest/services/tx_provider.d.ts.map +1 -1
  176. package/dest/services/tx_provider_instrumentation.d.ts +1 -1
  177. package/dest/services/tx_provider_instrumentation.d.ts.map +1 -1
  178. package/dest/services/tx_provider_instrumentation.js +5 -5
  179. package/dest/test-helpers/index.d.ts +3 -1
  180. package/dest/test-helpers/index.d.ts.map +1 -1
  181. package/dest/test-helpers/index.js +2 -0
  182. package/dest/test-helpers/test_tx_provider.d.ts +40 -0
  183. package/dest/test-helpers/test_tx_provider.d.ts.map +1 -0
  184. package/dest/test-helpers/test_tx_provider.js +41 -0
  185. package/dest/test-helpers/testbench-utils.d.ts +158 -0
  186. package/dest/test-helpers/testbench-utils.d.ts.map +1 -0
  187. package/dest/test-helpers/testbench-utils.js +297 -0
  188. package/dest/testbench/p2p_client_testbench_worker.d.ts +28 -2
  189. package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -1
  190. package/dest/testbench/p2p_client_testbench_worker.js +212 -133
  191. package/dest/testbench/worker_client_manager.d.ts +51 -6
  192. package/dest/testbench/worker_client_manager.d.ts.map +1 -1
  193. package/dest/testbench/worker_client_manager.js +226 -44
  194. package/package.json +14 -14
  195. package/src/bootstrap/bootstrap.ts +7 -4
  196. package/src/client/factory.ts +6 -10
  197. package/src/client/p2p_client.ts +14 -7
  198. package/src/client/test/tx_proposal_collector/README.md +227 -0
  199. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker.ts +336 -0
  200. package/src/client/test/tx_proposal_collector/proposal_tx_collector_worker_protocol.ts +43 -0
  201. package/src/config.ts +6 -1
  202. package/src/mem_pools/instrumentation.ts +2 -1
  203. package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +2 -2
  204. package/src/mem_pools/tx_pool/eviction/eviction_manager.ts +2 -1
  205. package/src/mem_pools/tx_pool/eviction/eviction_strategy.ts +2 -1
  206. package/src/mem_pools/tx_pool/eviction/fee_payer_balance_eviction_rule.ts +10 -7
  207. package/src/mem_pools/tx_pool/eviction/invalid_txs_after_reorg_rule.ts +4 -2
  208. package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -14
  209. package/src/msg_validators/attestation_validator/fisherman_attestation_validator.ts +14 -8
  210. package/src/msg_validators/clock_tolerance.ts +51 -0
  211. package/src/msg_validators/proposal_validator/proposal_validator.ts +31 -31
  212. package/src/msg_validators/proposal_validator/proposal_validator_test_suite.ts +91 -67
  213. package/src/msg_validators/tx_validator/archive_cache.ts +3 -3
  214. package/src/msg_validators/tx_validator/block_header_validator.ts +6 -5
  215. package/src/msg_validators/tx_validator/data_validator.ts +6 -2
  216. package/src/msg_validators/tx_validator/double_spend_validator.ts +4 -3
  217. package/src/msg_validators/tx_validator/factory.ts +64 -23
  218. package/src/msg_validators/tx_validator/gas_validator.ts +9 -3
  219. package/src/msg_validators/tx_validator/index.ts +1 -0
  220. package/src/msg_validators/tx_validator/metadata_validator.ts +6 -3
  221. package/src/msg_validators/tx_validator/phases_validator.ts +5 -3
  222. package/src/msg_validators/tx_validator/size_validator.ts +22 -0
  223. package/src/msg_validators/tx_validator/timestamp_validator.ts +6 -3
  224. package/src/msg_validators/tx_validator/tx_permitted_validator.ts +8 -3
  225. package/src/msg_validators/tx_validator/tx_proof_validator.ts +8 -3
  226. package/src/services/data_store.ts +10 -7
  227. package/src/services/discv5/discV5_service.ts +1 -1
  228. package/src/services/dummy_service.ts +45 -0
  229. package/src/services/encoding.ts +2 -3
  230. package/src/services/libp2p/instrumentation.ts +15 -2
  231. package/src/services/libp2p/libp2p_service.ts +99 -73
  232. package/src/services/peer-manager/metrics.ts +21 -4
  233. package/src/services/peer-manager/peer_scoring.ts +4 -1
  234. package/src/services/reqresp/batch-tx-requester/README.md +305 -0
  235. package/src/services/reqresp/batch-tx-requester/batch_tx_requester.ts +706 -0
  236. package/src/services/reqresp/batch-tx-requester/config.ts +40 -0
  237. package/src/services/reqresp/batch-tx-requester/interface.ts +57 -0
  238. package/src/services/reqresp/batch-tx-requester/missing_txs.ts +209 -0
  239. package/src/services/reqresp/batch-tx-requester/peer_collection.ts +205 -0
  240. package/src/services/reqresp/batch-tx-requester/tx_validator.ts +37 -0
  241. package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +65 -4
  242. package/src/services/reqresp/connection-sampler/connection_sampler.ts +16 -0
  243. package/src/services/reqresp/interface.ts +5 -2
  244. package/src/services/reqresp/metrics.ts +34 -9
  245. package/src/services/reqresp/protocols/block_txs/bitvector.ts +7 -0
  246. package/src/services/reqresp/protocols/block_txs/block_txs_handler.ts +18 -4
  247. package/src/services/reqresp/protocols/block_txs/block_txs_reqresp.ts +51 -9
  248. package/src/services/reqresp/reqresp.ts +66 -19
  249. package/src/services/service.ts +4 -0
  250. package/src/services/tx_collection/config.ts +15 -1
  251. package/src/services/tx_collection/fast_tx_collection.ts +36 -13
  252. package/src/services/tx_collection/index.ts +5 -0
  253. package/src/services/tx_collection/instrumentation.ts +11 -2
  254. package/src/services/tx_collection/proposal_tx_collector.ts +114 -0
  255. package/src/services/tx_collection/slow_tx_collection.ts +2 -2
  256. package/src/services/tx_collection/tx_collection.ts +8 -8
  257. package/src/services/tx_provider.ts +2 -2
  258. package/src/services/tx_provider_instrumentation.ts +11 -5
  259. package/src/test-helpers/index.ts +2 -0
  260. package/src/test-helpers/test_tx_provider.ts +64 -0
  261. package/src/test-helpers/testbench-utils.ts +374 -0
  262. package/src/testbench/p2p_client_testbench_worker.ts +321 -126
  263. package/src/testbench/worker_client_manager.ts +304 -47
@@ -1,10 +1,10 @@
1
- import { SecretValue } from '@aztec/foundation/config';
2
1
  import { EthAddress } from '@aztec/foundation/eth-address';
3
2
  import type { Logger } from '@aztec/foundation/log';
4
3
  import { sleep } from '@aztec/foundation/sleep';
5
4
  import type { ChainConfig } from '@aztec/stdlib/config';
6
5
 
7
6
  import { type ChildProcess, fork } from 'child_process';
7
+ import { existsSync } from 'fs';
8
8
  import path from 'path';
9
9
  import { fileURLToPath } from 'url';
10
10
 
@@ -12,9 +12,19 @@ import { type P2PConfig, getP2PDefaultConfig } from '../config.js';
12
12
  import { generatePeerIdPrivateKeys } from '../test-helpers/generate-peer-id-private-keys.js';
13
13
  import { getPorts } from '../test-helpers/get-ports.js';
14
14
  import { makeEnr, makeEnrs } from '../test-helpers/make-enrs.js';
15
+ import { BENCHMARK_CONSTANTS } from '../test-helpers/testbench-utils.js';
16
+ import type {
17
+ BenchReqRespCommand,
18
+ BenchResultMessage,
19
+ CollectorType,
20
+ DistributionPattern,
21
+ } from './p2p_client_testbench_worker.js';
15
22
 
16
23
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
17
- const workerPath = path.join(__dirname, '../../dest/testbench/p2p_client_testbench_worker.js');
24
+ const p2pRoot = path.resolve(__dirname, '../..');
25
+ const workerTsPath = path.join(__dirname, 'p2p_client_testbench_worker.ts');
26
+ const workerJsPath = path.join(p2pRoot, 'dest/testbench/p2p_client_testbench_worker.js');
27
+ const tsconfigPath = path.join(p2pRoot, 'tsconfig.json');
18
28
 
19
29
  const testChainConfig: ChainConfig = {
20
30
  l1ChainId: 31337,
@@ -24,11 +34,32 @@ const testChainConfig: ChainConfig = {
24
34
  },
25
35
  };
26
36
 
37
+ export interface ReqRespBenchmarkConfig {
38
+ txCount: number;
39
+ distribution: DistributionPattern;
40
+ collectorType: CollectorType;
41
+ timeoutMs: number;
42
+ pinnedPeerIndex?: number;
43
+ blockNumber?: number;
44
+ seed?: number;
45
+ }
46
+
47
+ export interface ReqRespBenchmarkResult {
48
+ txCount: number;
49
+ distribution: DistributionPattern;
50
+ collector: CollectorType;
51
+ durationMs: number;
52
+ fetchedCount: number;
53
+ success: boolean;
54
+ error?: string;
55
+ }
56
+
27
57
  class WorkerClientManager {
28
58
  public processes: ChildProcess[] = [];
29
59
  public peerIdPrivateKeys: string[] = [];
30
60
  public peerEnrs: string[] = [];
31
61
  public ports: number[] = [];
62
+ public peerIds: string[] = [];
32
63
  private p2pConfig: Partial<P2PConfig>;
33
64
  private logger: Logger;
34
65
  private messageReceivedByClient: number[] = [];
@@ -46,39 +77,55 @@ class WorkerClientManager {
46
77
  }
47
78
 
48
79
  /**
49
- * Creates a client configuration object
80
+ * Creates a client configuration object for IPC.
81
+ * Note: We send the raw peerIdPrivateKey string instead of SecretValue
82
+ * because SecretValue.toJSON() returns '[Redacted]', losing the value.
83
+ * The worker must re-wrap it in SecretValue.
50
84
  */
51
85
  private createClientConfig(
52
86
  clientIndex: number,
53
87
  port: number,
54
88
  otherNodes: string[],
55
- ): P2PConfig & Partial<ChainConfig> {
89
+ ): Omit<P2PConfig, 'peerIdPrivateKey'> & { peerIdPrivateKey: string } & Partial<ChainConfig> {
56
90
  return {
57
91
  ...getP2PDefaultConfig(),
58
92
  p2pEnabled: true,
59
- peerIdPrivateKey: new SecretValue(this.peerIdPrivateKeys[clientIndex]),
93
+ peerIdPrivateKey: this.peerIdPrivateKeys[clientIndex],
60
94
  listenAddress: '127.0.0.1',
61
95
  p2pIp: '127.0.0.1',
62
96
  p2pPort: port,
63
97
  bootstrapNodes: [...otherNodes],
64
98
  ...this.p2pConfig,
65
- };
99
+ } as Omit<P2PConfig, 'peerIdPrivateKey'> & { peerIdPrivateKey: string } & Partial<ChainConfig>;
66
100
  }
67
101
 
68
102
  /**
69
- * Spawns a worker process and returns a promise that resolves when the worker is ready
103
+ * Spawns a worker process and returns a promise that resolves when the worker is ready.
104
+ * Config uses raw string for peerIdPrivateKey (not SecretValue) for IPC serialization.
70
105
  */
71
106
  private spawnWorkerProcess(
72
- config: P2PConfig & Partial<ChainConfig>,
107
+ config: Omit<P2PConfig, 'peerIdPrivateKey'> & { peerIdPrivateKey: string } & Partial<ChainConfig>,
73
108
  clientIndex: number,
74
109
  ): [ChildProcess, Promise<void>] {
75
- const childProcess = fork(workerPath);
76
- // Extract the raw peerIdPrivateKey value since SecretValue can't be serialized via IPC
77
- const serializedConfig = {
78
- ...config,
79
- peerIdPrivateKey: config.peerIdPrivateKey?.getValue(),
110
+ const useCompiled = existsSync(workerJsPath);
111
+ const workerPath = useCompiled ? workerJsPath : workerTsPath;
112
+
113
+ const execArgv = [...process.execArgv];
114
+ if (!useCompiled && !execArgv.includes('ts-node/esm')) {
115
+ execArgv.push('--loader', 'ts-node/esm');
116
+ }
117
+
118
+ const env = {
119
+ ...process.env,
120
+ TS_NODE_PROJECT: tsconfigPath,
80
121
  };
81
- childProcess.send({ type: 'START', config: serializedConfig, clientIndex });
122
+
123
+ const childProcess = fork(workerPath, {
124
+ cwd: p2pRoot,
125
+ execArgv,
126
+ env,
127
+ });
128
+ childProcess.send({ type: 'START', config, clientIndex });
82
129
 
83
130
  // Handle unexpected child process exit
84
131
  childProcess.on('exit', (code, signal) => {
@@ -95,74 +142,131 @@ class WorkerClientManager {
95
142
 
96
143
  // Create ready signal promise
97
144
  const readySignal = new Promise<void>((resolve, reject) => {
98
- // Set a timeout to avoid hanging indefinitely
145
+ let resolved = false;
146
+
99
147
  const timeout = setTimeout(() => {
148
+ if (resolved) {
149
+ return;
150
+ }
151
+ resolved = true;
152
+ childProcess.off('message', messageHandler);
153
+ childProcess.off('exit', exitHandler);
100
154
  reject(new Error(`Timeout waiting for worker ${clientIndex} to be ready`));
101
- }, 30000); // 30 second timeout
155
+ }, BENCHMARK_CONSTANTS.WORKER_READY_TIMEOUT_MS);
102
156
 
103
- childProcess.once('message', (msg: any) => {
104
- clearTimeout(timeout);
157
+ const messageHandler = (msg: any) => {
158
+ if (resolved) {
159
+ return;
160
+ }
161
+ // Only handle READY or ERROR messages; ignore others (e.g., GOSSIP_RECEIVED)
105
162
  if (msg.type === 'READY') {
163
+ resolved = true;
164
+ clearTimeout(timeout);
165
+ childProcess.off('message', messageHandler);
166
+ childProcess.off('exit', exitHandler);
167
+ if (typeof msg.peerId === 'string') {
168
+ this.peerIds[clientIndex] = msg.peerId;
169
+ }
106
170
  resolve();
107
- }
108
- // For future use
109
- if (msg.type === 'ERROR') {
171
+ } else if (msg.type === 'ERROR') {
172
+ resolved = true;
173
+ clearTimeout(timeout);
174
+ childProcess.off('message', messageHandler);
175
+ childProcess.off('exit', exitHandler);
110
176
  reject(new Error(msg.error));
111
177
  }
112
- });
178
+ // Ignore other message types and keep waiting for READY/ERROR
179
+ };
113
180
 
114
- // Also resolve/reject if process exits before sending message
115
- childProcess.once('exit', code => {
181
+ const exitHandler = (code: number | null) => {
182
+ if (resolved) {
183
+ return;
184
+ }
185
+ resolved = true;
116
186
  clearTimeout(timeout);
187
+ childProcess.off('message', messageHandler);
117
188
  if (code === 0) {
118
189
  resolve();
119
190
  } else {
120
191
  reject(new Error(`Worker ${clientIndex} exited with code ${code} before becoming ready`));
121
192
  }
122
- });
193
+ };
194
+
195
+ childProcess.on('message', messageHandler);
196
+ childProcess.once('exit', exitHandler);
123
197
  });
124
198
 
125
199
  return [childProcess, readySignal];
126
200
  }
127
201
 
128
202
  /**
129
- * Creates a number of worker clients in separate processes
130
- * All are configured to connect to each other and overrided with the test specific config
203
+ * Creates a number of worker clients in separate processes.
204
+ * All are configured to connect to each other and overridden with the test-specific config.
131
205
  *
132
206
  * @param numberOfClients - The number of clients to create
207
+ * @param options - Optional overrides for seeding/bootstrapping strategy
133
208
  * @returns The ENRs of the created clients
134
209
  */
135
- async makeWorkerClients(numberOfClients: number) {
210
+ async makeWorkerClients(
211
+ numberOfClients: number,
212
+ options: {
213
+ bootstrapMode?: 'subset' | 'all';
214
+ seedPeerLimit?: number;
215
+ batchSize?: number;
216
+ batchDelayMs?: number;
217
+ } = {},
218
+ ) {
136
219
  try {
220
+ const bootstrapMode = options.bootstrapMode ?? (this.p2pConfig.bootstrapNodesAsFullPeers ? 'all' : 'subset');
221
+ const seedPeerLimit = options.seedPeerLimit ?? 10;
222
+ const batchSize = options.batchSize ?? (bootstrapMode === 'all' ? Math.min(5, numberOfClients) : numberOfClients);
223
+ const batchDelayMs = options.batchDelayMs ?? (bootstrapMode === 'all' ? 500 : 0);
224
+
137
225
  this.messageReceivedByClient = new Array(numberOfClients).fill(0);
138
226
  this.peerIdPrivateKeys = generatePeerIdPrivateKeys(numberOfClients);
139
227
  this.ports = await getPorts(numberOfClients);
140
228
  this.peerEnrs = await makeEnrs(this.peerIdPrivateKeys, this.ports, testChainConfig);
229
+ this.peerIds = new Array(numberOfClients);
141
230
 
142
231
  this.processes = [];
143
232
  const readySignals: Promise<void>[] = [];
144
233
 
145
- for (let i = 0; i < numberOfClients; i++) {
146
- this.logger.info(`Creating client ${i}`);
234
+ for (let batchStart = 0; batchStart < numberOfClients; batchStart += batchSize) {
235
+ const batchEnd = Math.min(batchStart + batchSize, numberOfClients);
236
+ const batchPromises: Promise<void>[] = [];
237
+
238
+ for (let i = batchStart; i < batchEnd; i++) {
239
+ this.logger.info(`Creating client ${i}`);
147
240
 
148
- // Maximum seed with 10 other peers to allow peer discovery to connect them at a smoother rate
149
- const otherNodes = this.peerEnrs.filter((_, ind) => ind < Math.min(i, 10));
241
+ const otherNodes =
242
+ bootstrapMode === 'all'
243
+ ? this.peerEnrs.filter((_, ind) => ind !== i)
244
+ : this.peerEnrs.filter((_, ind) => ind < Math.min(i, seedPeerLimit));
150
245
 
151
- const config = this.createClientConfig(i, this.ports[i], otherNodes);
152
- const [childProcess, readySignal] = this.spawnWorkerProcess(config, i);
246
+ const config = this.createClientConfig(i, this.ports[i], otherNodes);
247
+ const [childProcess, readySignal] = this.spawnWorkerProcess(config, i);
153
248
 
154
- readySignals.push(readySignal);
155
- this.processes.push(childProcess);
249
+ readySignals.push(readySignal);
250
+ batchPromises.push(readySignal);
251
+ this.processes.push(childProcess);
252
+ }
253
+
254
+ await Promise.all(batchPromises);
255
+
256
+ if (batchEnd < numberOfClients && batchDelayMs > 0) {
257
+ await sleep(batchDelayMs);
258
+ }
156
259
  }
157
260
 
158
- // Wait for peers to all connect with each other
159
- await sleep(10000);
261
+ await sleep(BENCHMARK_CONSTANTS.PEER_DISCOVERY_WAIT_MS);
160
262
 
161
- // Wait for all peers to be booted up with timeout
162
263
  await Promise.race([
163
264
  Promise.all(readySignals),
164
265
  new Promise((_, reject) =>
165
- setTimeout(() => reject(new Error('Timeout waiting for all workers to be ready')), 30000),
266
+ setTimeout(
267
+ () => reject(new Error('Timeout waiting for all workers to be ready')),
268
+ BENCHMARK_CONSTANTS.WORKER_READY_TIMEOUT_MS,
269
+ ),
166
270
  ),
167
271
  ]);
168
272
 
@@ -220,11 +324,13 @@ class WorkerClientManager {
220
324
 
221
325
  this.processes[clientIndex] = childProcess;
222
326
 
223
- // Wait for the process to be ready with a timeout
224
327
  await Promise.race([
225
328
  readySignal,
226
329
  new Promise((_, reject) =>
227
- setTimeout(() => reject(new Error(`Timeout waiting for client ${clientIndex} to be ready`)), 30000),
330
+ setTimeout(
331
+ () => reject(new Error(`Timeout waiting for client ${clientIndex} to be ready`)),
332
+ BENCHMARK_CONSTANTS.WORKER_READY_TIMEOUT_MS,
333
+ ),
228
334
  ),
229
335
  ]);
230
336
  } catch (error) {
@@ -244,15 +350,14 @@ class WorkerClientManager {
244
350
  }
245
351
 
246
352
  return new Promise<void>(resolve => {
247
- // Set a timeout for the graceful exit
248
353
  const forceKillTimeout = setTimeout(() => {
249
354
  this.logger.warn(`Process ${index} didn't exit gracefully, force killing...`);
250
355
  try {
251
- process.kill('SIGKILL'); // Force kill
356
+ process.kill('SIGKILL');
252
357
  } catch (e) {
253
358
  this.logger.error(`Error force killing process ${index}:`, e);
254
359
  }
255
- }, 5000); // 5 second timeout for graceful exit
360
+ }, BENCHMARK_CONSTANTS.GRACEFUL_SHUTDOWN_TIMEOUT_MS);
256
361
 
257
362
  // Listen for process exit
258
363
  process.once('exit', () => {
@@ -285,7 +390,6 @@ class WorkerClientManager {
285
390
  // Create array of promises for each process termination
286
391
  const terminationPromises = this.processes.map((process, index) => this.terminateProcess(process, index));
287
392
 
288
- // Wait for all processes to terminate with a timeout
289
393
  try {
290
394
  await Promise.race([
291
395
  Promise.all(terminationPromises),
@@ -302,7 +406,7 @@ class WorkerClientManager {
302
406
  }
303
407
  });
304
408
  resolve();
305
- }, 10000); // 10 second timeout for all processes
409
+ }, BENCHMARK_CONSTANTS.CLEANUP_TIMEOUT_MS);
306
410
  }),
307
411
  ]);
308
412
  } catch (error) {
@@ -310,8 +414,161 @@ class WorkerClientManager {
310
414
  }
311
415
 
312
416
  this.processes = [];
417
+ this.peerIds = [];
313
418
  this.logger.info('All worker processes cleaned up');
314
419
  }
420
+
421
+ /**
422
+ * Run a req/resp benchmark across all worker clients.
423
+ *
424
+ * This sends a BENCH_REQRESP command to all workers:
425
+ * - Aggregator (client 0) runs the collector and returns timing results
426
+ * - Responders (clients 1..N) populate their tx pools based on distribution
427
+ *
428
+ * All workers generate the same txs deterministically from a shared seed,
429
+ * then filter based on their peerIndex and distribution pattern.
430
+ */
431
+ async runReqRespBenchmark(config: ReqRespBenchmarkConfig): Promise<ReqRespBenchmarkResult> {
432
+ const peerCount = this.processes.length;
433
+ if (peerCount < 2) {
434
+ throw new Error('Need at least 2 peers to run req/resp benchmark');
435
+ }
436
+
437
+ const seed = config.seed ?? Date.now();
438
+ const blockNumber = config.blockNumber ?? 1;
439
+ const pinnedPeerId = config.pinnedPeerIndex !== undefined ? this.peerIds[config.pinnedPeerIndex] : undefined;
440
+
441
+ this.logger.info(
442
+ `Starting req/resp benchmark: txCount=${config.txCount}, distribution=${config.distribution}, collector=${config.collectorType}`,
443
+ );
444
+
445
+ const readyPromises: Promise<void>[] = [];
446
+
447
+ for (let i = 1; i < peerCount; i++) {
448
+ const cmd: BenchReqRespCommand = {
449
+ type: 'BENCH_REQRESP',
450
+ txCount: config.txCount,
451
+ peerCount,
452
+ distribution: config.distribution,
453
+ collectorType: config.collectorType,
454
+ timeoutMs: config.timeoutMs,
455
+ isAggregator: false,
456
+ peerIndex: i,
457
+ pinnedPeerIndex: config.pinnedPeerIndex,
458
+ pinnedPeerId,
459
+ blockNumber,
460
+ seed,
461
+ };
462
+
463
+ this.processes[i].send(cmd);
464
+ readyPromises.push(this.waitForBenchReady(i, 30000));
465
+ }
466
+
467
+ await Promise.all(readyPromises);
468
+ this.logger.info('All responder peers ready, starting aggregator benchmark...');
469
+
470
+ const aggregatorCmd: BenchReqRespCommand = {
471
+ type: 'BENCH_REQRESP',
472
+ txCount: config.txCount,
473
+ peerCount,
474
+ distribution: config.distribution,
475
+ collectorType: config.collectorType,
476
+ timeoutMs: config.timeoutMs,
477
+ isAggregator: true,
478
+ peerIndex: 0,
479
+ pinnedPeerIndex: config.pinnedPeerIndex,
480
+ pinnedPeerId,
481
+ blockNumber,
482
+ seed,
483
+ };
484
+
485
+ this.processes[0].send(aggregatorCmd);
486
+ const result = await this.waitForBenchResult(0, config.timeoutMs + 30000);
487
+
488
+ this.logger.info(
489
+ `Benchmark complete: fetched=${result.fetchedCount}/${config.txCount}, duration=${result.durationMs.toFixed(0)}ms, success=${result.success}`,
490
+ );
491
+
492
+ return {
493
+ txCount: config.txCount,
494
+ distribution: config.distribution,
495
+ collector: config.collectorType,
496
+ durationMs: result.durationMs,
497
+ fetchedCount: result.fetchedCount,
498
+ success: result.success,
499
+ error: result.error,
500
+ };
501
+ }
502
+
503
+ private waitForBenchReady(clientIndex: number, timeoutMs: number): Promise<void> {
504
+ return new Promise((resolve, reject) => {
505
+ let resolved = false;
506
+
507
+ const handler = (msg: any) => {
508
+ if (resolved) {
509
+ return;
510
+ }
511
+ if (msg.type === 'BENCH_READY') {
512
+ resolved = true;
513
+ clearTimeout(timeout);
514
+ this.processes[clientIndex].off('message', handler);
515
+ resolve();
516
+ } else if (msg.type === 'ERROR') {
517
+ resolved = true;
518
+ clearTimeout(timeout);
519
+ this.processes[clientIndex].off('message', handler);
520
+ reject(new Error(`Client ${clientIndex} error: ${msg.error}`));
521
+ }
522
+ };
523
+
524
+ const timeout = setTimeout(() => {
525
+ if (resolved) {
526
+ return;
527
+ }
528
+ resolved = true;
529
+ this.processes[clientIndex].off('message', handler);
530
+ reject(new Error(`Timeout waiting for BENCH_READY from client ${clientIndex}`));
531
+ }, timeoutMs);
532
+
533
+ this.processes[clientIndex].on('message', handler);
534
+ });
535
+ }
536
+
537
+ private waitForBenchResult(clientIndex: number, timeoutMs: number): Promise<BenchResultMessage> {
538
+ return new Promise((resolve, reject) => {
539
+ let resolved = false;
540
+
541
+ const handler = (msg: any) => {
542
+ if (resolved) {
543
+ return;
544
+ }
545
+ if (msg.type === 'BENCH_RESULT') {
546
+ resolved = true;
547
+ clearTimeout(timeout);
548
+ this.processes[clientIndex].off('message', handler);
549
+ resolve(msg as BenchResultMessage);
550
+ } else if (msg.type === 'ERROR') {
551
+ resolved = true;
552
+ clearTimeout(timeout);
553
+ this.processes[clientIndex].off('message', handler);
554
+ reject(new Error(`Client ${clientIndex} error: ${msg.error}`));
555
+ }
556
+ };
557
+
558
+ const timeout = setTimeout(() => {
559
+ if (resolved) {
560
+ return;
561
+ }
562
+ resolved = true;
563
+ this.processes[clientIndex].off('message', handler);
564
+ reject(new Error(`Timeout waiting for BENCH_RESULT from client ${clientIndex}`));
565
+ }, timeoutMs);
566
+
567
+ this.processes[clientIndex].on('message', handler);
568
+ });
569
+ }
315
570
  }
316
571
 
317
572
  export { WorkerClientManager, testChainConfig };
573
+ export type { DistributionPattern, CollectorType } from './p2p_client_testbench_worker.js';
574
+ export { COLLECTOR_DISPLAY_NAMES } from './p2p_client_testbench_worker.js';