From 2e7c1b380a7aacc25f93008abb890946ebf33a9f Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Wed, 5 Aug 2020 16:20:24 +0200 Subject: [PATCH] chore: use libp2p as parameter --- .aegir.js | 60 +++++++++++ package.json | 10 +- src/index.js | 36 +------ test/2-nodes.spec.js | 102 ++++--------------- test/emit-self.spec.js | 14 ++- test/fixtures/peers.js | 26 +++++ test/fixtures/relay.js | 13 +++ test/multiple-nodes.spec.js | 196 +++++------------------------------- test/pubsub.spec.js | 17 ++-- test/utils/create-peer.js | 128 +++++++++++++++++++++++ test/utils/index.js | 55 ---------- 11 files changed, 301 insertions(+), 356 deletions(-) create mode 100644 .aegir.js create mode 100644 test/fixtures/peers.js create mode 100644 test/fixtures/relay.js create mode 100644 test/utils/create-peer.js diff --git a/.aegir.js b/.aegir.js new file mode 100644 index 0000000..7db0939 --- /dev/null +++ b/.aegir.js @@ -0,0 +1,60 @@ +'use strict' + +/** + * This file uses aegir hooks to + * set up a libp2p instance for browser nodes to relay through + * before tests start + */ + +const Libp2p = require('libp2p') +const PeerId = require('peer-id') + +const WS = require('libp2p-websockets') +const MPLEX = require('libp2p-mplex') +const { NOISE } = require('libp2p-noise') + +const RelayPeer = require('./test/fixtures/relay') + +let libp2p + +const before = async () => { + // Use the last peer + const peerId = await PeerId.createFromJSON(RelayPeer) + + libp2p = new Libp2p({ + addresses: { + listen: [RelayPeer.multiaddr] + }, + peerId, + modules: { + transport: [WS], + streamMuxer: [MPLEX], + connEncryption: [NOISE] + }, + config: { + relay: { + enabled: true, + hop: { + enabled: true, + active: false + } + }, + pubsub: { + enabled: false + } + } + }) + + await libp2p.start() +} + +const after = async () => { + await libp2p.stop() +} + +module.exports = { + hooks: { + pre: before, + post: after + } +} diff --git a/package.json b/package.json index 842d650..0b2f372 100644 --- a/package.json +++ b/package.json @@ -48,14 +48,17 @@ "chai-spies": "^1.0.0", "detect-node": "^2.0.4", "dirty-chai": "^2.0.1", - "it-pair": "^1.0.0", + "libp2p": "https://github.com/libp2p/js-libp2p#0.29.x", + "libp2p-mplex": "^0.9.5", + "libp2p-noise": "^1.1.2", + "libp2p-websockets": "^0.13.6", "lodash": "^4.17.15", "multiaddr": "^7.1.0", "p-defer": "^3.0.0", + "p-wait-for": "^3.1.0", "sinon": "^9.0.1" }, "dependencies": { - "async.nexttick": "^0.5.2", "buffer": "^5.6.0", "debug": "^4.1.1", "it-pipe": "^1.0.1", @@ -65,6 +68,9 @@ "protons": "^1.0.1", "time-cache": "^0.3.0" }, + "peerDependencies": { + "libp2p": "https://github.com/libp2p/js-libp2p#0.29.x" + }, "contributors": [ "David Dias ", "Vasco Santos ", diff --git a/src/index.js b/src/index.js index f3f1363..13748ff 100644 --- a/src/index.js +++ b/src/index.js @@ -15,24 +15,6 @@ const { multicodec } = require('./config') const ensureArray = utils.ensureArray -function validateRegistrar (registrar) { - if (typeof registrar !== 'object') { - throw new Error('a registrar object is required') - } - - if (typeof registrar.handle !== 'function') { - throw new Error('a handle function must be provided in registrar') - } - - if (typeof registrar.register !== 'function') { - throw new Error('a register function must be provided in registrar') - } - - if (typeof registrar.unregister !== 'function') { - throw new Error('a unregister function must be provided in registrar') - } -} - /** * FloodSub (aka dumbsub is an implementation of pubsub focused on * delivering an API for Publish/Subscribe, but with no CastTree Forming @@ -40,27 +22,17 @@ function validateRegistrar (registrar) { */ class FloodSub extends BaseProtocol { /** - * @param {PeerId} peerId instance of the peer's PeerId - * @param {Object} registrar - * @param {function} registrar.handle - * @param {function} registrar.register - * @param {function} registrar.unregister + * @param {Libp2p} libp2p instance of libp2p * @param {Object} [options] * @param {boolean} options.emitSelf if publish should emit to self, if subscribed, defaults to false * @constructor */ - constructor (peerId, registrar, options = {}) { - if (!PeerId.isPeerId(peerId)) { - throw new Error('peerId must be an instance of `peer-id`') - } - - validateRegistrar(registrar) - + constructor (libp2p, options = {}) { super({ debugName: debugName, multicodecs: multicodec, - peerId: peerId, - registrar: registrar, + peerId: libp2p.peerId, + registrar: libp2p.registrar, ...options }) diff --git a/test/2-nodes.spec.js b/test/2-nodes.spec.js index 6f7a81b..2293133 100644 --- a/test/2-nodes.spec.js +++ b/test/2-nodes.spec.js @@ -6,42 +6,36 @@ const chai = require('chai') chai.use(require('dirty-chai')) chai.use(require('chai-spies')) const expect = chai.expect + const { Buffer } = require('buffer') const pDefer = require('p-defer') +const pWaitFor = require('p-wait-for') const times = require('lodash/times') const FloodSub = require('../src') -const { multicodec } = require('../src') const { defOptions, first, - createPeerId, - createMockRegistrar, - expectSet, - ConnectionPair + expectSet } = require('./utils') +const { createPeers } = require('./utils/create-peer') + function shouldNotHappen (_) { expect.fail() } describe('basics between 2 nodes', () => { describe('fresh nodes', () => { - let peerIdA, peerIdB + let peerA, peerB let fsA, fsB - const registrarRecordA = {} - const registrarRecordB = {} - // Mount pubsub protocol before(async () => { - [peerIdA, peerIdB] = await Promise.all([ - createPeerId(), - createPeerId() - ]) + [peerA, peerB] = await createPeers({ number: 2 }) - fsA = new FloodSub(peerIdA, createMockRegistrar(registrarRecordA), defOptions) - fsB = new FloodSub(peerIdB, createMockRegistrar(registrarRecordB), defOptions) + fsA = new FloodSub(peerA, defOptions) + fsB = new FloodSub(peerB, defOptions) expect(fsA.peers.size).to.be.eql(0) expect(fsA.subscriptions.size).to.eql(0) @@ -57,34 +51,10 @@ describe('basics between 2 nodes', () => { // Connect floodsub nodes before(async () => { - const onConnectA = registrarRecordA[multicodec].onConnect - const onConnectB = registrarRecordB[multicodec].onConnect - const handleA = registrarRecordA[multicodec].handler - const handleB = registrarRecordB[multicodec].handler - - // Notice peers of connection - const [c0, c1] = ConnectionPair() - await onConnectA(peerIdB, c0) - await onConnectB(peerIdA, c1) - - await handleB({ - protocol: multicodec, - stream: c1.stream, - connection: { - remotePeer: peerIdA - } - }) - - await handleA({ - protocol: multicodec, - stream: c0.stream, - connection: { - remotePeer: peerIdB - } - }) + await peerA.dialProtocol(peerB.peerId, FloodSub.multicodec) - expect(fsA.peers.size).to.be.eql(1) - expect(fsB.peers.size).to.be.eql(1) + // Wait for peers to be ready in pubsub + await pWaitFor(() => fsA.peers.size === 1 && fsB.peers.size === 1) }) after(() => { @@ -213,21 +183,20 @@ describe('basics between 2 nodes', () => { }) describe('nodes send state on connection', () => { - let peerIdA, peerIdB + let peerA, peerB let fsA, fsB - const registrarRecordA = {} - const registrarRecordB = {} - // Mount pubsub protocol before(async () => { - [peerIdA, peerIdB] = await Promise.all([ - createPeerId(), - createPeerId() - ]) + [peerA, peerB] = await createPeers({ number: 2 }) + + fsA = new FloodSub(peerA, defOptions) + fsB = new FloodSub(peerB, defOptions) - fsA = new FloodSub(peerIdA, createMockRegistrar(registrarRecordA), defOptions) - fsB = new FloodSub(peerIdB, createMockRegistrar(registrarRecordB), defOptions) + expect(fsA.peers.size).to.be.eql(0) + expect(fsA.subscriptions.size).to.eql(0) + expect(fsB.peers.size).to.be.eql(0) + expect(fsB.subscriptions.size).to.eql(0) }) // Start pubsub @@ -255,35 +224,8 @@ describe('basics between 2 nodes', () => { }) it('existing subscriptions are sent upon peer connection', async () => { - const dial = async () => { - const onConnectA = registrarRecordA[multicodec].onConnect - const onConnectB = registrarRecordB[multicodec].onConnect - const handleA = registrarRecordA[multicodec].handler - const handleB = registrarRecordB[multicodec].handler - - // Notice peers of connection - const [c0, c1] = ConnectionPair() - await onConnectA(peerIdB, c0) - await handleB({ - protocol: multicodec, - stream: c1.stream, - connection: { - remotePeer: peerIdA - } - }) - - await onConnectB(peerIdA, c1) - await handleA({ - protocol: multicodec, - stream: c0.stream, - connection: { - remotePeer: peerIdB - } - }) - } - await Promise.all([ - dial(), + peerA.dialProtocol(peerB.peerId, FloodSub.multicodec), new Promise((resolve) => fsA.once('floodsub:subscription-change', resolve)), new Promise((resolve) => fsB.once('floodsub:subscription-change', resolve)) ]) diff --git a/test/emit-self.spec.js b/test/emit-self.spec.js index 512e519..0caab42 100644 --- a/test/emit-self.spec.js +++ b/test/emit-self.spec.js @@ -8,21 +8,19 @@ const expect = chai.expect const { Buffer } = require('buffer') const FloodSub = require('../src') -const { - createPeerId, mockRegistrar -} = require('./utils') +const { createPeers } = require('./utils/create-peer') const shouldNotHappen = (_) => expect.fail() describe('emit self', () => { let floodsub - let peerId + let peer const topic = 'Z' describe('enabled', () => { before(async () => { - peerId = await createPeerId() - floodsub = new FloodSub(peerId, mockRegistrar, { emitSelf: true }) + [peer] = await createPeers() + floodsub = new FloodSub(peer, { emitSelf: true }) }) before(async () => { @@ -44,8 +42,8 @@ describe('emit self', () => { describe('disabled', () => { before(async () => { - peerId = await createPeerId() - floodsub = new FloodSub(peerId, mockRegistrar, { emitSelf: false }) + [peer] = await createPeers() + floodsub = new FloodSub(peer, { emitSelf: false }) }) before(async () => { diff --git a/test/fixtures/peers.js b/test/fixtures/peers.js new file mode 100644 index 0000000..e73697b --- /dev/null +++ b/test/fixtures/peers.js @@ -0,0 +1,26 @@ +'use strict' + +/** + * These peer id / keypairs are used across tests to seed peers + */ +module.exports = [{ + id: 'QmNMMAqSxPetRS1cVMmutW5BCN1qQQyEr4u98kUvZjcfEw', + privKey: 'CAASpQkwggShAgEAAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAECggEAB2H2uPRoRCAKU+T3gO4QeoiJaYKNjIO7UCplE0aMEeHDnEjAKC1HQ1G0DRdzZ8sb0fxuIGlNpFMZv5iZ2ZFg2zFfV//DaAwTek9tIOpQOAYHUtgHxkj5FIlg2BjlflGb+ZY3J2XsVB+2HNHkUEXOeKn2wpTxcoJE07NmywkO8Zfr1OL5oPxOPlRN1gI4ffYH2LbfaQVtRhwONR2+fs5ISfubk5iKso6BX4moMYkxubYwZbpucvKKi/rIjUA3SK86wdCUnno1KbDfdXSgCiUlvxt/IbRFXFURQoTV6BOi3sP5crBLw8OiVubMr9/8WE6KzJ0R7hPd5+eeWvYiYnWj4QKBgQD6jRlAFo/MgPO5NZ/HRAk6LUG+fdEWexA+GGV7CwJI61W/Dpbn9ZswPDhRJKo3rquyDFVZPdd7+RlXYg1wpmp1k54z++L1srsgj72vlg4I8wkZ4YLBg0+zVgHlQ0kxnp16DvQdOgiRFvMUUMEgetsoIx1CQWTd67hTExGsW+WAZQKBgQDT/WaHWvwyq9oaZ8G7F/tfeuXvNTk3HIJdfbWGgRXB7lJ7Gf6FsX4x7PeERfL5a67JLV6JdiLLVuYC2CBhipqLqC2DB962aKMvxobQpSljBBZvZyqP1IGPoKskrSo+2mqpYkeCLbDMuJ1nujgMP7gqVjabs2zj6ACKmmpYH/oNowJ/T0ZVtvFsjkg+1VsiMupUARRQuPUWMwa9HOibM1NIZcoQV2NGXB5Z++kR6JqxQO0DZlKArrviclderUdY+UuuY4VRiSEprpPeoW7ZlbTku/Ap8QZpWNEzZorQDro7bnfBW91fX9/81ets/gCPGrfEn+58U3pdb9oleCOQc/ifpQKBgBTYGbi9bYbd9vgZs6bd2M2um+VFanbMytS+g5bSIn2LHXkVOT2UEkB+eGf9KML1n54QY/dIMmukA8HL1oNAyalpw+/aWj+9Ui5kauUhGEywHjSeBEVYM9UXizxz+m9rsoktLLLUI0o97NxCJzitG0Kub3gn0FEogsUeIc7AdinZAoGBANnM1vcteSQDs7x94TDEnvvqwSkA2UWyLidD2jXgE0PG4V6tTkK//QPBmC9eq6TIqXkzYlsErSw4XeKO91knFofmdBzzVh/ddgx/NufJV4tXF+a2iTpqYBUJiz9wpIKgf43/Ob+P1EA99GAhSdxz1ess9O2aTqf3ANzn6v6g62Pv', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAE=' +}, { + id: 'QmW8rAgaaA6sRydK1k6vonShQME47aDxaFidbtMevWs73t', + privKey: 'CAASpwkwggSjAgEAAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAECggEAHq2f8MqpYjLiAFZKl9IUs3uFZkEiZsgx9BmbMAb91Aec+WWJG4OLHrNVTG1KWp+IcaQablEa9bBvoToQnS7y5OpOon1d066egg7Ymfmv24NEMM5KRpktCNcOSA0CySpPIB6yrg6EiUr3ixiaFUGABKkxmwgVz/Q15IqM0ZMmCUsC174PMAz1COFZxD0ZX0zgHblOJQW3dc0X3XSzhht8vU02SMoVObQHQfeXEHv3K/RiVj/Ax0bTc5JVkT8dm8xksTtsFCNOzRBqFS6MYqX6U/u0Onz3Jm5Jt7fLWb5n97gZR4SleyGrqxYNb46d9X7mP0ie7E6bzFW0DsWBIeAqVQKBgQDW0We2L1n44yOvJaMs3evpj0nps13jWidt2I3RlZXjWzWHiYQfvhWUWqps/xZBnAYgnN/38xbKzHZeRNhrqOo+VB0WK1IYl0lZVE4l6TNKCsLsUfQzsb1pePkd1eRZA+TSqsi+I/IOQlQU7HA0bMrah/5FYyUBP0jYvCOvYTlZuwKBgQCvkcVRydVlzjUgv7lY5lYvT8IHV5iYO4Qkk2q6Wjv9VUKAJZauurMdiy05PboWfs5kbETdwFybXMBcknIvZO4ihxmwL8mcoNwDVZHI4bXapIKMTCyHgUKvJ9SeTcKGC7ZuQJ8mslRmYox/HloTOXEJgQgPRxXcwa3amzvdZI+6LwKBgQCLsnQqgxKUi0m6bdR2qf7vzTH4258z6X34rjpT0F5AEyF1edVFOz0XU/q+lQhpNEi7zqjLuvbYfSyA026WXKuwSsz7jMJ/oWqev/duKgAjp2npesY/E9gkjfobD+zGgoS9BzkyhXe1FCdP0A6L2S/1+zg88WOwMvJxl6/xLl24XwKBgCm60xSajX8yIQyUpWBM9yUtpueJ2Xotgz4ST+bVNbcEAddll8gWFiaqgug9FLLuFu5lkYTHiPtgc1RNdphvO+62/9MRuLDixwh/2TPO+iNqwKDKJjda8Nei9vVddCPaOtU/xNQ0xLzFJbG9LBmvqH9izOCcu8SJwGHaTcNUeJj/AoGADCJ26cY30c13F/8awAAmFYpZWCuTP5ppTsRmjd63ixlrqgkeLGpJ7kYb5fXkcTycRGYgP0e1kssBGcmE7DuG955fx3ZJESX3GQZ+XfMHvYGONwF1EiK1f0p6+GReC2VlQ7PIkoD9o0hojM6SnWvv9EXNjCPALEbfPFFvcniKVsE=', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAE=' +}, { + id: 'QmZqCdSzgpsmB3Qweb9s4fojAoqELWzqku21UVrqtVSKi4', + privKey: 'CAASpgkwggSiAgEAAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAECggEAQ1N0qHoxl5pmvqv8iaFlqLSUmx5y6GbI6CGJMQpvV9kQQU68yjItr3VuIXx8d/CBZyEMAK4oko7OeOyMcr3MLKLy3gyQWnXgsopDjhZ/8fH8uwps8g2+IZuFJrO+6LaxEPGvFu06fOiphPUVfn40R2KN/iBjGeox+AaXijmCqaV2vEdNJJPpMfz6VKZBDLTrbiqvo/3GN1U99PUqfPWpOWR29oAhh/Au6blSqvqTUPXB2+D/X6e1JXv31mxMPK68atDHSUjZWKB9lE4FMK1bkSKJRbyXmNIlbZ9V8X4/0r8/6T7JnW7ZT8ugRkquohmwgG7KkDXB1YsOCKXYUqzVYQKBgQDtnopFXWYl7XUyePJ/2MA5i7eoko9jmF44L31irqmHc5unNf6JlNBjlxTNx3WyfzhUzrn3c18psnGkqtow0tkBj5hmqn8/WaPbc5UA/5R1FNaNf8W5khn7MDm6KtYRPjN9djqTDiVHyC6ljONYd+5S+MqyKVWZ3t/xvG60sw85qwKBgQCpmpDtL+2JBwkfeUr3LyDcQxvbfzcv8lXj2otopWxWiLiZF1HzcqgAa2CIwu9kCGEt9Zr+9E4uINbe1To0b01/FhvR6xKO/ukceGA/mBB3vsKDcRmvpBUp+3SmnhY0nOk+ArQl4DhJ34k8pDM3EDPrixPf8SfVdU/8IM32lsdHhQKBgHLgpvCKCwxjFLnmBzcPzz8C8TOqR3BbBZIcQ34l+wflOGdKj1hsfaLoM8KYn6pAHzfBCd88A9Hg11hI0VuxVACRL5jS7NnvuGwsIOluppNEE8Ys86aXn7/0vLPoab3EWJhbRE48FIHzobmft3nZ4XpzlWs02JGfUp1IAC2UM9QpAoGAeWy3pZhSr2/iEC5+hUmwdQF2yEbj8+fDpkWo2VrVnX506uXPPkQwE1zM2Bz31t5I9OaJ+U5fSpcoPpDaAwBMs1fYwwlRWB8YNdHY1q6/23svN3uZsC4BGPV2JnO34iMUudilsRg+NGVdk5TbNejbwx7nM8Urh59djFzQGGMKeSECgYA0QMCARPpdMY50Mf2xQaCP7HfMJhESSPaBq9V3xY6ToEOEnXgAR5pNjnU85wnspHp+82r5XrKfEQlFxGpj2YA4DRRmn239sjDa29qP42UNAFg1+C3OvXTht1d5oOabaGhU0udwKmkEKUbb0bG5xPQJ5qeSJ5T1gLzLk3SIP0GlSw==', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAE=' +}, { + id: 'QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA', + privKey: 'CAASpwkwggSjAgEAAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAECggEAS64HK8JZfE09eYGJNWPe8ECmD1C7quw21BpwVe+GVPSTizvQHswPohbKDMNj0srXDMPxCnNw1OgqcaOwyjsGuZaOoXoTroTM8nOHRIX27+PUqzaStS6aCG2IsiCozKUHjGTuupftS7XRaF4eIsUtWtFcQ1ytZ9pJYHypRQTi5NMSrTze5ThjnWxtHilK7gnBXik+aR0mYEVfSn13czQEC4rMOs+b9RAc/iibDNoLopfIdvmCCvfxzmySnR7Cu1iSUAONkir7PB+2Mt/qRFCH6P+jMamtCgQ8AmifXgVmDUlun+4MnKg3KrPd6ZjOEKhVe9mCHtGozk65RDREShfDdQKBgQDi+x2MuRa9peEMOHnOyXTS+v+MFcfmG0InsO08rFNBKZChLB+c9UHBdIvexpfBHigSyERfuDye4z6lxi8ZnierWMYJP30nxmrnxwTGTk1MQquhfs1A0kpmDnPsjlOS/drEIEIssNx2WbfJ7YtMxLWBtp+BJzGpQmr0LKC+NHRSrwKBgQCXiy2kJESIUkIs2ihV55hhT6/bZo1B1O5DPA2nkjOBXqXF6fvijzMDX82JjLd07lQZlI0n1Q/Hw0p4iYi9YVd2bLkLXF5UIb2qOeHj76enVFOrPHUSkC9Y2g/0Xs+60Ths2xRd8RrrfQU3kl5iVpBywkCIrb2M5+wRnNTk1W3TtwKBgQCvplyrteAfSurpJhs9JzE8w/hWU9SqAZYkWQp91W1oE95Um2yrbjBAoQxMjaqKS+f/APPIjy56Vqj4aHGyhW11b/Fw3qzfxvCcBKtxOs8eoMlo5FO6QgJJEA4tlcafDcvp0nzjUMqK28safLU7503+33B35fjMXxWdd5u9FaKfCQKBgC4W6j6tuRosymuRvgrCcRnHfpify/5loEFallyMnpWOD6Tt0OnK25z/GifnYDRz96gAAh5HMpFy18dpLOlMHamqz2yhHx8/U8vd5tHIJZlCkF/X91M5/uxrBccwvsT2tM6Got8fYSyVzWxlW8dUxIHiinYHQUsFjkqdBDLEpq5pAoGASoTw5RBEWFM0GuAZdXsyNyxU+4S+grkTS7WdW/Ymkukh+bJZbnvF9a6MkSehqXnknthmufonds2AFNS//63gixENsoOhzT5+2cdfc6tJECvJ9xXVXkf85AoQ6T/RrXF0W4m9yQyCngNJUrKUOIH3oDIfdZITlYzOC3u1ojj7VuQ=', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAE=' +}, { + id: 'QmScLDqRg7H6ipCYxm9fVk152UWavQFKscTdoT4YNHxgqp', + privKey: 'CAASpwkwggSjAgEAAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAECggEAdmt1dyswR2p4tdIeNpY7Pnj9JNIhTNDPznefI0dArCdBvBMhkVaYk6MoNIxcj6l7YOrDroAF8sXr0TZimMY6B/pERKCt/z1hPWTxRQBBAvnHhwvwRPq2jK6BfhAZoyM8IoBNKowP9mum5QUNdGV4Al8s73KyFX0IsCfgZSvNpRdlt+DzPh+hu/CyoZaMpRchJc1UmK8Fyk3KfO+m0DZNfHP5P08lXNfM6MZLgTJVVgERHyG+vBOzTd2RElMe19nVCzHwb3dPPRZSQ7Fnz3rA+GeLqsM2Zi4HNhfbD1OcD9C4wDj5tYL6hWTkdz4IlfVcjCeUHxgIOhdDV2K+OwbuAQKBgQD0FjUZ09UW2FQ/fitbvIB5f1SkXWPxTF9l6mAeuXhoGv2EtQUO4vq/PK6N08RjrZdWQy6UsqHgffi7lVQ8o3hvCKdbtf4sP+cM92OrY0WZV89os79ndj4tyvmnP8WojwRjt/2XEfgdoWcgWxW9DiYINTOQVimZX+X/3on4s8hEgQKBgQCdY3kOMbyQeLTRkqHXjVTY4ddO+v4S4wOUa1l4rTqAbq1W3JYWwoDQgFuIu3limIHmjnSJpCD4EioXFsM7p6csenoc20sHxsaHnJ6Mn5Te41UYmY9EW0otkQ0C3KbXM0hwQkjyplnEmZawGKmjEHW8DJ3vRYTv9TUCgYKxDHgOzQKBgB4A/NYH7BG61eBYKgxEx6YnuMfbkwV+Vdu5S8d7FQn3B2LgvZZu4FPRqcNVXLbEB+5ao8czjiKCWaj1Wj15+rvrXGcxn+Tglg5J+r5+nXeUC7LbJZQaPNp0MOwWMr3dlrSLUWjYlJ9Pz9VyXOG4c4Rexc/gR4zK9QLW4C7qKpwBAoGAZzyUb0cYlPtYQA+asTU3bnvVKy1f8yuNcZFowst+EDiI4u0WVh+HNzy6zdmLKa03p+/RaWeLaK0hhrubnEnAUmCUMNF3ScaM+u804LDcicc8TkKLwx7ObU0z56isl4RAA8K27tNHFrpYKXJD834cfBkaj5ReOrfw6Y/iFhhDuBECgYEA8gbC76uz7LSHhW30DSRTcqOzTyoe2oYKQaxuxYNp7vSSOkcdRen+mrdflDvud2q/zN2QdL4pgqdldHlR35M/lJ0f0B6zp74jlzbO9700wzsOqreezGc5eWiroDL100U9uIZ50BKb8CKtixIHpinUSPIUcVDkSAZ2y7mbfCxQwqQ=', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAE=' +}] diff --git a/test/fixtures/relay.js b/test/fixtures/relay.js new file mode 100644 index 0000000..47057a2 --- /dev/null +++ b/test/fixtures/relay.js @@ -0,0 +1,13 @@ +'use strict' + +/** + * This peer id / keypair / multiaddr is used to seed a relay node, + * used in browser tests to coordinate / relay messages between browser peers + */ + +module.exports = { + id: 'QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN', + privKey: 'CAASpwkwggSjAgEAAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAECggEBAKb5aN/1w3pBqz/HqRMbQpYLNuD33M3PexBNPAy+P0iFpDo63bh5Rz+A4lvuFNmzUX70MFz7qENlzi6+n/zolxMB29YtWBUH8k904rTEjXXl//NviQgITZk106tx+4k2x5gPEm57LYGfBOdFAUzNhzDnE2LkXwRNzkS161f7zKwOEsaGWRscj6UvhO4MIFxjb32CVwt5eK4yOVqtyMs9u30K4Og+AZYTlhtm+bHg6ndCCBO6CQurCQ3jD6YOkT+L3MotKqt1kORpvzIB0ujZRf49Um8wlcjC5G9aexBeGriXaVdPF62zm7GA7RMsbQM/6aRbA1fEQXvJhHUNF9UFeaECgYEA8wCjKqQA7UQnHjRwTsktdwG6szfxd7z+5MTqHHTWhWzgcQLgdh5/dO/zanEoOThadMk5C1Bqjq96gH2xim8dg5XQofSVtV3Ui0dDa+XRB3E3fyY4D3RF5hHv85O0GcvQc6DIb+Ja1oOhvHowFB1C+CT3yEgwzX/EK9xpe+KtYAkCgYEAv7hCnj/DcZFU3fAfS+unBLuVoVJT/drxv66P686s7J8UM6tW+39yDBZ1IcwY9vHFepBvxY2fFfEeLI02QFM+lZXVhNGzFkP90agNHK01psGgrmIufl9zAo8WOKgkLgbYbSHzkkDeqyjEPU+B0QSsZOCE+qLCHSdsnTmo/TjQhj0CgYAz1+j3yfGgrS+jVBC53lXi0+2fGspbf2jqKdDArXSvFqFzuudki/EpY6AND4NDYfB6hguzjD6PnoSGMUrVfAtR7X6LbwEZpqEX7eZGeMt1yQPMDr1bHrVi9mS5FMQR1NfuM1lP9Xzn00GIUpE7WVrWUhzDEBPJY/7YVLf0hFH08QKBgDWBRQZJIVBmkNrHktRrVddaSq4U/d/Q5LrsCrpymYwH8WliHgpeTQPWmKXwAd+ZJdXIzYjCt202N4eTeVqGYOb6Q/anV2WVYBbM4avpIxoA28kPGY6nML+8EyWIt2ApBOmgGgvtEreNzwaVU9NzjHEyv6n7FlVwlT1jxCe3XWq5AoGASYPKQoPeDlW+NmRG7z9EJXJRPVtmLL40fmGgtju9QIjLnjuK8XaczjAWT+ySI93Whu+Eujf2Uj7Q+NfUjvAEzJgwzuOd3jlQvoALq11kuaxlNQTn7rx0A1QhBgUJE8AkvShPC9FEnA4j/CLJU0re9H/8VvyN6qE0Mho0+YbjpP8=', + pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAE=', + multiaddr: '/ip4/127.0.0.1/tcp/15001/ws/p2p/QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN' +} diff --git a/test/multiple-nodes.spec.js b/test/multiple-nodes.spec.js index 05aea7c..885c18c 100644 --- a/test/multiple-nodes.spec.js +++ b/test/multiple-nodes.spec.js @@ -9,16 +9,11 @@ const { Buffer } = require('buffer') const pDefer = require('p-defer') const FloodSub = require('../src') -const { multicodec } = require('../src') -const { - createPeerId, - createMockRegistrar, - expectSet, - ConnectionPair -} = require('./utils') +const { expectSet } = require('./utils') +const { createPeers } = require('./utils/create-peer') -async function spawnPubSubNode (peerId, reg) { - const ps = new FloodSub(peerId, reg, { emitSelf: true }) +async function spawnPubSubNode (peer) { + const ps = new FloodSub(peer, { emitSelf: true }) await ps.start() return ps @@ -31,71 +26,22 @@ describe('multiple nodes (more than 2)', () => { // ◉────◉────◉ // a b c let psA, psB, psC - let peerIdA, peerIdB, peerIdC - - const registrarRecordA = {} - const registrarRecordB = {} - const registrarRecordC = {} + let peerA, peerB, peerC beforeEach(async () => { - [peerIdA, peerIdB, peerIdC] = await Promise.all([ - createPeerId(), - createPeerId(), - createPeerId() - ]); - - [psA, psB, psC] = await Promise.all([ - spawnPubSubNode(peerIdA, createMockRegistrar(registrarRecordA)), - spawnPubSubNode(peerIdB, createMockRegistrar(registrarRecordB)), - spawnPubSubNode(peerIdC, createMockRegistrar(registrarRecordC)) + [peerA, peerB, peerC] = await createPeers({ number: 3 }) + + ;[psA, psB, psC] = await Promise.all([ + spawnPubSubNode(peerA), + spawnPubSubNode(peerB), + spawnPubSubNode(peerC) ]) }) // connect nodes beforeEach(async () => { - const onConnectA = registrarRecordA[multicodec].onConnect - const onConnectB = registrarRecordB[multicodec].onConnect - const onConnectC = registrarRecordC[multicodec].onConnect - const handleA = registrarRecordA[multicodec].handler - const handleB = registrarRecordB[multicodec].handler - const handleC = registrarRecordC[multicodec].handler - - // Notice peers of connection - const [d0, d1] = ConnectionPair() - await onConnectA(peerIdB, d0) - await handleB({ - protocol: multicodec, - stream: d1.stream, - connection: { - remotePeer: peerIdA - } - }) - await onConnectB(peerIdA, d1) - await handleA({ - protocol: multicodec, - stream: d0.stream, - connection: { - remotePeer: peerIdB - } - }) - - const [d2, d3] = ConnectionPair() - await onConnectB(peerIdC, d2) - await handleC({ - protocol: multicodec, - stream: d3.stream, - connection: { - remotePeer: peerIdB - } - }) - await onConnectC(peerIdB, d3) - await handleB({ - protocol: multicodec, - stream: d2.stream, - connection: { - remotePeer: peerIdC - } - }) + await peerA.dialProtocol(peerB.peerId, FloodSub.multicodec) + await peerB.dialProtocol(peerC.peerId, FloodSub.multicodec) }) after(() => Promise.all([ @@ -260,117 +206,25 @@ describe('multiple nodes (more than 2)', () => { // ◉─┘ └─◉ // a let psA, psB, psC, psD, psE - let peerIdA, peerIdB, peerIdC, peerIdD, peerIdE - - const registrarRecordA = {} - const registrarRecordB = {} - const registrarRecordC = {} - const registrarRecordD = {} - const registrarRecordE = {} + let peerA, peerB, peerC, peerD, peerE before(async () => { - [peerIdA, peerIdB, peerIdC, peerIdD, peerIdE] = await Promise.all([ - createPeerId(), - createPeerId(), - createPeerId(), - createPeerId(), - createPeerId() - ]); - - [psA, psB, psC, psD, psE] = await Promise.all([ - spawnPubSubNode(peerIdA, createMockRegistrar(registrarRecordA)), - spawnPubSubNode(peerIdB, createMockRegistrar(registrarRecordB)), - spawnPubSubNode(peerIdC, createMockRegistrar(registrarRecordC)), - spawnPubSubNode(peerIdD, createMockRegistrar(registrarRecordD)), - spawnPubSubNode(peerIdE, createMockRegistrar(registrarRecordE)) + [peerA, peerB, peerC, peerD, peerE] = await createPeers({ number: 5 }) + ;[psA, psB, psC, psD, psE] = await Promise.all([ + spawnPubSubNode(peerA), + spawnPubSubNode(peerB), + spawnPubSubNode(peerC), + spawnPubSubNode(peerD), + spawnPubSubNode(peerE) ]) }) // connect nodes before(async () => { - const onConnectA = registrarRecordA[multicodec].onConnect - const onConnectB = registrarRecordB[multicodec].onConnect - const onConnectC = registrarRecordC[multicodec].onConnect - const onConnectD = registrarRecordD[multicodec].onConnect - const onConnectE = registrarRecordE[multicodec].onConnect - const handleA = registrarRecordA[multicodec].handler - const handleB = registrarRecordB[multicodec].handler - const handleC = registrarRecordC[multicodec].handler - const handleD = registrarRecordD[multicodec].handler - const handleE = registrarRecordE[multicodec].handler - - // Notice peers of connection - const [d0, d1] = ConnectionPair() // A <-> B - await onConnectA(peerIdB, d0) - await handleB({ - protocol: multicodec, - stream: d1.stream, - connection: { - remotePeer: peerIdA - } - }) - await onConnectB(peerIdA, d1) - await handleA({ - protocol: multicodec, - stream: d0.stream, - connection: { - remotePeer: peerIdB - } - }) - - const [d2, d3] = ConnectionPair() // B <-> C - await onConnectB(peerIdC, d2) - await handleC({ - protocol: multicodec, - stream: d3.stream, - connection: { - remotePeer: peerIdB - } - }) - await onConnectC(peerIdB, d3) - await handleB({ - protocol: multicodec, - stream: d2.stream, - connection: { - remotePeer: peerIdC - } - }) - - const [d4, d5] = ConnectionPair() // C <-> D - await onConnectC(peerIdD, d4) - await handleD({ - protocol: multicodec, - stream: d5.stream, - connection: { - remotePeer: peerIdC - } - }) - await onConnectD(peerIdC, d5) - await handleC({ - protocol: multicodec, - stream: d4.stream, - connection: { - remotePeer: peerIdD - } - }) - - const [d6, d7] = ConnectionPair() // D <-> E - await onConnectD(peerIdE, d6) - await handleE({ - protocol: multicodec, - stream: d7.stream, - connection: { - remotePeer: peerIdD - } - }) - await onConnectE(peerIdD, d7) - await handleD({ - protocol: multicodec, - stream: d6.stream, - connection: { - remotePeer: peerIdE - } - }) + await peerA.dialProtocol(peerB.peerId, FloodSub.multicodec) + await peerB.dialProtocol(peerC.peerId, FloodSub.multicodec) + await peerC.dialProtocol(peerD.peerId, FloodSub.multicodec) + await peerD.dialProtocol(peerE.peerId, FloodSub.multicodec) }) after(() => Promise.all([ diff --git a/test/pubsub.spec.js b/test/pubsub.spec.js index 4b5311b..81dba26 100644 --- a/test/pubsub.spec.js +++ b/test/pubsub.spec.js @@ -8,7 +8,8 @@ const expect = chai.expect const sinon = require('sinon') const { Buffer } = require('buffer') const Floodsub = require('../src') -const { createPeerId, mockRegistrar } = require('./utils') + +const { createPeers } = require('./utils/create-peer') const { utils } = require('libp2p-pubsub') const defOptions = { @@ -17,13 +18,13 @@ const defOptions = { describe('pubsub', () => { let floodsub - let peerId + let peer before(async () => { expect(Floodsub.multicodec).to.exist() - peerId = await createPeerId() - floodsub = new Floodsub(peerId, mockRegistrar, defOptions) + ;[peer] = await createPeers() + floodsub = new Floodsub(peer, defOptions) }) beforeEach(() => { @@ -49,7 +50,7 @@ describe('pubsub', () => { const [topics, messages] = floodsub._emitMessages.getCall(0).args expect(topics).to.eql([topic]) expect(messages).to.eql([{ - from: peerId.toB58String(), + from: peer.peerId.toB58String(), data: message, seqno: utils.randomSeqno.getCall(0).returnValue, topicIDs: topics @@ -68,7 +69,7 @@ describe('pubsub', () => { const [topics, messages] = floodsub._forwardMessages.getCall(0).args const expected = await floodsub._buildMessage({ - from: peerId.toB58String(), + from: peer.peerId.toB58String(), data: message, seqno: utils.randomSeqno.getCall(0).returnValue, topicIDs: topics @@ -91,7 +92,7 @@ describe('pubsub', () => { const rpc = { subscriptions: [], msgs: [{ - from: peerId.id, + from: peer.peerId.id, data: Buffer.from('an unsigned message'), seqno: utils.randomSeqno(), topicIDs: [topic] @@ -121,7 +122,7 @@ describe('pubsub', () => { const rpc = { subscriptions: [], msgs: [{ - from: peerId.id, + from: peer.peerId.id, data: Buffer.from('an unsigned message'), seqno: utils.randomSeqno(), topicIDs: [topic] diff --git a/test/utils/create-peer.js b/test/utils/create-peer.js new file mode 100644 index 0000000..521f789 --- /dev/null +++ b/test/utils/create-peer.js @@ -0,0 +1,128 @@ +'use strict' + +/** + * These utilities rely on the fixtures defined in test/fixtures + * + * We create peers for use in browser/node environments + * configured to either connect directly (websocket listening multiaddr) + * or connecting through a well-known relay + */ + +const Libp2p = require('libp2p') +const multiaddr = require('multiaddr') +const PeerId = require('peer-id') + +const WS = require('libp2p-websockets') +const MPLEX = require('libp2p-mplex') +const { NOISE } = require('libp2p-noise') + +const Peers = require('../fixtures/peers') +const RelayPeer = require('../fixtures/relay') + +const defaultConfig = { + modules: { + transport: [WS], + streamMuxer: [MPLEX], + connEncryption: [NOISE] + }, + config: { + pubsub: { + enabled: false + }, + peerDiscovery: { + autoDial: false + } + } +} + +/** + * Create libp2p node, selectively determining the listen address based on the operating environment + * If no peerId is given, default to the first peer in the fixtures peer list + */ +async function createPeer ({ peerId, started = true, config = {} } = {}) { + if (!peerId) { + peerId = await PeerId.createFromJSON(Peers[0]) + } + const libp2p = await Libp2p.create({ + peerId: peerId, + addresses: { + listen: [getListenAddress(peerId)] + }, + ...defaultConfig, + ...config + }) + + if (started) { + await libp2p.start() + } + + return libp2p +} + +/** + * Create libp2p nodes from known peer ids, preconfigured to use fixture peer ids + * @param {Object} [properties] + * @param {Object} [properties.config] + * @param {number} [properties.number] number of peers (default: 1). + * @param {boolean} [properties.started] nodes should start (default: true) + * @param {boolean} [properties.seedAddressBook] nodes should have each other in their addressbook + * @return {Promise>} + */ +async function createPeers ({ number = 1, started = true, seedAddressBook = true, config = {} } = {}) { + const peerIds = await Promise.all( + Array.from({ length: number }, (_, i) => Peers[i] ? PeerId.createFromJSON(Peers[i]) : PeerId.create()) + ) + const peers = await Promise.all( + Array.from({ length: number }, (_, i) => createPeer({ peerId: peerIds[i], started: false, config: config })) + ) + + if (started) { + await Promise.all( + peers.map((p) => p.start()) + ) + + if (seedAddressBook) { + addPeersToAddressBook(peers) + } + } + + return peers +} + +// TODO: use ipfs-utils +function isBrowser () { + return typeof window === 'object' || typeof self === 'object' +} + +/** + * Selectively determine the listen address based on the operating environment + * + * If in node, use websocket address + * If in browser, use relay address + * @param {PeerId} peerId + * @return {multiaddr} + */ +function getListenAddress (peerId) { + if (isBrowser()) { + // browser + return multiaddr(`${RelayPeer.multiaddr}/p2p-circuit/p2p/${peerId.toB58String()}`) + } else { + // node + return multiaddr('/ip4/127.0.0.1/tcp/0/ws') + } +} + +function addPeersToAddressBook (peers) { + for (let i = 0; i < peers.length; i++) { + for (let j = 0; j < peers.length; j++) { + if (i !== j) { + peers[i].peerStore.addressBook.set(peers[j].peerId, peers[j].multiaddrs) + } + } + } +} + +module.exports = { + createPeer, + createPeers +} diff --git a/test/utils/index.js b/test/utils/index.js index 6e04cf5..232ffe8 100644 --- a/test/utils/index.js +++ b/test/utils/index.js @@ -1,8 +1,5 @@ 'use strict' -const PeerId = require('peer-id') -const DuplexPair = require('it-pair/duplex') - const { expect } = require('chai') exports.first = (map) => map.values().next().value @@ -11,58 +8,6 @@ exports.expectSet = (set, subs) => { expect(Array.from(set.values())).to.eql(subs) } -exports.createPeerId = async () => { - const peerId = await PeerId.create({ bits: 1024 }) - - return peerId -} - -exports.mockRegistrar = { - handle: () => {}, - register: () => {}, - unregister: () => {} -} - -exports.createMockRegistrar = (registrarRecord) => ({ - handle: (multicodecs, handler) => { - const rec = registrarRecord[multicodecs[0]] || {} - - registrarRecord[multicodecs[0]] = { - ...rec, - handler - } - }, - register: ({ multicodecs, _onConnect, _onDisconnect }) => { - const rec = registrarRecord[multicodecs[0]] || {} - - registrarRecord[multicodecs[0]] = { - ...rec, - onConnect: _onConnect, - onDisconnect: _onDisconnect - } - - return multicodecs[0] - }, - unregister: (id) => { - delete registrarRecord[id] - } -}) - -exports.ConnectionPair = () => { - const [d0, d1] = DuplexPair() - - return [ - { - stream: d0, - newStream: () => Promise.resolve({ stream: d0 }) - }, - { - stream: d1, - newStream: () => Promise.resolve({ stream: d1 }) - } - ] -} - exports.defOptions = { emitSelf: true }