mirror of
https://github.com/fluencelabs/js-libp2p
synced 2025-07-24 13:01:58 +00:00
Compare commits
11 Commits
feature/go
...
0.29.x
Author | SHA1 | Date | |
---|---|---|---|
|
b88e35950a | ||
|
5dd4c34a89 | ||
|
28be6ad3af | ||
|
c4c7ef9b13 | ||
|
f3cfdad57a | ||
|
230259895f | ||
|
c070dda4c7 | ||
|
32e7a83c39 | ||
|
83856611de | ||
|
69c31374ab | ||
|
e14ce40b09 |
@@ -45,7 +45,7 @@ const after = async () => {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
bundlesize: { maxSize: '205kB' },
|
||||
bundlesize: { maxSize: '225kB' },
|
||||
hooks: {
|
||||
pre: before,
|
||||
post: after
|
||||
|
91
CHANGELOG.md
91
CHANGELOG.md
@@ -1,3 +1,94 @@
|
||||
<a name="0.29.0-rc.1"></a>
|
||||
# [0.29.0-rc.1](https://github.com/libp2p/js-libp2p/compare/v0.29.0-rc.0...v0.29.0-rc.1) (2020-08-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* peer record interop with go ([#739](https://github.com/libp2p/js-libp2p/issues/739)) ([c4c7ef9](https://github.com/libp2p/js-libp2p/commit/c4c7ef9))
|
||||
|
||||
|
||||
|
||||
<a name="0.29.0-rc.0"></a>
|
||||
# [0.29.0-rc.0](https://github.com/libp2p/js-libp2p/compare/v0.28.10...v0.29.0-rc.0) (2020-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not return self on peerstore.peers ([e1b8edc](https://github.com/libp2p/js-libp2p/commit/e1b8edc))
|
||||
* replace node buffers with uint8arrays ([#730](https://github.com/libp2p/js-libp2p/issues/730)) ([507f8c4](https://github.com/libp2p/js-libp2p/commit/507f8c4))
|
||||
* revert new identify protocol versions ([a798c65](https://github.com/libp2p/js-libp2p/commit/a798c65))
|
||||
* signature compliant with spec ([97b5d2a](https://github.com/libp2p/js-libp2p/commit/97b5d2a))
|
||||
|
||||
|
||||
### Chores
|
||||
|
||||
* update travis to use node lts and stable ([c272288](https://github.com/libp2p/js-libp2p/commit/c272288))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* cerified addressbook ([e0ed258](https://github.com/libp2p/js-libp2p/commit/e0ed258))
|
||||
* create self peer record in identify ([83922a7](https://github.com/libp2p/js-libp2p/commit/83922a7))
|
||||
* exchange signed peer records in identify ([f835457](https://github.com/libp2p/js-libp2p/commit/f835457))
|
||||
* gossipsub 1.1 ([#733](https://github.com/libp2p/js-libp2p/issues/733)) ([e14ce40](https://github.com/libp2p/js-libp2p/commit/e14ce40))
|
||||
* signed peer records record manager ([f95edf1](https://github.com/libp2p/js-libp2p/commit/f95edf1))
|
||||
|
||||
|
||||
### Reverts
|
||||
|
||||
* reapply "fix: throw if no conn encryption module provided ([#665](https://github.com/libp2p/js-libp2p/issues/665))" ([ad7f02e](https://github.com/libp2p/js-libp2p/commit/ad7f02e))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* pubsub implementation is now directly exposed and its API was updated according to the new pubsub interface in js-libp2p-interfaces repo
|
||||
|
||||
* chore: use gossipsub branch with src added
|
||||
|
||||
* fix: add pubsub handlers adapter
|
||||
|
||||
* chore: fix deps
|
||||
|
||||
* chore: update pubsub docs and examples
|
||||
|
||||
* chore: apply suggestions from code review
|
||||
|
||||
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
|
||||
|
||||
* chore: use new floodsub
|
||||
|
||||
* chore: change validator doc set
|
||||
|
||||
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
|
||||
|
||||
* chore: add new gossipsub src
|
||||
|
||||
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
|
||||
* - All deps used by this module now use Uint8Arrays in place of node Buffers
|
||||
|
||||
* chore: browser fixes
|
||||
|
||||
* chore: remove .only
|
||||
|
||||
* chore: stringify uint8array before parsing
|
||||
|
||||
* chore: update interop suite
|
||||
|
||||
* chore: remove ts from build command
|
||||
|
||||
* chore: update deps
|
||||
|
||||
* fix: update records to use uint8array
|
||||
|
||||
* chore: fix lint
|
||||
|
||||
* chore: update deps
|
||||
|
||||
Co-authored-by: Jacob Heun <jacobheun@gmail.com>
|
||||
* this drops testing support in node 10.
|
||||
|
||||
|
||||
|
||||
<a name="0.28.10"></a>
|
||||
## [0.28.10](https://github.com/libp2p/js-libp2p/compare/v0.28.9...v0.28.10) (2020-08-05)
|
||||
|
||||
|
141
doc/API.md
141
doc/API.md
@@ -46,6 +46,8 @@
|
||||
* [`pubsub.publish`](#pubsubpublish)
|
||||
* [`pubsub.subscribe`](#pubsubsubscribe)
|
||||
* [`pubsub.unsubscribe`](#pubsubunsubscribe)
|
||||
* [`pubsub.on`](#pubsubon)
|
||||
* [`pubsub.removeListener`](#pubsubremovelistener)
|
||||
* [`connectionManager.get`](#connectionmanagerget)
|
||||
* [`connectionManager.setPeerValue`](#connectionmanagersetpeervalue)
|
||||
* [`connectionManager.size`](#connectionmanagersize)
|
||||
@@ -1327,15 +1329,75 @@ await libp2p.pubsub.publish(topic, data)
|
||||
|
||||
### pubsub.subscribe
|
||||
|
||||
Subscribes the given handler to a pubsub topic.
|
||||
Subscribes to a pubsub topic.
|
||||
|
||||
`libp2p.pubsub.subscribe(topic, handler)`
|
||||
`libp2p.pubsub.subscribe(topic)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| topic | `string` | topic to subscribe |
|
||||
|
||||
#### Returns
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `void` | |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
}
|
||||
|
||||
libp2p.pubsub.on(topic, handler)
|
||||
libp2p.pubsub.subscribe(topic)
|
||||
```
|
||||
|
||||
### pubsub.unsubscribe
|
||||
|
||||
Unsubscribes from a pubsub topic.
|
||||
|
||||
`libp2p.pubsub.unsubscribe(topic)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| topic | `string` | topic to unsubscribe |
|
||||
|
||||
#### Returns
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `void` | |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
}
|
||||
|
||||
libp2p.pubsub.removeListener(topic handler)
|
||||
libp2p.pubsub.unsubscribe(topic)
|
||||
```
|
||||
|
||||
## pubsub.on
|
||||
|
||||
A Pubsub router is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) and uses its events for pubsub message handlers.
|
||||
|
||||
`libp2p.pubsub.on(topic, handler)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| topic | `string` | topic to listen |
|
||||
| handler | `function({ from: string, data: Uint8Array, seqno: Uint8Array, topicIDs: Array<string>, signature: Uint8Array, key: Uint8Array })` | handler for new data on topic |
|
||||
|
||||
#### Returns
|
||||
@@ -1352,21 +1414,22 @@ const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
}
|
||||
|
||||
libp2p.pubsub.subscribe(topic, handler)
|
||||
libp2p.pubsub.on(topic, handler)
|
||||
libp2p.pubsub.subscribe(topic)
|
||||
```
|
||||
|
||||
### pubsub.unsubscribe
|
||||
## pubsub.removeListener
|
||||
|
||||
Unsubscribes the given handler from a pubsub topic. If no handler is provided, all handlers for the topic are removed.
|
||||
A Pubsub router is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) and uses its events for pubsub message handlers.
|
||||
|
||||
`libp2p.pubsub.unsubscribe(topic, handler)`
|
||||
`libp2p.pubsub.removeListener(topic, handler)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| topic | `string` | topic to unsubscribe |
|
||||
| handler | `function(<object>)` | handler subscribed |
|
||||
| topic | `string` | topic to remove listener |
|
||||
| handler | `function({ from: string, data: Uint8Array, seqno: Uint8Array, topicIDs: Array<string>, signature: Uint8Array, key: Uint8Array })` | handler for new data on topic |
|
||||
|
||||
#### Returns
|
||||
|
||||
@@ -1382,7 +1445,67 @@ const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
}
|
||||
|
||||
libp2p.pubsub.unsubscribe(topic, handler)
|
||||
libp2p.pubsub.removeListener(topic handler)
|
||||
libp2p.pubsub.unsubscribe(topic)
|
||||
```
|
||||
|
||||
## pubsub.topicValidators.set
|
||||
|
||||
Pubsub routers support message validators per topic, which will validate the message before its propagations. Set is used to specify a validator for a topic.
|
||||
|
||||
`libp2p.pubsub.topicValidators.set(topic, validator)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| topic | `string` | topic to bind a validator |
|
||||
| handler | `function({ topic: string, msg: RPC })` | validator for new data on topic |
|
||||
|
||||
#### Returns
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `Map<string, function(string, RPC)>` | The `Map` object |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const validateMessage = (msgTopic, msg) => {
|
||||
const input = uint8ArrayToString(msg.data)
|
||||
const validInputs = ['a', 'b', 'c']
|
||||
|
||||
if (!validInputs.includes(input)) {
|
||||
throw new Error('no valid input received')
|
||||
}
|
||||
}
|
||||
libp2p.pubsub.topicValidators.set(topic, validateMessage)
|
||||
```
|
||||
|
||||
## pubsub.topicValidators.delete
|
||||
|
||||
Pubsub routers support message validators per topic, which will validate the message before its propagations. Delete is used to remove a validator for a topic.
|
||||
|
||||
`libp2p.pubsub.topicValidators.delete(topic)`
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
|------|------|-------------|
|
||||
| topic | `string` | topic to remove a validator |
|
||||
|
||||
#### Returns
|
||||
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `boolean` | `true` if an element in the Map object existed and has been removed, or `false` if the element does not exist. |
|
||||
|
||||
#### Example
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
libp2p.pubsub.topicValidators.delete(topic)
|
||||
```
|
||||
|
||||
### connectionManager.get
|
||||
|
282
doc/migrations/v0.28-v0.29.md
Normal file
282
doc/migrations/v0.28-v0.29.md
Normal file
@@ -0,0 +1,282 @@
|
||||
<!--Specify versions for migration below-->
|
||||
# Migrating to libp2p@0.29
|
||||
|
||||
A migration guide for refactoring your application code from libp2p v0.28.x to v0.29.0.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [API](#api)
|
||||
- [Pubsub](#pubsub)
|
||||
- [Uint8Arrays replace node Buffers](#uint8arrays-replace-node-buffers)
|
||||
- [Module Updates](#module-updates)
|
||||
|
||||
## API
|
||||
|
||||
### Pubsub
|
||||
|
||||
The [`libp2p-gossipsub`](https://github.com/ChainSafe/js-libp2p-gossipsub) javascript implementation is now upgraded according to the Gossipsub v1.1 [spec](https://github.com/libp2p/specs/blob/master/pubsub/gossipsub/gossipsub-v1.1.md) and it packs several security hardening extensions. You can read more about it in its [blogpost](https://blog.ipfs.io/2020-05-20-gossipsub-v1.1/).
|
||||
|
||||
We leveraged this update to rethink the pubsub interface, in order to make it easier, as well as to be consistent with the API of the routers. Moreover, the interface was also reconstructed to ease new pubsub router implementations.
|
||||
|
||||
#### Access router instance
|
||||
|
||||
Libp2p prior to 0.29 unnecessarily added a layer of abstraction over the pubsub routers. We now expose the pubsub router API directly and have a test suite in the [interface-pubsub](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/pubsub) to guarantee routers compliance. This enables more advanced usage of the underlying router.
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
libp2p.pubsub._pubsub.*
|
||||
libp2p.pubsub._pubsub.topicValidators.set(topic, validator)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
libp2p.pubsub.*
|
||||
libp2p.pubsub.topicValidators.set(topic, validator)
|
||||
```
|
||||
|
||||
#### Publish
|
||||
|
||||
Publish uses `Uint8Array` data instead of `Buffer`.
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const data = Buffer.from('data')
|
||||
|
||||
await libp2p.pubsub.publish(topic, data)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
|
||||
const topic = 'topic'
|
||||
const data = uint8ArrayFromString('data')
|
||||
|
||||
await libp2p.pubsub.publish(topic, data)
|
||||
```
|
||||
|
||||
#### Subscribe
|
||||
|
||||
Handlers should no longer be passed when subscribing, instead, applications should bind event handlers for each topic they wish to subscribe too. This enables more flexibility at the application level without changing the underlying subscriptions.
|
||||
Message data is now a `Uint8Array` instead of `Buffer`.
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
const data = msg.data.toString()
|
||||
}
|
||||
libp2p.pubsub.subscribe(topic, handler)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const topic = 'topic'
|
||||
const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
const data = uint8ArrayToString(msg.data)
|
||||
}
|
||||
libp2p.pubsub.on(topic, handler)
|
||||
libp2p.pubsub.subscribe(topic)
|
||||
```
|
||||
|
||||
#### Unsubscribe
|
||||
|
||||
Handlers should not be directly bound to the subscription anymore.
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
}
|
||||
libp2p.pubsub.unsubscribe(topic, handler)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const topic = 'topic'
|
||||
const handler = (msg) => {
|
||||
// msg.data - pubsub data received
|
||||
}
|
||||
libp2p.pubsub.removeListener(topic, handler)
|
||||
libp2p.pubsub.unsubscribe(topic)
|
||||
```
|
||||
|
||||
#### Topic Validators
|
||||
|
||||
The validator function does not include the peer parameter anymore. It was redundant since it is included in the message and it could lead to issues as the peer that sent the message might not be the one who created the message in first place. The validator function should also throw an error instead of returning `false` when the message is not valid.
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const validator = (msgTopic, peer, msg) => {
|
||||
// process message
|
||||
return false
|
||||
}
|
||||
libp2p.pubsub._pubsub.topicValidators.set(topic, validator)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const validator = (msgTopic, msg) => {
|
||||
const from = msg.from
|
||||
// process message
|
||||
throw new Error('not a valid message')
|
||||
}
|
||||
libp2p.pubsub.topicValidators.set(topic, validator)
|
||||
```
|
||||
|
||||
### Uint8Arrays replace node Buffers
|
||||
|
||||
Aiming to improve libp2p browser support, we are moving away from node core modules unless we can guarantee that the code we are writing will not run in a browser. It is worth mentioning that modern JavaScript runtimes have TypedArrays such as Uint8Array backed by ArrayBuffers. All libp2p dependencies were also updated to use Uint8Array.
|
||||
|
||||
We use the [uint8arrays](https://www.npmjs.com/package/uint8arrays) utilities module to deal with `Uint8Arrays` easily and we recommend its usage in the application layer. Thanks for the module [@achingbrain](https://github.com/achingbrain)! It includes utilities like `compare`, `concat`, `equals`, `fromString` and `toString`. In this migration examples, we will be using the following:
|
||||
|
||||
```js
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
```
|
||||
|
||||
#### contentRouting.put
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const key = '/key'
|
||||
const value = Buffer.from('oh hello there')
|
||||
|
||||
await libp2p.contentRouting.put(key, value)
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const key = '/key'
|
||||
const value = uint8ArrayFromString('oh hello there')
|
||||
|
||||
await libp2p.contentRouting.put(key, value)
|
||||
```
|
||||
|
||||
#### contentRouting.get
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const key = '/key'
|
||||
const value = await libp2p.contentRouting.put(key)
|
||||
|
||||
console.log('store value is: ', value.toString())
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const key = '/key'
|
||||
const value = await libp2p.contentRouting.put(key)
|
||||
|
||||
console.log('store value is: ', uint8ArrayToString(value))
|
||||
```
|
||||
|
||||
#### metadataBook.set
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
peerStore.metadataBook.set(peerId, 'location', Buffer.from('Saturn'))
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
peerStore.metadataBook.set(peerId, 'location', uint8ArrayFromString('Saturn'))
|
||||
```
|
||||
|
||||
#### metadataBook.get
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const data = peerStore.metadataBook.get(peerId)
|
||||
|
||||
console.log('stored location: ', data.get('location').toString())
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const data = peerStore.metadataBook.get(peerId)
|
||||
|
||||
console.log('stored location: ', uint8ArrayToString(data.get('location')))
|
||||
```
|
||||
|
||||
#### metadataBook.getValue
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const location = peerStore.metadataBook.getValue(peerId, 'location')
|
||||
|
||||
console.log('stored location: ', location.toString())
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const location = peerStore.metadataBook.getValue(peerId, 'location')
|
||||
|
||||
console.log('stored location: ', uint8ArrayToString(location))
|
||||
```
|
||||
|
||||
#### keychain.cms.encrypt
|
||||
|
||||
**Before**
|
||||
|
||||
```js
|
||||
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
|
||||
const enc = await libp2p.keychain.cms.encrypt('keyTest', Buffer.from('data'))
|
||||
```
|
||||
|
||||
**After**
|
||||
|
||||
```js
|
||||
const keyInfo = await libp2p.keychain.createKey('keyTest', 'rsa', 4096)
|
||||
const enc = await libp2p.keychain.cms.encrypt('keyTest', uint8ArrayFromString('data'))
|
||||
```
|
||||
|
||||
#### pubsub
|
||||
|
||||
Already specified in its own chapter above.
|
||||
|
||||
## Module Updates
|
||||
|
||||
With this release you should update the following libp2p modules if you are relying on them:
|
||||
|
||||
```json
|
||||
"libp2p-bootstrap": "^0.12.0",
|
||||
"libp2p-delegated-content-routing": "^0.6.0",
|
||||
"libp2p-delegated-peer-routing": "^0.6.0",
|
||||
"libp2p-floodsub": "^0.23.0",
|
||||
"libp2p-gossipsub": "^0.6.0",
|
||||
"libp2p-kad-dht": "^0.20.0",
|
||||
"libp2p-mdns": "^0.15.0",
|
||||
"libp2p-mplex": "^0.10.0",
|
||||
"libp2p-noise": "^2.0.0",
|
||||
"libp2p-secio": "^0.13.1",
|
||||
"libp2p-tcp": "^0.15.1",
|
||||
"libp2p-webrtc-star": "^0.20.0",
|
||||
"libp2p-websockets": "^0.14.0",
|
||||
```
|
@@ -8,6 +8,7 @@ const { NOISE } = require('libp2p-noise')
|
||||
const SECIO = require('libp2p-secio')
|
||||
const Gossipsub = require('libp2p-gossipsub')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const createNode = async () => {
|
||||
const node = await Libp2p.create({
|
||||
@@ -38,13 +39,15 @@ const createNode = async () => {
|
||||
node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||
await node1.dial(node2.peerId)
|
||||
|
||||
await node1.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node1 received: ${msg.data.toString()}`)
|
||||
node1.pubsub.on(topic, (msg) => {
|
||||
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node1.pubsub.subscribe(topic)
|
||||
|
||||
await node2.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node2 received: ${msg.data.toString()}`)
|
||||
node2.pubsub.on(topic, (msg) => {
|
||||
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node2.pubsub.subscribe(topic)
|
||||
|
||||
// node2 publishes "news" every second
|
||||
setInterval(() => {
|
||||
|
@@ -47,13 +47,15 @@ node1.peerStore.addressBook.set(node2.peerId, node2.multiaddrs)
|
||||
|
||||
await node1.dial(node2.peerId)
|
||||
|
||||
await node1.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node1 received: ${msg.data.toString()}`)
|
||||
node1.pubsub.on(topic, (msg) => {
|
||||
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node1.pubsub.subscribe(topic)
|
||||
|
||||
await node2.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node2 received: ${msg.data.toString()}`)
|
||||
node2.pubsub.on(topic, (msg) => {
|
||||
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node2.pubsub.subscribe(topic)
|
||||
|
||||
// node2 publishes "news" every second
|
||||
setInterval(() => {
|
||||
|
@@ -8,6 +8,7 @@ const { NOISE } = require('libp2p-noise')
|
||||
const SECIO = require('libp2p-secio')
|
||||
const Gossipsub = require('libp2p-gossipsub')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
const uint8ArrayToString = require('uint8arrays/to-string')
|
||||
|
||||
const createNode = async () => {
|
||||
const node = await Libp2p.create({
|
||||
@@ -43,29 +44,34 @@ const createNode = async () => {
|
||||
await node2.dial(node3.peerId)
|
||||
|
||||
//subscribe
|
||||
await node1.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node1 received: ${msg.data.toString()}`)
|
||||
node1.pubsub.on(topic, (msg) => {
|
||||
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node1.pubsub.subscribe(topic)
|
||||
|
||||
await node2.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node2 received: ${msg.data.toString()}`)
|
||||
node2.pubsub.on(topic, (msg) => {
|
||||
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node2.pubsub.subscribe(topic)
|
||||
|
||||
await node3.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node3 received: ${msg.data.toString()}`)
|
||||
node3.pubsub.on(topic, (msg) => {
|
||||
console.log(`node3 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node3.pubsub.subscribe(topic)
|
||||
|
||||
const validateFruit = (msgTopic, peer, msg) => {
|
||||
const fruit = msg.data.toString();
|
||||
const validateFruit = (msgTopic, msg) => {
|
||||
const fruit = uint8ArrayToString(msg.data)
|
||||
const validFruit = ['banana', 'apple', 'orange']
|
||||
const valid = validFruit.includes(fruit);
|
||||
return valid;
|
||||
|
||||
if (!validFruit.includes(fruit)) {
|
||||
throw new Error('no valid fruit received')
|
||||
}
|
||||
}
|
||||
|
||||
//validate fruit
|
||||
node1.pubsub._pubsub.topicValidators.set(topic, validateFruit);
|
||||
node2.pubsub._pubsub.topicValidators.set(topic, validateFruit);
|
||||
node3.pubsub._pubsub.topicValidators.set(topic, validateFruit);
|
||||
node1.pubsub.topicValidators.set(topic, validateFruit)
|
||||
node2.pubsub.topicValidators.set(topic, validateFruit)
|
||||
node3.pubsub.topicValidators.set(topic, validateFruit)
|
||||
|
||||
// node1 publishes "fruits" every five seconds
|
||||
var count = 0;
|
||||
|
@@ -44,31 +44,36 @@ Now we' can subscribe to the fruit topic and log incoming messages.
|
||||
```JavaScript
|
||||
const topic = 'fruit'
|
||||
|
||||
await node1.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node1 received: ${msg.data.toString()}`)
|
||||
node1.pubsub.on(topic, (msg) => {
|
||||
console.log(`node1 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node1.pubsub.subscribe(topic)
|
||||
|
||||
await node2.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node2 received: ${msg.data.toString()}`)
|
||||
node2.pubsub.on(topic, (msg) => {
|
||||
console.log(`node2 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node2.pubsub.subscribe(topic)
|
||||
|
||||
await node3.pubsub.subscribe(topic, (msg) => {
|
||||
console.log(`node3 received: ${msg.data.toString()}`)
|
||||
node3.pubsub.on(topic, (msg) => {
|
||||
console.log(`node3 received: ${uint8ArrayToString(msg.data)}`)
|
||||
})
|
||||
await node3.pubsub.subscribe(topic)
|
||||
```
|
||||
Finally, let's define the additional filter in the fruit topic.
|
||||
|
||||
```JavaScript
|
||||
const validateFruit = (msgTopic, peer, msg) => {
|
||||
const fruit = msg.data.toString();
|
||||
const validateFruit = (msgTopic, msg) => {
|
||||
const fruit = uint8ArrayToString(msg.data)
|
||||
const validFruit = ['banana', 'apple', 'orange']
|
||||
const valid = validFruit.includes(fruit);
|
||||
return valid;
|
||||
|
||||
if (!validFruit.includes(fruit)) {
|
||||
throw new Error('no valid fruit received')
|
||||
}
|
||||
}
|
||||
|
||||
node1.pubsub._pubsub.topicValidators.set(topic, validateFruit);
|
||||
node2.pubsub._pubsub.topicValidators.set(topic, validateFruit);
|
||||
node3.pubsub._pubsub.topicValidators.set(topic, validateFruit);
|
||||
node1.pubsub.topicValidators.set(topic, validateFruit)
|
||||
node2.pubsub.topicValidators.set(topic, validateFruit)
|
||||
node3.pubsub.topicValidators.set(topic, validateFruit)
|
||||
```
|
||||
|
||||
In this example, node one has an outdated version of the system, or is a malicious node. When it tries to publish fruit, the messages are re-shared and all the nodes share the message. However, when it tries to publish a vehicle the message is not re-shared.
|
||||
|
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "libp2p",
|
||||
"version": "0.28.10",
|
||||
"version": "0.29.0-rc.1",
|
||||
"description": "JavaScript implementation of libp2p, a modular peer to peer network stack",
|
||||
"leadMaintainer": "Jacob Heun <jacobheun@gmail.com>",
|
||||
"main": "src/index.js",
|
||||
@@ -59,13 +59,13 @@
|
||||
"it-pipe": "^1.1.0",
|
||||
"it-protocol-buffers": "^0.2.0",
|
||||
"libp2p-crypto": "^0.18.0",
|
||||
"libp2p-interfaces": "^0.5.0",
|
||||
"libp2p-interfaces": "^0.5.1",
|
||||
"libp2p-utils": "^0.2.0",
|
||||
"mafmt": "^8.0.0",
|
||||
"merge-options": "^2.0.0",
|
||||
"moving-average": "^1.0.0",
|
||||
"multiaddr": "^8.0.0",
|
||||
"multicodec": "^1.0.2",
|
||||
"multicodec": "^2.0.0",
|
||||
"multistream-select": "^1.0.0",
|
||||
"mutable-proxy": "^1.0.0",
|
||||
"node-forge": "^0.9.1",
|
||||
@@ -92,23 +92,24 @@
|
||||
"cids": "^1.0.0",
|
||||
"delay": "^4.3.0",
|
||||
"dirty-chai": "^2.0.1",
|
||||
"interop-libp2p": "^0.2.0",
|
||||
"interop-libp2p": "^0.3.0",
|
||||
"ipfs-http-client": "^46.0.0",
|
||||
"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.6.0",
|
||||
"libp2p-delegated-peer-routing": "^0.6.0",
|
||||
"libp2p-floodsub": "^0.22.0",
|
||||
"libp2p-gossipsub": "^0.5.0",
|
||||
"libp2p-floodsub": "^0.23.0",
|
||||
"libp2p-gossipsub": "^0.6.0",
|
||||
"libp2p-kad-dht": "^0.20.0",
|
||||
"libp2p-mdns": "^0.15.0",
|
||||
"libp2p-mplex": "^0.10.0",
|
||||
"libp2p-noise": "^2.0.0",
|
||||
"libp2p-secio": "^0.13.1",
|
||||
"libp2p-tcp": "^0.15.1",
|
||||
"libp2p-webrtc-star": "^0.19.0",
|
||||
"libp2p-webrtc-star": "^0.20.0",
|
||||
"libp2p-websockets": "^0.14.0",
|
||||
"multihashes": "^3.0.1",
|
||||
"nock": "^13.0.3",
|
||||
@@ -125,14 +126,14 @@
|
||||
"Jacob Heun <jacobheun@gmail.com>",
|
||||
"Vasco Santos <vasco.santos@moxy.studio>",
|
||||
"Alan Shaw <alan@tableflip.io>",
|
||||
"Cayman <caymannava@gmail.com>",
|
||||
"Alex Potsides <alex@achingbrain.net>",
|
||||
"Cayman <caymannava@gmail.com>",
|
||||
"Pedro Teixeira <i@pgte.me>",
|
||||
"Friedel Ziegelmayer <dignifiedquire@gmail.com>",
|
||||
"Maciej Krüger <mkg20001@gmail.com>",
|
||||
"Hugo Dias <mail@hugodias.me>",
|
||||
"dirkmc <dirkmdev@gmail.com>",
|
||||
"Volker Mische <volker.mische@gmail.com>",
|
||||
"dirkmc <dirkmdev@gmail.com>",
|
||||
"Richard Littauer <richard.littauer@gmail.com>",
|
||||
"ᴠɪᴄᴛᴏʀ ʙᴊᴇʟᴋʜᴏʟᴍ <victorbjelkholm@gmail.com>",
|
||||
"Andrew Nesbitt <andrewnez@gmail.com>",
|
||||
|
@@ -11,7 +11,6 @@ const PeerId = require('peer-id')
|
||||
|
||||
const peerRouting = require('./peer-routing')
|
||||
const contentRouting = require('./content-routing')
|
||||
const pubsub = require('./pubsub')
|
||||
const getPeer = require('./get-peer')
|
||||
const { validate: validateConfig } = require('./config')
|
||||
const { codes, messages } = require('./errors')
|
||||
@@ -25,6 +24,7 @@ const Metrics = require('./metrics')
|
||||
const TransportManager = require('./transport-manager')
|
||||
const Upgrader = require('./upgrader')
|
||||
const PeerStore = require('./peer-store')
|
||||
const PubsubAdapter = require('./pubsub-adapter')
|
||||
const PersistentPeerStore = require('./peer-store/persistent')
|
||||
const Registrar = require('./registrar')
|
||||
const ping = require('./ping')
|
||||
@@ -185,9 +185,11 @@ class Libp2p extends EventEmitter {
|
||||
})
|
||||
}
|
||||
|
||||
// start pubsub
|
||||
// Create pubsub if provided
|
||||
if (this._modules.pubsub) {
|
||||
this.pubsub = pubsub(this, this._modules.pubsub, this._config.pubsub)
|
||||
const Pubsub = this._modules.pubsub
|
||||
// using pubsub adapter with *DEPRECATED* handlers functionality
|
||||
this.pubsub = PubsubAdapter(Pubsub, this, this._config.pubsub)
|
||||
}
|
||||
|
||||
// Attach remaining APIs
|
||||
|
40
src/pubsub-adapter.js
Normal file
40
src/pubsub-adapter.js
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict'
|
||||
|
||||
// Pubsub adapter to keep API with handlers while not removed.
|
||||
module.exports = (PubsubRouter, libp2p, options) => {
|
||||
class Pubsub extends PubsubRouter {
|
||||
/**
|
||||
* Subscribes to a given topic.
|
||||
* @override
|
||||
* @param {string} topic
|
||||
* @param {function(msg: InMessage)} [handler]
|
||||
* @returns {void}
|
||||
*/
|
||||
subscribe (topic, handler) {
|
||||
// Bind provided handler
|
||||
handler && this.on(topic, handler)
|
||||
super.subscribe(topic)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from the given topic.
|
||||
* @override
|
||||
* @param {string} topic
|
||||
* @param {function(msg: InMessage)} [handler]
|
||||
* @returns {void}
|
||||
*/
|
||||
unsubscribe (topic, handler) {
|
||||
if (!handler) {
|
||||
this.removeAllListeners(topic)
|
||||
} else {
|
||||
this.removeListener(topic, handler)
|
||||
}
|
||||
|
||||
if (this.listenerCount(topic) === 0) {
|
||||
super.unsubscribe(topic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Pubsub(libp2p, options)
|
||||
}
|
109
src/pubsub.js
109
src/pubsub.js
@@ -1,109 +0,0 @@
|
||||
'use strict'
|
||||
|
||||
const errCode = require('err-code')
|
||||
const { messages, codes } = require('./errors')
|
||||
const uint8ArrayFromString = require('uint8arrays/from-string')
|
||||
|
||||
module.exports = (node, Pubsub, config) => {
|
||||
const pubsub = new Pubsub(node.peerId, node.registrar, config)
|
||||
|
||||
return {
|
||||
/**
|
||||
* Subscribe the given handler to a pubsub topic
|
||||
* @param {string} topic
|
||||
* @param {function} handler The handler to subscribe
|
||||
* @returns {void}
|
||||
*/
|
||||
subscribe: (topic, handler) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
|
||||
}
|
||||
|
||||
if (pubsub.listenerCount(topic) === 0) {
|
||||
pubsub.subscribe(topic)
|
||||
}
|
||||
|
||||
pubsub.on(topic, handler)
|
||||
},
|
||||
|
||||
/**
|
||||
* Unsubscribes from a pubsub topic
|
||||
* @param {string} topic
|
||||
* @param {function} [handler] The handler to unsubscribe from
|
||||
*/
|
||||
unsubscribe: (topic, handler) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
pubsub.removeAllListeners(topic)
|
||||
} else {
|
||||
pubsub.removeListener(topic, handler)
|
||||
}
|
||||
|
||||
if (pubsub.listenerCount(topic) === 0) {
|
||||
pubsub.unsubscribe(topic)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Publish messages to the given topics.
|
||||
* @param {Array<string>|string} topic
|
||||
* @param {Uint8Array} data
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
publish: (topic, data) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
|
||||
}
|
||||
|
||||
if (typeof data === 'string' || data instanceof String) {
|
||||
data = uint8ArrayFromString(data)
|
||||
}
|
||||
|
||||
try {
|
||||
data = Uint8Array.from(data)
|
||||
} catch (err) {
|
||||
throw errCode(new Error('data must be convertible to a Uint8Array'), 'ERR_DATA_IS_NOT_VALID')
|
||||
}
|
||||
|
||||
return pubsub.publish(topic, data)
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a list of topics the node is subscribed to.
|
||||
* @returns {Array<String>} topics
|
||||
*/
|
||||
getTopics: () => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
|
||||
}
|
||||
|
||||
return pubsub.getTopics()
|
||||
},
|
||||
|
||||
/**
|
||||
* Get a list of the peer-ids that are subscribed to one topic.
|
||||
* @param {string} topic
|
||||
* @returns {Array<string>}
|
||||
*/
|
||||
getSubscribers: (topic) => {
|
||||
if (!node.isStarted() && !pubsub.started) {
|
||||
throw errCode(new Error(messages.NOT_STARTED_YET), codes.PUBSUB_NOT_STARTED)
|
||||
}
|
||||
|
||||
return pubsub.getSubscribers(topic)
|
||||
},
|
||||
|
||||
setMaxListeners (n) {
|
||||
return pubsub.setMaxListeners(n)
|
||||
},
|
||||
|
||||
_pubsub: pubsub,
|
||||
|
||||
start: () => pubsub.start(),
|
||||
|
||||
stop: () => pubsub.stop()
|
||||
}
|
||||
}
|
@@ -140,7 +140,7 @@ Envelope.createFromProtobuf = async (data) => {
|
||||
*/
|
||||
Envelope.seal = async (record, peerId) => {
|
||||
const domain = record.domain
|
||||
const payloadType = uint8arraysFromString(record.codec)
|
||||
const payloadType = record.codec
|
||||
const payload = record.marshal()
|
||||
|
||||
const signData = formatSignaturePayload(domain, payloadType, payload)
|
||||
|
@@ -3,9 +3,9 @@
|
||||
const multicodec = require('multicodec')
|
||||
|
||||
// The domain string used for peer records contained in a Envelope.
|
||||
module.exports.ENVELOPE_DOMAIN_PEER_RECORD = 'libp2p-peer-record'
|
||||
module.exports.ENVELOPE_DOMAIN_PEER_RECORD = multicodec.getName(multicodec.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 = multicodec.print[multicodec.LIBP2P_PEER_RECORD]
|
||||
module.exports.ENVELOPE_PAYLOAD_TYPE_PEER_RECORD = Uint8Array.from([3, 1])
|
||||
|
@@ -42,13 +42,13 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(false)
|
||||
expect(libp2p.pubsub.started).to.equal(false)
|
||||
|
||||
await libp2p.start()
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(true)
|
||||
expect(libp2p.pubsub.started).to.equal(true)
|
||||
|
||||
await libp2p.stop()
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(false)
|
||||
expect(libp2p.pubsub.started).to.equal(false)
|
||||
})
|
||||
|
||||
it('should not start if disabled once libp2p starts', async () => {
|
||||
@@ -67,10 +67,10 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
})
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(false)
|
||||
expect(libp2p.pubsub.started).to.equal(false)
|
||||
|
||||
await libp2p.start()
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(false)
|
||||
expect(libp2p.pubsub.started).to.equal(false)
|
||||
})
|
||||
|
||||
it('should allow a manual start', async () => {
|
||||
@@ -90,9 +90,9 @@ describe('Pubsub subsystem is configurable', () => {
|
||||
|
||||
libp2p = await create(customOptions)
|
||||
await libp2p.start()
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(false)
|
||||
expect(libp2p.pubsub.started).to.equal(false)
|
||||
|
||||
await libp2p.pubsub.start()
|
||||
expect(libp2p.pubsub._pubsub.started).to.equal(true)
|
||||
expect(libp2p.pubsub.started).to.equal(true)
|
||||
})
|
||||
})
|
||||
|
@@ -66,8 +66,8 @@ describe('Pubsub subsystem operates correctly', () => {
|
||||
expect(connection).to.exist()
|
||||
|
||||
return Promise.all([
|
||||
pWaitFor(() => libp2p.pubsub._pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub._pubsub.peers.size === 1)
|
||||
pWaitFor(() => libp2p.pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub.peers.size === 1)
|
||||
])
|
||||
})
|
||||
|
||||
@@ -141,14 +141,14 @@ describe('Pubsub subsystem operates correctly', () => {
|
||||
const connection = await libp2p.dial(remotePeerId)
|
||||
|
||||
expect(connection).to.exist()
|
||||
expect(libp2p.pubsub._pubsub.peers.size).to.be.eql(0)
|
||||
expect(remoteLibp2p.pubsub._pubsub.peers.size).to.be.eql(0)
|
||||
expect(libp2p.pubsub.peers.size).to.be.eql(0)
|
||||
expect(remoteLibp2p.pubsub.peers.size).to.be.eql(0)
|
||||
|
||||
remoteLibp2p.pubsub.start()
|
||||
|
||||
return Promise.all([
|
||||
pWaitFor(() => libp2p.pubsub._pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub._pubsub.peers.size === 1)
|
||||
pWaitFor(() => libp2p.pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub.peers.size === 1)
|
||||
])
|
||||
})
|
||||
|
||||
@@ -164,8 +164,8 @@ describe('Pubsub subsystem operates correctly', () => {
|
||||
remoteLibp2p.pubsub.start()
|
||||
|
||||
await Promise.all([
|
||||
pWaitFor(() => libp2p.pubsub._pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub._pubsub.peers.size === 1)
|
||||
pWaitFor(() => libp2p.pubsub.peers.size === 1),
|
||||
pWaitFor(() => remoteLibp2p.pubsub.peers.size === 1)
|
||||
])
|
||||
|
||||
let subscribedTopics = libp2p.pubsub.getTopics()
|
||||
|
@@ -7,6 +7,8 @@ chai.use(require('chai-bytes'))
|
||||
chai.use(require('chai-as-promised'))
|
||||
const { expect } = chai
|
||||
|
||||
const uint8arrayFromString = require('uint8arrays/from-string')
|
||||
const uint8arrayEquals = require('uint8arrays/equals')
|
||||
const Envelope = require('../../src/record/envelope')
|
||||
const Record = require('libp2p-interfaces/src/record')
|
||||
const { codes: ErrorCodes } = require('../../src/errors')
|
||||
@@ -14,7 +16,7 @@ const { codes: ErrorCodes } = require('../../src/errors')
|
||||
const peerUtils = require('../utils/creators/peer')
|
||||
|
||||
const domain = 'libp2p-testing'
|
||||
const codec = '/libp2p/testdata'
|
||||
const codec = uint8arrayFromString('/libp2p/testdata')
|
||||
|
||||
class TestRecord extends Record {
|
||||
constructor (data) {
|
||||
@@ -23,16 +25,16 @@ class TestRecord extends Record {
|
||||
}
|
||||
|
||||
marshal () {
|
||||
return Buffer.from(this.data)
|
||||
return uint8arrayFromString(this.data)
|
||||
}
|
||||
|
||||
equals (other) {
|
||||
return Buffer.compare(this.data, other.data)
|
||||
return uint8arrayEquals(this.data, other.data)
|
||||
}
|
||||
}
|
||||
|
||||
describe('Envelope', () => {
|
||||
const payloadType = Buffer.from(codec)
|
||||
const payloadType = codec
|
||||
let peerId
|
||||
let testRecord
|
||||
|
||||
@@ -43,7 +45,7 @@ describe('Envelope', () => {
|
||||
|
||||
it('creates an envelope with a random key', () => {
|
||||
const payload = testRecord.marshal()
|
||||
const signature = Buffer.from(Math.random().toString(36).substring(7))
|
||||
const signature = uint8arrayFromString(Math.random().toString(36).substring(7))
|
||||
|
||||
const envelope = new Envelope({
|
||||
peerId,
|
||||
@@ -63,7 +65,7 @@ describe('Envelope', () => {
|
||||
const envelope = await Envelope.seal(testRecord, peerId)
|
||||
expect(envelope).to.exist()
|
||||
expect(envelope.peerId.equals(peerId)).to.eql(true)
|
||||
expect(envelope.payloadType).to.equalBytes(payloadType)
|
||||
expect(envelope.payloadType).to.eql(payloadType)
|
||||
expect(envelope.payload).to.exist()
|
||||
expect(envelope.signature).to.exist()
|
||||
})
|
||||
|
@@ -7,6 +7,7 @@ const { expect } = chai
|
||||
|
||||
const tests = require('libp2p-interfaces/src/record/tests')
|
||||
const multiaddr = require('multiaddr')
|
||||
const PeerId = require('peer-id')
|
||||
|
||||
const Envelope = require('../../src/record/envelope')
|
||||
const PeerRecord = require('../../src/record/peer-record')
|
||||
@@ -32,6 +33,23 @@ describe('PeerRecord', () => {
|
||||
[peerId] = await peerUtils.createPeerId()
|
||||
})
|
||||
|
||||
it('de/serializes the same as a go record', async () => {
|
||||
const privKey = Uint8Array.from([8, 1, 18, 64, 133, 251, 231, 43, 96, 100, 40, 144, 4, 165, 49, 249, 103, 137, 141, 245, 49, 158, 224, 41, 146, 253, 216, 64, 33, 250, 80, 82, 67, 75, 246, 238, 17, 187, 163, 237, 23, 33, 148, 140, 239, 180, 229, 11, 10, 11, 181, 202, 216, 166, 181, 45, 199, 177, 164, 15, 79, 102, 82, 16, 92, 145, 226, 196])
|
||||
const rawEnvelope = Uint8Array.from([10, 36, 8, 1, 18, 32, 17, 187, 163, 237, 23, 33, 148, 140, 239, 180, 229, 11, 10, 11, 181, 202, 216, 166, 181, 45, 199, 177, 164, 15, 79, 102, 82, 16, 92, 145, 226, 196, 18, 2, 3, 1, 26, 170, 1, 10, 38, 0, 36, 8, 1, 18, 32, 17, 187, 163, 237, 23, 33, 148, 140, 239, 180, 229, 11, 10, 11, 181, 202, 216, 166, 181, 45, 199, 177, 164, 15, 79, 102, 82, 16, 92, 145, 226, 196, 16, 216, 184, 224, 191, 147, 145, 182, 151, 22, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 0, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 1, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 2, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 3, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 4, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 5, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 6, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 7, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 8, 26, 10, 10, 8, 4, 1, 2, 3, 4, 6, 0, 9, 42, 64, 177, 151, 247, 107, 159, 40, 138, 242, 180, 103, 254, 102, 111, 119, 68, 118, 40, 112, 73, 180, 36, 183, 57, 117, 200, 134, 14, 251, 2, 55, 45, 2, 106, 121, 149, 132, 84, 26, 215, 47, 38, 84, 52, 100, 133, 188, 163, 236, 227, 100, 98, 183, 209, 177, 57, 28, 141, 39, 109, 196, 171, 139, 202, 11])
|
||||
const peerId = await PeerId.createFromPrivKey(privKey)
|
||||
|
||||
const env = await Envelope.openAndCertify(rawEnvelope, PeerRecord.DOMAIN)
|
||||
expect(peerId.equals(env.peerId))
|
||||
|
||||
const record = PeerRecord.createFromProtobuf(env.payload)
|
||||
|
||||
// The payload isn't going to match because of how the protobuf encodes uint64 values
|
||||
// They are marshalled correctly on both sides, but will be off by 1 value
|
||||
// Signatures will still be validated
|
||||
const jsEnv = await Envelope.seal(record, peerId)
|
||||
expect(env.payloadType).to.eql(jsEnv.payloadType)
|
||||
})
|
||||
|
||||
it('creates a peer record with peerId', () => {
|
||||
const peerRecord = new PeerRecord({ peerId })
|
||||
|
||||
|
Reference in New Issue
Block a user