Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(jellyfish-api-core): add network getPeerInfo RPC #938

Merged
merged 11 commits into from
Jan 17, 2022
46 changes: 46 additions & 0 deletions docs/node/CATEGORIES/03-net.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,52 @@ interface net {
}
```

## getPeerInfo

Returns data about each connected network node as a json array of objects.

```ts title="client.net.getPeerInfo()"
interface net {
getPeerInfo (): Promise<PeerInfo[]>
}

export interface PeerInfo {
id: number
addr: string
addrbind?: string
addrlocal?: string
services: string
relaytxes: boolean
lastsend: number
lastrecv: number
bytessent: number
bytesrecv: number
conntime: number
timeoffset: number
pingtime?: number
minping?: number
pingwait?: number
version: number
subver: string
inbound: boolean
addnode: boolean
startingheight: number
banscore?: number
synced_headers?: number
synced_blocks?: number
inflight: number[]
whitelisted: boolean
permissions: string[]
minfeefilter: number
bytessent_per_msg: {
[msg: string]: number
}
bytesrecv_per_msg: {
[msg: string]: number
}
}
```

## getNetworkInfo

Returns an object containing various state info regarding P2P networking.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ describe('takeLoan success', () => {
loanSchemeId: 'scheme5'
})
await bob.generate(1)
await tGroup.waitForSync()

await alice.rpc.loan.depositToVault({
vaultId: vaultId, from: aliceAddr, amount: '10000@DFI'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import { RegTestContainer } from '@defichain/testcontainers'
import { PeerInfo } from 'packages/jellyfish-api-core/src/category/net'
import { ContainerAdapterClient } from '../../container_adapter_client'
import Dockerode from 'dockerode'
import { TestingGroup } from '@defichain/jellyfish-testing'

const addrRegExp = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}(:[0-9]{1,5})?$/

describe('Network without masternode', () => {
const container = [
new RegTestContainer(),
new RegTestContainer()
]
const client = new ContainerAdapterClient(container[0])
let createdNetwork: Dockerode.NetworkInspectInfo

beforeAll(async () => {
await container[0].start()
await container[0].createNetwork('test')
const networks = await container[0].listNetworks()
createdNetwork = networks.find(n => n.Name === 'test') as Dockerode.NetworkInspectInfo
await container[0].connectNetwork(createdNetwork.Id)

await container[1].start()
await container[1].connectNetwork(createdNetwork.Id)

// addnode
await container[0].addNode(await container[1].getIp('test'))
})

afterAll(async () => {
await container[0].stop()
await container[1].stop()

await container[0].removeNetwork(createdNetwork.Id)
})

it('should getPeerInfo', async () => {
const peers: PeerInfo[] = await client.net.getPeerInfo()

expect(peers.length).toBeGreaterThan(0)

for (const peer of peers) {
expect(typeof peer.id).toStrictEqual('number')

expect(typeof peer.addr).toStrictEqual('string')
expect(addrRegExp.test(peer.addr)).toBeTruthy()

if (peer.addrbind !== undefined) {
expect(typeof peer.addrbind).toStrictEqual('string')
expect(addrRegExp.test(peer.addrbind)).toBeTruthy()
}

if (peer.addrlocal !== undefined) {
expect(typeof peer.addrlocal).toStrictEqual('string')
expect(addrRegExp.test(peer.addrlocal)).toBeTruthy()
}

expect(typeof peer.services).toStrictEqual('string')
expect(peer.services).toHaveLength(16)

expect(typeof peer.relaytxes).toStrictEqual('boolean')
expect(typeof peer.lastsend).toStrictEqual('number')
expect(typeof peer.lastrecv).toStrictEqual('number')
expect(typeof peer.bytessent).toStrictEqual('number')
expect(typeof peer.bytesrecv).toStrictEqual('number')
expect(typeof peer.conntime).toStrictEqual('number')
expect(typeof peer.timeoffset).toStrictEqual('number')

if (peer.pingtime !== undefined) {
expect(typeof peer.pingtime).toStrictEqual('number')
}

if (peer.minping !== undefined) {
expect(typeof peer.minping).toStrictEqual('number')
}

if (peer.pingwait !== undefined) {
expect(typeof peer.pingwait).toStrictEqual('number')
}

expect(typeof peer.version).toStrictEqual('number')
expect(typeof peer.subver).toStrictEqual('string')
expect(typeof peer.inbound).toStrictEqual('boolean')
expect(typeof peer.addnode).toStrictEqual('boolean')
expect(typeof peer.startingheight).toStrictEqual('number')

if (peer.banscore !== undefined) {
expect(typeof peer.banscore).toStrictEqual('number')
}

if (peer.synced_headers !== undefined) {
expect(typeof peer.synced_headers).toStrictEqual('number')
}

if (peer.synced_blocks !== undefined) {
expect(typeof peer.synced_blocks).toStrictEqual('number')
}

expect(typeof peer.inflight).toStrictEqual('object')
expect(typeof peer.whitelisted).toStrictEqual('boolean')
expect(typeof peer.permissions).toStrictEqual('object')
expect(typeof peer.minfeefilter).toStrictEqual('number')

for (const key in peer.bytessent_per_msg) {
expect(typeof peer.bytessent_per_msg[key]).toStrictEqual('number')
}

for (const key in peer.bytesrecv_per_msg) {
expect(typeof peer.bytesrecv_per_msg[key]).toStrictEqual('number')
}
}
})
})

describe('Network with masternode', () => {
const tgroup = TestingGroup.create(2)
const { rpc: { net } } = tgroup.get(0)

beforeAll(async () => {
await tgroup.start()
})

afterAll(async () => {
await tgroup.stop()
})

it('should getPeerInfo', async () => {
const peers: PeerInfo[] = await net.getPeerInfo()

expect(peers.length).toBeGreaterThan(0)

for (const peer of peers) {
expect(typeof peer.id).toStrictEqual('number')

expect(typeof peer.addr).toStrictEqual('string')
expect(addrRegExp.test(peer.addr)).toBeTruthy()

if (peer.addrbind !== undefined) {
expect(typeof peer.addrbind).toStrictEqual('string')
expect(addrRegExp.test(peer.addrbind)).toBeTruthy()
}

if (peer.addrlocal !== undefined) {
expect(typeof peer.addrlocal).toStrictEqual('string')
expect(addrRegExp.test(peer.addrlocal)).toBeTruthy()
}

expect(typeof peer.services).toStrictEqual('string')
expect(peer.services).toHaveLength(16)

expect(typeof peer.relaytxes).toStrictEqual('boolean')
expect(typeof peer.lastsend).toStrictEqual('number')
expect(typeof peer.lastrecv).toStrictEqual('number')
expect(typeof peer.bytessent).toStrictEqual('number')
expect(typeof peer.bytesrecv).toStrictEqual('number')
expect(typeof peer.conntime).toStrictEqual('number')
expect(typeof peer.timeoffset).toStrictEqual('number')

if (peer.pingtime !== undefined) {
expect(typeof peer.pingtime).toStrictEqual('number')
}

if (peer.minping !== undefined) {
expect(typeof peer.minping).toStrictEqual('number')
}

if (peer.pingwait !== undefined) {
expect(typeof peer.pingwait).toStrictEqual('number')
}

expect(typeof peer.version).toStrictEqual('number')
expect(typeof peer.subver).toStrictEqual('string')
expect(typeof peer.inbound).toStrictEqual('boolean')
expect(typeof peer.addnode).toStrictEqual('boolean')
expect(typeof peer.startingheight).toStrictEqual('number')

if (peer.banscore !== undefined) {
expect(typeof peer.banscore).toStrictEqual('number')
}

if (peer.synced_headers !== undefined) {
expect(typeof peer.synced_headers).toStrictEqual('number')
}

if (peer.synced_blocks !== undefined) {
expect(typeof peer.synced_blocks).toStrictEqual('number')
}

expect(typeof peer.inflight).toStrictEqual('object')
expect(typeof peer.whitelisted).toStrictEqual('boolean')
expect(typeof peer.permissions).toStrictEqual('object')
expect(typeof peer.minfeefilter).toStrictEqual('number')

for (const key in peer.bytessent_per_msg) {
expect(typeof peer.bytessent_per_msg[key]).toStrictEqual('number')
}

for (const key in peer.bytesrecv_per_msg) {
expect(typeof peer.bytesrecv_per_msg[key]).toStrictEqual('number')
}
}
})
})
45 changes: 45 additions & 0 deletions packages/jellyfish-api-core/src/category/net.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ export class Net {
return await this.client.call('getconnectioncount', [], 'number')
}

/**
* Returns data about each connected network node as a json array of objects.
*
* @return {Promise<PeerInfo[]>}
*/
async getPeerInfo (): Promise<PeerInfo[]> {
return await this.client.call('getpeerinfo', [], 'number')
}

/**
* Returns an object containing various state info regarding P2P networking.
*
Expand All @@ -29,6 +38,42 @@ export class Net {
}
}

export interface PeerInfo {
id: number
addr: string
addrbind?: string
addrlocal?: string
services: string
relaytxes: boolean
lastsend: number
lastrecv: number
bytessent: number
bytesrecv: number
conntime: number
timeoffset: number
pingtime?: number
minping?: number
pingwait?: number
version: number
subver: string
inbound: boolean
addnode: boolean
startingheight: number
banscore?: number
synced_headers?: number
synced_blocks?: number
inflight: number[]
whitelisted: boolean
permissions: string[]
minfeefilter: number
bytessent_per_msg: {
[msg: string]: number
}
bytesrecv_per_msg: {
[msg: string]: number
}
}

export interface NetworkInfo {
version: number
subversion: string
Expand Down
28 changes: 28 additions & 0 deletions packages/testcontainers/src/containers/DockerContainer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@ export abstract class DockerContainer {
return networks[name].IPAddress
}

async listNetworks (): Promise<Dockerode.NetworkInspectInfo[]> {
return await this.docker.listNetworks()
}

async getNetwork (id: string): Promise<Dockerode.Network> {
return this.docker.getNetwork(id)
}

async createNetwork (name: string): Promise<void> {
await this.docker.createNetwork({
Name: name,
IPAM: {
Driver: 'default',
Config: []
}
})
}

async connectNetwork (id: string): Promise<void> {
const network = await this.getNetwork(id)
await network.connect({ Container: this.id })
}

async removeNetwork (id: string): Promise<void> {
const network = await this.getNetwork(id)
await network.remove(id)
}

/**
* Try pull docker image if it doesn't already exist.
*/
Expand Down