From 22775bad67d026aa08cf4c29c6550e533c9be8ac Mon Sep 17 00:00:00 2001 From: haad Date: Thu, 1 Aug 2024 15:43:49 +0300 Subject: [PATCH] Add support for connecting peers through a relay --- .github/workflows/run-test.yml | 2 + conf/webpack.tests.config.js | 3 + package-lock.json | 6 +- package.json | 12 +- src/bin/cli.js | 5 + src/daemon.js | 5 +- src/lib/lander.js | 4 +- src/lib/orbiter.js | 2 +- src/utils/libp2p-config.js | 9 +- test/e2e-browser.test.js | 251 ++++++++++++------ test/utils/connect-nodes-via-relay.js | 35 +++ test/utils/connect-nodes.js | 2 +- test/utils/launch-lander.js | 37 +-- test/utils/launch-orbiter.js | 47 ++-- test/utils/relay.js | 56 ++++ .../lander-libp2p-config.js | 42 +++ .../orbiter-libp2p-config.js | 42 +++ .../utils/test-config/lander-libp2p-config.js | 40 +++ .../test-config/orbiter-libp2p-config.js | 40 +++ 19 files changed, 486 insertions(+), 154 deletions(-) create mode 100644 test/utils/connect-nodes-via-relay.js create mode 100644 test/utils/relay.js create mode 100644 test/utils/test-config-browser/lander-libp2p-config.js create mode 100644 test/utils/test-config-browser/orbiter-libp2p-config.js create mode 100644 test/utils/test-config/lander-libp2p-config.js create mode 100644 test/utils/test-config/orbiter-libp2p-config.js diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index da41894..fd78590 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -16,6 +16,8 @@ jobs: run: npm ci - name: Run linter run: npm run lint + - name: Run libp2p relay in the background + run: npm run start:relay:background - name: Run an Orbiter 1 instance in the background run: npm run start:orbiter1:background - name: Run an Orbiter 2 instance in the background diff --git a/conf/webpack.tests.config.js b/conf/webpack.tests.config.js index e28bd2a..bb532f0 100644 --- a/conf/webpack.tests.config.js +++ b/conf/webpack.tests.config.js @@ -28,6 +28,9 @@ export default (env, argv) => { }) ], resolve: { + alias: { + './test-config': path.resolve(__dirname, '../test/utils/test-config-browser') + }, modules: [ 'node_modules', path.resolve(__dirname, '../node_modules') diff --git a/package-lock.json b/package-lock.json index 65bd69b..7b3f902 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@chainsafe/libp2p-gossipsub": "^13.1.0", - "@orbitdb/core": "^2.2.0", + "@orbitdb/core": "https://github.com/orbitdb/orbitdb.git#expose-identities", "@orbitdb/set-db": "^1.0.2", "blockstore-level": "^1.1.8", "datastore-level": "^10.1.8", @@ -4182,8 +4182,8 @@ }, "node_modules/@orbitdb/core": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@orbitdb/core/-/core-2.2.0.tgz", - "integrity": "sha512-W1jScRjNVne7l0V9camdFQXrPPcWxSz7LwJzq6SryMe+xfVArrV4ADiElk7+dpQa6zwOOQpSUUfX2o46kY5dTw==", + "resolved": "git+ssh://git@github.com/orbitdb/orbitdb.git#17e322cd71b56aa19383165d16fac6c4d0094747", + "license": "MIT", "dependencies": { "@ipld/dag-cbor": "^9.0.6", "@libp2p/crypto": "^3.0.2", diff --git a/package.json b/package.json index f77fe96..bca2a4c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ }, "dependencies": { "@chainsafe/libp2p-gossipsub": "^13.1.0", - "@orbitdb/core": "^2.2.0", + "@orbitdb/core": "https://github.com/orbitdb/orbitdb.git#expose-identities", "@orbitdb/set-db": "^1.0.2", "blockstore-level": "^1.1.8", "datastore-level": "^10.1.8", @@ -37,10 +37,12 @@ "lint:fix": "standard --fix", "copy:fixtures1": "rm -rf ./orbiter1 && mkdir -p ./orbiter1/voyager/orbiter/keystore && cp -Rf test/fixtures/keystore1/** ./orbiter1/voyager/orbiter/keystore/", "copy:fixtures2": "rm -rf ./orbiter2 && mkdir -p ./orbiter2/voyager/orbiter/keystore && cp -Rf test/fixtures/keystore2/** ./orbiter2/voyager/orbiter/keystore/", - "start:orbiter1": "npm run copy:fixtures1 && node ./src/bin/cli.js daemon -p 54321 --allow --directory ./orbiter1 -vv", - "start:orbiter2": "npm run copy:fixtures2 && node ./src/bin/cli.js daemon -p 54322 --allow --directory ./orbiter2 -vv", - "start:orbiter1:background": "npm run copy:fixtures1 && node ./src/bin/cli.js daemon -p 54321 --allow --directory ./orbiter1 &", - "start:orbiter2:background": "npm run copy:fixtures2 && node ./src/bin/cli.js daemon -p 54322 --allow --directory ./orbiter2 &", + "start:relay": "node ./test/utils/relay.js", + "start:relay:background": "node ./test/utils/relay.js &", + "start:orbiter1": "npm run copy:fixtures1 && node ./src/bin/cli.js daemon -p 54321 -w 55441 --allow --directory ./orbiter1 -vv", + "start:orbiter2": "npm run copy:fixtures2 && node ./src/bin/cli.js daemon -p 54322 -w 55442 --allow --directory ./orbiter2 -vv", + "start:orbiter1:background": "npm run copy:fixtures1 && node ./src/bin/cli.js daemon -p 54321 -w 55441 --allow --directory ./orbiter1 &", + "start:orbiter2:background": "npm run copy:fixtures2 && node ./src/bin/cli.js daemon -p 54322 -w 55442 --allow --directory ./orbiter2 &", "test:browser": "npm run build:tests && ./node_modules/.bin/playwright-test test/browser/bundle.js --runner mocha" }, "standard": { diff --git a/src/bin/cli.js b/src/bin/cli.js index 09cd8e7..28257bf 100755 --- a/src/bin/cli.js +++ b/src/bin/cli.js @@ -23,6 +23,11 @@ yargs(hideBin(process.argv)) description: 'The port to listen on. Defaults to 0.', type: 'number' }) + .option('wsport', { + alias: 'w', + description: 'The port to listen on for WebSockets. Defaults to 0.', + type: 'number' + }) }, async (argv) => { await daemon({ options: argv }) diff --git a/src/daemon.js b/src/daemon.js index 14c4c76..dda9d54 100644 --- a/src/daemon.js +++ b/src/daemon.js @@ -27,10 +27,9 @@ export default async ({ options }) => { const defaultAccess = options.allow ? Access.ALLOW : Access.DENY options.verbose = options.verbose || 0 - options.silent = options.silent || false - options.port = options.port || 0 + options.wsport = options.wsport || 0 const id = orbiterId @@ -54,7 +53,7 @@ export default async ({ options }) => { const peerId = await createFromPrivKey(await keystore.getKey(id)) await keystore.close() - const libp2p = await createLibp2p(await libp2pConfig({ peerId, port: options.port })) + const libp2p = await createLibp2p(await libp2pConfig({ peerId, port: options.port, websocketPort: options.wsport })) log('peerid:', libp2p.peerId.toString()) for (const addr of libp2p.getMultiaddrs().map(e => e.toString())) { diff --git a/src/lib/lander.js b/src/lib/lander.js index e66dfca..fe2bda6 100644 --- a/src/lib/lander.js +++ b/src/lib/lander.js @@ -13,7 +13,7 @@ export default async ({ orbitdb, orbiterAddressOrId }) => { })() } - const stream = await orbitdb.ipfs.libp2p.dialProtocol(orbiterAddressOrId, voyagerProtocol) + const stream = await orbitdb.ipfs.libp2p.dialProtocol(orbiterAddressOrId, voyagerProtocol, { runOnTransientConnection: true }) await pipe(pinDBs, stream, async (source) => { for await (const chunk of source) { @@ -39,7 +39,7 @@ export default async ({ orbitdb, orbiterAddressOrId }) => { })() } - const stream = await orbitdb.ipfs.libp2p.dialProtocol(orbiterAddressOrId, voyagerProtocol) + const stream = await orbitdb.ipfs.libp2p.dialProtocol(orbiterAddressOrId, voyagerProtocol, { runOnTransientConnection: true }) await pipe(unpinDBs, stream, async source => { for await (const chunk of source) { diff --git a/src/lib/orbiter.js b/src/lib/orbiter.js index e5de78b..e97ba2c 100644 --- a/src/lib/orbiter.js +++ b/src/lib/orbiter.js @@ -28,7 +28,7 @@ export default async ({ orbitdb, defaultAccess, verbose } = {}) => { await pipe(stream, handleRequest({ log, orbitdb, pins, dbs, auth }), stream) } - await orbitdb.ipfs.libp2p.handle(voyagerProtocol, handleMessages) + await orbitdb.ipfs.libp2p.handle(voyagerProtocol, handleMessages, { runOnTransientConnection: true }) log('open pinned databases') diff --git a/src/utils/libp2p-config.js b/src/utils/libp2p-config.js index e893fca..93022c5 100644 --- a/src/utils/libp2p-config.js +++ b/src/utils/libp2p-config.js @@ -6,12 +6,12 @@ import { webSockets } from '@libp2p/websockets' import { gossipsub } from '@chainsafe/libp2p-gossipsub' import { mdns } from '@libp2p/mdns' -export const config = ({ peerId, port } = {}) => { +export const config = ({ peerId, port, websocketPort } = {}) => { const conf = { addresses: { listen: [ - '/ip4/0.0.0.0/tcp/0', - `/ip4/0.0.0.0/tcp/${port || 0}/ws` + `/ip4/0.0.0.0/tcp/${port || 0}`, + `/ip4/0.0.0.0/tcp/${websocketPort || 0}/ws` ] }, transports: [ @@ -24,6 +24,9 @@ export const config = ({ peerId, port } = {}) => { streamMuxers: [ yamux() ], + connectionGater: { + denyDialMultiaddr: () => false // allow dialling of private addresses. + }, peerDiscovery: [ mdns() ], diff --git a/test/e2e-browser.test.js b/test/e2e-browser.test.js index 7fbf22e..abff685 100644 --- a/test/e2e-browser.test.js +++ b/test/e2e-browser.test.js @@ -2,116 +2,207 @@ import { multiaddr } from '@multiformats/multiaddr' import { strictEqual, deepStrictEqual } from 'assert' import { rimraf } from 'rimraf' import { launchLander } from './utils/launch-lander.js' +import { launchOrbiter } from './utils/launch-orbiter.js' import waitFor from './utils/wait-for.js' +import connectPeers from './utils/connect-nodes-via-relay.js' + +const isBrowser = () => typeof window !== 'undefined' + +describe('End-to-End Browser Tests', function () { + describe('Orbiter in Nodejs', function () { + this.timeout(10000) + + const orbiterAddress1 = isBrowser() + ? multiaddr('/ip4/127.0.0.1/tcp/55441/ws/p2p/16Uiu2HAmBzKcgCfpJ4j4wJSLkKLbCVvnNBWPnhexrnJWJf1fDu5y') + : multiaddr('/ip4/127.0.0.1/tcp/54321/p2p/16Uiu2HAmBzKcgCfpJ4j4wJSLkKLbCVvnNBWPnhexrnJWJf1fDu5y') + + const orbiterAddress2 = isBrowser() + ? multiaddr('/ip4/127.0.0.1/tcp/55442/ws/p2p/16Uiu2HAmATMovCwY46yyJib7bGZF2f2XLRar7d7R3NJCSJtuyQLt') + : multiaddr('/ip4/127.0.0.1/tcp/54322/p2p/16Uiu2HAmATMovCwY46yyJib7bGZF2f2XLRar7d7R3NJCSJtuyQLt') + + let lander1 + let lander2 + let lander3 + + beforeEach(async function () { + lander1 = await launchLander({ orbiterAddress: orbiterAddress1, directory: 'lander1' }) + lander2 = await launchLander({ orbiterAddress: orbiterAddress1, directory: 'lander2' }) + lander3 = await launchLander({ orbiterAddress: orbiterAddress2, directory: 'lander3' }) + }) + + afterEach(async function () { + if (lander1) { + await lander1.shutdown() + } + if (lander2) { + await lander2.shutdown() + } + if (lander3) { + await lander3.shutdown() + } + await rimraf('./lander1') + await rimraf('./lander2') + await rimraf('./lander3') + }) + + it('pin and replicate a database - lander1->orbiter1->lander2', async function () { + const entryAmount = 100 + let replicated = false + + const db1 = await lander1.orbitdb.open('my-db') + + for (let i = 0; i < entryAmount; i++) { + await db1.add('hello world ' + i) + } + + const expected = await db1.all() + + console.time('pin') + await lander1.pin(db1.address) + console.timeEnd('pin') + await lander1.shutdown() -describe('End-to-End Browser Test', function () { - this.timeout(10000) + console.time('pin2') + await lander2.pin(db1.address) + console.timeEnd('pin2') - const orbiterAddress1 = multiaddr('/ip4/127.0.0.1/tcp/54321/ws/p2p/16Uiu2HAmBzKcgCfpJ4j4wJSLkKLbCVvnNBWPnhexrnJWJf1fDu5y') - const orbiterAddress2 = multiaddr('/ip4/127.0.0.1/tcp/54322/ws/p2p/16Uiu2HAmATMovCwY46yyJib7bGZF2f2XLRar7d7R3NJCSJtuyQLt') + console.time('replicate') + const db2 = await lander2.orbitdb.open(db1.address) - let lander1 - let lander2 - let lander3 + const onConnected = (peerId, heads) => { + replicated = true + } - beforeEach(async function () { - lander1 = await launchLander({ orbiterAddress: orbiterAddress1, directory: 'lander1' }) - lander2 = await launchLander({ orbiterAddress: orbiterAddress1, directory: 'lander2' }) - lander3 = await launchLander({ orbiterAddress: orbiterAddress2, directory: 'lander3' }) - }) + db2.events.on('join', onConnected) - afterEach(async function () { - if (lander1) { - await lander1.shutdown() - } - if (lander2) { - await lander2.shutdown() - } - if (lander3) { - await lander3.shutdown() - } - await rimraf('./lander1') - await rimraf('./lander2') - await rimraf('./lander3') - }) + await waitFor(() => replicated, () => true) + console.timeEnd('replicate') - it('pin and replicate a database - lander1->orbiter1->lander2', async function () { - const entryAmount = 100 - let replicated = false + const res = await db2.all() - const db1 = await lander1.orbitdb.open('my-db') + strictEqual(expected.length, entryAmount) + strictEqual(res.length, entryAmount) + deepStrictEqual(expected, res) + }) - for (let i = 0; i < entryAmount; i++) { - await db1.add('hello world ' + i) - } + it('pin and replicate a database - lander1->orbiter1->orbiter2->lander3', async function () { + const entryAmount = 100 + let replicated = false - const expected = await db1.all() + const db1 = await lander1.orbitdb.open('my-db2') - console.time('pin') - await lander1.pin(db1.address) - console.timeEnd('pin') - await lander1.shutdown() + for (let i = 0; i < entryAmount; i++) { + await db1.add('hello world ' + i) + } - console.time('pin') - await lander2.pin(db1.address) - console.timeEnd('pin') + const expected = await db1.all() - console.time('replicate') - const db2 = await lander2.orbitdb.open(db1.address) + console.time('pin') + await lander1.pin(db1.address) + console.timeEnd('pin') + await lander1.shutdown() - const onConnected = (peerId, heads) => { - replicated = true - } + console.time('pin2') + await lander3.pin(db1.address) + console.timeEnd('pin2') - db2.events.on('join', onConnected) + console.time('replicate') + const db2 = await lander3.orbitdb.open(db1.address) - await waitFor(() => replicated, () => true) - console.timeEnd('replicate') + const onConnected = (peerId, heads) => { + replicated = true + } - const res = await db2.all() + db2.events.on('join', onConnected) - strictEqual(expected.length, entryAmount) - strictEqual(res.length, entryAmount) - deepStrictEqual(expected, res) + await waitFor(() => replicated, () => true) + console.timeEnd('replicate') + + const res = await db2.all() + + strictEqual(expected.length, entryAmount) + strictEqual(res.length, entryAmount) + deepStrictEqual(expected, res) + }) }) - it('pin and replicate a database - lander1->orbiter1->orbiter2->lander3', async function () { - const entryAmount = 100 - let replicated = false + describe('Orbiter in the browser', function () { + this.timeout(10000) + + const orbiterAddress1 = isBrowser() + ? multiaddr('/ip4/127.0.0.1/tcp/55441/ws/p2p/16Uiu2HAmBzKcgCfpJ4j4wJSLkKLbCVvnNBWPnhexrnJWJf1fDu5y') + : multiaddr('/ip4/127.0.0.1/tcp/54321/p2p/16Uiu2HAmBzKcgCfpJ4j4wJSLkKLbCVvnNBWPnhexrnJWJf1fDu5y') + + let orbiter + let lander1 + let lander2 - const db1 = await lander1.orbitdb.open('my-db2') + beforeEach(async function () { + orbiter = await launchOrbiter({ directory: 'orbiter3' }) - for (let i = 0; i < entryAmount; i++) { - await db1.add('hello world ' + i) - } + await connectPeers(orbiter.orbitdb.ipfs, orbiterAddress1) + + lander1 = await launchLander({ orbiterAddress: orbiterAddress1, directory: 'lander4' }) + }) + + afterEach(async function () { + if (lander1) { + await lander1.shutdown() + } + if (lander2) { + await lander2.shutdown() + } + if (orbiter) { + await orbiter.shutdown() + } + await rimraf('./lander4') + await rimraf('./lander5') + await rimraf('./orbiter3') + }) + + it('pin and replicate a database - lander1->orbiter1(nodejs)->orbiter2(browser)->lander3', async function () { + const entryAmount = 100 + let replicated = false + + const db1 = await lander1.orbitdb.open('my-db3') + + for (let i = 0; i < entryAmount; i++) { + await db1.add('hello world ' + i) + } + + const expected = await db1.all() + + console.time('pin') + await lander1.pin(db1.address) + console.timeEnd('pin') + + await lander1.shutdown() - const expected = await db1.all() + lander2 = await launchLander({ orbiterAddress: orbiter.orbitdb.ipfs.libp2p.getMultiaddrs().shift(), directory: 'lander5' }) - console.time('pin') - await lander1.pin(db1.address) - console.timeEnd('pin') - await lander1.shutdown() + await orbiter.auth.add(lander2.orbitdb.identity.id) - console.time('pin') - await lander3.pin(db1.address) - console.timeEnd('pin') + console.time('pin2') + await lander2.pin(db1.address) + console.timeEnd('pin2') - console.time('replicate') - const db2 = await lander3.orbitdb.open(db1.address) + console.time('replicate') + const db2 = await lander2.orbitdb.open(db1.address) - const onConnected = (peerId, heads) => { - replicated = true - } + const onConnected = (peerId, heads) => { + replicated = true + } - db2.events.on('join', onConnected) + db2.events.on('join', onConnected) - await waitFor(() => replicated, () => true) - console.timeEnd('replicate') + await waitFor(() => replicated, () => true) + console.timeEnd('replicate') - const res = await db2.all() + const res = await db2.all() - strictEqual(expected.length, entryAmount) - strictEqual(res.length, entryAmount) - deepStrictEqual(expected, res) + strictEqual(expected.length, entryAmount) + strictEqual(res.length, entryAmount) + deepStrictEqual(expected, res) + }) }) }) diff --git a/test/utils/connect-nodes-via-relay.js b/test/utils/connect-nodes-via-relay.js new file mode 100644 index 0000000..95d5e65 --- /dev/null +++ b/test/utils/connect-nodes-via-relay.js @@ -0,0 +1,35 @@ +import { multiaddr } from '@multiformats/multiaddr' +import { WebRTC } from '@multiformats/multiaddr-matcher' +import { peerIdFromString } from '@libp2p/peer-id' +import waitFor from './wait-for.js' + +const defaultFilter = () => true + +const isBrowser = () => typeof window !== 'undefined' + +const connectIpfsNodes = async (ipfs, peerAddress, options = { + filter: defaultFilter +}) => { + if (isBrowser()) { + const relayId = '12D3KooWAJjbRkp8FPF5MKgMU53aUTxWkqvDrs4zc1VMbwRwfsbE' + + await ipfs.libp2p.dial(multiaddr(`/ip4/127.0.0.1/tcp/12345/ws/p2p/${relayId}`)) + + let address1 + + await waitFor(() => { + address1 = ipfs.libp2p.getMultiaddrs().filter(ma => WebRTC.matches(ma)).pop() + return address1 != null + }, () => true) + + await ipfs.libp2p.dial(peerAddress) + } else { + if (peerAddress) { + const peerId = peerIdFromString(peerAddress.getPeerId()) + await ipfs.libp2p.peerStore.save(peerId, { multiaddrs: [peerAddress] }) + await ipfs.libp2p.dial(peerAddress) + } + } +} + +export default connectIpfsNodes diff --git a/test/utils/connect-nodes.js b/test/utils/connect-nodes.js index 03792be..c216558 100644 --- a/test/utils/connect-nodes.js +++ b/test/utils/connect-nodes.js @@ -3,7 +3,7 @@ import { peerIdFromString } from '@libp2p/peer-id' const connectIpfsNodes = async (ipfs, peerAddress) => { const peerId = peerIdFromString(peerAddress.getPeerId()) await ipfs.libp2p.peerStore.save(peerId, { multiaddrs: [peerAddress] }) - await ipfs.libp2p.dial(peerId) + await ipfs.libp2p.dial(peerAddress) } export default connectIpfsNodes diff --git a/test/utils/launch-lander.js b/test/utils/launch-lander.js index efbf34a..471bf20 100644 --- a/test/utils/launch-lander.js +++ b/test/utils/launch-lander.js @@ -1,38 +1,12 @@ import { createHelia } from 'helia' import { createLibp2p } from 'libp2p' import { bitswap } from '@helia/block-brokers' -import { identify } from '@libp2p/identify' -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { webSockets } from '@libp2p/websockets' -import { gossipsub } from '@chainsafe/libp2p-gossipsub' import { createOrbitDB } from '@orbitdb/core' import Lander from '../../src/lib/lander.js' -import connectPeers from './connect-nodes.js' -import { all } from '@libp2p/websockets/filters' +// import connectPeers from './connect-nodes.js' +import connect from './connect-nodes-via-relay.js' -const options = { - transports: [ - webSockets({ - filter: all // connect to insecure sockets also (E.g. /ws/) - }) - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux() - ], - connectionGater: { - denyDialMultiaddr: () => false // allow dialling of private addresses. - }, - services: { - identify: identify(), - pubsub: gossipsub({ - emitSelf: true - }) - } -} +import Libp2pOptions from './test-config/lander-libp2p-config.js' const heliaOptions = { blockBrokers: [ @@ -43,6 +17,8 @@ const heliaOptions = { } export const launchLander = async ({ directory, orbiterAddress } = {}) => { + const options = Libp2pOptions + const libp2p = await createLibp2p({ ...options }) const ipfs = await createHelia({ libp2p, ...heliaOptions }) @@ -50,7 +26,8 @@ export const launchLander = async ({ directory, orbiterAddress } = {}) => { const orbitdb = await createOrbitDB({ ipfs, directory }) - await connectPeers(ipfs, orbiterAddress) + // await connectPeers(ipfs, orbiterAddress) + await connect(ipfs, orbiterAddress) const lander = await Lander({ orbitdb, orbiterAddressOrId: orbiterAddress }) diff --git a/test/utils/launch-orbiter.js b/test/utils/launch-orbiter.js index c369070..9e698b9 100644 --- a/test/utils/launch-orbiter.js +++ b/test/utils/launch-orbiter.js @@ -3,39 +3,30 @@ import { createHelia } from 'helia' import { LevelBlockstore } from 'blockstore-level' import { LevelDatastore } from 'datastore-level' import { createLibp2p } from 'libp2p' -import { identify } from '@libp2p/identify' -import { noise } from '@chainsafe/libp2p-noise' -import { yamux } from '@chainsafe/libp2p-yamux' -import { webSockets } from '@libp2p/websockets' -import { gossipsub } from '@chainsafe/libp2p-gossipsub' +import { bitswap } from '@helia/block-brokers' +import { multiaddr } from '@multiformats/multiaddr' import { createOrbitDB } from '@orbitdb/core' import Orbiter from '../../src/lib/orbiter.js' import { orbiter as orbiterId } from '../../src/utils/id.js' -const options = { - addresses: { - listen: [ - '/ip4/0.0.0.0/tcp/0/ws' - ] - }, - transports: [ - webSockets() - ], - connectionEncryption: [ - noise() - ], - streamMuxers: [ - yamux() +import Libp2pOptions from './test-config/orbiter-libp2p-config.js' + +const isBrowser = () => typeof window !== 'undefined' + +const relayId = '12D3KooWAJjbRkp8FPF5MKgMU53aUTxWkqvDrs4zc1VMbwRwfsbE' +const relayAddress = multiaddr(`/ip4/127.0.0.1/tcp/12345/ws/p2p/${relayId}`) + +const heliaOptions = { + blockBrokers: [ + bitswap() ], - services: { - identify: identify(), - pubsub: gossipsub({ - emitSelf: true - }) - } + routers: [ + ] } export const launchOrbiter = async ({ directory } = {}) => { + const options = Libp2pOptions + directory = directory || './orbiter' const id = orbiterId @@ -44,10 +35,14 @@ export const launchOrbiter = async ({ directory } = {}) => { const datastore = new LevelDatastore(join(directory, '/', 'ipfs', '/', 'data')) const libp2p = await createLibp2p({ ...options }) - const ipfs = await createHelia({ libp2p, datastore, blockstore }) + const ipfs = await createHelia({ libp2p, ...heliaOptions, datastore, blockstore }) const orbitdb = await createOrbitDB({ ipfs, directory, id }) const orbiter = await Orbiter({ orbitdb }) + if (isBrowser()) { + await ipfs.libp2p.dial(relayAddress) + } + // Helper function for tests orbiter.shutdown = async () => { await orbiter.stop() diff --git a/test/utils/relay.js b/test/utils/relay.js new file mode 100644 index 0000000..5ae1213 --- /dev/null +++ b/test/utils/relay.js @@ -0,0 +1,56 @@ +import { yamux } from '@chainsafe/libp2p-yamux' +import { createLibp2p } from 'libp2p' +import { noise } from '@chainsafe/libp2p-noise' +import { circuitRelayServer } from '@libp2p/circuit-relay-v2' +import { webSockets } from '@libp2p/websockets' +import * as filters from '@libp2p/websockets/filters' +import { identify } from '@libp2p/identify' +import { createFromPrivKey } from '@libp2p/peer-id-factory' +import { unmarshalPrivateKey } from '@libp2p/crypto/keys' +import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' + +// output of: console.log(server.peerId.privateKey.toString('hex')) +const relayPrivKey = '08011240821cb6bc3d4547fcccb513e82e4d718089f8a166b23ffcd4a436754b6b0774cf07447d1693cd10ce11ef950d7517bad6e9472b41a927cd17fc3fb23f8c70cd99' +// the peer id of the above key +// const relayId = '12D3KooWAJjbRkp8FPF5MKgMU53aUTxWkqvDrs4zc1VMbwRwfsbE' + +const encoded = uint8ArrayFromString(relayPrivKey, 'hex') +const privateKey = await unmarshalPrivateKey(encoded) +const peerId = await createFromPrivKey(privateKey) + +const server = await createLibp2p({ + peerId, + addresses: { + listen: ['/ip4/0.0.0.0/tcp/12345/ws'] + }, + transports: [ + webSockets({ + filter: filters.all + }) + ], + connectionEncryption: [noise()], + streamMuxers: [yamux()], + services: { + identify: identify(), + relay: circuitRelayServer({ + reservations: { + maxReservations: 5000, + reservationTtl: 1000, + defaultDataLimit: BigInt(1024 * 1024 * 1024) + } + }) + } +}) + +server.addEventListener('peer:connect', async event => { + console.log('peer:connect', event.detail) +}) + +server.addEventListener('peer:disconnect', async event => { + console.log('peer:disconnect', event.detail) + server.peerStore.delete(event.detail) +}) + +console.log(server.peerId.toString()) +console.log('p2p addr: ', server.getMultiaddrs().map((ma) => ma.toString())) +// generates a deterministic address: /ip4/127.0.0.1/tcp/33519/ws/p2p/12D3KooWAJjbRkp8FPF5MKgMU53aUTxWkqvDrs4zc1VMbwRwfsbE diff --git a/test/utils/test-config-browser/lander-libp2p-config.js b/test/utils/test-config-browser/lander-libp2p-config.js new file mode 100644 index 0000000..4daafd9 --- /dev/null +++ b/test/utils/test-config-browser/lander-libp2p-config.js @@ -0,0 +1,42 @@ +import { identify } from '@libp2p/identify' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { webSockets } from '@libp2p/websockets' +import { gossipsub } from '@chainsafe/libp2p-gossipsub' +import { all } from '@libp2p/websockets/filters' +import { webRTC } from '@libp2p/webrtc' +import { circuitRelayTransport } from '@libp2p/circuit-relay-v2' + +const Libp2pBrowserOptions = { + addresses: { + listen: [ + '/webrtc' + ] + }, + transports: [ + webSockets({ + filter: all // connect to insecure sockets also (E.g. /ws/) + }), + webRTC(), + circuitRelayTransport({ + discoverRelays: 1 + }) + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + yamux() + ], + connectionGater: { + denyDialMultiaddr: () => false // allow dialling of private addresses. + }, + services: { + identify: identify(), + pubsub: gossipsub({ + emitSelf: true + }) + } +} + +export default Libp2pBrowserOptions diff --git a/test/utils/test-config-browser/orbiter-libp2p-config.js b/test/utils/test-config-browser/orbiter-libp2p-config.js new file mode 100644 index 0000000..4daafd9 --- /dev/null +++ b/test/utils/test-config-browser/orbiter-libp2p-config.js @@ -0,0 +1,42 @@ +import { identify } from '@libp2p/identify' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { webSockets } from '@libp2p/websockets' +import { gossipsub } from '@chainsafe/libp2p-gossipsub' +import { all } from '@libp2p/websockets/filters' +import { webRTC } from '@libp2p/webrtc' +import { circuitRelayTransport } from '@libp2p/circuit-relay-v2' + +const Libp2pBrowserOptions = { + addresses: { + listen: [ + '/webrtc' + ] + }, + transports: [ + webSockets({ + filter: all // connect to insecure sockets also (E.g. /ws/) + }), + webRTC(), + circuitRelayTransport({ + discoverRelays: 1 + }) + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + yamux() + ], + connectionGater: { + denyDialMultiaddr: () => false // allow dialling of private addresses. + }, + services: { + identify: identify(), + pubsub: gossipsub({ + emitSelf: true + }) + } +} + +export default Libp2pBrowserOptions diff --git a/test/utils/test-config/lander-libp2p-config.js b/test/utils/test-config/lander-libp2p-config.js new file mode 100644 index 0000000..22db245 --- /dev/null +++ b/test/utils/test-config/lander-libp2p-config.js @@ -0,0 +1,40 @@ +import { identify } from '@libp2p/identify' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { webSockets } from '@libp2p/websockets' +import { gossipsub } from '@chainsafe/libp2p-gossipsub' +import { tcp } from '@libp2p/tcp' +import { mdns } from '@libp2p/mdns' + +const Libp2pOptions = { + addresses: { + listen: [ + '/ip4/0.0.0.0/tcp/0', + '/ip4/0.0.0.0/tcp/0/ws' + ] + }, + transports: [ + tcp(), + webSockets() + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + yamux() + ], + connectionGater: { + denyDialMultiaddr: () => false // allow dialling of private addresses. + }, + peerDiscovery: [ + mdns() + ], + services: { + identify: identify(), + pubsub: gossipsub({ + emitSelf: true + }) + } +} + +export default Libp2pOptions diff --git a/test/utils/test-config/orbiter-libp2p-config.js b/test/utils/test-config/orbiter-libp2p-config.js new file mode 100644 index 0000000..22db245 --- /dev/null +++ b/test/utils/test-config/orbiter-libp2p-config.js @@ -0,0 +1,40 @@ +import { identify } from '@libp2p/identify' +import { noise } from '@chainsafe/libp2p-noise' +import { yamux } from '@chainsafe/libp2p-yamux' +import { webSockets } from '@libp2p/websockets' +import { gossipsub } from '@chainsafe/libp2p-gossipsub' +import { tcp } from '@libp2p/tcp' +import { mdns } from '@libp2p/mdns' + +const Libp2pOptions = { + addresses: { + listen: [ + '/ip4/0.0.0.0/tcp/0', + '/ip4/0.0.0.0/tcp/0/ws' + ] + }, + transports: [ + tcp(), + webSockets() + ], + connectionEncryption: [ + noise() + ], + streamMuxers: [ + yamux() + ], + connectionGater: { + denyDialMultiaddr: () => false // allow dialling of private addresses. + }, + peerDiscovery: [ + mdns() + ], + services: { + identify: identify(), + pubsub: gossipsub({ + emitSelf: true + }) + } +} + +export default Libp2pOptions