Allow multiple wakunodes to be started in parallel

This commit is contained in:
Franck Royer 2021-03-12 17:08:42 +11:00
parent a0d6784e3c
commit fdbcbe0896
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
3 changed files with 57 additions and 62 deletions

View File

@ -1,6 +1,5 @@
import test from 'ava'; import test from 'ava';
import Pubsub from 'libp2p-interfaces/src/pubsub'; import Pubsub from 'libp2p-interfaces/src/pubsub';
import multiaddr from 'multiaddr';
import { delay } from '../test_utils/delay'; import { delay } from '../test_utils/delay';
import { NimWaku } from '../test_utils/nim_waku'; import { NimWaku } from '../test_utils/nim_waku';
@ -61,7 +60,7 @@ test('Nim-interop: nim-waku node connects to js node', async (t) => {
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(); const nimWaku = new NimWaku();
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start(t.title, { staticnode: multiAddrWithId });
const nimPeers = await nimWaku.peers(); const nimPeers = await nimWaku.peers();
@ -73,11 +72,10 @@ test('Nim-interop: nim-waku node connects to js node', async (t) => {
}, },
]); ]);
const nimAddress = await nimWaku.info().then((info) => info.listenStr); const nimPeerId = await nimWaku.getPeerId();
const nimPeerId = nimAddress.match(/[\d\w]+$/)[0];
const jsPeers = node.peerStore.peers; const jsPeers = node.peerStore.peers;
t.true(jsPeers.has(nimPeerId)); t.true(jsPeers.has(nimPeerId.toB58String()));
}); });
test('Nim-interop: js node subscribes to default waku topic (only checking js side)', async (t) => { test('Nim-interop: js node subscribes to default waku topic (only checking js side)', async (t) => {
@ -91,16 +89,15 @@ test('Nim-interop: js node subscribes to default waku topic (only checking js si
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(); const nimWaku = new NimWaku();
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start(t.title, { staticnode: multiAddrWithId });
const wakuRelayNode = new WakuRelay(node.pubsub); const wakuRelayNode = new WakuRelay(node.pubsub);
await wakuRelayNode.subscribe(); await wakuRelayNode.subscribe();
const nimAddress = await nimWaku.info().then((info) => info.listenStr); const nimPeerId = await nimWaku.getPeerId();
const nimPeerId = multiaddr(nimAddress).getPeerId();
const subscribers = node.pubsub.getSubscribers(TOPIC); const subscribers = node.pubsub.getSubscribers(TOPIC);
t.true(subscribers.includes(nimPeerId)); t.true(subscribers.includes(nimPeerId.toB58String()));
}); });
test('Nim-interop: nim node sends message', async (t) => { test('Nim-interop: nim node sends message', async (t) => {
@ -108,15 +105,13 @@ test('Nim-interop: nim node sends message', async (t) => {
const peerId = node.peerId.toB58String(); const peerId = node.peerId.toB58String();
console.log(`js peer id: ${peerId}`);
const localMultiaddr = node.multiaddrs.find((addr) => const localMultiaddr = node.multiaddrs.find((addr) =>
addr.toString().match(/127\.0\.0\.1/) addr.toString().match(/127\.0\.0\.1/)
); );
const multiAddrWithId = localMultiaddr + '/p2p/' + peerId; const multiAddrWithId = localMultiaddr + '/p2p/' + peerId;
const nimWaku = new NimWaku(); const nimWaku = new NimWaku();
await nimWaku.start({ staticnode: multiAddrWithId }); await nimWaku.start(t.title, { staticnode: multiAddrWithId });
const wakuRelayNode = new WakuRelay(node.pubsub); const wakuRelayNode = new WakuRelay(node.pubsub);
await wakuRelayNode.subscribe(); await wakuRelayNode.subscribe();

View File

@ -1,9 +1,11 @@
import test from 'ava'; import test from 'ava';
import { argsToArray, bufToHex, mergeArguments, strToHex } from './nim_waku'; import { argsToArray, bufToHex, defaultArgs, strToHex } from './nim_waku';
test('Correctly serialized arguments', (t) => {
const args = defaultArgs();
Object.assign(args, { portsShift: 42 });
test('Default arguments are correct', (t) => {
const args = mergeArguments({});
const actual = argsToArray(args); const actual = argsToArray(args);
const expected = [ const expected = [
@ -12,26 +14,7 @@ test('Default arguments are correct', (t) => {
'--relay=true', '--relay=true',
'--rpc=true', '--rpc=true',
'--rpc-admin=true', '--rpc-admin=true',
'--nodekey=B2C4E3DB22EA6EB6850689F7B3DF3DDA73F59C87EFFD902BEDCEE90A3A2341A6', '--ports-shift=42',
];
t.deepEqual(actual, expected);
});
test('Passing staticnode argument return default + static node', (t) => {
const args = mergeArguments({
staticnode: '/ip4/1.1.1.1/tcp/1234/p2p/aabbbccdd',
});
const actual = argsToArray(args);
const expected = [
'--nat=none',
'--listen-address=127.0.0.1',
'--relay=true',
'--rpc=true',
'--rpc-admin=true',
'--nodekey=B2C4E3DB22EA6EB6850689F7B3DF3DDA73F59C87EFFD902BEDCEE90A3A2341A6',
'--staticnode=/ip4/1.1.1.1/tcp/1234/p2p/aabbbccdd',
]; ];
t.deepEqual(actual, expected); t.deepEqual(actual, expected);

View File

@ -1,4 +1,5 @@
import { ChildProcess, spawn } from 'child_process'; import { ChildProcess, spawn } from 'child_process';
import { randomInt } from 'crypto';
import * as fs from 'fs'; import * as fs from 'fs';
import { promisify } from 'util'; import { promisify } from 'util';
@ -14,12 +15,9 @@ import waitForLine from './log_file';
const openAsync = promisify(fs.open); const openAsync = promisify(fs.open);
const NIM_WAKU_DEFAULT_P2P_PORT = 60000;
const NIM_WAKU_DEFAULT_RPC_PORT = 8545;
const NIM_WAKU_BIN = '/home/froyer/src/status-im/nim-waku/build/wakunode2'; const NIM_WAKU_BIN = '/home/froyer/src/status-im/nim-waku/build/wakunode2';
const NIM_WAKU_RPC_URL = 'http://localhost:8545/';
const NIM_WAKU_PEER_ID = PeerId.createFromB58String(
'16Uiu2HAkyzsXzENw5XBDYEQQAeQTCYjBJpMLgBmEXuwbtcrgxBJ4'
);
const NIM_WAKKU_LISTEN_ADDR = multiaddr('/ip4/127.0.0.1/tcp/60000/');
export interface Args { export interface Args {
staticnode?: string; staticnode?: string;
@ -29,21 +27,32 @@ export interface Args {
rpc?: boolean; rpc?: boolean;
rpcAdmin?: boolean; rpcAdmin?: boolean;
nodekey?: string; nodekey?: string;
portsShift?: number;
} }
export class NimWaku { export class NimWaku {
private process?: ChildProcess; private process?: ChildProcess;
private portsShift: number;
private peerId?: PeerId;
async start(args: Args) { constructor() {
// Start a local only node with the right RPC commands this.portsShift = randomInt(0, 5000);
// The fixed nodekey ensures the node has a fixed Peerid: 16Uiu2HAkyzsXzENw5XBDYEQQAeQTCYjBJpMLgBmEXuwbtcrgxBJ4 }
const logPath = './nim-waku.log'; async start(testName: string, args: Args) {
const logFilePrefix = testName.replace(/ /g, '_').replace(/[':()]/g, '');
const logPath = `./${logFilePrefix}-nim-waku.log`;
const logFile = await openAsync(logPath, 'w'); const logFile = await openAsync(logPath, 'w');
const mergedArgs = argsToArray(mergeArguments(args)); const mergedArgs = defaultArgs();
this.process = spawn(NIM_WAKU_BIN, mergedArgs, {
// Object.assign overrides the properties with the source (if there are conflicts)
Object.assign(mergedArgs, { portsShift: this.portsShift }, args);
const argsArray = argsToArray(mergedArgs);
this.process = spawn(NIM_WAKU_BIN, argsArray, {
cwd: '/home/froyer/src/status-im/nim-waku/', cwd: '/home/froyer/src/status-im/nim-waku/',
stdio: [ stdio: [
'ignore', // stdin 'ignore', // stdin
@ -57,7 +66,6 @@ export class NimWaku {
}); });
await waitForLine(logPath, 'RPC Server started'); await waitForLine(logPath, 'RPC Server started');
console.log('Nim waku RPC is started');
} }
/** Calls nim-waku2 JSON-RPC API `get_waku_v2_admin_v1_peers` to check /** Calls nim-waku2 JSON-RPC API `get_waku_v2_admin_v1_peers` to check
@ -72,7 +80,7 @@ export class NimWaku {
return res.result; return res.result;
} }
async info() { async info(): Promise<RpcInfoResponse> {
this.checkProcess(); this.checkProcess();
const res = await this.rpcCall('get_waku_v2_debug_v1_info', []); const res = await this.rpcCall('get_waku_v2_debug_v1_info', []);
@ -111,17 +119,30 @@ export class NimWaku {
return res.result; return res.result;
} }
get peerId(): PeerId { async getPeerId(): Promise<PeerId> {
return NIM_WAKU_PEER_ID; if (this.peerId) {
return this.peerId;
}
const res = await this.info();
const strPeerId = multiaddr(res.listenStr).getPeerId();
return PeerId.createFromB58String(strPeerId);
} }
get multiaddr(): Multiaddr { get multiaddr(): Multiaddr {
return NIM_WAKKU_LISTEN_ADDR; const port = NIM_WAKU_DEFAULT_P2P_PORT + this.portsShift;
return multiaddr(`/ip4/127.0.0.1/tcp/${port}/`);
}
get rpcUrl(): string {
const port = NIM_WAKU_DEFAULT_RPC_PORT + this.portsShift;
return `http://localhost:${port}/`;
} }
private async rpcCall(method: string, params: any[]) { private async rpcCall(method: string, params: any[]) {
const res = await axios.post( const res = await axios.post(
NIM_WAKU_RPC_URL, this.rpcUrl,
{ {
jsonrpc: '2.0', jsonrpc: '2.0',
id: 1, id: 1,
@ -159,25 +180,16 @@ export function argsToArray(args: Args): Array<string> {
return array; return array;
} }
function defaultArgs(): Args { export function defaultArgs(): Args {
return { return {
nat: 'none', nat: 'none',
listenAddress: '127.0.0.1', listenAddress: '127.0.0.1',
relay: true, relay: true,
rpc: true, rpc: true,
rpcAdmin: true, rpcAdmin: true,
nodekey: 'B2C4E3DB22EA6EB6850689F7B3DF3DDA73F59C87EFFD902BEDCEE90A3A2341A6',
}; };
} }
export function mergeArguments(args: Args): Args {
const res = defaultArgs();
Object.assign(res, args);
return res;
}
export function strToHex(str: string): string { export function strToHex(str: string): string {
let hex: string; let hex: string;
try { try {
@ -202,3 +214,8 @@ export function bufToHex(buffer: Uint8Array) {
.join('') .join('')
); );
} }
interface RpcInfoResponse {
// multiaddr including id.
listenStr: string;
}