Compare commits

..

52 Commits

Author SHA1 Message Date
Vasco Santos
d19401aa4c chore: release version v0.30.0 2020-12-16 14:03:09 +01:00
Vasco Santos
24bb8df521 chore: update contributors 2020-12-16 14:03:09 +01:00
Vasco Santos
58d4f9a915 chore: release version v0.30.0-rc.2 2020-12-16 13:56:41 +01:00
Vasco Santos
239413e331 chore: update contributors 2020-12-16 13:56:41 +01:00
Vasco Santos
01d43a7b60 chore: fix multicodec updates (#835)
* chore: fix specific multicodec version

* chore: fix multicodec issues

* chore: remove prepare script
2020-12-16 13:56:41 +01:00
Vasco Santos
37d66fd88c chore: release version v0.30.0-rc.1 2020-12-16 13:56:41 +01:00
Vasco Santos
21e8ced81a chore: update contributors 2020-12-16 13:56:41 +01:00
Vasco Santos
9ae1b758e9 fix: types from ipfs integration (#832) 2020-12-16 13:56:41 +01:00
Vasco Santos
408868655c chore: remove secio from packages table (#833) 2020-12-16 13:56:41 +01:00
Vasco Santos
c5f61ac05f chore: release version v0.30.0-rc.0 2020-12-16 13:56:41 +01:00
Vasco Santos
5d0ac529e4 chore: update contributors 2020-12-16 13:56:41 +01:00
Vasco Santos
bc05083207 docs: production guide base setup (#804) 2020-12-16 13:56:41 +01:00
Vasco Santos
169bb806a7 chore: add typedefs (#802) 2020-12-16 13:56:41 +01:00
Vasco Santos
7809e6444e chore: auto relay configuration example with noise (#828) 2020-12-16 13:56:41 +01:00
Vasco Santos
f7e1426b9e chore: update pubsub example by disabled emit self (#823) 2020-12-16 13:56:41 +01:00
Vasco Santos
7d76ba1367 docs: migration 0.29 to 0.30 (#808) 2020-12-16 13:56:41 +01:00
Vasco Santos
b538ebdc0a chore: use set-delayed-interval module on circuit (#809) 2020-12-16 13:56:41 +01:00
Vasco Santos
baedf3fe5a feat: discover and connect to closest peers (#798) 2020-12-16 13:56:41 +01:00
Vasco Santos
4ebcdb085c chore: update websockets (#806)
* chore: update websockets
2020-12-16 13:56:41 +01:00
Vasco Santos
4448de8432 docs: auto relay example (#795)
* chore: auto relay example

* chore: update examples to use process arguments

* chore: add test setup for node tests and test for auto-relay

* chore: apply suggestions from code review

* chore: do not use promise for multiaddrs event on example
2020-12-16 13:56:41 +01:00
Vasco Santos
585ad52b4c feat: custom dialer addr sorter (#792)
* feat: custom dialer addr sorter

* chore: use libp2p utils sorter via addressBook getMultiaddrsForPeer

* chore: use new libp2p utils

* chore: apply suggestions from code review

Co-authored-by: Jacob Heun <jacobheun@gmail.com>

Co-authored-by: Jacob Heun <jacobheun@gmail.com>
2020-12-16 13:56:41 +01:00
Vasco Santos
e50c6abcf2 chore: update pubsub (#801)
BREAKING CHANGE: pubsub signing policy properties were changed according to libp2p-interfaces changes to a single property. The emitSelf option default value was also modified to match the routers value
2020-12-16 13:56:41 +01:00
Vasco Santos
49fffda23c test: custom announce filter 2020-12-16 13:56:41 +01:00
Vasco Santos
689c35ed1c fix: remove test/dialing/utils extra file 2020-12-16 13:56:41 +01:00
Vasco Santos
1a13e2c6ca chore: update address manager readme 2020-12-16 13:56:41 +01:00
Vasco Santos
5758db8ea9 chore: remove noAnnounce from address manager 2020-12-16 13:56:41 +01:00
Vasco Santos
ef9d3ca2c6 feat: custom announce filter 2020-12-16 13:56:41 +01:00
Vasco Santos
97e3633f47 chore: store self protocols in protobook (#760) 2020-12-16 13:56:41 +01:00
Vasco Santos
e36b67a212 chore: improve logging for auto relay active listen 2020-12-16 13:56:41 +01:00
Vasco Santos
e977039c8a chore: sort relay addresses to listen for public first 2020-12-16 13:56:41 +01:00
Vasco Santos
a5337c1797 chore: lint issues fixed 2020-12-16 13:56:41 +01:00
Vasco Santos
ee23fb9508 chore: apply suggestions from code review
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
2020-12-16 13:56:41 +01:00
Vasco Santos
11a46ea71e chore: add configuration docs for auto relay and hop service 2020-12-16 13:56:41 +01:00
Vasco Santos
5c72424e57 chore: address review 2020-12-16 13:56:41 +01:00
Vasco Santos
0bf0b7cf89 feat: auto relay network query for new relays 2020-12-16 13:56:41 +01:00
Vasco Santos
55020056ee chore: lint issue fixed 0.30 2020-12-16 13:56:41 +01:00
Vasco Santos
bb83cacb5a chore: address review 2020-12-16 13:56:41 +01:00
Vasco Santos
447d0ed0dd chore: add identify test for multiaddr change 2020-12-16 13:56:41 +01:00
Vasco Santos
43eda43f06 chore: create signed peer record on new listen addresses in transport manager 2020-12-16 13:56:41 +01:00
Vasco Santos
7b93ece7f2 chore: use listening events to create self peer record on updates 2020-12-16 13:56:41 +01:00
Vasco Santos
74bdfd1024 chore: _isStarted is false when stop starts 2020-12-16 13:56:41 +01:00
Vasco Santos
4d1fcdb3d2 chore: auto relay multiaddr update push 2020-12-16 13:56:41 +01:00
Vasco Santos
caf66ea143 feat: auto relay (#723)
* feat: auto relay

* fix: leverage protoBook events to ask relay peers if they support hop

* chore: refactor disconnect

* chore: do not listen on a relayed conn

* chore: tweaks

* chore: improve _listenOnAvailableHopRelays logic

* chore: default value of 1 to maxListeners on auto-relay
2020-12-16 13:56:41 +01:00
Jacob Heun
48656712ea chore: release version v0.29.4 2020-12-09 16:42:21 +01:00
Jacob Heun
1a5ae74741 chore: update contributors 2020-12-09 16:42:20 +01:00
Smite Chow
8691465a52 feat: support custom listener options (#822)
* support custom listener options

* fix get listener options

* add doc to explain custom listener options

* add ut

* fix code style

* Apply suggestions from code review

Co-authored-by: Vasco Santos <vasco.santos@ua.pt>

* add missing comma

Co-authored-by: Vasco Santos <vasco.santos@ua.pt>
2020-12-09 16:31:17 +01:00
Vasco Santos
6350a187c7 fix: dial self (#826) 2020-12-09 16:13:25 +01:00
Michael Burns
8e3bb09279 chore: remove references to Solarnet (#820)
Co-authored-by: Vasco Santos <vasco.santos@ua.pt>
2020-12-01 19:10:47 +01:00
a1300
73204958ee docs: use Libp2p.create() in examples (#811) (#814) 2020-11-30 11:15:09 +01:00
a1300
e9e4b731a5 docs: fix JSDOc for stop and create (#812) (#813) 2020-11-27 10:50:35 +01:00
Vasco Santos
d0a9fada32 feat: custom and store self agent version + store self protocol version (#800)
* feat: custom and store self protocol and agent version

* fix: do not enable custom protocolVersion
2020-11-20 15:14:01 +01:00
Samlior
824a444f56 docs(fix): fix contentRouting.getMany (#803) 2020-11-18 10:28:43 +01:00
39 changed files with 601 additions and 232 deletions

View File

@@ -1,3 +1,89 @@
# [0.30.0](https://github.com/libp2p/js-libp2p/compare/v0.29.4...v0.30.0) (2020-12-16)
### Bug Fixes
* remove test/dialing/utils extra file ([689c35e](https://github.com/libp2p/js-libp2p/commit/689c35ed1c68e514293a9895d496e2e8440454e9))
* types from ipfs integration ([#832](https://github.com/libp2p/js-libp2p/issues/832)) ([9ae1b75](https://github.com/libp2p/js-libp2p/commit/9ae1b758e99e3fc9067e26b4eae4c15ccb1ba303))
### chore
* update pubsub ([#801](https://github.com/libp2p/js-libp2p/issues/801)) ([e50c6ab](https://github.com/libp2p/js-libp2p/commit/e50c6abcf2ebc80ebf2dfadd015ab21a20cffadc))
### Features
* auto relay ([#723](https://github.com/libp2p/js-libp2p/issues/723)) ([caf66ea](https://github.com/libp2p/js-libp2p/commit/caf66ea1439f6b75a0c321a16bd5c5d7d6a2bd47))
* auto relay network query for new relays ([0bf0b7c](https://github.com/libp2p/js-libp2p/commit/0bf0b7cf8968d55002ac4c559ffb59985feeb092))
* custom announce filter ([ef9d3ca](https://github.com/libp2p/js-libp2p/commit/ef9d3ca2c6f35d692d6079e74088c5146d46eebe))
* custom dialer addr sorter ([#792](https://github.com/libp2p/js-libp2p/issues/792)) ([585ad52](https://github.com/libp2p/js-libp2p/commit/585ad52b4c71dd7514e99a287e0318b2b837ec48))
* discover and connect to closest peers ([#798](https://github.com/libp2p/js-libp2p/issues/798)) ([baedf3f](https://github.com/libp2p/js-libp2p/commit/baedf3fe5ab946e938db1415d1662452cdfc0cc1))
### BREAKING CHANGES
* pubsub signing policy properties were changed according to libp2p-interfaces changes to a single property. The emitSelf option default value was also modified to match the routers value
# [0.30.0-rc.2](https://github.com/libp2p/js-libp2p/compare/v0.30.0-rc.1...v0.30.0-rc.2) (2020-12-15)
# [0.30.0-rc.1](https://github.com/libp2p/js-libp2p/compare/v0.30.0-rc.0...v0.30.0-rc.1) (2020-12-11)
### Bug Fixes
* types from ipfs integration ([#832](https://github.com/libp2p/js-libp2p/issues/832)) ([216eb97](https://github.com/libp2p/js-libp2p/commit/216eb9730ef473f73a974c3dbaf306ecdc815c8b))
# [0.30.0-rc.0](https://github.com/libp2p/js-libp2p/compare/v0.29.4...v0.30.0-rc.0) (2020-12-10)
### Bug Fixes
* remove test/dialing/utils extra file ([3f1dc20](https://github.com/libp2p/js-libp2p/commit/3f1dc20caf1c80078f403deb9174cd06d08567ab))
### chore
* update pubsub ([#801](https://github.com/libp2p/js-libp2p/issues/801)) ([9205fce](https://github.com/libp2p/js-libp2p/commit/9205fce34d0cd8dd5d32988be34c110fc0a5b6e2))
### Features
* auto relay ([#723](https://github.com/libp2p/js-libp2p/issues/723)) ([65ec267](https://github.com/libp2p/js-libp2p/commit/65ec267e7f4826caacd042213c3fbacce589ab5b))
* auto relay network query for new relays ([9faf1bf](https://github.com/libp2p/js-libp2p/commit/9faf1bfcf61581acc715b9be78b71dc14501835a))
* custom announce filter ([48476d5](https://github.com/libp2p/js-libp2p/commit/48476d504a98b7b51b3e2dc64eab93670fde0c7b))
* custom dialer addr sorter ([#792](https://github.com/libp2p/js-libp2p/issues/792)) ([91b15b6](https://github.com/libp2p/js-libp2p/commit/91b15b6790952b4db11264961d9c6f2a96d1fe43))
* discover and connect to closest peers ([#798](https://github.com/libp2p/js-libp2p/issues/798)) ([b73106e](https://github.com/libp2p/js-libp2p/commit/b73106eba2d559621f427f7aa788e9b0ef47d135))
### BREAKING CHANGES
* pubsub signing policy properties were changed according to libp2p-interfaces changes to a single property. The emitSelf option default value was also modified to match the routers value
<a name="0.29.4"></a>
## [0.29.4](https://github.com/libp2p/js-libp2p/compare/v0.29.3...v0.29.4) (2020-12-09)
### Bug Fixes
* dial self ([#826](https://github.com/libp2p/js-libp2p/issues/826)) ([6350a18](https://github.com/libp2p/js-libp2p/commit/6350a18))
### Features
* custom and store self agent version + store self protocol version ([#800](https://github.com/libp2p/js-libp2p/issues/800)) ([d0a9fad](https://github.com/libp2p/js-libp2p/commit/d0a9fad))
* support custom listener options ([#822](https://github.com/libp2p/js-libp2p/issues/822)) ([8691465](https://github.com/libp2p/js-libp2p/commit/8691465))
<a name="0.29.3"></a>
## [0.29.3](https://github.com/libp2p/js-libp2p/compare/v0.29.2...v0.29.3) (2020-11-04)

View File

@@ -147,7 +147,6 @@ List of packages currently in existence for libp2p
| [`libp2p-websockets`](//github.com/libp2p/js-libp2p-websockets) | [![npm](https://img.shields.io/npm/v/libp2p-websockets.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-websockets/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-websockets.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-websockets) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-websockets/master)](https://travis-ci.com/libp2p/js-libp2p-websockets) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-websockets/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-websockets) | [Jacob Heun](mailto:jacobheun@gmail.com) |
| **secure channels** |
| [`libp2p-noise`](//github.com/NodeFactoryIo/js-libp2p-noise) | [![npm](https://img.shields.io/npm/v/libp2p-noise.svg?maxAge=86400&style=flat-square)](//github.com/NodeFactoryIo/js-libp2p-noise/releases) | [![Deps](https://david-dm.org/NodeFactoryIo/js-libp2p-noise.svg?style=flat-square)](https://david-dm.org/NodeFactoryIo/js-libp2p-noise) | [![Travis CI](https://flat.badgen.net/travis/NodeFactoryIo/js-libp2p-noise/master)](https://travis-ci.com/NodeFactoryIo/js-libp2p-noise) | [![codecov](https://codecov.io/gh/NodeFactoryIo/js-libp2p-noise/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/NodeFactoryIo/js-libp2p-noise) | N/A |
| [`libp2p-secio`](//github.com/libp2p/js-libp2p-secio) | [![npm](https://img.shields.io/npm/v/libp2p-secio.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-secio/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-secio.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-secio) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-secio/master)](https://travis-ci.com/libp2p/js-libp2p-secio) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-secio/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-secio) | [Friedel Ziegelmayer](mailto:dignifiedquire@gmail.com) |
| **stream multiplexers** |
| [`libp2p-mplex`](//github.com/libp2p/js-libp2p-mplex) | [![npm](https://img.shields.io/npm/v/libp2p-mplex.svg?maxAge=86400&style=flat-square)](//github.com/libp2p/js-libp2p-mplex/releases) | [![Deps](https://david-dm.org/libp2p/js-libp2p-mplex.svg?style=flat-square)](https://david-dm.org/libp2p/js-libp2p-mplex) | [![Travis CI](https://flat.badgen.net/travis/libp2p/js-libp2p-mplex/master)](https://travis-ci.com/libp2p/js-libp2p-mplex) | [![codecov](https://codecov.io/gh/libp2p/js-libp2p-mplex/branch/master/graph/badge.svg?style=flat-square)](https://codecov.io/gh/libp2p/js-libp2p-mplex) | [Vasco Santos](mailto:vasco.santos@moxy.studio) |
| **peer discovery** |

View File

@@ -93,6 +93,7 @@ Creates an instance of Libp2p.
| options.modules | [`Array<object>`](./CONFIGURATION.md#modules) | libp2p [modules](./CONFIGURATION.md#modules) to use |
| [options.addresses] | `{ listen: Array<string>, announce: Array<string>, announceFilter: (ma: Array<multiaddr>) => Array<multiaddr> }` | Addresses for transport listening and to advertise to the network |
| [options.config] | `object` | libp2p modules configuration and core configuration |
| [options.host] | `{ agentVersion: string }` | libp2p host options |
| [options.connectionManager] | [`object`](./CONFIGURATION.md#configuring-connection-manager) | libp2p Connection Manager [configuration](./CONFIGURATION.md#configuring-connection-manager) |
| [options.transportManager] | [`object`](./CONFIGURATION.md#configuring-transport-manager) | libp2p transport manager [configuration](./CONFIGURATION.md#configuring-transport-manager) |
| [options.datastore] | `object` | must implement [ipfs/interface-datastore](https://github.com/ipfs/interface-datastore) (in memory datastore will be used if not provided) |
@@ -115,12 +116,25 @@ For Libp2p configurations and modules details read the [Configuration Document](
```js
const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
// specify options
const options = {}
async function main () {
// specify options
const options = {
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
}
}
// create libp2p
const libp2p = await Libp2p.create(options)
// create libp2p
const libp2p = await Libp2p.create(options)
}
main()
```
Note: The [`PeerId`][peer-id] option is not required and will be generated if it is not provided.
@@ -132,12 +146,30 @@ As an alternative, it is possible to create a Libp2p instance with the construct
```js
const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const { NOISE } = require('libp2p-noise')
const PeerId = require('peer-id')
// specify options
const options = {}
async function main () {
const peerId = await PeerId.create();
// create libp2p
const libp2p = new Libp2p(options)
// specify options
// peerId is required when Libp2p is instantiated via the constructor
const options = {
peerId,
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
}
}
// create libp2p
const libp2p = new Libp2p(options)
}
main()
```
Required keys in the `options` object:
@@ -647,7 +679,7 @@ Queries the DHT for the n values stored for the given key (without sorting).
// ...
const key = '/key'
const { from, val } = await libp2p.contentRouting.get(key)
const records = await libp2p.contentRouting.getMany(key, 2)
```
### peerRouting.findPeer

View File

@@ -445,13 +445,13 @@ const node = await Libp2p.create({
const Libp2p = require('libp2p')
const TCP = require('libp2p-tcp')
const MPLEX = require('libp2p-mplex')
const SECIO = require('libp2p-secio')
const { NOISE } = require('libp2p-noise')
const node = await Libp2p.create({
modules: {
transport: [TCP],
streamMuxer: [MPLEX],
connEncryption: [SECIO]
connEncryption: [NOISE]
},
config: {
relay: { // Circuit Relay options (this config is part of libp2p core configurations)
@@ -694,6 +694,35 @@ const node = await Libp2p.create({
})
```
During Libp2p startup, transport listeners will be created for the configured listen multiaddrs. Some transports support custom listener options and you can set them using the `listenerOptions` in the transport configuration. For example, [libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) transport listener supports the configuration of its underlying [simple-peer](https://github.com/feross/simple-peer) ice server(STUN/TURN) config as follows:
```js
const transportKey = WebRTCStar.prototype[Symbol.toStringTag]
const node = await Libp2p.create({
modules: {
transport: [WebRTCStar],
streamMuxer: [MPLEX],
connEncryption: [NOISE]
},
addresses: {
listen: ['/dns4/your-wrtc-star.pub/tcp/443/wss/p2p-webrtc-star'] // your webrtc dns multiaddr
},
config: {
transport: {
[transportKey]: {
listenerOptions: {
config: {
iceServers: [
{"urls": ["turn:YOUR.TURN.SERVER:3478"], "username": "YOUR.USER", "credential": "YOUR.PASSWORD"},
{"urls": ["stun:YOUR.STUN.SERVER:3478"], "username": "", "credential": ""}]
}
}
}
}
}
})
```
## Configuration examples
As libp2p is designed to be a modular networking library, its usage will vary based on individual project needs. We've included links to some existing project configurations for your reference, in case you wish to replicate their configuration:

View File

@@ -0,0 +1,3 @@
# Delegate Nodes
[TODO](https://github.com/libp2p/js-libp2p/pull/718)

65
doc/production/README.md Normal file
View File

@@ -0,0 +1,65 @@
# Production
Nowadays, you can run JavaScript code in several different environments, some of them with their own particularities. Moreover, you can use `js-libp2p` for a wide range of use cases. Different environments and different use cases mean different configurations and challenges in the network.
Libp2p nodes can vary from nodes behind an application, to infrastructure nodes that enable the network to operate and to be efficient. In this context, the Libp2p project provides public infrastructure to boost the network, enable nodes connectivity and improve constrained nodes performance. This public infrastructure should be leveraged for learning the concepts and experimenting. When an application on top of libp2p aims to move into production, its own infrastructure should be setup as the public nodes will be intensively used by others and its availability is not guaranteed.
This guide aims to guide you from using the public infrastructure into setting up your own.
## Table of Contents
* [Joining the Network](#joining-the-network)
* [Connecting to Nodes with connectivity limitations](#connecting-to-nodes-with-connectivity-limitations)
* [`webrtc-star` servers](#webrtc-star-servers)
* [Circuit Relay](#circuit-relay)
* [Querying the network from the browser](#querying-the-network-from-the-browser)
* [Others](#others)
* [SSL](#ssl)
## Joining the Network
Once a libp2p node stars, it will need to connect to a set of peers in order to establish its overlay network.
Currently `js-libp2p` is not the best choice for being a bootstrap node. Its DHT needs to be improved, in order to become an effective server to enable other nodes to properly bootstrap their network.
Setting up a fleet of [`go-libp2p`](https://github.com/libp2p/go-libp2p) nodes is the recommended way to proceed here.
## Connecting to Nodes with connectivity limitations
While the libp2p core codebase aims to work in multiple environments, there are some limitations that are not possible to overcome at the time of writing. These limitations include browser nodes, nodes behind NAT, reverse proxies, firewalls, or lack of compatible transports.
In the browser, libp2p supports two transports: `websockets` and `webrtc-star`. Nowadays, browsers do not support listening for connections, but only to dial known addresses. `webrtc-star` servers can be used to enable libp2p nodes to discover other nodes running on the browser and to help them establish a connection.
For nodes that cannot be dialed (including browser), circuit relay nodes should be used.
### `webrtc-star` servers
Regarding `webRTC` connections, a set of star servers are needed to act as a rendezvous point, where peers can learn about other peers (`peer-discovery`), as well as exchange their SDP offers (signaling data).
You can read on how to setup your own star servers in [libp2p/js-libp2p-webrtc-star/DEPLOYMENT.md](https://github.com/libp2p/js-libp2p-webrtc-star/blob/master/DEPLOYMENT.md).
It is worth pointing out that with new discovery protocols on the way, as well as support for distributed signaling, the star servers should be deprecated on the long run.
### Circuit Relay
Libp2p nodes acting as circuit relay aim to establish connectivity between libp2p nodes (e.g. IPFS nodes) that wouldn't otherwise be able to establish a direct connection to each other.
A relay is needed in situations where nodes are behind NAT, reverse proxies, firewalls and/or simply don't support the same transports (e.g. go-libp2p vs. browser-libp2p). The circuit relay protocol exists to overcome those scenarios. Nodes with the `auto-relay` feature enabled can automatically bind themselves on a relay to listen for connections on their behalf.
You can use [libp2p/js-libp2p-relay-server](https://github.com/libp2p/js-libp2p-relay-server) to setup your own relay server. This also includes an easy to customize Docker setup for a HOP Relay.
## Querying the network from the browser
Libp2p nodes in scenarios such as browser environment and constrained devices will not be an efficient node in the libp2p DHT overlay, as a consequence of their known limitations regarding connectivity and performance.
Aiming to support these type of nodes to find other peers and content in the network, delegate nodes can be setup. With a set of well known IPFS delegate nodes, nodes with limitations in the network can leverage them to perform peer and content routing queries.
Currently, delegate nodes must be IPFS nodes as the IPFS HTTP API is leveraged by them to make routing queries.
You can read on how to setup your own set of delegated nodes in [DELEGATE_NODES.md](./DELEGATE_NODES.md).
## Others
### SSL
TODO

View File

@@ -3,7 +3,7 @@
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
const Node = require('./libp2p-bundle')
const createLibp2p = require('./libp2p-bundle')
const { stdinToStream, streamToConsole } = require('./stream')
async function run() {
@@ -13,7 +13,7 @@ async function run() {
])
// Create a new libp2p node on localhost with a randomly chosen port
const nodeDialer = new Node({
const nodeDialer = await createLibp2p({
peerId: idDialer,
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0']

View File

@@ -7,21 +7,16 @@ const { NOISE } = require('libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../../..')
class Node extends libp2p {
constructor (_options) {
const defaults = {
modules: {
transport: [
TCP,
WS
],
streamMuxer: [ mplex ],
connEncryption: [ NOISE ]
}
}
super(defaultsDeep(_options, defaults))
async function createLibp2p(_options) {
const defaults = {
modules: {
transport: [TCP, WS],
streamMuxer: [mplex],
connEncryption: [NOISE],
},
}
return libp2p.create(defaultsDeep(_options, defaults))
}
module.exports = Node
module.exports = createLibp2p

View File

@@ -2,13 +2,13 @@
/* eslint-disable no-console */
const PeerId = require('peer-id')
const Node = require('./libp2p-bundle.js')
const createLibp2p = require('./libp2p-bundle.js')
const { stdinToStream, streamToConsole } = require('./stream')
async function run() {
// Create a new libp2p node with the given multi-address
const idListener = await PeerId.createFromJSON(require('./peer-id-listener'))
const nodeListener = new Node({
const nodeListener = await createLibp2p({
peerId: idListener,
addresses: {
listen: ['/ip4/0.0.0.0/tcp/10333']

View File

@@ -10,14 +10,11 @@ const Bootstrap = require('libp2p-bootstrap')
// Find this list at: https://github.com/ipfs/js-ipfs/blob/master/src/core/runtime/config-nodejs.json
const bootstrapers = [
'/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z',
'/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
'/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
'/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
'/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
'/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
'/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
]
;(async () => {

View File

@@ -40,14 +40,11 @@ In this configuration, we use a `bootstrappers` array listing peers to connect _
```JavaScript
const bootstrapers = [
'/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ',
'/ip4/104.236.176.52/tcp/4001/p2p/QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z',
'/ip4/104.236.179.241/tcp/4001/p2p/QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM',
'/ip4/162.243.248.213/tcp/4001/p2p/QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm',
'/ip4/128.199.219.111/tcp/4001/p2p/QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu',
'/ip4/104.236.76.40/tcp/4001/p2p/QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64',
'/ip4/178.62.158.247/tcp/4001/p2p/QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd',
'/ip4/178.62.61.185/tcp/4001/p2p/QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3',
'/ip4/104.236.151.122/tcp/4001/p2p/QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx'
'/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa',
'/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt'
]
```
@@ -93,23 +90,17 @@ From running [1.js](./1.js), you should see the following:
```bash
> node 1.js
Discovered: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
Discovered: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z
Discovered: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM
Discovered: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm
Discovered: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu
Discovered: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64
Discovered: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
Discovered: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
Discovered: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
Discovered: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
Discovered: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb
Discovered: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp
Discovered: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa
Discovered: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt
Connection established to: QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
Connection established to: QmSoLnSGccFuZQJzRadHn95W2CrSFmZuTdDWP8HXaHca9z
Connection established to: QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM
Connection established to: QmSoLueR4xBeUbY9WZ9xGUUxunbKWcrNFTDAadQJmocnWm
Connection established to: QmSoLSafTMBsPKadTEgaXctDQVcqN88CNLHXMkTNwMKPnu
Connection established to: QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64
Connection established to: QmSoLer265NRgSp2LA3dPaeykiS1J6DifTC88f5uVQKNAd
Connection established to: QmSoLMeWqB7YGVLJN3pNLQpmmEk35v6wYtsMGLzSr5QBU3
Connection established to: QmSoLju6m7xTh3DuokvT3886QRYqxAzb1kShaanJgW36yx
Connection established to: QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN
Connection established to: QmZa1sAxajnQjVM8WjWXoMbmPd7NsWhfKsPkErzpm9wGkp
Connection established to: QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa
Connection established to: QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt
Connection established to: QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb
```
## 2. MulticastDNS to find other peers in the network

View File

@@ -5,9 +5,8 @@
* Dialer Node
*/
const multiaddr = require('multiaddr')
const PeerId = require('peer-id')
const Node = require('./libp2p-bundle')
const createLibp2p = require('./libp2p-bundle')
const pipe = require('it-pipe')
async function run() {
@@ -17,7 +16,7 @@ async function run() {
])
// Dialer
const dialerNode = new Node({
const dialerNode = await createLibp2p({
addresses: {
listen: ['/ip4/0.0.0.0/tcp/0']
},

View File

@@ -8,21 +8,16 @@ const { NOISE } = require('libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('../../..')
class Node extends libp2p {
constructor (_options) {
const defaults = {
modules: {
transport: [
TCP,
WS
],
streamMuxer: [ mplex ],
connEncryption: [ NOISE ]
}
}
super(defaultsDeep(_options, defaults))
async function createLibp2p(_options) {
const defaults = {
modules: {
transport: [TCP, WS],
streamMuxer: [mplex],
connEncryption: [NOISE],
},
}
return libp2p.create(defaultsDeep(_options, defaults))
}
module.exports = Node
module.exports = createLibp2p

View File

@@ -6,14 +6,14 @@
*/
const PeerId = require('peer-id')
const Node = require('./libp2p-bundle')
const createLibp2p = require('./libp2p-bundle')
const pipe = require('it-pipe')
async function run() {
const listenerId = await PeerId.createFromJSON(require('./id-l'))
// Listener libp2p node
const listenerNode = new Node({
const listenerNode = await createLibp2p({
addresses: {
listen: ['/ip4/0.0.0.0/tcp/10333']
},

View File

@@ -43,6 +43,7 @@ const createNode = async () => {
})
await node1.pubsub.subscribe(topic)
// Will not receive own published messages by default
node2.pubsub.on(topic, (msg) => {
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
})

View File

@@ -44,7 +44,6 @@ const node2 = nodes[1]
// Add node's 2 data to the PeerStore
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
await node1.dial(node2.peerId)
node1.pubsub.on(topic, (msg) => {
@@ -52,6 +51,7 @@ node1.pubsub.on(topic, (msg) => {
})
await node1.pubsub.subscribe(topic)
// Will not receive own published messages by default
node2.pubsub.on(topic, (msg) => {
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
})
@@ -68,25 +68,34 @@ The output of the program should look like:
```
> node 1.js
connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82
node2 received: Bird bird bird, bird is the word!
node1 received: Bird bird bird, bird is the word!
node2 received: Bird bird bird, bird is the word!
node1 received: Bird bird bird, bird is the word!
```
You can change the pubsub `emitSelf` option if you don't want the publishing node to receive its own messages.
You can change the pubsub `emitSelf` option if you want the publishing node to receive its own messages.
```JavaScript
const defaults = {
config: {
pubsub: {
enabled: true,
emitSelf: false
emitSelf: true
}
}
}
```
The output of the program should look like:
```
> node 1.js
connected to QmWpvkKm6qHLhoxpWrTswY6UMNWDyn8hN265Qp9ZYvgS82
node1 received: Bird bird bird, bird is the word!
node2 received: Bird bird bird, bird is the word!
node1 received: Bird bird bird, bird is the word!
node2 received: Bird bird bird, bird is the word!
```
## 2. Future work
libp2p/IPFS PubSub is enabling a whole set of Distributed Real Time applications using CRDT (Conflict-Free Replicated Data Types). It is still going through heavy research (and hacking) and we invite you to join the conversation at [research-CRDT](https://github.com/ipfs/research-CRDT). Here is a list of some of the exciting examples:

View File

@@ -44,6 +44,7 @@ const createNode = async () => {
//subscribe
node1.pubsub.on(topic, (msg) => {
// Will not receive own published messages by default
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
})
await node1.pubsub.subscribe(topic)

View File

@@ -97,15 +97,12 @@ Result
```
> node 1.js
############## fruit banana ##############
node1 received: banana
node2 received: banana
node3 received: banana
############## fruit apple ##############
node1 received: apple
node2 received: apple
node3 received: apple
############## fruit car ##############
node1 received: car
############## fruit orange ##############
node1 received: orange
node2 received: orange

View File

@@ -23,7 +23,6 @@
"secure channels",
["NodeFactoryIo/js-libp2p-noise", "libp2p-noise"],
["libp2p/js-libp2p-secio", "libp2p-secio"],
"stream multiplexers",
["libp2p/js-libp2p-mplex", "libp2p-mplex"],

View File

@@ -1,6 +1,6 @@
{
"name": "libp2p",
"version": "0.29.3",
"version": "0.30.0",
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
"main": "src/index.js",
@@ -70,7 +70,7 @@
"it-pipe": "^1.1.0",
"it-protocol-buffers": "^0.2.0",
"libp2p-crypto": "^0.18.0",
"libp2p-interfaces": "libp2p/js-libp2p-interfaces#feat/add-types-with-post-install",
"libp2p-interfaces": "^0.8.1",
"libp2p-utils": "^0.2.2",
"mafmt": "^8.0.0",
"merge-options": "^2.0.0",
@@ -145,6 +145,7 @@
"dirkmc <dirkmdev@gmail.com>",
"Volker Mische <volker.mische@gmail.com>",
"Richard Littauer <richard.littauer@gmail.com>",
"a1300 <matthias-knopp@gmx.net>",
"Elven <mon.samuel@qq.com>",
"Andrew Nesbitt <andrewnez@gmail.com>",
"Giovanni T. Parra <fiatjaf@gmail.com>",
@@ -152,8 +153,6 @@
"Thomas Eizinger <thomas@eizinger.io>",
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
"Didrik Nordström <didrik@betamos.se>",
"Henrique Dias <hacdias@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>",
"Irakli Gozalishvili <rfobic@gmail.com>",
"Ethan Lam <elmemphis2000@gmail.com>",
"Joel Gustafson <joelg@mit.edu>",
@@ -163,9 +162,11 @@
"Dmitriy Ryajov <dryajov@gmail.com>",
"RasmusErik Voel Jensen <github@solsort.com>",
"Diogo Silva <fsdiogo@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>",
"Samlior <samlior@foxmail.com>",
"Smite Chow <xiaopengyou@live.com>",
"Soeren <nikorpoulsen@gmail.com>",
"Sönke Hahn <soenkehahn@gmail.com>",
"robertkiel <robert.kiel@validitylabs.org>",
"Tiago Alves <alvesjtiago@gmail.com>",
"Daijiro Wachi <daijiro.wachi@gmail.com>",
"Yusef Napora <yusef@napora.org>",
@@ -174,9 +175,11 @@
"Chris Bratlien <chrisbratlien@gmail.com>",
"ebinks <elizabethjbinks@gmail.com>",
"Bernd Strehl <bernd.strehl@gmail.com>",
"isan_rivkin <isanrivkin@gmail.com>",
"Florian-Merle <florian.david.merle@gmail.com>",
"Francis Gulotta <wizard@roborooter.com>",
"Felipe Martins <felipebrasil93@gmail.com>"
"Felipe Martins <felipebrasil93@gmail.com>",
"isan_rivkin <isanrivkin@gmail.com>",
"Henrique Dias <hacdias@gmail.com>",
"Fei Liu <liu.feiwood@gmail.com>"
]
}

View File

@@ -4,6 +4,7 @@ const mergeOptions = require('merge-options')
const { dnsaddrResolver } = require('multiaddr/src/resolvers')
const Constants = require('./constants')
const { AGENT_VERSION } = require('./identify/consts')
const RelayConstants = require('./circuit/constants')
const { publicAddressesFirst } = require('libp2p-utils/src/address-sort')
@@ -30,6 +31,9 @@ const DefaultConfig = {
},
addressSorter: publicAddressesFirst
},
host: {
agentVersion: AGENT_VERSION
},
metrics: {
enabled: false
},

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_DIALED_SELF: 'ERR_DIALED_SELF',
ERR_DISCOVERED_SELF: 'ERR_DISCOVERED_SELF',
ERR_DUPLICATE_TRANSPORT: 'ERR_DUPLICATE_TRANSPORT',
ERR_ENCRYPTION_FAILED: 'ERR_ENCRYPTION_FAILED',

View File

@@ -48,6 +48,15 @@ class IdentifyService {
this.handleMessage = this.handleMessage.bind(this)
// Store self host metadata
this._host = {
agentVersion: AGENT_VERSION,
protocolVersion: PROTOCOL_VERSION,
...libp2p._options.host
}
this.peerStore.metadataBook.set(this.peerId, 'AgentVersion', uint8ArrayFromString(this._host.agentVersion))
this.peerStore.metadataBook.set(this.peerId, 'ProtocolVersion', uint8ArrayFromString(this._host.protocolVersion))
// When a new connection happens, trigger identify
this.connectionManager.on('peer:connect', (connection) => {
this.identify(connection).catch(log.error)
@@ -236,8 +245,8 @@ class IdentifyService {
const protocols = this.peerStore.protoBook.get(this.peerId) || []
const message = Message.encode({
protocolVersion: PROTOCOL_VERSION,
agentVersion: AGENT_VERSION,
protocolVersion: this._host.protocolVersion,
agentVersion: this._host.agentVersion,
publicKey,
listenAddrs: this._libp2p.multiaddrs.map((ma) => ma.bytes),
signedPeerRecord,

View File

@@ -80,11 +80,32 @@ const IDENTIFY_PROTOCOLS = IdentifyService.multicodecs
* @property {Libp2pConfig} [config]
* @property {PeerId} peerId
*
* @typedef {Object} CreateOptions
* @property {PeerId} peerId
*
* @extends {EventEmitter}
* @fires Libp2p#error Emitted when an error occurs
* @fires Libp2p#peer:discovery Emitted when a peer is discovered
*/
class Libp2p extends EventEmitter {
/**
* Like `new Libp2p(options)` except it will create a `PeerId`
* instance if one is not provided in options.
*
* @param {Libp2pOptions & CreateOptions} options - Libp2p configuration options
* @returns {Promise<Libp2p>}
*/
static async create (options) {
if (options.peerId) {
return new Libp2p(options)
}
const peerId = await PeerId.create()
options.peerId = peerId
return new Libp2p(options)
}
/**
* Libp2p node.
*
@@ -401,6 +422,11 @@ class Libp2p extends EventEmitter {
*/
async dialProtocol (peer, protocols, options) {
const { id, multiaddrs } = getPeer(peer)
if (id.equals(this.peerId)) {
throw errCode(new Error('Cannot dial self'), codes.ERR_DIALED_SELF)
}
let connection = this.connectionManager.get(id)
if (!connection) {
@@ -656,27 +682,4 @@ class Libp2p extends EventEmitter {
}
}
/**
* @typedef {Object} CreateOptions
* @property {PeerId} peerId
*/
/**
* Like `new Libp2p(options)` except it will create a `PeerId`
* instance if one is not provided in options.
*
* @param {Libp2pOptions & CreateOptions} options - Libp2p configuration options
* @returns {Promise<Libp2p>}
*/
Libp2p.create = async function create (options) {
if (options.peerId) {
return new Libp2p(options)
}
const peerId = await PeerId.create()
options.peerId = peerId
return new Libp2p(options)
}
module.exports = Libp2p

View File

@@ -1,4 +1,3 @@
// @ts-nocheck
'use strict'
require('node-forge/lib/pkcs7')
@@ -9,6 +8,8 @@ const errcode = require('err-code')
const uint8ArrayFromString = require('uint8arrays/from-string')
const uint8ArrayToString = require('uint8arrays/to-string')
const privates = new WeakMap()
/**
* Cryptographic Message Syntax (aka PKCS #7)
*
@@ -23,13 +24,15 @@ class CMS {
* Creates a new instance with a keychain
*
* @param {import('./index')} keychain - the available keys
* @param {string} dek
*/
constructor (keychain) {
constructor (keychain, dek) {
if (!keychain) {
throw errcode(new Error('keychain is required'), 'ERR_KEYCHAIN_REQUIRED')
}
this.keychain = keychain
privates.set(this, { dek })
}
/**
@@ -48,7 +51,9 @@ class CMS {
const key = await this.keychain.findKeyByName(name)
const pem = await this.keychain._getPrivateKey(name)
const privateKey = forge.pki.decryptRsaPrivateKey(pem, this.keychain._())
/** @type {string} */
const dek = privates.get(this).dek
const privateKey = forge.pki.decryptRsaPrivateKey(pem, dek)
const certificate = await certificateForKey(key, privateKey)
// create a p7 enveloped message
@@ -115,8 +120,14 @@ class CMS {
}
const key = await this.keychain.findKeyById(r.keyId)
if (!key) {
throw errcode(new Error('No key available to decrypto'), 'ERR_NO_KEY')
}
const pem = await this.keychain._getPrivateKey(key.name)
const privateKey = forge.pki.decryptRsaPrivateKey(pem, this.keychain._())
const dek = privates.get(this).dek
const privateKey = forge.pki.decryptRsaPrivateKey(pem, dek)
cms.decrypt(r.recipient, privateKey)
return uint8ArrayFromString(cms.content.getBytes(), 'ascii')
}

View File

@@ -1,11 +1,10 @@
// @ts-nocheck
/* eslint max-nested-callbacks: ["error", 5] */
'use strict'
const sanitize = require('sanitize-filename')
const mergeOptions = require('merge-options')
const crypto = require('libp2p-crypto')
const DS = require('interface-datastore')
const Datastore = require('interface-datastore')
const CMS = require('./cms')
const errcode = require('err-code')
const { Number } = require('ipfs-utils/src/globalthis')
@@ -14,8 +13,14 @@ const uint8ArrayFromString = require('uint8arrays/from-string')
require('node-forge/lib/sha512')
/**
* @typedef {import('peer-id')} PeerId
* @typedef {import('interface-datastore/src/key')} Key
*/
const keyPrefix = '/pkcs8/'
const infoPrefix = '/info/'
const privates = new WeakMap()
// NIST SP 800-132
const NIST = {
@@ -46,7 +51,8 @@ function validateKeyName (name) {
* This assumes than an error indicates that the keychain is under attack. Delay returning an
* error to make brute force attacks harder.
*
* @param {string | Error} err - The error
* @param {string|Error} err - The error
* @returns {Promise<never>}
* @private
*/
async function throwDelayed (err) {
@@ -62,29 +68,28 @@ async function throwDelayed (err) {
* Converts a key name into a datastore name.
*
* @param {string} name
* @returns {DS.Key}
* @returns {Key}
* @private
*/
function DsName (name) {
return new DS.Key(keyPrefix + name)
return new Datastore.Key(keyPrefix + name)
}
/**
* Converts a key name into a datastore info name.
*
* @param {string} name
* @returns {DS.Key}
* @returns {Key}
* @private
*/
function DsInfoName (name) {
return new DS.Key(infoPrefix + name)
return new Datastore.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.
*/
@@ -101,7 +106,7 @@ class Keychain {
/**
* Creates a new instance of a key chain.
*
* @param {DS} store - where the key are.
* @param {Datastore} store - where the key are.
* @param {object} options
* @class
*/
@@ -134,7 +139,7 @@ class Keychain {
this.opts.dek.keyLength,
this.opts.dek.hash) : ''
Object.defineProperty(this, '_', { value: () => dek })
privates.set(this, { dek })
}
/**
@@ -148,13 +153,13 @@ class Keychain {
* @returns {CMS}
*/
get cms () {
return new CMS(this)
return new CMS(this, privates.get(this).dek)
}
/**
* Generates the options for a keychain. A random salt is produced.
*
* @returns {object}
* @returns {Object}
*/
static generateOptions () {
const options = Object.assign({}, defaultOptions)
@@ -167,7 +172,7 @@ class Keychain {
* Gets an object that can encrypt/decrypt protected data.
* The default options for a keychain.
*
* @returns {object}
* @returns {Object}
*/
static get options () {
return defaultOptions
@@ -178,10 +183,10 @@ class Keychain {
*
* @param {string} name - The local key name; cannot already exist.
* @param {string} type - One of the key types; 'rsa'.
* @param {int} [size] - The key size in bits. Used for rsa keys only.
* @returns {KeyInfo}
* @param {number} [size = 2048] - The key size in bits. Used for rsa keys only.
* @returns {Promise<KeyInfo>}
*/
async createKey (name, type, size) {
async createKey (name, type, size = 2048) {
const self = this
if (!validateKeyName(name) || name === 'self') {
@@ -208,9 +213,12 @@ class Keychain {
let keyInfo
try {
// @ts-ignore Differences between several crypto return types need to be fixed in libp2p-crypto
const keypair = await crypto.keys.generateKeyPair(type, size)
const kid = await keypair.id()
const pem = await keypair.export(this._())
/** @type {string} */
const dek = privates.get(this).dek
const pem = await keypair.export(dek)
keyInfo = {
name: name,
id: kid
@@ -230,7 +238,7 @@ class Keychain {
/**
* List all the keys.
*
* @returns {KeyInfo[]}
* @returns {Promise<KeyInfo[]>}
*/
async listKeys () {
const self = this
@@ -250,7 +258,7 @@ class Keychain {
* Find a key by it's id.
*
* @param {string} id - The universally unique key identifier.
* @returns {KeyInfo}
* @returns {Promise<KeyInfo|undefined>}
*/
async findKeyById (id) {
try {
@@ -265,7 +273,7 @@ class Keychain {
* Find a key by it's name.
*
* @param {string} name - The local key name.
* @returns {KeyInfo}
* @returns {Promise<KeyInfo>}
*/
async findKeyByName (name) {
if (!validateKeyName(name)) {
@@ -285,7 +293,7 @@ class Keychain {
* Remove an existing key.
*
* @param {string} name - The local key name; must already exist.
* @returns {KeyInfo}
* @returns {Promise<KeyInfo>}
*/
async removeKey (name) {
const self = this
@@ -306,7 +314,7 @@ class Keychain {
*
* @param {string} oldName - The old local key name; must already exist.
* @param {string} newName - The new local key name; must not already exist.
* @returns {KeyInfo}
* @returns {Promise<KeyInfo>}
*/
async renameKey (oldName, newName) {
const self = this
@@ -347,7 +355,7 @@ class Keychain {
*
* @param {string} name - The local key name; must already exist.
* @param {string} password - The password
* @returns {string}
* @returns {Promise<string>}
*/
async exportKey (name, password) {
if (!validateKeyName(name)) {
@@ -361,7 +369,9 @@ class Keychain {
try {
const res = await this.store.get(dsname)
const pem = uint8ArrayToString(res)
const privateKey = await crypto.keys.import(pem, this._())
/** @type {string} */
const dek = privates.get(this).dek
const privateKey = await crypto.keys.import(pem, dek)
return privateKey.export(password)
} catch (err) {
return throwDelayed(err)
@@ -374,7 +384,7 @@ class Keychain {
* @param {string} name - The local key name; must not already exist.
* @param {string} pem - The PEM encoded PKCS #8 string
* @param {string} password - The password.
* @returns {KeyInfo}
* @returns {Promise<KeyInfo>}
*/
async importKey (name, pem, password) {
const self = this
@@ -398,7 +408,9 @@ class Keychain {
let kid
try {
kid = await privateKey.id()
pem = await privateKey.export(this._())
/** @type {string} */
const dek = privates.get(this).dek
pem = await privateKey.export(dek)
} catch (err) {
return throwDelayed(err)
}
@@ -415,6 +427,13 @@ class Keychain {
return keyInfo
}
/**
* Import a peer key
*
* @param {string} name - The local key name; must not already exist.
* @param {PeerId} peer - The PEM encoded PKCS #8 string
* @returns {Promise<KeyInfo>}
*/
async importPeer (name, peer) {
const self = this
if (!validateKeyName(name)) {
@@ -431,7 +450,9 @@ class Keychain {
try {
const kid = await privateKey.id()
const pem = await privateKey.export(this._())
/** @type {string} */
const dek = privates.get(this).dek
const pem = await privateKey.export(dek)
const keyInfo = {
name: name,
id: kid
@@ -450,8 +471,7 @@ class Keychain {
* Gets the private key as PEM encoded PKCS #8 string.
*
* @param {string} name
* @returns {string}
* @private
* @returns {Promise<string>}
*/
async _getPrivateKey (name) {
if (!validateKeyName(name)) {

View File

@@ -73,7 +73,7 @@ class PeerRouting {
/**
* Iterates over all peer routers in series to find the given peer.
*
* @param {string} id - The id of the peer to find
* @param {PeerId} id - The id of the peer to find
* @param {object} [options]
* @param {number} [options.timeout] - How long the query should run
* @returns {Promise<{ id: PeerId, multiaddrs: Multiaddr[] }>}

View File

@@ -33,11 +33,11 @@ const Envelope = require('../record/envelope')
*
* @typedef {Object} Entry
* @property {Address[]} addresses peer Addresses.
* @property {CertifiedRecord} [record] certified peer record.
* @property {CertifiedRecord} record certified peer record.
*/
/**
* @extends {Book<Entry, Address[], Multiaddr[]>}
* @extends {Book}
*/
class AddressBook extends Book {
/**
@@ -56,13 +56,12 @@ class AddressBook extends Book {
peerStore,
eventName: 'change:multiaddrs',
eventProperty: 'multiaddrs',
eventTransformer: (entry) => {
if (!entry || !entry.addresses) {
eventTransformer: (data) => {
if (!data.addresses) {
return []
}
return entry.addresses.map((address) => address.multiaddr)
},
getTransformer: (entry) => entry && entry.addresses ? [...entry.addresses] : undefined
return data.addresses.map((address) => address.multiaddr)
}
})
/**
@@ -264,6 +263,23 @@ class AddressBook extends Book {
return this
}
/**
* Get the known data of a provided peer.
*
* @override
* @param {PeerId} peerId
* @returns {Address[]|undefined}
*/
get (peerId) {
if (!PeerId.isPeerId(peerId)) {
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
}
const entry = this.data.get(peerId.toB58String())
return entry && entry.addresses ? [...entry.addresses] : undefined
}
/**
* Transforms received multiaddrs into Address.
*

View File

@@ -13,9 +13,6 @@ const passthrough = data => data
* @typedef {import('./')} PeerStore
*/
/**
* @template Data, GetData, EventData
*/
class Book {
/**
* The Book is the skeleton for the PeerStore books.
@@ -25,20 +22,18 @@ class Book {
* @param {PeerStore} properties.peerStore - PeerStore instance.
* @param {string} properties.eventName - Name of the event to emit by the PeerStore.
* @param {string} properties.eventProperty - Name of the property to emit by the PeerStore.
* @param {(data: Data | undefined) => EventData | undefined} [properties.eventTransformer] - Transformer function of the provided data for being emitted.
* @param {(data: Data | undefined) => GetData | undefined} [properties.getTransformer] - Transformer function of the provided data for being returned on get.
* @param {(data: any) => any[]} [properties.eventTransformer] - Transformer function of the provided data for being emitted.
*/
constructor ({ peerStore, eventName, eventProperty, eventTransformer = passthrough, getTransformer = passthrough }) {
constructor ({ peerStore, eventName, eventProperty, eventTransformer = passthrough }) {
this._ps = peerStore
this.eventName = eventName
this.eventProperty = eventProperty
this.eventTransformer = eventTransformer
this.getTransformer = getTransformer
/**
* Map known peers to their data.
*
* @type {Map<string, Data>}
* @type {Map<string, any[]|any>}
*/
this.data = new Map()
}
@@ -47,7 +42,7 @@ class Book {
* Set known data of a provided peer.
*
* @param {PeerId} peerId
* @param {unknown} data
* @param {any[]|any} data
*/
set (peerId, data) {
throw errcode(new Error('set must be implemented by the subclass'), 'ERR_NOT_IMPLEMENTED')
@@ -58,7 +53,7 @@ class Book {
*
* @protected
* @param {PeerId} peerId - peerId of the data to store
* @param {Data} data - data to store.
* @param {any} data - data to store.
* @param {Object} [options] - storing options.
* @param {boolean} [options.emit = true] - emit the provided data.
* @returns {void}
@@ -78,7 +73,7 @@ class Book {
*
* @protected
* @param {PeerId} peerId
* @param {Data | undefined} [data]
* @param {any} [data]
*/
_emit (peerId, data) {
this._ps.emit(this.eventName, {
@@ -92,7 +87,7 @@ class Book {
* Returns `undefined` if there is no available data for the given peer.
*
* @param {PeerId} peerId
* @returns {GetData | undefined}
* @returns {any[]|any|undefined}
*/
get (peerId) {
if (!PeerId.isPeerId(peerId)) {
@@ -101,7 +96,8 @@ class Book {
const rec = this.data.get(peerId.toB58String())
return this.getTransformer(rec)
// @ts-ignore
return rec ? [...rec] : undefined
}
/**
@@ -119,7 +115,7 @@ class Book {
return false
}
this._emit(peerId, undefined)
this._emit(peerId, [])
return true
}

View File

@@ -20,7 +20,7 @@ const {
*/
/**
* @extends {Book<PeerId, PublicKey, PublicKey>}
* @extends {Book}
*/
class KeyBook extends Book {
/**
@@ -34,8 +34,7 @@ class KeyBook extends Book {
peerStore,
eventName: 'change:pubkey',
eventProperty: 'pubkey',
eventTransformer: (data) => data && data.pubKey,
getTransformer: (data) => data && data.pubKey
eventTransformer: (data) => data.pubKey
})
/**
@@ -75,6 +74,23 @@ class KeyBook extends Book {
return this
}
/**
* Get Public key of the given PeerId, if stored.
*
* @override
* @param {PeerId} peerId
* @returns {PublicKey | undefined}
*/
get (peerId) {
if (!PeerId.isPeerId(peerId)) {
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
}
const rec = this.data.get(peerId.toB58String())
return rec ? rec.pubKey : undefined
}
}
module.exports = KeyBook

View File

@@ -10,23 +10,17 @@ const uint8ArrayEquals = require('uint8arrays/equals')
const PeerId = require('peer-id')
const Book = require('./book')
const {
codes: { ERR_INVALID_PARAMETERS }
} = require('../errors')
const eventName = 'change:metadata'
const eventProperty = 'metadata'
/**
* @typedef {import('./')} PeerStore
*/
/**
* @typedef {Map<string, Uint8Array>} Metadata
*/
/**
* @extends {Book<Metadata, Metadata, string>}
* @extends {Book}
*
* @fires MetadataBook#change:metadata
*/
@@ -45,14 +39,14 @@ class MetadataBook extends Book {
*/
super({
peerStore,
eventName,
eventProperty
eventName: 'change:metadata',
eventProperty: 'metadata'
})
/**
* Map known peers to their known protocols.
*
* @type {Map<string, Metadata>}
* @type {Map<string, Map<string, Uint8Array>>}
*/
this.data = new Map()
}
@@ -105,6 +99,20 @@ class MetadataBook extends Book {
emit && this._emit(peerId, key)
}
/**
* Get the known data of a provided peer.
*
* @param {PeerId} peerId
* @returns {Map<string, Uint8Array>|undefined}
*/
get (peerId) {
if (!PeerId.isPeerId(peerId)) {
throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS)
}
return this.data.get(peerId.toB58String())
}
/**
* Get specific metadata value, if it exists
*
@@ -159,10 +167,7 @@ class MetadataBook extends Book {
return false
}
this._ps.emit(eventName, {
peerId,
[eventProperty]: key
})
this._emit(peerId, key)
return true
}

View File

@@ -17,21 +17,8 @@ const {
* @typedef {import('./')} PeerStore
*/
// @extends {Book<Entry, Address, Multiaddr>}
/**
* @param {Set<string> | undefined} set
* @returns {string[] | undefined}
*/
const transformSetToArray = (set) => {
if (!set) {
return undefined
}
return Array.from(set)
}
/**
* @extends {Book<Set<string>, string[], string[]>}
* @extends {Book}
*
* @fires ProtoBook#change:protocols
*/
@@ -52,8 +39,7 @@ class ProtoBook extends Book {
peerStore,
eventName: 'change:protocols',
eventProperty: 'protocols',
eventTransformer: (data) => transformSetToArray(data) || [],
getTransformer: (data) => transformSetToArray(data)
eventTransformer: (data) => Array.from(data)
})
/**

View File

@@ -3,9 +3,14 @@
const multicodec = require('multicodec')
// The domain string used for peer records contained in a Envelope.
module.exports.ENVELOPE_DOMAIN_PEER_RECORD = multicodec.getName(multicodec.LIBP2P_PEER_RECORD)
const domain = multicodec.getName(multicodec.LIBP2P_PEER_RECORD) || 'libp2p-peer-record'
// The type hint used to identify peer records in a Envelope.
// Defined in https://github.com/multiformats/multicodec/blob/master/table.csv
// with name "libp2p-peer-record"
module.exports.ENVELOPE_PAYLOAD_TYPE_PEER_RECORD = Uint8Array.from([3, 1])
const payloadType = Uint8Array.from([3, 1])
module.exports = {
ENVELOPE_DOMAIN_PEER_RECORD: domain,
ENVELOPE_PAYLOAD_TYPE_PEER_RECORD: payloadType
}

View File

@@ -36,6 +36,7 @@ class TransportManager {
/** @type {Map<string, Transport>} */
this._transports = new Map()
this._listeners = new Map()
this._listenerOptions = new Map()
this.faultTolerance = faultTolerance
}
@@ -63,6 +64,7 @@ class TransportManager {
})
this._transports.set(key, transport)
this._listenerOptions.set(key, transportOptions.listenerOptions || {})
if (!this._listeners.has(key)) {
this._listeners.set(key, [])
}
@@ -171,7 +173,7 @@ class TransportManager {
// For each supported multiaddr, create a listener
for (const addr of supportedAddrs) {
log('creating listener for %s on %s', key, addr)
const listener = transport.createListener({})
const listener = transport.createListener(this._listenerOptions.get(key))
this._listeners.get(key).push(listener)
// Track listen/close events

View File

@@ -15,10 +15,16 @@ const listenMultiaddr = '/ip4/127.0.0.1/tcp/15002/ws'
describe('Connection Manager', () => {
let libp2p
let peerIds
before(async () => {
peerIds = await peerUtils.createPeerId({ number: 2 })
})
beforeEach(async () => {
[libp2p] = await peerUtils.createPeer({
config: {
peerId: peerIds[0],
addresses: {
listen: [listenMultiaddr]
},
@@ -30,12 +36,10 @@ describe('Connection Manager', () => {
afterEach(() => libp2p.stop())
it('should filter connections on disconnect, removing the closed one', async () => {
const [localPeer, remotePeer] = await peerUtils.createPeerId({ number: 2 })
const conn1 = await mockConnection({ localPeer: peerIds[0], remotePeer: peerIds[1] })
const conn2 = await mockConnection({ localPeer: peerIds[0], remotePeer: peerIds[1] })
const conn1 = await mockConnection({ localPeer, remotePeer })
const conn2 = await mockConnection({ localPeer, remotePeer })
const id = remotePeer.toB58String()
const id = peerIds[1].toB58String()
// Add connection to the connectionManager
libp2p.connectionManager.onConnect(conn1)
@@ -54,6 +58,7 @@ describe('Connection Manager', () => {
it('should add connection on dial and remove on node stop', async () => {
const [remoteLibp2p] = await peerUtils.createPeer({
config: {
peerId: peerIds[1],
addresses: {
listen: ['/ip4/127.0.0.1/tcp/15003/ws']
},
@@ -86,9 +91,16 @@ describe('Connection Manager', () => {
})
describe('libp2p.connections', () => {
let peerIds
before(async () => {
peerIds = await peerUtils.createPeerId({ number: 2 })
})
it('libp2p.connections gets the connectionManager conns', async () => {
const [libp2p] = await peerUtils.createPeer({
config: {
peerId: peerIds[0],
addresses: {
listen: ['/ip4/127.0.0.1/tcp/15003/ws']
},
@@ -97,6 +109,7 @@ describe('libp2p.connections', () => {
})
const [remoteLibp2p] = await peerUtils.createPeer({
config: {
peerId: peerIds[1],
addresses: {
listen: ['/ip4/127.0.0.1/tcp/15004/ws']
},

View File

@@ -487,5 +487,20 @@ describe('Dialing (direct, WebSockets)', () => {
expect(libp2p.dialer.destroy).to.have.property('callCount', 1)
})
it('should fail to dial self', async () => {
libp2p = new Libp2p({
peerId,
modules: {
transport: [Transport],
streamMuxer: [Muxer],
connEncryption: [Crypto]
}
})
await expect(libp2p.dial(peerId))
.to.eventually.be.rejected()
.and.to.have.property('code', ErrorCodes.ERR_DIALED_SELF)
})
})
})

View File

@@ -55,7 +55,8 @@ describe('Identify', () => {
connectionManager: new EventEmitter(),
peerStore: localPeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
const remoteIdentify = new IdentifyService({
@@ -64,7 +65,8 @@ describe('Identify', () => {
connectionManager: new EventEmitter(),
peerStore: remotePeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
@@ -110,7 +112,8 @@ describe('Identify', () => {
connectionManager: new EventEmitter(),
peerStore: localPeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
@@ -120,7 +123,8 @@ describe('Identify', () => {
connectionManager: new EventEmitter(),
peerStore: remotePeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
@@ -168,7 +172,8 @@ describe('Identify', () => {
peerId: localPeer,
connectionManager: new EventEmitter(),
peerStore: localPeerStore,
multiaddrs: []
multiaddrs: [],
_options: { host: {} }
}
})
const remoteIdentify = new IdentifyService({
@@ -176,7 +181,8 @@ describe('Identify', () => {
peerId: remotePeer,
connectionManager: new EventEmitter(),
peerStore: remotePeerStore,
multiaddrs: []
multiaddrs: [],
_options: { host: {} }
}
})
@@ -202,6 +208,36 @@ describe('Identify', () => {
.and.to.have.property('code', Errors.ERR_INVALID_PEER)
})
it('should store host data and protocol version into metadataBook', () => {
const agentVersion = 'js-project/1.0.0'
const peerStore = new PeerStore({ peerId: localPeer })
sinon.spy(peerStore.metadataBook, 'set')
new IdentifyService({ // eslint-disable-line no-new
libp2p: {
peerId: localPeer,
connectionManager: new EventEmitter(),
peerStore,
multiaddrs: listenMaddrs,
_options: {
host: {
agentVersion
}
}
},
protocols
})
expect(peerStore.metadataBook.set.callCount).to.eql(2)
const storedAgentVersion = peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
const storedProtocolVersion = peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
expect(storedProtocolVersion).to.exist()
})
describe('push', () => {
it('should be able to push identify updates to another peer', async () => {
const storedProtocols = [multicodecs.IDENTIFY, multicodecs.IDENTIFY_PUSH, '/echo/1.0.0']
@@ -217,7 +253,8 @@ describe('Identify', () => {
connectionManager: new EventEmitter(),
peerStore: localPeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
@@ -230,7 +267,8 @@ describe('Identify', () => {
connectionManager,
peerStore: remotePeerStore,
multiaddrs: [],
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
@@ -287,7 +325,8 @@ describe('Identify', () => {
connectionManager: new EventEmitter(),
peerStore: localPeerStore,
multiaddrs: listenMaddrs,
isStarted: () => true
isStarted: () => true,
_options: { host: {} }
}
})
@@ -300,6 +339,7 @@ describe('Identify', () => {
connectionManager,
peerStore: new PeerStore({ peerId: remotePeer }),
multiaddrs: [],
_options: { host: {} },
isStarted: () => true
}
})
@@ -418,6 +458,24 @@ describe('Identify', () => {
await pWaitFor(() => connection.streams.length === 0)
})
it('should store host data and protocol version into metadataBook', () => {
const agentVersion = 'js-project/1.0.0'
libp2p = new Libp2p({
...baseOptions,
peerId,
host: {
agentVersion
}
})
const storedAgentVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'AgentVersion')
const storedProtocolVersion = libp2p.peerStore.metadataBook.getValue(localPeer, 'ProtocolVersion')
expect(agentVersion).to.eql(unit8ArrayToString(storedAgentVersion))
expect(storedProtocolVersion).to.exist()
})
it('should push multiaddr updates to an already connected peer', async () => {
libp2p = new Libp2p({
...baseOptions,

View File

@@ -11,6 +11,7 @@ const Transport = require('libp2p-tcp')
const PeerId = require('peer-id')
const multiaddr = require('multiaddr')
const mockUpgrader = require('../utils/mockUpgrader')
const sinon = require('sinon')
const Peers = require('../fixtures/peers')
const addrs = [
multiaddr('/ip4/127.0.0.1/tcp/0'),
@@ -50,7 +51,9 @@ describe('Transport Manager (TCP)', () => {
})
it('should be able to listen', async () => {
tm.add(Transport.prototype[Symbol.toStringTag], Transport)
tm.add(Transport.prototype[Symbol.toStringTag], Transport, { listenerOptions: { listen: 'carefully' } })
const transport = tm._transports.get(Transport.prototype[Symbol.toStringTag])
const spyListener = sinon.spy(transport, 'createListener')
await tm.listen(addrs)
expect(tm._listeners).to.have.key(Transport.prototype[Symbol.toStringTag])
expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(addrs.length)
@@ -59,6 +62,7 @@ describe('Transport Manager (TCP)', () => {
expect(tm.getAddrs().length).to.equal(addrs.length)
await tm.close()
expect(tm._listeners.get(Transport.prototype[Symbol.toStringTag])).to.have.length(0)
expect(spyListener.firstCall.firstArg).to.deep.equal({ listen: 'carefully' })
})
it('should create self signed peer record on listen', async () => {

View File

@@ -123,7 +123,10 @@ describe('libp2p.transportManager', () => {
const spy = sinon.spy()
const key = spy.prototype[Symbol.toStringTag] = 'TransportSpy'
const customOptions = {
another: 'value'
another: 'value',
listenerOptions: {
listen: 'carefully'
}
}
libp2p = new Libp2p({
peerId,
@@ -141,6 +144,7 @@ describe('libp2p.transportManager', () => {
expect(libp2p.transportManager).to.exist()
// Our transport and circuit relay
expect(libp2p.transportManager._transports.size).to.equal(2)
expect(libp2p.transportManager._listenerOptions.size).to.equal(2)
expect(spy).to.have.property('callCount', 1)
expect(spy.getCall(0)).to.have.deep.property('args', [{
...customOptions,