Skip to content

Commit

Permalink
Add a method to check peer dialablility (#79)
Browse files Browse the repository at this point in the history
* Add an option for intermediaries to the server script

* Add an option to specify additional peers in the server script

* Add a method to check peer dialablility

* Add script to fetch account balance on chain

* Fix balance script log

---------

Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
  • Loading branch information
prathamesh0 and nikugogoi authored Jul 11, 2023
1 parent 829b901 commit 564db65
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ const BUFFER_SIZE = 1_000;
const NUM_CONNECT_ATTEMPTS = 20;
const RETRY_SLEEP_DURATION = 5 * 1000; // milliseconds
const ERR_CONNECTION_CLOSED = 'the connection is being closed';
const ERR_PEER_NOT_FOUND = 'peer info not found';
const ERR_PEER_DIAL_FAILED = 'peer dial failed';

// BasicPeerInfo contains the basic information about a peer
export interface BasicPeerInfo {
Expand Down Expand Up @@ -481,4 +483,24 @@ export class P2PMessageService implements MessageService {
this.logger(`Connected and sent info to peer ${peerId.toString()}`);
}
}

// Custom method to check if a peer is known and dialable
async isPeerDialable(peerAddress: string): Promise<[boolean, string]> {
assert(this.peers);

// Try to load peer from the peers info map
const [peerInfo, foundPeer] = this.peers.load(peerAddress);
if (!foundPeer) {
return [false, ERR_PEER_NOT_FOUND];
}
assert(peerInfo);

try {
await this.p2pHost.dial(peerInfo.id);
} catch (err) {
return [false, ERR_PEER_DIAL_FAILED];
}

return [true, ''];
}
}
13 changes: 13 additions & 0 deletions packages/server/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@
"project": "./tsconfig.eslint.json"
},
"rules": {
// Override airbnb eslint no-restricted-syntax
// https://github.com/airbnb/javascript/blob/master/packages/eslint-config-airbnb-base/rules/style.js
"no-restricted-syntax": [
"error",
{
"selector": "LabeledStatement",
"message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
},
{
"selector": "WithStatement",
"message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
}
],
"import/no-extraneous-dependencies": [
"error",
{
Expand Down
42 changes: 32 additions & 10 deletions packages/server/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import yargs from 'yargs';
import debug from 'debug';
import assert from 'assert';
import fs from 'fs';
import path from 'path';
import 'dotenv/config';

Expand Down Expand Up @@ -45,9 +46,9 @@ const getArgv = () => yargs.parserConfiguration({
type: 'string',
describe: 'Counterparty to create channel(s) against',
},
cpMultiaddr: {
additionalPeers: {
type: 'string',
describe: "Counterparty's peer multiaddr",
describe: 'JSON file path with peer multiaddrs to be added',
},
directFund: {
type: 'boolean',
Expand Down Expand Up @@ -114,6 +115,10 @@ const getArgv = () => yargs.parserConfiguration({
default: false,
describe: 'Whether to keep CLI running',
},
intermediaries: {
type: 'array',
default: [],
},
}).argv;

const main = async () => {
Expand All @@ -140,14 +145,31 @@ const main = async () => {

log('Started P2PMessageService');

if (argv.cpMultiaddr) {
assert(argv.counterparty, 'Specify counterparty address');
const peersToConnect: string[] = argv.counterparty ? [argv.counterparty] : [];
peersToConnect.push(...(argv.intermediaries as string[]));

log('Adding client', argv.counterparty);
await msgService.addPeerByMultiaddr(argv.counterparty, argv.cpMultiaddr);
} else {
// Wait for a peer to be discovered
await waitForPeerInfoExchange(1, [msgService]);
let peersToAdd: any[] = [];
if (argv.additionalPeers) {
const data = fs.readFileSync(path.resolve(argv.additionalPeers), 'utf-8');
peersToAdd = JSON.parse(data);

for await (const [, peerToAdd] of Array.from(peersToAdd).entries()) {
log('Adding client', peerToAdd.address);
await msgService.addPeerByMultiaddr(peerToAdd.address, peerToAdd.multiaddr);
peersToConnect.push(peerToAdd.address);
}
}

// Wait for peers to be discovered
log(`Waiting for ${argv.intermediaries.length} intermediaries to be discovered`);
await waitForPeerInfoExchange(argv.intermediaries.length - peersToAdd.length + 1, [msgService]);

// Check that all required peers are dialable
for await (const peer of peersToConnect) {
const [dialable, errString] = await msgService.isPeerDialable(peer);
if (!dialable) {
throw new Error(`Not able to dial peer with address ${peer}: ${errString}`);
}
}

let ledgerChannelIdString = argv.ledgerChannel;
Expand Down Expand Up @@ -186,7 +208,7 @@ const main = async () => {
assert(counterParty, 'Specify counterparty address');
const virtualFundparams: VirtualFundParams = {
counterParty,
intermediaries: [],
intermediaries: argv.intermediaries,
challengeDuration: 0,
outcome: createOutcome(
asset,
Expand Down
3 changes: 2 additions & 1 deletion packages/util/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"build": "yarn clean && tsc && if [ \"$TARGET\" = \"browser\" ]; then yarn build:fix-modules; fi",
"clean": "rm -rf ./dist",
"test:deploy-contracts": "yarn ts-node scripts/deploy-contracts.ts",
"build:fix-modules": "yarn ts-node scripts/fix-modules.ts"
"build:fix-modules": "yarn ts-node scripts/fix-modules.ts",
"balance": "DEBUG=ts-nitro:* yarn ts-node scripts/balance.ts"
}
}
57 changes: 57 additions & 0 deletions packages/util/scripts/balance.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import yargs from 'yargs';
import debug from 'debug';
import { Wallet, providers } from 'ethers';

import { DEFAULT_CHAIN_URL } from '../src/constants';

const log = debug('ts-nitro:util');

const getArgv = () => yargs.parserConfiguration({
'parse-numbers': false,
}).options({
chainurl: {
alias: 'c',
type: 'string',
describe: 'RPC endpoint for the chain',
default: DEFAULT_CHAIN_URL,
},
address: {
alias: 'a',
type: 'string',
describe: 'Address of account to check balance for',
},
key: {
alias: 'k',
type: 'string',
describe: 'Private key of account to check',
},
}).argv;

async function main() {
const argv = getArgv();

const provider = new providers.JsonRpcProvider(argv.chainurl);
let address: string;

if (argv.address) {
address = argv.address;
} else if (argv.key) {
const signer = new Wallet(argv.key, provider);
address = await signer.getAddress();
} else {
throw new Error('Provide either address or private key of an account');
}

const balance = await provider.getBalance(address);
log(`Balance of account ${address} is ${balance.toString()}`);
}

main()
.then(() => {})
.catch((err) => {
log(err);
});

process.on('uncaughtException', (err) => {
log('uncaughtException', err);
});
10 changes: 10 additions & 0 deletions packages/util/src/nitro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ export class Nitro {
await this.msgService.addPeerByMultiaddr(address, multiaddrString);
}

async isPeerDialable(address: string): Promise<[boolean, string]> {
const [dialable, errString] = await this.msgService.isPeerDialable(address);

if (!dialable) {
return [false, `Not able to dial peer with address ${address}: ${errString}`];
}

return [true, `Peer with address ${address} is dialable`];
}

async directFund(counterParty: string, amount: number): Promise<void> {
const outcome = createOutcome(
ASSET,
Expand Down

0 comments on commit 564db65

Please sign in to comment.