chore: config types and dependencies update (#904)

BREAKING CHANGES:

top level types were updated, multiaddr@9.0.0 is used, dialer and keychain internal property names changed and connectionManager minPeers is not supported anymore
This commit is contained in:
Vasco Santos
2021-04-15 09:40:02 +02:00
committed by GitHub
parent 8e1743cac4
commit 8506414ea1
114 changed files with 4600 additions and 828 deletions

View File

@ -1,5 +1,6 @@
'use strict'
const path = require('path')
const Libp2p = require('./src')
const { MULTIADDRS_WEBSOCKETS } = require('./test/fixtures/browser')
const Peers = require('./test/fixtures/peers')
@ -47,16 +48,23 @@ const after = async () => {
await libp2p.stop()
}
/** @type {import('aegir').Options["build"]["config"]} */
const esbuild = {
inject: [path.join(__dirname, './scripts/node-globals.js')]
}
/** @type {import('aegir').PartialOptions} */
module.exports = {
bundlesize: { maxSize: '223kB' },
hooks: {
pre: before,
post: after
build: {
bundlesizeMax: '253kB'
},
webpack: {
node: {
// needed by bcrypto
Buffer: true
test: {
before,
after,
browser: {
config: {
buildConfig: esbuild
}
}
}
}

102
.github/workflows/examples.yml vendored Normal file
View File

@ -0,0 +1,102 @@
name: examples
on:
push:
branches:
- master
pull_request:
branches:
- '**'
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npx aegir lint
- run: npx aegir ts -p check
- run: npx aegir build
test-auto-relay-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- auto-relay
test-chat-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- chat
test-connection-encryption-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- connection-encryption
test-discovery-mechanisms-example:
needs: check
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- discovery-mechanisms
test-echo-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- echo
test-libp2p-in-the-browser-example:
needs: check
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- libp2p-in-the-browser
test-peer-and-content-routing-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- peer-and-content-routing
test-pnet-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- pnet
test-protocol-and-stream-muxing-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- protocol-and-stream-muxing
test-pubsub-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- pubsub
test-transports-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- transports
test-webrtc-direct-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: cd examples && yarn && npm run test -- webrtc-direct

View File

@ -12,11 +12,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: yarn lint
- run: npm install
- run: npx aegir lint
- uses: gozala/typescript-error-reporter-action@v1.0.8
- run: yarn build
- run: yarn aegir dep-check
- run: npx aegir build
- run: npx aegir dep-check
- uses: ipfs/aegir/actions/bundle-size@master
name: size
with:
@ -34,111 +34,34 @@ jobs:
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- run: yarn
- run: npx nyc --reporter=lcov aegir test -t node -- --bail
- run: npm install
- run: npx aegir test -t node --cov --bail
- uses: codecov/codecov-action@v1
test-chrome:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: npm install
- run: npx aegir test -t browser -t webworker --bail
test-firefox:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: npx aegir test -t browser -t webworker --bail -- --browsers FirefoxHeadless
- run: npm install
- run: npx aegir test -t browser -t webworker --bail -- --browser firefox
test-ts:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm install
- run: npm run test:ts
test-interop:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: npm install
- run: cd node_modules/interop-libp2p && yarn && LIBP2P_JS=${GITHUB_WORKSPACE}/src/index.js npx aegir test -t node --bail
test-auto-relay-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- auto-relay
test-chat-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- chat
test-connection-encryption-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- connection-encryption
test-discovery-mechanisms-example:
needs: check
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- discovery-mechanisms
test-echo-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- echo
test-libp2p-in-the-browser-example:
needs: check
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- libp2p-in-the-browser
test-peer-and-content-routing-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- peer-and-content-routing
test-pnet-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- pnet
test-protocol-and-stream-muxing-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- protocol-and-stream-muxing
test-pubsub-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- pubsub
test-transports-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- transports
test-webrtc-direct-example:
needs: check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: yarn
- run: cd examples && yarn && npm run test -- webrtc-direct

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ docs
test/repo-tests*
**/bundle.js
.cache
.parcel-cache
# Logs
logs

View File

@ -599,7 +599,7 @@ const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const { FaultTolerance } = require('libp2p/src/transport-manager')}
const { FaultTolerance } = require('libp2p/src/transport-manager')
const node = await Libp2p.create({
modules: {

View File

@ -2,7 +2,7 @@
"name": "libp2p-in-browser",
"version": "1.0.0",
"description": "A libp2p node running in the browser",
"main": "index.js",
"main": "dist/index.html",
"browserslist": [
"last 2 Chrome versions"
],
@ -20,8 +20,8 @@
"libp2p-bootstrap": "^0.12.1",
"libp2p-mplex": "^0.10.0",
"libp2p-noise": "^2.0.0",
"libp2p-webrtc-star": "^0.20.0",
"libp2p-websockets": "^0.14.0"
"libp2p-webrtc-star": "^0.22.0",
"libp2p-websockets": "^0.15.0"
},
"devDependencies": {
"@babel/cli": "^7.13.10",
@ -29,6 +29,6 @@
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-polyfill": "^6.26.0",
"parcel-bundler": "1.12.3"
"parcel": "next"
}
}

View File

@ -17,10 +17,10 @@ async function run() {
const out = chunk.toString()
if (out.includes('Server running at')) {
url = out.replace('Server running at ', '')
url = out.split('Server running at ')[1]
}
if (out.includes('Built in ')) {
if (out.includes('Built in')) {
try {
const browser = await chromium.launch();
const page = await browser.newPage();

View File

@ -3,6 +3,7 @@
"version": "0.0.1",
"private": true,
"description": "",
"main": "dist/index.html",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "parcel build index.html",
@ -15,14 +16,15 @@
"babel-plugin-syntax-async-functions": "^6.13.0",
"babel-plugin-transform-regenerator": "^6.26.0",
"babel-polyfill": "^6.26.0",
"parcel-bundler": "1.12.3"
"parcel-bundler": "1.12.3",
"util": "^0.12.3"
},
"dependencies": {
"libp2p": "../../",
"libp2p-bootstrap": "^0.12.1",
"libp2p-mplex": "^0.10.1",
"libp2p-noise": "^2.0.1",
"libp2p-webrtc-direct": "^0.5.0",
"libp2p-webrtc-direct": "^0.6.0",
"peer-id": "^0.14.3"
},
"browser": {

View File

@ -50,10 +50,12 @@ async function test () {
const out = chunk.toString()
if (out.includes('Server running at')) {
dialerUrl = out.replace('Server running at ', '')
dialerUrl = out.split('Server running at ')[1]
}
if (out.includes('✨ Built in ')) {
if (out.includes('Built in ')) {
try {
const browser = await chromium.launch();
const page = await browser.newPage();

View File

@ -20,10 +20,28 @@
"scripts": {
"lint": "aegir lint",
"build": "aegir build",
"test": "npm run test:node && npm run test:browser",
"build:proto": "npm run build:proto:circuit && npm run build:proto:identify && npm run build:proto:plaintext && npm run build:proto:address-book && npm run build:proto:proto-book && npm run build:proto:peer-record && npm run build:proto:envelope",
"build:proto:circuit": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/circuit/protocol/index.js ./src/circuit/protocol/index.proto",
"build:proto:identify": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/identify/message.js ./src/identify/message.proto",
"build:proto:plaintext": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/insecure/proto.js ./src/insecure/proto.proto",
"build:proto:address-book": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/peer-store/persistent/pb/address-book.js ./src/peer-store/persistent/pb/address-book.proto",
"build:proto:proto-book": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/peer-store/persistent/pb/proto-book.js ./src/peer-store/persistent/pb/proto-book.proto",
"build:proto:peer-record": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/record/peer-record/peer-record.js ./src/record/peer-record/peer-record.proto",
"build:proto:envelope": "pbjs -t static-module -w commonjs --force-number --no-verify --no-delimited --no-create --no-beautify --no-defaults --lint eslint-disable -o src/record/envelope/envelope.js ./src/record/envelope/envelope.proto",
"build:proto-types": "npm run build:proto-types:circuit && npm run build:proto-types:identify && npm run build:proto-types:plaintext && npm run build:proto-types:address-book && npm run build:proto-types:proto-book && npm run build:proto-types:peer-record && npm run build:proto-types:envelope",
"build:proto-types:circuit": "pbts -o src/circuit/protocol/index.d.ts src/circuit/protocol/index.js",
"build:proto-types:identify": "pbts -o src/identify/message.d.ts src/identify/message.js",
"build:proto-types:plaintext": "pbts -o src/insecure/proto.d.ts src/insecure/proto.js",
"build:proto-types:address-book": "pbts -o src/peer-store/persistent/pb/address-book.d.ts src/peer-store/persistent/pb/address-book.js",
"build:proto-types:proto-book": "pbts -o src/peer-store/persistent/pb/proto-book.d.ts src/peer-store/persistent/pb/proto-book.js",
"build:proto-types:peer-record": "pbts -o src/record/peer-record/peer-record.d.ts src/record/peer-record/peer-record.js",
"build:proto-types:envelope": "pbts -o src/record/envelope/envelope.d.ts src/record/envelope/envelope.js",
"test": "aegir test",
"test:ts": "aegir build --no-bundle && npm run test --prefix test/ts-use",
"test:node": "aegir test -t node -f \"./test/**/*.{node,spec}.js\"",
"test:browser": "aegir test -t browser",
"test:examples": "cd examples && npm run test:all",
"prepare": "aegir build --no-bundle",
"release": "aegir release -t node -t browser",
"release-minor": "aegir release --type minor -t node -t browser",
"release-major": "aegir release --type major -t node -t browser",
@ -47,12 +65,18 @@
"homepage": "https://libp2p.io",
"license": "MIT",
"engines": {
"node": ">=12.0.0",
"npm": ">=6.0.0"
"node": ">=14.0.0"
},
"browser": {
"@motrix/nat-api": false
},
"eslintConfig": {
"extends": "ipfs",
"ignorePatterns": [
"!.aegir.js",
"test/ts-use"
]
},
"dependencies": {
"@motrix/nat-api": "^0.3.1",
"abort-controller": "^3.0.0",
@ -62,9 +86,9 @@
"cids": "^1.1.5",
"class-is": "^1.1.0",
"debug": "^4.3.1",
"err-code": "^2.0.0",
"err-code": "^3.0.0",
"es6-promisify": "^6.1.1",
"events": "^3.2.0",
"events": "^3.3.0",
"hashlru": "^2.3.0",
"interface-datastore": "^3.0.3",
"ipfs-utils": "^6.0.0",
@ -73,76 +97,78 @@
"it-drain": "^1.0.3",
"it-filter": "^1.0.1",
"it-first": "^1.0.4",
"it-handshake": "^1.0.2",
"it-length-prefixed": "^3.1.0",
"it-handshake": "^2.0.0",
"it-length-prefixed": "^5.0.2",
"it-map": "^1.0.4",
"it-merge": "1.0.0",
"it-pipe": "^1.1.0",
"it-protocol-buffers": "^0.2.0",
"it-take": "1.0.0",
"libp2p-crypto": "^0.19.0",
"libp2p-interfaces": "^0.8.1",
"libp2p-utils": "^0.2.2",
"mafmt": "^8.0.0",
"libp2p-interfaces": "^0.10.0",
"libp2p-utils": "^0.3.1",
"mafmt": "^9.0.0",
"merge-options": "^3.0.4",
"moving-average": "^1.0.0",
"multiaddr": "^8.1.0",
"multicodec": "^2.1.0",
"multihashing-async": "^2.0.1",
"multistream-select": "^1.0.0",
"multiaddr": "^9.0.1",
"multicodec": "^3.0.1",
"multihashing-async": "^2.1.2",
"multistream-select": "^2.0.0",
"mutable-proxy": "^1.0.0",
"node-forge": "^0.10.0",
"p-any": "^3.0.0",
"p-fifo": "^1.0.0",
"p-retry": "^4.2.0",
"p-settle": "^4.0.1",
"p-retry": "^4.4.0",
"p-settle": "^4.1.1",
"peer-id": "^0.14.2",
"private-ip": "^2.0.0",
"protons": "^2.0.0",
"retimer": "^2.0.0",
"private-ip": "^2.1.0",
"protobufjs": "^6.10.2",
"retimer": "^3.0.0",
"sanitize-filename": "^1.6.3",
"set-delayed-interval": "^1.0.0",
"streaming-iterables": "^5.0.2",
"timeout-abort-controller": "^1.1.1",
"varint": "^6.0.0",
"xsalsa20": "^1.0.2"
"xsalsa20": "^1.1.0"
},
"devDependencies": {
"@nodeutils/defaults-deep": "^1.1.0",
"@types/es6-promisify": "^6.0.0",
"@types/node-forge": "^0.9.7",
"@types/varint": "^6.0.0",
"abortable-iterator": "^3.0.0",
"aegir": "^29.2.0",
"aegir": "^33.0.0",
"buffer": "^6.0.3",
"chai-bytes": "^0.1.2",
"chai-string": "^1.5.0",
"delay": "^4.4.0",
"delay": "^5.0.0",
"interop-libp2p": "^0.3.0",
"into-stream": "^6.0.0",
"ipfs-http-client": "^48.2.2",
"ipfs-http-client": "^49.0.4",
"it-concat": "^1.0.0",
"it-pair": "^1.0.0",
"it-pushable": "^1.4.0",
"libp2p": ".",
"libp2p-bootstrap": "^0.12.0",
"libp2p-delegated-content-routing": "^0.9.0",
"libp2p-delegated-peer-routing": "^0.8.0",
"libp2p-floodsub": "^0.24.0",
"libp2p-bootstrap": "^0.12.3",
"libp2p-delegated-content-routing": "^0.10.0",
"libp2p-delegated-peer-routing": "^0.9.0",
"libp2p-floodsub": "^0.25.0",
"libp2p-gossipsub": "^0.8.0",
"libp2p-kad-dht": "^0.20.5",
"libp2p-mdns": "^0.15.0",
"libp2p-kad-dht": "^0.21.0",
"libp2p-mdns": "^0.16.0",
"libp2p-mplex": "^0.10.1",
"libp2p-noise": "^2.0.0",
"libp2p-secio": "^0.13.1",
"libp2p-tcp": "^0.15.1",
"libp2p-webrtc-star": "^0.20.0",
"libp2p-webrtc-star": "^0.22.0",
"libp2p-websockets": "^0.15.0",
"multihashes": "^3.0.1",
"multihashes": "^4.0.2",
"nock": "^13.0.3",
"p-defer": "^3.0.0",
"p-times": "^3.0.0",
"p-wait-for": "^3.2.0",
"rimraf": "^3.0.2",
"sinon": "^9.2.4",
"uint8arrays": "^2.0.5"
"sinon": "^10.0.0",
"uint8arrays": "^2.1.3",
"util": "^0.12.3"
},
"contributors": [
"David Dias <daviddias.p@gmail.com>",

2
scripts/node-globals.js Normal file
View File

@ -0,0 +1,2 @@
// @ts-nocheck
export const { Buffer } = require('buffer')

View File

@ -1,15 +1,9 @@
'use strict'
/** @typedef {import('../types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
/**
* @typedef {import('multiaddr')} Multiaddr
*/
/**
* @typedef {Object} AddressManagerOptions
* @property {string[]} [listen = []] - list of multiaddrs string representation to listen.
@ -47,7 +41,7 @@ class AddressManager extends EventEmitter {
* @returns {Multiaddr[]}
*/
getListenAddrs () {
return Array.from(this.listen).map((a) => multiaddr(a))
return Array.from(this.listen).map((a) => new Multiaddr(a))
}
/**
@ -56,7 +50,7 @@ class AddressManager extends EventEmitter {
* @returns {Multiaddr[]}
*/
getAnnounceAddrs () {
return Array.from(this.announce).map((a) => multiaddr(a))
return Array.from(this.announce).map((a) => new Multiaddr(a))
}
/**
@ -65,7 +59,7 @@ class AddressManager extends EventEmitter {
* @returns {Array<Multiaddr>}
*/
getObservedAddrs () {
return Array.from(this.observed).map((a) => multiaddr(a))
return Array.from(this.observed).map((a) => new Multiaddr(a))
}
/**
@ -74,7 +68,7 @@ class AddressManager extends EventEmitter {
* @param {string | Multiaddr} addr
*/
addObservedAddr (addr) {
let ma = multiaddr(addr)
let ma = new Multiaddr(addr)
const remotePeer = ma.getPeerId()
// strip our peer id if it has been passed
@ -83,7 +77,7 @@ class AddressManager extends EventEmitter {
// use same encoding for comparison
if (remotePeerId.equals(this.peerId)) {
ma = ma.decapsulate(multiaddr(`/p2p/${this.peerId}`))
ma = ma.decapsulate(new Multiaddr(`/p2p/${this.peerId}`))
}
}

View File

@ -37,7 +37,7 @@ Libp2p circuit configuration can be seen at [Setup with Relay](../../doc/CONFIGU
Once you have a circuit relay node running, you can configure other nodes to use it as a relay as follows:
```js
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
@ -47,7 +47,7 @@ const relayAddr = ...
const node = await Libp2p.create({
addresses: {
listen: [multiaddr(`${relayAddr}/p2p-circuit`)]
listen: [new Multiaddr(`${relayAddr}/p2p-circuit`)]
},
modules: {
transport: [TCP],

View File

@ -7,7 +7,7 @@ const log = Object.assign(debug('libp2p:auto-relay'), {
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const { relay: multicodec } = require('./multicodec')
@ -157,7 +157,7 @@ class AutoRelay {
// Attempt to listen on relay
try {
await this._transportManager.listen([multiaddr(listenAddr)])
await this._transportManager.listen([new Multiaddr(listenAddr)])
// Announce multiaddrs will update on listen success by TransportManager event being triggered
} catch (err) {
log.error(err)

View File

@ -18,17 +18,17 @@ const { stop } = require('./stop')
const multicodec = require('./../multicodec')
/**
* @typedef {import('../../types').CircuitRequest} CircuitRequest
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
* @typedef {import('../transport')} Transport
*/
/**
* @typedef {Object} HopRequest
* @property {Connection} connection
* @property {CircuitRequest} request
* @property {StreamHandlerT} streamHandler
* @property {ICircuitRelay} request
* @property {StreamHandler} streamHandler
* @property {Transport} circuit
*/
@ -58,6 +58,11 @@ async function handleHop ({
return log.error('invalid hop request via peer %s', connection.remotePeer.toB58String(), err)
}
if (!request.dstPeer) {
log('HOP request received but we do not receive a dstPeer')
return
}
// Get the connection to the destination (stop) peer
const destinationPeer = new PeerId(request.dstPeer.id)
@ -113,8 +118,8 @@ async function handleHop ({
*
* @param {object} options
* @param {Connection} options.connection - Connection to the relay
* @param {CircuitRequest} options.request
* @returns {Promise<Connection>}
* @param {ICircuitRelay} options.request
* @returns {Promise<MuxedStream>}
*/
async function hop ({
connection,
@ -128,6 +133,10 @@ async function hop ({
const response = await streamHandler.read()
if (!response) {
throw errCode(new Error('HOP request had no response'), Errors.ERR_HOP_REQUEST_FAILED)
}
if (response.code === CircuitPB.Status.SUCCESS) {
log('hop request was successful')
return streamHandler.rest()
@ -159,7 +168,7 @@ async function canHop ({
const response = await streamHandler.read()
await streamHandler.close()
if (response.code !== CircuitPB.Status.SUCCESS) {
if (!response || response.code !== CircuitPB.Status.SUCCESS) {
return false
}
@ -171,7 +180,7 @@ async function canHop ({
*
* @param {Object} options
* @param {Connection} options.connection
* @param {StreamHandlerT} options.streamHandler
* @param {StreamHandler} options.streamHandler
* @param {Transport} options.circuit
* @private
*/

View File

@ -13,8 +13,7 @@ const { validateAddrs } = require('./utils')
/**
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
* @typedef {import('../../types').CircuitRequest} CircuitRequest
* @typedef {import('./stream-handler')<CircuitRequest>} StreamHandlerT
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
*/
/**
@ -23,8 +22,8 @@ const { validateAddrs } = require('./utils')
* @private
* @param {Object} options
* @param {Connection} options.connection
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
* @param {StreamHandlerT} options.streamHandler
* @param {ICircuitRelay} options.request - The CircuitRelay protobuf request (unencoded)
* @param {StreamHandler} options.streamHandler
* @returns {Promise<MuxedStream>|void} Resolves a duplex iterable
*/
module.exports.handleStop = function handleStop ({
@ -54,7 +53,7 @@ module.exports.handleStop = function handleStop ({
* @private
* @param {Object} options
* @param {Connection} options.connection
* @param {CircuitRequest} options.request - The CircuitRelay protobuf request (unencoded)
* @param {ICircuitRelay} options.request - The CircuitRelay protobuf request (unencoded)
* @returns {Promise<MuxedStream|void>} Resolves a duplex iterable
*/
module.exports.stop = async function stop ({
@ -68,6 +67,10 @@ module.exports.stop = async function stop ({
streamHandler.write(request)
const response = await streamHandler.read()
if (!response) {
return streamHandler.close()
}
if (response.code === CircuitPB.Status.SUCCESS) {
log('stop request to %s was successful', connection.remotePeer.toB58String())
return streamHandler.rest()

View File

@ -6,16 +6,15 @@ const log = Object.assign(debug('libp2p:circuit:stream-handler'), {
})
const lp = require('it-length-prefixed')
// @ts-ignore it-handshake does not export types
const handshake = require('it-handshake')
const { CircuitRelay: CircuitPB } = require('../protocol')
const { CircuitRelay } = require('../protocol')
/**
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
*/
/**
* @template T
*/
class StreamHandler {
/**
* Create a stream handler for connection
@ -29,6 +28,7 @@ class StreamHandler {
this.stream = stream
this.shake = handshake(this.stream)
// @ts-ignore options are not optional
this.decoder = lp.decode.fromReader(this.shake.reader, { maxDataLength: maxLength })
}
@ -36,12 +36,11 @@ class StreamHandler {
* Read and decode message
*
* @async
* @returns {Promise<T|undefined>}
*/
async read () {
const msg = await this.decoder.next()
if (msg.value) {
const value = CircuitPB.decode(msg.value.slice())
const value = CircuitRelay.decode(msg.value.slice())
log('read message type', value.type)
return value
}
@ -54,13 +53,13 @@ class StreamHandler {
/**
* Encode and write array of buffers
*
* @param {CircuitPB} msg - An unencoded CircuitRelay protobuf message
* @param {ICircuitRelay} msg - An unencoded CircuitRelay protobuf message
* @returns {void}
*/
write (msg) {
log('write message type %s', msg.type)
// @ts-ignore lp.encode expects type type 'Buffer | BufferList', not 'Uint8Array'
this.shake.write(lp.encode.single(CircuitPB.encode(msg)))
this.shake.write(lp.encode.single(CircuitRelay.encode(msg).finish()))
}
/**
@ -73,6 +72,9 @@ class StreamHandler {
return this.shake.stream
}
/**
* @param {ICircuitRelay} msg - An unencoded CircuitRelay protobuf message
*/
end (msg) {
this.write(msg)
this.close()

View File

@ -1,18 +1,18 @@
'use strict'
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const { CircuitRelay } = require('../protocol')
/**
* @typedef {import('./stream-handler')} StreamHandler
* @typedef {import('../../types').CircuitStatus} CircuitStatus
* @typedef {import('../protocol').ICircuitRelay} ICircuitRelay
*/
/**
* Write a response
*
* @param {StreamHandler} streamHandler
* @param {CircuitStatus} status
* @param {import('../protocol').CircuitRelay.Status} status
*/
function writeResponse (streamHandler, status) {
streamHandler.write({
@ -24,14 +24,16 @@ function writeResponse (streamHandler, status) {
/**
* Validate incomming HOP/STOP message
*
* @param {*} msg - A CircuitRelay unencoded protobuf message
* @param {ICircuitRelay} msg - A CircuitRelay unencoded protobuf message
* @param {StreamHandler} streamHandler
*/
function validateAddrs (msg, streamHandler) {
try {
if (msg.dstPeer && msg.dstPeer.addrs) {
msg.dstPeer.addrs.forEach((addr) => {
return multiaddr(addr)
return new Multiaddr(addr)
})
}
} catch (err) {
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
? CircuitRelay.Status.HOP_DST_MULTIADDR_INVALID
@ -40,9 +42,11 @@ function validateAddrs (msg, streamHandler) {
}
try {
if (msg.srcPeer && msg.srcPeer.addrs) {
msg.srcPeer.addrs.forEach((addr) => {
return multiaddr(addr)
return new Multiaddr(addr)
})
}
} catch (err) {
writeResponse(streamHandler, msg.type === CircuitRelay.Type.HOP
? CircuitRelay.Status.HOP_SRC_MULTIADDR_INVALID

View File

@ -8,13 +8,12 @@ const log = Object.assign(debug('libp2p:relay'), {
const {
setDelayedInterval,
clearDelayedInterval
// @ts-ignore set-delayed-interval does not export types
} = require('set-delayed-interval')
const AutoRelay = require('./auto-relay')
const { namespaceToCid } = require('./utils')
const {
ADVERTISE_BOOT_DELAY,
ADVERTISE_TTL,
RELAY_RENDEZVOUS_NS
} = require('./constants')
@ -45,12 +44,6 @@ class Relay {
constructor (libp2p) {
this._libp2p = libp2p
this._options = {
advertise: {
bootDelay: ADVERTISE_BOOT_DELAY,
enabled: true,
ttl: ADVERTISE_TTL,
...libp2p._config.relay.advertise
},
...libp2p._config.relay
}

View File

@ -1,10 +1,9 @@
'use strict'
const { EventEmitter } = require('events')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
/**
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('libp2p-interfaces/src/transport/types').Listener} Listener
*/
@ -24,7 +23,7 @@ module.exports = (libp2p) => {
async function listen (addr) {
const addrString = String(addr).split('/p2p-circuit').find(a => a !== '')
const relayConn = await libp2p.dial(multiaddr(addrString))
const relayConn = await libp2p.dial(new Multiaddr(addrString))
const relayedAddr = relayConn.remoteAddr.encapsulate('/p2p-circuit')
listeningAddrs.set(relayConn.remotePeer.toB58String(), relayedAddr)

173
src/circuit/protocol/index.d.ts vendored Normal file
View File

@ -0,0 +1,173 @@
import * as $protobuf from "protobufjs";
/** Properties of a CircuitRelay. */
export interface ICircuitRelay {
/** CircuitRelay type */
type?: (CircuitRelay.Type|null);
/** CircuitRelay srcPeer */
srcPeer?: (CircuitRelay.IPeer|null);
/** CircuitRelay dstPeer */
dstPeer?: (CircuitRelay.IPeer|null);
/** CircuitRelay code */
code?: (CircuitRelay.Status|null);
}
/** Represents a CircuitRelay. */
export class CircuitRelay implements ICircuitRelay {
/**
* Constructs a new CircuitRelay.
* @param [p] Properties to set
*/
constructor(p?: ICircuitRelay);
/** CircuitRelay type. */
public type: CircuitRelay.Type;
/** CircuitRelay srcPeer. */
public srcPeer?: (CircuitRelay.IPeer|null);
/** CircuitRelay dstPeer. */
public dstPeer?: (CircuitRelay.IPeer|null);
/** CircuitRelay code. */
public code: CircuitRelay.Status;
/**
* Encodes the specified CircuitRelay message. Does not implicitly {@link CircuitRelay.verify|verify} messages.
* @param m CircuitRelay message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: ICircuitRelay, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a CircuitRelay message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns CircuitRelay
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): CircuitRelay;
/**
* Creates a CircuitRelay message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns CircuitRelay
*/
public static fromObject(d: { [k: string]: any }): CircuitRelay;
/**
* Creates a plain object from a CircuitRelay message. Also converts values to other types if specified.
* @param m CircuitRelay
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: CircuitRelay, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this CircuitRelay to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
export namespace CircuitRelay {
/** Status enum. */
enum Status {
SUCCESS = 100,
HOP_SRC_ADDR_TOO_LONG = 220,
HOP_DST_ADDR_TOO_LONG = 221,
HOP_SRC_MULTIADDR_INVALID = 250,
HOP_DST_MULTIADDR_INVALID = 251,
HOP_NO_CONN_TO_DST = 260,
HOP_CANT_DIAL_DST = 261,
HOP_CANT_OPEN_DST_STREAM = 262,
HOP_CANT_SPEAK_RELAY = 270,
HOP_CANT_RELAY_TO_SELF = 280,
STOP_SRC_ADDR_TOO_LONG = 320,
STOP_DST_ADDR_TOO_LONG = 321,
STOP_SRC_MULTIADDR_INVALID = 350,
STOP_DST_MULTIADDR_INVALID = 351,
STOP_RELAY_REFUSED = 390,
MALFORMED_MESSAGE = 400
}
/** Type enum. */
enum Type {
HOP = 1,
STOP = 2,
STATUS = 3,
CAN_HOP = 4
}
/** Properties of a Peer. */
interface IPeer {
/** Peer id */
id: Uint8Array;
/** Peer addrs */
addrs?: (Uint8Array[]|null);
}
/** Represents a Peer. */
class Peer implements IPeer {
/**
* Constructs a new Peer.
* @param [p] Properties to set
*/
constructor(p?: CircuitRelay.IPeer);
/** Peer id. */
public id: Uint8Array;
/** Peer addrs. */
public addrs: Uint8Array[];
/**
* Encodes the specified Peer message. Does not implicitly {@link CircuitRelay.Peer.verify|verify} messages.
* @param m Peer message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: CircuitRelay.IPeer, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a Peer message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Peer
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): CircuitRelay.Peer;
/**
* Creates a Peer message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Peer
*/
public static fromObject(d: { [k: string]: any }): CircuitRelay.Peer;
/**
* Creates a plain object from a Peer message. Also converts values to other types if specified.
* @param m Peer
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: CircuitRelay.Peer, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Peer to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
}

View File

@ -1,46 +1,530 @@
'use strict'
const protobuf = require('protons')
/*eslint-disable*/
"use strict";
/** @type {{CircuitRelay: import('../../types').CircuitMessageProto}} */
module.exports = protobuf(`
message CircuitRelay {
var $protobuf = require("protobufjs/minimal");
enum Status {
SUCCESS = 100;
HOP_SRC_ADDR_TOO_LONG = 220;
HOP_DST_ADDR_TOO_LONG = 221;
HOP_SRC_MULTIADDR_INVALID = 250;
HOP_DST_MULTIADDR_INVALID = 251;
HOP_NO_CONN_TO_DST = 260;
HOP_CANT_DIAL_DST = 261;
HOP_CANT_OPEN_DST_STREAM = 262;
HOP_CANT_SPEAK_RELAY = 270;
HOP_CANT_RELAY_TO_SELF = 280;
STOP_SRC_ADDR_TOO_LONG = 320;
STOP_DST_ADDR_TOO_LONG = 321;
STOP_SRC_MULTIADDR_INVALID = 350;
STOP_DST_MULTIADDR_INVALID = 351;
STOP_RELAY_REFUSED = 390;
MALFORMED_MESSAGE = 400;
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.CircuitRelay = (function() {
/**
* Properties of a CircuitRelay.
* @exports ICircuitRelay
* @interface ICircuitRelay
* @property {CircuitRelay.Type|null} [type] CircuitRelay type
* @property {CircuitRelay.IPeer|null} [srcPeer] CircuitRelay srcPeer
* @property {CircuitRelay.IPeer|null} [dstPeer] CircuitRelay dstPeer
* @property {CircuitRelay.Status|null} [code] CircuitRelay code
*/
/**
* Constructs a new CircuitRelay.
* @exports CircuitRelay
* @classdesc Represents a CircuitRelay.
* @implements ICircuitRelay
* @constructor
* @param {ICircuitRelay=} [p] Properties to set
*/
function CircuitRelay(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
enum Type { // RPC identifier, either HOP, STOP or STATUS
HOP = 1;
STOP = 2;
STATUS = 3;
CAN_HOP = 4;
/**
* CircuitRelay type.
* @member {CircuitRelay.Type} type
* @memberof CircuitRelay
* @instance
*/
CircuitRelay.prototype.type = 1;
/**
* CircuitRelay srcPeer.
* @member {CircuitRelay.IPeer|null|undefined} srcPeer
* @memberof CircuitRelay
* @instance
*/
CircuitRelay.prototype.srcPeer = null;
/**
* CircuitRelay dstPeer.
* @member {CircuitRelay.IPeer|null|undefined} dstPeer
* @memberof CircuitRelay
* @instance
*/
CircuitRelay.prototype.dstPeer = null;
/**
* CircuitRelay code.
* @member {CircuitRelay.Status} code
* @memberof CircuitRelay
* @instance
*/
CircuitRelay.prototype.code = 100;
/**
* Encodes the specified CircuitRelay message. Does not implicitly {@link CircuitRelay.verify|verify} messages.
* @function encode
* @memberof CircuitRelay
* @static
* @param {ICircuitRelay} m CircuitRelay message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
CircuitRelay.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.type != null && Object.hasOwnProperty.call(m, "type"))
w.uint32(8).int32(m.type);
if (m.srcPeer != null && Object.hasOwnProperty.call(m, "srcPeer"))
$root.CircuitRelay.Peer.encode(m.srcPeer, w.uint32(18).fork()).ldelim();
if (m.dstPeer != null && Object.hasOwnProperty.call(m, "dstPeer"))
$root.CircuitRelay.Peer.encode(m.dstPeer, w.uint32(26).fork()).ldelim();
if (m.code != null && Object.hasOwnProperty.call(m, "code"))
w.uint32(32).int32(m.code);
return w;
};
/**
* Decodes a CircuitRelay message from the specified reader or buffer.
* @function decode
* @memberof CircuitRelay
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {CircuitRelay} CircuitRelay
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
CircuitRelay.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.CircuitRelay();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.type = r.int32();
break;
case 2:
m.srcPeer = $root.CircuitRelay.Peer.decode(r, r.uint32());
break;
case 3:
m.dstPeer = $root.CircuitRelay.Peer.decode(r, r.uint32());
break;
case 4:
m.code = r.int32();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates a CircuitRelay message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof CircuitRelay
* @static
* @param {Object.<string,*>} d Plain object
* @returns {CircuitRelay} CircuitRelay
*/
CircuitRelay.fromObject = function fromObject(d) {
if (d instanceof $root.CircuitRelay)
return d;
var m = new $root.CircuitRelay();
switch (d.type) {
case "HOP":
case 1:
m.type = 1;
break;
case "STOP":
case 2:
m.type = 2;
break;
case "STATUS":
case 3:
m.type = 3;
break;
case "CAN_HOP":
case 4:
m.type = 4;
break;
}
if (d.srcPeer != null) {
if (typeof d.srcPeer !== "object")
throw TypeError(".CircuitRelay.srcPeer: object expected");
m.srcPeer = $root.CircuitRelay.Peer.fromObject(d.srcPeer);
}
if (d.dstPeer != null) {
if (typeof d.dstPeer !== "object")
throw TypeError(".CircuitRelay.dstPeer: object expected");
m.dstPeer = $root.CircuitRelay.Peer.fromObject(d.dstPeer);
}
switch (d.code) {
case "SUCCESS":
case 100:
m.code = 100;
break;
case "HOP_SRC_ADDR_TOO_LONG":
case 220:
m.code = 220;
break;
case "HOP_DST_ADDR_TOO_LONG":
case 221:
m.code = 221;
break;
case "HOP_SRC_MULTIADDR_INVALID":
case 250:
m.code = 250;
break;
case "HOP_DST_MULTIADDR_INVALID":
case 251:
m.code = 251;
break;
case "HOP_NO_CONN_TO_DST":
case 260:
m.code = 260;
break;
case "HOP_CANT_DIAL_DST":
case 261:
m.code = 261;
break;
case "HOP_CANT_OPEN_DST_STREAM":
case 262:
m.code = 262;
break;
case "HOP_CANT_SPEAK_RELAY":
case 270:
m.code = 270;
break;
case "HOP_CANT_RELAY_TO_SELF":
case 280:
m.code = 280;
break;
case "STOP_SRC_ADDR_TOO_LONG":
case 320:
m.code = 320;
break;
case "STOP_DST_ADDR_TOO_LONG":
case 321:
m.code = 321;
break;
case "STOP_SRC_MULTIADDR_INVALID":
case 350:
m.code = 350;
break;
case "STOP_DST_MULTIADDR_INVALID":
case 351:
m.code = 351;
break;
case "STOP_RELAY_REFUSED":
case 390:
m.code = 390;
break;
case "MALFORMED_MESSAGE":
case 400:
m.code = 400;
break;
}
return m;
};
/**
* Creates a plain object from a CircuitRelay message. Also converts values to other types if specified.
* @function toObject
* @memberof CircuitRelay
* @static
* @param {CircuitRelay} m CircuitRelay
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
CircuitRelay.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
d.type = o.enums === String ? "HOP" : 1;
d.srcPeer = null;
d.dstPeer = null;
d.code = o.enums === String ? "SUCCESS" : 100;
}
if (m.type != null && m.hasOwnProperty("type")) {
d.type = o.enums === String ? $root.CircuitRelay.Type[m.type] : m.type;
}
if (m.srcPeer != null && m.hasOwnProperty("srcPeer")) {
d.srcPeer = $root.CircuitRelay.Peer.toObject(m.srcPeer, o);
}
if (m.dstPeer != null && m.hasOwnProperty("dstPeer")) {
d.dstPeer = $root.CircuitRelay.Peer.toObject(m.dstPeer, o);
}
if (m.code != null && m.hasOwnProperty("code")) {
d.code = o.enums === String ? $root.CircuitRelay.Status[m.code] : m.code;
}
return d;
};
/**
* Converts this CircuitRelay to JSON.
* @function toJSON
* @memberof CircuitRelay
* @instance
* @returns {Object.<string,*>} JSON object
*/
CircuitRelay.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
/**
* Status enum.
* @name CircuitRelay.Status
* @enum {number}
* @property {number} SUCCESS=100 SUCCESS value
* @property {number} HOP_SRC_ADDR_TOO_LONG=220 HOP_SRC_ADDR_TOO_LONG value
* @property {number} HOP_DST_ADDR_TOO_LONG=221 HOP_DST_ADDR_TOO_LONG value
* @property {number} HOP_SRC_MULTIADDR_INVALID=250 HOP_SRC_MULTIADDR_INVALID value
* @property {number} HOP_DST_MULTIADDR_INVALID=251 HOP_DST_MULTIADDR_INVALID value
* @property {number} HOP_NO_CONN_TO_DST=260 HOP_NO_CONN_TO_DST value
* @property {number} HOP_CANT_DIAL_DST=261 HOP_CANT_DIAL_DST value
* @property {number} HOP_CANT_OPEN_DST_STREAM=262 HOP_CANT_OPEN_DST_STREAM value
* @property {number} HOP_CANT_SPEAK_RELAY=270 HOP_CANT_SPEAK_RELAY value
* @property {number} HOP_CANT_RELAY_TO_SELF=280 HOP_CANT_RELAY_TO_SELF value
* @property {number} STOP_SRC_ADDR_TOO_LONG=320 STOP_SRC_ADDR_TOO_LONG value
* @property {number} STOP_DST_ADDR_TOO_LONG=321 STOP_DST_ADDR_TOO_LONG value
* @property {number} STOP_SRC_MULTIADDR_INVALID=350 STOP_SRC_MULTIADDR_INVALID value
* @property {number} STOP_DST_MULTIADDR_INVALID=351 STOP_DST_MULTIADDR_INVALID value
* @property {number} STOP_RELAY_REFUSED=390 STOP_RELAY_REFUSED value
* @property {number} MALFORMED_MESSAGE=400 MALFORMED_MESSAGE value
*/
CircuitRelay.Status = (function() {
var valuesById = {}, values = Object.create(valuesById);
values[valuesById[100] = "SUCCESS"] = 100;
values[valuesById[220] = "HOP_SRC_ADDR_TOO_LONG"] = 220;
values[valuesById[221] = "HOP_DST_ADDR_TOO_LONG"] = 221;
values[valuesById[250] = "HOP_SRC_MULTIADDR_INVALID"] = 250;
values[valuesById[251] = "HOP_DST_MULTIADDR_INVALID"] = 251;
values[valuesById[260] = "HOP_NO_CONN_TO_DST"] = 260;
values[valuesById[261] = "HOP_CANT_DIAL_DST"] = 261;
values[valuesById[262] = "HOP_CANT_OPEN_DST_STREAM"] = 262;
values[valuesById[270] = "HOP_CANT_SPEAK_RELAY"] = 270;
values[valuesById[280] = "HOP_CANT_RELAY_TO_SELF"] = 280;
values[valuesById[320] = "STOP_SRC_ADDR_TOO_LONG"] = 320;
values[valuesById[321] = "STOP_DST_ADDR_TOO_LONG"] = 321;
values[valuesById[350] = "STOP_SRC_MULTIADDR_INVALID"] = 350;
values[valuesById[351] = "STOP_DST_MULTIADDR_INVALID"] = 351;
values[valuesById[390] = "STOP_RELAY_REFUSED"] = 390;
values[valuesById[400] = "MALFORMED_MESSAGE"] = 400;
return values;
})();
/**
* Type enum.
* @name CircuitRelay.Type
* @enum {number}
* @property {number} HOP=1 HOP value
* @property {number} STOP=2 STOP value
* @property {number} STATUS=3 STATUS value
* @property {number} CAN_HOP=4 CAN_HOP value
*/
CircuitRelay.Type = (function() {
var valuesById = {}, values = Object.create(valuesById);
values[valuesById[1] = "HOP"] = 1;
values[valuesById[2] = "STOP"] = 2;
values[valuesById[3] = "STATUS"] = 3;
values[valuesById[4] = "CAN_HOP"] = 4;
return values;
})();
CircuitRelay.Peer = (function() {
/**
* Properties of a Peer.
* @memberof CircuitRelay
* @interface IPeer
* @property {Uint8Array} id Peer id
* @property {Array.<Uint8Array>|null} [addrs] Peer addrs
*/
/**
* Constructs a new Peer.
* @memberof CircuitRelay
* @classdesc Represents a Peer.
* @implements IPeer
* @constructor
* @param {CircuitRelay.IPeer=} [p] Properties to set
*/
function Peer(p) {
this.addrs = [];
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
message Peer {
required bytes id = 1; // peer id
repeated bytes addrs = 2; // peer's known addresses
/**
* Peer id.
* @member {Uint8Array} id
* @memberof CircuitRelay.Peer
* @instance
*/
Peer.prototype.id = $util.newBuffer([]);
/**
* Peer addrs.
* @member {Array.<Uint8Array>} addrs
* @memberof CircuitRelay.Peer
* @instance
*/
Peer.prototype.addrs = $util.emptyArray;
/**
* Encodes the specified Peer message. Does not implicitly {@link CircuitRelay.Peer.verify|verify} messages.
* @function encode
* @memberof CircuitRelay.Peer
* @static
* @param {CircuitRelay.IPeer} m Peer message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Peer.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
w.uint32(10).bytes(m.id);
if (m.addrs != null && m.addrs.length) {
for (var i = 0; i < m.addrs.length; ++i)
w.uint32(18).bytes(m.addrs[i]);
}
return w;
};
optional Type type = 1; // Type of the message
/**
* Decodes a Peer message from the specified reader or buffer.
* @function decode
* @memberof CircuitRelay.Peer
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {CircuitRelay.Peer} Peer
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Peer.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.CircuitRelay.Peer();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.id = r.bytes();
break;
case 2:
if (!(m.addrs && m.addrs.length))
m.addrs = [];
m.addrs.push(r.bytes());
break;
default:
r.skipType(t & 7);
break;
}
}
if (!m.hasOwnProperty("id"))
throw $util.ProtocolError("missing required 'id'", { instance: m });
return m;
};
optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STATUS
optional Peer dstPeer = 3;
/**
* Creates a Peer message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof CircuitRelay.Peer
* @static
* @param {Object.<string,*>} d Plain object
* @returns {CircuitRelay.Peer} Peer
*/
Peer.fromObject = function fromObject(d) {
if (d instanceof $root.CircuitRelay.Peer)
return d;
var m = new $root.CircuitRelay.Peer();
if (d.id != null) {
if (typeof d.id === "string")
$util.base64.decode(d.id, m.id = $util.newBuffer($util.base64.length(d.id)), 0);
else if (d.id.length)
m.id = d.id;
}
if (d.addrs) {
if (!Array.isArray(d.addrs))
throw TypeError(".CircuitRelay.Peer.addrs: array expected");
m.addrs = [];
for (var i = 0; i < d.addrs.length; ++i) {
if (typeof d.addrs[i] === "string")
$util.base64.decode(d.addrs[i], m.addrs[i] = $util.newBuffer($util.base64.length(d.addrs[i])), 0);
else if (d.addrs[i].length)
m.addrs[i] = d.addrs[i];
}
}
return m;
};
optional Status code = 4; // Status code, used when Type is STATUS
}
`)
/**
* Creates a plain object from a Peer message. Also converts values to other types if specified.
* @function toObject
* @memberof CircuitRelay.Peer
* @static
* @param {CircuitRelay.Peer} m Peer
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Peer.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.arrays || o.defaults) {
d.addrs = [];
}
if (o.defaults) {
if (o.bytes === String)
d.id = "";
else {
d.id = [];
if (o.bytes !== Array)
d.id = $util.newBuffer(d.id);
}
}
if (m.id != null && m.hasOwnProperty("id")) {
d.id = o.bytes === String ? $util.base64.encode(m.id, 0, m.id.length) : o.bytes === Array ? Array.prototype.slice.call(m.id) : m.id;
}
if (m.addrs && m.addrs.length) {
d.addrs = [];
for (var j = 0; j < m.addrs.length; ++j) {
d.addrs[j] = o.bytes === String ? $util.base64.encode(m.addrs[j], 0, m.addrs[j].length) : o.bytes === Array ? Array.prototype.slice.call(m.addrs[j]) : m.addrs[j];
}
}
return d;
};
/**
* Converts this Peer to JSON.
* @function toJSON
* @memberof CircuitRelay.Peer
* @instance
* @returns {Object.<string,*>} JSON object
*/
Peer.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return Peer;
})();
return CircuitRelay;
})();
module.exports = $root;

View File

@ -0,0 +1,42 @@
syntax = "proto2";
message CircuitRelay {
enum Status {
SUCCESS = 100;
HOP_SRC_ADDR_TOO_LONG = 220;
HOP_DST_ADDR_TOO_LONG = 221;
HOP_SRC_MULTIADDR_INVALID = 250;
HOP_DST_MULTIADDR_INVALID = 251;
HOP_NO_CONN_TO_DST = 260;
HOP_CANT_DIAL_DST = 261;
HOP_CANT_OPEN_DST_STREAM = 262;
HOP_CANT_SPEAK_RELAY = 270;
HOP_CANT_RELAY_TO_SELF = 280;
STOP_SRC_ADDR_TOO_LONG = 320;
STOP_DST_ADDR_TOO_LONG = 321;
STOP_SRC_MULTIADDR_INVALID = 350;
STOP_DST_MULTIADDR_INVALID = 351;
STOP_RELAY_REFUSED = 390;
MALFORMED_MESSAGE = 400;
}
enum Type { // RPC identifier, either HOP, STOP or STATUS
HOP = 1;
STOP = 2;
STATUS = 3;
CAN_HOP = 4;
}
message Peer {
required bytes id = 1; // peer id
repeated bytes addrs = 2; // peer's known addresses
}
optional Type type = 1; // Type of the message
optional Peer srcPeer = 2; // srcPeer and dstPeer are used when Type is HOP or STATUS
optional Peer dstPeer = 3;
optional Status code = 4; // Status code, used when Type is STATUS
}

View File

@ -5,10 +5,12 @@ const log = Object.assign(debug('libp2p:circuit'), {
error: debug('libp2p:circuit:err')
})
const errCode = require('err-code')
const mafmt = require('mafmt')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const { CircuitRelay: CircuitPB } = require('./protocol')
const { codes } = require('../errors')
const toConnection = require('libp2p-utils/src/stream-to-ma-conn')
@ -21,10 +23,8 @@ const StreamHandler = require('./circuit/stream-handler')
const transportSymbol = Symbol.for('@libp2p/js-libp2p-circuit/circuit')
/**
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
* @typedef {import('../types').CircuitRequest} CircuitRequest
*/
class Circuit {
@ -54,7 +54,7 @@ class Circuit {
* @param {MuxedStream} props.stream
*/
async _onProtocol ({ connection, stream }) {
/** @type {import('./circuit/stream-handler')<CircuitRequest>} */
/** @type {import('./circuit/stream-handler')} */
const streamHandler = new StreamHandler({ stream })
const request = await streamHandler.read()
@ -96,8 +96,10 @@ class Circuit {
}
if (virtualConnection) {
const remoteAddr = multiaddr(request.dstPeer.addrs[0])
const localAddr = multiaddr(request.srcPeer.addrs[0])
// @ts-ignore dst peer will not be undefined
const remoteAddr = new Multiaddr(request.dstPeer.addrs[0])
// @ts-ignore src peer will not be undefined
const localAddr = new Multiaddr(request.srcPeer.addrs[0])
const maConn = toConnection({
stream: virtualConnection,
remoteAddr,
@ -123,10 +125,19 @@ class Circuit {
async dial (ma, options) {
// Check the multiaddr to see if it contains a relay and a destination peer
const addrs = ma.toString().split('/p2p-circuit')
const relayAddr = multiaddr(addrs[0])
const destinationAddr = multiaddr(addrs[addrs.length - 1])
const relayPeer = PeerId.createFromCID(relayAddr.getPeerId())
const destinationPeer = PeerId.createFromCID(destinationAddr.getPeerId())
const relayAddr = new Multiaddr(addrs[0])
const destinationAddr = new Multiaddr(addrs[addrs.length - 1])
const relayId = relayAddr.getPeerId()
const destinationId = destinationAddr.getPeerId()
if (!relayId || !destinationId) {
const errMsg = 'Circuit relay dial failed as addresses did not have peer id'
log.error(errMsg)
throw errCode(new Error(errMsg), codes.ERR_RELAYED_DIAL)
}
const relayPeer = PeerId.createFromCID(relayId)
const destinationPeer = PeerId.createFromCID(destinationId)
let disconnectOnFailure = false
let relayConnection = this._connectionManager.get(relayPeer)
@ -146,7 +157,7 @@ class Circuit {
},
dstPeer: {
id: destinationPeer.toBytes(),
addrs: [multiaddr(destinationAddr).bytes]
addrs: [new Multiaddr(destinationAddr).bytes]
}
}
})

View File

@ -1,6 +1,7 @@
'use strict'
const mergeOptions = require('merge-options')
// @ts-ignore no types in multiaddr path
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
const Constants = require('./constants')
@ -10,11 +11,18 @@ const RelayConstants = require('./circuit/constants')
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
const { FaultTolerance } = require('./transport-manager')
/**
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('.').Libp2pOptions} Libp2pOptions
* @typedef {import('.').constructorOptions} constructorOptions
*/
const DefaultConfig = {
addresses: {
listen: [],
announce: [],
noAnnounce: []
noAnnounce: [],
announceFilter: (/** @type {Multiaddr[]} */ multiaddrs) => multiaddrs
},
connectionManager: {
minConnections: 25
@ -95,10 +103,15 @@ const DefaultConfig = {
}
}
/**
* @param {Libp2pOptions} opts
* @returns {DefaultConfig & Libp2pOptions & constructorOptions}
*/
module.exports.validate = (opts) => {
opts = mergeOptions(DefaultConfig, opts)
/** @type {DefaultConfig & Libp2pOptions & constructorOptions} */
const resultingOptions = mergeOptions(DefaultConfig, opts)
if (opts.modules.transport.length < 1) throw new Error("'options.modules.transport' must contain at least 1 transport")
if (resultingOptions.modules.transport.length < 1) throw new Error("'options.modules.transport' must contain at least 1 transport")
return opts
return resultingOptions
}

View File

@ -8,10 +8,9 @@ const log = Object.assign(debug('libp2p:connection-manager'), {
const errcode = require('err-code')
const mergeOptions = require('merge-options')
const LatencyMonitor = require('./latency-monitor')
// @ts-ignore retimer does not have types
const retimer = require('retimer')
/** @typedef {import('../types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const PeerId = require('peer-id')
@ -188,8 +187,10 @@ class ConnectionManager extends EventEmitter {
_checkMetrics () {
if (this._libp2p.metrics) {
const movingAverages = this._libp2p.metrics.global.movingAverages
// @ts-ignore moving averages object types
const received = movingAverages.dataReceived[this._options.movingAverageInterval].movingAverage()
this._checkMaxLimit('maxReceivedData', received)
// @ts-ignore moving averages object types
const sent = movingAverages.dataSent[this._options.movingAverageInterval].movingAverage()
this._checkMaxLimit('maxSentData', sent)
const total = received + sent
@ -362,7 +363,7 @@ class ConnectionManager extends EventEmitter {
*/
_maybeDisconnectOne () {
if (this._options.minConnections < this.connections.size) {
const peerValues = Array.from(this._peerValues).sort(byPeerValue)
const peerValues = Array.from(new Map([...this._peerValues.entries()].sort((a, b) => a[1] - b[1])))
log('%s: sorted peer values: %j', this._peerId, peerValues)
const disconnectPeer = peerValues[0]
if (disconnectPeer) {
@ -381,7 +382,3 @@ class ConnectionManager extends EventEmitter {
}
module.exports = ConnectionManager
function byPeerValue (peerValueEntryA, peerValueEntryB) {
return peerValueEntryA[1] - peerValueEntryB[1]
}

View File

@ -5,8 +5,6 @@
* This code is based on `latency-monitor` (https://github.com/mlucool/latency-monitor) by `mlucool` (https://github.com/mlucool), available under Apache License 2.0 (https://github.com/mlucool/latency-monitor/blob/master/LICENSE)
*/
/** @typedef {import('../types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const VisibilityChangeEmitter = require('./visibility-change-emitter')
const debug = require('debug')('latency-monitor:LatencyMonitor')
@ -59,7 +57,8 @@ class LatencyMonitor extends EventEmitter {
that._latecyCheckMultiply = 2 * (that.latencyRandomPercentage / 100.0) * that.latencyCheckIntervalMs
that._latecyCheckSubtract = that._latecyCheckMultiply / 2
that.dataEmitIntervalMs = (dataEmitIntervalMs === null || dataEmitIntervalMs === 0) ? undefined
that.dataEmitIntervalMs = (dataEmitIntervalMs === null || dataEmitIntervalMs === 0)
? undefined
: dataEmitIntervalMs || 5 * 1000 // 5s
debug('latencyCheckIntervalMs: %s dataEmitIntervalMs: %s',
that.latencyCheckIntervalMs, that.dataEmitIntervalMs)
@ -174,7 +173,8 @@ class LatencyMonitor extends EventEmitter {
events: this._latencyData.events,
minMs: this._latencyData.minMs,
maxMs: this._latencyData.maxMs,
avgMs: this._latencyData.events ? this._latencyData.totalMs / this._latencyData.events
avgMs: this._latencyData.events
? this._latencyData.totalMs / this._latencyData.events
: Number.POSITIVE_INFINITY,
lengthMs: this.getDeltaMS(this._latencyData.startTime)
}

View File

@ -6,8 +6,6 @@
*/
'use strict'
/** @typedef {import('../types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const debug = require('debug')('latency-monitor:VisibilityChangeEmitter')

View File

@ -14,8 +14,9 @@ const { pipe } = require('it-pipe')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('cids')} CID
* @typedef {import('libp2p-interfaces/src/content-routing/types')} ContentRoutingModule
*/
/**
@ -31,6 +32,7 @@ class ContentRouting {
*/
constructor (libp2p) {
this.libp2p = libp2p
/** @type {ContentRoutingModule[]} */
this.routers = libp2p._modules.contentRouting || []
this.dht = libp2p._dht

View File

@ -7,7 +7,7 @@ const take = require('it-take')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('multiaddr').Multiaddr} Multiaddr
*/
/**

View File

@ -3,13 +3,14 @@
const errCode = require('err-code')
const AbortController = require('abort-controller').default
const { anySignal } = require('any-signal')
// @ts-ignore p-fifo does not export types
const FIFO = require('p-fifo')
const pAny = require('p-any')
/**
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('./')} Dialer
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('multiaddr').Multiaddr} Multiaddr
*/
/**

View File

@ -5,7 +5,8 @@ const log = Object.assign(debug('libp2p:dialer'), {
error: debug('libp2p:dialer:err')
})
const errCode = require('err-code')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
// @ts-ignore timeout-abourt-controles does not export types
const TimeoutController = require('timeout-abort-controller')
const { anySignal } = require('any-signal')
@ -22,7 +23,6 @@ const {
/**
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('peer-id')} PeerId
* @typedef {import('../peer-store')} PeerStore
* @typedef {import('../peer-store/address-book').Address} Address
@ -38,9 +38,9 @@ const {
*
* @typedef {Object} DialerOptions
* @property {(addresses: Address[]) => Address[]} [options.addressSorter = publicAddressesFirst] - Sort the known addresses of a peer before trying to dial.
* @property {number} [concurrency = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
* @property {number} [perPeerLimit = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
* @property {number} [timeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
* @property {number} [maxParallelDials = MAX_PARALLEL_DIALS] - Number of max concurrent dials.
* @property {number} [maxDialsPerPeer = MAX_PER_PEER_DIALS] - Number of max concurrent dials per peer.
* @property {number} [dialTimeout = DIAL_TIMEOUT] - How long a dial attempt is allowed to take.
* @property {Record<string, Resolver>} [resolvers = {}] - multiaddr resolvers to use when dialing
*
* @typedef DialTarget
@ -50,7 +50,7 @@ const {
* @typedef PendingDial
* @property {DialRequest} dialRequest
* @property {TimeoutController} controller
* @property {Promise} promise
* @property {Promise<Connection>} promise
* @property {function():void} destroy
*/
@ -63,22 +63,22 @@ class Dialer {
transportManager,
peerStore,
addressSorter = publicAddressesFirst,
concurrency = MAX_PARALLEL_DIALS,
timeout = DIAL_TIMEOUT,
perPeerLimit = MAX_PER_PEER_DIALS,
maxParallelDials = MAX_PARALLEL_DIALS,
dialTimeout = DIAL_TIMEOUT,
maxDialsPerPeer = MAX_PER_PEER_DIALS,
resolvers = {}
}) {
this.transportManager = transportManager
this.peerStore = peerStore
this.addressSorter = addressSorter
this.concurrency = concurrency
this.timeout = timeout
this.perPeerLimit = perPeerLimit
this.tokens = [...new Array(concurrency)].map((_, index) => index)
this.maxParallelDials = maxParallelDials
this.timeout = dialTimeout
this.maxDialsPerPeer = maxDialsPerPeer
this.tokens = [...new Array(maxParallelDials)].map((_, index) => index)
this._pendingDials = new Map()
for (const [key, value] of Object.entries(resolvers)) {
multiaddr.resolvers.set(key, value)
Multiaddr.resolvers.set(key, value)
}
}
@ -150,11 +150,12 @@ class Dialer {
// If received a multiaddr to dial, it should be the first to use
// But, if we know other multiaddrs for the peer, we should try them too.
if (multiaddr.isMultiaddr(peer)) {
if (Multiaddr.isMultiaddr(peer)) {
knownAddrs = knownAddrs.filter((addr) => !peer.equals(addr))
knownAddrs.unshift(peer)
}
/** @type {Multiaddr[]} */
const addrs = []
for (const a of knownAddrs) {
const resolvedAddrs = await this._resolve(a)
@ -177,6 +178,10 @@ class Dialer {
* @returns {PendingDial}
*/
_createPendingDial (dialTarget, options = {}) {
/**
* @param {Multiaddr} addr
* @param {{ signal: { aborted: any; }; }} options
*/
const dialAction = (addr, options) => {
if (options.signal.aborted) throw errCode(new Error('already aborted'), codes.ERR_ALREADY_ABORTED)
return this.transportManager.dial(addr, options)
@ -207,13 +212,19 @@ class Dialer {
return pendingDial
}
/**
* @param {number} num
*/
getTokens (num) {
const total = Math.min(num, this.perPeerLimit, this.tokens.length)
const total = Math.min(num, this.maxDialsPerPeer, this.tokens.length)
const tokens = this.tokens.splice(0, total)
log('%d tokens request, returning %d, %d remaining', num, total, this.tokens.length)
return tokens
}
/**
* @param {number} token
*/
releaseToken (token) {
// Guard against duplicate releases
if (this.tokens.indexOf(token) > -1) return
@ -259,7 +270,7 @@ class Dialer {
*/
async _resolveRecord (ma) {
try {
ma = multiaddr(ma.toString()) // Use current multiaddr module
ma = new Multiaddr(ma.toString()) // Use current multiaddr module
const multiaddrs = await ma.resolve()
return multiaddrs
} catch (_) {

View File

@ -16,6 +16,7 @@ exports.codes = {
ERR_NODE_NOT_STARTED: 'ERR_NODE_NOT_STARTED',
ERR_ALREADY_ABORTED: 'ERR_ALREADY_ABORTED',
ERR_NO_VALID_ADDRESSES: 'ERR_NO_VALID_ADDRESSES',
ERR_RELAYED_DIAL: 'ERR_RELAYED_DIAL',
ERR_DIALED_SELF: 'ERR_DIALED_SELF',
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',

View File

@ -1,15 +1,11 @@
'use strict'
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const errCode = require('err-code')
const { codes } = require('./errors')
/**
* @typedef {import('multiaddr')} Multiaddr
*/
/**
* Converts the given `peer` to a `Peer` object.
* If a multiaddr is received, the addressBook is updated.
@ -19,14 +15,23 @@ const { codes } = require('./errors')
*/
function getPeer (peer) {
if (typeof peer === 'string') {
peer = multiaddr(peer)
peer = new Multiaddr(peer)
}
let addr
if (multiaddr.isMultiaddr(peer)) {
if (Multiaddr.isMultiaddr(peer)) {
addr = peer
const idStr = peer.getPeerId()
if (!idStr) {
throw errCode(
new Error(`${peer} does not have a valid peer type`),
codes.ERR_INVALID_MULTIADDR
)
}
try {
peer = PeerId.createFromB58String(peer.getPeerId())
peer = PeerId.createFromB58String(idStr)
} catch (err) {
throw errCode(
new Error(`${peer} is not a valid peer type`),

View File

@ -5,14 +5,14 @@ const log = Object.assign(debug('libp2p:identify'), {
error: debug('libp2p:identify:err')
})
const errCode = require('err-code')
const pb = require('it-protocol-buffers')
const lp = require('it-length-prefixed')
const { pipe } = require('it-pipe')
const { collect, take, consume } = require('streaming-iterables')
const uint8ArrayFromString = require('uint8arrays/from-string')
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
// @ts-ignore it-buffer does not have types
const { toBuffer } = require('it-buffer')
const Message = require('./message')
@ -23,7 +23,6 @@ const PeerRecord = require('../record/peer-record')
const {
MULTICODEC_IDENTIFY,
MULTICODEC_IDENTIFY_PUSH,
AGENT_VERSION,
PROTOCOL_VERSION
} = require('./consts')
@ -34,6 +33,11 @@ const { codes } = require('../errors')
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
*/
/**
* @typedef {Object} HostProperties
* @property {string} agentVersion
*/
class IdentifyService {
/**
* @class
@ -51,7 +55,6 @@ class IdentifyService {
// Store self host metadata
this._host = {
agentVersion: AGENT_VERSION,
protocolVersion: PROTOCOL_VERSION,
...libp2p._options.host
}
@ -94,12 +97,12 @@ class IdentifyService {
const { stream } = await connection.newStream(MULTICODEC_IDENTIFY_PUSH)
await pipe(
[{
[Message.Identify.encode({
listenAddrs,
signedPeerRecord,
protocols
}],
pb.encode(Message),
}).finish()],
lp.encode(),
stream,
consume
)
@ -160,12 +163,12 @@ class IdentifyService {
let message
try {
message = Message.decode(data)
message = Message.Identify.decode(data)
} catch (err) {
throw errCode(err, codes.ERR_INVALID_MESSAGE)
}
let {
const {
publicKey,
listenAddrs,
protocols,
@ -180,7 +183,7 @@ class IdentifyService {
}
// Get the observedAddr if there is one
observedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
const cleanObservedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
try {
const envelope = await Envelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
@ -194,7 +197,7 @@ class IdentifyService {
// LEGACY: Update peers data in PeerStore
try {
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
this.peerStore.addressBook.set(id, listenAddrs.map((addr) => new Multiaddr(addr)))
} catch (err) {
log.error('received invalid addrs', err)
}
@ -203,7 +206,7 @@ class IdentifyService {
this.peerStore.metadataBook.set(id, 'AgentVersion', uint8ArrayFromString(message.agentVersion))
// TODO: Add and score our observed addr
log('received observed address of %s', observedAddr)
log('received observed address of %s', cleanObservedAddr)
// this.addressManager.addObservedAddr(observedAddr)
}
@ -246,7 +249,7 @@ class IdentifyService {
const signedPeerRecord = await this.peerStore.addressBook.getRawEnvelope(this.peerId)
const protocols = this.peerStore.protoBook.get(this.peerId) || []
const message = Message.encode({
const message = Message.Identify.encode({
protocolVersion: this._host.protocolVersion,
agentVersion: this._host.agentVersion,
publicKey,
@ -254,7 +257,7 @@ class IdentifyService {
signedPeerRecord,
observedAddr: connection.remoteAddr.bytes,
protocols
})
}).finish()
try {
await pipe(
@ -288,7 +291,7 @@ class IdentifyService {
toBuffer,
collect
)
message = Message.decode(data)
message = Message.Identify.decode(data)
} catch (err) {
return log.error('received invalid message', err)
}
@ -307,7 +310,8 @@ class IdentifyService {
// LEGACY: Update peers data in PeerStore
try {
this.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr)))
this.peerStore.addressBook.set(id,
message.listenAddrs.map((addr) => new Multiaddr(addr)))
} catch (err) {
log.error('received invalid addrs', err)
}
@ -320,12 +324,12 @@ class IdentifyService {
* Takes the `addr` and converts it to a Multiaddr if possible
*
* @param {Uint8Array | string} addr
* @returns {multiaddr|null}
* @returns {Multiaddr|null}
*/
static getCleanMultiaddr (addr) {
if (addr && addr.length > 0) {
try {
return multiaddr(addr)
return new Multiaddr(addr)
} catch (_) {
return null
}

95
src/identify/message.d.ts vendored Normal file
View File

@ -0,0 +1,95 @@
import * as $protobuf from "protobufjs";
/** Properties of an Identify. */
export interface IIdentify {
/** Identify protocolVersion */
protocolVersion?: (string|null);
/** Identify agentVersion */
agentVersion?: (string|null);
/** Identify publicKey */
publicKey?: (Uint8Array|null);
/** Identify listenAddrs */
listenAddrs?: (Uint8Array[]|null);
/** Identify observedAddr */
observedAddr?: (Uint8Array|null);
/** Identify protocols */
protocols?: (string[]|null);
/** Identify signedPeerRecord */
signedPeerRecord?: (Uint8Array|null);
}
/** Represents an Identify. */
export class Identify implements IIdentify {
/**
* Constructs a new Identify.
* @param [p] Properties to set
*/
constructor(p?: IIdentify);
/** Identify protocolVersion. */
public protocolVersion: string;
/** Identify agentVersion. */
public agentVersion: string;
/** Identify publicKey. */
public publicKey: Uint8Array;
/** Identify listenAddrs. */
public listenAddrs: Uint8Array[];
/** Identify observedAddr. */
public observedAddr: Uint8Array;
/** Identify protocols. */
public protocols: string[];
/** Identify signedPeerRecord. */
public signedPeerRecord: Uint8Array;
/**
* Encodes the specified Identify message. Does not implicitly {@link Identify.verify|verify} messages.
* @param m Identify message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IIdentify, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes an Identify message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Identify
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Identify;
/**
* Creates an Identify message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Identify
*/
public static fromObject(d: { [k: string]: any }): Identify;
/**
* Creates a plain object from an Identify message. Also converts values to other types if specified.
* @param m Identify
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Identify, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Identify to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}

View File

@ -1,35 +1,328 @@
'use strict'
/*eslint-disable*/
"use strict";
const protons = require('protons')
const schema = `
message Identify {
// protocolVersion determines compatibility between peers
optional string protocolVersion = 5; // e.g. ipfs/1.0.0
var $protobuf = require("protobufjs/minimal");
// agentVersion is like a UserAgent string in browsers, or client version in bittorrent
// includes the client name and client.
optional string agentVersion = 6; // e.g. go-ipfs/0.1.0
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// publicKey is this node's public key (which also gives its node.ID)
// - may not need to be sent, as secure channel implies it has been sent.
// - then again, if we change / disable secure channel, may still want it.
optional bytes publicKey = 1;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
// listenAddrs are the multiaddrs the sender node listens for open connections on
repeated bytes listenAddrs = 2;
$root.Identify = (function() {
// oservedAddr is the multiaddr of the remote endpoint that the sender node perceives
// this is useful information to convey to the other side, as it helps the remote endpoint
// determine whether its connection to the local peer goes through NAT.
optional bytes observedAddr = 4;
/**
* Properties of an Identify.
* @exports IIdentify
* @interface IIdentify
* @property {string|null} [protocolVersion] Identify protocolVersion
* @property {string|null} [agentVersion] Identify agentVersion
* @property {Uint8Array|null} [publicKey] Identify publicKey
* @property {Array.<Uint8Array>|null} [listenAddrs] Identify listenAddrs
* @property {Uint8Array|null} [observedAddr] Identify observedAddr
* @property {Array.<string>|null} [protocols] Identify protocols
* @property {Uint8Array|null} [signedPeerRecord] Identify signedPeerRecord
*/
repeated string protocols = 3;
/**
* Constructs a new Identify.
* @exports Identify
* @classdesc Represents an Identify.
* @implements IIdentify
* @constructor
* @param {IIdentify=} [p] Properties to set
*/
function Identify(p) {
this.listenAddrs = [];
this.protocols = [];
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
// signedPeerRecord contains a serialized SignedEnvelope containing a PeerRecord,
// signed by the sending node. It contains the same addresses as the listenAddrs field, but
// in a form that lets us share authenticated addrs with other peers.
optional bytes signedPeerRecord = 8;
}
`
/**
* Identify protocolVersion.
* @member {string} protocolVersion
* @memberof Identify
* @instance
*/
Identify.prototype.protocolVersion = "";
module.exports = protons(schema).Identify
/**
* Identify agentVersion.
* @member {string} agentVersion
* @memberof Identify
* @instance
*/
Identify.prototype.agentVersion = "";
/**
* Identify publicKey.
* @member {Uint8Array} publicKey
* @memberof Identify
* @instance
*/
Identify.prototype.publicKey = $util.newBuffer([]);
/**
* Identify listenAddrs.
* @member {Array.<Uint8Array>} listenAddrs
* @memberof Identify
* @instance
*/
Identify.prototype.listenAddrs = $util.emptyArray;
/**
* Identify observedAddr.
* @member {Uint8Array} observedAddr
* @memberof Identify
* @instance
*/
Identify.prototype.observedAddr = $util.newBuffer([]);
/**
* Identify protocols.
* @member {Array.<string>} protocols
* @memberof Identify
* @instance
*/
Identify.prototype.protocols = $util.emptyArray;
/**
* Identify signedPeerRecord.
* @member {Uint8Array} signedPeerRecord
* @memberof Identify
* @instance
*/
Identify.prototype.signedPeerRecord = $util.newBuffer([]);
/**
* Encodes the specified Identify message. Does not implicitly {@link Identify.verify|verify} messages.
* @function encode
* @memberof Identify
* @static
* @param {IIdentify} m Identify message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Identify.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey"))
w.uint32(10).bytes(m.publicKey);
if (m.listenAddrs != null && m.listenAddrs.length) {
for (var i = 0; i < m.listenAddrs.length; ++i)
w.uint32(18).bytes(m.listenAddrs[i]);
}
if (m.protocols != null && m.protocols.length) {
for (var i = 0; i < m.protocols.length; ++i)
w.uint32(26).string(m.protocols[i]);
}
if (m.observedAddr != null && Object.hasOwnProperty.call(m, "observedAddr"))
w.uint32(34).bytes(m.observedAddr);
if (m.protocolVersion != null && Object.hasOwnProperty.call(m, "protocolVersion"))
w.uint32(42).string(m.protocolVersion);
if (m.agentVersion != null && Object.hasOwnProperty.call(m, "agentVersion"))
w.uint32(50).string(m.agentVersion);
if (m.signedPeerRecord != null && Object.hasOwnProperty.call(m, "signedPeerRecord"))
w.uint32(66).bytes(m.signedPeerRecord);
return w;
};
/**
* Decodes an Identify message from the specified reader or buffer.
* @function decode
* @memberof Identify
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Identify} Identify
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Identify.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Identify();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 5:
m.protocolVersion = r.string();
break;
case 6:
m.agentVersion = r.string();
break;
case 1:
m.publicKey = r.bytes();
break;
case 2:
if (!(m.listenAddrs && m.listenAddrs.length))
m.listenAddrs = [];
m.listenAddrs.push(r.bytes());
break;
case 4:
m.observedAddr = r.bytes();
break;
case 3:
if (!(m.protocols && m.protocols.length))
m.protocols = [];
m.protocols.push(r.string());
break;
case 8:
m.signedPeerRecord = r.bytes();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates an Identify message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Identify
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Identify} Identify
*/
Identify.fromObject = function fromObject(d) {
if (d instanceof $root.Identify)
return d;
var m = new $root.Identify();
if (d.protocolVersion != null) {
m.protocolVersion = String(d.protocolVersion);
}
if (d.agentVersion != null) {
m.agentVersion = String(d.agentVersion);
}
if (d.publicKey != null) {
if (typeof d.publicKey === "string")
$util.base64.decode(d.publicKey, m.publicKey = $util.newBuffer($util.base64.length(d.publicKey)), 0);
else if (d.publicKey.length)
m.publicKey = d.publicKey;
}
if (d.listenAddrs) {
if (!Array.isArray(d.listenAddrs))
throw TypeError(".Identify.listenAddrs: array expected");
m.listenAddrs = [];
for (var i = 0; i < d.listenAddrs.length; ++i) {
if (typeof d.listenAddrs[i] === "string")
$util.base64.decode(d.listenAddrs[i], m.listenAddrs[i] = $util.newBuffer($util.base64.length(d.listenAddrs[i])), 0);
else if (d.listenAddrs[i].length)
m.listenAddrs[i] = d.listenAddrs[i];
}
}
if (d.observedAddr != null) {
if (typeof d.observedAddr === "string")
$util.base64.decode(d.observedAddr, m.observedAddr = $util.newBuffer($util.base64.length(d.observedAddr)), 0);
else if (d.observedAddr.length)
m.observedAddr = d.observedAddr;
}
if (d.protocols) {
if (!Array.isArray(d.protocols))
throw TypeError(".Identify.protocols: array expected");
m.protocols = [];
for (var i = 0; i < d.protocols.length; ++i) {
m.protocols[i] = String(d.protocols[i]);
}
}
if (d.signedPeerRecord != null) {
if (typeof d.signedPeerRecord === "string")
$util.base64.decode(d.signedPeerRecord, m.signedPeerRecord = $util.newBuffer($util.base64.length(d.signedPeerRecord)), 0);
else if (d.signedPeerRecord.length)
m.signedPeerRecord = d.signedPeerRecord;
}
return m;
};
/**
* Creates a plain object from an Identify message. Also converts values to other types if specified.
* @function toObject
* @memberof Identify
* @static
* @param {Identify} m Identify
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Identify.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.arrays || o.defaults) {
d.listenAddrs = [];
d.protocols = [];
}
if (o.defaults) {
if (o.bytes === String)
d.publicKey = "";
else {
d.publicKey = [];
if (o.bytes !== Array)
d.publicKey = $util.newBuffer(d.publicKey);
}
if (o.bytes === String)
d.observedAddr = "";
else {
d.observedAddr = [];
if (o.bytes !== Array)
d.observedAddr = $util.newBuffer(d.observedAddr);
}
d.protocolVersion = "";
d.agentVersion = "";
if (o.bytes === String)
d.signedPeerRecord = "";
else {
d.signedPeerRecord = [];
if (o.bytes !== Array)
d.signedPeerRecord = $util.newBuffer(d.signedPeerRecord);
}
}
if (m.publicKey != null && m.hasOwnProperty("publicKey")) {
d.publicKey = o.bytes === String ? $util.base64.encode(m.publicKey, 0, m.publicKey.length) : o.bytes === Array ? Array.prototype.slice.call(m.publicKey) : m.publicKey;
}
if (m.listenAddrs && m.listenAddrs.length) {
d.listenAddrs = [];
for (var j = 0; j < m.listenAddrs.length; ++j) {
d.listenAddrs[j] = o.bytes === String ? $util.base64.encode(m.listenAddrs[j], 0, m.listenAddrs[j].length) : o.bytes === Array ? Array.prototype.slice.call(m.listenAddrs[j]) : m.listenAddrs[j];
}
}
if (m.protocols && m.protocols.length) {
d.protocols = [];
for (var j = 0; j < m.protocols.length; ++j) {
d.protocols[j] = m.protocols[j];
}
}
if (m.observedAddr != null && m.hasOwnProperty("observedAddr")) {
d.observedAddr = o.bytes === String ? $util.base64.encode(m.observedAddr, 0, m.observedAddr.length) : o.bytes === Array ? Array.prototype.slice.call(m.observedAddr) : m.observedAddr;
}
if (m.protocolVersion != null && m.hasOwnProperty("protocolVersion")) {
d.protocolVersion = m.protocolVersion;
}
if (m.agentVersion != null && m.hasOwnProperty("agentVersion")) {
d.agentVersion = m.agentVersion;
}
if (m.signedPeerRecord != null && m.hasOwnProperty("signedPeerRecord")) {
d.signedPeerRecord = o.bytes === String ? $util.base64.encode(m.signedPeerRecord, 0, m.signedPeerRecord.length) : o.bytes === Array ? Array.prototype.slice.call(m.signedPeerRecord) : m.signedPeerRecord;
}
return d;
};
/**
* Converts this Identify to JSON.
* @function toJSON
* @memberof Identify
* @instance
* @returns {Object.<string,*>} JSON object
*/
Identify.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return Identify;
})();
module.exports = $root;

View File

@ -0,0 +1,30 @@
syntax = "proto3";
message Identify {
// protocolVersion determines compatibility between peers
optional string protocolVersion = 5; // e.g. ipfs/1.0.0
// agentVersion is like a UserAgent string in browsers, or client version in bittorrent
// includes the client name and client.
optional string agentVersion = 6; // e.g. go-ipfs/0.1.0
// publicKey is this node's public key (which also gives its node.ID)
// - may not need to be sent, as secure channel implies it has been sent.
// - then again, if we change / disable secure channel, may still want it.
optional bytes publicKey = 1;
// listenAddrs are the multiaddrs the sender node listens for open connections on
repeated bytes listenAddrs = 2;
// oservedAddr is the multiaddr of the remote endpoint that the sender node perceives
// this is useful information to convey to the other side, as it helps the remote endpoint
// determine whether its connection to the local peer goes through NAT.
optional bytes observedAddr = 4;
repeated string protocols = 3;
// signedPeerRecord contains a serialized SignedEnvelope containing a PeerRecord,
// signed by the sending node. It contains the same addresses as the listenAddrs field, but
// in a form that lets us share authenticated addrs with other peers.
optional bytes signedPeerRecord = 8;
}

View File

@ -4,13 +4,11 @@ const debug = require('debug')
const log = Object.assign(debug('libp2p'), {
error: debug('libp2p:err')
})
/** @typedef {import('./types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const errCode = require('err-code')
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerRouting = require('./peer-routing')
const ContentRouting = require('./content-routing')
@ -38,29 +36,60 @@ const NatManager = require('./nat-manager')
const { updateSelfPeerRecord } = require('./record/utils')
/**
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory} TransportFactory
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory<any, any>} TransportFactory
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxerFactory} MuxerFactory
* @typedef {import('libp2p-interfaces/src/content-routing/types')} ContentRoutingModule
* @typedef {import('libp2p-interfaces/src/peer-discovery/types')} PeerDiscoveryModule
* @typedef {import('libp2p-interfaces/src/peer-routing/types')} PeerRoutingModule
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
* @typedef {import('libp2p-interfaces/src/pubsub')} Pubsub
* @typedef {import('libp2p-interfaces/src/pubsub').PubsubOptions} PubsubOptions
* @typedef {import('interface-datastore').Datastore} Datastore
* @typedef {import('./pnet')} Protector
*/
/**
* @typedef {Object} HandlerProps
* @property {Connection} connection
* @property {MuxedStream} stream
* @property {string} protocol
*
* @typedef {Object} RandomWalkOptions
* @property {boolean} [enabled = false]
* @property {number} [queriesPerPeriod = 1]
* @property {number} [interval = 300e3]
* @property {number} [timeout = 10e3]
*
* @typedef {Object} DhtOptions
* @property {boolean} [enabled = false]
* @property {number} [kBucketSize = 20]
* @property {RandomWalkOptions} [randomWalk]
*
* @typedef {Object} KeychainOptions
* @property {Datastore} [datastore]
*
* @typedef {Object} PeerStoreOptions
* @property {boolean} persistence
*
* @typedef {Object} RelayOptions
* @typedef {Object} PubsubLocalOptions
* @property {boolean} enabled
* @property {import('./circuit').RelayAdvertiseOptions} advertise
* @property {import('./circuit').HopOptions} hop
* @property {import('./circuit').AutoRelayOptions} autoRelay
*
* @typedef {Object} MetricsOptions
* @property {boolean} enabled
*
* @typedef {Object} RelayOptions
* @property {boolean} [enabled = true]
* @property {import('./circuit').RelayAdvertiseOptions} [advertise]
* @property {import('./circuit').HopOptions} [hop]
* @property {import('./circuit').AutoRelayOptions} [autoRelay]
*
* @typedef {Object} Libp2pConfig
* @property {Object} [dht] dht module options
* @property {Object} [peerDiscovery]
* @property {Pubsub} [pubsub] pubsub module options
* @property {DhtOptions} [dht] dht module options
* @property {import('./nat-manager').NatManagerOptions} [nat]
* @property {Record<string, Object|boolean>} [peerDiscovery]
* @property {PubsubLocalOptions & PubsubOptions} [pubsub] pubsub module options
* @property {RelayOptions} [relay]
* @property {Record<string, Object>} [transport] transport options indexed by transport key
*
@ -68,16 +97,25 @@ const { updateSelfPeerRecord } = require('./record/utils')
* @property {TransportFactory[]} transport
* @property {MuxerFactory[]} streamMuxer
* @property {Crypto[]} connEncryption
* @property {PeerDiscoveryModule[]} [peerDiscovery]
* @property {PeerRoutingModule[]} [peerRouting]
* @property {ContentRoutingModule[]} [contentRouting]
* @property {Object} [dht]
* @property {Pubsub} [pubsub]
* @property {Protector} [connProtector]
*
* @typedef {Object} Libp2pOptions
* @property {Libp2pModules} modules libp2p modules to use
* @property {import('./address-manager').AddressManagerOptions} [addresses]
* @property {import('./connection-manager').ConnectionManagerOptions} [connectionManager]
* @property {Datastore} [datastore]
* @property {import('./dialer').DialerOptions} [dialer]
* @property {import('./metrics').MetricsOptions} [metrics]
* @property {Object} [keychain]
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
* @property {import('./identify/index').HostProperties} [host] libp2p host
* @property {KeychainOptions & import('./keychain/index').KeychainOptions} [keychain]
* @property {MetricsOptions & import('./metrics').MetricsOptions} [metrics]
* @property {import('./peer-routing').PeerRoutingOptions} [peerRouting]
* @property {PeerStoreOptions & import('./peer-store/persistent').PersistentPeerStoreOptions} [peerStore]
* @property {import('./transport-manager').TransportManagerOptions} [transportManager]
* @property {Libp2pConfig} [config]
*
* @typedef {Object} constructorOptions
@ -152,9 +190,6 @@ class Libp2p extends EventEmitter {
this._discovery = new Map() // Discovery service instances/references
// Create the Connection Manager
if (this._options.connectionManager.minPeers) { // Remove in 0.29
this._options.connectionManager.minConnections = this._options.connectionManager.minPeers
}
this.connectionManager = new ConnectionManager(this, {
autoDial: this._config.peerDiscovery.autoDial,
...this._options.connectionManager
@ -175,7 +210,6 @@ class Libp2p extends EventEmitter {
const keychainOpts = Keychain.generateOptions()
this.keychain = new Keychain(this._options.keychain.datastore, {
passPhrase: this._options.keychain.pass,
...keychainOpts,
...this._options.keychain
})
@ -203,6 +237,7 @@ class Libp2p extends EventEmitter {
peerId: this.peerId,
addressManager: this.addressManager,
transportManager: this.transportManager,
// @ts-ignore Nat typedef is not understood as Object
...this._options.config.nat
})
@ -227,11 +262,7 @@ class Libp2p extends EventEmitter {
this.dialer = new Dialer({
transportManager: this.transportManager,
peerStore: this.peerStore,
concurrency: this._options.dialer.maxParallelDials,
perPeerLimit: this._options.dialer.maxDialsPerPeer,
timeout: this._options.dialer.dialTimeout,
resolvers: this._options.dialer.resolvers,
addressSorter: this._options.dialer.addressSorter
...this._options.dialer
})
this._modules.transport.forEach((Transport) => {
@ -268,6 +299,7 @@ class Libp2p extends EventEmitter {
// dht provided components (peerRouting, contentRouting, dht)
if (this._modules.dht) {
const DHT = this._modules.dht
// @ts-ignore Object is not constructable
this._dht = new DHT({
libp2p: this,
dialer: this.dialer,
@ -426,7 +458,7 @@ class Libp2p extends EventEmitter {
* @returns {Promise<Connection>}
*/
dial (peer, options) {
return this.dialProtocol(peer, [], options)
return this._dial(peer, options)
}
/**
@ -439,9 +471,26 @@ class Libp2p extends EventEmitter {
* @param {string[]|string} protocols
* @param {object} [options]
* @param {AbortSignal} [options.signal]
* @returns {Promise<Connection|*>}
* @returns {Promise<Connection|{ stream: MuxedStream; protocol: string; }>}
*/
async dialProtocol (peer, protocols, options) {
const connection = await this._dial(peer, options)
// If a protocol was provided, create a new stream
if (protocols && protocols.length) {
return connection.newStream(protocols)
}
return connection
}
/**
* @async
* @param {PeerId|Multiaddr|string} peer - The peer to dial
* @param {object} [options]
* @returns {Promise<Connection>}
*/
async _dial (peer, options) {
const { id, multiaddrs } = getPeer(peer)
if (id.equals(this.peerId)) {
@ -456,11 +505,6 @@ class Libp2p extends EventEmitter {
this.peerStore.addressBook.add(id, multiaddrs)
}
// If a protocol was provided, create a new stream
if (protocols && protocols.length) {
return connection.newStream(protocols)
}
return connection
}
@ -484,13 +528,13 @@ class Libp2p extends EventEmitter {
addrs = addrs.concat(this.addressManager.getObservedAddrs().map(ma => ma.toString()))
const announceFilter = this._options.addresses.announceFilter || ((multiaddrs) => multiaddrs)
const announceFilter = this._options.addresses.announceFilter
// dedupe multiaddrs
const addrSet = new Set(addrs)
// Create advertising list
return announceFilter(Array.from(addrSet).map(str => multiaddr(str)))
return announceFilter(Array.from(addrSet).map(str => new Multiaddr(str)))
}
/**
@ -536,7 +580,7 @@ class Libp2p extends EventEmitter {
* Registers the `handler` for each protocol
*
* @param {string[]|string} protocols
* @param {({ connection: Connection, stream: MuxedStream, protocol: string }) => void} handler
* @param {(props: HandlerProps) => void} handler
*/
handle (protocols, handler) {
protocols = Array.isArray(protocols) ? protocols : [protocols]
@ -669,6 +713,9 @@ class Libp2p extends EventEmitter {
* @private
*/
async _setupPeerDiscovery () {
/**
* @param {PeerDiscoveryModule} DiscoveryService
*/
const setupService = (DiscoveryService) => {
let config = {
enabled: true // on by default
@ -677,6 +724,7 @@ class Libp2p extends EventEmitter {
if (DiscoveryService.tag &&
this._config.peerDiscovery &&
this._config.peerDiscovery[DiscoveryService.tag]) {
// @ts-ignore PeerDiscovery not understood as an Object for spread
config = { ...config, ...this._config.peerDiscovery[DiscoveryService.tag] }
}
@ -685,6 +733,7 @@ class Libp2p extends EventEmitter {
let discoveryService
if (typeof DiscoveryService === 'function') {
// @ts-ignore DiscoveryService has no constructor type inferred
discoveryService = new DiscoveryService(Object.assign({}, config, {
peerId: this.peerId,
libp2p: this

View File

@ -4,6 +4,7 @@ const debug = require('debug')
const log = Object.assign(debug('libp2p:plaintext'), {
error: debug('libp2p:plaintext:err')
})
// @ts-ignore it-handshake do not export types
const handshake = require('it-handshake')
const lp = require('it-length-prefixed')
const PeerId = require('peer-id')
@ -16,8 +17,12 @@ const protocol = '/plaintext/2.0.0'
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
*/
/**
* @param {import('./proto').IExchange} exchange
*/
function lpEncodeExchange (exchange) {
const pb = Exchange.encode(exchange)
const pb = Exchange.encode(exchange).finish()
// @ts-ignore TODO: Uint8Array not assignable to Buffer
return lp.encode.single(pb)
}
@ -68,12 +73,23 @@ async function encrypt (localId, conn, remoteId) {
}
}
module.exports = {
module.exports =
{
protocol,
/**
* @param {PeerId} localId
* @param {Connection} conn
* @param {PeerId | undefined} remoteId
*/
secureInbound: (localId, conn, remoteId) => {
return encrypt(localId, conn, remoteId)
},
/**
* @param {PeerId} localId
* @param {Connection} conn
* @param {PeerId | undefined} remoteId
*/
secureOutbound: (localId, conn, remoteId) => {
return encrypt(localId, conn, remoteId)
}
}
}

128
src/insecure/proto.d.ts vendored Normal file
View File

@ -0,0 +1,128 @@
import * as $protobuf from "protobufjs";
/** Properties of an Exchange. */
export interface IExchange {
/** Exchange id */
id?: (Uint8Array|null);
/** Exchange pubkey */
pubkey?: (IPublicKey|null);
}
/** Represents an Exchange. */
export class Exchange implements IExchange {
/**
* Constructs a new Exchange.
* @param [p] Properties to set
*/
constructor(p?: IExchange);
/** Exchange id. */
public id: Uint8Array;
/** Exchange pubkey. */
public pubkey?: (IPublicKey|null);
/**
* Encodes the specified Exchange message. Does not implicitly {@link Exchange.verify|verify} messages.
* @param m Exchange message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IExchange, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes an Exchange message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Exchange
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Exchange;
/**
* Creates an Exchange message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Exchange
*/
public static fromObject(d: { [k: string]: any }): Exchange;
/**
* Creates a plain object from an Exchange message. Also converts values to other types if specified.
* @param m Exchange
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Exchange, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Exchange to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
/** KeyType enum. */
export enum KeyType {
RSA = 0,
Ed25519 = 1,
Secp256k1 = 2,
ECDSA = 3
}
/** Represents a PublicKey. */
export class PublicKey implements IPublicKey {
/**
* Constructs a new PublicKey.
* @param [p] Properties to set
*/
constructor(p?: IPublicKey);
/** PublicKey Type. */
public Type: KeyType;
/** PublicKey Data. */
public Data: Uint8Array;
/**
* Encodes the specified PublicKey message. Does not implicitly {@link PublicKey.verify|verify} messages.
* @param m PublicKey message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IPublicKey, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a PublicKey message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns PublicKey
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): PublicKey;
/**
* Creates a PublicKey message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns PublicKey
*/
public static fromObject(d: { [k: string]: any }): PublicKey;
/**
* Creates a plain object from a PublicKey message. Also converts values to other types if specified.
* @param m PublicKey
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: PublicKey, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this PublicKey to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}

View File

@ -1,22 +1,371 @@
'use strict'
/*eslint-disable*/
"use strict";
const protobuf = require('protons')
var $protobuf = require("protobufjs/minimal");
module.exports = protobuf(`
message Exchange {
optional bytes id = 1;
optional PublicKey pubkey = 2;
}
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
enum KeyType {
RSA = 0;
Ed25519 = 1;
Secp256k1 = 2;
ECDSA = 3;
}
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
message PublicKey {
required KeyType Type = 1;
required bytes Data = 2;
}
`)
$root.Exchange = (function() {
/**
* Properties of an Exchange.
* @exports IExchange
* @interface IExchange
* @property {Uint8Array|null} [id] Exchange id
* @property {IPublicKey|null} [pubkey] Exchange pubkey
*/
/**
* Constructs a new Exchange.
* @exports Exchange
* @classdesc Represents an Exchange.
* @implements IExchange
* @constructor
* @param {IExchange=} [p] Properties to set
*/
function Exchange(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* Exchange id.
* @member {Uint8Array} id
* @memberof Exchange
* @instance
*/
Exchange.prototype.id = $util.newBuffer([]);
/**
* Exchange pubkey.
* @member {IPublicKey|null|undefined} pubkey
* @memberof Exchange
* @instance
*/
Exchange.prototype.pubkey = null;
/**
* Encodes the specified Exchange message. Does not implicitly {@link Exchange.verify|verify} messages.
* @function encode
* @memberof Exchange
* @static
* @param {IExchange} m Exchange message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Exchange.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.id != null && Object.hasOwnProperty.call(m, "id"))
w.uint32(10).bytes(m.id);
if (m.pubkey != null && Object.hasOwnProperty.call(m, "pubkey"))
$root.PublicKey.encode(m.pubkey, w.uint32(18).fork()).ldelim();
return w;
};
/**
* Decodes an Exchange message from the specified reader or buffer.
* @function decode
* @memberof Exchange
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Exchange} Exchange
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Exchange.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Exchange();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.id = r.bytes();
break;
case 2:
m.pubkey = $root.PublicKey.decode(r, r.uint32());
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates an Exchange message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Exchange
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Exchange} Exchange
*/
Exchange.fromObject = function fromObject(d) {
if (d instanceof $root.Exchange)
return d;
var m = new $root.Exchange();
if (d.id != null) {
if (typeof d.id === "string")
$util.base64.decode(d.id, m.id = $util.newBuffer($util.base64.length(d.id)), 0);
else if (d.id.length)
m.id = d.id;
}
if (d.pubkey != null) {
if (typeof d.pubkey !== "object")
throw TypeError(".Exchange.pubkey: object expected");
m.pubkey = $root.PublicKey.fromObject(d.pubkey);
}
return m;
};
/**
* Creates a plain object from an Exchange message. Also converts values to other types if specified.
* @function toObject
* @memberof Exchange
* @static
* @param {Exchange} m Exchange
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Exchange.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
if (o.bytes === String)
d.id = "";
else {
d.id = [];
if (o.bytes !== Array)
d.id = $util.newBuffer(d.id);
}
d.pubkey = null;
}
if (m.id != null && m.hasOwnProperty("id")) {
d.id = o.bytes === String ? $util.base64.encode(m.id, 0, m.id.length) : o.bytes === Array ? Array.prototype.slice.call(m.id) : m.id;
}
if (m.pubkey != null && m.hasOwnProperty("pubkey")) {
d.pubkey = $root.PublicKey.toObject(m.pubkey, o);
}
return d;
};
/**
* Converts this Exchange to JSON.
* @function toJSON
* @memberof Exchange
* @instance
* @returns {Object.<string,*>} JSON object
*/
Exchange.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return Exchange;
})();
/**
* KeyType enum.
* @exports KeyType
* @enum {number}
* @property {number} RSA=0 RSA value
* @property {number} Ed25519=1 Ed25519 value
* @property {number} Secp256k1=2 Secp256k1 value
* @property {number} ECDSA=3 ECDSA value
*/
$root.KeyType = (function() {
var valuesById = {}, values = Object.create(valuesById);
values[valuesById[0] = "RSA"] = 0;
values[valuesById[1] = "Ed25519"] = 1;
values[valuesById[2] = "Secp256k1"] = 2;
values[valuesById[3] = "ECDSA"] = 3;
return values;
})();
$root.PublicKey = (function() {
/**
* Properties of a PublicKey.
* @exports IPublicKey
* @interface IPublicKey
* @property {KeyType|null} [Type] PublicKey Type
* @property {Uint8Array|null} [Data] PublicKey Data
*/
/**
* Constructs a new PublicKey.
* @exports PublicKey
* @classdesc Represents a PublicKey.
* @implements IPublicKey
* @constructor
* @param {IPublicKey=} [p] Properties to set
*/
function PublicKey(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* PublicKey Type.
* @member {KeyType} Type
* @memberof PublicKey
* @instance
*/
PublicKey.prototype.Type = 0;
/**
* PublicKey Data.
* @member {Uint8Array} Data
* @memberof PublicKey
* @instance
*/
PublicKey.prototype.Data = $util.newBuffer([]);
/**
* Encodes the specified PublicKey message. Does not implicitly {@link PublicKey.verify|verify} messages.
* @function encode
* @memberof PublicKey
* @static
* @param {IPublicKey} m PublicKey message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
PublicKey.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.Type != null && Object.hasOwnProperty.call(m, "Type"))
w.uint32(8).int32(m.Type);
if (m.Data != null && Object.hasOwnProperty.call(m, "Data"))
w.uint32(18).bytes(m.Data);
return w;
};
/**
* Decodes a PublicKey message from the specified reader or buffer.
* @function decode
* @memberof PublicKey
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {PublicKey} PublicKey
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
PublicKey.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.PublicKey();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.Type = r.int32();
break;
case 2:
m.Data = r.bytes();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates a PublicKey message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof PublicKey
* @static
* @param {Object.<string,*>} d Plain object
* @returns {PublicKey} PublicKey
*/
PublicKey.fromObject = function fromObject(d) {
if (d instanceof $root.PublicKey)
return d;
var m = new $root.PublicKey();
switch (d.Type) {
case "RSA":
case 0:
m.Type = 0;
break;
case "Ed25519":
case 1:
m.Type = 1;
break;
case "Secp256k1":
case 2:
m.Type = 2;
break;
case "ECDSA":
case 3:
m.Type = 3;
break;
}
if (d.Data != null) {
if (typeof d.Data === "string")
$util.base64.decode(d.Data, m.Data = $util.newBuffer($util.base64.length(d.Data)), 0);
else if (d.Data.length)
m.Data = d.Data;
}
return m;
};
/**
* Creates a plain object from a PublicKey message. Also converts values to other types if specified.
* @function toObject
* @memberof PublicKey
* @static
* @param {PublicKey} m PublicKey
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
PublicKey.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
d.Type = o.enums === String ? "RSA" : 0;
if (o.bytes === String)
d.Data = "";
else {
d.Data = [];
if (o.bytes !== Array)
d.Data = $util.newBuffer(d.Data);
}
}
if (m.Type != null && m.hasOwnProperty("Type")) {
d.Type = o.enums === String ? $root.KeyType[m.Type] : m.Type;
}
if (m.Data != null && m.hasOwnProperty("Data")) {
d.Data = o.bytes === String ? $util.base64.encode(m.Data, 0, m.Data.length) : o.bytes === Array ? Array.prototype.slice.call(m.Data) : m.Data;
}
return d;
};
/**
* Converts this PublicKey to JSON.
* @function toJSON
* @memberof PublicKey
* @instance
* @returns {Object.<string,*>} JSON object
*/
PublicKey.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return PublicKey;
})();
module.exports = $root;

18
src/insecure/proto.proto Normal file
View File

@ -0,0 +1,18 @@
syntax = "proto3";
message Exchange {
optional bytes id = 1;
optional PublicKey pubkey = 2;
}
enum KeyType {
RSA = 0;
Ed25519 = 1;
Secp256k1 = 2;
ECDSA = 3;
}
message PublicKey {
KeyType Type = 1;
bytes Data = 2;
}

View File

@ -1,7 +1,10 @@
'use strict'
// @ts-ignore node-forge types not exported
require('node-forge/lib/pkcs7')
// @ts-ignore node-forge types not exported
require('node-forge/lib/pbe')
// @ts-ignore node-forge types not exported
const forge = require('node-forge/lib/forge')
const { certificateForKey, findAsync } = require('./util')
const errcode = require('err-code')
@ -85,6 +88,7 @@ class CMS {
try {
const buf = forge.util.createBuffer(uint8ArrayToString(cmsData, 'ascii'))
const obj = forge.asn1.fromDer(buf)
// @ts-ignore not defined
cms = forge.pkcs7.messageFromAsn1(obj)
} catch (err) {
throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS')
@ -93,11 +97,15 @@ class CMS {
// Find a recipient whose key we hold. We only deal with recipient certs
// issued by ipfs (O=ipfs).
const recipients = cms.recipients
// @ts-ignore cms types not defined
.filter(r => r.issuer.find(a => a.shortName === 'O' && a.value === 'ipfs'))
// @ts-ignore cms types not defined
.filter(r => r.issuer.find(a => a.shortName === 'CN'))
// @ts-ignore cms types not defined
.map(r => {
return {
recipient: r,
// @ts-ignore cms types not defined
keyId: r.issuer.find(a => a.shortName === 'CN').value
}
})
@ -113,6 +121,7 @@ class CMS {
})
if (!r) {
// @ts-ignore cms types not defined
const missingKeys = recipients.map(r => r.keyId)
throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', {
missingKeys

View File

@ -10,6 +10,7 @@ const errcode = require('err-code')
const uint8ArrayToString = require('uint8arrays/to-string')
const uint8ArrayFromString = require('uint8arrays/from-string')
// @ts-ignore node-forge sha512 types not exported
require('node-forge/lib/sha512')
/**
@ -17,6 +18,26 @@ require('node-forge/lib/sha512')
* @typedef {import('interface-datastore').Datastore} Datastore
*/
/**
* @typedef {Object} DekOptions
* @property {string} hash
* @property {string} salt
* @property {number} iterationCount
* @property {number} keyLength
*
* @typedef {Object} KeychainOptions
* @property {string} pass
* @property {DekOptions} [dek]
*/
/**
* Information about a key.
*
* @typedef {Object} KeyInfo
* @property {string} id - The universally unique key id.
* @property {string} name - The local key name.
*/
const keyPrefix = '/pkcs8/'
const infoPrefix = '/info/'
const privates = new WeakMap()
@ -38,6 +59,9 @@ const defaultOptions = {
}
}
/**
* @param {string} name
*/
function validateKeyName (name) {
if (!name) return false
if (typeof name !== 'string') return false
@ -85,14 +109,6 @@ function DsInfoName (name) {
return new Key(infoPrefix + name)
}
/**
* Information about a key.
*
* @typedef {Object} KeyInfo
* @property {string} id - The universally unique key id.
* @property {string} name - The local key name.
*/
/**
* Manages the lifecycle of a key. Keys are encrypted at rest using PKCS #8.
*
@ -106,7 +122,7 @@ class Keychain {
* Creates a new instance of a key chain.
*
* @param {Datastore} store - where the key are.
* @param {object} options
* @param {KeychainOptions} options
* @class
*/
constructor (store, options) {
@ -118,8 +134,8 @@ class Keychain {
this.opts = mergeOptions(defaultOptions, options)
// Enforce NIST SP 800-132
if (this.opts.passPhrase && this.opts.passPhrase.length < 20) {
throw new Error('passPhrase must be least 20 characters')
if (this.opts.pass && this.opts.pass.length < 20) {
throw new Error('pass must be least 20 characters')
}
if (this.opts.dek.keyLength < NIST.minKeyLength) {
throw new Error(`dek.keyLength must be least ${NIST.minKeyLength} bytes`)
@ -131,12 +147,14 @@ class Keychain {
throw new Error(`dek.iterationCount must be least ${NIST.minIterationCount}`)
}
const dek = this.opts.passPhrase ? crypto.pbkdf2(
this.opts.passPhrase,
const dek = this.opts.pass
? crypto.pbkdf2(
this.opts.pass,
this.opts.dek.salt,
this.opts.dek.iterationCount,
this.opts.dek.keyLength,
this.opts.dek.hash) : ''
this.opts.dek.hash)
: ''
privates.set(this, { dek })
}

View File

@ -4,7 +4,6 @@
require('node-forge/lib/x509')
const forge = require('node-forge/lib/forge')
const pki = forge.pki
exports = module.exports
/**
* Gets a self-signed X.509 certificate for the key.
@ -17,7 +16,7 @@ exports = module.exports
* @param {RsaPrivateKey} privateKey - The naked key
* @returns {Uint8Array}
*/
exports.certificateForKey = (key, privateKey) => {
const certificateForKey = (key, privateKey) => {
const publicKey = pki.setRsaPublicKey(privateKey.n, privateKey.e)
const cert = pki.createCertificate()
cert.publicKey = publicKey
@ -87,4 +86,7 @@ async function findAsync (array, asyncCompare) {
return array[index]
}
module.exports.findAsync = findAsync
module.exports = {
certificateForKey,
findAsync
}

View File

@ -1,8 +1,6 @@
// @ts-nocheck
'use strict'
/** @typedef {import('../types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const Big = require('bignumber.js')
const MovingAverage = require('moving-average')
@ -32,13 +30,13 @@ class Stats extends EventEmitter {
const intervals = this._options.movingAverageIntervals
for (var i = 0; i < initialCounters.length; i++) {
var key = initialCounters[i]
for (let i = 0; i < initialCounters.length; i++) {
const key = initialCounters[i]
this._stats[key] = Big(0)
this._movingAverages[key] = {}
for (var k = 0; k < intervals.length; k++) {
var interval = intervals[k]
var ma = this._movingAverages[key][interval] = MovingAverage(interval)
for (let k = 0; k < intervals.length; k++) {
const interval = intervals[k]
const ma = this._movingAverages[key][interval] = MovingAverage(interval)
ma.push(this._frequencyLastTime, 0)
}
}
@ -72,8 +70,6 @@ class Stats extends EventEmitter {
/**
* Returns a clone of the current stats.
*
* @returns {Object}
*/
get snapshot () {
return Object.assign({}, this._stats)
@ -81,8 +77,6 @@ class Stats extends EventEmitter {
/**
* Returns a clone of the internal movingAverages
*
* @returns {Object}
*/
get movingAverages () {
return Object.assign({}, this._movingAverages)
@ -219,9 +213,9 @@ class Stats extends EventEmitter {
const intervals = this._options.movingAverageIntervals
for (var i = 0; i < intervals.length; i++) {
var movingAverageInterval = intervals[i]
var movingAverage = movingAverages[movingAverageInterval]
for (let i = 0; i < intervals.length; i++) {
const movingAverageInterval = intervals[i]
let movingAverage = movingAverages[movingAverageInterval]
if (!movingAverage) {
movingAverage = movingAverages[movingAverageInterval] = MovingAverage(movingAverageInterval)
}

View File

@ -1,14 +1,16 @@
'use strict'
// @ts-ignore nat-api does not export types
const NatAPI = require('@motrix/nat-api')
const debug = require('debug')
const { promisify } = require('es6-promisify')
const Multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const log = Object.assign(debug('libp2p:nat'), {
error: debug('libp2p:nat:err')
})
const { isBrowser } = require('ipfs-utils/src/env')
const retry = require('p-retry')
// @ts-ignore private-api does not export types
const isPrivateIp = require('private-ip')
const pkg = require('../package.json')
const errcode = require('err-code')
@ -17,33 +19,39 @@ const {
} = require('./errors')
const isLoopback = require('libp2p-utils/src/multiaddr/is-loopback')
const DEFAULT_TTL = 7200
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('./transport-manager')} TransportManager
* @typedef {import('./address-manager')} AddressManager
*/
/**
* @typedef {Object} NatManagerProperties
* @property {PeerId} peerId - The peer ID of the current node
* @property {TransportManager} transportManager - A transport manager
* @property {AddressManager} addressManager - An address manager
*
* @typedef {Object} NatManagerOptions
* @property {boolean} enabled - Whether to enable the NAT manager
* @property {string} [externalIp] - Pass a value to use instead of auto-detection
* @property {string} [description] - A string value to use for the port mapping description on the gateway
* @property {number} [ttl = DEFAULT_TTL] - How long UPnP port mappings should last for in seconds (minimum 1200)
* @property {boolean} [keepAlive] - Whether to automatically refresh UPnP port mappings when their TTL is reached
* @property {string} [gateway] - Pass a value to use instead of auto-detection
* @property {object} [pmp] - PMP options
* @property {boolean} [pmp.enabled] - Whether to enable PMP as well as UPnP
*/
function highPort (min = 1024, max = 65535) {
return Math.floor(Math.random() * (max - min + 1) + min)
}
const DEFAULT_TTL = 7200
class NatManager {
/**
* @class
* @param {object} options
* @param {PeerId} options.peerId - The peer ID of the current node
* @param {TransportManager} options.transportManager - A transport manager
* @param {AddressManager} options.addressManager - An address manager
* @param {boolean} options.enabled - Whether to enable the NAT manager
* @param {string} [options.externalIp] - Pass a value to use instead of auto-detection
* @param {string} [options.description] - A string value to use for the port mapping description on the gateway
* @param {number} [options.ttl] - How long UPnP port mappings should last for in seconds (minimum 1200)
* @param {boolean} [options.keepAlive] - Whether to automatically refresh UPnP port mappings when their TTL is reached
* @param {string} [options.gateway] - Pass a value to use instead of auto-detection
* @param {object} [options.pmp] - PMP options
* @param {boolean} [options.pmp.enabled] - Whether to enable PMP as well as UPnP
* @param {NatManagerProperties & NatManagerOptions} options
*/
constructor ({ peerId, addressManager, transportManager, ...options }) {
this._peerId = peerId
@ -89,15 +97,18 @@ class NatManager {
if (!addr.isThinWaistAddress() || transport !== 'tcp') {
// only bare tcp addresses
// eslint-disable-next-line no-continue
continue
}
if (isLoopback(addr)) {
// eslint-disable-next-line no-continue
continue
}
if (family !== 'ipv4') {
if (family !== 4) {
// ignore ipv6
// eslint-disable-next-line no-continue
continue
}
@ -119,9 +130,9 @@ class NatManager {
})
this._addressManager.addObservedAddr(Multiaddr.fromNodeAddress({
family: 'IPv4',
family: 4,
address: publicIp,
port: `${publicPort}`
port: publicPort
}, transport))
}
}
@ -133,11 +144,11 @@ class NatManager {
const client = new NatAPI(this._options)
/** @type {(...any) => any} */
/** @type {(...any: any) => any} */
const map = promisify(client.map.bind(client))
/** @type {(...any) => any} */
/** @type {(...any: any) => any} */
const destroy = promisify(client.destroy.bind(client))
/** @type {(...any) => any} */
/** @type {(...any: any) => any} */
const externalIp = promisify(client.externalIp.bind(client))
// these are all network operations so add a retry

View File

@ -19,12 +19,25 @@ const filter = require('it-filter')
const {
setDelayedInterval,
clearDelayedInterval
// @ts-ignore module with no types
} = require('set-delayed-interval')
const PeerId = require('peer-id')
/**
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('peer-id')} PeerId
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('libp2p-interfaces/src/peer-routing/types')} PeerRoutingModule
*/
/**
* @typedef {Object} RefreshManagerOptions
* @property {boolean} [enabled = true] - Whether to enable the Refresh manager
* @property {number} [bootDelay = 6e5] - Boot delay to start the Refresh Manager (in ms)
* @property {number} [interval = 10e3] - Interval between each Refresh Manager run (in ms)
*
* @typedef {Object} PeerRoutingOptions
* @property {RefreshManagerOptions} [refreshManager]
*/
class PeerRouting {
/**
* @class
@ -33,6 +46,7 @@ class PeerRouting {
constructor (libp2p) {
this._peerId = libp2p.peerId
this._peerStore = libp2p.peerStore
/** @type {PeerRoutingModule[]} */
this._routers = libp2p._modules.peerRouting || []
// If we have the dht, add it to the available peer routers
@ -95,6 +109,7 @@ class PeerRouting {
...this._routers.map(router => [router.findPeer(id, options)])
),
(source) => filter(source, Boolean),
// @ts-ignore findPeer resolves a Promise
(source) => storeAddresses(source, this._peerStore),
(source) => first(source)
)

View File

@ -6,7 +6,7 @@ const log = Object.assign(debug('libp2p:peer-store:address-book'), {
})
const errcode = require('err-code')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const Book = require('./book')
@ -18,7 +18,6 @@ const {
const Envelope = require('../record/envelope')
/**
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('./')} PeerStore
*/
@ -60,7 +59,7 @@ class AddressBook extends Book {
if (!data.addresses) {
return []
}
return data.addresses.map((address) => address.multiaddr)
return data.addresses.map((/** @type {Address} */ address) => address.multiaddr)
}
})
@ -295,9 +294,10 @@ class AddressBook extends Book {
}
// create Address for each address
/** @type {Address[]} */
const addresses = []
multiaddrs.forEach((addr) => {
if (!multiaddr.isMultiaddr(addr)) {
if (!Multiaddr.isMultiaddr(addr)) {
log.error(`multiaddr ${addr} must be an instance of multiaddr`)
throw errcode(new Error(`multiaddr ${addr} must be an instance of multiaddr`), ERR_INVALID_PARAMETERS)
}

View File

@ -7,6 +7,9 @@ const {
codes: { ERR_INVALID_PARAMETERS }
} = require('../errors')
/**
* @param {any} data
*/
const passthrough = data => data
/**

View File

@ -2,8 +2,6 @@
const errcode = require('err-code')
/** @typedef {import('../types').EventEmitterFactory} Events */
/** @type Events */
const EventEmitter = require('events')
const PeerId = require('peer-id')

View File

@ -81,6 +81,9 @@ class MetadataBook extends Book {
* Set data into the datastructure
*
* @override
* @param {PeerId} peerId
* @param {string} key
* @param {Uint8Array} value
*/
_setValue (peerId, key, value, { emit = true } = {}) {
const id = peerId.toB58String()

View File

@ -5,7 +5,7 @@ const log = Object.assign(debug('libp2p:persistent-peer-store'), {
error: debug('libp2p:persistent-peer-store:err')
})
const { Key } = require('interface-datastore')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const PeerStore = require('..')
@ -18,13 +18,18 @@ const {
NAMESPACE_PROTOCOL
} = require('./consts')
const Addresses = require('./pb/address-book.proto')
const Protocols = require('./pb/proto-book.proto')
const { Addresses } = require('./pb/address-book')
const { Protocols } = require('./pb/proto-book')
/**
* @typedef {import('interface-datastore').Batch} Batch
* @typedef {import('../address-book.js').Address} Address
*/
/**
* @typedef {Object} PersistentPeerStoreProperties
* @property {PeerId} peerId
* @property {any} datastore
* @property {import('interface-datastore').Datastore} datastore
*
* @typedef {Object} PersistentPeerStoreOptions
* @property {number} [threshold = 5] - Number of dirty peers allowed before commit data.
@ -214,7 +219,7 @@ class PersistentPeerStore extends PeerStore {
*
* @private
* @param {PeerId} peerId
* @param {Object} batch
* @param {Batch} batch
*/
_batchAddressBook (peerId, batch) {
const b32key = peerId.toString()
@ -234,11 +239,13 @@ class PersistentPeerStore extends PeerStore {
multiaddr: address.multiaddr.bytes,
isCertified: address.isCertified
})),
certified_record: entry.record ? {
certifiedRecord: entry.record
? {
seq: entry.record.seqNumber,
raw: entry.record.raw
} : undefined
})
}
: undefined
}).finish()
batch.put(key, encodedData)
} catch (err) {
@ -251,7 +258,7 @@ class PersistentPeerStore extends PeerStore {
*
* @private
* @param {PeerId} peerId
* @param {Object} batch
* @param {Batch} batch
*/
_batchKeyBook (peerId, batch) {
const b32key = peerId.toString()
@ -277,14 +284,14 @@ class PersistentPeerStore extends PeerStore {
*
* @private
* @param {PeerId} peerId
* @param {Object} batch
* @param {Batch} batch
*/
_batchMetadataBook (peerId, batch) {
const b32key = peerId.toString()
const dirtyMetada = this._dirtyMetadata.get(peerId.toB58String()) || []
try {
dirtyMetada.forEach((dirtyKey) => {
dirtyMetada.forEach((/** @type {string} */ dirtyKey) => {
const key = new Key(`${NAMESPACE_METADATA}${b32key}/${dirtyKey}`)
const dirtyValue = this.metadataBook.getValue(peerId, dirtyKey)
@ -304,7 +311,7 @@ class PersistentPeerStore extends PeerStore {
*
* @private
* @param {PeerId} peerId
* @param {Object} batch
* @param {Batch} batch
*/
_batchProtoBook (peerId, batch) {
const b32key = peerId.toString()
@ -319,7 +326,7 @@ class PersistentPeerStore extends PeerStore {
return
}
const encodedData = Protocols.encode({ protocols })
const encodedData = Protocols.encode({ protocols }).finish()
batch.put(key, encodedData)
} catch (err) {
@ -351,13 +358,15 @@ class PersistentPeerStore extends PeerStore {
peerId,
{
addresses: decoded.addrs.map((address) => ({
multiaddr: multiaddr(address.multiaddr),
multiaddr: new Multiaddr(address.multiaddr),
isCertified: Boolean(address.isCertified)
})),
record: decoded.certified_record ? {
raw: decoded.certified_record.raw,
seqNumber: decoded.certified_record.seq
} : undefined
record: decoded.certifiedRecord
? {
raw: decoded.certifiedRecord.raw,
seqNumber: decoded.certifiedRecord.seq
}
: undefined
},
{ emit: false })
break

View File

@ -0,0 +1,198 @@
import * as $protobuf from "protobufjs";
/** Properties of an Addresses. */
export interface IAddresses {
/** Addresses addrs */
addrs?: (Addresses.IAddress[]|null);
/** Addresses certifiedRecord */
certifiedRecord?: (Addresses.ICertifiedRecord|null);
}
/** Represents an Addresses. */
export class Addresses implements IAddresses {
/**
* Constructs a new Addresses.
* @param [p] Properties to set
*/
constructor(p?: IAddresses);
/** Addresses addrs. */
public addrs: Addresses.IAddress[];
/** Addresses certifiedRecord. */
public certifiedRecord?: (Addresses.ICertifiedRecord|null);
/**
* Encodes the specified Addresses message. Does not implicitly {@link Addresses.verify|verify} messages.
* @param m Addresses message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IAddresses, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes an Addresses message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Addresses
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Addresses;
/**
* Creates an Addresses message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Addresses
*/
public static fromObject(d: { [k: string]: any }): Addresses;
/**
* Creates a plain object from an Addresses message. Also converts values to other types if specified.
* @param m Addresses
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Addresses, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Addresses to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
export namespace Addresses {
/** Properties of an Address. */
interface IAddress {
/** Address multiaddr */
multiaddr?: (Uint8Array|null);
/** Address isCertified */
isCertified?: (boolean|null);
}
/** Represents an Address. */
class Address implements IAddress {
/**
* Constructs a new Address.
* @param [p] Properties to set
*/
constructor(p?: Addresses.IAddress);
/** Address multiaddr. */
public multiaddr: Uint8Array;
/** Address isCertified. */
public isCertified: boolean;
/**
* Encodes the specified Address message. Does not implicitly {@link Addresses.Address.verify|verify} messages.
* @param m Address message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: Addresses.IAddress, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes an Address message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Address
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Addresses.Address;
/**
* Creates an Address message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Address
*/
public static fromObject(d: { [k: string]: any }): Addresses.Address;
/**
* Creates a plain object from an Address message. Also converts values to other types if specified.
* @param m Address
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Addresses.Address, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Address to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
/** Properties of a CertifiedRecord. */
interface ICertifiedRecord {
/** CertifiedRecord seq */
seq?: (number|null);
/** CertifiedRecord raw */
raw?: (Uint8Array|null);
}
/** Represents a CertifiedRecord. */
class CertifiedRecord implements ICertifiedRecord {
/**
* Constructs a new CertifiedRecord.
* @param [p] Properties to set
*/
constructor(p?: Addresses.ICertifiedRecord);
/** CertifiedRecord seq. */
public seq: number;
/** CertifiedRecord raw. */
public raw: Uint8Array;
/**
* Encodes the specified CertifiedRecord message. Does not implicitly {@link Addresses.CertifiedRecord.verify|verify} messages.
* @param m CertifiedRecord message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: Addresses.ICertifiedRecord, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a CertifiedRecord message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns CertifiedRecord
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Addresses.CertifiedRecord;
/**
* Creates a CertifiedRecord message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns CertifiedRecord
*/
public static fromObject(d: { [k: string]: any }): Addresses.CertifiedRecord;
/**
* Creates a plain object from a CertifiedRecord message. Also converts values to other types if specified.
* @param m CertifiedRecord
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Addresses.CertifiedRecord, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this CertifiedRecord to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
}

View File

@ -0,0 +1,522 @@
/*eslint-disable*/
"use strict";
var $protobuf = require("protobufjs/minimal");
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.Addresses = (function() {
/**
* Properties of an Addresses.
* @exports IAddresses
* @interface IAddresses
* @property {Array.<Addresses.IAddress>|null} [addrs] Addresses addrs
* @property {Addresses.ICertifiedRecord|null} [certifiedRecord] Addresses certifiedRecord
*/
/**
* Constructs a new Addresses.
* @exports Addresses
* @classdesc Represents an Addresses.
* @implements IAddresses
* @constructor
* @param {IAddresses=} [p] Properties to set
*/
function Addresses(p) {
this.addrs = [];
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* Addresses addrs.
* @member {Array.<Addresses.IAddress>} addrs
* @memberof Addresses
* @instance
*/
Addresses.prototype.addrs = $util.emptyArray;
/**
* Addresses certifiedRecord.
* @member {Addresses.ICertifiedRecord|null|undefined} certifiedRecord
* @memberof Addresses
* @instance
*/
Addresses.prototype.certifiedRecord = null;
/**
* Encodes the specified Addresses message. Does not implicitly {@link Addresses.verify|verify} messages.
* @function encode
* @memberof Addresses
* @static
* @param {IAddresses} m Addresses message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Addresses.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.addrs != null && m.addrs.length) {
for (var i = 0; i < m.addrs.length; ++i)
$root.Addresses.Address.encode(m.addrs[i], w.uint32(10).fork()).ldelim();
}
if (m.certifiedRecord != null && Object.hasOwnProperty.call(m, "certifiedRecord"))
$root.Addresses.CertifiedRecord.encode(m.certifiedRecord, w.uint32(18).fork()).ldelim();
return w;
};
/**
* Decodes an Addresses message from the specified reader or buffer.
* @function decode
* @memberof Addresses
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Addresses} Addresses
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Addresses.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Addresses();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
if (!(m.addrs && m.addrs.length))
m.addrs = [];
m.addrs.push($root.Addresses.Address.decode(r, r.uint32()));
break;
case 2:
m.certifiedRecord = $root.Addresses.CertifiedRecord.decode(r, r.uint32());
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates an Addresses message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Addresses
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Addresses} Addresses
*/
Addresses.fromObject = function fromObject(d) {
if (d instanceof $root.Addresses)
return d;
var m = new $root.Addresses();
if (d.addrs) {
if (!Array.isArray(d.addrs))
throw TypeError(".Addresses.addrs: array expected");
m.addrs = [];
for (var i = 0; i < d.addrs.length; ++i) {
if (typeof d.addrs[i] !== "object")
throw TypeError(".Addresses.addrs: object expected");
m.addrs[i] = $root.Addresses.Address.fromObject(d.addrs[i]);
}
}
if (d.certifiedRecord != null) {
if (typeof d.certifiedRecord !== "object")
throw TypeError(".Addresses.certifiedRecord: object expected");
m.certifiedRecord = $root.Addresses.CertifiedRecord.fromObject(d.certifiedRecord);
}
return m;
};
/**
* Creates a plain object from an Addresses message. Also converts values to other types if specified.
* @function toObject
* @memberof Addresses
* @static
* @param {Addresses} m Addresses
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Addresses.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.arrays || o.defaults) {
d.addrs = [];
}
if (o.defaults) {
d.certifiedRecord = null;
}
if (m.addrs && m.addrs.length) {
d.addrs = [];
for (var j = 0; j < m.addrs.length; ++j) {
d.addrs[j] = $root.Addresses.Address.toObject(m.addrs[j], o);
}
}
if (m.certifiedRecord != null && m.hasOwnProperty("certifiedRecord")) {
d.certifiedRecord = $root.Addresses.CertifiedRecord.toObject(m.certifiedRecord, o);
}
return d;
};
/**
* Converts this Addresses to JSON.
* @function toJSON
* @memberof Addresses
* @instance
* @returns {Object.<string,*>} JSON object
*/
Addresses.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
Addresses.Address = (function() {
/**
* Properties of an Address.
* @memberof Addresses
* @interface IAddress
* @property {Uint8Array|null} [multiaddr] Address multiaddr
* @property {boolean|null} [isCertified] Address isCertified
*/
/**
* Constructs a new Address.
* @memberof Addresses
* @classdesc Represents an Address.
* @implements IAddress
* @constructor
* @param {Addresses.IAddress=} [p] Properties to set
*/
function Address(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* Address multiaddr.
* @member {Uint8Array} multiaddr
* @memberof Addresses.Address
* @instance
*/
Address.prototype.multiaddr = $util.newBuffer([]);
/**
* Address isCertified.
* @member {boolean} isCertified
* @memberof Addresses.Address
* @instance
*/
Address.prototype.isCertified = false;
/**
* Encodes the specified Address message. Does not implicitly {@link Addresses.Address.verify|verify} messages.
* @function encode
* @memberof Addresses.Address
* @static
* @param {Addresses.IAddress} m Address message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Address.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.multiaddr != null && Object.hasOwnProperty.call(m, "multiaddr"))
w.uint32(10).bytes(m.multiaddr);
if (m.isCertified != null && Object.hasOwnProperty.call(m, "isCertified"))
w.uint32(16).bool(m.isCertified);
return w;
};
/**
* Decodes an Address message from the specified reader or buffer.
* @function decode
* @memberof Addresses.Address
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Addresses.Address} Address
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Address.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Addresses.Address();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.multiaddr = r.bytes();
break;
case 2:
m.isCertified = r.bool();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates an Address message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Addresses.Address
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Addresses.Address} Address
*/
Address.fromObject = function fromObject(d) {
if (d instanceof $root.Addresses.Address)
return d;
var m = new $root.Addresses.Address();
if (d.multiaddr != null) {
if (typeof d.multiaddr === "string")
$util.base64.decode(d.multiaddr, m.multiaddr = $util.newBuffer($util.base64.length(d.multiaddr)), 0);
else if (d.multiaddr.length)
m.multiaddr = d.multiaddr;
}
if (d.isCertified != null) {
m.isCertified = Boolean(d.isCertified);
}
return m;
};
/**
* Creates a plain object from an Address message. Also converts values to other types if specified.
* @function toObject
* @memberof Addresses.Address
* @static
* @param {Addresses.Address} m Address
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Address.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
if (o.bytes === String)
d.multiaddr = "";
else {
d.multiaddr = [];
if (o.bytes !== Array)
d.multiaddr = $util.newBuffer(d.multiaddr);
}
d.isCertified = false;
}
if (m.multiaddr != null && m.hasOwnProperty("multiaddr")) {
d.multiaddr = o.bytes === String ? $util.base64.encode(m.multiaddr, 0, m.multiaddr.length) : o.bytes === Array ? Array.prototype.slice.call(m.multiaddr) : m.multiaddr;
}
if (m.isCertified != null && m.hasOwnProperty("isCertified")) {
d.isCertified = m.isCertified;
}
return d;
};
/**
* Converts this Address to JSON.
* @function toJSON
* @memberof Addresses.Address
* @instance
* @returns {Object.<string,*>} JSON object
*/
Address.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return Address;
})();
Addresses.CertifiedRecord = (function() {
/**
* Properties of a CertifiedRecord.
* @memberof Addresses
* @interface ICertifiedRecord
* @property {number|null} [seq] CertifiedRecord seq
* @property {Uint8Array|null} [raw] CertifiedRecord raw
*/
/**
* Constructs a new CertifiedRecord.
* @memberof Addresses
* @classdesc Represents a CertifiedRecord.
* @implements ICertifiedRecord
* @constructor
* @param {Addresses.ICertifiedRecord=} [p] Properties to set
*/
function CertifiedRecord(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* CertifiedRecord seq.
* @member {number} seq
* @memberof Addresses.CertifiedRecord
* @instance
*/
CertifiedRecord.prototype.seq = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
/**
* CertifiedRecord raw.
* @member {Uint8Array} raw
* @memberof Addresses.CertifiedRecord
* @instance
*/
CertifiedRecord.prototype.raw = $util.newBuffer([]);
/**
* Encodes the specified CertifiedRecord message. Does not implicitly {@link Addresses.CertifiedRecord.verify|verify} messages.
* @function encode
* @memberof Addresses.CertifiedRecord
* @static
* @param {Addresses.ICertifiedRecord} m CertifiedRecord message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
CertifiedRecord.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.seq != null && Object.hasOwnProperty.call(m, "seq"))
w.uint32(8).uint64(m.seq);
if (m.raw != null && Object.hasOwnProperty.call(m, "raw"))
w.uint32(18).bytes(m.raw);
return w;
};
/**
* Decodes a CertifiedRecord message from the specified reader or buffer.
* @function decode
* @memberof Addresses.CertifiedRecord
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Addresses.CertifiedRecord} CertifiedRecord
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
CertifiedRecord.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Addresses.CertifiedRecord();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.seq = r.uint64();
break;
case 2:
m.raw = r.bytes();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates a CertifiedRecord message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Addresses.CertifiedRecord
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Addresses.CertifiedRecord} CertifiedRecord
*/
CertifiedRecord.fromObject = function fromObject(d) {
if (d instanceof $root.Addresses.CertifiedRecord)
return d;
var m = new $root.Addresses.CertifiedRecord();
if (d.seq != null) {
if ($util.Long)
(m.seq = $util.Long.fromValue(d.seq)).unsigned = true;
else if (typeof d.seq === "string")
m.seq = parseInt(d.seq, 10);
else if (typeof d.seq === "number")
m.seq = d.seq;
else if (typeof d.seq === "object")
m.seq = new $util.LongBits(d.seq.low >>> 0, d.seq.high >>> 0).toNumber(true);
}
if (d.raw != null) {
if (typeof d.raw === "string")
$util.base64.decode(d.raw, m.raw = $util.newBuffer($util.base64.length(d.raw)), 0);
else if (d.raw.length)
m.raw = d.raw;
}
return m;
};
/**
* Creates a plain object from a CertifiedRecord message. Also converts values to other types if specified.
* @function toObject
* @memberof Addresses.CertifiedRecord
* @static
* @param {Addresses.CertifiedRecord} m CertifiedRecord
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
CertifiedRecord.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
if ($util.Long) {
var n = new $util.Long(0, 0, true);
d.seq = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n;
} else
d.seq = o.longs === String ? "0" : 0;
if (o.bytes === String)
d.raw = "";
else {
d.raw = [];
if (o.bytes !== Array)
d.raw = $util.newBuffer(d.raw);
}
}
if (m.seq != null && m.hasOwnProperty("seq")) {
if (typeof m.seq === "number")
d.seq = o.longs === String ? String(m.seq) : m.seq;
else
d.seq = o.longs === String ? $util.Long.prototype.toString.call(m.seq) : o.longs === Number ? new $util.LongBits(m.seq.low >>> 0, m.seq.high >>> 0).toNumber(true) : m.seq;
}
if (m.raw != null && m.hasOwnProperty("raw")) {
d.raw = o.bytes === String ? $util.base64.encode(m.raw, 0, m.raw.length) : o.bytes === Array ? Array.prototype.slice.call(m.raw) : m.raw;
}
return d;
};
/**
* Converts this CertifiedRecord to JSON.
* @function toJSON
* @memberof Addresses.CertifiedRecord
* @instance
* @returns {Object.<string,*>} JSON object
*/
CertifiedRecord.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return CertifiedRecord;
})();
return Addresses;
})();
module.exports = $root;

View File

@ -1,12 +1,9 @@
'use strict'
syntax = "proto3";
const protons = require('protons')
const message = `
message Addresses {
// Address represents a single multiaddr.
message Address {
required bytes multiaddr = 1;
bytes multiaddr = 1;
// Flag to indicate if the address comes from a certified source.
optional bool isCertified = 2;
@ -28,6 +25,3 @@ message Addresses {
// The most recently received signed PeerRecord.
CertifiedRecord certified_record = 2;
}
`
module.exports = protons(message).Addresses

View File

@ -0,0 +1,59 @@
import * as $protobuf from "protobufjs";
/** Properties of a Protocols. */
export interface IProtocols {
/** Protocols protocols */
protocols?: (string[]|null);
}
/** Represents a Protocols. */
export class Protocols implements IProtocols {
/**
* Constructs a new Protocols.
* @param [p] Properties to set
*/
constructor(p?: IProtocols);
/** Protocols protocols. */
public protocols: string[];
/**
* Encodes the specified Protocols message. Does not implicitly {@link Protocols.verify|verify} messages.
* @param m Protocols message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IProtocols, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a Protocols message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Protocols
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Protocols;
/**
* Creates a Protocols message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Protocols
*/
public static fromObject(d: { [k: string]: any }): Protocols;
/**
* Creates a plain object from a Protocols message. Also converts values to other types if specified.
* @param m Protocols
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Protocols, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Protocols to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}

View File

@ -0,0 +1,157 @@
/*eslint-disable*/
"use strict";
var $protobuf = require("protobufjs/minimal");
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.Protocols = (function() {
/**
* Properties of a Protocols.
* @exports IProtocols
* @interface IProtocols
* @property {Array.<string>|null} [protocols] Protocols protocols
*/
/**
* Constructs a new Protocols.
* @exports Protocols
* @classdesc Represents a Protocols.
* @implements IProtocols
* @constructor
* @param {IProtocols=} [p] Properties to set
*/
function Protocols(p) {
this.protocols = [];
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* Protocols protocols.
* @member {Array.<string>} protocols
* @memberof Protocols
* @instance
*/
Protocols.prototype.protocols = $util.emptyArray;
/**
* Encodes the specified Protocols message. Does not implicitly {@link Protocols.verify|verify} messages.
* @function encode
* @memberof Protocols
* @static
* @param {IProtocols} m Protocols message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Protocols.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.protocols != null && m.protocols.length) {
for (var i = 0; i < m.protocols.length; ++i)
w.uint32(10).string(m.protocols[i]);
}
return w;
};
/**
* Decodes a Protocols message from the specified reader or buffer.
* @function decode
* @memberof Protocols
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Protocols} Protocols
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Protocols.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Protocols();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
if (!(m.protocols && m.protocols.length))
m.protocols = [];
m.protocols.push(r.string());
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates a Protocols message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Protocols
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Protocols} Protocols
*/
Protocols.fromObject = function fromObject(d) {
if (d instanceof $root.Protocols)
return d;
var m = new $root.Protocols();
if (d.protocols) {
if (!Array.isArray(d.protocols))
throw TypeError(".Protocols.protocols: array expected");
m.protocols = [];
for (var i = 0; i < d.protocols.length; ++i) {
m.protocols[i] = String(d.protocols[i]);
}
}
return m;
};
/**
* Creates a plain object from a Protocols message. Also converts values to other types if specified.
* @function toObject
* @memberof Protocols
* @static
* @param {Protocols} m Protocols
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Protocols.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.arrays || o.defaults) {
d.protocols = [];
}
if (m.protocols && m.protocols.length) {
d.protocols = [];
for (var j = 0; j < m.protocols.length; ++j) {
d.protocols[j] = m.protocols[j];
}
}
return d;
};
/**
* Converts this Protocols to JSON.
* @function toJSON
* @memberof Protocols
* @instance
* @returns {Object.<string,*>} JSON object
*/
Protocols.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return Protocols;
})();
module.exports = $root;

View File

@ -0,0 +1,5 @@
syntax = "proto3";
message Protocols {
repeated string protocols = 1;
}

View File

@ -1,12 +0,0 @@
'use strict'
const protons = require('protons')
/* eslint-disable no-tabs */
const message = `
message Protocols {
repeated string protocols = 1;
}
`
module.exports = protons(message).Protocols

View File

@ -74,6 +74,10 @@ class ProtoBook extends Book {
const recSet = this.data.get(id)
const newSet = new Set(protocols)
/**
* @param {Set<string>} a
* @param {Set<string>} b
*/
const isSetEqual = (a, b) => a.size === b.size && [...a].every(value => b.has(value))
// Already knows the peer and the recorded protocols are the same?

View File

@ -8,6 +8,7 @@ const errCode = require('err-code')
const crypto = require('libp2p-crypto')
const { pipe } = require('it-pipe')
// @ts-ignore it-buffer has no types exported
const { toBuffer } = require('it-buffer')
const { collect, take } = require('streaming-iterables')
const equals = require('uint8arrays/equals')
@ -16,8 +17,9 @@ const { PROTOCOL, PING_LENGTH } = require('./constants')
/**
* @typedef {import('../')} Libp2p
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('peer-id')} PeerId
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
*/
/**
@ -31,7 +33,8 @@ async function ping (node, peer) {
// @ts-ignore multiaddr might not have toB58String
log('dialing %s to %s', PROTOCOL, peer.toB58String ? peer.toB58String() : peer)
const { stream } = await node.dialProtocol(peer, PROTOCOL)
const connection = await node.dial(peer)
const { stream } = await connection.newStream(PROTOCOL)
const start = Date.now()
const data = crypto.randomBytes(PING_LENGTH)
@ -39,7 +42,7 @@ async function ping (node, peer) {
const [result] = await pipe(
[data],
stream,
stream => take(1, stream),
(/** @type {MuxedStream} */ stream) => take(1, stream),
toBuffer,
collect
)

View File

@ -3,11 +3,16 @@
const crypto = require('libp2p-crypto')
const constants = require('./constants')
exports = module.exports
exports.rnd = (length) => {
/**
* @param {number} length
*/
function rnd (length) {
if (!length) {
length = constants.PING_LENGTH
}
return crypto.randomBytes(length)
}
module.exports = {
rnd
}

View File

@ -7,6 +7,7 @@ const log = Object.assign(debug('libp2p:pnet'), {
})
const Errors = require('./errors')
// @ts-ignore xsalsa20 has no types exported
const xsalsa20 = require('xsalsa20')
const KEY_LENGTH = require('./key-generator').KEY_LENGTH
const uint8ArrayFromString = require('uint8arrays/from-string')
@ -21,7 +22,8 @@ const uint8ArrayToString = require('uint8arrays/to-string')
*/
module.exports.createBoxStream = (nonce, psk) => {
const xor = xsalsa20(nonce, psk)
return (source) => (async function * () {
return (/** @type {AsyncIterable<Uint8Array>} */ source) => (async function * () {
for await (const chunk of source) {
yield Uint8Array.from(xor.update(chunk.slice()))
}
@ -36,7 +38,7 @@ module.exports.createBoxStream = (nonce, psk) => {
* @returns {*} a through iterable
*/
module.exports.createUnboxStream = (nonce, psk) => {
return (source) => (async function * () {
return (/** @type {AsyncIterable<Uint8Array>} */ source) => (async function * () {
const xor = xsalsa20(nonce, psk)
log.trace('Decryption enabled')
@ -51,7 +53,7 @@ module.exports.createUnboxStream = (nonce, psk) => {
*
* @param {Uint8Array} pskBuffer
* @throws {INVALID_PSK}
* @returns {Object} The PSK metadata (tag, codecName, psk)
* @returns {{ tag?: string, codecName?: string, psk: Uint8Array }} The PSK metadata (tag, codecName, psk)
*/
module.exports.decodeV1PSK = (pskBuffer) => {
try {

View File

@ -6,6 +6,7 @@ const log = Object.assign(debug('libp2p:pnet'), {
})
const { pipe } = require('it-pipe')
const errcode = require('err-code')
// @ts-ignore it-pair has no types exported
const duplexPair = require('it-pair/duplex')
const crypto = require('libp2p-crypto')
const Errors = require('./errors')
@ -17,6 +18,7 @@ const {
createUnboxStream,
decodeV1PSK
} = require('./crypto')
// @ts-ignore it-handshake has no types exported
const handshake = require('it-handshake')
const { NONCE_LENGTH } = require('./key-generator')

View File

@ -22,8 +22,12 @@ module.exports = generate
module.exports.NONCE_LENGTH = 24
module.exports.KEY_LENGTH = KEY_LENGTH
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
if (require.main === module) {
try {
// @ts-ignore This condition will always return 'false' since the types 'Module | undefined'
if (require.main === module) {
// @ts-ignore
generate(process.stdout)
}
} catch (error) {
}

View File

@ -1,12 +1,18 @@
'use strict'
// Pubsub adapter to keep API with handlers while not removed.
/**
* @typedef {import('libp2p-interfaces/src/pubsub').InMessage} InMessage
* @typedef {import('libp2p-interfaces/src/pubsub')} PubsubRouter
*/
// Pubsub adapter to keep API with handlers while not removed.
/**
* @param {import("libp2p-interfaces/src/pubsub")} PubsubRouter
* @param {import('.')} libp2p
* @param {{ enabled: boolean; } & import(".").PubsubLocalOptions & import("libp2p-interfaces/src/pubsub").PubsubOptions} options
*/
function pubsubAdapter (PubsubRouter, libp2p, options) {
// @ts-ignore Pubsub constructor type not defined
const pubsub = new PubsubRouter(libp2p, options)
pubsub._subscribeAdapter = pubsub.subscribe
pubsub._unsubscribeAdapter = pubsub.unsubscribe

77
src/record/envelope/envelope.d.ts vendored Normal file
View File

@ -0,0 +1,77 @@
import * as $protobuf from "protobufjs";
/** Properties of an Envelope. */
export interface IEnvelope {
/** Envelope publicKey */
publicKey?: (Uint8Array|null);
/** Envelope payloadType */
payloadType?: (Uint8Array|null);
/** Envelope payload */
payload?: (Uint8Array|null);
/** Envelope signature */
signature?: (Uint8Array|null);
}
/** Represents an Envelope. */
export class Envelope implements IEnvelope {
/**
* Constructs a new Envelope.
* @param [p] Properties to set
*/
constructor(p?: IEnvelope);
/** Envelope publicKey. */
public publicKey: Uint8Array;
/** Envelope payloadType. */
public payloadType: Uint8Array;
/** Envelope payload. */
public payload: Uint8Array;
/** Envelope signature. */
public signature: Uint8Array;
/**
* Encodes the specified Envelope message. Does not implicitly {@link Envelope.verify|verify} messages.
* @param m Envelope message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IEnvelope, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes an Envelope message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns Envelope
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): Envelope;
/**
* Creates an Envelope message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns Envelope
*/
public static fromObject(d: { [k: string]: any }): Envelope;
/**
* Creates a plain object from an Envelope message. Also converts values to other types if specified.
* @param m Envelope
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: Envelope, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this Envelope to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}

View File

@ -0,0 +1,243 @@
/*eslint-disable*/
"use strict";
var $protobuf = require("protobufjs/minimal");
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.Envelope = (function() {
/**
* Properties of an Envelope.
* @exports IEnvelope
* @interface IEnvelope
* @property {Uint8Array|null} [publicKey] Envelope publicKey
* @property {Uint8Array|null} [payloadType] Envelope payloadType
* @property {Uint8Array|null} [payload] Envelope payload
* @property {Uint8Array|null} [signature] Envelope signature
*/
/**
* Constructs a new Envelope.
* @exports Envelope
* @classdesc Represents an Envelope.
* @implements IEnvelope
* @constructor
* @param {IEnvelope=} [p] Properties to set
*/
function Envelope(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* Envelope publicKey.
* @member {Uint8Array} publicKey
* @memberof Envelope
* @instance
*/
Envelope.prototype.publicKey = $util.newBuffer([]);
/**
* Envelope payloadType.
* @member {Uint8Array} payloadType
* @memberof Envelope
* @instance
*/
Envelope.prototype.payloadType = $util.newBuffer([]);
/**
* Envelope payload.
* @member {Uint8Array} payload
* @memberof Envelope
* @instance
*/
Envelope.prototype.payload = $util.newBuffer([]);
/**
* Envelope signature.
* @member {Uint8Array} signature
* @memberof Envelope
* @instance
*/
Envelope.prototype.signature = $util.newBuffer([]);
/**
* Encodes the specified Envelope message. Does not implicitly {@link Envelope.verify|verify} messages.
* @function encode
* @memberof Envelope
* @static
* @param {IEnvelope} m Envelope message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
Envelope.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.publicKey != null && Object.hasOwnProperty.call(m, "publicKey"))
w.uint32(10).bytes(m.publicKey);
if (m.payloadType != null && Object.hasOwnProperty.call(m, "payloadType"))
w.uint32(18).bytes(m.payloadType);
if (m.payload != null && Object.hasOwnProperty.call(m, "payload"))
w.uint32(26).bytes(m.payload);
if (m.signature != null && Object.hasOwnProperty.call(m, "signature"))
w.uint32(42).bytes(m.signature);
return w;
};
/**
* Decodes an Envelope message from the specified reader or buffer.
* @function decode
* @memberof Envelope
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {Envelope} Envelope
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
Envelope.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.Envelope();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.publicKey = r.bytes();
break;
case 2:
m.payloadType = r.bytes();
break;
case 3:
m.payload = r.bytes();
break;
case 5:
m.signature = r.bytes();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates an Envelope message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof Envelope
* @static
* @param {Object.<string,*>} d Plain object
* @returns {Envelope} Envelope
*/
Envelope.fromObject = function fromObject(d) {
if (d instanceof $root.Envelope)
return d;
var m = new $root.Envelope();
if (d.publicKey != null) {
if (typeof d.publicKey === "string")
$util.base64.decode(d.publicKey, m.publicKey = $util.newBuffer($util.base64.length(d.publicKey)), 0);
else if (d.publicKey.length)
m.publicKey = d.publicKey;
}
if (d.payloadType != null) {
if (typeof d.payloadType === "string")
$util.base64.decode(d.payloadType, m.payloadType = $util.newBuffer($util.base64.length(d.payloadType)), 0);
else if (d.payloadType.length)
m.payloadType = d.payloadType;
}
if (d.payload != null) {
if (typeof d.payload === "string")
$util.base64.decode(d.payload, m.payload = $util.newBuffer($util.base64.length(d.payload)), 0);
else if (d.payload.length)
m.payload = d.payload;
}
if (d.signature != null) {
if (typeof d.signature === "string")
$util.base64.decode(d.signature, m.signature = $util.newBuffer($util.base64.length(d.signature)), 0);
else if (d.signature.length)
m.signature = d.signature;
}
return m;
};
/**
* Creates a plain object from an Envelope message. Also converts values to other types if specified.
* @function toObject
* @memberof Envelope
* @static
* @param {Envelope} m Envelope
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
Envelope.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
if (o.bytes === String)
d.publicKey = "";
else {
d.publicKey = [];
if (o.bytes !== Array)
d.publicKey = $util.newBuffer(d.publicKey);
}
if (o.bytes === String)
d.payloadType = "";
else {
d.payloadType = [];
if (o.bytes !== Array)
d.payloadType = $util.newBuffer(d.payloadType);
}
if (o.bytes === String)
d.payload = "";
else {
d.payload = [];
if (o.bytes !== Array)
d.payload = $util.newBuffer(d.payload);
}
if (o.bytes === String)
d.signature = "";
else {
d.signature = [];
if (o.bytes !== Array)
d.signature = $util.newBuffer(d.signature);
}
}
if (m.publicKey != null && m.hasOwnProperty("publicKey")) {
d.publicKey = o.bytes === String ? $util.base64.encode(m.publicKey, 0, m.publicKey.length) : o.bytes === Array ? Array.prototype.slice.call(m.publicKey) : m.publicKey;
}
if (m.payloadType != null && m.hasOwnProperty("payloadType")) {
d.payloadType = o.bytes === String ? $util.base64.encode(m.payloadType, 0, m.payloadType.length) : o.bytes === Array ? Array.prototype.slice.call(m.payloadType) : m.payloadType;
}
if (m.payload != null && m.hasOwnProperty("payload")) {
d.payload = o.bytes === String ? $util.base64.encode(m.payload, 0, m.payload.length) : o.bytes === Array ? Array.prototype.slice.call(m.payload) : m.payload;
}
if (m.signature != null && m.hasOwnProperty("signature")) {
d.signature = o.bytes === String ? $util.base64.encode(m.signature, 0, m.signature.length) : o.bytes === Array ? Array.prototype.slice.call(m.signature) : m.signature;
}
return d;
};
/**
* Converts this Envelope to JSON.
* @function toJSON
* @memberof Envelope
* @instance
* @returns {Object.<string,*>} JSON object
*/
Envelope.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return Envelope;
})();
module.exports = $root;

View File

@ -1,9 +1,5 @@
'use strict'
syntax = "proto3";
const protons = require('protons')
/** @type {{Envelope: import('../../types').MessageProto}} */
module.exports = protons(`
message Envelope {
// public_key is the public key of the keypair the enclosed payload was
// signed with.
@ -21,4 +17,3 @@ message Envelope {
// additional security.
bytes signature = 5;
}
`)

View File

@ -3,13 +3,14 @@
const errCode = require('err-code')
const uint8arraysConcat = require('uint8arrays/concat')
const uint8arraysFromString = require('uint8arrays/from-string')
// @ts-ignore libp2p-crypto does not support types
const cryptoKeys = require('libp2p-crypto/src/keys')
const PeerId = require('peer-id')
const varint = require('varint')
const uint8arraysEquals = require('uint8arrays/equals')
const { codes } = require('../../errors')
const Protobuf = require('./envelope.proto')
const { Envelope: Protobuf } = require('./envelope')
/**
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
@ -49,12 +50,12 @@ class Envelope {
const publicKey = cryptoKeys.marshalPublicKey(this.peerId.pubKey)
this._marshal = Protobuf.Envelope.encode({
public_key: publicKey,
payload_type: this.payloadType,
this._marshal = Protobuf.encode({
publicKey: publicKey,
payloadType: this.payloadType,
payload: this.payload,
signature: this.signature
})
}).finish()
return this._marshal
}
@ -124,12 +125,12 @@ const formatSignaturePayload = (domain, payloadType, payload) => {
* @returns {Promise<Envelope>}
*/
Envelope.createFromProtobuf = async (data) => {
const envelopeData = Protobuf.Envelope.decode(data)
const peerId = await PeerId.createFromPubKey(envelopeData.public_key)
const envelopeData = Protobuf.decode(data)
const peerId = await PeerId.createFromPubKey(envelopeData.publicKey)
return new Envelope({
peerId,
payloadType: envelopeData.payload_type,
payloadType: envelopeData.payloadType,
payload: envelopeData.payload,
signature: envelopeData.signature
})

View File

@ -1,18 +1,17 @@
'use strict'
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const arrayEquals = require('libp2p-utils/src/array-equals')
const Protobuf = require('./peer-record.proto')
const { PeerRecord: Protobuf } = require('./peer-record')
const {
ENVELOPE_DOMAIN_PEER_RECORD,
ENVELOPE_PAYLOAD_TYPE_PEER_RECORD
} = require('./consts')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('../../peer-store/address-book.js').Address} Address
* @typedef {import('libp2p-interfaces/src/record/types').Record} Record
*/
@ -52,13 +51,13 @@ class PeerRecord {
return this._marshal
}
this._marshal = Protobuf.PeerRecord.encode({
peer_id: this.peerId.toBytes(),
this._marshal = Protobuf.encode({
peerId: this.peerId.toBytes(),
seq: this.seqNumber,
addresses: this.multiaddrs.map((m) => ({
multiaddr: m.bytes
}))
})
}).finish()
return this._marshal
}
@ -100,12 +99,11 @@ class PeerRecord {
* @returns {PeerRecord}
*/
PeerRecord.createFromProtobuf = (buf) => {
// Decode
const peerRecord = Protobuf.PeerRecord.decode(buf)
const peerRecord = Protobuf.decode(buf)
const peerId = PeerId.createFromBytes(peerRecord.peer_id)
const multiaddrs = (peerRecord.addresses || []).map((a) => multiaddr(a.multiaddr))
const seqNumber = peerRecord.seq
const peerId = PeerId.createFromBytes(peerRecord.peerId)
const multiaddrs = (peerRecord.addresses || []).map((a) => new Multiaddr(a.multiaddr))
const seqNumber = Number(peerRecord.seq)
return new PeerRecord({ peerId, multiaddrs, seqNumber })
}

133
src/record/peer-record/peer-record.d.ts vendored Normal file
View File

@ -0,0 +1,133 @@
import * as $protobuf from "protobufjs";
/** Properties of a PeerRecord. */
export interface IPeerRecord {
/** PeerRecord peerId */
peerId?: (Uint8Array|null);
/** PeerRecord seq */
seq?: (number|null);
/** PeerRecord addresses */
addresses?: (PeerRecord.IAddressInfo[]|null);
}
/** Represents a PeerRecord. */
export class PeerRecord implements IPeerRecord {
/**
* Constructs a new PeerRecord.
* @param [p] Properties to set
*/
constructor(p?: IPeerRecord);
/** PeerRecord peerId. */
public peerId: Uint8Array;
/** PeerRecord seq. */
public seq: number;
/** PeerRecord addresses. */
public addresses: PeerRecord.IAddressInfo[];
/**
* Encodes the specified PeerRecord message. Does not implicitly {@link PeerRecord.verify|verify} messages.
* @param m PeerRecord message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: IPeerRecord, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes a PeerRecord message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns PeerRecord
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): PeerRecord;
/**
* Creates a PeerRecord message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns PeerRecord
*/
public static fromObject(d: { [k: string]: any }): PeerRecord;
/**
* Creates a plain object from a PeerRecord message. Also converts values to other types if specified.
* @param m PeerRecord
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: PeerRecord, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this PeerRecord to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
export namespace PeerRecord {
/** Properties of an AddressInfo. */
interface IAddressInfo {
/** AddressInfo multiaddr */
multiaddr?: (Uint8Array|null);
}
/** Represents an AddressInfo. */
class AddressInfo implements IAddressInfo {
/**
* Constructs a new AddressInfo.
* @param [p] Properties to set
*/
constructor(p?: PeerRecord.IAddressInfo);
/** AddressInfo multiaddr. */
public multiaddr: Uint8Array;
/**
* Encodes the specified AddressInfo message. Does not implicitly {@link PeerRecord.AddressInfo.verify|verify} messages.
* @param m AddressInfo message or plain object to encode
* @param [w] Writer to encode to
* @returns Writer
*/
public static encode(m: PeerRecord.IAddressInfo, w?: $protobuf.Writer): $protobuf.Writer;
/**
* Decodes an AddressInfo message from the specified reader or buffer.
* @param r Reader or buffer to decode from
* @param [l] Message length if known beforehand
* @returns AddressInfo
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
public static decode(r: ($protobuf.Reader|Uint8Array), l?: number): PeerRecord.AddressInfo;
/**
* Creates an AddressInfo message from a plain object. Also converts values to their respective internal types.
* @param d Plain object
* @returns AddressInfo
*/
public static fromObject(d: { [k: string]: any }): PeerRecord.AddressInfo;
/**
* Creates a plain object from an AddressInfo message. Also converts values to other types if specified.
* @param m AddressInfo
* @param [o] Conversion options
* @returns Plain object
*/
public static toObject(m: PeerRecord.AddressInfo, o?: $protobuf.IConversionOptions): { [k: string]: any };
/**
* Converts this AddressInfo to JSON.
* @returns JSON object
*/
public toJSON(): { [k: string]: any };
}
}

View File

@ -0,0 +1,367 @@
/*eslint-disable*/
"use strict";
var $protobuf = require("protobufjs/minimal");
// Common aliases
var $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;
// Exported root namespace
var $root = $protobuf.roots["default"] || ($protobuf.roots["default"] = {});
$root.PeerRecord = (function() {
/**
* Properties of a PeerRecord.
* @exports IPeerRecord
* @interface IPeerRecord
* @property {Uint8Array|null} [peerId] PeerRecord peerId
* @property {number|null} [seq] PeerRecord seq
* @property {Array.<PeerRecord.IAddressInfo>|null} [addresses] PeerRecord addresses
*/
/**
* Constructs a new PeerRecord.
* @exports PeerRecord
* @classdesc Represents a PeerRecord.
* @implements IPeerRecord
* @constructor
* @param {IPeerRecord=} [p] Properties to set
*/
function PeerRecord(p) {
this.addresses = [];
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* PeerRecord peerId.
* @member {Uint8Array} peerId
* @memberof PeerRecord
* @instance
*/
PeerRecord.prototype.peerId = $util.newBuffer([]);
/**
* PeerRecord seq.
* @member {number} seq
* @memberof PeerRecord
* @instance
*/
PeerRecord.prototype.seq = $util.Long ? $util.Long.fromBits(0,0,true) : 0;
/**
* PeerRecord addresses.
* @member {Array.<PeerRecord.IAddressInfo>} addresses
* @memberof PeerRecord
* @instance
*/
PeerRecord.prototype.addresses = $util.emptyArray;
/**
* Encodes the specified PeerRecord message. Does not implicitly {@link PeerRecord.verify|verify} messages.
* @function encode
* @memberof PeerRecord
* @static
* @param {IPeerRecord} m PeerRecord message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
PeerRecord.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.peerId != null && Object.hasOwnProperty.call(m, "peerId"))
w.uint32(10).bytes(m.peerId);
if (m.seq != null && Object.hasOwnProperty.call(m, "seq"))
w.uint32(16).uint64(m.seq);
if (m.addresses != null && m.addresses.length) {
for (var i = 0; i < m.addresses.length; ++i)
$root.PeerRecord.AddressInfo.encode(m.addresses[i], w.uint32(26).fork()).ldelim();
}
return w;
};
/**
* Decodes a PeerRecord message from the specified reader or buffer.
* @function decode
* @memberof PeerRecord
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {PeerRecord} PeerRecord
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
PeerRecord.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.PeerRecord();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.peerId = r.bytes();
break;
case 2:
m.seq = r.uint64();
break;
case 3:
if (!(m.addresses && m.addresses.length))
m.addresses = [];
m.addresses.push($root.PeerRecord.AddressInfo.decode(r, r.uint32()));
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates a PeerRecord message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof PeerRecord
* @static
* @param {Object.<string,*>} d Plain object
* @returns {PeerRecord} PeerRecord
*/
PeerRecord.fromObject = function fromObject(d) {
if (d instanceof $root.PeerRecord)
return d;
var m = new $root.PeerRecord();
if (d.peerId != null) {
if (typeof d.peerId === "string")
$util.base64.decode(d.peerId, m.peerId = $util.newBuffer($util.base64.length(d.peerId)), 0);
else if (d.peerId.length)
m.peerId = d.peerId;
}
if (d.seq != null) {
if ($util.Long)
(m.seq = $util.Long.fromValue(d.seq)).unsigned = true;
else if (typeof d.seq === "string")
m.seq = parseInt(d.seq, 10);
else if (typeof d.seq === "number")
m.seq = d.seq;
else if (typeof d.seq === "object")
m.seq = new $util.LongBits(d.seq.low >>> 0, d.seq.high >>> 0).toNumber(true);
}
if (d.addresses) {
if (!Array.isArray(d.addresses))
throw TypeError(".PeerRecord.addresses: array expected");
m.addresses = [];
for (var i = 0; i < d.addresses.length; ++i) {
if (typeof d.addresses[i] !== "object")
throw TypeError(".PeerRecord.addresses: object expected");
m.addresses[i] = $root.PeerRecord.AddressInfo.fromObject(d.addresses[i]);
}
}
return m;
};
/**
* Creates a plain object from a PeerRecord message. Also converts values to other types if specified.
* @function toObject
* @memberof PeerRecord
* @static
* @param {PeerRecord} m PeerRecord
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
PeerRecord.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.arrays || o.defaults) {
d.addresses = [];
}
if (o.defaults) {
if (o.bytes === String)
d.peerId = "";
else {
d.peerId = [];
if (o.bytes !== Array)
d.peerId = $util.newBuffer(d.peerId);
}
if ($util.Long) {
var n = new $util.Long(0, 0, true);
d.seq = o.longs === String ? n.toString() : o.longs === Number ? n.toNumber() : n;
} else
d.seq = o.longs === String ? "0" : 0;
}
if (m.peerId != null && m.hasOwnProperty("peerId")) {
d.peerId = o.bytes === String ? $util.base64.encode(m.peerId, 0, m.peerId.length) : o.bytes === Array ? Array.prototype.slice.call(m.peerId) : m.peerId;
}
if (m.seq != null && m.hasOwnProperty("seq")) {
if (typeof m.seq === "number")
d.seq = o.longs === String ? String(m.seq) : m.seq;
else
d.seq = o.longs === String ? $util.Long.prototype.toString.call(m.seq) : o.longs === Number ? new $util.LongBits(m.seq.low >>> 0, m.seq.high >>> 0).toNumber(true) : m.seq;
}
if (m.addresses && m.addresses.length) {
d.addresses = [];
for (var j = 0; j < m.addresses.length; ++j) {
d.addresses[j] = $root.PeerRecord.AddressInfo.toObject(m.addresses[j], o);
}
}
return d;
};
/**
* Converts this PeerRecord to JSON.
* @function toJSON
* @memberof PeerRecord
* @instance
* @returns {Object.<string,*>} JSON object
*/
PeerRecord.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
PeerRecord.AddressInfo = (function() {
/**
* Properties of an AddressInfo.
* @memberof PeerRecord
* @interface IAddressInfo
* @property {Uint8Array|null} [multiaddr] AddressInfo multiaddr
*/
/**
* Constructs a new AddressInfo.
* @memberof PeerRecord
* @classdesc Represents an AddressInfo.
* @implements IAddressInfo
* @constructor
* @param {PeerRecord.IAddressInfo=} [p] Properties to set
*/
function AddressInfo(p) {
if (p)
for (var ks = Object.keys(p), i = 0; i < ks.length; ++i)
if (p[ks[i]] != null)
this[ks[i]] = p[ks[i]];
}
/**
* AddressInfo multiaddr.
* @member {Uint8Array} multiaddr
* @memberof PeerRecord.AddressInfo
* @instance
*/
AddressInfo.prototype.multiaddr = $util.newBuffer([]);
/**
* Encodes the specified AddressInfo message. Does not implicitly {@link PeerRecord.AddressInfo.verify|verify} messages.
* @function encode
* @memberof PeerRecord.AddressInfo
* @static
* @param {PeerRecord.IAddressInfo} m AddressInfo message or plain object to encode
* @param {$protobuf.Writer} [w] Writer to encode to
* @returns {$protobuf.Writer} Writer
*/
AddressInfo.encode = function encode(m, w) {
if (!w)
w = $Writer.create();
if (m.multiaddr != null && Object.hasOwnProperty.call(m, "multiaddr"))
w.uint32(10).bytes(m.multiaddr);
return w;
};
/**
* Decodes an AddressInfo message from the specified reader or buffer.
* @function decode
* @memberof PeerRecord.AddressInfo
* @static
* @param {$protobuf.Reader|Uint8Array} r Reader or buffer to decode from
* @param {number} [l] Message length if known beforehand
* @returns {PeerRecord.AddressInfo} AddressInfo
* @throws {Error} If the payload is not a reader or valid buffer
* @throws {$protobuf.util.ProtocolError} If required fields are missing
*/
AddressInfo.decode = function decode(r, l) {
if (!(r instanceof $Reader))
r = $Reader.create(r);
var c = l === undefined ? r.len : r.pos + l, m = new $root.PeerRecord.AddressInfo();
while (r.pos < c) {
var t = r.uint32();
switch (t >>> 3) {
case 1:
m.multiaddr = r.bytes();
break;
default:
r.skipType(t & 7);
break;
}
}
return m;
};
/**
* Creates an AddressInfo message from a plain object. Also converts values to their respective internal types.
* @function fromObject
* @memberof PeerRecord.AddressInfo
* @static
* @param {Object.<string,*>} d Plain object
* @returns {PeerRecord.AddressInfo} AddressInfo
*/
AddressInfo.fromObject = function fromObject(d) {
if (d instanceof $root.PeerRecord.AddressInfo)
return d;
var m = new $root.PeerRecord.AddressInfo();
if (d.multiaddr != null) {
if (typeof d.multiaddr === "string")
$util.base64.decode(d.multiaddr, m.multiaddr = $util.newBuffer($util.base64.length(d.multiaddr)), 0);
else if (d.multiaddr.length)
m.multiaddr = d.multiaddr;
}
return m;
};
/**
* Creates a plain object from an AddressInfo message. Also converts values to other types if specified.
* @function toObject
* @memberof PeerRecord.AddressInfo
* @static
* @param {PeerRecord.AddressInfo} m AddressInfo
* @param {$protobuf.IConversionOptions} [o] Conversion options
* @returns {Object.<string,*>} Plain object
*/
AddressInfo.toObject = function toObject(m, o) {
if (!o)
o = {};
var d = {};
if (o.defaults) {
if (o.bytes === String)
d.multiaddr = "";
else {
d.multiaddr = [];
if (o.bytes !== Array)
d.multiaddr = $util.newBuffer(d.multiaddr);
}
}
if (m.multiaddr != null && m.hasOwnProperty("multiaddr")) {
d.multiaddr = o.bytes === String ? $util.base64.encode(m.multiaddr, 0, m.multiaddr.length) : o.bytes === Array ? Array.prototype.slice.call(m.multiaddr) : m.multiaddr;
}
return d;
};
/**
* Converts this AddressInfo to JSON.
* @function toJSON
* @memberof PeerRecord.AddressInfo
* @instance
* @returns {Object.<string,*>} JSON object
*/
AddressInfo.prototype.toJSON = function toJSON() {
return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
};
return AddressInfo;
})();
return PeerRecord;
})();
module.exports = $root;

View File

@ -1,14 +1,5 @@
'use strict'
syntax = "proto3";
const protons = require('protons')
// PeerRecord messages contain information that is useful to share with other peers.
// Currently, a PeerRecord contains the public listen addresses for a peer, but this
// is expected to expand to include other information in the future.
// PeerRecords are designed to be serialized to bytes and placed inside of
// SignedEnvelopes before sharing with other peers.
/** @type {{PeerRecord: import('../../types').MessageProto}} */
module.exports = protons(`
message PeerRecord {
// AddressInfo is a wrapper around a binary multiaddr. It is defined as a
// separate message to allow us to add per-address metadata in the future.
@ -25,4 +16,3 @@ message PeerRecord {
// addresses is a list of public listen addresses for the peer.
repeated AddressInfo addresses = 3;
}
`)

View File

@ -1,8 +1,8 @@
'use strict'
const debug = require('debug')
const log = Object.assign(debug('libp2p:peer-store'), {
error: debug('libp2p:peer-store:err')
const log = Object.assign(debug('libp2p:registrar'), {
error: debug('libp2p:registrar:err')
})
const errcode = require('err-code')
@ -16,7 +16,11 @@ const Topology = require('libp2p-interfaces/src/topology')
* @typedef {import('./peer-store')} PeerStore
* @typedef {import('./connection-manager')} ConnectionManager
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/topology')} Topology
* @typedef {import('./').HandlerProps} HandlerProps
*/
/**
*
*/
/**
@ -38,20 +42,28 @@ class Registrar {
/**
* Map of topologies
*
* @type {Map<string, object>}
* @type {Map<string, Topology>}
*/
this.topologies = new Map()
/** @type {(protocols: string[]|string, handler: (props: HandlerProps) => void) => void} */
// @ts-ignore handle is not optional
this._handle = undefined
this._onDisconnect = this._onDisconnect.bind(this)
this.connectionManager.on('peer:disconnect', this._onDisconnect)
}
/**
* @returns {(protocols: string[]|string, handler: (props: HandlerProps) => void) => void}
*/
get handle () {
return this._handle
}
/**
* @param {(protocols: string[]|string, handler: (props: HandlerProps) => void) => void} handle
*/
set handle (handle) {
this._handle = handle
}
@ -103,12 +115,11 @@ class Registrar {
* Remove a disconnected peer from the record
*
* @param {Connection} connection
* @param {Error} [error]
* @returns {void}
*/
_onDisconnect (connection, error) {
_onDisconnect (connection) {
for (const [, topology] of this.topologies) {
topology.disconnect(connection.remotePeer, error)
topology.disconnect(connection.remotePeer)
}
}
}

View File

@ -12,10 +12,10 @@ const errCode = require('err-code')
const { updateSelfPeerRecord } = require('./record/utils')
/**
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('multiaddr').Multiaddr} Multiaddr
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory} TransportFactory
* @typedef {import('libp2p-interfaces/src/transport/types').Transport} Transport
* @typedef {import('libp2p-interfaces/src/transport/types').TransportFactory<any, any>} TransportFactory
* @typedef {import('libp2p-interfaces/src/transport/types').Transport<any, any>} Transport
*
* @typedef {Object} TransportManagerProperties
* @property {import('./')} libp2p
@ -121,6 +121,7 @@ class TransportManager {
* @returns {Multiaddr[]}
*/
getAddrs () {
/** @type {Multiaddr[]} */
let addrs = []
for (const listeners of this._listeners.values()) {
for (const listener of listeners) {

View File

@ -1,103 +0,0 @@
// Insecure Message types
export enum KeyType {
RSA = 0,
Ed25519 = 1,
Secp256k1 = 2,
ECDSA = 3
}
// Protobufs
export type MessageProto = {
encode(value: any): Uint8Array
decode(bytes: Uint8Array): any
}
export type SUCCESS = 100;
export type HOP_SRC_ADDR_TOO_LONG = 220;
export type HOP_DST_ADDR_TOO_LONG = 221;
export type HOP_SRC_MULTIADDR_INVALID = 250;
export type HOP_DST_MULTIADDR_INVALID = 251;
export type HOP_NO_CONN_TO_DST = 260;
export type HOP_CANT_DIAL_DST = 261;
export type HOP_CANT_OPEN_DST_STREAM = 262;
export type HOP_CANT_SPEAK_RELAY = 270;
export type HOP_CANT_RELAY_TO_SELF = 280;
export type STOP_SRC_ADDR_TOO_LONG = 320;
export type STOP_DST_ADDR_TOO_LONG = 321;
export type STOP_SRC_MULTIADDR_INVALID = 350;
export type STOP_DST_MULTIADDR_INVALID = 351;
export type STOP_RELAY_REFUSED = 390;
export type MALFORMED_MESSAGE = 400;
export type CircuitStatus = SUCCESS | HOP_SRC_ADDR_TOO_LONG | HOP_DST_ADDR_TOO_LONG
| HOP_SRC_MULTIADDR_INVALID | HOP_DST_MULTIADDR_INVALID | HOP_NO_CONN_TO_DST
| HOP_CANT_DIAL_DST | HOP_CANT_OPEN_DST_STREAM | HOP_CANT_SPEAK_RELAY | HOP_CANT_RELAY_TO_SELF
| STOP_SRC_ADDR_TOO_LONG | STOP_DST_ADDR_TOO_LONG | STOP_SRC_MULTIADDR_INVALID
| STOP_DST_MULTIADDR_INVALID | STOP_RELAY_REFUSED | MALFORMED_MESSAGE
export type HOP = 1;
export type STOP = 2;
export type STATUS = 3;
export type CAN_HOP = 4;
export type CircuitType = HOP | STOP | STATUS | CAN_HOP
export type CircuitPeer = {
id: Uint8Array
addrs: Uint8Array[]
}
export type CircuitRequest = {
type: CircuitType
dstPeer: CircuitPeer
srcPeer: CircuitPeer
}
export type CircuitMessageProto = {
encode(value: any): Uint8Array
decode(bytes: Uint8Array): any
Status: {
SUCCESS: SUCCESS,
HOP_SRC_ADDR_TOO_LONG: HOP_SRC_ADDR_TOO_LONG,
HOP_DST_ADDR_TOO_LONG: HOP_DST_ADDR_TOO_LONG,
HOP_SRC_MULTIADDR_INVALID: HOP_SRC_MULTIADDR_INVALID,
HOP_DST_MULTIADDR_INVALID: HOP_DST_MULTIADDR_INVALID,
HOP_NO_CONN_TO_DST: HOP_NO_CONN_TO_DST,
HOP_CANT_DIAL_DST: HOP_CANT_DIAL_DST,
HOP_CANT_OPEN_DST_STREAM: HOP_CANT_OPEN_DST_STREAM,
HOP_CANT_SPEAK_RELAY: HOP_CANT_SPEAK_RELAY,
HOP_CANT_RELAY_TO_SELF: HOP_CANT_RELAY_TO_SELF,
STOP_SRC_ADDR_TOO_LONG: STOP_SRC_ADDR_TOO_LONG,
STOP_DST_ADDR_TOO_LONG: STOP_DST_ADDR_TOO_LONG,
STOP_SRC_MULTIADDR_INVALID: STOP_SRC_MULTIADDR_INVALID,
STOP_DST_MULTIADDR_INVALID: STOP_DST_MULTIADDR_INVALID,
STOP_RELAY_REFUSED: STOP_RELAY_REFUSED,
MALFORMED_MESSAGE: MALFORMED_MESSAGE
},
Type: {
HOP: HOP,
STOP: STOP,
STATUS: STATUS,
CAN_HOP: CAN_HOP
}
}
export interface EventEmitterFactory {
new(): EventEmitter;
}
export interface EventEmitter {
addListener(event: string | symbol, listener: (...args: any[]) => void);
on(event: string | symbol, listener: (...args: any[]) => void);
once(event: string | symbol, listener: (...args: any[]) => void);
removeListener(event: string | symbol, listener: (...args: any[]) => void);
off(event: string | symbol, listener: (...args: any[]) => void);
removeAllListeners(event?: string | symbol);
setMaxListeners(n: number);
getMaxListeners(): number;
listeners(event: string | symbol): Function[]; // eslint-disable-line @typescript-eslint/ban-types
rawListeners(event: string | symbol): Function[]; // eslint-disable-line @typescript-eslint/ban-types
emit(event: string | symbol, ...args: any[]): boolean;
listenerCount(event: string | symbol): number;
}

View File

@ -5,10 +5,12 @@ const log = Object.assign(debug('libp2p:upgrader'), {
error: debug('libp2p:upgrader:err')
})
const errCode = require('err-code')
// @ts-ignore multistream-select does not export types
const Multistream = require('multistream-select')
const { Connection } = require('libp2p-interfaces/src/connection')
const PeerId = require('peer-id')
const { pipe } = require('it-pipe')
// @ts-ignore mutable-proxy does not export types
const mutableProxy = require('mutable-proxy')
const { codes } = require('./errors')
@ -19,7 +21,8 @@ const { codes } = require('./errors')
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').Muxer} Muxer
* @typedef {import('libp2p-interfaces/src/stream-muxer/types').MuxedStream} MuxedStream
* @typedef {import('libp2p-interfaces/src/crypto/types').Crypto} Crypto
* @typedef {import('multiaddr')} Multiaddr
* @typedef {import('libp2p-interfaces/src/connection').Connection} Connection
* @typedef {import('multiaddr').Multiaddr} Multiaddr
*/
/**
@ -36,8 +39,8 @@ class Upgrader {
* @param {import('./metrics')} [options.metrics]
* @param {Map<string, Crypto>} [options.cryptos]
* @param {Map<string, MuxerFactory>} [options.muxers]
* @param {(Connection) => void} options.onConnection - Called when a connection is upgraded
* @param {(Connection) => void} options.onConnectionEnd
* @param {(connection: Connection) => void} options.onConnection - Called when a connection is upgraded
* @param {(connection: Connection) => void} options.onConnectionEnd
*/
constructor ({
localPeer,
@ -51,6 +54,7 @@ class Upgrader {
this.metrics = metrics
this.cryptos = cryptos
this.muxers = muxers
/** @type {import("./pnet") | null} */
this.protector = null
this.protocols = new Map()
this.onConnection = onConnection
@ -216,16 +220,18 @@ class Upgrader {
Muxer,
remotePeer
}) {
/** @type {import("libp2p-interfaces/src/stream-muxer/types").Muxer} */
let muxer
let newStream
// eslint-disable-next-line prefer-const
let connection
/** @type {Connection} */
let connection // eslint-disable-line prefer-const
if (Muxer) {
// Create the muxer
muxer = new Muxer({
// Run anytime a remote stream is created
onStream: async muxedStream => {
if (!connection) return
const mss = new Multistream.Listener(muxedStream)
try {
const { stream, protocol } = await mss.handle(Array.from(this.protocols.keys()))
@ -243,7 +249,7 @@ class Upgrader {
}
})
newStream = async protocols => {
newStream = async (/** @type {string | string[]} */ protocols) => {
log('%s: starting new stream on %s', direction, protocols)
const muxedStream = muxer.newStream()
const mss = new Multistream.Dialer(muxedStream)
@ -302,12 +308,12 @@ class Upgrader {
encryption: cryptoProtocol
},
newStream: newStream || errConnectionNotMultiplexed,
getStreams: () => muxer ? muxer.streams : errConnectionNotMultiplexed,
close: async (err) => {
getStreams: () => muxer ? muxer.streams : errConnectionNotMultiplexed(),
close: async (/** @type {Error | undefined} */ err) => {
await maConn.close(err)
// Ensure remaining streams are aborted
if (muxer) {
muxer.streams.map(stream => stream.abort(err))
muxer.streams.map(stream => stream.abort())
}
}
})
@ -371,7 +377,7 @@ class Upgrader {
* @private
* @async
* @param {PeerId} localPeer - The initiators PeerId
* @param {*} connection
* @param {MultiaddrConnection} connection
* @param {PeerId} remotePeerId
* @param {Map<string, Crypto>} cryptos
* @returns {Promise<CryptoResult>} An encrypted connection, remote peer `PeerId` and the protocol of the `Crypto` used

View File

@ -2,7 +2,7 @@
/* eslint-env mocha */
const { expect } = require('aegir/utils/chai')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const AddressManager = require('../../src/address-manager')
@ -37,8 +37,8 @@ describe('Address Manager', () => {
const listenMultiaddrs = am.getListenAddrs()
expect(listenMultiaddrs.length).to.equal(2)
expect(listenMultiaddrs[0].equals(multiaddr(listenAddresses[0]))).to.equal(true)
expect(listenMultiaddrs[1].equals(multiaddr(listenAddresses[1]))).to.equal(true)
expect(listenMultiaddrs[0].equals(new Multiaddr(listenAddresses[0]))).to.equal(true)
expect(listenMultiaddrs[1].equals(new Multiaddr(listenAddresses[1]))).to.equal(true)
})
it('should return announce multiaddrs on get', () => {
@ -52,7 +52,7 @@ describe('Address Manager', () => {
const announceMultiaddrs = am.getAnnounceAddrs()
expect(announceMultiaddrs.length).to.equal(1)
expect(announceMultiaddrs[0].equals(multiaddr(announceAddreses[0]))).to.equal(true)
expect(announceMultiaddrs[0].equals(new Multiaddr(announceAddreses[0]))).to.equal(true)
})
it('should add observed addresses', () => {

View File

@ -4,7 +4,7 @@
const { expect } = require('aegir/utils/chai')
const sinon = require('sinon')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const isLoopback = require('libp2p-utils/src/multiaddr/is-loopback')
const { AddressesOptions } = require('./utils')
@ -111,9 +111,9 @@ describe('libp2p.multiaddrs', () => {
expect(libp2p.multiaddrs.length).to.equal(0)
// Stub transportManager addresses to add a public address
const stubMa = multiaddr('/ip4/120.220.10.1/tcp/1000')
const stubMa = new Multiaddr('/ip4/120.220.10.1/tcp/1000')
sinon.stub(libp2p.transportManager, 'getAddrs').returns([
...listenAddresses.map((a) => multiaddr(a)),
...listenAddresses.map((a) => new Multiaddr(a)),
stubMa
])

View File

@ -11,7 +11,7 @@ const mergeOptions = require('merge-options')
const CID = require('cids')
const ipfsHttpClient = require('ipfs-http-client')
const DelegatedContentRouter = require('libp2p-delegated-content-routing')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const drain = require('it-drain')
const all = require('it-all')
@ -28,6 +28,8 @@ describe('content-routing', () => {
})
})
after(() => node.stop())
it('.findProviders should return an error', async () => {
try {
for await (const _ of node.contentRouting.findProviders('a cid')) {} // eslint-disable-line
@ -277,7 +279,7 @@ describe('content-routing', () => {
const result = {
id: providerPeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/49320')
new Multiaddr('/ip4/123.123.123.123/tcp/49320')
]
}
@ -301,7 +303,7 @@ describe('content-routing', () => {
const result = {
id: providerPeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/49320')
new Multiaddr('/ip4/123.123.123.123/tcp/49320')
]
}
@ -327,7 +329,7 @@ describe('content-routing', () => {
const result = {
id: providerPeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/49320')
new Multiaddr('/ip4/123.123.123.123/tcp/49320')
]
}
@ -348,13 +350,13 @@ describe('content-routing', () => {
const result1 = {
id: providerPeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/49320')
new Multiaddr('/ip4/123.123.123.123/tcp/49320')
]
}
const result2 = {
id: providerPeerId,
multiaddrs: [
multiaddr('/ip4/213.213.213.213/tcp/2344')
new Multiaddr('/ip4/213.213.213.213/tcp/2344')
]
}

View File

@ -3,7 +3,7 @@
const { expect } = require('aegir/utils/chai')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const pWaitFor = require('p-wait-for')
const mergeOptions = require('merge-options')
const uint8ArrayFromString = require('uint8arrays/from-string')
@ -12,8 +12,8 @@ const { create } = require('../../../src')
const { subsystemOptions, subsystemMulticodecs } = require('./utils')
const peerUtils = require('../../utils/creators/peer')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/8000')
const remoteListenAddr = multiaddr('/ip4/127.0.0.1/tcp/8001')
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/8000')
const remoteListenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/8001')
describe('DHT subsystem operates correctly', () => {
let peerId, remotePeerId

View File

@ -23,6 +23,8 @@ describe('ping', () => {
nodes[1].peerStore.addressBook.set(nodes[0].peerId, nodes[0].multiaddrs)
})
afterEach(() => Promise.all(nodes.map(n => n.stop())))
it('ping once from peer0 to peer1 using a multiaddr', async () => {
const ma = `${nodes[2].multiaddrs[0]}/p2p/${nodes[2].peerId.toB58String()}`
const latency = await nodes[0].ping(ma)
@ -56,6 +58,7 @@ describe('ping', () => {
if (firstInvocation) {
firstInvocation = false
// eslint-disable-next-line no-unreachable-loop
for await (const data of stream) {
return {
value: data,

View File

@ -6,7 +6,7 @@ const sinon = require('sinon')
const Transport = require('libp2p-tcp')
const Muxer = require('libp2p-mplex')
const { NOISE: Crypto } = require('libp2p-noise')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const delay = require('delay')
const pDefer = require('p-defer')
@ -33,8 +33,8 @@ const createMockConnection = require('../utils/mockConnection')
const Peers = require('../fixtures/peers')
const { createPeerId } = require('../utils/creators/peer')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
const unsupportedAddr = multiaddr('/ip4/127.0.0.1/tcp/9999/ws/p2p/QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN')
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
const unsupportedAddr = new Multiaddr('/ip4/127.0.0.1/tcp/9999/ws/p2p/QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN')
describe('Dialing (direct, TCP)', () => {
let remoteTM
@ -147,7 +147,7 @@ describe('Dialing (direct, TCP)', () => {
const dialer = new Dialer({
transportManager: localTM,
peerStore,
timeout: 50
dialTimeout: 50
})
sinon.stub(localTM, 'dial').callsFake(async (addr, options) => {
expect(options.signal).to.exist()
@ -165,13 +165,13 @@ describe('Dialing (direct, TCP)', () => {
it('should dial to the max concurrency', async () => {
const addrs = [
multiaddr('/ip4/0.0.0.0/tcp/8000'),
multiaddr('/ip4/0.0.0.0/tcp/8001'),
multiaddr('/ip4/0.0.0.0/tcp/8002')
new Multiaddr('/ip4/0.0.0.0/tcp/8000'),
new Multiaddr('/ip4/0.0.0.0/tcp/8001'),
new Multiaddr('/ip4/0.0.0.0/tcp/8002')
]
const dialer = new Dialer({
transportManager: localTM,
concurrency: 2,
maxParallelDials: 2,
peerStore: {
addressBook: {
add: () => {},

View File

@ -10,7 +10,7 @@ const Transport = require('libp2p-websockets')
const filters = require('libp2p-websockets/src/filters')
const Muxer = require('libp2p-mplex')
const { NOISE: Crypto } = require('libp2p-noise')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const AggregateError = require('aggregate-error')
const { AbortError } = require('libp2p-interfaces/src/transport/errors')
@ -26,7 +26,7 @@ const { MULTIADDRS_WEBSOCKETS } = require('../fixtures/browser')
const mockUpgrader = require('../utils/mockUpgrader')
const createMockConnection = require('../utils/mockConnection')
const { createPeerId } = require('../utils/creators/peer')
const unsupportedAddr = multiaddr('/ip4/127.0.0.1/tcp/9999/ws/p2p/QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN')
const unsupportedAddr = new Multiaddr('/ip4/127.0.0.1/tcp/9999/ws/p2p/QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN')
const remoteAddr = MULTIADDRS_WEBSOCKETS[0]
describe('Dialing (direct, WebSockets)', () => {
@ -52,7 +52,7 @@ describe('Dialing (direct, WebSockets)', () => {
it('should have appropriate defaults', () => {
const dialer = new Dialer({ transportManager: localTM, peerStore })
expect(dialer.concurrency).to.equal(Constants.MAX_PARALLEL_DIALS)
expect(dialer.maxParallelDials).to.equal(Constants.MAX_PARALLEL_DIALS)
expect(dialer.timeout).to.equal(Constants.DIAL_TIMEOUT)
})
@ -155,7 +155,7 @@ describe('Dialing (direct, WebSockets)', () => {
it('should abort dials on queue task timeout', async () => {
const dialer = new Dialer({
transportManager: localTM,
timeout: 50,
dialTimeout: 50,
peerStore: {
addressBook: {
add: () => {},
@ -179,9 +179,9 @@ describe('Dialing (direct, WebSockets)', () => {
it('should sort addresses on dial', async () => {
const peerMultiaddrs = [
multiaddr('/ip4/127.0.0.1/tcp/15001/ws'),
multiaddr('/ip4/20.0.0.1/tcp/15001/ws'),
multiaddr('/ip4/30.0.0.1/tcp/15001/ws')
new Multiaddr('/ip4/127.0.0.1/tcp/15001/ws'),
new Multiaddr('/ip4/20.0.0.1/tcp/15001/ws'),
new Multiaddr('/ip4/30.0.0.1/tcp/15001/ws')
]
sinon.spy(addressSort, 'publicAddressesFirst')
@ -190,7 +190,7 @@ describe('Dialing (direct, WebSockets)', () => {
const dialer = new Dialer({
transportManager: localTM,
addressSorter: addressSort.publicAddressesFirst,
concurrency: 3,
maxParallelDials: 3,
peerStore
})
@ -211,7 +211,7 @@ describe('Dialing (direct, WebSockets)', () => {
it('should dial to the max concurrency', async () => {
const dialer = new Dialer({
transportManager: localTM,
concurrency: 2,
maxParallelDials: 2,
peerStore: {
addressBook: {
set: () => {},
@ -249,7 +249,7 @@ describe('Dialing (direct, WebSockets)', () => {
it('.destroy should abort pending dials', async () => {
const dialer = new Dialer({
transportManager: localTM,
concurrency: 2,
maxParallelDials: 2,
peerStore: {
addressBook: {
set: () => {},
@ -318,8 +318,8 @@ describe('Dialing (direct, WebSockets)', () => {
})
expect(libp2p.dialer).to.exist()
expect(libp2p.dialer.concurrency).to.equal(Constants.MAX_PARALLEL_DIALS)
expect(libp2p.dialer.perPeerLimit).to.equal(Constants.MAX_PER_PEER_DIALS)
expect(libp2p.dialer.maxParallelDials).to.equal(Constants.MAX_PARALLEL_DIALS)
expect(libp2p.dialer.maxDialsPerPeer).to.equal(Constants.MAX_PER_PEER_DIALS)
expect(libp2p.dialer.timeout).to.equal(Constants.DIAL_TIMEOUT)
// Ensure the dialer also has the transport manager
expect(libp2p.transportManager).to.equal(libp2p.dialer.transportManager)
@ -349,8 +349,8 @@ describe('Dialing (direct, WebSockets)', () => {
libp2p = await Libp2p.create(config)
expect(libp2p.dialer).to.exist()
expect(libp2p.dialer.concurrency).to.equal(config.dialer.maxParallelDials)
expect(libp2p.dialer.perPeerLimit).to.equal(config.dialer.maxDialsPerPeer)
expect(libp2p.dialer.maxParallelDials).to.equal(config.dialer.maxParallelDials)
expect(libp2p.dialer.maxDialsPerPeer).to.equal(config.dialer.maxDialsPerPeer)
expect(libp2p.dialer.timeout).to.equal(config.dialer.dialTimeout)
})

View File

@ -4,8 +4,8 @@
const { expect } = require('aegir/utils/chai')
const sinon = require('sinon')
const multiaddr = require('multiaddr')
const { Resolver } = require('multiaddr/src/resolvers/dns')
const { Multiaddr } = require('multiaddr')
const Resolver = require('multiaddr/src/resolvers/dns')
const { codes: ErrorCodes } = require('../../src/errors')
@ -39,7 +39,7 @@ describe('Dialing (resolvable addresses)', () => {
config: {
...baseOptions,
addresses: {
listen: [multiaddr(`${relayAddr}/p2p-circuit`)]
listen: [new Multiaddr(`${relayAddr}/p2p-circuit`)]
},
config: {
...baseOptions.config,
@ -60,8 +60,8 @@ describe('Dialing (resolvable addresses)', () => {
it('resolves dnsaddr to ws local address', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = multiaddr(relayedAddr(remoteId))
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = new Multiaddr(relayedAddr(remoteId))
// Transport spy
const transport = libp2p.transportManager._transports.get('Circuit')
@ -82,8 +82,8 @@ describe('Dialing (resolvable addresses)', () => {
it('resolves a dnsaddr recursively', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = multiaddr(relayedAddr(remoteId))
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = new Multiaddr(relayedAddr(remoteId))
// Transport spy
const transport = libp2p.transportManager._transports.get('Circuit')
@ -114,10 +114,10 @@ describe('Dialing (resolvable addresses)', () => {
// Resolver just returns the received multiaddrs
it('stops recursive resolve if finds dns4/dns6 and dials it', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
// Stub resolver
const dnsMa = multiaddr(`/dns4/ams-1.remote.libp2p.io/tcp/443/wss/p2p/${remoteId}`)
const dnsMa = new Multiaddr(`/dns4/ams-1.remote.libp2p.io/tcp/443/wss/p2p/${remoteId}`)
const stubResolve = sinon.stub(Resolver.prototype, 'resolveTxt')
stubResolve.returns(Promise.resolve([
[`dnsaddr=${dnsMa}`]
@ -135,8 +135,8 @@ describe('Dialing (resolvable addresses)', () => {
it('resolves a dnsaddr recursively not failing if one address fails to resolve', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = multiaddr(relayedAddr(remoteId))
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const relayedAddrFetched = new Multiaddr(relayedAddr(remoteId))
// Transport spy
const transport = libp2p.transportManager._transports.get('Circuit')
@ -159,7 +159,7 @@ describe('Dialing (resolvable addresses)', () => {
it('fails to dial if resolve fails and there are no addresses to dial', async () => {
const remoteId = remoteLibp2p.peerId.toB58String()
const dialAddr = multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
const dialAddr = new Multiaddr(`/dnsaddr/remote.libp2p.io/p2p/${remoteId}`)
// Stub resolver
const stubResolve = sinon.stub(Resolver.prototype, 'resolveTxt')

View File

@ -1,7 +1,7 @@
'use strict'
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
module.exports.MULTIADDRS_WEBSOCKETS = [
multiaddr('/ip4/127.0.0.1/tcp/15001/ws/p2p/12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5')
new Multiaddr('/ip4/127.0.0.1/tcp/15001/ws/p2p/12D3KooWHFKTMzwerBtsVmtz4ZZEQy2heafxzWw6wNn5PPYkBxJ5')
]

View File

@ -7,7 +7,7 @@ const sinon = require('sinon')
const { EventEmitter } = require('events')
const PeerId = require('peer-id')
const duplexPair = require('it-pair/duplex')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const pWaitFor = require('p-wait-for')
const unit8ArrayToString = require('uint8arrays/to-string')
@ -25,7 +25,7 @@ const AddressManager = require('../../src/address-manager')
const { MULTIADDRS_WEBSOCKETS } = require('../fixtures/browser')
const remoteAddr = MULTIADDRS_WEBSOCKETS[0]
const listenMaddrs = [multiaddr('/ip4/127.0.0.1/tcp/15002/ws')]
const listenMaddrs = [new Multiaddr('/ip4/127.0.0.1/tcp/15002/ws')]
describe('Identify', () => {
let localPeer, localPeerStore, localAddressManager
@ -74,7 +74,7 @@ describe('Identify', () => {
}
})
const observedAddr = multiaddr('/ip4/127.0.0.1/tcp/1234')
const observedAddr = new Multiaddr('/ip4/127.0.0.1/tcp/1234')
const localConnectionMock = { newStream: () => {}, remotePeer }
const remoteConnectionMock = { remoteAddr: observedAddr }
@ -110,6 +110,7 @@ describe('Identify', () => {
// LEGACY
it('should be able to identify another peer with no certified peer records support', async () => {
const agentVersion = `js-libp2p/${pkg.version}`
const localIdentify = new IdentifyService({
libp2p: {
peerId: localPeer,
@ -118,7 +119,7 @@ describe('Identify', () => {
peerStore: localPeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true,
_options: { host: {} }
_options: { host: { agentVersion } }
}
})
@ -130,11 +131,11 @@ describe('Identify', () => {
peerStore: remotePeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true,
_options: { host: {} }
_options: { host: { agentVersion } }
}
})
const observedAddr = multiaddr('/ip4/127.0.0.1/tcp/1234')
const observedAddr = new Multiaddr('/ip4/127.0.0.1/tcp/1234')
const localConnectionMock = { newStream: () => {}, remotePeer }
const remoteConnectionMock = { remoteAddr: observedAddr }
@ -162,7 +163,7 @@ describe('Identify', () => {
const metadataArgs = localIdentify.peerStore.metadataBook.set.firstCall.args
expect(metadataArgs[0].id.bytes).to.equal(remotePeer.bytes)
expect(metadataArgs[1]).to.equal('AgentVersion')
expect(unit8ArrayToString(metadataArgs[2])).to.equal(`js-libp2p/${pkg.version}`)
expect(unit8ArrayToString(metadataArgs[2])).to.equal(agentVersion)
// Validate the remote peer gets updated in the peer store
const call = localIdentify.peerStore.addressBook.set.firstCall
@ -192,7 +193,7 @@ describe('Identify', () => {
}
})
const observedAddr = multiaddr('/ip4/127.0.0.1/tcp/1234')
const observedAddr = new Multiaddr('/ip4/127.0.0.1/tcp/1234')
const localConnectionMock = { newStream: () => {}, remotePeer: localPeer }
const remoteConnectionMock = { remoteAddr: observedAddr }
@ -500,7 +501,7 @@ describe('Identify', () => {
await libp2p.identifyService.identify.firstCall.returnValue
sinon.stub(libp2p, 'isStarted').returns(true)
libp2p.peerStore.addressBook.add(libp2p.peerId, [multiaddr('/ip4/180.0.0.1/tcp/15001/ws')])
libp2p.peerStore.addressBook.add(libp2p.peerId, [new Multiaddr('/ip4/180.0.0.1/tcp/15001/ws')])
// Verify the remote peer is notified of change
expect(libp2p.identifyService.push.callCount).to.equal(1)

View File

@ -27,8 +27,8 @@ describe('keychain', () => {
datastore1 = new MemoryDatastore()
datastore2 = new MemoryDatastore()
ks = new Keychain(datastore2, { passPhrase: passPhrase })
emptyKeystore = new Keychain(datastore1, { passPhrase: passPhrase })
ks = new Keychain(datastore2, { pass: passPhrase })
emptyKeystore = new Keychain(datastore1, { pass: passPhrase })
await datastore1.open()
await datastore2.open()
@ -44,11 +44,11 @@ describe('keychain', () => {
})
it('needs a NIST SP 800-132 non-weak pass phrase', () => {
expect(() => new Keychain(datastore2, { passPhrase: '< 20 character' })).to.throw()
expect(() => new Keychain(datastore2, { pass: '< 20 character' })).to.throw()
})
it('needs a store to persist a key', () => {
expect(() => new Keychain(null, { passPhrase: passPhrase })).to.throw()
expect(() => new Keychain(null, { pass: passPhrase })).to.throw()
})
it('has default options', () => {
@ -56,12 +56,12 @@ describe('keychain', () => {
})
it('supports supported hashing alorithms', () => {
const ok = new Keychain(datastore2, { passPhrase: passPhrase, dek: { hash: 'sha2-256' } })
const ok = new Keychain(datastore2, { pass: passPhrase, dek: { hash: 'sha2-256' } })
expect(ok).to.exist()
})
it('does not support unsupported hashing alorithms', () => {
expect(() => new Keychain(datastore2, { passPhrase: passPhrase, dek: { hash: 'my-hash' } })).to.throw()
expect(() => new Keychain(datastore2, { pass: passPhrase, dek: { hash: 'my-hash' } })).to.throw()
})
it('can list keys without a password', async () => {
@ -72,7 +72,7 @@ describe('keychain', () => {
it('can find a key without a password', async () => {
const keychain = new Keychain(datastore2)
const keychainWithPassword = new Keychain(datastore2, { passPhrase: `hello-${Date.now()}-${Date.now()}` })
const keychainWithPassword = new Keychain(datastore2, { pass: `hello-${Date.now()}-${Date.now()}` })
const name = `key-${Math.random()}`
const { id } = await keychainWithPassword.createKey(name, 'ed25519')
@ -82,7 +82,7 @@ describe('keychain', () => {
it('can remove a key without a password', async () => {
const keychainWithoutPassword = new Keychain(datastore2)
const keychainWithPassword = new Keychain(datastore2, { passPhrase: `hello-${Date.now()}-${Date.now()}` })
const keychainWithPassword = new Keychain(datastore2, { pass: `hello-${Date.now()}-${Date.now()}` })
const name = `key-${Math.random()}`
expect(await keychainWithPassword.createKey(name, 'ed25519')).to.have.property('name', name)
@ -99,7 +99,7 @@ describe('keychain', () => {
it('can generate options', () => {
const options = Keychain.generateOptions()
options.passPhrase = passPhrase
options.pass = passPhrase
const chain = new Keychain(datastore2, options)
expect(chain).to.exist()
})

View File

@ -71,7 +71,7 @@ describe('Nat Manager (TCP)', () => {
}
}
afterEach(() => Promise.all(teardown))
afterEach(() => Promise.all(teardown.map(t => t())))
it('should map TCP connections to external ports', async () => {
const {

View File

@ -10,14 +10,14 @@ const Bootstrap = require('libp2p-bootstrap')
const crypto = require('libp2p-crypto')
const KadDht = require('libp2p-kad-dht')
const MulticastDNS = require('libp2p-mdns')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const uint8ArrayToString = require('uint8arrays/to-string')
const Libp2p = require('../../src')
const baseOptions = require('../utils/base-options')
const { createPeerId } = require('../utils/creators/peer')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
describe('peer discovery scenarios', () => {
let peerId, remotePeerId1, remotePeerId2
@ -30,6 +30,7 @@ describe('peer discovery scenarios', () => {
afterEach(async () => {
libp2p && await libp2p.stop()
})
it('should ignore self on discovery', async () => {
libp2p = new Libp2p(mergeOptions(baseOptions, {
peerId,

View File

@ -7,7 +7,7 @@ const sinon = require('sinon')
const defer = require('p-defer')
const mergeOptions = require('merge-options')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const WebRTCStar = require('libp2p-webrtc-star')
const Libp2p = require('../../src')
@ -38,7 +38,7 @@ describe('peer discovery', () => {
}
})
libp2p.peerStore.addressBook.set(remotePeerId, [multiaddr('/ip4/165.1.1.1/tcp/80')])
libp2p.peerStore.addressBook.set(remotePeerId, [new Multiaddr('/ip4/165.1.1.1/tcp/80')])
const deferred = defer()
sinon.stub(libp2p.dialer, 'connectToPeer').callsFake((remotePeerId) => {
@ -89,6 +89,10 @@ describe('peer discovery', () => {
[peerId] = await createPeerId()
})
afterEach(async () => {
libp2p && await libp2p.stop()
})
it('should add discovery module if present in transports and enabled', async () => {
libp2p = new Libp2p(mergeOptions(baseOptions, {
peerId,

View File

@ -15,7 +15,7 @@ const all = require('it-all')
const ipfsHttpClient = require('ipfs-http-client')
const DelegatedPeerRouter = require('libp2p-delegated-peer-routing')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const PeerId = require('peer-id')
const peerUtils = require('../utils/creators/peer')
@ -31,6 +31,8 @@ describe('peer-routing', () => {
})
})
after(() => node.stop())
it('.findPeer should return an error', async () => {
await expect(node.peerRouting.findPeer('a cid'))
.to.eventually.be.rejected()
@ -360,7 +362,7 @@ describe('peer-routing', () => {
const results = {
id: remotePeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/38982')
new Multiaddr('/ip4/123.123.123.123/tcp/38982')
]
}
@ -400,7 +402,7 @@ describe('peer-routing', () => {
const result = {
id: remotePeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/38982')
new Multiaddr('/ip4/123.123.123.123/tcp/38982')
]
}
@ -422,7 +424,7 @@ describe('peer-routing', () => {
const results = [{
id: remotePeerId,
multiaddrs: [
multiaddr('/ip4/123.123.123.123/tcp/38982')
new Multiaddr('/ip4/123.123.123.123/tcp/38982')
]
}]
@ -456,8 +458,8 @@ describe('peer-routing', () => {
it('should be enabled and start by default', async () => {
const results = [
{ id: peerIds[0], multiaddrs: [multiaddr('/ip4/30.0.0.1/tcp/2000')] },
{ id: peerIds[1], multiaddrs: [multiaddr('/ip4/32.0.0.1/tcp/2000')] }
{ id: peerIds[0], multiaddrs: [new Multiaddr('/ip4/30.0.0.1/tcp/2000')] },
{ id: peerIds[1], multiaddrs: [new Multiaddr('/ip4/32.0.0.1/tcp/2000')] }
]
;[node] = await peerUtils.createPeer({
@ -533,7 +535,7 @@ describe('peer-routing', () => {
})
sinon.stub(node._dht, 'getClosestPeers').callsFake(function * () {
yield { id: peerIds[0], multiaddrs: [multiaddr('/ip4/30.0.0.1/tcp/2000')] }
yield { id: peerIds[0], multiaddrs: [new Multiaddr('/ip4/30.0.0.1/tcp/2000')] }
})
await node.start()

View File

@ -4,7 +4,7 @@
const { expect } = require('aegir/utils/chai')
const { Buffer } = require('buffer')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const arrayEquals = require('libp2p-utils/src/array-equals')
const addressSort = require('libp2p-utils/src/address-sort')
const PeerId = require('peer-id')
@ -19,9 +19,9 @@ const {
codes: { ERR_INVALID_PARAMETERS }
} = require('../../src/errors')
const addr1 = multiaddr('/ip4/127.0.0.1/tcp/8000')
const addr2 = multiaddr('/ip4/20.0.0.1/tcp/8001')
const addr3 = multiaddr('/ip4/127.0.0.1/tcp/8002')
const addr1 = new Multiaddr('/ip4/127.0.0.1/tcp/8000')
const addr2 = new Multiaddr('/ip4/20.0.0.1/tcp/8001')
const addr3 = new Multiaddr('/ip4/127.0.0.1/tcp/8002')
describe('addressBook', () => {
let peerId

View File

@ -21,6 +21,8 @@ describe('libp2p.peerStore', () => {
})
})
afterEach(() => Promise.all([libp2p, remoteLibp2p].map(l => l.stop())))
it('adds peer address to AddressBook and keys to the keybook when establishing connection', async () => {
const remoteIdStr = remoteLibp2p.peerId.toB58String()

View File

@ -4,15 +4,15 @@
const { expect } = require('aegir/utils/chai')
const PeerStore = require('../../src/peer-store')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const uint8ArrayFromString = require('uint8arrays/from-string')
const peerUtils = require('../utils/creators/peer')
const addr1 = multiaddr('/ip4/127.0.0.1/tcp/8000')
const addr2 = multiaddr('/ip4/127.0.0.1/tcp/8001')
const addr3 = multiaddr('/ip4/127.0.0.1/tcp/8002')
const addr4 = multiaddr('/ip4/127.0.0.1/tcp/8003')
const addr1 = new Multiaddr('/ip4/127.0.0.1/tcp/8000')
const addr2 = new Multiaddr('/ip4/127.0.0.1/tcp/8001')
const addr3 = new Multiaddr('/ip4/127.0.0.1/tcp/8002')
const addr4 = new Multiaddr('/ip4/127.0.0.1/tcp/8003')
const proto1 = '/protocol1'
const proto2 = '/protocol2'

View File

@ -8,7 +8,7 @@ const Envelope = require('../../src/record/envelope')
const PeerRecord = require('../../src/record/peer-record')
const PeerStore = require('../../src/peer-store/persistent')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const { MemoryDatastore } = require('interface-datastore')
const uint8ArrayFromString = require('uint8arrays/from-string')
@ -65,7 +65,7 @@ describe('Persisted PeerStore', () => {
it('should store peerStore content on datastore after peer marked as dirty (threshold 1)', async () => {
const [peer] = await peerUtils.createPeerId({ number: 2 })
const multiaddrs = [multiaddr('/ip4/156.10.1.22/tcp/1000')]
const multiaddrs = [new Multiaddr('/ip4/156.10.1.22/tcp/1000')]
const protocols = ['/ping/1.0.0']
const spyDirty = sinon.spy(peerStore, '_addDirtyPeer')
const spyDs = sinon.spy(datastore, 'batch')
@ -115,8 +115,8 @@ describe('Persisted PeerStore', () => {
const peers = await peerUtils.createPeerId({ number: 2 })
const commitSpy = sinon.spy(peerStore, '_commitData')
const multiaddrs = [
multiaddr('/ip4/156.10.1.22/tcp/1000'),
multiaddr('/ip4/156.10.1.23/tcp/1000')
new Multiaddr('/ip4/156.10.1.22/tcp/1000'),
new Multiaddr('/ip4/156.10.1.23/tcp/1000')
]
const protocols = ['/ping/1.0.0']
@ -173,7 +173,7 @@ describe('Persisted PeerStore', () => {
it('should delete content from the datastore on delete', async () => {
const [peer] = await peerUtils.createPeerId()
const multiaddrs = [multiaddr('/ip4/156.10.1.22/tcp/1000')]
const multiaddrs = [new Multiaddr('/ip4/156.10.1.22/tcp/1000')]
const protocols = ['/ping/1.0.0']
const commitSpy = sinon.spy(peerStore, '_commitData')
@ -221,7 +221,7 @@ describe('Persisted PeerStore', () => {
it('should store certified peer records after peer marked as dirty (threshold 1)', async () => {
const [peerId] = await peerUtils.createPeerId()
const multiaddrs = [multiaddr('/ip4/156.10.1.22/tcp/1000')]
const multiaddrs = [new Multiaddr('/ip4/156.10.1.22/tcp/1000')]
const spyDirty = sinon.spy(peerStore, '_addDirtyPeer')
const spyDs = sinon.spy(datastore, 'batch')
const commitSpy = sinon.spy(peerStore, '_commitData')
@ -266,8 +266,8 @@ describe('Persisted PeerStore', () => {
const peers = await peerUtils.createPeerId({ number: 2 })
const commitSpy = sinon.spy(peerStore, '_commitData')
const multiaddrs = [
multiaddr('/ip4/156.10.1.22/tcp/1000'),
multiaddr('/ip4/156.10.1.23/tcp/1000')
new Multiaddr('/ip4/156.10.1.22/tcp/1000'),
new Multiaddr('/ip4/156.10.1.23/tcp/1000')
]
const peerRecord0 = new PeerRecord({
peerId: peers[0],
@ -332,7 +332,7 @@ describe('Persisted PeerStore', () => {
it('should delete certified peer records from the datastore on delete', async () => {
const [peer] = await peerUtils.createPeerId()
const multiaddrs = [multiaddr('/ip4/156.10.1.22/tcp/1000')]
const multiaddrs = [new Multiaddr('/ip4/156.10.1.22/tcp/1000')]
const commitSpy = sinon.spy(peerStore, '_commitData')
await peerStore.start()
@ -395,7 +395,7 @@ describe('Persisted PeerStore', () => {
const peers = await peerUtils.createPeerId({ number: 2 })
const multiaddrs = [multiaddr('/ip4/156.10.1.22/tcp/1000')]
const multiaddrs = [new Multiaddr('/ip4/156.10.1.22/tcp/1000')]
const protocols = ['/ping/1.0.0']
await peerStore.start()
@ -540,8 +540,8 @@ describe('libp2p.peerStore (Persisted)', () => {
const commitSpy = sinon.spy(libp2p.peerStore, '_commitData')
const peers = await peerUtils.createPeerId({ number: 3 })
const multiaddrs = [
multiaddr('/ip4/156.10.1.22/tcp/1000'),
multiaddr('/ip4/156.10.1.23/tcp/1000')
new Multiaddr('/ip4/156.10.1.22/tcp/1000'),
new Multiaddr('/ip4/156.10.1.23/tcp/1000')
]
const protocols = ['/ping/1.0.0']
@ -572,6 +572,11 @@ describe('libp2p.peerStore (Persisted)', () => {
datastore: memoryDatastore,
peerStore: {
persistence: true
},
config: {
peerDiscovery: {
autoDial: false
}
}
}
})

View File

@ -3,13 +3,13 @@
const { expect } = require('aegir/utils/chai')
const mergeOptions = require('merge-options')
const multiaddr = require('multiaddr')
const { Multiaddr } = require('multiaddr')
const { create } = require('../../src')
const { baseOptions, subsystemOptions } = require('./utils')
const peerUtils = require('../utils/creators/peer')
const listenAddr = multiaddr('/ip4/127.0.0.1/tcp/0')
const listenAddr = new Multiaddr('/ip4/127.0.0.1/tcp/0')
describe('Pubsub subsystem is configurable', () => {
let libp2p

Some files were not shown because too many files have changed in this diff Show More