Skip to content

Commit

Permalink
Merge pull request #299 from airgap-it/feat/add-beacon-nodes
Browse files Browse the repository at this point in the history
Feat/add beacon nodes
  • Loading branch information
AndreasGassmann authored Nov 24, 2021
2 parents 3462b66 + 1206cdd commit 3466f8f
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 137 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@airgap/beacon-sdk",
"version": "2.3.7",
"version": "2.3.8",
"description": "The beacon-sdk allows you to easily connect DApps with Wallets through P2P communication or a chrome extension.",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
Expand Down
2 changes: 1 addition & 1 deletion src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export const SDK_VERSION: string = '2.3.7'
export const SDK_VERSION: string = '2.3.8'
export const BEACON_VERSION: string = '2'
41 changes: 13 additions & 28 deletions src/transports/clients/P2PCommunicationClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,18 @@ import { ExposedPromise } from '../../utils/exposed-promise'
const logger = new Logger('P2PCommunicationClient')

export const KNOWN_RELAY_SERVERS = [
'beacon-node-1.diamond.papers.tech',
'beacon-node-1.sky.papers.tech',
'beacon-node-0.papers.tech:8448',
'beacon-node-2.sky.papers.tech'
'beacon-node-2.sky.papers.tech',
'beacon-node-1.hope.papers.tech',
'beacon-node-1.hope-2.papers.tech',
'beacon-node-1.hope-3.papers.tech',
'beacon-node-1.hope-4.papers.tech',
'beacon-node-0.papers.tech:8448'
]
export const publicKeyToNumber = (arr: Uint8Array, mod: number) => {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i] + i
}
return Math.floor(sum % mod)
}

export const deterministicShuffle = (arr: string[], keypair: sodium.KeyPair) => {
const arrCopy: string[] = JSON.parse(JSON.stringify(arr))
const newArr: string[] = []
while (arrCopy.length > 0) {
const position = publicKeyToNumber(keypair.publicKey, arrCopy.length)
newArr.push(...arrCopy.splice(position, 1))
}
return newArr
}

/**
* @internalapi
*
*
*/
export class P2PCommunicationClient extends CommunicationClient {
private client: ExposedPromise<MatrixClient> = new ExposedPromise()
Expand Down Expand Up @@ -86,7 +72,7 @@ export class P2PCommunicationClient extends CommunicationClient {

logger.log('constructor', 'P2PCommunicationClient created')
const nodes = matrixNodes.length > 0 ? matrixNodes : KNOWN_RELAY_SERVERS
this.ENABLED_RELAY_SERVERS = deterministicShuffle(nodes, keyPair)
this.ENABLED_RELAY_SERVERS = nodes
}

public async getPairingRequestInfo(): Promise<P2PPairingRequest> {
Expand Down Expand Up @@ -142,12 +128,11 @@ export class P2PCommunicationClient extends CommunicationClient {
return node
}

const startIndex = publicKeyToNumber(this.keyPair.publicKey, this.ENABLED_RELAY_SERVERS.length)
let offset = 0
const nodes = [...this.ENABLED_RELAY_SERVERS]

while (offset < this.ENABLED_RELAY_SERVERS.length) {
const serverIndex = (startIndex + offset) % this.ENABLED_RELAY_SERVERS.length
const server = this.ENABLED_RELAY_SERVERS[serverIndex]
while (nodes.length > 0) {
const index = Math.floor(Math.random() * nodes.length)
const server = nodes[index]

try {
await axios.get(`https://${server}/_matrix/client/versions`)
Expand All @@ -159,7 +144,7 @@ export class P2PCommunicationClient extends CommunicationClient {
return server
} catch (relayError) {
logger.log(`Ignoring server "${server}", trying another one...`)
offset++
nodes.splice(index, 1)
}
}

Expand Down
106 changes: 1 addition & 105 deletions test/transports/p2p-client.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,15 @@ import * as sinon from 'sinon'

import { LocalStorage, P2PCommunicationClient } from '../../src'
import { BeaconEventHandler } from '../../src/events'
import {
deterministicShuffle,
publicKeyToNumber
} from '../../src/transports/clients/P2PCommunicationClient'
import { getKeypairFromSeed } from '../../src/utils/crypto'
import { generateGUID } from '../../src/utils/generate-uuid'

// use chai-as-promised plugin
chai.use(chaiAsPromised)
const expect = chai.expect

const SEED = 'test'

describe.only(`P2PCommunicationClient`, () => {
describe(`P2PCommunicationClient`, () => {
let client: P2PCommunicationClient

beforeEach(async () => {
Expand All @@ -35,103 +30,4 @@ describe.only(`P2PCommunicationClient`, () => {
it(`should have more than 1 node available`, async () => {
expect((client as any).ENABLED_RELAY_SERVERS.length > 1).to.be.true
})

it(`should return a random number from public key`, async () => {
const numberOfIterations = 1000
for (let maxNumber of [1, 2, 3, 4, 5, 10, 20]) {
const results: Record<number, number> = {}
for (let x = 0; x < numberOfIterations; x++) {
const seed = await getKeypairFromSeed(await generateGUID())
const result = publicKeyToNumber(seed.publicKey, maxNumber)
const temp = results[result] ?? 0
results[result] = temp + 1
}

const margin = 0.04 * maxNumber
const expectedAmount = Math.floor(numberOfIterations / maxNumber)

const upperLimit = expectedAmount * (1 + margin)
const lowerLimit = expectedAmount * (1 - margin)

for (let el of Object.values(results)) {
expect(el).to.be.lessThan(upperLimit)
expect(el).to.be.greaterThan(lowerLimit)
}

// TODO: Why does this fail?
// Object.values(results).forEach((el: number) => {
// isValid = isValid && el < upperLimit
// isValid = isValid && el > lowerLimit
// expect(el).to.be.greaterThan(2)
// expect(el).to.be.lessThan(2)
// })
}
})

it(`should deterministicalls shuffle an array`, async () => {
const keypair1 = await getKeypairFromSeed('test')
const keypair2 = await getKeypairFromSeed('test1')
const arr1 = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']

const shuffled1A = deterministicShuffle(arr1, keypair1)
// console.log('shuffled1A', shuffled1A)
expect(shuffled1A).to.deep.equal(['7', '2', '6', '3', '9', '4', '1', '8', '5', '10'])
const shuffled1B = deterministicShuffle(arr1, keypair2)
// console.log('shuffled1B', shuffled1B)
expect(shuffled1B).to.deep.equal(['9', '6', '3', '5', '4', '8', '7', '10', '1', '2'])

const arr2 = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
const shuffled2A = deterministicShuffle(arr2, keypair1)
// console.log('shuffled2A', shuffled2A)
expect(shuffled2A).to.deep.equal(['2', '6', '3', '8', '4', '1', '7', '5', '9'])
const shuffled2B = deterministicShuffle(arr2, keypair2)
// console.log('shuffled2B', shuffled2B)
expect(shuffled2B).to.deep.equal(['6', '3', '5', '4', '8', '7', '9', '1', '2'])
})

it(`should randomize node array`, async () => {
const testCases = [
{
seed: 'test',
order: [
'beacon-node-0.papers.tech:8448',
'beacon-node-1.sky.papers.tech',
'beacon-node-2.sky.papers.tech'
]
},
{
seed: 'test1',
order: [
'beacon-node-2.sky.papers.tech',
'beacon-node-1.sky.papers.tech',
'beacon-node-0.papers.tech:8448'
]
},
{
seed: 'test2',
order: [
'beacon-node-1.sky.papers.tech',
'beacon-node-2.sky.papers.tech',
'beacon-node-0.papers.tech:8448'
]
},
{
seed: 'test3',
order: [
'beacon-node-1.sky.papers.tech',
'beacon-node-2.sky.papers.tech',
'beacon-node-0.papers.tech:8448'
]
}
]
for (let testCase of testCases) {
const keypair = await getKeypairFromSeed(testCase.seed)
const localStorage = new LocalStorage()

const c = new P2PCommunicationClient('Test', keypair, 2, localStorage, [])
expect((c as any).ENABLED_RELAY_SERVERS, `seed: ${testCase.seed}`).to.deep.equal(
testCase.order
)
}
})
})

0 comments on commit 3466f8f

Please sign in to comment.