From 9be582e2222697b747c081199debdb7edab778e4 Mon Sep 17 00:00:00 2001 From: Vasco Santos Date: Tue, 25 Aug 2020 16:49:07 +0200 Subject: [PATCH] docs: migration 0.28 to 0.29 (#736) * docs: migration 0.28 to 0.29 * chore: finish pubsub migration * chore: add uintarray migration and modules * chore: apply suggestions from code review Co-authored-by: Jacob Heun * chore: add uint8array module reference * chore: rename files Co-authored-by: Jacob Heun --- .../{v0.27-v.28.md => v0.27-v0.28.md} | 0 doc/migrations/v0.28-v0.29.md | 282 ++++++++++++++++++ 2 files changed, 282 insertions(+) rename doc/migrations/{v0.27-v.28.md => v0.27-v0.28.md} (100%) create mode 100644 doc/migrations/v0.28-v0.29.md diff --git a/doc/migrations/v0.27-v.28.md b/doc/migrations/v0.27-v0.28.md similarity index 100% rename from doc/migrations/v0.27-v.28.md rename to doc/migrations/v0.27-v0.28.md diff --git a/doc/migrations/v0.28-v0.29.md b/doc/migrations/v0.28-v0.29.md new file mode 100644 index 00000000..8681125d --- /dev/null +++ b/doc/migrations/v0.28-v0.29.md @@ -0,0 +1,282 @@ + +# 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.19.0", +"libp2p-websockets": "^0.14.0", +```