@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.
- package/README.md +7 -0
- package/dest/bootstrap/bootstrap.d.ts +38 -0
- package/dest/bootstrap/bootstrap.d.ts.map +1 -0
- package/dest/bootstrap/bootstrap.js +123 -0
- package/dest/client/factory.d.ts +21 -0
- package/dest/client/factory.d.ts.map +1 -0
- package/dest/client/factory.js +37 -0
- package/dest/client/index.d.ts +3 -0
- package/dest/client/index.d.ts.map +1 -0
- package/dest/client/index.js +2 -0
- package/dest/client/p2p_client.d.ts +314 -0
- package/dest/client/p2p_client.d.ts.map +1 -0
- package/dest/client/p2p_client.js +505 -0
- package/dest/config.d.ts +180 -0
- package/dest/config.d.ts.map +1 -0
- package/dest/config.js +193 -0
- package/dest/enr/generate-enr.d.ts +9 -0
- package/dest/enr/generate-enr.d.ts.map +1 -0
- package/dest/enr/generate-enr.js +30 -0
- package/dest/enr/index.d.ts +2 -0
- package/dest/enr/index.d.ts.map +1 -0
- package/dest/enr/index.js +1 -0
- package/dest/errors/reqresp.error.d.ts +28 -0
- package/dest/errors/reqresp.error.d.ts.map +1 -0
- package/dest/errors/reqresp.error.js +30 -0
- package/dest/index.d.ts +8 -0
- package/dest/index.d.ts.map +1 -0
- package/dest/index.js +7 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts +57 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool.js +6 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/attestation_pool_test_suite.js +195 -0
- package/dest/mem_pools/attestation_pool/index.d.ts +3 -0
- package/dest/mem_pools/attestation_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/index.js +2 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts +22 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/kv_attestation_pool.js +112 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts +17 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/memory_attestation_pool.js +129 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts +19 -0
- package/dest/mem_pools/attestation_pool/mocks.d.ts.map +1 -0
- package/dest/mem_pools/attestation_pool/mocks.js +33 -0
- package/dest/mem_pools/index.d.ts +4 -0
- package/dest/mem_pools/index.d.ts.map +1 -0
- package/dest/mem_pools/index.js +1 -0
- package/dest/mem_pools/instrumentation.d.ts +30 -0
- package/dest/mem_pools/instrumentation.d.ts.map +1 -0
- package/dest/mem_pools/instrumentation.js +84 -0
- package/dest/mem_pools/interface.d.ts +11 -0
- package/dest/mem_pools/interface.d.ts.map +1 -0
- package/dest/mem_pools/interface.js +3 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts +66 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/aztec_kv_tx_pool.js +245 -0
- package/dest/mem_pools/tx_pool/index.d.ts +4 -0
- package/dest/mem_pools/tx_pool/index.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/index.js +3 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts +56 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/memory_tx_pool.js +141 -0
- package/dest/mem_pools/tx_pool/priority.d.ts +8 -0
- package/dest/mem_pools/tx_pool/priority.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/priority.js +10 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts +66 -0
- package/dest/mem_pools/tx_pool/tx_pool.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool.js +3 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts +7 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.d.ts.map +1 -0
- package/dest/mem_pools/tx_pool/tx_pool_test_suite.js +169 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts +8 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/attestation_validator.js +19 -0
- package/dest/msg_validators/attestation_validator/index.d.ts +2 -0
- package/dest/msg_validators/attestation_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/attestation_validator/index.js +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts +8 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/block_proposal_validator.js +21 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts +2 -0
- package/dest/msg_validators/block_proposal_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/block_proposal_validator/index.js +1 -0
- package/dest/msg_validators/index.d.ts +4 -0
- package/dest/msg_validators/index.d.ts.map +1 -0
- package/dest/msg_validators/index.js +3 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts +7 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/aggregate_tx_validator.js +31 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts +11 -0
- package/dest/msg_validators/tx_validator/block_header_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/block_header_validator.js +26 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts +6 -0
- package/dest/msg_validators/tx_validator/data_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/data_validator.js +107 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts +12 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/double_spend_validator.js +41 -0
- package/dest/msg_validators/tx_validator/index.d.ts +7 -0
- package/dest/msg_validators/tx_validator/index.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/index.js +6 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts +10 -0
- package/dest/msg_validators/tx_validator/metadata_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/metadata_validator.js +44 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts +9 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.d.ts.map +1 -0
- package/dest/msg_validators/tx_validator/tx_proof_validator.js +25 -0
- package/dest/services/data_store.d.ts +27 -0
- package/dest/services/data_store.d.ts.map +1 -0
- package/dest/services/data_store.js +188 -0
- package/dest/services/discv5/discV5_service.d.ts +42 -0
- package/dest/services/discv5/discV5_service.d.ts.map +1 -0
- package/dest/services/discv5/discV5_service.js +214 -0
- package/dest/services/dummy_service.d.ts +85 -0
- package/dest/services/dummy_service.d.ts.map +1 -0
- package/dest/services/dummy_service.js +92 -0
- package/dest/services/encoding.d.ts +31 -0
- package/dest/services/encoding.d.ts.map +1 -0
- package/dest/services/encoding.js +66 -0
- package/dest/services/gossipsub/scoring.d.ts +7 -0
- package/dest/services/gossipsub/scoring.d.ts.map +1 -0
- package/dest/services/gossipsub/scoring.js +10 -0
- package/dest/services/index.d.ts +3 -0
- package/dest/services/index.d.ts.map +1 -0
- package/dest/services/index.js +2 -0
- package/dest/services/libp2p/libp2p_service.d.ts +186 -0
- package/dest/services/libp2p/libp2p_service.d.ts.map +1 -0
- package/dest/services/libp2p/libp2p_service.js +712 -0
- package/dest/services/peer-manager/metrics.d.ts +12 -0
- package/dest/services/peer-manager/metrics.d.ts.map +1 -0
- package/dest/services/peer-manager/metrics.js +33 -0
- package/dest/services/peer-manager/peer_manager.d.ts +94 -0
- package/dest/services/peer-manager/peer_manager.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_manager.js +445 -0
- package/dest/services/peer-manager/peer_scoring.d.ts +28 -0
- package/dest/services/peer-manager/peer_scoring.d.ts.map +1 -0
- package/dest/services/peer-manager/peer_scoring.js +86 -0
- package/dest/services/reqresp/config.d.ts +16 -0
- package/dest/services/reqresp/config.d.ts.map +1 -0
- package/dest/services/reqresp/config.js +20 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts +45 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/batch_connection_sampler.js +88 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts +61 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.d.ts.map +1 -0
- package/dest/services/reqresp/connection-sampler/connection_sampler.js +181 -0
- package/dest/services/reqresp/index.d.ts +6 -0
- package/dest/services/reqresp/index.d.ts.map +1 -0
- package/dest/services/reqresp/index.js +4 -0
- package/dest/services/reqresp/interface.d.ts +116 -0
- package/dest/services/reqresp/interface.d.ts.map +1 -0
- package/dest/services/reqresp/interface.js +84 -0
- package/dest/services/reqresp/metrics.d.ts +15 -0
- package/dest/services/reqresp/metrics.d.ts.map +1 -0
- package/dest/services/reqresp/metrics.js +55 -0
- package/dest/services/reqresp/protocols/block.d.ts +4 -0
- package/dest/services/reqresp/protocols/block.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/block.js +8 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts +51 -0
- package/dest/services/reqresp/protocols/goodbye.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/goodbye.js +87 -0
- package/dest/services/reqresp/protocols/index.d.ts +9 -0
- package/dest/services/reqresp/protocols/index.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/index.js +7 -0
- package/dest/services/reqresp/protocols/ping.d.ts +9 -0
- package/dest/services/reqresp/protocols/ping.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/ping.js +7 -0
- package/dest/services/reqresp/protocols/status.d.ts +9 -0
- package/dest/services/reqresp/protocols/status.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/status.js +7 -0
- package/dest/services/reqresp/protocols/tx.d.ts +13 -0
- package/dest/services/reqresp/protocols/tx.d.ts.map +1 -0
- package/dest/services/reqresp/protocols/tx.js +20 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts +2 -0
- package/dest/services/reqresp/rate-limiter/index.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/index.js +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts +102 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limiter.js +184 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts +3 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.d.ts.map +1 -0
- package/dest/services/reqresp/rate-limiter/rate_limits.js +54 -0
- package/dest/services/reqresp/reqresp.d.ts +166 -0
- package/dest/services/reqresp/reqresp.d.ts.map +1 -0
- package/dest/services/reqresp/reqresp.js +516 -0
- package/dest/services/reqresp/status.d.ts +31 -0
- package/dest/services/reqresp/status.d.ts.map +1 -0
- package/dest/services/reqresp/status.js +51 -0
- package/dest/services/service.d.ts +87 -0
- package/dest/services/service.d.ts.map +1 -0
- package/dest/services/service.js +5 -0
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts +7 -0
- package/dest/test-helpers/generate-peer-id-private-keys.d.ts.map +1 -0
- package/dest/test-helpers/generate-peer-id-private-keys.js +13 -0
- package/dest/test-helpers/get-ports.d.ts +7 -0
- package/dest/test-helpers/get-ports.d.ts.map +1 -0
- package/dest/test-helpers/get-ports.js +8 -0
- package/dest/test-helpers/index.d.ts +6 -0
- package/dest/test-helpers/index.d.ts.map +1 -0
- package/dest/test-helpers/index.js +5 -0
- package/dest/test-helpers/make-enrs.d.ts +16 -0
- package/dest/test-helpers/make-enrs.d.ts.map +1 -0
- package/dest/test-helpers/make-enrs.js +32 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts +36 -0
- package/dest/test-helpers/make-test-p2p-clients.d.ts.map +1 -0
- package/dest/test-helpers/make-test-p2p-clients.js +68 -0
- package/dest/test-helpers/reqresp-nodes.d.ts +66 -0
- package/dest/test-helpers/reqresp-nodes.d.ts.map +1 -0
- package/dest/test-helpers/reqresp-nodes.js +207 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts +2 -0
- package/dest/testbench/p2p_client_testbench_worker.d.ts.map +1 -0
- package/dest/testbench/p2p_client_testbench_worker.js +132 -0
- package/dest/testbench/parse_log_file.d.ts +2 -0
- package/dest/testbench/parse_log_file.d.ts.map +1 -0
- package/dest/testbench/parse_log_file.js +131 -0
- package/dest/testbench/testbench.d.ts +2 -0
- package/dest/testbench/testbench.d.ts.map +1 -0
- package/dest/testbench/testbench.js +61 -0
- package/dest/testbench/worker_client_manager.d.ts +56 -0
- package/dest/testbench/worker_client_manager.d.ts.map +1 -0
- package/dest/testbench/worker_client_manager.js +266 -0
- package/dest/types/index.d.ts +32 -0
- package/dest/types/index.d.ts.map +1 -0
- package/dest/types/index.js +28 -0
- package/dest/util.d.ts +53 -0
- package/dest/util.d.ts.map +1 -0
- package/dest/util.js +140 -0
- package/dest/versioning.d.ts +12 -0
- package/dest/versioning.d.ts.map +1 -0
- package/dest/versioning.js +33 -0
- package/package.json +127 -0
- package/src/bootstrap/bootstrap.ts +146 -0
- package/src/client/factory.ts +89 -0
- package/src/client/index.ts +2 -0
- package/src/client/p2p_client.ts +754 -0
- package/src/config.ts +371 -0
- package/src/enr/generate-enr.ts +39 -0
- package/src/enr/index.ts +1 -0
- package/src/errors/reqresp.error.ts +35 -0
- package/src/index.ts +7 -0
- package/src/mem_pools/attestation_pool/attestation_pool.ts +62 -0
- package/src/mem_pools/attestation_pool/attestation_pool_test_suite.ts +230 -0
- package/src/mem_pools/attestation_pool/index.ts +2 -0
- package/src/mem_pools/attestation_pool/kv_attestation_pool.ts +159 -0
- package/src/mem_pools/attestation_pool/memory_attestation_pool.ts +161 -0
- package/src/mem_pools/attestation_pool/mocks.ts +44 -0
- package/src/mem_pools/index.ts +3 -0
- package/src/mem_pools/instrumentation.ts +126 -0
- package/src/mem_pools/interface.ts +12 -0
- package/src/mem_pools/tx_pool/aztec_kv_tx_pool.ts +309 -0
- package/src/mem_pools/tx_pool/index.ts +3 -0
- package/src/mem_pools/tx_pool/memory_tx_pool.ts +174 -0
- package/src/mem_pools/tx_pool/priority.ts +13 -0
- package/src/mem_pools/tx_pool/tx_pool.ts +76 -0
- package/src/mem_pools/tx_pool/tx_pool_test_suite.ts +130 -0
- package/src/msg_validators/attestation_validator/attestation_validator.ts +26 -0
- package/src/msg_validators/attestation_validator/index.ts +1 -0
- package/src/msg_validators/block_proposal_validator/block_proposal_validator.ts +29 -0
- package/src/msg_validators/block_proposal_validator/index.ts +1 -0
- package/src/msg_validators/index.ts +3 -0
- package/src/msg_validators/tx_validator/aggregate_tx_validator.ts +32 -0
- package/src/msg_validators/tx_validator/block_header_validator.ts +25 -0
- package/src/msg_validators/tx_validator/data_validator.ts +106 -0
- package/src/msg_validators/tx_validator/double_spend_validator.ts +38 -0
- package/src/msg_validators/tx_validator/index.ts +6 -0
- package/src/msg_validators/tx_validator/metadata_validator.ts +48 -0
- package/src/msg_validators/tx_validator/tx_proof_validator.ts +18 -0
- package/src/services/data_store.ts +235 -0
- package/src/services/discv5/discV5_service.ts +256 -0
- package/src/services/dummy_service.ts +134 -0
- package/src/services/encoding.ts +79 -0
- package/src/services/gossipsub/scoring.ts +13 -0
- package/src/services/index.ts +2 -0
- package/src/services/libp2p/libp2p_service.ts +871 -0
- package/src/services/peer-manager/metrics.ts +41 -0
- package/src/services/peer-manager/peer_manager.ts +530 -0
- package/src/services/peer-manager/peer_scoring.ts +105 -0
- package/src/services/reqresp/config.ts +35 -0
- package/src/services/reqresp/connection-sampler/batch_connection_sampler.ts +94 -0
- package/src/services/reqresp/connection-sampler/connection_sampler.ts +217 -0
- package/src/services/reqresp/index.ts +4 -0
- package/src/services/reqresp/interface.ts +185 -0
- package/src/services/reqresp/metrics.ts +57 -0
- package/src/services/reqresp/protocols/block.ts +15 -0
- package/src/services/reqresp/protocols/goodbye.ts +101 -0
- package/src/services/reqresp/protocols/index.ts +8 -0
- package/src/services/reqresp/protocols/ping.ts +8 -0
- package/src/services/reqresp/protocols/status.ts +8 -0
- package/src/services/reqresp/protocols/tx.ts +29 -0
- package/src/services/reqresp/rate-limiter/index.ts +1 -0
- package/src/services/reqresp/rate-limiter/rate_limiter.ts +228 -0
- package/src/services/reqresp/rate-limiter/rate_limits.ts +55 -0
- package/src/services/reqresp/reqresp.ts +661 -0
- package/src/services/reqresp/status.ts +59 -0
- package/src/services/service.ts +112 -0
- package/src/test-helpers/generate-peer-id-private-keys.ts +15 -0
- package/src/test-helpers/get-ports.ts +8 -0
- package/src/test-helpers/index.ts +5 -0
- package/src/test-helpers/make-enrs.ts +44 -0
- package/src/test-helpers/make-test-p2p-clients.ts +122 -0
- package/src/test-helpers/reqresp-nodes.ts +289 -0
- package/src/testbench/README.md +20 -0
- package/src/testbench/p2p_client_testbench_worker.ts +152 -0
- package/src/testbench/parse_log_file.ts +175 -0
- package/src/testbench/testbench.ts +66 -0
- package/src/testbench/worker_client_manager.ts +318 -0
- package/src/types/index.ts +36 -0
- package/src/util.ts +196 -0
- 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 @@
|
|
|
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 @@
|
|
|
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 };
|