diff --git a/packages/libp2p-connection/LICENSE b/packages/interface-address-manager/LICENSE similarity index 100% rename from packages/libp2p-connection/LICENSE rename to packages/interface-address-manager/LICENSE diff --git a/packages/libp2p-connection/LICENSE-APACHE b/packages/interface-address-manager/LICENSE-APACHE similarity index 100% rename from packages/libp2p-connection/LICENSE-APACHE rename to packages/interface-address-manager/LICENSE-APACHE diff --git a/packages/libp2p-connection/LICENSE-MIT b/packages/interface-address-manager/LICENSE-MIT similarity index 100% rename from packages/libp2p-connection/LICENSE-MIT rename to packages/interface-address-manager/LICENSE-MIT diff --git a/packages/interface-address-manager/README.md b/packages/interface-address-manager/README.md new file mode 100644 index 000000000..7e9240d08 --- /dev/null +++ b/packages/interface-address-manager/README.md @@ -0,0 +1,35 @@ +# @libp2p/interface-address-manager + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Address Manager interface for libp2p + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-address-manager +``` + +## Usage + +```js +import type { AddressManager } from '@libp2p/interfaces-address-manager' +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-peer-collections/package.json b/packages/interface-address-manager/package.json similarity index 81% rename from packages/libp2p-peer-collections/package.json rename to packages/interface-address-manager/package.json index 7a31c5702..d35a6fb2e 100644 --- a/packages/libp2p-peer-collections/package.json +++ b/packages/interface-address-manager/package.json @@ -1,9 +1,9 @@ { - "name": "@libp2p/peer-collections", - "version": "1.0.3", - "description": "Stores values against a peer id", + "name": "@libp2p/interface-address-manager", + "version": "0.0.1", + "description": "Address Manager interface for libp2p", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-peer-collections#readme", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-address-manager#readme", "repository": { "type": "git", "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" @@ -12,7 +12,8 @@ "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" }, "keywords": [ - "IPFS" + "interface", + "libp2p" ], "engines": { "node": ">=16.0.0", @@ -28,6 +29,7 @@ ], "exports": { ".": { + "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" } }, @@ -123,21 +125,13 @@ "lint": "aegir lint", "dep-check": "aegir dep-check", "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", "release": "aegir release" }, "dependencies": { "@libp2p/interfaces": "^2.0.0", - "@libp2p/peer-id": "^1.1.0" + "@multiformats/multiaddr": "^10.2.0" }, "devDependencies": { - "@libp2p/peer-id-factory": "^1.0.0", - "aegir": "^37.0.7" + "aegir": "^37.0.17" } } diff --git a/packages/libp2p-interfaces/src/address-manager/index.ts b/packages/interface-address-manager/src/index.ts similarity index 91% rename from packages/libp2p-interfaces/src/address-manager/index.ts rename to packages/interface-address-manager/src/index.ts index e91b9869e..1ebddb3c5 100644 --- a/packages/libp2p-interfaces/src/address-manager/index.ts +++ b/packages/interface-address-manager/src/index.ts @@ -1,5 +1,5 @@ import type { Multiaddr } from '@multiformats/multiaddr' -import type { EventEmitter } from '../events.js' +import type { EventEmitter } from '@libp2p/interfaces/events' export interface AddressManagerEvents { /** diff --git a/packages/libp2p-logger/tsconfig.json b/packages/interface-address-manager/tsconfig.json similarity index 73% rename from packages/libp2p-logger/tsconfig.json rename to packages/interface-address-manager/tsconfig.json index d59d66e96..838a878cc 100644 --- a/packages/libp2p-logger/tsconfig.json +++ b/packages/interface-address-manager/tsconfig.json @@ -4,12 +4,11 @@ "outDir": "dist" }, "include": [ - "src", - "test" + "src" ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interfaces" } ] } diff --git a/packages/libp2p-interface-compliance-tests/CHANGELOG.md b/packages/interface-compliance-tests/CHANGELOG.md similarity index 100% rename from packages/libp2p-interface-compliance-tests/CHANGELOG.md rename to packages/interface-compliance-tests/CHANGELOG.md diff --git a/packages/libp2p-interface-compliance-tests/LICENSE b/packages/interface-compliance-tests/LICENSE similarity index 100% rename from packages/libp2p-interface-compliance-tests/LICENSE rename to packages/interface-compliance-tests/LICENSE diff --git a/packages/libp2p-interface-compliance-tests/LICENSE-APACHE b/packages/interface-compliance-tests/LICENSE-APACHE similarity index 100% rename from packages/libp2p-interface-compliance-tests/LICENSE-APACHE rename to packages/interface-compliance-tests/LICENSE-APACHE diff --git a/packages/libp2p-interface-compliance-tests/LICENSE-MIT b/packages/interface-compliance-tests/LICENSE-MIT similarity index 100% rename from packages/libp2p-interface-compliance-tests/LICENSE-MIT rename to packages/interface-compliance-tests/LICENSE-MIT diff --git a/packages/interface-compliance-tests/README.md b/packages/interface-compliance-tests/README.md new file mode 100644 index 000000000..df08c7a51 --- /dev/null +++ b/packages/interface-compliance-tests/README.md @@ -0,0 +1,33 @@ +# @libp2p/interface-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for JS libp2p interfaces + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-compliance-tests +``` + +## Usage + +Each [interface](https://npmjs.org/packages/@libp2p/interfaces) has its documentation on how to use the compliance tests and should be used as the source of truth. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-compliance-tests/package.json b/packages/interface-compliance-tests/package.json new file mode 100644 index 000000000..0b452b339 --- /dev/null +++ b/packages/interface-compliance-tests/package.json @@ -0,0 +1,157 @@ +{ + "name": "@libp2p/interface-compliance-tests", + "version": "2.0.3", + "description": "Compliance tests for JS libp2p interfaces", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ], + "src/*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ] + } + }, + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + }, + "./is-valid-tick": { + "types": "./dist/src/is-valid-tick.d.ts", + "import": "./dist/src/is-valid-tick.js" + }, + "./peers": { + "types": "./dist/src/peers.d.ts", + "import": "./dist/src/peers.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/index.ts b/packages/interface-compliance-tests/src/index.ts similarity index 100% rename from packages/libp2p-interface-compliance-tests/src/index.ts rename to packages/interface-compliance-tests/src/index.ts diff --git a/packages/libp2p-interface-compliance-tests/src/utils/is-valid-tick.ts b/packages/interface-compliance-tests/src/is-valid-tick.ts similarity index 100% rename from packages/libp2p-interface-compliance-tests/src/utils/is-valid-tick.ts rename to packages/interface-compliance-tests/src/is-valid-tick.ts diff --git a/packages/libp2p-interface-compliance-tests/src/utils/peers.ts b/packages/interface-compliance-tests/src/peers.ts similarity index 100% rename from packages/libp2p-interface-compliance-tests/src/utils/peers.ts rename to packages/interface-compliance-tests/src/peers.ts diff --git a/packages/libp2p-interfaces/tsconfig.json b/packages/interface-compliance-tests/tsconfig.json similarity index 100% rename from packages/libp2p-interfaces/tsconfig.json rename to packages/interface-compliance-tests/tsconfig.json diff --git a/packages/libp2p-interfaces/LICENSE b/packages/interface-connection-compliance-tests/LICENSE similarity index 100% rename from packages/libp2p-interfaces/LICENSE rename to packages/interface-connection-compliance-tests/LICENSE diff --git a/packages/libp2p-interfaces/LICENSE-APACHE b/packages/interface-connection-compliance-tests/LICENSE-APACHE similarity index 100% rename from packages/libp2p-interfaces/LICENSE-APACHE rename to packages/interface-connection-compliance-tests/LICENSE-APACHE diff --git a/packages/libp2p-interfaces/LICENSE-MIT b/packages/interface-connection-compliance-tests/LICENSE-MIT similarity index 100% rename from packages/libp2p-interfaces/LICENSE-MIT rename to packages/interface-connection-compliance-tests/LICENSE-MIT diff --git a/packages/interface-connection-compliance-tests/README.md b/packages/interface-connection-compliance-tests/README.md new file mode 100644 index 000000000..ea67e339b --- /dev/null +++ b/packages/interface-connection-compliance-tests/README.md @@ -0,0 +1,53 @@ +# @libp2p/interface-connection-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p Connection interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-connection-compliance-tests +``` + +## Usage + +This is a test suite and interface you can use to implement a connection. The connection interface contains all the metadata associated with it, as well as an array of the streams opened through this connection. In the same way as the connection, a stream contains properties with its metadata, plus an iterable duplex object that offers a mechanism for writing and reading data, with back pressure. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. + +The primary goal of this module is to enable developers to pick, swap or upgrade their connection without losing the same API expectations and mechanisms such as back pressure and the ability to half close a connection. + +Publishing a test suite as a module lets multiple modules ensure compatibility since they use the same test suite. + +```js +import tests from '@libp2p/interface-connection-compliance-tests' + +describe('your connection', () => { + tests({ + // Options should be passed to your connection + async setup (options) { + return YourConnection + }, + async teardown () { + // cleanup resources created by setup() + } + }) +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-connection-compliance-tests/package.json b/packages/interface-connection-compliance-tests/package.json new file mode 100644 index 000000000..82baef166 --- /dev/null +++ b/packages/interface-connection-compliance-tests/package.json @@ -0,0 +1,136 @@ +{ + "name": "@libp2p/interface-connection-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p Connection interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-connection": "~0.0.0", + "aegir": "^37.0.17", + "sinon": "^14.0.0" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/connection/connection.ts b/packages/interface-connection-compliance-tests/src/connection.ts similarity index 97% rename from packages/libp2p-interface-compliance-tests/src/connection/connection.ts rename to packages/interface-connection-compliance-tests/src/connection.ts index 9b1ef05b8..f7553cecd 100644 --- a/packages/libp2p-interface-compliance-tests/src/connection/connection.ts +++ b/packages/interface-connection-compliance-tests/src/connection.ts @@ -1,7 +1,7 @@ import { expect } from 'aegir/chai' import sinon from 'sinon' -import type { TestSetup } from '../index.js' -import type { Connection } from '@libp2p/interfaces/connection' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Connection } from '@libp2p/interface-connection' export default (test: TestSetup) => { describe('connection', () => { diff --git a/packages/interface-connection-compliance-tests/src/index.ts b/packages/interface-connection-compliance-tests/src/index.ts new file mode 100644 index 000000000..c87ff4cdf --- /dev/null +++ b/packages/interface-connection-compliance-tests/src/index.ts @@ -0,0 +1,7 @@ +import connectionSuite from './connection.js' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Connection } from '@libp2p/interface-connection' + +export default (test: TestSetup) => { + connectionSuite(test) +} diff --git a/packages/interface-connection-compliance-tests/tsconfig.json b/packages/interface-connection-compliance-tests/tsconfig.json new file mode 100644 index 000000000..40cf163c0 --- /dev/null +++ b/packages/interface-connection-compliance-tests/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "references": [ + { + "path": "../interface-compliance-tests" + }, + { + "path": "../interface-connection" + } + ] +} diff --git a/packages/libp2p-logger/LICENSE b/packages/interface-connection-encrypter-compliance-tests/LICENSE similarity index 100% rename from packages/libp2p-logger/LICENSE rename to packages/interface-connection-encrypter-compliance-tests/LICENSE diff --git a/packages/libp2p-logger/LICENSE-APACHE b/packages/interface-connection-encrypter-compliance-tests/LICENSE-APACHE similarity index 100% rename from packages/libp2p-logger/LICENSE-APACHE rename to packages/interface-connection-encrypter-compliance-tests/LICENSE-APACHE diff --git a/packages/libp2p-logger/LICENSE-MIT b/packages/interface-connection-encrypter-compliance-tests/LICENSE-MIT similarity index 100% rename from packages/libp2p-logger/LICENSE-MIT rename to packages/interface-connection-encrypter-compliance-tests/LICENSE-MIT diff --git a/packages/interface-connection-encrypter-compliance-tests/README.md b/packages/interface-connection-encrypter-compliance-tests/README.md new file mode 100644 index 000000000..1bac4c31a --- /dev/null +++ b/packages/interface-connection-encrypter-compliance-tests/README.md @@ -0,0 +1,46 @@ +# @libp2p/interface-connection-encrypter-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p Connection Encrypter interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-connection-encrypter-compliance-tests +``` + +## Usage + +```js +import tests from '@libp2p/interface-connection-encrypter-compliance-tests' +import yourCrypto from './your-encrypter' + +tests({ + setup () { + // Set up your crypto if needed, then return it + return yourCrypto + }, + teardown () { + // Clean up your crypto if needed + } +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-connection-encrypter-compliance-tests/package.json b/packages/interface-connection-encrypter-compliance-tests/package.json new file mode 100644 index 000000000..43ebcea7c --- /dev/null +++ b/packages/interface-connection-encrypter-compliance-tests/package.json @@ -0,0 +1,144 @@ +{ + "name": "@libp2p/interface-connection-encrypter-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p Connection Encrypter interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection-encrypter-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-connection-encrypter": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/peer-id-factory": "^1.0.12", + "@multiformats/multiaddr": "^10.2.0", + "aegir": "^37.0.17", + "it-all": "^1.0.6", + "it-pair": "^2.0.2", + "it-pipe": "^2.0.3", + "it-stream-types": "^1.0.4", + "uint8arrays": "^3.0.0" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/connection-encrypter/index.ts b/packages/interface-connection-encrypter-compliance-tests/src/index.ts similarity index 89% rename from packages/libp2p-interface-compliance-tests/src/connection-encrypter/index.ts rename to packages/interface-connection-encrypter-compliance-tests/src/index.ts index ccfc7dec0..16ee443ad 100644 --- a/packages/libp2p-interface-compliance-tests/src/connection-encrypter/index.ts +++ b/packages/interface-connection-encrypter-compliance-tests/src/index.ts @@ -3,12 +3,12 @@ import { pipe } from 'it-pipe' import * as PeerIdFactory from '@libp2p/peer-id-factory' import all from 'it-all' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import peers from '../utils/peers.js' -import { UnexpectedPeerError } from '@libp2p/interfaces/connection-encrypter/errors' +import peers from '@libp2p/interface-compliance-tests/peers' +import { UnexpectedPeerError } from '@libp2p/interface-connection-encrypter/errors' import { createMaConnPair } from './utils/index.js' -import type { TestSetup } from '../index.js' -import type { ConnectionEncrypter } from '@libp2p/interfaces/connection-encrypter' -import type { PeerId } from '@libp2p/interfaces/peer-id' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { ConnectionEncrypter } from '@libp2p/interface-connection-encrypter' +import type { PeerId } from '@libp2p/interface-peer-id' import type { Source } from 'it-stream-types' export default (common: TestSetup) => { diff --git a/packages/libp2p-interface-compliance-tests/src/connection-encrypter/utils/index.ts b/packages/interface-connection-encrypter-compliance-tests/src/utils/index.ts similarity index 89% rename from packages/libp2p-interface-compliance-tests/src/connection-encrypter/utils/index.ts rename to packages/interface-connection-encrypter-compliance-tests/src/utils/index.ts index e5f43054d..99b300729 100644 --- a/packages/libp2p-interface-compliance-tests/src/connection-encrypter/utils/index.ts +++ b/packages/interface-connection-encrypter-compliance-tests/src/utils/index.ts @@ -1,6 +1,6 @@ import { duplexPair } from 'it-pair/duplex' import { Multiaddr } from '@multiformats/multiaddr' -import type { MultiaddrConnection } from '@libp2p/interfaces/transport' +import type { MultiaddrConnection } from '@libp2p/interface-connection' import type { Duplex } from 'it-stream-types' export function createMaConnPair (): [MultiaddrConnection, MultiaddrConnection] { diff --git a/packages/libp2p-connection/tsconfig.json b/packages/interface-connection-encrypter-compliance-tests/tsconfig.json similarity index 56% rename from packages/libp2p-connection/tsconfig.json rename to packages/interface-connection-encrypter-compliance-tests/tsconfig.json index eb97dd54b..77fd5244f 100644 --- a/packages/libp2p-connection/tsconfig.json +++ b/packages/interface-connection-encrypter-compliance-tests/tsconfig.json @@ -9,16 +9,16 @@ ], "references": [ { - "path": "../libp2p-interface-compliance-tests" + "path": "../interface-compliance-tests" }, { - "path": "../libp2p-interfaces" + "path": "../interface-connection" }, { - "path": "../libp2p-logger" + "path": "../interface-connection-encrypter" }, { - "path": "../libp2p-peer-id-factory" + "path": "../interface-peer-id" } ] } diff --git a/packages/libp2p-multistream-select/LICENSE b/packages/interface-connection-encrypter/LICENSE similarity index 100% rename from packages/libp2p-multistream-select/LICENSE rename to packages/interface-connection-encrypter/LICENSE diff --git a/packages/libp2p-multistream-select/LICENSE-APACHE b/packages/interface-connection-encrypter/LICENSE-APACHE similarity index 100% rename from packages/libp2p-multistream-select/LICENSE-APACHE rename to packages/interface-connection-encrypter/LICENSE-APACHE diff --git a/packages/libp2p-multistream-select/LICENSE-MIT b/packages/interface-connection-encrypter/LICENSE-MIT similarity index 100% rename from packages/libp2p-multistream-select/LICENSE-MIT rename to packages/interface-connection-encrypter/LICENSE-MIT diff --git a/packages/libp2p-interfaces/src/connection-encrypter/README.md b/packages/interface-connection-encrypter/README.md similarity index 73% rename from packages/libp2p-interfaces/src/connection-encrypter/README.md rename to packages/interface-connection-encrypter/README.md index a0631421d..20bab8b33 100644 --- a/packages/libp2p-interfaces/src/connection-encrypter/README.md +++ b/packages/interface-connection-encrypter/README.md @@ -1,42 +1,31 @@ -interface-connection-encrypter -================== +# @libp2p/interface-connection-encrypter -> A test suite you can use to implement a libp2p crypto module. A libp2p crypto module is used to ensure all exchanged data between two peers is encrypted. +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) -**Modules that implement the interface** +> Connection Encrypter interface for libp2p -- [@chainSafe/js-libp2p-noise](https://github.com/ChainSafe/js-libp2p-noise) -- [js-libp2p-secio](https://github.com/NodeFactoryIo/js-libp2p-secio) +## Table of contents -## Table of Contents -- [interface-connection-encrypter](#interface-connection-encrypter) - - [Table of Contents](#table-of-contents) - - [Using the Test Suite](#using-the-test-suite) - - [API](#api) - - [Secure Inbound](#secure-inbound) - - [Secure Outbound](#secure-outbound) - - [Crypto Errors](#crypto-errors) - - [Error Types](#error-types) +- [Install](#install) +- [API](#api) + - [Secure Inbound](#secure-inbound) + - [Secure Outbound](#secure-outbound) +- [Crypto Errors](#crypto-errors) + - [Error Types](#error-types) +- [License](#license) + - [Contribution](#contribution) -## Using the Test Suite +## Install -You can also check out the [internal test suite](../../test/crypto/compliance.spec.js) to see the setup in action. - -```js -const tests = require('libp2p-interfaces-compliance-tests/connection-encrypter') -const yourCrypto = require('./your-encrypter') - -tests({ - setup () { - // Set up your crypto if needed, then return it - return yourCrypto - }, - teardown () { - // Clean up your crypto if needed - } -}) +```console +$ npm i @libp2p/interface-connection-encrypter ``` +**Modules that implement the interface** + +- [@chainSafe/js-libp2p-noise](https://github.com/ChainSafe/js-libp2p-noise) +- [js-libp2p-secio](https://github.com/NodeFactoryIo/js-libp2p-secio) + ## API - `Crypto` @@ -51,11 +40,13 @@ tests({ Secures an inbound [streaming iterable duplex][iterable-duplex] connection. It returns an encrypted [streaming iterable duplex][iterable-duplex], as well as the [PeerId][peer-id] of the remote peer. **Parameters** + - `localPeer` is the [PeerId][peer-id] of the receiving peer. - `duplex` is the [streaming iterable duplex][iterable-duplex] that will be encryption. - `remotePeer` is the optional [PeerId][peer-id] of the initiating peer, if known. This may only exist during transport upgrades. **Return Value** + - `` - `conn`: An encrypted [streaming iterable duplex][iterable-duplex]. - `remotePeer`: The [PeerId][peer-id] of the remote peer. @@ -67,16 +58,19 @@ Secures an inbound [streaming iterable duplex][iterable-duplex] connection. It r Secures an outbound [streaming iterable duplex][iterable-duplex] connection. It returns an encrypted [streaming iterable duplex][iterable-duplex], as well as the [PeerId][peer-id] of the remote peer. **Parameters** + - `localPeer` is the [PeerId][peer-id] of the receiving peer. - `duplex` is the [streaming iterable duplex][iterable-duplex] that will be encrypted. - `remotePeer` is the [PeerId][peer-id] of the remote peer. If provided, implementations **should** use this to validate the integrity of the remote peer. **Return Value** + - `` - `conn`: An encrypted [streaming iterable duplex][iterable-duplex]. - `remotePeer`: The [PeerId][peer-id] of the remote peer. This **should** match the `remotePeer` parameter, and implementations should enforce this. [peer-id]: https://github.com/libp2p/js-peer-id + [iterable-duplex]: https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it ## Crypto Errors @@ -99,3 +93,14 @@ console.log(error.code === UnexpectedPeerError.code) // true - `InvalidCryptoExchangeError` - Should be thrown when a peer provides data that is insufficient to finish the crypto exchange. - `InvalidCryptoTransmissionError` - Should be thrown when an error occurs during encryption/decryption. - `UnexpectedPeerError` - Should be thrown when the expected peer id does not match the peer id determined via the crypto exchange. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-connection-encrypter/package.json b/packages/interface-connection-encrypter/package.json new file mode 100644 index 000000000..c05a92a13 --- /dev/null +++ b/packages/interface-connection-encrypter/package.json @@ -0,0 +1,157 @@ +{ + "name": "@libp2p/interface-connection-encrypter", + "version": "0.0.1", + "description": "Connection Encrypter interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection-encrypter#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ], + "src/*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ] + } + }, + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + }, + "./errors": { + "types": "./dist/src/errors.d.ts", + "import": "./dist/src/errors.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0", + "it-stream-types": "^1.0.4" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/connection-encrypter/errors.ts b/packages/interface-connection-encrypter/src/errors.ts similarity index 100% rename from packages/libp2p-interfaces/src/connection-encrypter/errors.ts rename to packages/interface-connection-encrypter/src/errors.ts diff --git a/packages/libp2p-interfaces/src/connection-encrypter/index.ts b/packages/interface-connection-encrypter/src/index.ts similarity index 92% rename from packages/libp2p-interfaces/src/connection-encrypter/index.ts rename to packages/interface-connection-encrypter/src/index.ts index c14c7b908..f815b30cf 100644 --- a/packages/libp2p-interfaces/src/connection-encrypter/index.ts +++ b/packages/interface-connection-encrypter/src/index.ts @@ -1,4 +1,4 @@ -import type { PeerId } from '../peer-id/index.js' +import type { PeerId } from '@libp2p/interface-peer-id' import type { Duplex } from 'it-stream-types' /** diff --git a/packages/libp2p-peer-id/tsconfig.json b/packages/interface-connection-encrypter/tsconfig.json similarity index 73% rename from packages/libp2p-peer-id/tsconfig.json rename to packages/interface-connection-encrypter/tsconfig.json index d59d66e96..d8db0b667 100644 --- a/packages/libp2p-peer-id/tsconfig.json +++ b/packages/interface-connection-encrypter/tsconfig.json @@ -4,12 +4,11 @@ "outDir": "dist" }, "include": [ - "src", - "test" + "src" ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-peer-id" } ] } diff --git a/packages/libp2p-peer-collections/LICENSE b/packages/interface-connection-manager/LICENSE similarity index 100% rename from packages/libp2p-peer-collections/LICENSE rename to packages/interface-connection-manager/LICENSE diff --git a/packages/libp2p-peer-collections/LICENSE-APACHE b/packages/interface-connection-manager/LICENSE-APACHE similarity index 100% rename from packages/libp2p-peer-collections/LICENSE-APACHE rename to packages/interface-connection-manager/LICENSE-APACHE diff --git a/packages/libp2p-peer-collections/LICENSE-MIT b/packages/interface-connection-manager/LICENSE-MIT similarity index 100% rename from packages/libp2p-peer-collections/LICENSE-MIT rename to packages/interface-connection-manager/LICENSE-MIT diff --git a/packages/interface-connection-manager/README.md b/packages/interface-connection-manager/README.md new file mode 100644 index 000000000..9edac0398 --- /dev/null +++ b/packages/interface-connection-manager/README.md @@ -0,0 +1,35 @@ +# @libp2p/interface-connection-manager + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Connection Manager interface for libp2p + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-connection-manager +``` + +## Usage + +```js +import type { ConnectionManager } from '@libp2p/interface-connection-manager' +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-tracked-map/package.json b/packages/interface-connection-manager/package.json similarity index 82% rename from packages/libp2p-tracked-map/package.json rename to packages/interface-connection-manager/package.json index 97a9afb8c..bce28e340 100644 --- a/packages/libp2p-tracked-map/package.json +++ b/packages/interface-connection-manager/package.json @@ -1,9 +1,9 @@ { - "name": "@libp2p/tracked-map", - "version": "1.0.7", - "description": "Allows tracking of statistics while libp2p is running", + "name": "@libp2p/interface-connection-manager", + "version": "0.0.1", + "description": "Connection Manager interface for libp2p", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-tracked-map#readme", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection-manager#readme", "repository": { "type": "git", "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" @@ -12,7 +12,8 @@ "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" }, "keywords": [ - "IPFS" + "interface", + "libp2p" ], "engines": { "node": ">=16.0.0", @@ -28,6 +29,7 @@ ], "exports": { ".": { + "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" } }, @@ -123,20 +125,14 @@ "lint": "aegir lint", "dep-check": "aegir dep-check", "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", "release": "aegir release" }, "dependencies": { + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0", "@libp2p/interfaces": "^2.0.0" }, "devDependencies": { - "aegir": "^37.0.7", - "sinon": "^14.0.0" + "aegir": "^37.0.17" } } diff --git a/packages/libp2p-interfaces/src/connection-manager/index.ts b/packages/interface-connection-manager/src/index.ts similarity index 70% rename from packages/libp2p-interfaces/src/connection-manager/index.ts rename to packages/interface-connection-manager/src/index.ts index e6903350e..516e02e1e 100644 --- a/packages/libp2p-interfaces/src/connection-manager/index.ts +++ b/packages/interface-connection-manager/src/index.ts @@ -1,7 +1,7 @@ -import type { AbortOptions } from '../index.js' -import type { EventEmitter } from '../events.js' -import type { Connection } from '../connection/index.js' -import type { PeerId } from '../peer-id/index.js' +import type { AbortOptions } from '@libp2p/interfaces' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Connection } from '@libp2p/interface-connection' +import type { PeerId } from '@libp2p/interface-peer-id' export interface ConnectionManagerEvents { 'peer:connect': CustomEvent diff --git a/packages/interface-connection-manager/tsconfig.json b/packages/interface-connection-manager/tsconfig.json new file mode 100644 index 000000000..cbde3d05c --- /dev/null +++ b/packages/interface-connection-manager/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-connection" + }, + { + "path": "../interface-peer-id" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/libp2p-peer-id-factory/LICENSE b/packages/interface-connection/LICENSE similarity index 100% rename from packages/libp2p-peer-id-factory/LICENSE rename to packages/interface-connection/LICENSE diff --git a/packages/libp2p-peer-id-factory/LICENSE-APACHE b/packages/interface-connection/LICENSE-APACHE similarity index 100% rename from packages/libp2p-peer-id-factory/LICENSE-APACHE rename to packages/interface-connection/LICENSE-APACHE diff --git a/packages/libp2p-peer-id-factory/LICENSE-MIT b/packages/interface-connection/LICENSE-MIT similarity index 100% rename from packages/libp2p-peer-id-factory/LICENSE-MIT rename to packages/interface-connection/LICENSE-MIT diff --git a/packages/libp2p-interfaces/src/connection/README.md b/packages/interface-connection/README.md similarity index 78% rename from packages/libp2p-interfaces/src/connection/README.md rename to packages/interface-connection/README.md index db1b3da59..969bae0be 100644 --- a/packages/libp2p-interfaces/src/connection/README.md +++ b/packages/interface-connection/README.md @@ -1,5 +1,45 @@ -interface-connection -================== +# @libp2p/interface-connection + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Connection interface for libp2p + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [Connection](#connection) +- [Test suite](#test-suite) +- [API](#api) + - [Connection](#connection-1) + - [Creating a connection instance](#creating-a-connection-instance) + - [Create a new stream](#create-a-new-stream) + - [Add stream metadata](#add-stream-metadata) + - [Remove a from the registry](#remove-a-from-the-registry) + - [Close connection](#close-connection) + - [Connection identifier](#connection-identifier) + - [Connection streams registry](#connection-streams-registry) + - [Remote peer](#remote-peer) + - [Local peer](#local-peer) + - [Get the connection Streams](#get-the-connection-streams) + - [Remote address](#remote-address) + - [Local address](#local-address) + - [Stat](#stat) + - [Tags](#tags) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-connection +``` + +## Usage + +```js +import type { Connection } from '@libp2p/interface-connection' +``` This is a test suite and interface you can use to implement a connection. The connection interface contains all the metadata associated with it, as well as an array of the streams opened through this connection. In the same way as the connection, a stream contains properties with its metadata, plus an iterable duplex object that offers a mechanism for writing and reading data, with back pressure. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. @@ -7,25 +47,23 @@ The primary goal of this module is to enable developers to pick, swap or upgrade Publishing a test suite as a module lets multiple modules ensure compatibility since they use the same test suite. -## Usage - -### Connection +## Connection Before creating a connection from a transport compatible with `libp2p` it is important to understand some concepts: - **socket**: the underlying raw duplex connection between two nodes. It is created by the transports during a dial/listen. - **[multiaddr connection](https://github.com/libp2p/interface-transport#multiaddrconnection)**: an abstraction over the socket to allow it to work with multiaddr addresses. It is a duplex connection that transports create to wrap the socket before passing to an upgrader that turns it into a standard connection (see below). -- **connection**: a connection between two _peers_ that has built in multiplexing and info about the connected peer. It is created from a [multiaddr connection](https://github.com/libp2p/interface-transport#multiaddrconnection) by an upgrader. The upgrader uses multistream-select to add secio and multiplexing and returns this object. +- **connection**: a connection between two *peers* that has built in multiplexing and info about the connected peer. It is created from a [multiaddr connection](https://github.com/libp2p/interface-transport#multiaddrconnection) by an upgrader. The upgrader uses multistream-select to add secio and multiplexing and returns this object. - **stream**: a muxed duplex channel of the `connection`. Each connection may have many streams. A connection stands for the libp2p communication duplex layer between two nodes. It is **not** the underlying raw transport duplex layer (socket), such as a TCP socket, but an abstracted layer that sits on top of the raw socket. This helps ensuring that the transport is responsible for socket management, while also allowing the application layer to handle the connection management. -### Test suite +## Test suite ```js -const tests = require('libp2p-interfaces-compliance-tests/connection') +const tests = require('@libp2p/interface-connection-compliance-tests') describe('your connection', () => { tests({ // Options should be passed to your connection @@ -46,6 +84,7 @@ describe('your connection', () => { A valid connection (one that follows this abstraction), must implement the following API: - type: `Connection` + ```js new Connection({ localAddr, @@ -66,17 +105,18 @@ new Connection({ } }) ``` - - ` conn.localAddr` - - ` conn.remoteAddr` - - ` conn.localPeer` - - ` conn.remotePeer` - - ` conn.stat` - - ` conn.registry` - - `Array conn.streams` - - `Promise conn.newStream(Array)` - - ` conn.removeStream(id)` - - ` conn.addStream(stream, protocol, metadata)` - - `Promise<> conn.close()` + +- ` conn.localAddr` +- ` conn.remoteAddr` +- ` conn.localPeer` +- ` conn.remotePeer` +- ` conn.stat` +- ` conn.registry` +- `Array conn.streams` +- `Promise conn.newStream(Array)` +- ` conn.removeStream(id)` +- ` conn.addStream(stream, protocol, metadata)` +- `Promise<> conn.close()` It can be obtained as follows: @@ -117,11 +157,12 @@ Creates a new Connection instance. `close` is the `function` responsible for closing the raw connection. `getStreams` is the `function` responsible for getting the streams muxed within the connection. `stats` is an `object` with the metadata of the connection. It contains: + - `direction` is a `string` indicating whether the connection is `inbound` or `outbound`. - `timeline` is an `object` with the relevant events timestamps of the connection (`open`, `upgraded` and `closed`; the `closed` will be added when the connection is closed). - `multiplexer` is a `string` with the connection multiplexing codec (optional). - `encryption` is a `string` with the connection encryption method identifier (optional). -- `status` is a `string` indicating the overall status of the connection. It is one of [`'open'`, `'closing'`, `'closed'`] +- `status` is a `string` indicating the overall status of the connection. It is one of \[`'open'`, `'closing'`, `'closed'`] #### Create a new stream @@ -160,7 +201,6 @@ Removes the stream with the given id from the connection registry. `id` is the unique id of the stream for this connection. - #### Close connection - `JavaScript` - `conn.close()` @@ -254,3 +294,14 @@ This property contains the encryption method being used in the connection. It is - `JavaScript` - `conn.tags` This property contains an array of tags associated with the connection. New tags can be pushed to this array during the connection's lifetime. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-interfaces/src/connection/img/badge.png b/packages/interface-connection/img/badge.png similarity index 100% rename from packages/libp2p-interfaces/src/connection/img/badge.png rename to packages/interface-connection/img/badge.png diff --git a/packages/libp2p-interfaces/src/connection/img/badge.sketch b/packages/interface-connection/img/badge.sketch similarity index 100% rename from packages/libp2p-interfaces/src/connection/img/badge.sketch rename to packages/interface-connection/img/badge.sketch diff --git a/packages/libp2p-interfaces/src/connection/img/badge.svg b/packages/interface-connection/img/badge.svg similarity index 100% rename from packages/libp2p-interfaces/src/connection/img/badge.svg rename to packages/interface-connection/img/badge.svg diff --git a/packages/libp2p-topology/package.json b/packages/interface-connection/package.json similarity index 85% rename from packages/libp2p-topology/package.json rename to packages/interface-connection/package.json index cef0be793..95072bdab 100644 --- a/packages/libp2p-topology/package.json +++ b/packages/interface-connection/package.json @@ -1,9 +1,9 @@ { - "name": "@libp2p/topology", - "version": "1.1.8", - "description": "libp2p network topology", + "name": "@libp2p/interface-connection", + "version": "0.0.1", + "description": "Connection interface for libp2p", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-topology#readme", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-connection#readme", "repository": { "type": "git", "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" @@ -45,12 +45,12 @@ ], "exports": { ".": { - "import": "./dist/src/index.js", - "types": "./dist/src/index.d.ts" + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" }, - "./multicodec-topology": { - "import": "./dist/src/multicodec-topology.js", - "types": "./dist/src/multicodec-topology.d.ts" + "./status": { + "types": "./dist/src/status.d.ts", + "import": "./dist/src/status.js" } }, "eslintConfig": { @@ -148,13 +148,12 @@ "release": "aegir release" }, "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0", "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", - "@multiformats/multiaddr": "^10.1.5", - "err-code": "^3.0.1", - "it-all": "^1.0.6" + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" }, "devDependencies": { - "aegir": "^37.0.7" + "aegir": "^37.0.17" } } diff --git a/packages/libp2p-interfaces/src/connection/index.ts b/packages/interface-connection/src/index.ts similarity index 91% rename from packages/libp2p-interfaces/src/connection/index.ts rename to packages/interface-connection/src/index.ts index b07c2f0eb..85d32feca 100644 --- a/packages/libp2p-interfaces/src/connection/index.ts +++ b/packages/interface-connection/src/index.ts @@ -1,9 +1,8 @@ import type { Multiaddr } from '@multiformats/multiaddr' -import type { PeerId } from '../peer-id' +import type { PeerId } from '@libp2p/interface-peer-id' import type * as Status from './status.js' import type { Duplex } from 'it-stream-types' -import type { MultiaddrConnection } from '../transport' -import type { AbortOptions } from '..' +import type { AbortOptions } from '@libp2p/interfaces' export interface Timeline { open: number @@ -204,3 +203,20 @@ export interface ConnectionProtector { */ protect: (connection: MultiaddrConnection) => Promise } + +export interface MultiaddrConnectionTimeline { + open: number + upgraded?: number + close?: number +} + +/** + * A MultiaddrConnection is returned by transports after dialing + * a peer. It is a low-level primitive and is the raw connection + * without encryption or stream multiplexing. + */ +export interface MultiaddrConnection extends Duplex { + close: (err?: Error) => Promise + remoteAddr: Multiaddr + timeline: MultiaddrConnectionTimeline +} diff --git a/packages/libp2p-interfaces/src/connection/status.ts b/packages/interface-connection/src/status.ts similarity index 100% rename from packages/libp2p-interfaces/src/connection/status.ts rename to packages/interface-connection/src/status.ts diff --git a/packages/interface-connection/tsconfig.json b/packages/interface-connection/tsconfig.json new file mode 100644 index 000000000..22a45bf0b --- /dev/null +++ b/packages/interface-connection/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-id" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/libp2p-peer-id/LICENSE b/packages/interface-content-routing/LICENSE similarity index 100% rename from packages/libp2p-peer-id/LICENSE rename to packages/interface-content-routing/LICENSE diff --git a/packages/libp2p-peer-id/LICENSE-APACHE b/packages/interface-content-routing/LICENSE-APACHE similarity index 100% rename from packages/libp2p-peer-id/LICENSE-APACHE rename to packages/interface-content-routing/LICENSE-APACHE diff --git a/packages/libp2p-peer-id/LICENSE-MIT b/packages/interface-content-routing/LICENSE-MIT similarity index 100% rename from packages/libp2p-peer-id/LICENSE-MIT rename to packages/interface-content-routing/LICENSE-MIT diff --git a/packages/interface-content-routing/README.md b/packages/interface-content-routing/README.md new file mode 100644 index 000000000..574afd73e --- /dev/null +++ b/packages/interface-content-routing/README.md @@ -0,0 +1,92 @@ +# @libp2p/interface-content-routing + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Content routing interface for libp2p + +## Table of contents + +- - [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [How to use the battery of tests](#how-to-use-the-battery-of-tests) + - [Node.js](#nodejs) +- [API](#api) + - - [findProviders](#findproviders) + - [provide](#provide) + - [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-content-routing +``` + +The primary goal of this module is to enable developers to pick and swap their Content Routing module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. + +Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. + +# Modules that implement the interface + +- [JavaScript libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) +- [JavaScript libp2p-delegated-content-routing](https://github.com/libp2p/js-libp2p-delegated-content-routing) + +# Badge + +Include this badge in your readme if you make a module that is compatible with the interface-content-routing API. You can validate this by running the tests. + +![](img/badge.png) + +# How to use the battery of tests + +## Node.js + +TBD + +# API + +A valid (read: that follows this abstraction) Content Routing module must implement the following API. + +### findProviders + +- `findProviders(cid)` + +Find peers in the network that can provide a specific value, given a key. + +**Parameters** + +- [CID](https://github.com/multiformats/js-cid) + +**Returns** + +It returns an `AsyncIterable` containing the identification and addresses of the peers providing the given key, as follows: + +`AsyncIterable<{ id: PeerId, multiaddrs: Multiaddr[] }>` + +### provide + +- `provide(cid)` + +Announce to the network that we are providing the given value. + +**Parameters** + +- [CID](https://github.com/multiformats/js-cid) + +**Returns** + +It returns a promise that is resolved on the success of the operation. + +`Promise` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-interfaces/src/content-routing/img/badge.png b/packages/interface-content-routing/img/badge.png similarity index 100% rename from packages/libp2p-interfaces/src/content-routing/img/badge.png rename to packages/interface-content-routing/img/badge.png diff --git a/packages/libp2p-interfaces/src/content-routing/img/badge.sketch b/packages/interface-content-routing/img/badge.sketch similarity index 100% rename from packages/libp2p-interfaces/src/content-routing/img/badge.sketch rename to packages/interface-content-routing/img/badge.sketch diff --git a/packages/libp2p-interfaces/src/content-routing/img/badge.svg b/packages/interface-content-routing/img/badge.svg similarity index 100% rename from packages/libp2p-interfaces/src/content-routing/img/badge.svg rename to packages/interface-content-routing/img/badge.svg diff --git a/packages/libp2p-peer-id/package.json b/packages/interface-content-routing/package.json similarity index 81% rename from packages/libp2p-peer-id/package.json rename to packages/interface-content-routing/package.json index 74769de50..38d0b4d70 100644 --- a/packages/libp2p-peer-id/package.json +++ b/packages/interface-content-routing/package.json @@ -1,9 +1,9 @@ { - "name": "@libp2p/peer-id", - "version": "1.1.11", - "description": "IPFS Peer Id implementation in Node.js", + "name": "@libp2p/interface-content-routing", + "version": "0.0.1", + "description": "Content routing interface for libp2p", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-peer-id#readme", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-content-routing#readme", "repository": { "type": "git", "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" @@ -12,7 +12,8 @@ "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" }, "keywords": [ - "IPFS" + "interface", + "libp2p" ], "engines": { "node": ">=16.0.0", @@ -28,6 +29,7 @@ ], "exports": { ".": { + "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" } }, @@ -123,22 +125,14 @@ "lint": "aegir lint", "dep-check": "aegir dep-check", "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", "release": "aegir release" }, "dependencies": { + "@libp2p/interface-peer-info": "~0.0.0", "@libp2p/interfaces": "^2.0.0", - "err-code": "^3.0.1", - "multiformats": "^9.6.3", - "uint8arrays": "^3.0.0" + "multiformats": "^9.6.3" }, "devDependencies": { - "aegir": "^37.0.7" + "aegir": "^37.0.17" } } diff --git a/packages/libp2p-interfaces/src/content-routing/index.ts b/packages/interface-content-routing/src/index.ts similarity index 76% rename from packages/libp2p-interfaces/src/content-routing/index.ts rename to packages/interface-content-routing/src/index.ts index 4b8690767..788c7e95c 100644 --- a/packages/libp2p-interfaces/src/content-routing/index.ts +++ b/packages/interface-content-routing/src/index.ts @@ -1,6 +1,6 @@ import type { CID } from 'multiformats/cid' -import type { AbortOptions } from '../index.js' -import type { PeerInfo } from '../peer-info/index.js' +import type { AbortOptions } from '@libp2p/interfaces' +import type { PeerInfo } from '@libp2p/interface-peer-info' export interface ContentRouting { provide: (cid: CID, options?: AbortOptions) => Promise diff --git a/packages/interface-content-routing/tsconfig.json b/packages/interface-content-routing/tsconfig.json new file mode 100644 index 000000000..84bbd0ffe --- /dev/null +++ b/packages/interface-content-routing/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-info" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/libp2p-peer-record/LICENSE b/packages/interface-dht/LICENSE similarity index 100% rename from packages/libp2p-peer-record/LICENSE rename to packages/interface-dht/LICENSE diff --git a/packages/libp2p-peer-record/LICENSE-APACHE b/packages/interface-dht/LICENSE-APACHE similarity index 100% rename from packages/libp2p-peer-record/LICENSE-APACHE rename to packages/interface-dht/LICENSE-APACHE diff --git a/packages/libp2p-peer-record/LICENSE-MIT b/packages/interface-dht/LICENSE-MIT similarity index 100% rename from packages/libp2p-peer-record/LICENSE-MIT rename to packages/interface-dht/LICENSE-MIT diff --git a/packages/interface-dht/README.md b/packages/interface-dht/README.md new file mode 100644 index 000000000..84a8ea68f --- /dev/null +++ b/packages/interface-dht/README.md @@ -0,0 +1,28 @@ +# @libp2p/interface-dht + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> DHT interface for libp2p + +## Table of contents + +- [Install](#install) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-dht +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-logger/package.json b/packages/interface-dht/package.json similarity index 81% rename from packages/libp2p-logger/package.json rename to packages/interface-dht/package.json index 7c1095c39..9497e16cb 100644 --- a/packages/libp2p-logger/package.json +++ b/packages/interface-dht/package.json @@ -1,9 +1,9 @@ { - "name": "@libp2p/logger", - "version": "1.1.5", - "description": "A logging component for use in js-libp2p components", + "name": "@libp2p/interface-dht", + "version": "0.0.1", + "description": "DHT interface for libp2p", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-logger#readme", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-dht#readme", "repository": { "type": "git", "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" @@ -12,7 +12,8 @@ "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" }, "keywords": [ - "IPFS" + "interface", + "libp2p" ], "engines": { "node": ">=16.0.0", @@ -28,6 +29,7 @@ ], "exports": { ".": { + "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" } }, @@ -123,23 +125,16 @@ "lint": "aegir lint", "dep-check": "aegir dep-check", "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", "release": "aegir release" }, "dependencies": { + "@libp2p/interface-peer-discovery": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/interface-peer-info": "~0.0.0", "@libp2p/interfaces": "^2.0.0", - "debug": "^4.3.3", - "interface-datastore": "^6.1.0", "multiformats": "^9.6.3" }, "devDependencies": { - "@types/debug": "^4.1.7", - "aegir": "^37.0.7" + "aegir": "^37.0.17" } } diff --git a/packages/libp2p-interfaces/src/dht/index.ts b/packages/interface-dht/src/index.ts similarity index 95% rename from packages/libp2p-interfaces/src/dht/index.ts rename to packages/interface-dht/src/index.ts index 8723ac39c..8ac543b8a 100644 --- a/packages/libp2p-interfaces/src/dht/index.ts +++ b/packages/interface-dht/src/index.ts @@ -1,8 +1,8 @@ -import type { PeerId } from '../peer-id/index.js' +import type { PeerId } from '@libp2p/interface-peer-id' import type { CID } from 'multiformats/cid' -import type { PeerInfo } from '../peer-info/index.js' -import type { AbortOptions } from '../index.js' -import type { PeerDiscovery } from '../peer-discovery/index.js' +import type { PeerInfo } from '@libp2p/interface-peer-info' +import type { AbortOptions } from '@libp2p/interfaces' +import type { PeerDiscovery } from '@libp2p/interface-peer-discovery' /** * The types of events emitted during DHT queries diff --git a/packages/interface-dht/tsconfig.json b/packages/interface-dht/tsconfig.json new file mode 100644 index 000000000..29f294568 --- /dev/null +++ b/packages/interface-dht/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-discovery" + }, + { + "path": "../interface-peer-id" + }, + { + "path": "../interface-peer-info" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/libp2p-peer-store/LICENSE b/packages/interface-keychain/LICENSE similarity index 100% rename from packages/libp2p-peer-store/LICENSE rename to packages/interface-keychain/LICENSE diff --git a/packages/libp2p-peer-store/LICENSE-APACHE b/packages/interface-keychain/LICENSE-APACHE similarity index 100% rename from packages/libp2p-peer-store/LICENSE-APACHE rename to packages/interface-keychain/LICENSE-APACHE diff --git a/packages/libp2p-peer-store/LICENSE-MIT b/packages/interface-keychain/LICENSE-MIT similarity index 100% rename from packages/libp2p-peer-store/LICENSE-MIT rename to packages/interface-keychain/LICENSE-MIT diff --git a/packages/libp2p-interfaces/src/content-routing/README.md b/packages/interface-keychain/README.md similarity index 57% rename from packages/libp2p-interfaces/src/content-routing/README.md rename to packages/interface-keychain/README.md index fb2d1bde9..9fd56eaeb 100644 --- a/packages/libp2p-interfaces/src/content-routing/README.md +++ b/packages/interface-keychain/README.md @@ -1,9 +1,27 @@ -interface-content-routing -===================== +# @libp2p/interface-keychain -**WIP: This module is not yet implemented** +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) -> A test suite and interface you can use to implement a Content Routing module for libp2p. +> Keychain interface for libp2p + +## Table of contents + +- - [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [How to use the battery of tests](#how-to-use-the-battery-of-tests) + - [Node.js](#nodejs) +- [API](#api) + - - [findProviders](#findproviders) + - [provide](#provide) + - [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-keychain +``` The primary goal of this module is to enable developers to pick and swap their Content Routing module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. @@ -37,6 +55,7 @@ A valid (read: that follows this abstraction) Content Routing module must implem Find peers in the network that can provide a specific value, given a key. **Parameters** + - [CID](https://github.com/multiformats/js-cid) **Returns** @@ -52,6 +71,7 @@ It returns an `AsyncIterable` containing the identification and addresses of the Announce to the network that we are providing the given value. **Parameters** + - [CID](https://github.com/multiformats/js-cid) **Returns** @@ -59,3 +79,14 @@ Announce to the network that we are providing the given value. It returns a promise that is resolved on the success of the operation. `Promise` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-keychain/package.json b/packages/interface-keychain/package.json new file mode 100644 index 000000000..231b4194e --- /dev/null +++ b/packages/interface-keychain/package.json @@ -0,0 +1,136 @@ +{ + "name": "@libp2p/interface-keychain", + "version": "0.0.1", + "description": "Keychain interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-keychain#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "multiformats": "^9.6.3" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/keychain/index.ts b/packages/interface-keychain/src/index.ts similarity index 100% rename from packages/libp2p-interfaces/src/keychain/index.ts rename to packages/interface-keychain/src/index.ts diff --git a/packages/interface-keychain/tsconfig.json b/packages/interface-keychain/tsconfig.json new file mode 100644 index 000000000..5fe8ea40d --- /dev/null +++ b/packages/interface-keychain/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ] +} diff --git a/packages/libp2p-pubsub/LICENSE b/packages/interface-keys/LICENSE similarity index 100% rename from packages/libp2p-pubsub/LICENSE rename to packages/interface-keys/LICENSE diff --git a/packages/libp2p-pubsub/LICENSE-APACHE b/packages/interface-keys/LICENSE-APACHE similarity index 100% rename from packages/libp2p-pubsub/LICENSE-APACHE rename to packages/interface-keys/LICENSE-APACHE diff --git a/packages/libp2p-pubsub/LICENSE-MIT b/packages/interface-keys/LICENSE-MIT similarity index 100% rename from packages/libp2p-pubsub/LICENSE-MIT rename to packages/interface-keys/LICENSE-MIT diff --git a/packages/interface-keys/README.md b/packages/interface-keys/README.md new file mode 100644 index 000000000..8ab09964d --- /dev/null +++ b/packages/interface-keys/README.md @@ -0,0 +1,48 @@ +# @libp2p/interface-keys + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Keys interface for libp2p + +## Table of contents + +- [Install](#install) +- [Using the Test Suite](#using-the-test-suite) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-keys +``` + +## Using the Test Suite + +You can also check out the [internal test suite](../../test/crypto/compliance.spec.js) to see the setup in action. + +```js +const tests = require('libp2p-interfaces-compliance-tests/keys') +const yourKeys = require('./your-keys') + +tests({ + setup () { + // Set up your keys if needed, then return it + return yourKeys + }, + teardown () { + // Clean up your keys if needed + } +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-keys/package.json b/packages/interface-keys/package.json new file mode 100644 index 000000000..dda5dbae5 --- /dev/null +++ b/packages/interface-keys/package.json @@ -0,0 +1,133 @@ +{ + "name": "@libp2p/interface-keys", + "version": "0.0.1", + "description": "Keys interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-keys#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/keys/index.ts b/packages/interface-keys/src/index.ts similarity index 100% rename from packages/libp2p-interfaces/src/keys/index.ts rename to packages/interface-keys/src/index.ts diff --git a/packages/interface-keys/tsconfig.json b/packages/interface-keys/tsconfig.json new file mode 100644 index 000000000..5fe8ea40d --- /dev/null +++ b/packages/interface-keys/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ] +} diff --git a/packages/libp2p-topology/LICENSE b/packages/interface-metrics/LICENSE similarity index 100% rename from packages/libp2p-topology/LICENSE rename to packages/interface-metrics/LICENSE diff --git a/packages/libp2p-topology/LICENSE-APACHE b/packages/interface-metrics/LICENSE-APACHE similarity index 100% rename from packages/libp2p-topology/LICENSE-APACHE rename to packages/interface-metrics/LICENSE-APACHE diff --git a/packages/libp2p-topology/LICENSE-MIT b/packages/interface-metrics/LICENSE-MIT similarity index 100% rename from packages/libp2p-topology/LICENSE-MIT rename to packages/interface-metrics/LICENSE-MIT diff --git a/packages/interface-metrics/README.md b/packages/interface-metrics/README.md new file mode 100644 index 000000000..d743efea5 --- /dev/null +++ b/packages/interface-metrics/README.md @@ -0,0 +1,48 @@ +# @libp2p/interface-metrics + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Metrics interface for libp2p + +## Table of contents + +- [Install](#install) +- [Using the Test Suite](#using-the-test-suite) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-metrics +``` + +## Using the Test Suite + +You can also check out the [internal test suite](../../test/crypto/compliance.spec.js) to see the setup in action. + +```js +const tests = require('libp2p-interfaces-compliance-tests/keys') +const yourKeys = require('./your-keys') + +tests({ + setup () { + // Set up your keys if needed, then return it + return yourKeys + }, + teardown () { + // Clean up your keys if needed + } +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-metrics/package.json b/packages/interface-metrics/package.json new file mode 100644 index 000000000..d331c311b --- /dev/null +++ b/packages/interface-metrics/package.json @@ -0,0 +1,137 @@ +{ + "name": "@libp2p/interface-metrics", + "version": "0.0.1", + "description": "Metrics interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-metrics#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0", + "it-stream-types": "^1.0.4" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/metrics/index.ts b/packages/interface-metrics/src/index.ts similarity index 98% rename from packages/libp2p-interfaces/src/metrics/index.ts rename to packages/interface-metrics/src/index.ts index e5ac7eec1..ba6ad1b59 100644 --- a/packages/libp2p-interfaces/src/metrics/index.ts +++ b/packages/interface-metrics/src/index.ts @@ -1,4 +1,4 @@ -import type { PeerId } from '../peer-id' +import type { PeerId } from '@libp2p/interface-peer-id' import type { Duplex } from 'it-stream-types' export interface MetricsInit { diff --git a/packages/interface-metrics/tsconfig.json b/packages/interface-metrics/tsconfig.json new file mode 100644 index 000000000..d8db0b667 --- /dev/null +++ b/packages/interface-metrics/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-id" + } + ] +} diff --git a/packages/interface-mocks/CHANGELOG.md b/packages/interface-mocks/CHANGELOG.md new file mode 100644 index 000000000..50c187554 --- /dev/null +++ b/packages/interface-mocks/CHANGELOG.md @@ -0,0 +1,460 @@ +## [@libp2p/interface-compliance-tests-v2.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v2.0.2...@libp2p/interface-compliance-tests-v2.0.3) (2022-05-24) + + +### Bug Fixes + +* only close muxed stream for reading ([#220](https://github.com/libp2p/js-libp2p-interfaces/issues/220)) ([f2f7141](https://github.com/libp2p/js-libp2p-interfaces/commit/f2f7141f01af715e600201ac9e7e52fbbb5c7e1b)) + +## [@libp2p/interface-compliance-tests-v2.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v2.0.1...@libp2p/interface-compliance-tests-v2.0.2) (2022-05-24) + + +### Bug Fixes + +* accept abort options in connection.newStream ([#219](https://github.com/libp2p/js-libp2p-interfaces/issues/219)) ([8bfcbc9](https://github.com/libp2p/js-libp2p-interfaces/commit/8bfcbc9ee883336f213cdfc83e477549ca368df5)) +* chunk data in mock muxer ([#218](https://github.com/libp2p/js-libp2p-interfaces/issues/218)) ([14604f6](https://github.com/libp2p/js-libp2p-interfaces/commit/14604f69a858bf8c16ce118420c5e49f3f5331ea)) + +## [@libp2p/interface-compliance-tests-v2.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v2.0.0...@libp2p/interface-compliance-tests-v2.0.1) (2022-05-23) + + +### Bug Fixes + +* make stream return types synchronous ([#217](https://github.com/libp2p/js-libp2p-interfaces/issues/217)) ([2fe61b7](https://github.com/libp2p/js-libp2p-interfaces/commit/2fe61b7fbeda2e549edf095a927d623aa8eb476b)) + +## [@libp2p/interface-compliance-tests-v2.0.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.34...@libp2p/interface-compliance-tests-v2.0.0) (2022-05-20) + + +### ⚠ BREAKING CHANGES + +* This adds closeWrite and closeRead checks in the tests, which will cause test failures for muxers that don't implement those + +### Bug Fixes + +* close streams when connection is closed ([#214](https://github.com/libp2p/js-libp2p-interfaces/issues/214)) ([88fcd58](https://github.com/libp2p/js-libp2p-interfaces/commit/88fcd586276e03dd740c7095f05e21754ac1f3b5)), closes [#90](https://github.com/libp2p/js-libp2p-interfaces/issues/90) +* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) + +## [@libp2p/interface-compliance-tests-v1.1.34](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.33...@libp2p/interface-compliance-tests-v1.1.34) (2022-05-10) + + +### Trivial Changes + +* **deps:** bump sinon from 13.0.2 to 14.0.0 ([#211](https://github.com/libp2p/js-libp2p-interfaces/issues/211)) ([8859f70](https://github.com/libp2p/js-libp2p-interfaces/commit/8859f70943c0bcdb210f54a338ae901739e5e6f2)) + +## [@libp2p/interface-compliance-tests-v1.1.33](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.32...@libp2p/interface-compliance-tests-v1.1.33) (2022-05-06) + + +### Bug Fixes + +* add tag to peer discovery interface ([#210](https://github.com/libp2p/js-libp2p-interfaces/issues/210)) ([f99c833](https://github.com/libp2p/js-libp2p-interfaces/commit/f99c833c8436f8434f380d890ec5d267279312d7)) + +## [@libp2p/interface-compliance-tests-v1.1.32](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.31...@libp2p/interface-compliance-tests-v1.1.32) (2022-05-04) + + +### Bug Fixes + +* move startable and events interfaces ([#209](https://github.com/libp2p/js-libp2p-interfaces/issues/209)) ([8ce8a08](https://github.com/libp2p/js-libp2p-interfaces/commit/8ce8a08c94b0738aa32da516558977b195ddd8ed)) + +## [@libp2p/interface-compliance-tests-v1.1.31](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.30...@libp2p/interface-compliance-tests-v1.1.31) (2022-05-03) + + +### Bug Fixes + +* only send handled protocols ([#207](https://github.com/libp2p/js-libp2p-interfaces/issues/207)) ([1f7afc2](https://github.com/libp2p/js-libp2p-interfaces/commit/1f7afc29d72fde708064ec6479011dbc0a225962)) + +## [@libp2p/interface-compliance-tests-v1.1.30](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.29...@libp2p/interface-compliance-tests-v1.1.30) (2022-05-01) + + +### Bug Fixes + +* move connection manager mock to connection manager module ([#205](https://github.com/libp2p/js-libp2p-interfaces/issues/205)) ([a367375](https://github.com/libp2p/js-libp2p-interfaces/commit/a367375accc690d7b4608c9a3313f91df700efd8)) + +## [@libp2p/interface-compliance-tests-v1.1.29](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.28...@libp2p/interface-compliance-tests-v1.1.29) (2022-04-28) + + +### Bug Fixes + +* pubsub should not be startable ([#204](https://github.com/libp2p/js-libp2p-interfaces/issues/204)) ([59bd924](https://github.com/libp2p/js-libp2p-interfaces/commit/59bd9245a207268525bdd26a05c5306fe436fcc4)) + +## [@libp2p/interface-compliance-tests-v1.1.28](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.27...@libp2p/interface-compliance-tests-v1.1.28) (2022-04-28) + + +### Bug Fixes + +* pubsub and dht are always set ([#203](https://github.com/libp2p/js-libp2p-interfaces/issues/203)) ([86860c1](https://github.com/libp2p/js-libp2p-interfaces/commit/86860c1836a2464b2ad380b09542e3f3271ae287)) + +## [@libp2p/interface-compliance-tests-v1.1.27](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.26...@libp2p/interface-compliance-tests-v1.1.27) (2022-04-26) + + +### Bug Fixes + +* add delays for gossipsub ([#202](https://github.com/libp2p/js-libp2p-interfaces/issues/202)) ([cf85799](https://github.com/libp2p/js-libp2p-interfaces/commit/cf85799fdd0d4848ad2187bbbb0dd6ac5e8cb254)) + +## [@libp2p/interface-compliance-tests-v1.1.26](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.25...@libp2p/interface-compliance-tests-v1.1.26) (2022-04-25) + + +### Bug Fixes + +* stop pubsub after test ([#200](https://github.com/libp2p/js-libp2p-interfaces/issues/200)) ([2d2650c](https://github.com/libp2p/js-libp2p-interfaces/commit/2d2650cb8cabce137665aafd55a2fb14cbd5dacd)) + +## [@libp2p/interface-compliance-tests-v1.1.25](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.24...@libp2p/interface-compliance-tests-v1.1.25) (2022-04-22) + + +### Bug Fixes + +* update pubsub interface in line with gossipsub ([#199](https://github.com/libp2p/js-libp2p-interfaces/issues/199)) ([3f55596](https://github.com/libp2p/js-libp2p-interfaces/commit/3f555965cddea3ef03e7217b755c82aa4107e093)) + +## [@libp2p/interface-compliance-tests-v1.1.24](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.23...@libp2p/interface-compliance-tests-v1.1.24) (2022-04-21) + + +### Bug Fixes + +* test PubSub interface and not PubSubBaseProtocol ([#198](https://github.com/libp2p/js-libp2p-interfaces/issues/198)) ([96c15c9](https://github.com/libp2p/js-libp2p-interfaces/commit/96c15c9780821a3cb763e48854d64377bf562692)) + +## [@libp2p/interface-compliance-tests-v1.1.23](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.22...@libp2p/interface-compliance-tests-v1.1.23) (2022-04-20) + + +### Bug Fixes + +* emit pubsub messages using 'message' event ([#197](https://github.com/libp2p/js-libp2p-interfaces/issues/197)) ([df9b685](https://github.com/libp2p/js-libp2p-interfaces/commit/df9b685cea30653109f2fa2cb5583a3bca7b09bb)) + +## [@libp2p/interface-compliance-tests-v1.1.22](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.21...@libp2p/interface-compliance-tests-v1.1.22) (2022-04-19) + + +### Bug Fixes + +* move dev deps to prod ([#195](https://github.com/libp2p/js-libp2p-interfaces/issues/195)) ([3e1ffc7](https://github.com/libp2p/js-libp2p-interfaces/commit/3e1ffc7b174e74be483943ad4e5fcab823ae3f6d)) + +## [@libp2p/interface-compliance-tests-v1.1.21](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.20...@libp2p/interface-compliance-tests-v1.1.21) (2022-04-08) + + +### Bug Fixes + +* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) + + +### Trivial Changes + +* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) + +## [@libp2p/interface-compliance-tests-v1.1.20](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.19...@libp2p/interface-compliance-tests-v1.1.20) (2022-03-24) + + +### Bug Fixes + +* rename peer data to peer info ([#187](https://github.com/libp2p/js-libp2p-interfaces/issues/187)) ([dfea342](https://github.com/libp2p/js-libp2p-interfaces/commit/dfea3429bad57abde040397e4e7a58539829e9c2)) + +## [@libp2p/interface-compliance-tests-v1.1.19](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.18...@libp2p/interface-compliance-tests-v1.1.19) (2022-03-22) + + +### Bug Fixes + +* add method for startable lifecyle ([#186](https://github.com/libp2p/js-libp2p-interfaces/issues/186)) ([2730e29](https://github.com/libp2p/js-libp2p-interfaces/commit/2730e2947bbd231db3f7f82951b51ee534733ab2)) + +## [@libp2p/interface-compliance-tests-v1.1.18](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.17...@libp2p/interface-compliance-tests-v1.1.18) (2022-03-20) + + +### Bug Fixes + +* update pubsub types ([#183](https://github.com/libp2p/js-libp2p-interfaces/issues/183)) ([7ef4baa](https://github.com/libp2p/js-libp2p-interfaces/commit/7ef4baad0fe30f783f3eecd5199ef92af08b7f57)) + +## [@libp2p/interface-compliance-tests-v1.1.17](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.16...@libp2p/interface-compliance-tests-v1.1.17) (2022-03-15) + + +### Bug Fixes + +* use custom event instead of error event ([#181](https://github.com/libp2p/js-libp2p-interfaces/issues/181)) ([71ab242](https://github.com/libp2p/js-libp2p-interfaces/commit/71ab2424dfbf6337111d6d9d994f27c7967c20f1)) + +## [@libp2p/interface-compliance-tests-v1.1.16](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.15...@libp2p/interface-compliance-tests-v1.1.16) (2022-03-15) + + +### Bug Fixes + +* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) + +## [@libp2p/interface-compliance-tests-v1.1.15](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.14...@libp2p/interface-compliance-tests-v1.1.15) (2022-02-27) + + +### Bug Fixes + +* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) + +## [@libp2p/interface-compliance-tests-v1.1.14](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.13...@libp2p/interface-compliance-tests-v1.1.14) (2022-02-27) + + +### Bug Fixes + +* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) + +## [@libp2p/interface-compliance-tests-v1.1.13](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.12...@libp2p/interface-compliance-tests-v1.1.13) (2022-02-21) + + +### Bug Fixes + +* increase stream test timeout ([#175](https://github.com/libp2p/js-libp2p-interfaces/issues/175)) ([568aefb](https://github.com/libp2p/js-libp2p-interfaces/commit/568aefb5c099ba0161ffecf86bda238b92d396b0)) + +## [@libp2p/interface-compliance-tests-v1.1.12](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.11...@libp2p/interface-compliance-tests-v1.1.12) (2022-02-21) + + +### Bug Fixes + +* update muxer to pass transport tests ([#174](https://github.com/libp2p/js-libp2p-interfaces/issues/174)) ([466ed53](https://github.com/libp2p/js-libp2p-interfaces/commit/466ed53192aa196ac2dbdb83df3c8db9cd5b1e07)) + +## [@libp2p/interface-compliance-tests-v1.1.11](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.10...@libp2p/interface-compliance-tests-v1.1.11) (2022-02-18) + + +### Bug Fixes + +* remove delays from pubsub tests ([#173](https://github.com/libp2p/js-libp2p-interfaces/issues/173)) ([5c8fe09](https://github.com/libp2p/js-libp2p-interfaces/commit/5c8fe09294f0cbd8add1406a61fa7dbc5b4e788b)) + +## [@libp2p/interface-compliance-tests-v1.1.10](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.9...@libp2p/interface-compliance-tests-v1.1.10) (2022-02-18) + + +### Bug Fixes + +* simpler pubsub ([#172](https://github.com/libp2p/js-libp2p-interfaces/issues/172)) ([98715ed](https://github.com/libp2p/js-libp2p-interfaces/commit/98715ed73183b32e4fda3d878a462389548358d9)) + +## [@libp2p/interface-compliance-tests-v1.1.9](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.8...@libp2p/interface-compliance-tests-v1.1.9) (2022-02-17) + + +### Bug Fixes + +* update deps ([#171](https://github.com/libp2p/js-libp2p-interfaces/issues/171)) ([d0d2564](https://github.com/libp2p/js-libp2p-interfaces/commit/d0d2564a84a0722ab587a3aa6ec01e222442b100)) + +## [@libp2p/interface-compliance-tests-v1.1.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.7...@libp2p/interface-compliance-tests-v1.1.8) (2022-02-17) + + +### Bug Fixes + +* add multistream-select and update pubsub types ([#170](https://github.com/libp2p/js-libp2p-interfaces/issues/170)) ([b9ecb2b](https://github.com/libp2p/js-libp2p-interfaces/commit/b9ecb2bee8f2abc0c41bfcf7bf2025894e37ddc2)) + +## [@libp2p/interface-compliance-tests-v1.1.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.6...@libp2p/interface-compliance-tests-v1.1.7) (2022-02-16) + + +### Bug Fixes + +* test muxer ([#169](https://github.com/libp2p/js-libp2p-interfaces/issues/169)) ([574723d](https://github.com/libp2p/js-libp2p-interfaces/commit/574723d11007e875e7adfa5c32819445f9b8def7)) + +## [@libp2p/interface-compliance-tests-v1.1.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.5...@libp2p/interface-compliance-tests-v1.1.6) (2022-02-12) + + +### Bug Fixes + +* return registered topologies in mock ([#168](https://github.com/libp2p/js-libp2p-interfaces/issues/168)) ([1583019](https://github.com/libp2p/js-libp2p-interfaces/commit/158301982384a694ac3fb8f9df67c71b7b776b47)) + +## [@libp2p/interface-compliance-tests-v1.1.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.4...@libp2p/interface-compliance-tests-v1.1.5) (2022-02-12) + + +### Bug Fixes + +* hide implementations behind factory methods ([#167](https://github.com/libp2p/js-libp2p-interfaces/issues/167)) ([2fba080](https://github.com/libp2p/js-libp2p-interfaces/commit/2fba0800c9896af6dcc49da4fa904bb4a3e3e40d)) + +## [@libp2p/interface-compliance-tests-v1.1.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.3...@libp2p/interface-compliance-tests-v1.1.4) (2022-02-11) + + +### Bug Fixes + +* simpler topologies ([#164](https://github.com/libp2p/js-libp2p-interfaces/issues/164)) ([45fcaa1](https://github.com/libp2p/js-libp2p-interfaces/commit/45fcaa10a6a3215089340ff2eff117d7fd1100e7)) + +## [@libp2p/interface-compliance-tests-v1.1.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.2...@libp2p/interface-compliance-tests-v1.1.3) (2022-02-10) + + +### Bug Fixes + +* make registrar simpler ([#163](https://github.com/libp2p/js-libp2p-interfaces/issues/163)) ([d122f3d](https://github.com/libp2p/js-libp2p-interfaces/commit/d122f3daaccc04039d90814960da92b513265644)) + +## [@libp2p/interface-compliance-tests-v1.1.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.1...@libp2p/interface-compliance-tests-v1.1.2) (2022-02-10) + + +### Bug Fixes + +* remove args from listener events ([#162](https://github.com/libp2p/js-libp2p-interfaces/issues/162)) ([011ac89](https://github.com/libp2p/js-libp2p-interfaces/commit/011ac891ec7d44625cb4342f068bcd9f241a5b45)) + +## [@libp2p/interface-compliance-tests-v1.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.1.0...@libp2p/interface-compliance-tests-v1.1.1) (2022-02-10) + + +### Bug Fixes + +* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) + +## [@libp2p/interface-compliance-tests-v1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.8...@libp2p/interface-compliance-tests-v1.1.0) (2022-02-09) + + +### Features + +* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) + +## [@libp2p/interface-compliance-tests-v1.0.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.7...@libp2p/interface-compliance-tests-v1.0.8) (2022-02-05) + + +### Bug Fixes + +* fix muxer tests ([#157](https://github.com/libp2p/js-libp2p-interfaces/issues/157)) ([7233c44](https://github.com/libp2p/js-libp2p-interfaces/commit/7233c4438479dff56a682f45209ef7a938d63857)) + +## [@libp2p/interface-compliance-tests-v1.0.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.6...@libp2p/interface-compliance-tests-v1.0.7) (2022-01-31) + + +### Trivial Changes + +* **deps:** bump sinon from 12.0.1 to 13.0.0 ([#154](https://github.com/libp2p/js-libp2p-interfaces/issues/154)) ([3fc8812](https://github.com/libp2p/js-libp2p-interfaces/commit/3fc8812897fa197e7b62f77614abaea4a5563404)) + +## [@libp2p/interface-compliance-tests-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.5...@libp2p/interface-compliance-tests-v1.0.6) (2022-01-29) + + +### Bug Fixes + +* remove extra fields ([#153](https://github.com/libp2p/js-libp2p-interfaces/issues/153)) ([ccd7cf3](https://github.com/libp2p/js-libp2p-interfaces/commit/ccd7cf3f5ac71337baf516d3b0f6fc724ee0d3b4)) + +## [@libp2p/interface-compliance-tests-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.4...@libp2p/interface-compliance-tests-v1.0.5) (2022-01-15) + + +### Bug Fixes + +* remove abort controller dep ([#151](https://github.com/libp2p/js-libp2p-interfaces/issues/151)) ([518bce1](https://github.com/libp2p/js-libp2p-interfaces/commit/518bce1f9bd1f8b2922338e0c65c9934af7da3af)) + +## [@libp2p/interface-compliance-tests-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.3...@libp2p/interface-compliance-tests-v1.0.4) (2022-01-15) + + +### Trivial Changes + +* update project config ([#149](https://github.com/libp2p/js-libp2p-interfaces/issues/149)) ([6eb8556](https://github.com/libp2p/js-libp2p-interfaces/commit/6eb85562c0da167d222808da10a7914daf12970b)) + +## [@libp2p/interface-compliance-tests-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.2...@libp2p/interface-compliance-tests-v1.0.3) (2022-01-14) + + +### Bug Fixes + +* update it-* deps to ts versions ([#148](https://github.com/libp2p/js-libp2p-interfaces/issues/148)) ([7a6fdd7](https://github.com/libp2p/js-libp2p-interfaces/commit/7a6fdd7622ce2870b89dbb849ab421d0dd714b43)) + +## [@libp2p/interface-compliance-tests-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/interface-compliance-tests-v1.0.1...@libp2p/interface-compliance-tests-v1.0.2) (2022-01-08) + + +### Trivial Changes + +* add semantic release config ([#141](https://github.com/libp2p/js-libp2p-interfaces/issues/141)) ([5f0de59](https://github.com/libp2p/js-libp2p-interfaces/commit/5f0de59136b6343d2411abb2d6a4dd2cd0b7efe4)) +* update package versions ([#140](https://github.com/libp2p/js-libp2p-interfaces/issues/140)) ([cd844f6](https://github.com/libp2p/js-libp2p-interfaces/commit/cd844f6e39f4ee50d006e86eac8dadf696900eb5)) + +# Change Log + +All notable changes to this project will be documented in this file. +See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. + +# 0.2.0 (2022-01-04) + + +### Features + +* add auto-publish ([7aede5d](https://github.com/libp2p/js-libp2p-interfaces/commit/7aede5df39ea6b5f243348ec9a212b3e33c16a81)) +* update package names ([#133](https://github.com/libp2p/js-libp2p-interfaces/issues/133)) ([337adc9](https://github.com/libp2p/js-libp2p-interfaces/commit/337adc9a9bc0278bdae8cbce9c57d07a83c8b5c2)) + + + + + +## [3.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@3.1.0...libp2p-interfaces-compliance-tests@3.1.1) (2022-01-02) + + +### Bug Fixes + +* move errors ([#132](https://github.com/libp2p/js-libp2p-interfaces/issues/132)) ([21d282a](https://github.com/libp2p/js-libp2p-interfaces/commit/21d282a6d77bd7d1a12daa1cc8b3a3fed8635dad)) + + + + + +# [3.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@3.0.0...libp2p-interfaces-compliance-tests@3.1.0) (2022-01-02) + + +### Bug Fixes + +* update dialer tests ([#116](https://github.com/libp2p/js-libp2p-interfaces/issues/116)) ([c679729](https://github.com/libp2p/js-libp2p-interfaces/commit/c679729113feb963ff27815fcafd7af51f722df7)) + + +### Features + +* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) + + + + + +# [3.0.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@2.0.0...libp2p-interfaces-compliance-tests@3.0.0) (2021-12-02) + + +### chore + +* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) + + +### BREAKING CHANGES + +* requires node 15+ + + + + + +# [2.0.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@1.1.2...libp2p-interfaces-compliance-tests@2.0.0) (2021-11-22) + + +### Features + +* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) + + +### BREAKING CHANGES + +* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out + + + + + +## [1.1.2](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@1.1.1...libp2p-interfaces-compliance-tests@1.1.2) (2021-10-18) + +**Note:** Version bump only for package libp2p-interfaces-compliance-tests + + + + + +## [1.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@1.1.0...libp2p-interfaces-compliance-tests@1.1.1) (2021-09-20) + +**Note:** Version bump only for package libp2p-interfaces-compliance-tests + + + + + +# [1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@1.0.1...libp2p-interfaces-compliance-tests@1.1.0) (2021-08-20) + + +### Features + +* update uint8arrays ([#105](https://github.com/libp2p/js-libp2p-interfaces/issues/105)) ([9297a9c](https://github.com/libp2p/js-libp2p-interfaces/commit/9297a9c379276d03c8da849af6108b38e581b4a6)) + + + + + +## [1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-interfaces-compliance-tests@1.0.0...libp2p-interfaces-compliance-tests@1.0.1) (2021-07-08) + + +### Bug Fixes + +* make tests more reliable ([#103](https://github.com/libp2p/js-libp2p-interfaces/issues/103)) ([cd4c409](https://github.com/libp2p/js-libp2p-interfaces/commit/cd4c40908efe2e9ffc14aa61aace5176a43fd70a)) +* remove timeouts ([#104](https://github.com/libp2p/js-libp2p-interfaces/issues/104)) ([3699c17](https://github.com/libp2p/js-libp2p-interfaces/commit/3699c17f022da40a87ab24adc3b2081df7a0ddcd)) + + + + + +# 1.0.0 (2021-07-07) + + +### chore + +* monorepo separating interfaces and compliance tests ([#97](https://github.com/libp2p/js-libp2p-interfaces/issues/97)) ([946348f](https://github.com/libp2p/js-libp2p-interfaces/commit/946348f7f8acc1ff7bc9cd0ab4c2602d41106f76)) + + +### BREAKING CHANGES + +* the tests now live in the libp2p-interfaces-compliance-tests module diff --git a/packages/libp2p-tracked-map/LICENSE b/packages/interface-mocks/LICENSE similarity index 100% rename from packages/libp2p-tracked-map/LICENSE rename to packages/interface-mocks/LICENSE diff --git a/packages/libp2p-tracked-map/LICENSE-APACHE b/packages/interface-mocks/LICENSE-APACHE similarity index 100% rename from packages/libp2p-tracked-map/LICENSE-APACHE rename to packages/interface-mocks/LICENSE-APACHE diff --git a/packages/libp2p-tracked-map/LICENSE-MIT b/packages/interface-mocks/LICENSE-MIT similarity index 100% rename from packages/libp2p-tracked-map/LICENSE-MIT rename to packages/interface-mocks/LICENSE-MIT diff --git a/packages/interface-mocks/README.md b/packages/interface-mocks/README.md new file mode 100644 index 000000000..1718e1e66 --- /dev/null +++ b/packages/interface-mocks/README.md @@ -0,0 +1,33 @@ +# @libp2p/interface-mocks + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Mock implementations of several libp2p interfaces + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-mocks +``` + +## Usage + +Each [interface](../interfaces) has its documentation on how to use the compliance tests and should be used as the source of truth. + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-multistream-select/package.json b/packages/interface-mocks/package.json similarity index 73% rename from packages/libp2p-multistream-select/package.json rename to packages/interface-mocks/package.json index 4c4d0b27e..5a4b1c974 100644 --- a/packages/libp2p-multistream-select/package.json +++ b/packages/interface-mocks/package.json @@ -1,9 +1,9 @@ { - "name": "@libp2p/multistream-select", - "version": "1.0.6", - "description": "JavaScript implementation of multistream-select", + "name": "@libp2p/interface-mocks", + "version": "0.0.1", + "description": "Mock implementations of several libp2p interfaces", "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-multistream-select#readme", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-mocks#readme", "repository": { "type": "git", "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" @@ -12,11 +12,8 @@ "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" }, "keywords": [ - "ipfs", - "libp2p", - "multistream", - "protocol", - "stream" + "interface", + "libp2p" ], "engines": { "node": ">=16.0.0", @@ -32,6 +29,7 @@ ], "exports": { ".": { + "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js" } }, @@ -137,30 +135,39 @@ "release": "aegir release" }, "dependencies": { + "@libp2p/components": "~0.0.0", + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-connection-encrypter": "~0.0.0", + "@libp2p/interface-connection-manager": "~0.0.0", + "@libp2p/interface-peer-discovery": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/interface-peer-info": "~0.0.0", + "@libp2p/interface-registrar": "~0.0.0", + "@libp2p/interface-stream-muxer": "~0.0.0", + "@libp2p/interface-transport": "~0.0.0", "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", + "@libp2p/logger": "^1.1.6", + "@libp2p/multistream-select": "^1.0.6", + "@libp2p/peer-id": "^1.1.12", + "@libp2p/peer-id-factory": "^1.0.12", + "@multiformats/multiaddr": "^10.2.0", "abortable-iterator": "^4.0.2", + "any-signal": "^3.0.1", "err-code": "^3.0.1", - "it-first": "^1.0.6", "it-handshake": "^3.0.1", - "it-length-prefixed": "^7.0.1", + "it-map": "^1.0.6", + "it-ndjson": "^0.1.1", + "it-pair": "^2.0.2", "it-pipe": "^2.0.3", - "it-pushable": "^2.0.1", - "it-reader": "^5.0.0", + "it-pushable": "^2.0.2", "it-stream-types": "^1.0.4", - "p-defer": "^4.0.0", "uint8arraylist": "^1.5.1", "uint8arrays": "^3.0.0" }, "devDependencies": { - "aegir": "^37.0.7", - "iso-random-stream": "^2.0.2", - "it-all": "^1.0.6", - "it-map": "^1.0.6", - "it-pair": "^2.0.2", - "p-timeout": "^5.0.2", - "timeout-abort-controller": "^3.0.0", - "util": "^0.12.4", - "varint": "^6.0.0" + "@libp2p/interface-connection-encrypter-compliance-tests": "~0.0.0", + "@libp2p/interface-peer-discovery-compliance-tests": "~0.0.0", + "@libp2p/interface-stream-muxer-compliance-tests": "~0.0.0", + "aegir": "^37.0.17" } } diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/connection-encrypter.ts b/packages/interface-mocks/src/connection-encrypter.ts similarity index 95% rename from packages/libp2p-interface-compliance-tests/src/mocks/connection-encrypter.ts rename to packages/interface-mocks/src/connection-encrypter.ts index 85cf70b13..96e58f90f 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/connection-encrypter.ts +++ b/packages/interface-mocks/src/connection-encrypter.ts @@ -2,9 +2,9 @@ import { peerIdFromBytes } from '@libp2p/peer-id' import { handshake } from 'it-handshake' import { duplexPair } from 'it-pair/duplex' import { pipe } from 'it-pipe' -import { UnexpectedPeerError } from '@libp2p/interfaces/connection-encrypter/errors' +import { UnexpectedPeerError } from '@libp2p/interface-connection-encrypter/errors' import { Multiaddr } from '@multiformats/multiaddr' -import type { ConnectionEncrypter } from '@libp2p/interfaces/connection-encrypter' +import type { ConnectionEncrypter } from '@libp2p/interface-connection-encrypter' import type { Transform, Source } from 'it-stream-types' // A basic transform that does nothing to the data diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/connection-gater.ts b/packages/interface-mocks/src/connection-gater.ts similarity index 100% rename from packages/libp2p-interface-compliance-tests/src/mocks/connection-gater.ts rename to packages/interface-mocks/src/connection-gater.ts diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/connection-manager.ts b/packages/interface-mocks/src/connection-manager.ts similarity index 93% rename from packages/libp2p-interface-compliance-tests/src/mocks/connection-manager.ts rename to packages/interface-mocks/src/connection-manager.ts index 22e7356f5..025f44f29 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/connection-manager.ts +++ b/packages/interface-mocks/src/connection-manager.ts @@ -1,9 +1,9 @@ import { CustomEvent, EventEmitter } from '@libp2p/interfaces/events' import type { Startable } from '@libp2p/interfaces/startable' -import type { Connection } from '@libp2p/interfaces/connection' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { ConnectionManager, ConnectionManagerEvents } from '@libp2p/interfaces/connection-manager' -import type { Components, Initializable } from '@libp2p/interfaces/src/components' +import type { Connection } from '@libp2p/interface-connection' +import type { PeerId } from '@libp2p/interface-peer-id' +import type { ConnectionManager, ConnectionManagerEvents } from '@libp2p/interface-connection-manager' +import type { Components, Initializable } from '@libp2p/components' import { connectionPair } from './connection.js' import errCode from 'err-code' diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/connection.ts b/packages/interface-mocks/src/connection.ts similarity index 90% rename from packages/libp2p-interface-compliance-tests/src/mocks/connection.ts rename to packages/interface-mocks/src/connection.ts index 4e482b972..b041f2323 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/connection.ts +++ b/packages/interface-mocks/src/connection.ts @@ -1,20 +1,19 @@ import { peerIdFromString } from '@libp2p/peer-id' import { pipe } from 'it-pipe' import { duplexPair } from 'it-pair/duplex' -import type { MultiaddrConnection } from '@libp2p/interfaces/transport' -import type { Connection, Stream, Metadata, ProtocolStream, ConnectionStat } from '@libp2p/interfaces/connection' +import type { MultiaddrConnection, Connection, Stream, Metadata, ProtocolStream, ConnectionStat } from '@libp2p/interface-connection' import type { Duplex } from 'it-stream-types' import { mockMuxer } from './muxer.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' +import type { PeerId } from '@libp2p/interface-peer-id' import { mockMultiaddrConnection } from './multiaddr-connection.js' -import type { Registrar } from '@libp2p/interfaces/registrar' +import type { Registrar } from '@libp2p/interface-registrar' import { mockRegistrar } from './registrar.js' import { Dialer, Listener } from '@libp2p/multistream-select' import { logger } from '@libp2p/logger' -import * as STATUS from '@libp2p/interfaces/connection/status' +import * as STATUS from '@libp2p/interface-connection/status' import type { Multiaddr } from '@multiformats/multiaddr' -import type { StreamMuxer } from '@libp2p/interfaces/stream-muxer' -import { Components } from '@libp2p/interfaces/components' +import type { StreamMuxer } from '@libp2p/interface-stream-muxer' +import { Components } from '@libp2p/components' import type { AbortOptions } from '@libp2p/interfaces' const log = logger('libp2p:mock-connection') @@ -137,7 +136,7 @@ export function mockConnection (maConn: MultiaddrConnection, opts: MockConnectio muxedStream = { ...muxedStream, ...stream } connection.addStream(muxedStream, { protocol, metadata: {} }) - const handler = registrar.getHandler(protocol) + const { handler } = registrar.getHandler(protocol) handler({ connection, stream: muxedStream, protocol }) }).catch(err => { diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/duplex.ts b/packages/interface-mocks/src/duplex.ts similarity index 100% rename from packages/libp2p-interface-compliance-tests/src/mocks/duplex.ts rename to packages/interface-mocks/src/duplex.ts diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/index.ts b/packages/interface-mocks/src/index.ts similarity index 88% rename from packages/libp2p-interface-compliance-tests/src/mocks/index.ts rename to packages/interface-mocks/src/index.ts index 87771e098..6e7d2f712 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/index.ts +++ b/packages/interface-mocks/src/index.ts @@ -1,4 +1,4 @@ - +export { mockConnectionEncrypter } from './connection-encrypter.js' export { mockConnectionGater } from './connection-gater.js' export { mockConnectionManager, mockNetwork } from './connection-manager.js' export { mockConnection, mockStream, connectionPair } from './connection.js' diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/multiaddr-connection.ts b/packages/interface-mocks/src/multiaddr-connection.ts similarity index 93% rename from packages/libp2p-interface-compliance-tests/src/mocks/multiaddr-connection.ts rename to packages/interface-mocks/src/multiaddr-connection.ts index 73257376b..c842f1663 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/multiaddr-connection.ts +++ b/packages/interface-mocks/src/multiaddr-connection.ts @@ -1,9 +1,9 @@ import { Multiaddr } from '@multiformats/multiaddr' import { duplexPair } from 'it-pair/duplex' import { abortableSource } from 'abortable-iterator' -import type { MultiaddrConnection } from '@libp2p/interfaces/transport' +import type { MultiaddrConnection } from '@libp2p/interface-connection' import type { Duplex } from 'it-stream-types' -import type { PeerId } from '@libp2p/interfaces/peer-id' +import type { PeerId } from '@libp2p/interface-peer-id' export function mockMultiaddrConnection (source: Duplex & Partial, peerId: PeerId): MultiaddrConnection { const maConn: MultiaddrConnection = { diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/muxer.ts b/packages/interface-mocks/src/muxer.ts similarity index 98% rename from packages/libp2p-interface-compliance-tests/src/mocks/muxer.ts rename to packages/interface-mocks/src/muxer.ts index bfc12c8fc..8a6180098 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/muxer.ts +++ b/packages/interface-mocks/src/muxer.ts @@ -6,12 +6,12 @@ import { anySignal } from 'any-signal' import errCode from 'err-code' import { Logger, logger } from '@libp2p/logger' import * as ndjson from 'it-ndjson' -import type { Stream } from '@libp2p/interfaces/connection' -import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer' +import type { Stream } from '@libp2p/interface-connection' +import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface-stream-muxer' import type { Source } from 'it-stream-types' import { pipe } from 'it-pipe' import map from 'it-map' -import type { Components } from '@libp2p/interfaces/components' +import type { Components } from '@libp2p/components' import { Uint8ArrayList } from 'uint8arraylist' let muxers = 0 diff --git a/packages/libp2p-interface-compliance-tests/test/peer-discovery/mock-discovery.ts b/packages/interface-mocks/src/peer-discovery.ts similarity index 90% rename from packages/libp2p-interface-compliance-tests/test/peer-discovery/mock-discovery.ts rename to packages/interface-mocks/src/peer-discovery.ts index 99bb93fd3..49d78fea2 100644 --- a/packages/libp2p-interface-compliance-tests/test/peer-discovery/mock-discovery.ts +++ b/packages/interface-mocks/src/peer-discovery.ts @@ -1,9 +1,9 @@ import { Multiaddr } from '@multiformats/multiaddr' import * as PeerIdFactory from '@libp2p/peer-id-factory' import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events' -import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interfaces/peer-discovery' -import type { PeerInfo } from '@libp2p/interfaces/peer-info' -import { symbol } from '@libp2p/interfaces/peer-discovery' +import type { PeerDiscovery, PeerDiscoveryEvents } from '@libp2p/interface-peer-discovery' +import type { PeerInfo } from '@libp2p/interface-peer-info' +import { symbol } from '@libp2p/interface-peer-discovery' interface MockDiscoveryInit { discoveryDelay?: number diff --git a/packages/interface-mocks/src/registrar.ts b/packages/interface-mocks/src/registrar.ts new file mode 100644 index 000000000..3c7fea2fc --- /dev/null +++ b/packages/interface-mocks/src/registrar.ts @@ -0,0 +1,81 @@ +import type { IncomingStreamData, Registrar, StreamHandler, Topology, StreamHandlerOptions, StreamHandlerRecord } from '@libp2p/interface-registrar' +import type { Connection } from '@libp2p/interface-connection' +import type { PeerId } from '@libp2p/interface-peer-id' + +export class MockRegistrar implements Registrar { + private readonly topologies: Map> = new Map() + private readonly handlers: Map = new Map() + + getProtocols () { + return Array.from(this.handlers.keys()).sort() + } + + async handle (protocol: string, handler: StreamHandler, options: StreamHandlerOptions = { maxConcurrentStreams: 1 }): Promise { + if (this.handlers.has(protocol)) { + throw new Error(`Handler already registered for protocol ${protocol}`) + } + + this.handlers.set(protocol, { + handler, + options + }) + } + + async unhandle (protocol: string) { + this.handlers.delete(protocol) + } + + getHandler (protocol: string) { + const handler = this.handlers.get(protocol) + + if (handler == null) { + throw new Error(`No handler registered for protocol ${protocol}`) + } + + return handler + } + + async register (protocol: string, topology: Topology) { + const id = `topology-id-${Math.random()}` + let topologies = this.topologies.get(protocol) + + if (topologies == null) { + topologies = [] + } + + topologies.push({ + id, + topology + }) + + this.topologies.set(protocol, topologies) + + return id + } + + unregister (id: string | string[]) { + if (!Array.isArray(id)) { + id = [id] + } + + id.forEach(id => this.topologies.delete(id)) + } + + getTopologies (protocol: string) { + return (this.topologies.get(protocol) ?? []).map(t => t.topology) + } +} + +export function mockRegistrar () { + return new MockRegistrar() +} + +export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise { + return { + ...await conn.newStream([protocol]), + // @ts-expect-error incomplete implementation + connection: { + remotePeer + } + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/upgrader.ts b/packages/interface-mocks/src/upgrader.ts similarity index 63% rename from packages/libp2p-interface-compliance-tests/src/mocks/upgrader.ts rename to packages/interface-mocks/src/upgrader.ts index c81b8a80e..4d7d7f8c4 100644 --- a/packages/libp2p-interface-compliance-tests/src/mocks/upgrader.ts +++ b/packages/interface-mocks/src/upgrader.ts @@ -1,20 +1,13 @@ -import { expect } from 'aegir/chai' import { mockConnection } from './connection.js' -import type { Upgrader, MultiaddrConnection, UpgraderEvents } from '@libp2p/interfaces/transport' -import type { Registrar } from '@libp2p/interfaces/registrar' +import type { Upgrader, UpgraderEvents } from '@libp2p/interface-transport' +import type { MultiaddrConnection } from '@libp2p/interface-connection' +import type { Registrar } from '@libp2p/interface-registrar' import { EventEmitter } from '@libp2p/interfaces/events' export interface MockUpgraderInit { registrar?: Registrar } -function ensureProps (multiaddrConnection: MultiaddrConnection) { - ['sink', 'source', 'remoteAddr', 'timeline', 'close'].forEach(prop => { - expect(multiaddrConnection).to.have.property(prop) - }) - return multiaddrConnection -} - class MockUpgrader extends EventEmitter implements Upgrader { private readonly registrar?: Registrar @@ -25,7 +18,6 @@ class MockUpgrader extends EventEmitter implements Upgrader { } async upgradeOutbound (multiaddrConnection: MultiaddrConnection) { - ensureProps(multiaddrConnection) return mockConnection(multiaddrConnection, { direction: 'outbound', registrar: this.registrar @@ -33,7 +25,6 @@ class MockUpgrader extends EventEmitter implements Upgrader { } async upgradeInbound (multiaddrConnection: MultiaddrConnection) { - ensureProps(multiaddrConnection) return mockConnection(multiaddrConnection, { direction: 'inbound', registrar: this.registrar diff --git a/packages/libp2p-interface-compliance-tests/test/mocks/connection-encrypter.spec.ts b/packages/interface-mocks/test/connection-encrypter.spec.ts similarity index 50% rename from packages/libp2p-interface-compliance-tests/test/mocks/connection-encrypter.spec.ts rename to packages/interface-mocks/test/connection-encrypter.spec.ts index 5044d89fc..88778b6eb 100644 --- a/packages/libp2p-interface-compliance-tests/test/mocks/connection-encrypter.spec.ts +++ b/packages/interface-mocks/test/connection-encrypter.spec.ts @@ -1,5 +1,5 @@ -import tests from '../../src/connection-encrypter/index.js' -import { mockConnectionEncrypter } from '../../src/mocks/connection-encrypter.js' +import tests from '@libp2p/interface-connection-encrypter-compliance-tests' +import { mockConnectionEncrypter } from '../src/connection-encrypter.js' describe('compliance tests', () => { tests({ diff --git a/packages/libp2p-interface-compliance-tests/test/mocks/muxer.spec.ts b/packages/interface-mocks/test/muxer.spec.ts similarity index 55% rename from packages/libp2p-interface-compliance-tests/test/mocks/muxer.spec.ts rename to packages/interface-mocks/test/muxer.spec.ts index 322b08b5b..cc96310af 100644 --- a/packages/libp2p-interface-compliance-tests/test/mocks/muxer.spec.ts +++ b/packages/interface-mocks/test/muxer.spec.ts @@ -1,5 +1,5 @@ -import tests from '../../src/stream-muxer/index.js' -import { mockMuxer } from '../../src/mocks/muxer.js' +import tests from '@libp2p/interface-stream-muxer-compliance-tests' +import { mockMuxer } from '../src/muxer.js' describe('compliance tests', () => { tests({ diff --git a/packages/libp2p-interface-compliance-tests/test/peer-discovery/index.spec.ts b/packages/interface-mocks/test/peer-discovery.spec.ts similarity index 73% rename from packages/libp2p-interface-compliance-tests/test/peer-discovery/index.spec.ts rename to packages/interface-mocks/test/peer-discovery.spec.ts index fa248ce33..a41d8453f 100644 --- a/packages/libp2p-interface-compliance-tests/test/peer-discovery/index.spec.ts +++ b/packages/interface-mocks/test/peer-discovery.spec.ts @@ -1,5 +1,5 @@ -import tests from '../../src/peer-discovery/index.js' -import { MockDiscovery } from './mock-discovery.js' +import tests from '@libp2p/interface-peer-discovery-compliance-tests' +import { MockDiscovery } from '../src/peer-discovery.js' describe('compliance tests', () => { let intervalId: any diff --git a/packages/interface-mocks/tsconfig.json b/packages/interface-mocks/tsconfig.json new file mode 100644 index 000000000..92a4aa134 --- /dev/null +++ b/packages/interface-mocks/tsconfig.json @@ -0,0 +1,52 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test", + "../libp2p-interfaces-connection-encrypter-compliance-tests/connection-encrypter" + ], + "references": [ + { + "path": "../interface-connection" + }, + { + "path": "../interface-connection-encrypter" + }, + { + "path": "../interface-connection-encrypter-compliance-tests" + }, + { + "path": "../interface-connection-manager" + }, + { + "path": "../interface-peer-discovery" + }, + { + "path": "../interface-peer-discovery-compliance-tests" + }, + { + "path": "../interface-peer-id" + }, + { + "path": "../interface-peer-info" + }, + { + "path": "../interface-registrar" + }, + { + "path": "../interface-stream-muxer" + }, + { + "path": "../interface-stream-muxer-compliance-tests" + }, + { + "path": "../interface-transport" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/interface-peer-discovery-compliance-tests/LICENSE b/packages/interface-peer-discovery-compliance-tests/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-peer-discovery-compliance-tests/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-peer-discovery-compliance-tests/LICENSE-APACHE b/packages/interface-peer-discovery-compliance-tests/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-peer-discovery-compliance-tests/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-peer-discovery-compliance-tests/LICENSE-MIT b/packages/interface-peer-discovery-compliance-tests/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-peer-discovery-compliance-tests/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-peer-discovery-compliance-tests/README.md b/packages/interface-peer-discovery-compliance-tests/README.md new file mode 100644 index 000000000..6a562f758 --- /dev/null +++ b/packages/interface-peer-discovery-compliance-tests/README.md @@ -0,0 +1,47 @@ +# @libp2p/interface-peer-discovery-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p Peer Discovery interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-peer-discovery-compliance-tests +``` + +## Usage + +```js +import tests from '@libp2p/interface-peer-discovery-compliance-tests' + +describe('your peer discovery implementation', () => { + tests({ + // Options should be passed to your implementation + async setup (options) { + return new YourImplementation() + }, + async teardown () { + // cleanup resources created by setup() + } + }) +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-peer-discovery-compliance-tests/package.json b/packages/interface-peer-discovery-compliance-tests/package.json new file mode 100644 index 000000000..664fe37af --- /dev/null +++ b/packages/interface-peer-discovery-compliance-tests/package.json @@ -0,0 +1,139 @@ +{ + "name": "@libp2p/interface-peer-discovery-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p Peer Discovery interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-peer-discovery-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-peer-discovery": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "@multiformats/multiaddr": "^10.2.0", + "aegir": "^37.0.17", + "delay": "^5.0.0", + "p-defer": "^4.0.0" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/peer-discovery/index.ts b/packages/interface-peer-discovery-compliance-tests/src/index.ts similarity index 94% rename from packages/libp2p-interface-compliance-tests/src/peer-discovery/index.ts rename to packages/interface-peer-discovery-compliance-tests/src/index.ts index df29ca708..eef6f4cfb 100644 --- a/packages/libp2p-interface-compliance-tests/src/peer-discovery/index.ts +++ b/packages/interface-peer-discovery-compliance-tests/src/index.ts @@ -3,8 +3,8 @@ import { Multiaddr } from '@multiformats/multiaddr' import delay from 'delay' import pDefer from 'p-defer' import { start, stop } from '@libp2p/interfaces/startable' -import type { TestSetup } from '../index.js' -import type { PeerDiscovery } from '@libp2p/interfaces/peer-discovery' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { PeerDiscovery } from '@libp2p/interface-peer-discovery' import type { Startable } from '@libp2p/interfaces/startable' export default (common: TestSetup) => { diff --git a/packages/libp2p-peer-collections/tsconfig.json b/packages/interface-peer-discovery-compliance-tests/tsconfig.json similarity index 63% rename from packages/libp2p-peer-collections/tsconfig.json rename to packages/interface-peer-discovery-compliance-tests/tsconfig.json index 7a7d79b82..faf685538 100644 --- a/packages/libp2p-peer-collections/tsconfig.json +++ b/packages/interface-peer-discovery-compliance-tests/tsconfig.json @@ -9,13 +9,13 @@ ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-compliance-tests" }, { - "path": "../libp2p-peer-id" + "path": "../interface-peer-discovery" }, { - "path": "../libp2p-peer-id-factory" + "path": "../interfaces" } ] } diff --git a/packages/interface-peer-discovery/LICENSE b/packages/interface-peer-discovery/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-peer-discovery/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-peer-discovery/LICENSE-APACHE b/packages/interface-peer-discovery/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-peer-discovery/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-peer-discovery/LICENSE-MIT b/packages/interface-peer-discovery/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-peer-discovery/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/peer-discovery/README.md b/packages/interface-peer-discovery/README.md similarity index 67% rename from packages/libp2p-interfaces/src/peer-discovery/README.md rename to packages/interface-peer-discovery/README.md index e84b30ad4..a47159bdd 100644 --- a/packages/libp2p-interfaces/src/peer-discovery/README.md +++ b/packages/interface-peer-discovery/README.md @@ -1,7 +1,28 @@ -interface-peer-discovery -======================== +# @libp2p/interface-peer-discovery -> A test suite and interface you can use to implement a Peer Discovery module for libp2p. +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Peer Discovery interface for libp2p + +## Table of contents + +- [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [Usage](#usage) + - [Node.js](#nodejs) +- [API](#api) + - [`start` the service](#start-the-service) + - [`stop` the service](#stop-the-service) + - [discovering peers](#discovering-peers) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-peer-discovery +``` The primary goal of this module is to enable developers to pick and/or swap their Peer Discovery modules as they see fit for their application, without having to go through shims or compatibility issues. This module and test suite was heavily inspired by [abstract-blob-store](https://github.com/maxogden/abstract-blob-store). @@ -76,3 +97,14 @@ Every time a peer is discovered by a discovery service, it emits a `peer` event - `<`[`PeerId`](https://github.com/libp2p/js-peer-id)`>` `peerData.id` - `>` `peerData.multiaddrs` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-interfaces/src/peer-discovery/img/badge.png b/packages/interface-peer-discovery/img/badge.png similarity index 100% rename from packages/libp2p-interfaces/src/peer-discovery/img/badge.png rename to packages/interface-peer-discovery/img/badge.png diff --git a/packages/libp2p-interfaces/src/peer-discovery/img/badge.sketch b/packages/interface-peer-discovery/img/badge.sketch similarity index 100% rename from packages/libp2p-interfaces/src/peer-discovery/img/badge.sketch rename to packages/interface-peer-discovery/img/badge.sketch diff --git a/packages/libp2p-interfaces/src/peer-discovery/img/badge.svg b/packages/interface-peer-discovery/img/badge.svg similarity index 100% rename from packages/libp2p-interfaces/src/peer-discovery/img/badge.svg rename to packages/interface-peer-discovery/img/badge.svg diff --git a/packages/interface-peer-discovery/package.json b/packages/interface-peer-discovery/package.json new file mode 100644 index 000000000..de58164fd --- /dev/null +++ b/packages/interface-peer-discovery/package.json @@ -0,0 +1,137 @@ +{ + "name": "@libp2p/interface-peer-discovery", + "version": "0.0.1", + "description": "Peer Discovery interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-peer-discovery#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-info": "~0.0.0", + "@libp2p/interfaces": "^2.0.0" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/peer-discovery/index.ts b/packages/interface-peer-discovery/src/index.ts similarity index 80% rename from packages/libp2p-interfaces/src/peer-discovery/index.ts rename to packages/interface-peer-discovery/src/index.ts index cc1975eba..4a2c22a44 100644 --- a/packages/libp2p-interfaces/src/peer-discovery/index.ts +++ b/packages/interface-peer-discovery/src/index.ts @@ -1,5 +1,5 @@ -import type { PeerInfo } from '../peer-info/index.js' -import type { EventEmitter } from '../events.js' +import type { PeerInfo } from '@libp2p/interface-peer-info' +import type { EventEmitter } from '@libp2p/interfaces/events' export const symbol = Symbol.for('@libp2p/peer-discovery') diff --git a/packages/interface-peer-discovery/tsconfig.json b/packages/interface-peer-discovery/tsconfig.json new file mode 100644 index 000000000..84bbd0ffe --- /dev/null +++ b/packages/interface-peer-discovery/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-info" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/interface-peer-id/LICENSE b/packages/interface-peer-id/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-peer-id/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-peer-id/LICENSE-APACHE b/packages/interface-peer-id/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-peer-id/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-peer-id/LICENSE-MIT b/packages/interface-peer-id/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-peer-id/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/peer-id/README.md b/packages/interface-peer-id/README.md similarity index 55% rename from packages/libp2p-interfaces/src/peer-id/README.md rename to packages/interface-peer-id/README.md index 49567facf..dcf2383b7 100644 --- a/packages/libp2p-interfaces/src/peer-id/README.md +++ b/packages/interface-peer-id/README.md @@ -1,7 +1,24 @@ -interface-peer-id -======================== +# @libp2p/interface-peer-id -> A test suite and interface you can use to implement a PeerId module for libp2p. +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Peer Identifier interface for libp2p + +## Table of contents + +- [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [Usage](#usage) + - [Node.js](#nodejs) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-peer-id +``` The primary goal of this module is to enable developers to implement PeerId modules. This module and test suite was heavily inspired by earlier implementation of [PeerId](https://github.com/libp2p/js-peer-id). @@ -42,3 +59,14 @@ describe('your peer id', () => { }) }) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-peer-id/package.json b/packages/interface-peer-id/package.json new file mode 100644 index 000000000..52206c24d --- /dev/null +++ b/packages/interface-peer-id/package.json @@ -0,0 +1,136 @@ +{ + "name": "@libp2p/interface-peer-id", + "version": "0.0.1", + "description": "Peer Identifier interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-peer-id#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "multiformats": "^9.6.3" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/peer-id/index.ts b/packages/interface-peer-id/src/index.ts similarity index 100% rename from packages/libp2p-interfaces/src/peer-id/index.ts rename to packages/interface-peer-id/src/index.ts diff --git a/packages/interface-peer-id/tsconfig.json b/packages/interface-peer-id/tsconfig.json new file mode 100644 index 000000000..5fe8ea40d --- /dev/null +++ b/packages/interface-peer-id/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ] +} diff --git a/packages/interface-peer-info/LICENSE b/packages/interface-peer-info/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-peer-info/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-peer-info/LICENSE-APACHE b/packages/interface-peer-info/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-peer-info/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-peer-info/LICENSE-MIT b/packages/interface-peer-info/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-peer-info/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-peer-info/README.md b/packages/interface-peer-info/README.md new file mode 100644 index 000000000..74082ac40 --- /dev/null +++ b/packages/interface-peer-info/README.md @@ -0,0 +1,28 @@ +# @libp2p/interface-peer-info + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Peer Info interface for libp2p + +## Table of contents + +- [Install](#install) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-peer-info +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-peer-info/package.json b/packages/interface-peer-info/package.json new file mode 100644 index 000000000..4ece4bede --- /dev/null +++ b/packages/interface-peer-info/package.json @@ -0,0 +1,137 @@ +{ + "name": "@libp2p/interface-peer-info", + "version": "0.0.1", + "description": "Peer Info interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-peer-info#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0", + "@multiformats/multiaddr": "^10.2.0" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/peer-info/index.ts b/packages/interface-peer-info/src/index.ts similarity index 72% rename from packages/libp2p-interfaces/src/peer-info/index.ts rename to packages/interface-peer-info/src/index.ts index e28588201..59ae2b5d3 100644 --- a/packages/libp2p-interfaces/src/peer-info/index.ts +++ b/packages/interface-peer-info/src/index.ts @@ -1,4 +1,4 @@ -import type { PeerId } from '../peer-id' +import type { PeerId } from '@libp2p/interface-peer-id' import type { Multiaddr } from '@multiformats/multiaddr' export interface PeerInfo { diff --git a/packages/interface-peer-info/tsconfig.json b/packages/interface-peer-info/tsconfig.json new file mode 100644 index 000000000..d8db0b667 --- /dev/null +++ b/packages/interface-peer-info/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-id" + } + ] +} diff --git a/packages/interface-peer-routing/LICENSE b/packages/interface-peer-routing/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-peer-routing/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-peer-routing/LICENSE-APACHE b/packages/interface-peer-routing/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-peer-routing/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-peer-routing/LICENSE-MIT b/packages/interface-peer-routing/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-peer-routing/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/peer-routing/README.md b/packages/interface-peer-routing/README.md similarity index 53% rename from packages/libp2p-interfaces/src/peer-routing/README.md rename to packages/interface-peer-routing/README.md index 83f1e21f0..50e0033a2 100644 --- a/packages/libp2p-interfaces/src/peer-routing/README.md +++ b/packages/interface-peer-routing/README.md @@ -1,9 +1,26 @@ -interface-peer-routing -===================== +# @libp2p/interface-peer-routing -**WIP: This module is not yet implemented** +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) -> A test suite and interface you can use to implement a Peer Routing module for libp2p. +> Peer Routing interface for libp2p + +## Table of contents + +- - [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [How to use the battery of tests](#how-to-use-the-battery-of-tests) + - [Node.js](#nodejs) +- [API](#api) + - - [findPeer](#findpeer) + - [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-peer-routing +``` The primary goal of this module is to enable developers to pick and swap their Peer Routing module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. @@ -37,6 +54,7 @@ A valid (read: that follows this abstraction) Peer Routing module must implement Query the network for all multiaddresses associated with a `PeerId`. **Parameters** + - [peerId](https://github.com/libp2p/js-peer-id). **Returns** @@ -44,3 +62,14 @@ Query the network for all multiaddresses associated with a `PeerId`. It returns the [peerId](https://github.com/libp2p/js-peer-id) together with the known peers [multiaddrs](https://github.com/multiformats/js-multiaddr), as follows: `Promise<{ id: PeerId, multiaddrs: Multiaddr[] }>` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-interfaces/src/peer-routing/img/badge.png b/packages/interface-peer-routing/img/badge.png similarity index 100% rename from packages/libp2p-interfaces/src/peer-routing/img/badge.png rename to packages/interface-peer-routing/img/badge.png diff --git a/packages/libp2p-interfaces/src/peer-routing/img/badge.sketch b/packages/interface-peer-routing/img/badge.sketch similarity index 100% rename from packages/libp2p-interfaces/src/peer-routing/img/badge.sketch rename to packages/interface-peer-routing/img/badge.sketch diff --git a/packages/libp2p-interfaces/src/peer-routing/img/badge.svg b/packages/interface-peer-routing/img/badge.svg similarity index 100% rename from packages/libp2p-interfaces/src/peer-routing/img/badge.svg rename to packages/interface-peer-routing/img/badge.svg diff --git a/packages/interface-peer-routing/package.json b/packages/interface-peer-routing/package.json new file mode 100644 index 000000000..f3598b36a --- /dev/null +++ b/packages/interface-peer-routing/package.json @@ -0,0 +1,138 @@ +{ + "name": "@libp2p/interface-peer-routing", + "version": "0.0.1", + "description": "Peer Routing interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-peer-routing#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/interface-peer-info": "~0.0.0", + "@libp2p/interfaces": "^2.0.0" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/peer-routing/index.ts b/packages/interface-peer-routing/src/index.ts similarity index 53% rename from packages/libp2p-interfaces/src/peer-routing/index.ts rename to packages/interface-peer-routing/src/index.ts index 12ff5c190..b87b97159 100644 --- a/packages/libp2p-interfaces/src/peer-routing/index.ts +++ b/packages/interface-peer-routing/src/index.ts @@ -1,6 +1,6 @@ -import type { PeerId } from '../peer-id/index.js' -import type { PeerInfo } from '../peer-info/index.js' -import type { AbortOptions } from '../index.js' +import type { PeerId } from '@libp2p/interface-peer-id' +import type { PeerInfo } from '@libp2p/interface-peer-info' +import type { AbortOptions } from '@libp2p/interfaces' export interface PeerRouting { findPeer: (peerId: PeerId, options?: AbortOptions) => Promise diff --git a/packages/interface-peer-routing/tsconfig.json b/packages/interface-peer-routing/tsconfig.json new file mode 100644 index 000000000..02d375dbd --- /dev/null +++ b/packages/interface-peer-routing/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-id" + }, + { + "path": "../interface-peer-info" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/interface-peer-store/LICENSE b/packages/interface-peer-store/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-peer-store/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-peer-store/LICENSE-APACHE b/packages/interface-peer-store/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-peer-store/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-peer-store/LICENSE-MIT b/packages/interface-peer-store/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-peer-store/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-peer-store/README.md b/packages/interface-peer-store/README.md new file mode 100644 index 000000000..1c74e8e94 --- /dev/null +++ b/packages/interface-peer-store/README.md @@ -0,0 +1,28 @@ +# @libp2p/interface-peer-store + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Peer Store interface for libp2p + +## Table of contents + +- [Install](#install) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-peer-store +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-peer-store/package.json b/packages/interface-peer-store/package.json new file mode 100644 index 000000000..659612e18 --- /dev/null +++ b/packages/interface-peer-store/package.json @@ -0,0 +1,140 @@ +{ + "name": "@libp2p/interface-peer-store", + "version": "0.0.1", + "description": "Peer Store interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-peer-store#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/interface-peer-info": "~0.0.0", + "@libp2p/interface-record": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "@multiformats/multiaddr": "^10.2.0" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/peer-store/index.ts b/packages/interface-peer-store/src/index.ts similarity index 96% rename from packages/libp2p-interfaces/src/peer-store/index.ts rename to packages/interface-peer-store/src/index.ts index 1c3e1cfa3..059c01069 100644 --- a/packages/libp2p-interfaces/src/peer-store/index.ts +++ b/packages/interface-peer-store/src/index.ts @@ -1,8 +1,8 @@ -import type { PeerId } from '../peer-id/index.js' +import type { PeerId } from '@libp2p/interface-peer-id' import type { Multiaddr } from '@multiformats/multiaddr' -import type { EventEmitter } from '../events.js' -import type { Envelope } from '../record/index.js' -import type { PeerInfo } from '../peer-info/index.js' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Envelope } from '@libp2p/interface-record' +import type { PeerInfo } from '@libp2p/interface-peer-info' export interface Address { /** diff --git a/packages/interface-peer-store/tsconfig.json b/packages/interface-peer-store/tsconfig.json new file mode 100644 index 000000000..6f6f8aed5 --- /dev/null +++ b/packages/interface-peer-store/tsconfig.json @@ -0,0 +1,23 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-peer-id" + }, + { + "path": "../interface-peer-info" + }, + { + "path": "../interface-record" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/interface-pubsub-compliance-tests/LICENSE b/packages/interface-pubsub-compliance-tests/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-pubsub-compliance-tests/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-pubsub-compliance-tests/LICENSE-APACHE b/packages/interface-pubsub-compliance-tests/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-pubsub-compliance-tests/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-pubsub-compliance-tests/LICENSE-MIT b/packages/interface-pubsub-compliance-tests/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-pubsub-compliance-tests/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-pubsub-compliance-tests/README.md b/packages/interface-pubsub-compliance-tests/README.md new file mode 100644 index 000000000..3e80c1abd --- /dev/null +++ b/packages/interface-pubsub-compliance-tests/README.md @@ -0,0 +1,47 @@ +# @libp2p/interface-pubsub-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p PubSub interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-pubsub-compliance-tests +``` + +## Usage + +```js +import tests from '@libp2p/interface-pubsub-compliance-tests' + +describe('your pubsub implementation', () => { + tests({ + // Options should be passed to your implementation + async setup (options) { + return new YourImplementation() + }, + async teardown () { + // cleanup resources created by setup() + } + }) +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-pubsub-compliance-tests/package.json b/packages/interface-pubsub-compliance-tests/package.json new file mode 100644 index 000000000..0d246110b --- /dev/null +++ b/packages/interface-pubsub-compliance-tests/package.json @@ -0,0 +1,146 @@ +{ + "name": "@libp2p/interface-pubsub-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p PubSub interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-pubsub-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/components": "~0.0.0", + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-mocks": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/interface-pubsub": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "@libp2p/peer-id-factory": "^1.0.12", + "aegir": "^37.0.17", + "delay": "^5.0.0", + "p-defer": "^4.0.0", + "p-event": "^5.0.1", + "p-wait-for": "^4.1.0", + "sinon": "^14.0.0", + "uint8arrays": "^3.0.0" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/api.ts b/packages/interface-pubsub-compliance-tests/src/api.ts similarity index 92% rename from packages/libp2p-interface-compliance-tests/src/pubsub/api.ts rename to packages/interface-pubsub-compliance-tests/src/api.ts index 2712306a9..55b15f903 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/api.ts +++ b/packages/interface-pubsub-compliance-tests/src/api.ts @@ -4,13 +4,13 @@ import pDefer from 'p-defer' import pWaitFor from 'p-wait-for' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import delay from 'delay' -import type { TestSetup } from '../index.js' -import type { PubSub } from '@libp2p/interfaces/pubsub' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { PubSub } from '@libp2p/interface-pubsub' import type { PubSubArgs } from './index.js' -import type { Components } from '@libp2p/interfaces/components' +import type { Components } from '@libp2p/components' import { createComponents } from './utils.js' import { isStartable, start, stop } from '@libp2p/interfaces/startable' -import { mockNetwork } from '../mocks/connection-manager.js' +import { mockNetwork } from '@libp2p/interface-mocks' const topic = 'foo' const data = uint8ArrayFromString('bar') diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/connection-handlers.ts b/packages/interface-pubsub-compliance-tests/src/connection-handlers.ts similarity index 98% rename from packages/libp2p-interface-compliance-tests/src/pubsub/connection-handlers.ts rename to packages/interface-pubsub-compliance-tests/src/connection-handlers.ts index 21859888a..eb434f957 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/connection-handlers.ts +++ b/packages/interface-pubsub-compliance-tests/src/connection-handlers.ts @@ -4,14 +4,14 @@ import pDefer from 'p-defer' import pWaitFor from 'p-wait-for' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import type { TestSetup } from '../index.js' -import type { Message, PubSub } from '@libp2p/interfaces/pubsub' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Message, PubSub } from '@libp2p/interface-pubsub' import type { PubSubArgs } from './index.js' -import type { Components } from '@libp2p/interfaces/components' +import type { Components } from '@libp2p/components' import { start, stop } from '@libp2p/interfaces/startable' import { createComponents } from './utils.js' import { pEvent } from 'p-event' -import { mockNetwork } from '../mocks/connection-manager.js' +import { mockNetwork } from '@libp2p/interface-mocks' export default (common: TestSetup) => { describe('pubsub connection handlers', () => { diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/emit-self.ts b/packages/interface-pubsub-compliance-tests/src/emit-self.ts similarity index 90% rename from packages/libp2p-interface-compliance-tests/src/pubsub/emit-self.ts rename to packages/interface-pubsub-compliance-tests/src/emit-self.ts index ba960f0e5..6c4d756e7 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/emit-self.ts +++ b/packages/interface-pubsub-compliance-tests/src/emit-self.ts @@ -2,14 +2,13 @@ import { expect } from 'aegir/chai' import sinon from 'sinon' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { mockRegistrar } from '../mocks/registrar.js' -import type { TestSetup } from '../index.js' +import { mockRegistrar, mockNetwork } from '@libp2p/interface-mocks' +import type { TestSetup } from '@libp2p/interface-compliance-tests' import type { PubSubArgs } from './index.js' -import { Components } from '@libp2p/interfaces/components' +import { Components } from '@libp2p/components' import { start, stop } from '@libp2p/interfaces/startable' -import type { PubSub } from '@libp2p/interfaces/pubsub' +import type { PubSub } from '@libp2p/interface-pubsub' import { createComponents } from './utils.js' -import { mockNetwork } from '../mocks/connection-manager.js' const topic = 'foo' const data = uint8ArrayFromString('bar') diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/index.ts b/packages/interface-pubsub-compliance-tests/src/index.ts similarity index 77% rename from packages/libp2p-interface-compliance-tests/src/pubsub/index.ts rename to packages/interface-pubsub-compliance-tests/src/index.ts index b90977035..be359d2b5 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/index.ts +++ b/packages/interface-pubsub-compliance-tests/src/index.ts @@ -4,9 +4,9 @@ import messagesTest from './messages.js' import connectionHandlersTest from './connection-handlers.js' import twoNodesTest from './two-nodes.js' import multipleNodesTest from './multiple-nodes.js' -import type { TestSetup } from '../index.js' -import type { PubSub, PubSubInit } from '@libp2p/interfaces/pubsub' -import type { Components } from '@libp2p/interfaces/components' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { PubSub, PubSubInit } from '@libp2p/interface-pubsub' +import type { Components } from '@libp2p/components' export interface PubSubArgs { components: Components diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/messages.ts b/packages/interface-pubsub-compliance-tests/src/messages.ts similarity index 86% rename from packages/libp2p-interface-compliance-tests/src/pubsub/messages.ts rename to packages/interface-pubsub-compliance-tests/src/messages.ts index c9ade884c..d1da58173 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/messages.ts +++ b/packages/interface-pubsub-compliance-tests/src/messages.ts @@ -1,14 +1,14 @@ import { expect } from 'aegir/chai' import sinon from 'sinon' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import type { TestSetup } from '../index.js' -import type { Message, PubSub } from '@libp2p/interfaces/pubsub' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Message, PubSub } from '@libp2p/interface-pubsub' import type { PubSubArgs } from './index.js' -import type { Components } from '@libp2p/interfaces/components' +import type { Components } from '@libp2p/components' import { start, stop } from '@libp2p/interfaces/startable' import { pEvent } from 'p-event' import { createComponents } from './utils.js' -import { mockNetwork } from '../mocks/connection-manager.js' +import { mockNetwork } from '@libp2p/interface-mocks' const topic = 'foo' const data = uint8ArrayFromString('bar') diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/multiple-nodes.ts b/packages/interface-pubsub-compliance-tests/src/multiple-nodes.ts similarity index 98% rename from packages/libp2p-interface-compliance-tests/src/pubsub/multiple-nodes.ts rename to packages/interface-pubsub-compliance-tests/src/multiple-nodes.ts index a523b3d39..fdf4bee04 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/multiple-nodes.ts +++ b/packages/interface-pubsub-compliance-tests/src/multiple-nodes.ts @@ -6,13 +6,13 @@ import pWaitFor from 'p-wait-for' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { createComponents, waitForSubscriptionUpdate } from './utils.js' -import type { TestSetup } from '../index.js' -import type { Message, PubSub } from '@libp2p/interfaces/pubsub' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Message, PubSub } from '@libp2p/interface-pubsub' import type { PubSubArgs } from './index.js' -import type { Components } from '@libp2p/interfaces/components' +import type { Components } from '@libp2p/components' import { start, stop } from '@libp2p/interfaces/startable' import delay from 'delay' -import { mockNetwork } from '../mocks/connection-manager.js' +import { mockNetwork } from '@libp2p/interface-mocks' export default (common: TestSetup) => { describe('pubsub with multiple nodes', function () { diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/two-nodes.ts b/packages/interface-pubsub-compliance-tests/src/two-nodes.ts similarity index 96% rename from packages/libp2p-interface-compliance-tests/src/pubsub/two-nodes.ts rename to packages/interface-pubsub-compliance-tests/src/two-nodes.ts index ac8a89c62..08d163841 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/two-nodes.ts +++ b/packages/interface-pubsub-compliance-tests/src/two-nodes.ts @@ -6,12 +6,12 @@ import pWaitFor from 'p-wait-for' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { createComponents, waitForSubscriptionUpdate } from './utils.js' -import type { TestSetup } from '../index.js' -import type { Message, PubSub } from '@libp2p/interfaces/pubsub' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Message, PubSub } from '@libp2p/interface-pubsub' import type { PubSubArgs } from './index.js' -import type { Components } from '@libp2p/interfaces/components' +import type { Components } from '@libp2p/components' import { start, stop } from '@libp2p/interfaces/startable' -import { mockNetwork } from '../mocks/connection-manager.js' +import { mockNetwork } from '@libp2p/interface-mocks' const topic = 'foo' diff --git a/packages/libp2p-interface-compliance-tests/src/pubsub/utils.ts b/packages/interface-pubsub-compliance-tests/src/utils.ts similarity index 73% rename from packages/libp2p-interface-compliance-tests/src/pubsub/utils.ts rename to packages/interface-pubsub-compliance-tests/src/utils.ts index d6224b19e..349b840ff 100644 --- a/packages/libp2p-interface-compliance-tests/src/pubsub/utils.ts +++ b/packages/interface-pubsub-compliance-tests/src/utils.ts @@ -1,11 +1,10 @@ import { pEvent } from 'p-event' import pWaitFor from 'p-wait-for' -import { Components } from '@libp2p/interfaces/components' -import type { PubSub, SubscriptionChangeData } from '@libp2p/interfaces/pubsub' -import type { PeerId } from '@libp2p/interfaces/peer-id' +import { Components } from '@libp2p/components' +import type { PubSub, SubscriptionChangeData } from '@libp2p/interface-pubsub' +import type { PeerId } from '@libp2p/interface-peer-id' import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { mockConnectionManager, mockRegistrar } from '../mocks/index.js' -import { mockNetwork } from '../mocks/connection-manager.js' +import { mockConnectionManager, mockRegistrar, mockNetwork } from '@libp2p/interface-mocks' export async function waitForSubscriptionUpdate (a: PubSub, b: PeerId) { await pWaitFor(async () => { diff --git a/packages/interface-pubsub-compliance-tests/tsconfig.json b/packages/interface-pubsub-compliance-tests/tsconfig.json new file mode 100644 index 000000000..26b67bfb0 --- /dev/null +++ b/packages/interface-pubsub-compliance-tests/tsconfig.json @@ -0,0 +1,27 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "references": [ + { + "path": "../interface-compliance-tests" + }, + { + "path": "../interface-mocks" + }, + { + "path": "../interface-peer-id" + }, + { + "path": "../interface-pubsub" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/interface-pubsub/LICENSE b/packages/interface-pubsub/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-pubsub/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-pubsub/LICENSE-APACHE b/packages/interface-pubsub/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-pubsub/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-pubsub/LICENSE-MIT b/packages/interface-pubsub/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-pubsub/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/pubsub/README.md b/packages/interface-pubsub/README.md similarity index 52% rename from packages/libp2p-interfaces/src/pubsub/README.md rename to packages/interface-pubsub/README.md index b9f44f75b..a14835cfc 100644 --- a/packages/libp2p-interfaces/src/pubsub/README.md +++ b/packages/interface-pubsub/README.md @@ -1,47 +1,96 @@ -interface-pubsub -================== +# @libp2p/interface-pubsub + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> PubSub interface for libp2p + +## Table of contents + +- - [Install](#install) +- [Table of Contents ](#table-of-contents----omit-in-toc---) + - [Implementations using this interface](#implementations-using-this-interface) + - [Interface usage](#interface-usage) + - [Extend interface](#extend-interface) + - [Example](#example) + - [API](#api) + - [Constructor](#constructor) + - [`new Pubsub({options})`](#new-pubsuboptions) + - [Parameters](#parameters) + - [Start](#start) + - [`pubsub.start()`](#pubsubstart) + - [Stop](#stop) + - [`pubsub.stop()`](#pubsubstop) + - [Publish](#publish) + - [`pubsub.publish(topic, message)`](#pubsubpublishtopic-message) + - [Parameters](#parameters-1) + - [Returns](#returns) + - [Subscribe](#subscribe) + - [`pubsub.subscribe(topic)`](#pubsubsubscribetopic) + - [Parameters](#parameters-2) + - [Unsubscribe](#unsubscribe) + - [`pubsub.unsubscribe(topic)`](#pubsubunsubscribetopic) + - [Parameters](#parameters-3) + - [Get Topics](#get-topics) + - [`pubsub.getTopics()`](#pubsubgettopics) + - [Returns](#returns-1) + - [Get Peers Subscribed to a topic](#get-peers-subscribed-to-a-topic) + - [`pubsub.getSubscribers(topic)`](#pubsubgetsubscriberstopic) + - [Parameters](#parameters-4) + - [Returns](#returns-2) + - [Validate](#validate) + - [`pubsub.validate(message)`](#pubsubvalidatemessage) + - [Parameters](#parameters-5) + - [Returns](#returns-3) + - [Test suite usage](#test-suite-usage) + - [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-pubsub +``` The `interface-pubsub` contains the base implementation for a libp2p pubsub router implementation. This interface should be used to implement a pubsub router compatible with libp2p. It includes a test suite that pubsub routers should run, in order to ensure compatibility with libp2p. -Table of Contents -================= - -* [Implementations using this interface](#implementations-using-this-interface) -* [Interface usage](#interface-usage) - * [Extend interface](#extend-interface) - * [Example](#example) -* [API](#api) - * [Constructor](#constructor) - * [new Pubsub(options)](#new-pubsuboptions) - * [Parameters](#parameters) - * [Start](#start) - * [pubsub.start()](#pubsubstart) - * [Returns](#returns) - * [Stop](#stop) - * [pubsub.stop()](#pubsubstop) - * [Returns](#returns-1) - * [Publish](#publish) - * [pubsub.publish(topics, message)](#pubsubpublishtopics-message) - * [Parameters](#parameters-1) - * [Returns](#returns-2) - * [Subscribe](#subscribe) - * [pubsub.subscribe(topic)](#pubsubsubscribetopic) - * [Parameters](#parameters-2) - * [Unsubscribe](#unsubscribe) - * [pubsub.unsubscribe(topic)](#pubsubunsubscribetopic) - * [Parameters](#parameters-3) - * [Get Topics](#get-topics) - * [pubsub.getTopics()](#pubsubgettopics) - * [Returns](#returns-3) - * [Get Peers Subscribed to a topic](#get-peers-subscribed-to-a-topic) - * [pubsub.getSubscribers(topic)](#pubsubgetsubscriberstopic) - * [Parameters](#parameters-4) - * [Returns](#returns-4) - * [Validate](#validate) - * [pubsub.validate(message)](#pubsubvalidatemessage) - * [Parameters](#parameters-5) - * [Returns](#returns-5) -* [Test suite usage](#test-suite-usage) +# Table of Contents + +- [Implementations using this interface](#implementations-using-this-interface) +- [Interface usage](#interface-usage) + - [Extend interface](#extend-interface) + - [Example](#example) +- [API](#api) + - [Constructor](#constructor) + - [`new Pubsub({options})`](#new-pubsuboptions) + - [Parameters](#parameters) + - [Start](#start) + - [`pubsub.start()`](#pubsubstart) + - [Stop](#stop) + - [`pubsub.stop()`](#pubsubstop) + - [Publish](#publish) + - [`pubsub.publish(topic, message)`](#pubsubpublishtopic-message) + - [Parameters](#parameters-1) + - [Returns](#returns) + - [Subscribe](#subscribe) + - [`pubsub.subscribe(topic)`](#pubsubsubscribetopic) + - [Parameters](#parameters-2) + - [Unsubscribe](#unsubscribe) + - [`pubsub.unsubscribe(topic)`](#pubsubunsubscribetopic) + - [Parameters](#parameters-3) + - [Get Topics](#get-topics) + - [`pubsub.getTopics()`](#pubsubgettopics) + - [Returns](#returns-1) + - [Get Peers Subscribed to a topic](#get-peers-subscribed-to-a-topic) + - [`pubsub.getSubscribers(topic)`](#pubsubgetsubscriberstopic) + - [Parameters](#parameters-4) + - [Returns](#returns-2) + - [Validate](#validate) + - [`pubsub.validate(message)`](#pubsubvalidatemessage) + - [Parameters](#parameters-5) + - [Returns](#returns-3) +- [Test suite usage](#test-suite-usage) +- [License](#license) + - [Contribution](#contribution) ## Implementations using this interface @@ -108,14 +157,14 @@ The base class constructor configures the pubsub instance for use with a libp2p ##### Parameters -| Name | Type | Description | Default | -|------|------|-------------|---------| -| options.libp2p | `Libp2p` | libp2p instance | required, no default | -| options.debugName | `string` | log namespace | required, no default | -| options.multicodecs | `string \| Array` | protocol identifier(s) | required, no default | -| options.globalSignaturePolicy | `'StrictSign' \| 'StrictNoSign'` | signature policy to be globally applied | `'StrictSign'` | -| options.canRelayMessage | `boolean` | if can relay messages if not subscribed | `false` | -| options.emitSelf | `boolean` | if `publish` should emit to self, if subscribed | `false` | +| Name | Type | Description | Default | +| ----------------------------- | -------------------------------- | ----------------------------------------------- | -------------------- | +| options.libp2p | `Libp2p` | libp2p instance | required, no default | +| options.debugName | `string` | log namespace | required, no default | +| options.multicodecs | `string \| Array` | protocol identifier(s) | required, no default | +| options.globalSignaturePolicy | `'StrictSign' \| 'StrictNoSign'` | signature policy to be globally applied | `'StrictSign'` | +| options.canRelayMessage | `boolean` | if can relay messages if not subscribed | `false` | +| options.emitSelf | `boolean` | if `publish` should emit to self, if subscribed | `false` | ### Start @@ -137,15 +186,15 @@ Publish data message to pubsub topics. ##### Parameters -| Name | Type | Description | -|------|------|-------------| -| topic | `string` | pubsub topic | +| Name | Type | Description | +| ------- | ------------ | ------------------ | +| topic | `string` | pubsub topic | | message | `Uint8Array` | message to publish | ##### Returns -| Type | Description | -|------|-------------| +| Type | Description | +| --------------- | ----------------------------------------------------- | | `Promise` | resolves once the message is published to the network | ### Subscribe @@ -156,8 +205,8 @@ Subscribe to the given topic. ##### Parameters -| Name | Type | Description | -|------|------|-------------| +| Name | Type | Description | +| ----- | -------- | ------------ | | topic | `string` | pubsub topic | ### Unsubscribe @@ -168,8 +217,8 @@ Unsubscribe from the given topic. ##### Parameters -| Name | Type | Description | -|------|------|-------------| +| Name | Type | Description | +| ----- | -------- | ------------ | | topic | `string` | pubsub topic | ### Get Topics @@ -180,8 +229,8 @@ Get the list of topics which the peer is subscribed to. ##### Returns -| Type | Description | -|------|-------------| +| Type | Description | +| --------------- | -------------------------- | | `Array` | Array of subscribed topics | ### Get Peers Subscribed to a topic @@ -192,14 +241,14 @@ Get a list of the [PeerId](https://github.com/libp2p/js-peer-id) strings that ar ##### Parameters -| Name | Type | Description | -|------|------|-------------| +| Name | Type | Description | +| ----- | -------- | ------------ | | topic | `string` | pubsub topic | ##### Returns -| Type | Description | -|------|-------------| +| Type | Description | +| --------------- | ------------------------- | | `Array` | Array of base-58 PeerId's | ### Validate @@ -210,14 +259,14 @@ Validates a message according to the signature policy and topic-specific validat ##### Parameters -| Name | Type | Description | -|------|------|-------------| +| Name | Type | Description | +| ------- | --------- | ---------------- | | message | `Message` | a pubsub message | #### Returns -| Type | Description | -|------|-------------| +| Type | Description | +| --------------- | -------------------------------- | | `Promise` | resolves if the message is valid | ## Test suite usage @@ -253,3 +302,14 @@ describe('compliance', () => { }) }) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-pubsub/package.json b/packages/interface-pubsub/package.json new file mode 100644 index 000000000..baa5e2ae6 --- /dev/null +++ b/packages/interface-pubsub/package.json @@ -0,0 +1,139 @@ +{ + "name": "@libp2p/interface-pubsub", + "version": "0.0.1", + "description": "PubSub interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-pubsub#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "it-pushable": "^2.0.2" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/pubsub/index.ts b/packages/interface-pubsub/src/index.ts similarity index 94% rename from packages/libp2p-interfaces/src/pubsub/index.ts rename to packages/interface-pubsub/src/index.ts index 56d825049..22761d33e 100644 --- a/packages/libp2p-interfaces/src/pubsub/index.ts +++ b/packages/interface-pubsub/src/index.ts @@ -1,7 +1,7 @@ -import type { PeerId } from '../peer-id/index.js' +import type { PeerId } from '@libp2p/interface-peer-id' import type { Pushable } from 'it-pushable' -import type { EventEmitter } from '../events.js' -import type { Stream } from '../connection/index.js' +import type { EventEmitter } from '@libp2p/interfaces/events' +import type { Stream } from '@libp2p/interface-connection' /** * On the producing side: diff --git a/packages/interface-pubsub/tsconfig.json b/packages/interface-pubsub/tsconfig.json new file mode 100644 index 000000000..cbde3d05c --- /dev/null +++ b/packages/interface-pubsub/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ], + "references": [ + { + "path": "../interface-connection" + }, + { + "path": "../interface-peer-id" + }, + { + "path": "../interfaces" + } + ] +} diff --git a/packages/interface-record-compliance-tests/LICENSE b/packages/interface-record-compliance-tests/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-record-compliance-tests/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-record-compliance-tests/LICENSE-APACHE b/packages/interface-record-compliance-tests/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-record-compliance-tests/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-record-compliance-tests/LICENSE-MIT b/packages/interface-record-compliance-tests/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-record-compliance-tests/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-record-compliance-tests/README.md b/packages/interface-record-compliance-tests/README.md new file mode 100644 index 000000000..cd966ce17 --- /dev/null +++ b/packages/interface-record-compliance-tests/README.md @@ -0,0 +1,47 @@ +# @libp2p/interface-record-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p Record interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-record-compliance-tests +``` + +## Usage + +```js +import tests from '@libp2p/interface-record-tests' + +describe('your record implementation', () => { + tests({ + // Options should be passed to your implementation + async setup (options) { + return new YourImplementation() + }, + async teardown () { + // cleanup resources created by setup() + } + }) +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-record-compliance-tests/package.json b/packages/interface-record-compliance-tests/package.json new file mode 100644 index 000000000..5b179d55e --- /dev/null +++ b/packages/interface-record-compliance-tests/package.json @@ -0,0 +1,135 @@ +{ + "name": "@libp2p/interface-record-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p Record interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-record-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-record": "~0.0.0", + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/record/index.ts b/packages/interface-record-compliance-tests/src/index.ts similarity index 84% rename from packages/libp2p-interface-compliance-tests/src/record/index.ts rename to packages/interface-record-compliance-tests/src/index.ts index dd3d169a7..08e72ac2e 100644 --- a/packages/libp2p-interface-compliance-tests/src/record/index.ts +++ b/packages/interface-record-compliance-tests/src/index.ts @@ -1,6 +1,6 @@ import { expect } from 'aegir/chai' -import type { TestSetup } from '../index.js' -import type { Record } from '@libp2p/interfaces/record' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Record } from '@libp2p/interface-record' export default (test: TestSetup) => { describe('record', () => { diff --git a/packages/interface-record-compliance-tests/tsconfig.json b/packages/interface-record-compliance-tests/tsconfig.json new file mode 100644 index 000000000..6ca17f6cd --- /dev/null +++ b/packages/interface-record-compliance-tests/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "references": [ + { + "path": "../interface-compliance-tests" + }, + { + "path": "../interface-record" + } + ] +} diff --git a/packages/interface-record/LICENSE b/packages/interface-record/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-record/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-record/LICENSE-APACHE b/packages/interface-record/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-record/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-record/LICENSE-MIT b/packages/interface-record/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-record/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/record/README.md b/packages/interface-record/README.md similarity index 72% rename from packages/libp2p-interfaces/src/record/README.md rename to packages/interface-record/README.md index a34fbc6d9..ce72d5d27 100644 --- a/packages/libp2p-interfaces/src/record/README.md +++ b/packages/interface-record/README.md @@ -1,5 +1,25 @@ -interface-record -================== +# @libp2p/interface-record + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Record interface for libp2p + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [Create Record](#create-record) +- [API](#api) + - [marshal](#marshal) + - [equals](#equals) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-record +``` A libp2p node needs to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information. Libp2p provides an all-purpose data container called **envelope**, which includes a signature of the data, so that it its authenticity can be verified. @@ -85,7 +105,20 @@ It returns a `Protobuf` containing the record data. Verifies if the other Record is identical to this one. **Parameters** + - other is a `Record` to compare with the current instance. **Returns** + - `other is Record` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-record/package.json b/packages/interface-record/package.json new file mode 100644 index 000000000..e80836701 --- /dev/null +++ b/packages/interface-record/package.json @@ -0,0 +1,136 @@ +{ + "name": "@libp2p/interface-record", + "version": "0.0.1", + "description": "Record interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-record#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-peer-id": "~0.0.0" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/record/index.ts b/packages/interface-record/src/index.ts similarity index 92% rename from packages/libp2p-interfaces/src/record/index.ts rename to packages/interface-record/src/index.ts index a5ce29ed8..953910004 100644 --- a/packages/libp2p-interfaces/src/record/index.ts +++ b/packages/interface-record/src/index.ts @@ -1,4 +1,4 @@ -import type { PeerId } from '../peer-id/index.js' +import type { PeerId } from '@libp2p/interface-peer-id' /** * Record is the base implementation of a record that can be used as the payload of a libp2p envelope. diff --git a/packages/libp2p-tracked-map/tsconfig.json b/packages/interface-record/tsconfig.json similarity index 83% rename from packages/libp2p-tracked-map/tsconfig.json rename to packages/interface-record/tsconfig.json index d59d66e96..9da008198 100644 --- a/packages/libp2p-tracked-map/tsconfig.json +++ b/packages/interface-record/tsconfig.json @@ -9,7 +9,7 @@ ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-peer-id" } ] } diff --git a/packages/interface-registrar/LICENSE b/packages/interface-registrar/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-registrar/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-registrar/LICENSE-APACHE b/packages/interface-registrar/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-registrar/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-registrar/LICENSE-MIT b/packages/interface-registrar/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-registrar/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-registrar/README.md b/packages/interface-registrar/README.md new file mode 100644 index 000000000..f23c9dfa7 --- /dev/null +++ b/packages/interface-registrar/README.md @@ -0,0 +1,28 @@ +# @libp2p/interface-registrar + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Registrar interface for libp2p + +## Table of contents + +- [Install](#install) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-registrar +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-registrar/package.json b/packages/interface-registrar/package.json new file mode 100644 index 000000000..d5e85dabc --- /dev/null +++ b/packages/interface-registrar/package.json @@ -0,0 +1,137 @@ +{ + "name": "@libp2p/interface-registrar", + "version": "0.0.1", + "description": "Registrar interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-registrar#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-peer-id": "~0.0.0" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/interface-registrar/src/index.ts b/packages/interface-registrar/src/index.ts new file mode 100644 index 000000000..3b772595f --- /dev/null +++ b/packages/interface-registrar/src/index.ts @@ -0,0 +1,73 @@ +import type { Connection, Stream } from '@libp2p/interface-connection' +import type { PeerId } from '@libp2p/interface-peer-id' + +export interface IncomingStreamData { + protocol: string + stream: Stream + connection: Connection +} + +export interface StreamHandler { + (data: IncomingStreamData): void +} + +export interface StreamHandlerOptions { + /** + * How many streams can be open for this protocol at the same time on each connection (default: 1) + */ + maxConcurrentStreams?: number +} + +export interface StreamHandlerRecord { + handler: StreamHandler + options: StreamHandlerOptions +} + +export interface Registrar { + getProtocols: () => string[] + handle: (protocol: string, handler: StreamHandler, options?: StreamHandlerOptions) => Promise + unhandle: (protocol: string) => Promise + getHandler: (protocol: string) => StreamHandlerRecord + + register: (protocol: string, topology: Topology) => Promise + unregister: (id: string) => void + getTopologies: (protocol: string) => Topology[] +} + +export interface onConnectHandler { + (peerId: PeerId, conn: Connection): void +} + +export interface onDisconnectHandler { + (peerId: PeerId, conn?: Connection): void +} + +export interface TopologyInit { + /** + * minimum needed connections + */ + min?: number + + /** + * maximum needed connections + */ + max?: number + onConnect?: onConnectHandler + onDisconnect?: onDisconnectHandler +} + +export interface Topology { + min: number + max: number + peers: Set + + onConnect: (peerId: PeerId, conn: Connection) => void + onDisconnect: (peerId: PeerId) => void + setRegistrar: (registrar: Registrar) => Promise +} + +export const topologySymbol = Symbol.for('@libp2p/topology') + +export function isTopology (other: any): other is Topology { + return other != null && Boolean(other[topologySymbol]) +} diff --git a/packages/libp2p-peer-id-factory/tsconfig.json b/packages/interface-registrar/tsconfig.json similarity index 71% rename from packages/libp2p-peer-id-factory/tsconfig.json rename to packages/interface-registrar/tsconfig.json index a58dc440b..92a8421e0 100644 --- a/packages/libp2p-peer-id-factory/tsconfig.json +++ b/packages/interface-registrar/tsconfig.json @@ -9,10 +9,10 @@ ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-connection" }, { - "path": "../libp2p-peer-id" + "path": "../interface-peer-id" } ] } diff --git a/packages/interface-stream-muxer-compliance-tests/LICENSE b/packages/interface-stream-muxer-compliance-tests/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-stream-muxer-compliance-tests/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-stream-muxer-compliance-tests/LICENSE-APACHE b/packages/interface-stream-muxer-compliance-tests/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-stream-muxer-compliance-tests/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-stream-muxer-compliance-tests/LICENSE-MIT b/packages/interface-stream-muxer-compliance-tests/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-stream-muxer-compliance-tests/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-stream-muxer-compliance-tests/README.md b/packages/interface-stream-muxer-compliance-tests/README.md new file mode 100644 index 000000000..21cc96d59 --- /dev/null +++ b/packages/interface-stream-muxer-compliance-tests/README.md @@ -0,0 +1,47 @@ +# @libp2p/interface-stream-muxer-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p Stream Muxer interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-stream-muxer-compliance-tests +``` + +## Usage + +```js +import tests from '@libp2p/interface-stream-muxer-compliance-tests' + +describe('your stream muxer implementation', () => { + tests({ + // Options should be passed to your implementation + async setup (options) { + return new YourImplementation() + }, + async teardown () { + // cleanup resources created by setup() + } + }) +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-stream-muxer-compliance-tests/package.json b/packages/interface-stream-muxer-compliance-tests/package.json new file mode 100644 index 000000000..26d066e96 --- /dev/null +++ b/packages/interface-stream-muxer-compliance-tests/package.json @@ -0,0 +1,148 @@ +{ + "name": "@libp2p/interface-stream-muxer-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p Stream Muxer interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-stream-muxer-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/components": "~0.0.0", + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-stream-muxer": "~0.0.0", + "abortable-iterator": "^4.0.2", + "aegir": "^37.0.17", + "delay": "^5.0.0", + "it-all": "^1.0.6", + "it-drain": "^1.0.5", + "it-map": "^1.0.6", + "it-pair": "^2.0.2", + "it-pipe": "^2.0.3", + "it-stream-types": "^1.0.4", + "p-defer": "^4.0.0", + "p-limit": "^4.0.0", + "uint8arrays": "^3.0.0" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/stream-muxer/base-test.ts b/packages/interface-stream-muxer-compliance-tests/src/base-test.ts similarity index 95% rename from packages/libp2p-interface-compliance-tests/src/stream-muxer/base-test.ts rename to packages/interface-stream-muxer-compliance-tests/src/base-test.ts index b14113519..21e8170d6 100644 --- a/packages/libp2p-interface-compliance-tests/src/stream-muxer/base-test.ts +++ b/packages/interface-stream-muxer-compliance-tests/src/base-test.ts @@ -7,13 +7,13 @@ import all from 'it-all' import defer from 'p-defer' import { toString as uint8ArrayToString } from 'uint8arrays/to-string' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { isValidTick } from '../utils/is-valid-tick.js' +import { isValidTick } from '@libp2p/interface-compliance-tests/is-valid-tick' import type { DeferredPromise } from 'p-defer' -import type { TestSetup } from '../index.js' -import type { Stream } from '@libp2p/interfaces/connection' -import type { StreamMuxerFactory } from '@libp2p/interfaces/stream-muxer' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Stream } from '@libp2p/interface-connection' +import type { StreamMuxerFactory } from '@libp2p/interface-stream-muxer' import type { Source, Duplex } from 'it-stream-types' -import { Components } from '@libp2p/interfaces/components' +import { Components } from '@libp2p/components' async function drainAndClose (stream: Duplex) { return await pipe([], stream, drain) diff --git a/packages/libp2p-interface-compliance-tests/src/stream-muxer/close-test.ts b/packages/interface-stream-muxer-compliance-tests/src/close-test.ts similarity index 97% rename from packages/libp2p-interface-compliance-tests/src/stream-muxer/close-test.ts rename to packages/interface-stream-muxer-compliance-tests/src/close-test.ts index 9ec44b186..7a880961e 100644 --- a/packages/libp2p-interface-compliance-tests/src/stream-muxer/close-test.ts +++ b/packages/interface-stream-muxer-compliance-tests/src/close-test.ts @@ -6,9 +6,9 @@ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import drain from 'it-drain' import { expect } from 'aegir/chai' import delay from 'delay' -import type { TestSetup } from '../index.js' -import type { StreamMuxerFactory } from '@libp2p/interfaces/stream-muxer' -import { Components } from '@libp2p/interfaces/components' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { StreamMuxerFactory } from '@libp2p/interface-stream-muxer' +import { Components } from '@libp2p/components' import pDefer from 'p-defer' import all from 'it-all' diff --git a/packages/libp2p-interface-compliance-tests/src/stream-muxer/index.ts b/packages/interface-stream-muxer-compliance-tests/src/index.ts similarity index 72% rename from packages/libp2p-interface-compliance-tests/src/stream-muxer/index.ts rename to packages/interface-stream-muxer-compliance-tests/src/index.ts index dea7d648f..8b2d57a19 100644 --- a/packages/libp2p-interface-compliance-tests/src/stream-muxer/index.ts +++ b/packages/interface-stream-muxer-compliance-tests/src/index.ts @@ -2,8 +2,8 @@ import baseTest from './base-test.js' import closeTest from './close-test.js' import stressTest from './stress-test.js' import megaStressTest from './mega-stress-test.js' -import type { TestSetup } from '../index.js' -import type { StreamMuxerFactory } from '@libp2p/interfaces/stream-muxer' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { StreamMuxerFactory } from '@libp2p/interface-stream-muxer' export default (common: TestSetup) => { describe('interface-stream-muxer', () => { diff --git a/packages/libp2p-interface-compliance-tests/src/stream-muxer/mega-stress-test.ts b/packages/interface-stream-muxer-compliance-tests/src/mega-stress-test.ts similarity index 76% rename from packages/libp2p-interface-compliance-tests/src/stream-muxer/mega-stress-test.ts rename to packages/interface-stream-muxer-compliance-tests/src/mega-stress-test.ts index 6e52930e9..3ec38d7a0 100644 --- a/packages/libp2p-interface-compliance-tests/src/stream-muxer/mega-stress-test.ts +++ b/packages/interface-stream-muxer-compliance-tests/src/mega-stress-test.ts @@ -1,7 +1,7 @@ import spawn from './spawner.js' -import type { TestSetup } from '../index.js' -import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer' -import { Components } from '@libp2p/interfaces/components' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface-stream-muxer' +import { Components } from '@libp2p/components' export default (common: TestSetup) => { const createMuxer = async (init?: StreamMuxerInit): Promise => { diff --git a/packages/libp2p-interface-compliance-tests/src/stream-muxer/spawner.ts b/packages/interface-stream-muxer-compliance-tests/src/spawner.ts similarity index 98% rename from packages/libp2p-interface-compliance-tests/src/stream-muxer/spawner.ts rename to packages/interface-stream-muxer-compliance-tests/src/spawner.ts index d7670ae56..9d93da9d6 100644 --- a/packages/libp2p-interface-compliance-tests/src/stream-muxer/spawner.ts +++ b/packages/interface-stream-muxer-compliance-tests/src/spawner.ts @@ -5,7 +5,7 @@ import pLimit from 'p-limit' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import drain from 'it-drain' import all from 'it-all' -import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interfaces/stream-muxer' +import type { StreamMuxer, StreamMuxerInit } from '@libp2p/interface-stream-muxer' export default async (createMuxer: (init?: StreamMuxerInit) => Promise, nStreams: number, nMsg: number, limit?: number) => { const [dialerSocket, listenerSocket] = duplexPair() diff --git a/packages/libp2p-interface-compliance-tests/src/stream-muxer/stress-test.ts b/packages/interface-stream-muxer-compliance-tests/src/stress-test.ts similarity index 89% rename from packages/libp2p-interface-compliance-tests/src/stream-muxer/stress-test.ts rename to packages/interface-stream-muxer-compliance-tests/src/stress-test.ts index 117ac5743..6db568f87 100644 --- a/packages/libp2p-interface-compliance-tests/src/stream-muxer/stress-test.ts +++ b/packages/interface-stream-muxer-compliance-tests/src/stress-test.ts @@ -1,7 +1,7 @@ import spawn from './spawner.js' -import type { TestSetup } from '../index.js' -import type { StreamMuxerFactory, StreamMuxerInit, StreamMuxer } from '@libp2p/interfaces/stream-muxer' -import { Components } from '@libp2p/interfaces/components' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { StreamMuxerFactory, StreamMuxerInit, StreamMuxer } from '@libp2p/interface-stream-muxer' +import { Components } from '@libp2p/components' export default (common: TestSetup) => { const createMuxer = async (init?: StreamMuxerInit): Promise => { diff --git a/packages/interface-stream-muxer-compliance-tests/tsconfig.json b/packages/interface-stream-muxer-compliance-tests/tsconfig.json new file mode 100644 index 000000000..467d95314 --- /dev/null +++ b/packages/interface-stream-muxer-compliance-tests/tsconfig.json @@ -0,0 +1,21 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src", + "test" + ], + "references": [ + { + "path": "../interface-compliance-tests" + }, + { + "path": "../interface-connection" + }, + { + "path": "../interface-stream-muxer" + } + ] +} diff --git a/packages/interface-stream-muxer/LICENSE b/packages/interface-stream-muxer/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-stream-muxer/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-stream-muxer/LICENSE-APACHE b/packages/interface-stream-muxer/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-stream-muxer/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-stream-muxer/LICENSE-MIT b/packages/interface-stream-muxer/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-stream-muxer/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/stream-muxer/README.md b/packages/interface-stream-muxer/README.md similarity index 57% rename from packages/libp2p-interfaces/src/stream-muxer/README.md rename to packages/interface-stream-muxer/README.md index ea440a313..1f38b5ebb 100644 --- a/packages/libp2p-interfaces/src/stream-muxer/README.md +++ b/packages/interface-stream-muxer/README.md @@ -1,6 +1,29 @@ -# interface-stream-muxer +# @libp2p/interface-stream-muxer -> A test suite and interface you can use to implement a stream muxer. "A one stop shop for all your muxing needs" +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Stream Muxer interface for libp2p + +## Table of contents + +- [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [Usage](#usage) +- [API](#api) + - [`const muxer = new Muxer([options])`](#const-muxer--new-muxeroptions) + - [`muxer.onStream`](#muxeronstream) + - [`muxer.onStreamEnd`](#muxeronstreamend) + - [`const stream = muxer.newStream([options])`](#const-stream--muxernewstreamoptions) + - [`const streams = muxer.streams`](#const-streams--muxerstreams) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-stream-muxer +``` The primary goal of this module is to enable developers to pick and swap their stream muxing module as they see fit for their application, without having to go through shims or compatibility issues. This module and test suite was heavily inspired by [abstract-blob-store](https://github.com/maxogden/abstract-blob-store). @@ -47,7 +70,7 @@ A valid (one that follows this abstraction) stream muxer, must implement the fol ### `const muxer = new Muxer([options])` -Create a new _duplex_ stream that can be piped together with a connection in order to allow multiplexed communications. +Create a new *duplex* stream that can be piped together with a connection in order to allow multiplexed communications. e.g. @@ -64,27 +87,27 @@ pipe(conn, muxer, conn) // conn is duplex connection to another peer `options` is an optional `Object` that may have the following properties: -* `onStream` - A function called when receiving a new stream from the remote. e.g. - ```js - // Receive a new stream on the muxed connection - const onStream = stream => { - // Read from this stream and write back to it (echo server) - pipe( - stream, - source => (async function * () { - for await (const data of source) yield data - })() - stream - ) - } - const muxer = new Muxer({ onStream }) - // ... - ``` - **Note:** The `onStream` function can be passed in place of the `options` object. i.e. - ```js - new Mplex(stream => { /* ... */ }) - ``` -* `onStreamEnd` - A function called when a stream ends. +- `onStream` - A function called when receiving a new stream from the remote. e.g. + ```js + // Receive a new stream on the muxed connection + const onStream = stream => { + // Read from this stream and write back to it (echo server) + pipe( + stream, + source => (async function * () { + for await (const data of source) yield data + })() + stream + ) + } + const muxer = new Muxer({ onStream }) + // ... + ``` + **Note:** The `onStream` function can be passed in place of the `options` object. i.e. + ```js + new Mplex(stream => { /* ... */ }) + ``` +- `onStreamEnd` - A function called when a stream ends. ```js // Get notified when a stream has ended const onStreamEnd = stream => { @@ -92,16 +115,16 @@ pipe(conn, muxer, conn) // conn is duplex connection to another peer } const muxer = new Muxer({ onStreamEnd, ... }) ``` -* `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) which can be used to abort the muxer, _including_ all of it's multiplexed connections. e.g. - ```js - const controller = new AbortController() - const muxer = new Muxer({ signal: controller.signal }) +- `signal` - An [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) which can be used to abort the muxer, *including* all of it's multiplexed connections. e.g. + ```js + const controller = new AbortController() + const muxer = new Muxer({ signal: controller.signal }) - pipe(conn, muxer, conn) + pipe(conn, muxer, conn) - controller.abort() - ``` -* `maxMsgSize` - The maximum size in bytes the data field of multiplexed messages may contain (default 1MB) + controller.abort() + ``` +- `maxMsgSize` - The maximum size in bytes the data field of multiplexed messages may contain (default 1MB) ### `muxer.onStream` @@ -147,3 +170,14 @@ muxer.streams.map(stream => { console.log(stream.id) }) ``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-interfaces/src/stream-muxer/img/badge.png b/packages/interface-stream-muxer/img/badge.png similarity index 100% rename from packages/libp2p-interfaces/src/stream-muxer/img/badge.png rename to packages/interface-stream-muxer/img/badge.png diff --git a/packages/libp2p-interfaces/src/stream-muxer/img/badge.sketch b/packages/interface-stream-muxer/img/badge.sketch similarity index 100% rename from packages/libp2p-interfaces/src/stream-muxer/img/badge.sketch rename to packages/interface-stream-muxer/img/badge.sketch diff --git a/packages/libp2p-interfaces/src/stream-muxer/img/badge.svg b/packages/interface-stream-muxer/img/badge.svg similarity index 100% rename from packages/libp2p-interfaces/src/stream-muxer/img/badge.svg rename to packages/interface-stream-muxer/img/badge.svg diff --git a/packages/interface-stream-muxer/package.json b/packages/interface-stream-muxer/package.json new file mode 100644 index 000000000..96a74c184 --- /dev/null +++ b/packages/interface-stream-muxer/package.json @@ -0,0 +1,139 @@ +{ + "name": "@libp2p/interface-stream-muxer", + "version": "0.0.1", + "description": "Stream Muxer interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-stream-muxer#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/components": "~0.0.0", + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "it-stream-types": "^1.0.4" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/stream-muxer/index.ts b/packages/interface-stream-muxer/src/index.ts similarity index 79% rename from packages/libp2p-interfaces/src/stream-muxer/index.ts rename to packages/interface-stream-muxer/src/index.ts index e7bf058ca..994e04e83 100644 --- a/packages/libp2p-interfaces/src/stream-muxer/index.ts +++ b/packages/interface-stream-muxer/src/index.ts @@ -1,7 +1,7 @@ import type { Duplex } from 'it-stream-types' -import type { Components } from '../components.js' -import type { Stream } from '../connection/index.js' -import type { AbortOptions } from '../index.js' +import type { Components } from '@libp2p/components' +import type { Stream } from '@libp2p/interface-connection' +import type { AbortOptions } from '@libp2p/interfaces' export interface StreamMuxerFactory { protocol: string diff --git a/packages/libp2p-multistream-select/tsconfig.json b/packages/interface-stream-muxer/tsconfig.json similarity index 73% rename from packages/libp2p-multistream-select/tsconfig.json rename to packages/interface-stream-muxer/tsconfig.json index d96dd69f8..181d553f6 100644 --- a/packages/libp2p-multistream-select/tsconfig.json +++ b/packages/interface-stream-muxer/tsconfig.json @@ -9,10 +9,10 @@ ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-connection" }, { - "path": "../libp2p-logger" + "path": "../interfaces" } ] } diff --git a/packages/interface-transport-compliance-tests/LICENSE b/packages/interface-transport-compliance-tests/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-transport-compliance-tests/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-transport-compliance-tests/LICENSE-APACHE b/packages/interface-transport-compliance-tests/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-transport-compliance-tests/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-transport-compliance-tests/LICENSE-MIT b/packages/interface-transport-compliance-tests/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-transport-compliance-tests/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interface-transport-compliance-tests/README.md b/packages/interface-transport-compliance-tests/README.md new file mode 100644 index 000000000..67173f266 --- /dev/null +++ b/packages/interface-transport-compliance-tests/README.md @@ -0,0 +1,47 @@ +# @libp2p/interface-transport-compliance-tests + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Compliance tests for implementations of the libp2p Transport interface + +## Table of contents + +- [Install](#install) +- [Usage](#usage) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-transport-compliance-tests +``` + +## Usage + +```js +import tests from '@libp2p/interface-transport-compliance-tests' + +describe('your transport implementation', () => { + tests({ + // Options should be passed to your implementation + async setup (options) { + return new YourImplementation() + }, + async teardown () { + // cleanup resources created by setup() + } + }) +}) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interface-transport-compliance-tests/package.json b/packages/interface-transport-compliance-tests/package.json new file mode 100644 index 000000000..7199f1daa --- /dev/null +++ b/packages/interface-transport-compliance-tests/package.json @@ -0,0 +1,147 @@ +{ + "name": "@libp2p/interface-transport-compliance-tests", + "version": "0.0.1", + "description": "Compliance tests for implementations of the libp2p Transport interface", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-transport-compliance-tests#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-compliance-tests": "^2.0.0", + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interface-mocks": "~0.0.0", + "@libp2p/interface-registrar": "~0.0.0", + "@libp2p/interface-transport": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "@multiformats/multiaddr": "^10.2.0", + "aegir": "^37.0.17", + "it-all": "^1.0.6", + "it-drain": "^1.0.5", + "it-pipe": "^2.0.3", + "p-defer": "^4.0.0", + "p-wait-for": "^4.1.0", + "sinon": "^14.0.0", + "uint8arrays": "^3.0.0" + } +} diff --git a/packages/libp2p-interface-compliance-tests/src/transport/dial-test.ts b/packages/interface-transport-compliance-tests/src/dial-test.ts similarity index 92% rename from packages/libp2p-interface-compliance-tests/src/transport/dial-test.ts rename to packages/interface-transport-compliance-tests/src/dial-test.ts index 65fec3381..f60c5616f 100644 --- a/packages/libp2p-interface-compliance-tests/src/transport/dial-test.ts +++ b/packages/interface-transport-compliance-tests/src/dial-test.ts @@ -1,18 +1,17 @@ import { expect } from 'aegir/chai' -import { isValidTick } from '../utils/is-valid-tick.js' -import { mockUpgrader } from '../mocks/upgrader.js' -import { mockRegistrar } from '../mocks/registrar.js' +import { isValidTick } from '@libp2p/interface-compliance-tests/is-valid-tick' +import { mockUpgrader, mockRegistrar } from '@libp2p/interface-mocks' import all from 'it-all' import { pipe } from 'it-pipe' import { AbortError } from '@libp2p/interfaces/errors' import sinon from 'sinon' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import drain from 'it-drain' -import type { TestSetup } from '../index.js' -import type { Transport, Listener, Upgrader } from '@libp2p/interfaces/transport' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Transport, Listener, Upgrader } from '@libp2p/interface-transport' import type { TransportTestFixtures, Connector } from './index.js' import type { Multiaddr } from '@multiformats/multiaddr' -import type { Registrar } from '@libp2p/interfaces/registrar' +import type { Registrar } from '@libp2p/interface-registrar' export default (common: TestSetup) => { describe('dial', () => { diff --git a/packages/libp2p-interface-compliance-tests/src/transport/filter-test.ts b/packages/interface-transport-compliance-tests/src/filter-test.ts similarity index 82% rename from packages/libp2p-interface-compliance-tests/src/transport/filter-test.ts rename to packages/interface-transport-compliance-tests/src/filter-test.ts index 83eb16685..3145f59f2 100644 --- a/packages/libp2p-interface-compliance-tests/src/transport/filter-test.ts +++ b/packages/interface-transport-compliance-tests/src/filter-test.ts @@ -1,6 +1,6 @@ import { expect } from 'aegir/chai' -import type { TestSetup } from '../index.js' -import type { Transport } from '@libp2p/interfaces/transport' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Transport } from '@libp2p/interface-transport' import type { TransportTestFixtures } from './index.js' import type { Multiaddr } from '@multiformats/multiaddr' diff --git a/packages/libp2p-interface-compliance-tests/src/transport/index.ts b/packages/interface-transport-compliance-tests/src/index.ts similarity index 80% rename from packages/libp2p-interface-compliance-tests/src/transport/index.ts rename to packages/interface-transport-compliance-tests/src/index.ts index 15fc48fe1..0301a6833 100644 --- a/packages/libp2p-interface-compliance-tests/src/transport/index.ts +++ b/packages/interface-transport-compliance-tests/src/index.ts @@ -1,8 +1,8 @@ import dial from './dial-test.js' import listen from './listen-test.js' import filter from './filter-test.js' -import type { TestSetup } from '../index.js' -import type { Transport } from '@libp2p/interfaces/transport' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Transport } from '@libp2p/interface-transport' import type { Multiaddr } from '@multiformats/multiaddr' export interface Connector { diff --git a/packages/libp2p-interface-compliance-tests/src/transport/listen-test.ts b/packages/interface-transport-compliance-tests/src/listen-test.ts similarity index 92% rename from packages/libp2p-interface-compliance-tests/src/transport/listen-test.ts rename to packages/interface-transport-compliance-tests/src/listen-test.ts index f6199da0c..073909df9 100644 --- a/packages/libp2p-interface-compliance-tests/src/transport/listen-test.ts +++ b/packages/interface-transport-compliance-tests/src/listen-test.ts @@ -4,18 +4,17 @@ import sinon from 'sinon' import pWaitFor from 'p-wait-for' import { pipe } from 'it-pipe' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { isValidTick } from '../utils/is-valid-tick.js' -import { mockUpgrader } from '../mocks/upgrader.js' +import { isValidTick } from '@libp2p/interface-compliance-tests/is-valid-tick' +import { mockUpgrader, mockRegistrar } from '@libp2p/interface-mocks' import defer from 'p-defer' -import { mockRegistrar } from '../mocks/registrar.js' import drain from 'it-drain' import { CustomEvent } from '@libp2p/interfaces/events' -import type { TestSetup } from '../index.js' -import type { Transport, Upgrader } from '@libp2p/interfaces/transport' +import type { TestSetup } from '@libp2p/interface-compliance-tests' +import type { Transport, Upgrader } from '@libp2p/interface-transport' import type { TransportTestFixtures } from './index.js' import type { Multiaddr } from '@multiformats/multiaddr' -import type { Connection } from '@libp2p/interfaces/connection' -import type { Registrar } from '@libp2p/interfaces/registrar' +import type { Connection } from '@libp2p/interface-connection' +import type { Registrar } from '@libp2p/interface-registrar' export default (common: TestSetup) => { describe('listen', () => { diff --git a/packages/libp2p-interface-compliance-tests/tsconfig.json b/packages/interface-transport-compliance-tests/tsconfig.json similarity index 51% rename from packages/libp2p-interface-compliance-tests/tsconfig.json rename to packages/interface-transport-compliance-tests/tsconfig.json index 37d90abfc..0ac9c0854 100644 --- a/packages/libp2p-interface-compliance-tests/tsconfig.json +++ b/packages/interface-transport-compliance-tests/tsconfig.json @@ -9,22 +9,22 @@ ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-compliance-tests" }, { - "path": "../libp2p-logger" + "path": "../interface-connection" }, { - "path": "../libp2p-multistream-select" + "path": "../interface-mocks" }, { - "path": "../libp2p-peer-id" + "path": "../interface-registrar" }, { - "path": "../libp2p-peer-id-factory" + "path": "../interface-transport" }, { - "path": "../libp2p-pubsub" + "path": "../interfaces" } ] } diff --git a/packages/interface-transport/LICENSE b/packages/interface-transport/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interface-transport/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interface-transport/LICENSE-APACHE b/packages/interface-transport/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interface-transport/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interface-transport/LICENSE-MIT b/packages/interface-transport/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interface-transport/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/libp2p-interfaces/src/transport/README.md b/packages/interface-transport/README.md similarity index 81% rename from packages/libp2p-interfaces/src/transport/README.md rename to packages/interface-transport/README.md index 0187d157a..7b25a6acb 100644 --- a/packages/libp2p-interfaces/src/transport/README.md +++ b/packages/interface-transport/README.md @@ -1,7 +1,36 @@ -interface-transport -=================== - -> A test suite and interface you can use to implement a libp2p transport. A libp2p transport is understood as something that offers a dial and listen interface. +# @libp2p/interface-transport + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Transport interface for libp2p + +## Table of contents + +- [Install](#install) +- [Modules that implement the interface](#modules-that-implement-the-interface) +- [Badge](#badge) +- [How to use the battery of tests](#how-to-use-the-battery-of-tests) +- [Node.js](#nodejs) +- [API](#api) + - [Types](#types) + - [Upgrader](#upgrader) + - [MultiaddrConnection](#multiaddrconnection) + - [Creating a transport instance](#creating-a-transport-instance) + - [Dial to another peer](#dial-to-another-peer) + - [Canceling a dial](#canceling-a-dial) + - [Filtering Addresses](#filtering-addresses) + - [Create a listener](#create-a-listener) + - [Start a listener](#start-a-listener) + - [Get listener addrs](#get-listener-addrs) + - [Stop a listener](#stop-a-listener) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interface-transport +``` The primary goal of this module is to enable developers to pick and swap their transport module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by abstract-blob-store, interface-stream-muxer and others. @@ -9,7 +38,7 @@ Publishing a test suite as a module lets multiple modules all ensure compatibili The purpose of this interface is not to reinvent any wheels when it comes to dialing and listening to transports. Instead, it tries to provide a uniform API for several transports through a shimmed interface. -# Modules that implement the interface +## Modules that implement the interface - [js-libp2p-tcp](https://github.com/libp2p/js-libp2p-tcp) - [js-libp2p-webrtc-star](https://github.com/libp2p/js-libp2p-webrtc-star) @@ -19,13 +48,13 @@ The purpose of this interface is not to reinvent any wheels when it comes to dia - [js-libp2p-utp](https://github.com/libp2p/js-libp2p-utp) - [webrtc-explorer](https://github.com/diasdavid/webrtc-explorer) -# Badge +## Badge Include this badge in your readme if you make a module that is compatible with the interface-transport API. You can validate this by running the tests. ![](img/badge.png) -# How to use the battery of tests +## How to use the battery of tests ## Node.js @@ -70,7 +99,7 @@ describe('compliance', () => { }) ``` -# API +## API A valid transport (one that follows the interface defined) must implement the following API: @@ -93,7 +122,9 @@ A valid transport (one that follows the interface defined) must implement the fo ### Types #### Upgrader + Upgraders have 2 methods: `upgradeOutbound` and `upgradeInbound`. + - `upgradeOutbound` must be called and returned by `transport.dial`. - `upgradeInbound` must be called and the results must be passed to the `createListener` `handlerFunction` and the `connection` event handler, anytime a new connection is created. @@ -211,4 +242,15 @@ This method closes the listener so that no more connections can be opened on thi `options` is an optional object that may contain the following properties: - - `timeout` - A timeout value (in ms) after which all connections on this transport will be destroyed if the transport is not able to close gracefully. (e.g { timeout: 1000 }) +- `timeout` - A timeout value (in ms) after which all connections on this transport will be destroyed if the transport is not able to close gracefully. (e.g { timeout: 1000 }) + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-interfaces/src/transport/img/badge.png b/packages/interface-transport/img/badge.png similarity index 100% rename from packages/libp2p-interfaces/src/transport/img/badge.png rename to packages/interface-transport/img/badge.png diff --git a/packages/libp2p-interfaces/src/transport/img/badge.sketch b/packages/interface-transport/img/badge.sketch similarity index 100% rename from packages/libp2p-interfaces/src/transport/img/badge.sketch rename to packages/interface-transport/img/badge.sketch diff --git a/packages/libp2p-interfaces/src/transport/img/badge.svg b/packages/interface-transport/img/badge.svg similarity index 100% rename from packages/libp2p-interfaces/src/transport/img/badge.svg rename to packages/interface-transport/img/badge.svg diff --git a/packages/interface-transport/package.json b/packages/interface-transport/package.json new file mode 100644 index 000000000..29b2eff90 --- /dev/null +++ b/packages/interface-transport/package.json @@ -0,0 +1,139 @@ +{ + "name": "@libp2p/interface-transport", + "version": "0.0.1", + "description": "Transport interface for libp2p", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interface-transport#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "dependencies": { + "@libp2p/interface-connection": "~0.0.0", + "@libp2p/interfaces": "^2.0.0", + "@multiformats/multiaddr": "^10.2.0", + "it-stream-types": "^1.0.4" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/transport/index.ts b/packages/interface-transport/src/index.ts similarity index 82% rename from packages/libp2p-interfaces/src/transport/index.ts rename to packages/interface-transport/src/index.ts index a27f9b3cb..49c8260b7 100644 --- a/packages/libp2p-interfaces/src/transport/index.ts +++ b/packages/interface-transport/src/index.ts @@ -1,7 +1,7 @@ -import type { AbortOptions } from '../index.js' -import type { EventEmitter } from '../events.js' +import type { AbortOptions } from '@libp2p/interfaces' +import type { EventEmitter } from '@libp2p/interfaces/events' import type { Multiaddr } from '@multiformats/multiaddr' -import type { Connection } from '../connection/index.js' +import type { Connection, MultiaddrConnection } from '@libp2p/interface-connection' import type { Duplex } from 'it-stream-types' export const symbol = Symbol.for('@libp2p/transport') @@ -90,23 +90,6 @@ export interface Upgrader extends EventEmitter { upgradeInbound: (maConn: MultiaddrConnection) => Promise } -export interface MultiaddrConnectionTimeline { - open: number - upgraded?: number - close?: number -} - -/** - * A MultiaddrConnection is returned by transports after dialing - * a peer. It is a low-level primitive and is the raw connection - * without encryption or stream multiplexing. - */ -export interface MultiaddrConnection extends Duplex { - close: (err?: Error) => Promise - remoteAddr: Multiaddr - timeline: MultiaddrConnectionTimeline -} - export interface ProtocolHandler { (stream: Duplex, connection: Connection): void } diff --git a/packages/libp2p-topology/tsconfig.json b/packages/interface-transport/tsconfig.json similarity index 73% rename from packages/libp2p-topology/tsconfig.json rename to packages/interface-transport/tsconfig.json index d96dd69f8..181d553f6 100644 --- a/packages/libp2p-topology/tsconfig.json +++ b/packages/interface-transport/tsconfig.json @@ -9,10 +9,10 @@ ], "references": [ { - "path": "../libp2p-interfaces" + "path": "../interface-connection" }, { - "path": "../libp2p-logger" + "path": "../interfaces" } ] } diff --git a/packages/libp2p-interfaces/CHANGELOG.md b/packages/interfaces/CHANGELOG.md similarity index 100% rename from packages/libp2p-interfaces/CHANGELOG.md rename to packages/interfaces/CHANGELOG.md diff --git a/packages/interfaces/LICENSE b/packages/interfaces/LICENSE new file mode 100644 index 000000000..20ce483c8 --- /dev/null +++ b/packages/interfaces/LICENSE @@ -0,0 +1,4 @@ +This project is dual licensed under MIT and Apache-2.0. + +MIT: https://www.opensource.org/licenses/mit +Apache-2.0: https://www.apache.org/licenses/license-2.0 diff --git a/packages/interfaces/LICENSE-APACHE b/packages/interfaces/LICENSE-APACHE new file mode 100644 index 000000000..14478a3b6 --- /dev/null +++ b/packages/interfaces/LICENSE-APACHE @@ -0,0 +1,5 @@ +Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. diff --git a/packages/interfaces/LICENSE-MIT b/packages/interfaces/LICENSE-MIT new file mode 100644 index 000000000..72dc60d84 --- /dev/null +++ b/packages/interfaces/LICENSE-MIT @@ -0,0 +1,19 @@ +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/interfaces/README.md b/packages/interfaces/README.md new file mode 100644 index 000000000..cd24cb599 --- /dev/null +++ b/packages/interfaces/README.md @@ -0,0 +1,93 @@ +# @libp2p/interfaces + +[![test & maybe release](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml/badge.svg)](https://github.com/libp2p/js-libp2p-interfaces/actions/workflows/js-test-and-release.yml) + +> Common code shared by the various libp2p interfaces + +## Table of contents + +- [Install](#install) +- [Usage](#usage) + - [AbortError](#aborterror) + - [Events](#events) + - [AbortOptions](#abortoptions) + - [Startable](#startable) +- [License](#license) + - [Contribution](#contribution) + +## Install + +```console +$ npm i @libp2p/interfaces +``` + +## Usage + +### AbortError + +Throw an error with a `.code` property of `'ABORT_ERR'`: + +```js +import { AbortError } from '@libp2p/interfaces/errors' + +throw new AbortError() +``` + +### Events + +Typed events: + +```js +import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events' + +export interface MyEmitterEvents { + 'some-event': CustomEvent; +} + +class MyEmitter extends EventEmitter { + +} + +// later +const myEmitter = new MyEmitter() +myEmitter.addEventListener('some-event', (evt) => { + const num = evt.detail // <-- inferred as number +}) +``` + +### AbortOptions + +```js +import type { AbortOptions } from '@libp2p/interfaces' +``` + +### Startable + +Lifecycles for components + +```js +import { start, stop, isStartable } from '@libp2p/interfaces/startable' +import type { Startable } from '@libp2p/interfaces/startable' + +class MyStartable implements Startable { + // .. implementation methods +} + +const myStartable = new MyStartable() + +isStartable(myStartable) // returns true + +await start(myStartable) +await stop(myStartable) +``` + +## License + +Licensed under either of + +- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / ) +- MIT ([LICENSE-MIT](LICENSE-MIT) / ) + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/interfaces/package.json b/packages/interfaces/package.json new file mode 100644 index 000000000..f2e64fc2f --- /dev/null +++ b/packages/interfaces/package.json @@ -0,0 +1,161 @@ +{ + "name": "@libp2p/interfaces", + "version": "2.0.3", + "description": "Common code shared by the various libp2p interfaces", + "license": "Apache-2.0 OR MIT", + "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/interfaces#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" + }, + "bugs": { + "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" + }, + "keywords": [ + "interface", + "libp2p" + ], + "engines": { + "node": ">=16.0.0", + "npm": ">=7.0.0" + }, + "type": "module", + "types": "./dist/src/index.d.ts", + "typesVersions": { + "*": { + "*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ], + "src/*": [ + "*", + "dist/*", + "dist/src/*", + "dist/src/*/index" + ] + } + }, + "files": [ + "src", + "dist/src", + "!dist/test", + "!**/*.tsbuildinfo" + ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + }, + "./errors": { + "types": "./dist/src/errors.d.ts", + "import": "./dist/src/errors.js" + }, + "./events": { + "types": "./dist/src/events.d.ts", + "import": "./dist/src/events.js" + }, + "./startable": { + "types": "./dist/src/startable.d.ts", + "import": "./dist/src/startable.js" + } + }, + "eslintConfig": { + "extends": "ipfs", + "parserOptions": { + "sourceType": "module" + } + }, + "release": { + "branches": [ + "master" + ], + "plugins": [ + [ + "@semantic-release/commit-analyzer", + { + "preset": "conventionalcommits", + "releaseRules": [ + { + "breaking": true, + "release": "major" + }, + { + "revert": true, + "release": "patch" + }, + { + "type": "feat", + "release": "minor" + }, + { + "type": "fix", + "release": "patch" + }, + { + "type": "chore", + "release": "patch" + }, + { + "type": "docs", + "release": "patch" + }, + { + "type": "test", + "release": "patch" + }, + { + "scope": "no-release", + "release": false + } + ] + } + ], + [ + "@semantic-release/release-notes-generator", + { + "preset": "conventionalcommits", + "presetConfig": { + "types": [ + { + "type": "feat", + "section": "Features" + }, + { + "type": "fix", + "section": "Bug Fixes" + }, + { + "type": "chore", + "section": "Trivial Changes" + }, + { + "type": "docs", + "section": "Trivial Changes" + }, + { + "type": "test", + "section": "Tests" + } + ] + } + } + ], + "@semantic-release/changelog", + "@semantic-release/npm", + "@semantic-release/github", + "@semantic-release/git" + ] + }, + "scripts": { + "clean": "aegir clean", + "lint": "aegir lint", + "dep-check": "aegir dep-check", + "build": "aegir build", + "release": "aegir release" + }, + "devDependencies": { + "aegir": "^37.0.17" + } +} diff --git a/packages/libp2p-interfaces/src/errors.ts b/packages/interfaces/src/errors.ts similarity index 100% rename from packages/libp2p-interfaces/src/errors.ts rename to packages/interfaces/src/errors.ts diff --git a/packages/libp2p-interfaces/src/events.ts b/packages/interfaces/src/events.ts similarity index 100% rename from packages/libp2p-interfaces/src/events.ts rename to packages/interfaces/src/events.ts diff --git a/packages/libp2p-interfaces/src/index.ts b/packages/interfaces/src/index.ts similarity index 100% rename from packages/libp2p-interfaces/src/index.ts rename to packages/interfaces/src/index.ts diff --git a/packages/libp2p-interfaces/src/startable.ts b/packages/interfaces/src/startable.ts similarity index 100% rename from packages/libp2p-interfaces/src/startable.ts rename to packages/interfaces/src/startable.ts diff --git a/packages/interfaces/tsconfig.json b/packages/interfaces/tsconfig.json new file mode 100644 index 000000000..5fe8ea40d --- /dev/null +++ b/packages/interfaces/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "aegir/src/config/tsconfig.aegir.json", + "compilerOptions": { + "outDir": "dist" + }, + "include": [ + "src" + ] +} diff --git a/packages/libp2p-connection/CHANGELOG.md b/packages/libp2p-connection/CHANGELOG.md deleted file mode 100644 index 58ab42f78..000000000 --- a/packages/libp2p-connection/CHANGELOG.md +++ /dev/null @@ -1,188 +0,0 @@ -## [@libp2p/connection-v2.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v2.0.2...@libp2p/connection-v2.0.3) (2022-05-24) - - -### Bug Fixes - -* accept abort options in connection.newStream ([#219](https://github.com/libp2p/js-libp2p-interfaces/issues/219)) ([8bfcbc9](https://github.com/libp2p/js-libp2p-interfaces/commit/8bfcbc9ee883336f213cdfc83e477549ca368df5)) - -## [@libp2p/connection-v2.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v2.0.1...@libp2p/connection-v2.0.2) (2022-05-23) - - -### Bug Fixes - -* make stream return types synchronous ([#217](https://github.com/libp2p/js-libp2p-interfaces/issues/217)) ([2fe61b7](https://github.com/libp2p/js-libp2p-interfaces/commit/2fe61b7fbeda2e549edf095a927d623aa8eb476b)) - -## [@libp2p/connection-v2.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v2.0.0...@libp2p/connection-v2.0.1) (2022-05-20) - - -### Bug Fixes - -* update sibling deps ([#216](https://github.com/libp2p/js-libp2p-interfaces/issues/216)) ([0ceca65](https://github.com/libp2p/js-libp2p-interfaces/commit/0ceca658901e92de554c828105b328b88a1416f8)) - -## [@libp2p/connection-v2.0.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.1.5...@libp2p/connection-v2.0.0) (2022-05-20) - - -### ⚠ BREAKING CHANGES - -* This adds closeWrite and closeRead checks in the tests, which will cause test failures for muxers that don't implement those - -### Bug Fixes - -* close streams when connection is closed ([#214](https://github.com/libp2p/js-libp2p-interfaces/issues/214)) ([88fcd58](https://github.com/libp2p/js-libp2p-interfaces/commit/88fcd586276e03dd740c7095f05e21754ac1f3b5)), closes [#90](https://github.com/libp2p/js-libp2p-interfaces/issues/90) -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/connection-v1.1.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.1.4...@libp2p/connection-v1.1.5) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/connection-v1.1.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.1.3...@libp2p/connection-v1.1.4) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/connection-v1.1.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.1.2...@libp2p/connection-v1.1.3) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/connection-v1.1.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.1.1...@libp2p/connection-v1.1.2) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/connection-v1.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.1.0...@libp2p/connection-v1.1.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## [@libp2p/connection-v1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.0.4...@libp2p/connection-v1.1.0) (2022-02-09) - - -### Features - -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) - -## [@libp2p/connection-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.0.3...@libp2p/connection-v1.0.4) (2022-01-15) - - -### Trivial Changes - -* update project config ([#149](https://github.com/libp2p/js-libp2p-interfaces/issues/149)) ([6eb8556](https://github.com/libp2p/js-libp2p-interfaces/commit/6eb85562c0da167d222808da10a7914daf12970b)) - -## [@libp2p/connection-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.0.2...@libp2p/connection-v1.0.3) (2022-01-14) - - -### Bug Fixes - -* update it-* deps to ts versions ([#148](https://github.com/libp2p/js-libp2p-interfaces/issues/148)) ([7a6fdd7](https://github.com/libp2p/js-libp2p-interfaces/commit/7a6fdd7622ce2870b89dbb849ab421d0dd714b43)) - -## [@libp2p/connection-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/connection-v1.0.1...@libp2p/connection-v1.0.2) (2022-01-08) - - -### Trivial Changes - -* add semantic release config ([#141](https://github.com/libp2p/js-libp2p-interfaces/issues/141)) ([5f0de59](https://github.com/libp2p/js-libp2p-interfaces/commit/5f0de59136b6343d2411abb2d6a4dd2cd0b7efe4)) -* update package versions ([#140](https://github.com/libp2p/js-libp2p-interfaces/issues/140)) ([cd844f6](https://github.com/libp2p/js-libp2p-interfaces/commit/cd844f6e39f4ee50d006e86eac8dadf696900eb5)) - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 0.2.0 (2022-01-04) - - -### Bug Fixes - -* update dialer tests ([#116](https://github.com/libp2p/js-libp2p-interfaces/issues/116)) ([c679729](https://github.com/libp2p/js-libp2p-interfaces/commit/c679729113feb963ff27815fcafd7af51f722df7)) - - -### chore - -* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) - - -### Features - -* add auto-publish ([7aede5d](https://github.com/libp2p/js-libp2p-interfaces/commit/7aede5df39ea6b5f243348ec9a212b3e33c16a81)) -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) -* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) -* update package names ([#133](https://github.com/libp2p/js-libp2p-interfaces/issues/133)) ([337adc9](https://github.com/libp2p/js-libp2p-interfaces/commit/337adc9a9bc0278bdae8cbce9c57d07a83c8b5c2)) - - -### BREAKING CHANGES - -* requires node 15+ -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out - - - - - -## [0.3.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-connection@0.3.0...libp2p-connection@0.3.1) (2022-01-02) - -**Note:** Version bump only for package libp2p-connection - - - - - -# [0.3.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-connection@0.2.0...libp2p-connection@0.3.0) (2022-01-02) - - -### Bug Fixes - -* update dialer tests ([#116](https://github.com/libp2p/js-libp2p-interfaces/issues/116)) ([c679729](https://github.com/libp2p/js-libp2p-interfaces/commit/c679729113feb963ff27815fcafd7af51f722df7)) - - -### Features - -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) - - - - - -# [0.2.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-connection@0.1.0...libp2p-connection@0.2.0) (2021-12-02) - - -### chore - -* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) - - -### BREAKING CHANGES - -* requires node 15+ - - - - - -# 0.1.0 (2021-11-22) - - -### Features - -* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) - - -### BREAKING CHANGES - -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out diff --git a/packages/libp2p-connection/README.md b/packages/libp2p-connection/README.md deleted file mode 100644 index fa99846e7..000000000 --- a/packages/libp2p-connection/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# libp2p-connection - -> Contains an implementation of the [Connection](https://github.com/libp2p/js-libp2p-interfaces/blob/master/packages/libp2p-interfaces/src/connection/index.ts) interface - -## Table of contents - -- [Usage](#usage) -- [Contribute](#contribute) -- [License](#license) - -## Usage - -```console -npm i libp2p-connection -``` - -```javascript -import { Connection } from '@libp2p/connection' - -const connection = new Connection({ ... }) -const stream = connection.newStream([ '/my-protocol/v1.0.0' ]) -``` - -## Contribute - -The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: - - - Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - - **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - - **Add tests**. There can never be enough tests. - -## License - -[Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) © Protocol Labs \ No newline at end of file diff --git a/packages/libp2p-connection/package.json b/packages/libp2p-connection/package.json deleted file mode 100644 index 970060b31..000000000 --- a/packages/libp2p-connection/package.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "name": "@libp2p/connection", - "version": "2.0.3", - "description": "JS Libp2p connections", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-connection#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "interface", - "libp2p" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "typesVersions": { - "*": { - "*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ], - "src/*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ] - } - }, - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js", - "types": "./dist/src/index.d.ts" - }, - "./status": { - "import": "./dist/src/status.js", - "types": "./dist/src/status.d.ts" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - } - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "release": "aegir release" - }, - "dependencies": { - "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", - "@multiformats/multiaddr": "^10.1.5", - "err-code": "^3.0.1" - }, - "devDependencies": { - "@libp2p/interface-compliance-tests": "^2.0.0", - "@libp2p/peer-id-factory": "^1.0.0", - "aegir": "^37.0.7", - "it-pair": "^2.0.2" - } -} diff --git a/packages/libp2p-connection/src/index.ts b/packages/libp2p-connection/src/index.ts deleted file mode 100644 index 1f45967a7..000000000 --- a/packages/libp2p-connection/src/index.ts +++ /dev/null @@ -1,176 +0,0 @@ -import type { Multiaddr } from '@multiformats/multiaddr' -import errCode from 'err-code' -import { OPEN, CLOSING, CLOSED } from '@libp2p/interfaces/connection/status' -import { symbol } from '@libp2p/interfaces/connection' -import type { Connection, ConnectionStat, Metadata, ProtocolStream, Stream } from '@libp2p/interfaces/connection' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { logger } from '@libp2p/logger' -import type { AbortOptions } from '@libp2p/interfaces' - -const log = logger('libp2p:connection') - -interface ConnectionInit { - remoteAddr: Multiaddr - remotePeer: PeerId - newStream: (protocols: string[], options?: AbortOptions) => Promise - close: () => Promise - getStreams: () => Stream[] - stat: ConnectionStat -} - -/** - * An implementation of the js-libp2p connection. - * Any libp2p transport should use an upgrader to return this connection. - */ -export class ConnectionImpl implements Connection { - /** - * Connection identifier. - */ - public readonly id: string - /** - * Observed multiaddr of the remote peer - */ - public readonly remoteAddr: Multiaddr - /** - * Remote peer id - */ - public readonly remotePeer: PeerId - /** - * Connection metadata - */ - public readonly stat: ConnectionStat - /** - * User provided tags - * - */ - public tags: string[] - - /** - * Reference to the new stream function of the multiplexer - */ - private readonly _newStream: (protocols: string[], options?: AbortOptions) => Promise - /** - * Reference to the close function of the raw connection - */ - private readonly _close: () => Promise - /** - * Reference to the getStreams function of the muxer - */ - private readonly _getStreams: () => Stream[] - /** - * Connection streams registry - */ - public readonly registry: Map - private _closing: boolean - - /** - * An implementation of the js-libp2p connection. - * Any libp2p transport should use an upgrader to return this connection. - */ - constructor (init: ConnectionInit) { - const { remoteAddr, remotePeer, newStream, close, getStreams, stat } = init - - this.id = `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}` - this.remoteAddr = remoteAddr - this.remotePeer = remotePeer - this.stat = { - ...stat, - status: OPEN - } - this._newStream = newStream - this._close = close - this._getStreams = getStreams - this.registry = new Map() - this.tags = [] - this._closing = false - } - - get [Symbol.toStringTag] () { - return 'Connection' - } - - get [symbol] () { - return true - } - - /** - * Get all the streams of the muxer - */ - get streams () { - return this._getStreams() - } - - /** - * Create a new stream from this connection - */ - async newStream (protocols: string | string[], options?: AbortOptions) { - if (this.stat.status === CLOSING) { - throw errCode(new Error('the connection is being closed'), 'ERR_CONNECTION_BEING_CLOSED') - } - - if (this.stat.status === CLOSED) { - throw errCode(new Error('the connection is closed'), 'ERR_CONNECTION_CLOSED') - } - - if (!Array.isArray(protocols)) { - protocols = [protocols] - } - - const { stream, protocol } = await this._newStream(protocols, options) - - this.addStream(stream, { protocol, metadata: {} }) - - return { - stream, - protocol - } - } - - /** - * Add a stream when it is opened to the registry - */ - addStream (stream: Stream, metadata: Partial = {}) { - // Add metadata for the stream - this.registry.set(stream.id, { - protocol: metadata.protocol ?? '', - metadata: metadata.metadata ?? {} - }) - } - - /** - * Remove stream registry after it is closed - */ - removeStream (id: string) { - this.registry.delete(id) - } - - /** - * Close the connection - */ - async close () { - if (this.stat.status === CLOSED || this._closing) { - return - } - - this.stat.status = CLOSING - - // close all streams - this can throw if we're not multiplexed - try { - this.streams.forEach(s => s.close()) - } catch (err) { - log.error(err) - } - - // Close raw connection - this._closing = true - await this._close() - this._closing = false - - this.stat.timeline.close = Date.now() - this.stat.status = CLOSED - } -} - -export function createConnection (init: ConnectionInit): Connection { - return new ConnectionImpl(init) -} diff --git a/packages/libp2p-connection/test/compliance.spec.ts b/packages/libp2p-connection/test/compliance.spec.ts deleted file mode 100644 index ced782a91..000000000 --- a/packages/libp2p-connection/test/compliance.spec.ts +++ /dev/null @@ -1,71 +0,0 @@ -import tests from '@libp2p/interface-compliance-tests/connection' -import { createConnection } from '../src/index.js' -import peers from '@libp2p/interface-compliance-tests/utils/peers' -import * as PeerIdFactory from '@libp2p/peer-id-factory' -import { Multiaddr } from '@multiformats/multiaddr' -import { pair } from 'it-pair' -import type { Stream } from '@libp2p/interfaces/connection' - -describe('compliance tests', () => { - tests({ - /** - * Test setup. `properties` allows the compliance test to override - * certain values for testing. - */ - async setup (properties) { - const remoteAddr = new Multiaddr('/ip4/127.0.0.1/tcp/8081') - const remotePeer = await PeerIdFactory.createFromJSON(peers[0]) - const openStreams: Stream[] = [] - let streamId = 0 - - const connection = createConnection({ - remotePeer, - remoteAddr, - stat: { - timeline: { - open: Date.now() - 10, - upgraded: Date.now() - }, - direction: 'outbound', - encryption: '/secio/1.0.0', - multiplexer: '/mplex/6.7.0', - status: 'OPEN' - }, - newStream: async (protocols) => { - const id = `${streamId++}` - const stream: Stream = { - ...pair(), - close: () => { - void stream.sink(async function * () {}()) - connection.removeStream(stream.id) - }, - closeRead: () => {}, - closeWrite: () => { - void stream.sink(async function * () {}()) - }, - id, - abort: () => {}, - reset: () => {}, - timeline: { - open: 0 - } - } - - openStreams.push(stream) - - return { - stream, - protocol: protocols[0] - } - }, - close: async () => {}, - getStreams: () => openStreams, - ...properties - }) - return connection - }, - async teardown () { - // cleanup resources created by setup() - } - }) -}) diff --git a/packages/libp2p-connection/test/index.spec.ts b/packages/libp2p-connection/test/index.spec.ts deleted file mode 100644 index deb949b56..000000000 --- a/packages/libp2p-connection/test/index.spec.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { createConnection } from '../src/index.js' -import * as PeerIdFactory from '@libp2p/peer-id-factory' -import { pair } from 'it-pair' -import { Multiaddr } from '@multiformats/multiaddr' -import type { Stream } from '@libp2p/interfaces/connection' - -const peers = [{ - id: 'QmNMMAqSxPetRS1cVMmutW5BCN1qQQyEr4u98kUvZjcfEw', - privKey: 'CAASpQkwggShAgEAAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAECggEAB2H2uPRoRCAKU+T3gO4QeoiJaYKNjIO7UCplE0aMEeHDnEjAKC1HQ1G0DRdzZ8sb0fxuIGlNpFMZv5iZ2ZFg2zFfV//DaAwTek9tIOpQOAYHUtgHxkj5FIlg2BjlflGb+ZY3J2XsVB+2HNHkUEXOeKn2wpTxcoJE07NmywkO8Zfr1OL5oPxOPlRN1gI4ffYH2LbfaQVtRhwONR2+fs5ISfubk5iKso6BX4moMYkxubYwZbpucvKKi/rIjUA3SK86wdCUnno1KbDfdXSgCiUlvxt/IbRFXFURQoTV6BOi3sP5crBLw8OiVubMr9/8WE6KzJ0R7hPd5+eeWvYiYnWj4QKBgQD6jRlAFo/MgPO5NZ/HRAk6LUG+fdEWexA+GGV7CwJI61W/Dpbn9ZswPDhRJKo3rquyDFVZPdd7+RlXYg1wpmp1k54z++L1srsgj72vlg4I8wkZ4YLBg0+zVgHlQ0kxnp16DvQdOgiRFvMUUMEgetsoIx1CQWTd67hTExGsW+WAZQKBgQDT/WaHWvwyq9oaZ8G7F/tfeuXvNTk3HIJdfbWGgRXB7lJ7Gf6FsX4x7PeERfL5a67JLV6JdiLLVuYC2CBhipqLqC2DB962aKMvxobQpSljBBZvZyqP1IGPoKskrSo+2mqpYkeCLbDMuJ1nujgMP7gqVjabs2zj6ACKmmpYH/oNowJ/T0ZVtvFsjkg+1VsiMupUARRQuPUWMwa9HOibM1NIZcoQV2NGXB5Z++kR6JqxQO0DZlKArrviclderUdY+UuuY4VRiSEprpPeoW7ZlbTku/Ap8QZpWNEzZorQDro7bnfBW91fX9/81ets/gCPGrfEn+58U3pdb9oleCOQc/ifpQKBgBTYGbi9bYbd9vgZs6bd2M2um+VFanbMytS+g5bSIn2LHXkVOT2UEkB+eGf9KML1n54QY/dIMmukA8HL1oNAyalpw+/aWj+9Ui5kauUhGEywHjSeBEVYM9UXizxz+m9rsoktLLLUI0o97NxCJzitG0Kub3gn0FEogsUeIc7AdinZAoGBANnM1vcteSQDs7x94TDEnvvqwSkA2UWyLidD2jXgE0PG4V6tTkK//QPBmC9eq6TIqXkzYlsErSw4XeKO91knFofmdBzzVh/ddgx/NufJV4tXF+a2iTpqYBUJiz9wpIKgf43/Ob+P1EA99GAhSdxz1ess9O2aTqf3ANzn6v6g62Pv', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPek2aeHMa0blL42RTKd6xgtkk4Zkldvq4LHxzcag5uXepiQzWANEUvoD3KcUTmMRmx14PvsxdLCNst7S2JSa0R2n5wSRs14zGy6892lx4H4tLBD1KSpQlJ6vabYM1CJhIQRG90BtzDPrJ/X1iJ2HA0PPDz0Mflam2QUMDDrU0IuV2m7gSCJ5r4EmMs3U0xnH/1gShkVx4ir0WUdoWf5KQUJOmLn1clTRHYPv4KL9A/E38+imNAXfkH3c2T7DrCcYRkZSpK+WecjMsH1dCX15hhhggNqfp3iulO1tGPxHjm7PDGTPUjpCWKpD5e50sLqsUwexac1ja6ktMfszIR+FPAgMBAAE=' -}, { - id: 'QmW8rAgaaA6sRydK1k6vonShQME47aDxaFidbtMevWs73t', - privKey: 'CAASpwkwggSjAgEAAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAECggEAHq2f8MqpYjLiAFZKl9IUs3uFZkEiZsgx9BmbMAb91Aec+WWJG4OLHrNVTG1KWp+IcaQablEa9bBvoToQnS7y5OpOon1d066egg7Ymfmv24NEMM5KRpktCNcOSA0CySpPIB6yrg6EiUr3ixiaFUGABKkxmwgVz/Q15IqM0ZMmCUsC174PMAz1COFZxD0ZX0zgHblOJQW3dc0X3XSzhht8vU02SMoVObQHQfeXEHv3K/RiVj/Ax0bTc5JVkT8dm8xksTtsFCNOzRBqFS6MYqX6U/u0Onz3Jm5Jt7fLWb5n97gZR4SleyGrqxYNb46d9X7mP0ie7E6bzFW0DsWBIeAqVQKBgQDW0We2L1n44yOvJaMs3evpj0nps13jWidt2I3RlZXjWzWHiYQfvhWUWqps/xZBnAYgnN/38xbKzHZeRNhrqOo+VB0WK1IYl0lZVE4l6TNKCsLsUfQzsb1pePkd1eRZA+TSqsi+I/IOQlQU7HA0bMrah/5FYyUBP0jYvCOvYTlZuwKBgQCvkcVRydVlzjUgv7lY5lYvT8IHV5iYO4Qkk2q6Wjv9VUKAJZauurMdiy05PboWfs5kbETdwFybXMBcknIvZO4ihxmwL8mcoNwDVZHI4bXapIKMTCyHgUKvJ9SeTcKGC7ZuQJ8mslRmYox/HloTOXEJgQgPRxXcwa3amzvdZI+6LwKBgQCLsnQqgxKUi0m6bdR2qf7vzTH4258z6X34rjpT0F5AEyF1edVFOz0XU/q+lQhpNEi7zqjLuvbYfSyA026WXKuwSsz7jMJ/oWqev/duKgAjp2npesY/E9gkjfobD+zGgoS9BzkyhXe1FCdP0A6L2S/1+zg88WOwMvJxl6/xLl24XwKBgCm60xSajX8yIQyUpWBM9yUtpueJ2Xotgz4ST+bVNbcEAddll8gWFiaqgug9FLLuFu5lkYTHiPtgc1RNdphvO+62/9MRuLDixwh/2TPO+iNqwKDKJjda8Nei9vVddCPaOtU/xNQ0xLzFJbG9LBmvqH9izOCcu8SJwGHaTcNUeJj/AoGADCJ26cY30c13F/8awAAmFYpZWCuTP5ppTsRmjd63ixlrqgkeLGpJ7kYb5fXkcTycRGYgP0e1kssBGcmE7DuG955fx3ZJESX3GQZ+XfMHvYGONwF1EiK1f0p6+GReC2VlQ7PIkoD9o0hojM6SnWvv9EXNjCPALEbfPFFvcniKVsE=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCTU3gVDv3SRXLOsFln9GEf1nJ/uCEDhOG10eC0H9l9IPpVxjuPT1ep+ykFUdvefq3D3q+W3hbmiHm81o8dYv26RxZIEioToUWp7Ec5M2B/niYoE93za9/ZDwJdl7eh2hNKwAdxTmdbXUPjkIU4vLyHKRFbJIn9X8w9djldz8hoUvC1BK4L1XrT6F2l0ruJXErH2ZwI1youfSzo87TdXIoFKdrQLuW6hOtDCGKTiS+ab/DkMODc6zl8N47Oczv7vjzoWOJMUJs1Pg0ZsD1zmISY38P0y/QyEhatZn0B8BmSWxlLQuukatzOepQI6k+HtfyAAjn4UEqnMaXTP1uwLldVAgMBAAE=' -}, { - id: 'QmZqCdSzgpsmB3Qweb9s4fojAoqELWzqku21UVrqtVSKi4', - privKey: 'CAASpgkwggSiAgEAAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAECggEAQ1N0qHoxl5pmvqv8iaFlqLSUmx5y6GbI6CGJMQpvV9kQQU68yjItr3VuIXx8d/CBZyEMAK4oko7OeOyMcr3MLKLy3gyQWnXgsopDjhZ/8fH8uwps8g2+IZuFJrO+6LaxEPGvFu06fOiphPUVfn40R2KN/iBjGeox+AaXijmCqaV2vEdNJJPpMfz6VKZBDLTrbiqvo/3GN1U99PUqfPWpOWR29oAhh/Au6blSqvqTUPXB2+D/X6e1JXv31mxMPK68atDHSUjZWKB9lE4FMK1bkSKJRbyXmNIlbZ9V8X4/0r8/6T7JnW7ZT8ugRkquohmwgG7KkDXB1YsOCKXYUqzVYQKBgQDtnopFXWYl7XUyePJ/2MA5i7eoko9jmF44L31irqmHc5unNf6JlNBjlxTNx3WyfzhUzrn3c18psnGkqtow0tkBj5hmqn8/WaPbc5UA/5R1FNaNf8W5khn7MDm6KtYRPjN9djqTDiVHyC6ljONYd+5S+MqyKVWZ3t/xvG60sw85qwKBgQCpmpDtL+2JBwkfeUr3LyDcQxvbfzcv8lXj2otopWxWiLiZF1HzcqgAa2CIwu9kCGEt9Zr+9E4uINbe1To0b01/FhvR6xKO/ukceGA/mBB3vsKDcRmvpBUp+3SmnhY0nOk+ArQl4DhJ34k8pDM3EDPrixPf8SfVdU/8IM32lsdHhQKBgHLgpvCKCwxjFLnmBzcPzz8C8TOqR3BbBZIcQ34l+wflOGdKj1hsfaLoM8KYn6pAHzfBCd88A9Hg11hI0VuxVACRL5jS7NnvuGwsIOluppNEE8Ys86aXn7/0vLPoab3EWJhbRE48FIHzobmft3nZ4XpzlWs02JGfUp1IAC2UM9QpAoGAeWy3pZhSr2/iEC5+hUmwdQF2yEbj8+fDpkWo2VrVnX506uXPPkQwE1zM2Bz31t5I9OaJ+U5fSpcoPpDaAwBMs1fYwwlRWB8YNdHY1q6/23svN3uZsC4BGPV2JnO34iMUudilsRg+NGVdk5TbNejbwx7nM8Urh59djFzQGGMKeSECgYA0QMCARPpdMY50Mf2xQaCP7HfMJhESSPaBq9V3xY6ToEOEnXgAR5pNjnU85wnspHp+82r5XrKfEQlFxGpj2YA4DRRmn239sjDa29qP42UNAFg1+C3OvXTht1d5oOabaGhU0udwKmkEKUbb0bG5xPQJ5qeSJ5T1gLzLk3SIP0GlSw==', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCdbSEsTmw7lp5HagRcx57DaLiSUEkh4iBcKc7Y+jHICEIA8NIVi9FlfGEZj9G21FpiTR4Cy+BLVEuf8Nm90bym4iV+cSumeS21fvD8xGTEbeKGljs6OYHy3M45JhWF85gqHQJOqZufI2NRDuRgMZEO2+qGEXmSlv9mMXba/+9ecze8nSpB7bG2Z2pnKDeYwhF9Cz+ElMyn7TBWDjJERGVgFbTpdM3rBnbhB/TGpvs732QqZmIBlxnDb/Jn0l1gNZCgkEDcJ/0NDMBJTQ8vbvcdmaw3eaMPLkn1ix4wdu9QWCA0IBtuY1R7vSUtf4irnLJG7DnAw2GfM5QrF3xF1GLXAgMBAAE=' -}, { - id: 'QmR5VwgsL7jyfZHAGyp66tguVrQhCRQuRc3NokocsCZ3fA', - privKey: 'CAASpwkwggSjAgEAAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAECggEAS64HK8JZfE09eYGJNWPe8ECmD1C7quw21BpwVe+GVPSTizvQHswPohbKDMNj0srXDMPxCnNw1OgqcaOwyjsGuZaOoXoTroTM8nOHRIX27+PUqzaStS6aCG2IsiCozKUHjGTuupftS7XRaF4eIsUtWtFcQ1ytZ9pJYHypRQTi5NMSrTze5ThjnWxtHilK7gnBXik+aR0mYEVfSn13czQEC4rMOs+b9RAc/iibDNoLopfIdvmCCvfxzmySnR7Cu1iSUAONkir7PB+2Mt/qRFCH6P+jMamtCgQ8AmifXgVmDUlun+4MnKg3KrPd6ZjOEKhVe9mCHtGozk65RDREShfDdQKBgQDi+x2MuRa9peEMOHnOyXTS+v+MFcfmG0InsO08rFNBKZChLB+c9UHBdIvexpfBHigSyERfuDye4z6lxi8ZnierWMYJP30nxmrnxwTGTk1MQquhfs1A0kpmDnPsjlOS/drEIEIssNx2WbfJ7YtMxLWBtp+BJzGpQmr0LKC+NHRSrwKBgQCXiy2kJESIUkIs2ihV55hhT6/bZo1B1O5DPA2nkjOBXqXF6fvijzMDX82JjLd07lQZlI0n1Q/Hw0p4iYi9YVd2bLkLXF5UIb2qOeHj76enVFOrPHUSkC9Y2g/0Xs+60Ths2xRd8RrrfQU3kl5iVpBywkCIrb2M5+wRnNTk1W3TtwKBgQCvplyrteAfSurpJhs9JzE8w/hWU9SqAZYkWQp91W1oE95Um2yrbjBAoQxMjaqKS+f/APPIjy56Vqj4aHGyhW11b/Fw3qzfxvCcBKtxOs8eoMlo5FO6QgJJEA4tlcafDcvp0nzjUMqK28safLU7503+33B35fjMXxWdd5u9FaKfCQKBgC4W6j6tuRosymuRvgrCcRnHfpify/5loEFallyMnpWOD6Tt0OnK25z/GifnYDRz96gAAh5HMpFy18dpLOlMHamqz2yhHx8/U8vd5tHIJZlCkF/X91M5/uxrBccwvsT2tM6Got8fYSyVzWxlW8dUxIHiinYHQUsFjkqdBDLEpq5pAoGASoTw5RBEWFM0GuAZdXsyNyxU+4S+grkTS7WdW/Ymkukh+bJZbnvF9a6MkSehqXnknthmufonds2AFNS//63gixENsoOhzT5+2cdfc6tJECvJ9xXVXkf85AoQ6T/RrXF0W4m9yQyCngNJUrKUOIH3oDIfdZITlYzOC3u1ojj7VuQ=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCGXYU+uc2nn1zuJhfdFOl34upztnrD1gpHu58ousgHdGlGgYgbqLBAvIAauXdEL0+e30HofjA634SQxE+9nV+0FQBam1DDzHQlXsuwHV+2SKvSDkk4bVllMFpu2SJtts6VH+OXC/2ANJOm+eTALykQPYXgLIBxrhp/eD+Jz5r6wW2nq3k6OmYyK/4pgGzFjo5UyX+fa/171AJ68UPboFpDy6BZCcUjS0ondxPvD7cv5jMNqqMKIB/7rpi8n+Q3oeccRqVL56wH+FE3/QLjwYHwY6ILNRyvNXRqHjwBEXB2R5moXN0AFUWTw9rt3KhFiEjR1U81BTw5/xS7W2Iu0FgZAgMBAAE=' -}, { - id: 'QmScLDqRg7H6ipCYxm9fVk152UWavQFKscTdoT4YNHxgqp', - privKey: 'CAASpwkwggSjAgEAAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAECggEAdmt1dyswR2p4tdIeNpY7Pnj9JNIhTNDPznefI0dArCdBvBMhkVaYk6MoNIxcj6l7YOrDroAF8sXr0TZimMY6B/pERKCt/z1hPWTxRQBBAvnHhwvwRPq2jK6BfhAZoyM8IoBNKowP9mum5QUNdGV4Al8s73KyFX0IsCfgZSvNpRdlt+DzPh+hu/CyoZaMpRchJc1UmK8Fyk3KfO+m0DZNfHP5P08lXNfM6MZLgTJVVgERHyG+vBOzTd2RElMe19nVCzHwb3dPPRZSQ7Fnz3rA+GeLqsM2Zi4HNhfbD1OcD9C4wDj5tYL6hWTkdz4IlfVcjCeUHxgIOhdDV2K+OwbuAQKBgQD0FjUZ09UW2FQ/fitbvIB5f1SkXWPxTF9l6mAeuXhoGv2EtQUO4vq/PK6N08RjrZdWQy6UsqHgffi7lVQ8o3hvCKdbtf4sP+cM92OrY0WZV89os79ndj4tyvmnP8WojwRjt/2XEfgdoWcgWxW9DiYINTOQVimZX+X/3on4s8hEgQKBgQCdY3kOMbyQeLTRkqHXjVTY4ddO+v4S4wOUa1l4rTqAbq1W3JYWwoDQgFuIu3limIHmjnSJpCD4EioXFsM7p6csenoc20sHxsaHnJ6Mn5Te41UYmY9EW0otkQ0C3KbXM0hwQkjyplnEmZawGKmjEHW8DJ3vRYTv9TUCgYKxDHgOzQKBgB4A/NYH7BG61eBYKgxEx6YnuMfbkwV+Vdu5S8d7FQn3B2LgvZZu4FPRqcNVXLbEB+5ao8czjiKCWaj1Wj15+rvrXGcxn+Tglg5J+r5+nXeUC7LbJZQaPNp0MOwWMr3dlrSLUWjYlJ9Pz9VyXOG4c4Rexc/gR4zK9QLW4C7qKpwBAoGAZzyUb0cYlPtYQA+asTU3bnvVKy1f8yuNcZFowst+EDiI4u0WVh+HNzy6zdmLKa03p+/RaWeLaK0hhrubnEnAUmCUMNF3ScaM+u804LDcicc8TkKLwx7ObU0z56isl4RAA8K27tNHFrpYKXJD834cfBkaj5ReOrfw6Y/iFhhDuBECgYEA8gbC76uz7LSHhW30DSRTcqOzTyoe2oYKQaxuxYNp7vSSOkcdRen+mrdflDvud2q/zN2QdL4pgqdldHlR35M/lJ0f0B6zp74jlzbO9700wzsOqreezGc5eWiroDL100U9uIZ50BKb8CKtixIHpinUSPIUcVDkSAZ2y7mbfCxQwqQ=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWEHaTZ6LBLFP5OPrUqjDM/cF4b2zrfh1Zm3kd02ZtgQB3iYtZqRPJT5ctT3A7WdVF/7dCxPGOCkJlLekTx4Y4gD8JtjA+EfN9fR/2RBKbti2N3CD4vkGp9ss4hbBFcXIhl8zuD/ELHutbV6b8b4QXJGnxfp/B+1kNPnyd7SJznS0QyvI8OLI1nAkVKdYLDRW8kPKeHyx1xhdNDuTQVTFyAjRGQ4e3UYFB7bYIHW3E6kCtCoJDlj+JPC02Yt1LHzIzZVLvPvNFnYY2mag6OiGFuh/oMBIqvnPc1zRZ3eLUqeGZjQVaoR0kdgZUKz7Q2TBeNldxK/s6XO0DnkQTlelNAgMBAAE=' -}, { - id: 'QmckxVrJw1Yo8LqvmDJNUmdAsKtSbiKWmrXJFyKmUraBoN', - privKey: 'CAASpwkwggSjAgEAAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAECggEBAKb5aN/1w3pBqz/HqRMbQpYLNuD33M3PexBNPAy+P0iFpDo63bh5Rz+A4lvuFNmzUX70MFz7qENlzi6+n/zolxMB29YtWBUH8k904rTEjXXl//NviQgITZk106tx+4k2x5gPEm57LYGfBOdFAUzNhzDnE2LkXwRNzkS161f7zKwOEsaGWRscj6UvhO4MIFxjb32CVwt5eK4yOVqtyMs9u30K4Og+AZYTlhtm+bHg6ndCCBO6CQurCQ3jD6YOkT+L3MotKqt1kORpvzIB0ujZRf49Um8wlcjC5G9aexBeGriXaVdPF62zm7GA7RMsbQM/6aRbA1fEQXvJhHUNF9UFeaECgYEA8wCjKqQA7UQnHjRwTsktdwG6szfxd7z+5MTqHHTWhWzgcQLgdh5/dO/zanEoOThadMk5C1Bqjq96gH2xim8dg5XQofSVtV3Ui0dDa+XRB3E3fyY4D3RF5hHv85O0GcvQc6DIb+Ja1oOhvHowFB1C+CT3yEgwzX/EK9xpe+KtYAkCgYEAv7hCnj/DcZFU3fAfS+unBLuVoVJT/drxv66P686s7J8UM6tW+39yDBZ1IcwY9vHFepBvxY2fFfEeLI02QFM+lZXVhNGzFkP90agNHK01psGgrmIufl9zAo8WOKgkLgbYbSHzkkDeqyjEPU+B0QSsZOCE+qLCHSdsnTmo/TjQhj0CgYAz1+j3yfGgrS+jVBC53lXi0+2fGspbf2jqKdDArXSvFqFzuudki/EpY6AND4NDYfB6hguzjD6PnoSGMUrVfAtR7X6LbwEZpqEX7eZGeMt1yQPMDr1bHrVi9mS5FMQR1NfuM1lP9Xzn00GIUpE7WVrWUhzDEBPJY/7YVLf0hFH08QKBgDWBRQZJIVBmkNrHktRrVddaSq4U/d/Q5LrsCrpymYwH8WliHgpeTQPWmKXwAd+ZJdXIzYjCt202N4eTeVqGYOb6Q/anV2WVYBbM4avpIxoA28kPGY6nML+8EyWIt2ApBOmgGgvtEreNzwaVU9NzjHEyv6n7FlVwlT1jxCe3XWq5AoGASYPKQoPeDlW+NmRG7z9EJXJRPVtmLL40fmGgtju9QIjLnjuK8XaczjAWT+ySI93Whu+Eujf2Uj7Q+NfUjvAEzJgwzuOd3jlQvoALq11kuaxlNQTn7rx0A1QhBgUJE8AkvShPC9FEnA4j/CLJU0re9H/8VvyN6qE0Mho0+YbjpP8=', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1/GFud/7xutux7qRfMj1sIdMRh99/chR6HqVj6LQqrgk4jil0mdN/LCk/tqPqmDtObHdmEhCoybzuhLbCKgUqryKDwO6yBJHSKWY9QqrKZtLJ37SgKwGjE3+NUD4r1dJHhtQrICFdOdSCBzs/v8gi+J+KZLHo7+Nms4z09ysy7qZh94Pd7cW4gmSMergqUeANLD9C0ERw1NXolswOW7Bi7UGr7yuBxejICLO3nkxe0OtpQBrYrqdCD9vs3t/HQZbPWVoiRj4VO7fxkAPKLl30HzcIfxj/ayg8NHcH59d08D+N2v5Sdh28gsiYKIPE9CXvuw//HUY2WVRY5fDC5JglAgMBAAE=' -}] - -describe('connection tests', () => { - it('should not require local or remote addrs', async () => { - const remotePeer = await PeerIdFactory.createFromJSON(peers[1]) - - const openStreams: any[] = [] - let streamId = 0 - - return createConnection({ - remotePeer, - remoteAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4002'), - stat: { - timeline: { - open: Date.now() - 10, - upgraded: Date.now() - }, - direction: 'outbound', - encryption: '/secio/1.0.0', - multiplexer: '/mplex/6.7.0', - status: 'OPEN' - }, - newStream: async (protocols) => { - const id = `${streamId++}` - const stream: Stream = { - ...pair(), - close: () => { - void stream.sink(async function * () {}()) - }, - closeRead: () => {}, - closeWrite: () => { - void stream.sink(async function * () {}()) - }, - id, - abort: () => {}, - reset: () => {}, - timeline: { - open: 0 - } - } - - openStreams.push(stream) - - return { - stream, - protocol: protocols[0] - } - }, - close: async () => {}, - getStreams: () => openStreams - }) - }) -}) diff --git a/packages/libp2p-interface-compliance-tests/README.md b/packages/libp2p-interface-compliance-tests/README.md deleted file mode 100644 index ddd903f34..000000000 --- a/packages/libp2p-interface-compliance-tests/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# libp2p-interfaces-compliance-tests - -> Contains test suites you should use to implement the various components of libp2p - -## Table of contents - -- [Usage](#usage) -- [Contribute](#contribute) -- [License](#license) - -## Usage - -Each [interface](../interfaces) has its documentation on how to use the compliance tests and should be used as the source of truth. - -## Contribute - -The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: - - - Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - - **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - - **Add tests**. There can never be enough tests. - -## License - -[Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) © Protocol Labs diff --git a/packages/libp2p-interface-compliance-tests/package.json b/packages/libp2p-interface-compliance-tests/package.json deleted file mode 100644 index 56dc0c38c..000000000 --- a/packages/libp2p-interface-compliance-tests/package.json +++ /dev/null @@ -1,235 +0,0 @@ -{ - "name": "@libp2p/interface-compliance-tests", - "version": "2.0.3", - "description": "Compliance tests for JS libp2p interfaces", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interface-compliance-tests#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "interface", - "libp2p" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "typesVersions": { - "*": { - "*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ], - "src/*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ] - } - }, - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js", - "types": "./dist/src/index.d.ts" - }, - "./connection": { - "import": "./dist/src/connection/index.js", - "types": "./dist/src/connection/index.d.ts" - }, - "./connection-encrypter": { - "import": "./dist/src/connection-encrypter/index.js", - "types": "./dist/src/connection-encrypter/index.d.ts" - }, - "./mocks": { - "import": "./dist/src/mocks/index.js", - "types": "./dist/src/mocks/index.d.ts" - }, - "./peer-discovery": { - "import": "./dist/src/peer-discovery/index.js", - "types": "./dist/src/peer-discovery/index.d.ts" - }, - "./pubsub": { - "import": "./dist/src/pubsub/index.js", - "types": "./dist/src/pubsub/index.d.ts" - }, - "./record": { - "import": "./dist/src/record/index.js", - "types": "./dist/src/record/index.d.ts" - }, - "./stream-muxer": { - "import": "./dist/src/stream-muxer/index.js", - "types": "./dist/src/stream-muxer/index.d.ts" - }, - "./topology": { - "import": "./dist/src/topology/topology.js", - "types": "./dist/src/topology/topology.d.ts" - }, - "./topology/multicodec-toplogy": { - "import": "./dist/src/topology/multicodec-toplogy.js", - "types": "./dist/src/topology/multicodec-toplogy.d.ts" - }, - "./transport": { - "import": "./dist/src/transport/index.js", - "types": "./dist/src/transport/index.d.ts" - }, - "./transport/utils": { - "import": "./dist/src/transport/utils/index.js", - "types": "./dist/src/transport/utils/index.d.ts" - }, - "./utils/peers": { - "import": "./dist/src/utils/peers.js", - "types": "./dist/src/utils/peers.d.ts" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - } - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "release": "aegir release" - }, - "dependencies": { - "@libp2p/crypto": "^0.22.8", - "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", - "@libp2p/multistream-select": "^1.0.0", - "@libp2p/peer-id": "^1.1.0", - "@libp2p/peer-id-factory": "^1.0.0", - "@libp2p/pubsub": "^1.2.0", - "@multiformats/multiaddr": "^10.1.5", - "abortable-iterator": "^4.0.2", - "aegir": "^37.0.7", - "any-signal": "^3.0.0", - "delay": "^5.0.0", - "err-code": "^3.0.1", - "it-all": "^1.0.6", - "it-drain": "^1.0.5", - "it-goodbye": "^4.0.1", - "it-handshake": "^3.0.1", - "it-map": "^1.0.6", - "it-ndjson": "^0.1.1", - "it-pair": "^2.0.2", - "it-pipe": "^2.0.3", - "it-pushable": "^2.0.1", - "it-stream-types": "^1.0.4", - "multiformats": "^9.6.3", - "p-defer": "^4.0.0", - "p-event": "^5.0.1", - "p-limit": "^4.0.0", - "p-wait-for": "^4.1.0", - "sinon": "^14.0.0", - "uint8arraylist": "^1.5.1", - "uint8arrays": "^3.0.0", - "util": "^0.12.4" - } -} diff --git a/packages/libp2p-interface-compliance-tests/src/connection/README.md b/packages/libp2p-interface-compliance-tests/src/connection/README.md deleted file mode 100644 index db1b3da59..000000000 --- a/packages/libp2p-interface-compliance-tests/src/connection/README.md +++ /dev/null @@ -1,256 +0,0 @@ -interface-connection -================== - -This is a test suite and interface you can use to implement a connection. The connection interface contains all the metadata associated with it, as well as an array of the streams opened through this connection. In the same way as the connection, a stream contains properties with its metadata, plus an iterable duplex object that offers a mechanism for writing and reading data, with back pressure. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. - -The primary goal of this module is to enable developers to pick, swap or upgrade their connection without losing the same API expectations and mechanisms such as back pressure and the ability to half close a connection. - -Publishing a test suite as a module lets multiple modules ensure compatibility since they use the same test suite. - -## Usage - -### Connection - -Before creating a connection from a transport compatible with `libp2p` it is important to understand some concepts: - -- **socket**: the underlying raw duplex connection between two nodes. It is created by the transports during a dial/listen. -- **[multiaddr connection](https://github.com/libp2p/interface-transport#multiaddrconnection)**: an abstraction over the socket to allow it to work with multiaddr addresses. It is a duplex connection that transports create to wrap the socket before passing to an upgrader that turns it into a standard connection (see below). -- **connection**: a connection between two _peers_ that has built in multiplexing and info about the connected peer. It is created from a [multiaddr connection](https://github.com/libp2p/interface-transport#multiaddrconnection) by an upgrader. The upgrader uses multistream-select to add secio and multiplexing and returns this object. -- **stream**: a muxed duplex channel of the `connection`. Each connection may have many streams. - -A connection stands for the libp2p communication duplex layer between two nodes. It is **not** the underlying raw transport duplex layer (socket), such as a TCP socket, but an abstracted layer that sits on top of the raw socket. - -This helps ensuring that the transport is responsible for socket management, while also allowing the application layer to handle the connection management. - -### Test suite - -```js -const tests = require('libp2p-interfaces-compliance-tests/connection') -describe('your connection', () => { - tests({ - // Options should be passed to your connection - async setup (options) { - return YourConnection - }, - async teardown () { - // cleanup resources created by setup() - } - }) -}) -``` - -## API - -### Connection - -A valid connection (one that follows this abstraction), must implement the following API: - -- type: `Connection` -```js -new Connection({ - localAddr, - remoteAddr, - localPeer, - remotePeer, - newStream, - close, - getStreams, - stat: { - direction, - timeline: { - open, - upgraded - }, - multiplexer, - encryption - } -}) -``` - - ` conn.localAddr` - - ` conn.remoteAddr` - - ` conn.localPeer` - - ` conn.remotePeer` - - ` conn.stat` - - ` conn.registry` - - `Array conn.streams` - - `Promise conn.newStream(Array)` - - ` conn.removeStream(id)` - - ` conn.addStream(stream, protocol, metadata)` - - `Promise<> conn.close()` - -It can be obtained as follows: - -```js -const { Connection } = require('interface-connection') - -const conn = new Connection({ - localAddr: maConn.localAddr, - remoteAddr: maConn.remoteAddr, - localPeer: this._peerId, - remotePeer, - newStream, - close: err => maConn.close(err), - getStreams, - stats: { - direction: 'outbound', - timeline: { - open: maConn.timeline.open, - upgraded: Date.now() - }, - multiplexer, - encryption - } -}) -``` - -#### Creating a connection instance - -- `JavaScript` - `const conn = new Connection({localAddr, remoteAddr, localPeer, remotePeer, newStream, close, getStreams, direction, multiplexer, encryption})` - -Creates a new Connection instance. - -`localAddr` is the optional [multiaddr](https://github.com/multiformats/multiaddr) address used by the local peer to reach the remote. -`remoteAddr` is the optional [multiaddr](https://github.com/multiformats/multiaddr) address used to communicate with the remote peer. -`localPeer` is the [PeerId](https://github.com/libp2p/js-peer-id) of the local peer. -`remotePeer` is the [PeerId](https://github.com/libp2p/js-peer-id) of the remote peer. -`newStream` is the `function` responsible for getting a new muxed+multistream-selected stream. -`close` is the `function` responsible for closing the raw connection. -`getStreams` is the `function` responsible for getting the streams muxed within the connection. -`stats` is an `object` with the metadata of the connection. It contains: -- `direction` is a `string` indicating whether the connection is `inbound` or `outbound`. -- `timeline` is an `object` with the relevant events timestamps of the connection (`open`, `upgraded` and `closed`; the `closed` will be added when the connection is closed). -- `multiplexer` is a `string` with the connection multiplexing codec (optional). -- `encryption` is a `string` with the connection encryption method identifier (optional). -- `status` is a `string` indicating the overall status of the connection. It is one of [`'open'`, `'closing'`, `'closed'`] - -#### Create a new stream - -- `JavaScript` - `conn.newStream(protocols)` - -Create a new stream within the connection. - -`protocols` is an array of the intended protocol to use (by order of preference). Example: `[/echo/1.0.0]` - -It returns a `Promise` with an object with the following properties: - -```js -{ - stream, - protocol -} -``` - -The stream property contains the muxed stream, while the protocol contains the protocol codec used by the stream. - -#### Add stream metadata - -- `JavaScript` - `conn.addStream(stream, { protocol, ...metadata })` - -Add a new stream to the connection registry. - -`stream` is a muxed stream. -`protocol` is the string codec for the protocol used by the stream. Example: `/echo/1.0.0` -`metadata` is an object containing any additional, optional, stream metadata that you wish to track (such as its `tags`). - -#### Remove a from the registry - -- `JavaScript` - `conn.removeStream(id)` - -Removes the stream with the given id from the connection registry. - -`id` is the unique id of the stream for this connection. - - -#### Close connection - -- `JavaScript` - `conn.close()` - -This method closes the connection to the remote peer, as well as all the streams muxed within the connection. - -It returns a `Promise`. - -#### Connection identifier - -- `JavaScript` - `conn.id` - -This property contains the identifier of the connection. - -#### Connection streams registry - -- `JavaScript` - `conn.registry` - -This property contains a map with the muxed streams indexed by their id. This registry contains the protocol used by the stream, as well as its metadata. - -#### Remote peer - -- `JavaScript` - `conn.remotePeer` - -This property contains the remote `peer-id` of this connection. - -#### Local peer - -- `JavaScript` - `conn.localPeer` - -This property contains the local `peer-id` of this connection. - -#### Get the connection Streams - -- `JavaScript` - `conn.streams` - -This getter returns all the muxed streams within the connection. - -It returns an `Array`. - -#### Remote address - -- `JavaScript` - `conn.remoteAddr` - -This getter returns the `remote` [multiaddr](https://github.com/multiformats/multiaddr) address. - -#### Local address - -- `JavaScript` - `conn.localAddr` - -This getter returns the `local` [multiaddr](https://github.com/multiformats/multiaddr) address. - -#### Stat - -- `JavaScript` - `conn.stat` - -This getter returns an `Object` with the metadata of the connection, as follows: - -- `status`: - -This property contains the status of the connection. It can be either `open`, `closing` or `closed`. Once the connection is created it is in an `open` status. When a `conn.close()` happens, the status will change to `closing` and finally, after all the connection streams are properly closed, the status will be `closed`. These values can also be directly referenced by importing the `status` file: - -```js -const { - OPEN, CLOSING, CLOSED -} = require('libp2p-interfaces/src/connection/status') - -if (connection.stat.status === OPEN) { - // ... -} -``` - -- `timeline`: - -This property contains an object with the `open`, `upgraded` and `close` timestamps of the connection. Note that, the `close` timestamp is `undefined` until the connection is closed. - -- `direction`: - -This property contains the direction of the peer in the connection. It can be `inbound` or `outbound`. - -- `multiplexer`: - -This property contains the `multiplexing` codec being used in the connection. - -- `encryption`: - -This property contains the encryption method being used in the connection. It is `undefined` if the connection is not encrypted. - -#### Tags - -- `JavaScript` - `conn.tags` - -This property contains an array of tags associated with the connection. New tags can be pushed to this array during the connection's lifetime. diff --git a/packages/libp2p-interface-compliance-tests/src/connection/index.ts b/packages/libp2p-interface-compliance-tests/src/connection/index.ts deleted file mode 100644 index 0832ca5da..000000000 --- a/packages/libp2p-interface-compliance-tests/src/connection/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import connectionSuite from './connection.js' -import type { TestSetup } from '../index.js' -import type { Connection } from '@libp2p/interfaces/connection' - -export default (test: TestSetup) => { - connectionSuite(test) -} diff --git a/packages/libp2p-interface-compliance-tests/src/mocks/registrar.ts b/packages/libp2p-interface-compliance-tests/src/mocks/registrar.ts deleted file mode 100644 index a8463b752..000000000 --- a/packages/libp2p-interface-compliance-tests/src/mocks/registrar.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type { IncomingStreamData, Registrar, StreamHandler } from '@libp2p/interfaces/registrar' -import type { Connection } from '@libp2p/interfaces/connection' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { Topology } from '@libp2p/interfaces/topology' - -export class MockRegistrar implements Registrar { - private readonly topologies: Map = new Map() - private readonly handlers: Map = new Map() - - getProtocols () { - return Array.from(this.handlers.keys()).sort() - } - - async handle (protocols: string | string[], handler: StreamHandler): Promise { - const protocolList = Array.isArray(protocols) ? protocols : [protocols] - - for (const protocol of protocolList) { - if (this.handlers.has(protocol)) { - throw new Error(`Handler already registered for protocol ${protocol}`) - } - - this.handlers.set(protocol, handler) - } - } - - async unhandle (protocols: string | string[]) { - const protocolList = Array.isArray(protocols) ? protocols : [protocols] - - protocolList.forEach(protocol => { - this.handlers.delete(protocol) - }) - } - - getHandler (protocol: string) { - const handler = this.handlers.get(protocol) - - if (handler == null) { - throw new Error(`No handler registered for protocol ${protocol}`) - } - - return handler - } - - async register (protocols: string | string[], topology: Topology) { - if (!Array.isArray(protocols)) { - protocols = [protocols] - } - - const id = `topology-id-${Math.random()}` - - this.topologies.set(id, { - topology, - protocols - }) - - return id - } - - unregister (id: string | string[]) { - if (!Array.isArray(id)) { - id = [id] - } - - id.forEach(id => this.topologies.delete(id)) - } - - getTopologies (protocol: string) { - const output: Topology[] = [] - - for (const { topology, protocols } of this.topologies.values()) { - if (protocols.includes(protocol)) { - output.push(topology) - } - } - - if (output.length > 0) { - return output - } - - return [] - } -} - -export function mockRegistrar () { - return new MockRegistrar() -} - -export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise { - return { - ...await conn.newStream([protocol]), - // @ts-expect-error incomplete implementation - connection: { - remotePeer - } - } -} diff --git a/packages/libp2p-interface-compliance-tests/src/topology/topology.ts b/packages/libp2p-interface-compliance-tests/src/topology/topology.ts deleted file mode 100644 index a4e14066d..000000000 --- a/packages/libp2p-interface-compliance-tests/src/topology/topology.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import type { TestSetup } from '../index.js' -import type { Topology } from '@libp2p/interfaces/topology' - -export default (test: TestSetup) => { - describe('topology', () => { - let topology: Topology - - beforeEach(async () => { - topology = await test.setup() - }) - - afterEach(async () => { - sinon.restore() - await test.teardown() - }) - - it('should have properties set', () => { - expect(topology.min).to.exist() - expect(topology.max).to.exist() - expect(topology.peers).to.exist() - }) - }) -} diff --git a/packages/libp2p-interface-compliance-tests/test/connection-encrypter/index.spec.ts b/packages/libp2p-interface-compliance-tests/test/connection-encrypter/index.spec.ts deleted file mode 100644 index bb9d77938..000000000 --- a/packages/libp2p-interface-compliance-tests/test/connection-encrypter/index.spec.ts +++ /dev/null @@ -1,11 +0,0 @@ -import tests from '../../src/connection-encrypter/index.js' -import mockCrypto from './mock-crypto.js' - -describe('compliance tests', () => { - tests({ - async setup () { - return mockCrypto - }, - async teardown () {} - }) -}) diff --git a/packages/libp2p-interface-compliance-tests/test/connection-encrypter/mock-crypto.ts b/packages/libp2p-interface-compliance-tests/test/connection-encrypter/mock-crypto.ts deleted file mode 100644 index 3f596a395..000000000 --- a/packages/libp2p-interface-compliance-tests/test/connection-encrypter/mock-crypto.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { peerIdFromBytes } from '@libp2p/peer-id' -import { handshake } from 'it-handshake' -import { duplexPair } from 'it-pair/duplex' -import { pipe } from 'it-pipe' -import { UnexpectedPeerError } from '@libp2p/interfaces/connection-encrypter/errors' -import { Multiaddr } from '@multiformats/multiaddr' -import type { ConnectionEncrypter } from '@libp2p/interfaces/connection-encrypter' -import type { Transform, Source } from 'it-stream-types' - -// A basic transform that does nothing to the data -const transform = (): Transform => { - return (source: Source) => (async function * () { - for await (const chunk of source) { - yield chunk - } - })() -} - -const crypto: ConnectionEncrypter = { - protocol: 'insecure', - secureInbound: async (localPeer, duplex, expectedPeer) => { - // 1. Perform a basic handshake. - const shake = handshake(duplex) - shake.write(localPeer.toBytes()) - const remoteId = await shake.read() - - if (remoteId == null) { - throw new Error('Could not read remote ID') - } - - const remotePeer = peerIdFromBytes(remoteId.slice()) - shake.rest() - - if (expectedPeer != null && !expectedPeer.equals(remotePeer)) { - throw new UnexpectedPeerError() - } - - // 2. Create your encryption box/unbox wrapper - const wrapper = duplexPair() - const encrypt = transform() // Use transform iterables to modify data - const decrypt = transform() - - void pipe( - wrapper[0], // We write to wrapper - encrypt, // The data is encrypted - shake.stream, // It goes to the remote peer - decrypt, // Decrypt the incoming data - wrapper[0] // Pipe to the wrapper - ) - - return { - conn: { - ...wrapper[1], - close: async () => {}, - localAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4001'), - remoteAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4002'), - timeline: { - open: Date.now() - }, - conn: true - }, - remotePeer, - remoteEarlyData: new Uint8Array(0) - } - }, - secureOutbound: async (localPeer, duplex, remotePeer) => { - // 1. Perform a basic handshake. - const shake = handshake(duplex) - shake.write(localPeer.toBytes()) - const remoteId = await shake.read() - - if (remoteId == null) { - throw new Error('Could not read remote ID') - } - - shake.rest() - - // 2. Create your encryption box/unbox wrapper - const wrapper = duplexPair() - const encrypt = transform() - const decrypt = transform() - - void pipe( - wrapper[0], // We write to wrapper - encrypt, // The data is encrypted - shake.stream, // It goes to the remote peer - decrypt, // Decrypt the incoming data - wrapper[0] // Pipe to the wrapper - ) - - return { - conn: { - ...wrapper[1], - close: async () => {}, - localAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4001'), - remoteAddr: new Multiaddr('/ip4/127.0.0.1/tcp/4002'), - timeline: { - open: Date.now() - }, - conn: true - }, - remotePeer: peerIdFromBytes(remoteId.slice()), - remoteEarlyData: new Uint8Array(0) - } - } -} - -export default crypto diff --git a/packages/libp2p-interfaces/README.md b/packages/libp2p-interfaces/README.md deleted file mode 100644 index 86a3a0fae..000000000 --- a/packages/libp2p-interfaces/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# libp2p-interfaces - -> Contains interfaces you can use to implement the various components of libp2p - -## Table of contents - -- [Interfaces](#interfaces) -- [Origin Repositories](#origin-repositories) -- [Contribute](#contribute) -- [License](#license) - -## Interfaces - -- [Connection](./src/connection) -- [Content Routing](./src/content-routing) -- [Crypto](./src/crypto) -- [Peer Discovery](./src/peer-discovery) -- [Peer Routing](./src/peer-routing) -- [Pubsub](./src/pubsub) -- [Record](./src/record) -- [Stream Muxer](./src/stream-muxer) -- [Topology](./src/topology) -- [Transport](./src/transport) - -## Origin Repositories - -For posterity, here are links to the original repositories for each of the interfaces (if they had one). - -- [Connection](https://github.com/libp2p/interface-connection) -- [Content Routing](https://github.com/libp2p/interface-content-routing) -- [Peer Discovery](https://github.com/libp2p/interface-peer-discovery) -- [Peer Routing](https://github.com/libp2p/interface-peer-routing) -- [Pubsub](https://github.com/libp2p/js-libp2p-pubsub) -- [Stream Muxer](https://github.com/libp2p/interface-stream-muxer) -- [Transport](https://github.com/libp2p/interface-transport) - -## Contribute - -The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: - - - Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - - **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - - **Add tests**. There can never be enough tests. - -## License - -[Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) © Protocol Labs diff --git a/packages/libp2p-interfaces/package.json b/packages/libp2p-interfaces/package.json deleted file mode 100644 index 59bde7d78..000000000 --- a/packages/libp2p-interfaces/package.json +++ /dev/null @@ -1,261 +0,0 @@ -{ - "name": "@libp2p/interfaces", - "version": "2.0.4", - "description": "Interfaces for JS Libp2p", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "interface", - "libp2p" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "typesVersions": { - "*": { - "*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ], - "src/*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ] - } - }, - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js", - "types": "./dist/src/index.d.ts" - }, - "./address-manager": { - "import": "./dist/src/address-manager.js", - "types": "./dist/src/address-manager.d.ts" - }, - "./components": { - "import": "./dist/src/components.js", - "types": "./dist/src/components.d.ts" - }, - "./connection": { - "import": "./dist/src/connection/index.js", - "types": "./dist/src/connection/index.d.ts" - }, - "./connection-encrypter": { - "import": "./dist/src/connection-encrypter/index.js", - "types": "./dist/src/connection-encrypter/index.d.ts" - }, - "./connection-encrypter/errors": { - "import": "./dist/src/connection-encrypter/errors.js", - "types": "./dist/src/connection-encrypter/errors.d.ts" - }, - "./connection-manager": { - "import": "./dist/src/connection-manager/index.js", - "types": "./dist/src/connection-manager/index.d.ts" - }, - "./connection/status": { - "import": "./dist/src/connection/status.js", - "types": "./dist/src/connection/status.d.ts" - }, - "./content-routing": { - "import": "./dist/src/content-routing/index.js", - "types": "./dist/src/content-routing/index.d.ts" - }, - "./dht": { - "import": "./dist/src/dht/index.js", - "types": "./dist/src/dht/index.d.ts" - }, - "./errors": { - "import": "./dist/src/errors.js", - "types": "./dist/src/errors.d.ts" - }, - "./events": { - "import": "./dist/src/events.js", - "types": "./dist/src/events.d.ts" - }, - "./keys": { - "import": "./dist/src/keys/index.js", - "types": "./dist/src/keys/index.d.ts" - }, - "./metrics": { - "import": "./dist/src/metrics/index.js", - "types": "./dist/src/metrics/index.d.ts" - }, - "./peer-discovery": { - "import": "./dist/src/peer-discovery/index.js", - "types": "./dist/src/peer-discovery/index.d.ts" - }, - "./peer-id": { - "import": "./dist/src/peer-id/index.js", - "types": "./dist/src/peer-id/index.d.ts" - }, - "./peer-info": { - "import": "./dist/src/peer-info/index.js", - "types": "./dist/src/peer-info/index.d.ts" - }, - "./peer-routing": { - "import": "./dist/src/peer-routing/index.js", - "types": "./dist/src/peer-routing/index.d.ts" - }, - "./peer-store": { - "import": "./dist/src/peer-store/index.js", - "types": "./dist/src/peer-store/index.d.ts" - }, - "./pubsub": { - "import": "./dist/src/pubsub/index.js", - "types": "./dist/src/pubsub/index.d.ts" - }, - "./record": { - "import": "./dist/src/record/index.js", - "types": "./dist/src/record/index.d.ts" - }, - "./registrar": { - "import": "./dist/src/registrar/index.js", - "types": "./dist/src/registrar/index.d.ts" - }, - "./startable": { - "import": "./dist/src/startable.js", - "types": "./dist/src/startable.d.ts" - }, - "./stream-muxer": { - "import": "./dist/src/stream-muxer/index.js", - "types": "./dist/src/stream-muxer/index.d.ts" - }, - "./topology": { - "import": "./dist/src/topology/index.js", - "types": "./dist/src/topology/index.d.ts" - }, - "./transport": { - "import": "./dist/src/transport/index.js", - "types": "./dist/src/transport/index.d.ts" - }, - "./value-store": { - "import": "./dist/src/value-store/index.js", - "types": "./dist/src/value-store/index.d.ts" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - } - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "build": "aegir build", - "release": "aegir release" - }, - "dependencies": { - "@multiformats/multiaddr": "^10.1.5", - "err-code": "^3.0.1", - "interface-datastore": "^6.1.0", - "it-pushable": "^2.0.1", - "it-stream-types": "^1.0.4", - "multiformats": "^9.6.3" - }, - "devDependencies": { - "aegir": "^37.0.7" - } -} diff --git a/packages/libp2p-interfaces/src/components.ts b/packages/libp2p-interfaces/src/components.ts deleted file mode 100644 index 6f33469c8..000000000 --- a/packages/libp2p-interfaces/src/components.ts +++ /dev/null @@ -1,444 +0,0 @@ -import errCode from 'err-code' -import type { ConnectionGater, ConnectionProtector } from './connection/index.js' -import type { ContentRouting } from './content-routing/index.js' -import type { AddressManager } from './address-manager/index.js' -import { isStartable, Startable } from './startable.js' -import type { Metrics } from './metrics/index.js' -import type { PeerId } from './peer-id/index.js' -import type { PeerRouting } from './peer-routing/index.js' -import type { PeerStore } from './peer-store/index.js' -import type { Registrar } from './registrar/index.js' -import type { TransportManager, Upgrader } from './transport/index.js' -import type { Datastore } from 'interface-datastore' -import type { PubSub } from './pubsub/index.js' -import type { DualDHT } from './dht/index.js' -import type { ConnectionManager } from './connection-manager/index.js' - -export interface Initializable { - init: (components: Components) => void -} - -export function isInitializable (obj: any): obj is Initializable { - return obj != null && typeof obj.init === 'function' -} - -export interface ComponentsInit { - peerId?: PeerId - addressManager?: AddressManager - peerStore?: PeerStore - upgrader?: Upgrader - metrics?: Metrics - registrar?: Registrar - connectionManager?: ConnectionManager - transportManager?: TransportManager - connectionGater?: ConnectionGater - contentRouting?: ContentRouting - peerRouting?: PeerRouting - datastore?: Datastore - connectionProtector?: ConnectionProtector - dht?: DualDHT - pubsub?: PubSub -} - -export class Components implements Startable { - private peerId?: PeerId - private addressManager?: AddressManager - private peerStore?: PeerStore - private upgrader?: Upgrader - private metrics?: Metrics - private registrar?: Registrar - private connectionManager?: ConnectionManager - private transportManager?: TransportManager - private connectionGater?: ConnectionGater - private contentRouting?: ContentRouting - private peerRouting?: PeerRouting - private datastore?: Datastore - private connectionProtector?: ConnectionProtector - private dht?: DualDHT - private pubsub?: PubSub - private started = false - - constructor (init: ComponentsInit = {}) { - if (init.peerId != null) { - this.setPeerId(init.peerId) - } - - if (init.addressManager != null) { - this.setAddressManager(init.addressManager) - } - - if (init.peerStore != null) { - this.setPeerStore(init.peerStore) - } - - if (init.upgrader != null) { - this.setUpgrader(init.upgrader) - } - - if (init.metrics != null) { - this.setMetrics(init.metrics) - } - - if (init.registrar != null) { - this.setRegistrar(init.registrar) - } - - if (init.connectionManager != null) { - this.setConnectionManager(init.connectionManager) - } - - if (init.transportManager != null) { - this.setTransportManager(init.transportManager) - } - - if (init.connectionGater != null) { - this.setConnectionGater(init.connectionGater) - } - - if (init.contentRouting != null) { - this.setContentRouting(init.contentRouting) - } - - if (init.peerRouting != null) { - this.setPeerRouting(init.peerRouting) - } - - if (init.datastore != null) { - this.setDatastore(init.datastore) - } - - if (init.connectionProtector != null) { - this.setConnectionProtector(init.connectionProtector) - } - - if (init.dht != null) { - this.setDHT(init.dht) - } - - if (init.pubsub != null) { - this.setPubSub(init.pubsub) - } - } - - isStarted () { - return this.started - } - - async beforeStart () { - await Promise.all( - Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => { - if (startable.beforeStart != null) { - await startable.beforeStart() - } - }) - ) - } - - async start () { - await Promise.all( - Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => { - await startable.start() - }) - ) - - this.started = true - } - - async afterStart () { - await Promise.all( - Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => { - if (startable.afterStart != null) { - await startable.afterStart() - } - }) - ) - } - - async beforeStop () { - await Promise.all( - Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => { - if (startable.beforeStop != null) { - await startable.beforeStop() - } - }) - ) - } - - async stop () { - await Promise.all( - Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => { - await startable.stop() - }) - ) - - this.started = false - } - - async afterStop () { - await Promise.all( - Object.values(this).filter(obj => isStartable(obj)).map(async (startable: Startable) => { - if (startable.afterStop != null) { - await startable.afterStop() - } - }) - ) - } - - setPeerId (peerId: PeerId) { - this.peerId = peerId - - return peerId - } - - getPeerId (): PeerId { - if (this.peerId == null) { - throw errCode(new Error('peerId not set'), 'ERR_SERVICE_MISSING') - } - - return this.peerId - } - - setMetrics (metrics: Metrics) { - this.metrics = metrics - - if (isInitializable(metrics)) { - metrics.init(this) - } - - return metrics - } - - getMetrics (): Metrics | undefined { - return this.metrics - } - - setAddressManager (addressManager: AddressManager) { - this.addressManager = addressManager - - if (isInitializable(addressManager)) { - addressManager.init(this) - } - - return addressManager - } - - getAddressManager (): AddressManager { - if (this.addressManager == null) { - throw errCode(new Error('addressManager not set'), 'ERR_SERVICE_MISSING') - } - - return this.addressManager - } - - setPeerStore (peerStore: PeerStore) { - this.peerStore = peerStore - - if (isInitializable(peerStore)) { - peerStore.init(this) - } - - return peerStore - } - - getPeerStore (): PeerStore { - if (this.peerStore == null) { - throw errCode(new Error('peerStore not set'), 'ERR_SERVICE_MISSING') - } - - return this.peerStore - } - - setUpgrader (upgrader: Upgrader) { - this.upgrader = upgrader - - if (isInitializable(upgrader)) { - upgrader.init(this) - } - - return upgrader - } - - getUpgrader (): Upgrader { - if (this.upgrader == null) { - throw errCode(new Error('upgrader not set'), 'ERR_SERVICE_MISSING') - } - - return this.upgrader - } - - setRegistrar (registrar: Registrar) { - this.registrar = registrar - - if (isInitializable(registrar)) { - registrar.init(this) - } - - return registrar - } - - getRegistrar (): Registrar { - if (this.registrar == null) { - throw errCode(new Error('registrar not set'), 'ERR_SERVICE_MISSING') - } - - return this.registrar - } - - setConnectionManager (connectionManager: ConnectionManager) { - this.connectionManager = connectionManager - - if (isInitializable(connectionManager)) { - connectionManager.init(this) - } - - return connectionManager - } - - getConnectionManager (): ConnectionManager { - if (this.connectionManager == null) { - throw errCode(new Error('connectionManager not set'), 'ERR_SERVICE_MISSING') - } - - return this.connectionManager - } - - setTransportManager (transportManager: TransportManager) { - this.transportManager = transportManager - - if (isInitializable(transportManager)) { - transportManager.init(this) - } - - return transportManager - } - - getTransportManager (): TransportManager { - if (this.transportManager == null) { - throw errCode(new Error('transportManager not set'), 'ERR_SERVICE_MISSING') - } - - return this.transportManager - } - - setConnectionGater (connectionGater: ConnectionGater) { - this.connectionGater = connectionGater - - if (isInitializable(connectionGater)) { - connectionGater.init(this) - } - - return connectionGater - } - - getConnectionGater (): ConnectionGater { - if (this.connectionGater == null) { - throw errCode(new Error('connectionGater not set'), 'ERR_SERVICE_MISSING') - } - - return this.connectionGater - } - - setContentRouting (contentRouting: ContentRouting) { - this.contentRouting = contentRouting - - if (isInitializable(contentRouting)) { - contentRouting.init(this) - } - - return contentRouting - } - - getContentRouting (): ContentRouting { - if (this.contentRouting == null) { - throw errCode(new Error('contentRouting not set'), 'ERR_SERVICE_MISSING') - } - - return this.contentRouting - } - - setPeerRouting (peerRouting: PeerRouting) { - this.peerRouting = peerRouting - - if (isInitializable(peerRouting)) { - peerRouting.init(this) - } - - return peerRouting - } - - getPeerRouting (): PeerRouting { - if (this.peerRouting == null) { - throw errCode(new Error('peerRouting not set'), 'ERR_SERVICE_MISSING') - } - - return this.peerRouting - } - - setDatastore (datastore: Datastore) { - this.datastore = datastore - - if (isInitializable(datastore)) { - datastore.init(this) - } - - return datastore - } - - getDatastore (): Datastore { - if (this.datastore == null) { - throw errCode(new Error('datastore not set'), 'ERR_SERVICE_MISSING') - } - - return this.datastore - } - - setConnectionProtector (connectionProtector: ConnectionProtector) { - this.connectionProtector = connectionProtector - - if (isInitializable(connectionProtector)) { - connectionProtector.init(this) - } - - return connectionProtector - } - - getConnectionProtector (): ConnectionProtector | undefined { - return this.connectionProtector - } - - setDHT (dht: DualDHT) { - this.dht = dht - - if (isInitializable(dht)) { - dht.init(this) - } - - return dht - } - - getDHT (): DualDHT { - if (this.dht == null) { - throw errCode(new Error('dht not set'), 'ERR_SERVICE_MISSING') - } - - return this.dht - } - - setPubSub (pubsub: PubSub) { - this.pubsub = pubsub - - if (isInitializable(pubsub)) { - pubsub.init(this) - } - - return pubsub - } - - getPubSub (): PubSub { - if (this.pubsub == null) { - throw errCode(new Error('pubsub not set'), 'ERR_SERVICE_MISSING') - } - - return this.pubsub - } -} diff --git a/packages/libp2p-interfaces/src/keys/README.md b/packages/libp2p-interfaces/src/keys/README.md deleted file mode 100644 index dfa14148f..000000000 --- a/packages/libp2p-interfaces/src/keys/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# interface-keys - -> Interfaces for libp2p keys - -## Table of Contents -- [Using the Test Suite](#using-the-test-suite) - -## Using the Test Suite - -You can also check out the [internal test suite](../../test/crypto/compliance.spec.js) to see the setup in action. - -```js -const tests = require('libp2p-interfaces-compliance-tests/keys') -const yourKeys = require('./your-keys') - -tests({ - setup () { - // Set up your keys if needed, then return it - return yourKeys - }, - teardown () { - // Clean up your keys if needed - } -}) -``` diff --git a/packages/libp2p-interfaces/src/registrar/index.ts b/packages/libp2p-interfaces/src/registrar/index.ts deleted file mode 100644 index f22bff16a..000000000 --- a/packages/libp2p-interfaces/src/registrar/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Connection, Stream } from '../connection/index.js' -import type { Topology } from '../topology/index.js' - -export interface IncomingStreamData { - protocol: string - stream: Stream - connection: Connection -} - -export interface StreamHandler { - (data: IncomingStreamData): void -} - -export interface Registrar { - getProtocols: () => string[] - handle: (protocol: string | string[], handler: StreamHandler) => Promise - unhandle: (protocol: string | string[]) => Promise - getHandler: (protocol: string) => StreamHandler - - register: (protocols: string | string[], topology: Topology) => Promise - unregister: (id: string) => void - getTopologies: (protocol: string) => Topology[] -} diff --git a/packages/libp2p-interfaces/src/topology/README.md b/packages/libp2p-interfaces/src/topology/README.md deleted file mode 100644 index 7caa4b13f..000000000 --- a/packages/libp2p-interfaces/src/topology/README.md +++ /dev/null @@ -1,128 +0,0 @@ -interface-topology -======================== - -> Implementation of the topology interface used by the `js-libp2p` registrar. - -Topologies can be used in conjunction with `js-libp2p` to help shape its network and the overlays of its subsystems, such as pubsub and the DHT. - -## Table of Contents - -- [Implementations](#implementations) -- [Install](#install) -- [Modules using the interface](#modulesUsingTheInterface) -- [Usage](#usage) -- [Api](#api) - -## Implementations - -### Topology - -A libp2p topology with a group of common peers. - -### Multicodec Topology - -A libp2p topology with a group of peers that support the same protocol. - -## Install - -```sh -$ npm install libp2p-interfaces -``` - -## Modules using the interface - -TBA - -## Usage - -### Topology - -```js -import { createTopology } from '@libp2p/topology' - -const toplogy = createTopology({ - min: 0, - max: 50, - multicodecs: ['/echo/1.0.0'], - onConnect: (peerId, conn) => {}, - onDisconnect: (peerId) => {} -}) -``` - -## API - -### Topology - -- `Topology` - - `peers>`: A Map of peers belonging to the topology. - - `disconnect`: Called when a peer has been disconnected - -#### Constructor - -```js -import { createTopology } from '@libp2p/topology' - -const toplogy = createTopology({ - min: 0, - max: 50, - onConnect: (peerId, conn) => {}, - onDisconnect: (peerId) => {} -}) -``` - -**Parameters** -- `properties` is an `Object` containing the properties of the topology. - - `min` is a `number` with the minimum needed connections (default: 0) - - `max` is a `number` with the maximum needed connections (default: Infinity) - - `handlers` is an optional `Object` containing the handler called when a peer is connected or disconnected. - - `onConnect` is a `function` called everytime a peer is connected in the topology context. - - `onDisconnect` is a `function` called everytime a peer is disconnected in the topology context. - -#### Set a peer - -- `topology.peers.set(id, peerId)` - -Add a peer to the topology. - -**Parameters** -- `id` is the `string` that identifies the peer to add. -- `peerId` is the [PeerId][peer-id] of the peer to add. - -#### Notify about a peer disconnected event - -- `topology.disconnect(peerId)` - -**Parameters** -- `peerId` is the [PeerId][peer-id] of the peer disconnected. - -### Multicodec Topology - -- `MulticodecTopology` - - `registrar`: The `Registrar` of the topology. This is set by the `Registrar` during registration. - - `peers>`: The Map of peers that belong to the topology - - `disconnect`: Disconnects a peer from the topology. - -#### Constructor - -```js -const toplogy = new MulticodecTopology({ - min: 0, - max: 50, - multicodecs: ['/echo/1.0.0'], - handlers: { - onConnect: (peerId, conn) => {}, - onDisconnect: (peerId) => {} - } -}) -``` - -**Parameters** -- `properties` is an `Object` containing the properties of the topology. - - `min` is a `number` with the minimum needed connections (default: 0) - - `max` is a `number` with the maximum needed connections (default: Infinity) - - `multicodecs` is a `Array` with the multicodecs associated with the topology. - - `handlers` is an optional `Object` containing the handler called when a peer is connected or disconnected. - - `onConnect` is a `function` called everytime a peer is connected in the topology context. - - `onDisconnect` is a `function` called everytime a peer is disconnected in the topology context. - -[peer-id]: https://github.com/libp2p/js-peer-id diff --git a/packages/libp2p-interfaces/src/topology/index.ts b/packages/libp2p-interfaces/src/topology/index.ts deleted file mode 100644 index b9372354e..000000000 --- a/packages/libp2p-interfaces/src/topology/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { PeerId } from '../peer-id/index.js' -import type { Connection } from '../connection/index.js' -import type { Registrar } from '../registrar/index.js' - -export interface onConnectHandler { - (peerId: PeerId, conn: Connection): void -} - -export interface onDisconnectHandler { - (peerId: PeerId, conn?: Connection): void -} - -export interface TopologyInit { - /** - * minimum needed connections - */ - min?: number - - /** - * maximum needed connections - */ - max?: number - onConnect?: onConnectHandler - onDisconnect?: onDisconnectHandler -} - -export interface Topology { - min: number - max: number - peers: Set - - onConnect: (peerId: PeerId, conn: Connection) => void - onDisconnect: (peerId: PeerId) => void - setRegistrar: (registrar: Registrar) => Promise -} - -export const symbol = Symbol.for('@libp2p/topology') - -export function isTopology (other: any): other is Topology { - return other != null && Boolean(other[symbol]) -} diff --git a/packages/libp2p-interfaces/src/value-store/README.md b/packages/libp2p-interfaces/src/value-store/README.md deleted file mode 100644 index 5a9384a2b..000000000 --- a/packages/libp2p-interfaces/src/value-store/README.md +++ /dev/null @@ -1,70 +0,0 @@ -interface-value-store -===================== - -**WIP: This module is not yet implemented** - -> A test suite and interface you can use to implement a Value Store module for libp2p. - -A Value Store is a key/value storage interface that may be used to provide libp2p services such as Content Routing, service advertisment, etc. - -The primary goal of this module is to enable developers to pick and swap their Value Store module as they see fit for their libp2p installation, without having to go through shims or compatibility issues. This module and test suite were heavily inspired by abstract-blob-store and interface-stream-muxer. - -Publishing a test suite as a module lets multiple modules all ensure compatibility since they use the same test suite. - -# Modules that implement the interface - -- [JavaScript libp2p-kad-dht](https://github.com/libp2p/js-libp2p-kad-dht) -- [JavaScript libp2p-delegated-content-routing](https://github.com/libp2p/js-libp2p-delegated-content-routing) - - provided by the `DelegatedValueStore` class - -# How to use the battery of tests - -## Node.js - -TBD - -# API - -A valid (read: that follows this abstraction) Content Routing module must implement the following API. - -### put - -- `put(key, value, options)` - -Associate a value with the given key. - -**Parameters** -- `key`: `Uint8Array` - the key used to identify the value. -- `value`: `Uint8Array` - the value to associate with the key. -- `options`: `object | undefined` -- `options.timeout`: `number` - timeout in ms. - -Note that implementations may specify additional options, and must ignore unknown options. - -**Returns** - -A `Promise` that will resolve with no value on success, or fail with an `Error` if something goes wrong. - -### get - -- `get(key, options)` - -Fetch the value for the given key. - -**Parameters** -- `key`: `Uint8Array` - the key used to identify the value. -- `options`: `object | undefined` -- `options.timeout`: `number` - timeout in ms. - -Note that implementations may specify additional options, and must ignore unknown options. - -**Returns** - -A `Promise` that resolves with an object of the following shape on success: - -```js -{ - from: PeerId, - val: Uint8Array, -} -``` diff --git a/packages/libp2p-interfaces/src/value-store/index.ts b/packages/libp2p-interfaces/src/value-store/index.ts deleted file mode 100644 index a514d6553..000000000 --- a/packages/libp2p-interfaces/src/value-store/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { PeerId } from '../peer-id/index.js' - -export interface GetValueResult { - from: PeerId - val: Uint8Array -} - -export interface ValueStore { - put: (key: Uint8Array, value: Uint8Array, options?: Object) => Promise - get: (key: Uint8Array, options?: Object) => Promise -} - -export default ValueStore diff --git a/packages/libp2p-logger/CHANGELOG.md b/packages/libp2p-logger/CHANGELOG.md deleted file mode 100644 index 8d66510bb..000000000 --- a/packages/libp2p-logger/CHANGELOG.md +++ /dev/null @@ -1,88 +0,0 @@ -## [@libp2p/logger-v1.1.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.1.4...@libp2p/logger-v1.1.5) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/logger-v1.1.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.1.3...@libp2p/logger-v1.1.4) (2022-04-14) - - -### Bug Fixes - -* add logger methods, fix peer id deserialization ([#194](https://github.com/libp2p/js-libp2p-interfaces/issues/194)) ([f0e1fad](https://github.com/libp2p/js-libp2p-interfaces/commit/f0e1fad42701d73eef4233ec2b9a8aafa0b2ab96)) - -## [@libp2p/logger-v1.1.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.1.2...@libp2p/logger-v1.1.3) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/logger-v1.1.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.1.1...@libp2p/logger-v1.1.2) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/logger-v1.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.1.0...@libp2p/logger-v1.1.1) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/logger-v1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.0.4...@libp2p/logger-v1.1.0) (2022-02-26) - - -### Features - -* add trace option to logger ([#177](https://github.com/libp2p/js-libp2p-interfaces/issues/177)) ([19774eb](https://github.com/libp2p/js-libp2p-interfaces/commit/19774ebe05cc4ff8c8200dfdde046016abf5d19e)) - -## [@libp2p/logger-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.0.3...@libp2p/logger-v1.0.4) (2022-02-21) - - -### Bug Fixes - -* remove unused dht query option ([#176](https://github.com/libp2p/js-libp2p-interfaces/issues/176)) ([e0ce46d](https://github.com/libp2p/js-libp2p-interfaces/commit/e0ce46d371a92a7063f02e7a1729a39def80e15e)) - -## [@libp2p/logger-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.0.2...@libp2p/logger-v1.0.3) (2022-02-11) - - -### Bug Fixes - -* log cids ([#165](https://github.com/libp2p/js-libp2p-interfaces/issues/165)) ([68831e8](https://github.com/libp2p/js-libp2p-interfaces/commit/68831e804630e1f45ffee56a7585af62072d7145)) - -## [@libp2p/logger-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.0.1...@libp2p/logger-v1.0.2) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## [@libp2p/logger-v1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/logger-v1.0.0...@libp2p/logger-v1.0.1) (2022-02-07) - - -### Bug Fixes - -* add logging formatters ([#159](https://github.com/libp2p/js-libp2p-interfaces/issues/159)) ([2fa518c](https://github.com/libp2p/js-libp2p-interfaces/commit/2fa518c7489dcd31d5b28f79114dfdc94133d784)) - -## @libp2p/logger-v1.0.0 (2022-02-07) - - -### Features - -* add logger package ([#158](https://github.com/libp2p/js-libp2p-interfaces/issues/158)) ([f327cd2](https://github.com/libp2p/js-libp2p-interfaces/commit/f327cd24825d9ce2f45a02fdb9b47c9735c847e0)) - -## @libp2p/tracked-map-v1.0.0 (2022-02-05) - - -### Features - -* add tracked-map ([#156](https://github.com/libp2p/js-libp2p-interfaces/issues/156)) ([c17730f](https://github.com/libp2p/js-libp2p-interfaces/commit/c17730f8bca172db85507740eaba81b3cf514d04)) diff --git a/packages/libp2p-logger/README.md b/packages/libp2p-logger/README.md deleted file mode 100644 index 9e3263896..000000000 --- a/packages/libp2p-logger/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# libp2p-logger - -> A logging component for use in js-libp2p components - -## Table of Contents - -- [Description](#description) -- [Installation](#installation) -- [Example](#example) -- [License](#license) - - [Contribution](#contribution) - -## Description - -A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. - -If metrics are disabled a regular map is used. - -## Installation - -```console -$ npm i @libp2p/logger -``` - -## Example - -```JavaScript -import { logger } from '@libp2p/logger' - -const log = logger('libp2p:my:component:name') - -log('something happened: %s', 'it was ok') -log.error('something bad happened: %o', err) - -log('with this peer: %p', aPeerId) -log('and this base58btc: %b', aUint8Array) -log('and this base32: %t', aUint8Array) -``` - -```console -$ DEBUG=libp2p:* node index.js -something happened: it was ok -something bad happened: -with this peer: 12D3Foo -with this base58btc: Qmfoo -with this base32: bafyfoo -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-logger/src/index.ts b/packages/libp2p-logger/src/index.ts deleted file mode 100644 index 164918a93..000000000 --- a/packages/libp2p-logger/src/index.ts +++ /dev/null @@ -1,63 +0,0 @@ -import debug from 'debug' -import { base58btc } from 'multiformats/bases/base58' -import { base32 } from 'multiformats/bases/base32' -import { base64 } from 'multiformats/bases/base64' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { CID } from 'multiformats/cid' -import type { Key } from 'interface-datastore' - -// Add a formatter for converting to a base58 string -debug.formatters.b = (v?: Uint8Array) => { - return v == null ? 'undefined' : base58btc.baseEncode(v) -} - -// Add a formatter for converting to a base32 string -debug.formatters.t = (v?: Uint8Array) => { - return v == null ? 'undefined' : base32.baseEncode(v) -} - -// Add a formatter for converting to a base64 string -debug.formatters.m = (v?: Uint8Array) => { - return v == null ? 'undefined' : base64.baseEncode(v) -} - -// Add a formatter for stringifying peer ids -debug.formatters.p = (v?: PeerId) => { - return v == null ? 'undefined' : v.toString() -} - -// Add a formatter for stringifying CIDs -debug.formatters.c = (v?: CID) => { - return v == null ? 'undefined' : v.toString() -} - -// Add a formatter for stringifying Datastore keys -debug.formatters.k = (v: Key) => { - return v == null ? 'undefined' : v.toString() -} - -export interface Logger { - (formatter: any, ...args: any[]): void - error: (formatter: any, ...args: any[]) => void - trace: (formatter: any, ...args: any[]) => void - enabled: boolean -} - -export function logger (name: string): Logger { - return Object.assign(debug(name), { - error: debug(`${name}:error`), - trace: debug(`${name}:trace`) - }) -} - -export function disable () { - debug.disable() -} - -export function enable (namespaces: string) { - debug.enable(namespaces) -} - -export function enabled (namespaces: string) { - return debug.enabled(namespaces) -} diff --git a/packages/libp2p-logger/test/index.spec.ts b/packages/libp2p-logger/test/index.spec.ts deleted file mode 100644 index 71d2b4822..000000000 --- a/packages/libp2p-logger/test/index.spec.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { expect } from 'aegir/chai' -import { logger } from '../src/index.js' - -describe('logger', () => { - it('creates a logger', () => { - const log = logger('hello') - - expect(log).to.be.a('function') - expect(log).to.have.property('error').that.is.a('function') - expect(log).to.have.property('enabled') - }) -}) diff --git a/packages/libp2p-multistream-select/CHANGELOG.md b/packages/libp2p-multistream-select/CHANGELOG.md deleted file mode 100644 index 2a5a8652f..000000000 --- a/packages/libp2p-multistream-select/CHANGELOG.md +++ /dev/null @@ -1,53 +0,0 @@ -## [@libp2p/multistream-select-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/multistream-select-v1.0.5...@libp2p/multistream-select-v1.0.6) (2022-05-24) - - -### Bug Fixes - -* chunk data in mock muxer ([#218](https://github.com/libp2p/js-libp2p-interfaces/issues/218)) ([14604f6](https://github.com/libp2p/js-libp2p-interfaces/commit/14604f69a858bf8c16ce118420c5e49f3f5331ea)) - -## [@libp2p/multistream-select-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/multistream-select-v1.0.4...@libp2p/multistream-select-v1.0.5) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/multistream-select-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/multistream-select-v1.0.3...@libp2p/multistream-select-v1.0.4) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/multistream-select-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/multistream-select-v1.0.2...@libp2p/multistream-select-v1.0.3) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/multistream-select-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/multistream-select-v1.0.1...@libp2p/multistream-select-v1.0.2) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/multistream-select-v1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/multistream-select-v1.0.0...@libp2p/multistream-select-v1.0.1) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## @libp2p/multistream-select-v1.0.0 (2022-02-17) - - -### Bug Fixes - -* add multistream-select and update pubsub types ([#170](https://github.com/libp2p/js-libp2p-interfaces/issues/170)) ([b9ecb2b](https://github.com/libp2p/js-libp2p-interfaces/commit/b9ecb2bee8f2abc0c41bfcf7bf2025894e37ddc2)) diff --git a/packages/libp2p-multistream-select/README.md b/packages/libp2p-multistream-select/README.md deleted file mode 100644 index c4330554a..000000000 --- a/packages/libp2p-multistream-select/README.md +++ /dev/null @@ -1,290 +0,0 @@ -# js-multistream-select - -[![](https://img.shields.io/badge/made%20by-Protocol%20Labs-blue.svg?style=flat-square)](https://protocol.ai) -[![](https://img.shields.io/badge/project-multiformats-blue.svg?style=flat-square)](https://github.com/multiformats/multiformats) -[![](https://img.shields.io/badge/freenode-%23ipfs-blue.svg?style=flat-square)](https://webchat.freenode.net/?channels=%23ipfs) -[![](https://img.shields.io/codecov/c/github/multiformats/js-multistream-select.svg?style=flat-square)](https://codecov.io/gh/multiformats/js-multistream-select) -[![](https://img.shields.io/travis/multiformats/js-multistream-select.svg?style=flat-square)](https://travis-ci.com/multiformats/js-multistream-select) -[![Dependency Status](https://david-dm.org/multiformats/js-multistream-select.svg?style=flat-square)](https://david-dm.org/multiformats/js-multistream-select) -[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat-square)](https://github.com/feross/standard) - -> JavaScript implementation of [multistream-select](https://github.com/multiformats/multistream-select) - -## Lead Maintainer - -[Jacob Heun](https://github.com/jacobheun) - -## Table of Contents - -- [Background](#background) - - [What is `multistream-select`?](#what-is-multistream-select) - - [Select a protocol flow](#select-a-protocol-flow) -- [Install](#install) -- [Usage](#usage) - - [Dialer](#dialer) - - [Listener](#listener) -- [API](#api) - - [`new MSS.Dialer(duplex)`](#new-mssdialerduplex) - - [Parameters](#parameters) - - [Returns](#returns) - - [Examples](#examples) - - [`dialer.select(protocols, [options])`](#dialerselectprotocols-options) - - [Parameters](#parameters-1) - - [Returns](#returns-1) - - [Examples](#examples-1) - - [`dialer.ls([options])`](#dialerlsoptions) - - [Parameters](#parameters-2) - - [Returns](#returns-2) - - [Examples](#examples-2) - - [`new MSS.Listener(duplex)`](#new-msslistenerduplex) - - [Parameters](#parameters-3) - - [Returns](#returns-3) - - [Examples](#examples-3) - - [`listener.handle(protocols, [options])`](#listenerhandleprotocols-options) - - [Parameters](#parameters-4) - - [Returns](#returns-4) - - [Examples](#examples-4) -- [Contribute](#contribute) -- [License](#license) - -## Background - -### What is `multistream-select`? - -TLDR; multistream-select is protocol multiplexing per connection/stream. [Full spec here](https://github.com/multiformats/multistream-select) - -#### Select a protocol flow - -The caller will send "interactive" messages, expecting for some acknowledgement from the callee, which will "select" the handler for the desired and supported protocol: - -```console -< /multistream-select/0.3.0 # i speak multistream-select/0.3.0 -> /multistream-select/0.3.0 # ok, let's speak multistream-select/0.3.0 -> /ipfs-dht/0.2.3 # i want to speak ipfs-dht/0.2.3 -< na # ipfs-dht/0.2.3 is not available -> /ipfs-dht/0.1.9 # What about ipfs-dht/0.1.9 ? -< /ipfs-dht/0.1.9 # ok let's speak ipfs-dht/0.1.9 -- in a sense acts as an ACK -> -> -> -``` - -This mode also packs a `ls` option, so that the callee can list the protocols it currently supports - -## Install - -```sh -npm i multistream-select -``` - -## Usage - -```js -const MSS = require('multistream-select') -// You can now use -// MSS.Dialer - actively select a protocol with a remote -// MSS.Listener - handle a protocol with a remote -``` - -### Dialer - -```js -import { pipe } from 'it-pipe' -const MSS = require('multistream-select') -const Mplex = require('libp2p-mplex') - -const muxer = new Mplex() -const muxedStream = muxer.newStream() - -const mss = new MSS.Dialer(muxedStream) - -// mss.select(protocol(s)) -// Select from one of the passed protocols (in priority order) -// Returns selected stream and protocol -const { stream: dhtStream, protocol } = await mss.select([ - // This might just be different versions of DHT, but could be different impls - '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item. - '/ipfs-dht/1.0.0' -]) - -// Typically this stream will be passed back to the caller of libp2p.dialProtocol -// -// ...it might then do something like this: -// try { -// await pipe( -// [uint8ArrayFromString('Some DHT data')] -// dhtStream, -// async source => { -// for await (const chunk of source) -// // DHT response data -// } -// ) -// } catch (err) { -// // Error in stream -// } -``` - -### Listener - -```js -import { pipe } from 'it-pipe' -const MSS = require('multistream-select') -const Mplex = require('libp2p-mplex') - -const muxer = new Mplex({ - async onStream (muxedStream) { - const mss = new MSS.Listener(muxedStream) - - // mss.handle(handledProtocols) - // Returns selected stream and protocol - const { stream, protocol } = await mss.handle([ - '/ipfs-dht/1.0.0', - '/ipfs-bitswap/1.0.0' - ]) - - // Typically here we'd call the handler function that was registered in - // libp2p for the given protocol: - // e.g. handlers[protocol].handler(stream) - // - // If protocol was /ipfs-dht/1.0.0 it might do something like this: - // try { - // await pipe( - // dhtStream, - // source => (async function * () { - // for await (const chunk of source) - // // Incoming DHT data -> process and yield to respond - // })(), - // dhtStream - // ) - // } catch (err) { - // // Error in stream - // } - } -}) -``` - -## API - -### `new MSS.Dialer(duplex)` - -Create a new multistream select "dialer" instance which can be used to negotiate a protocol to use, list all available protocols the remote supports, or do both. - -#### Parameters - -* `duplex` (`Object`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to dial on. - -#### Returns - -A new multistream select dialer instance. - -#### Examples - -```js -const dialer = new MSS.Dialer(duplex) -``` - -### `dialer.select(protocols, [options])` - -Negotiate a protocol to use from a list of protocols. - -#### Parameters - -* `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) to negotiate with. Protocols are attempted in order until a match is made. -* `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal - -#### Returns - -`Promise<{ stream, protocol }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`. - -Note that after a protocol is selected `dialer` can no longer be used. - -#### Examples - -```js -const { stream, protocol } = await dialer.select([ - // This might just be different versions of DHT, but could be different impls - '/ipfs-dht/2.0.0', // Most of the time this will probably just be one item. - '/ipfs-dht/1.0.0' -]) -// Now talk `protocol` on `stream` -``` - -### `dialer.ls([options])` - -List protocols that the remote supports. - -#### Parameters - -* `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal - -#### Returns - -`String[]` - A list of all the protocols the remote supports. - -#### Examples - -```js -const protocols = await dialer.ls() -const wantedProto = '/ipfs-dht/2.0.0' - -if (!protocols.includes(wantedProto)) { - throw new Error('remote does not support ' + wantedProto) -} - -// Now use dialer.select to use wantedProto, safe in the knowledge it is supported -``` - -### `new MSS.Listener(duplex)` - -Construct a new multistream select "listener" instance which can be used to handle multistream protocol selections for particular protocols. - -#### Parameters - -* `duplex` (`Object`) - A [duplex iterable stream](https://gist.github.com/alanshaw/591dc7dd54e4f99338a347ef568d6ee9#duplex-it) to listen on. - -#### Returns - -A new multistream select listener instance. - -#### Examples - -```js -const listener = new MSS.Listener(duplex) -``` - -### `listener.handle(protocols, [options])` - -Handle multistream protocol selections for the given list of protocols. - -#### Parameters - -* `protocols` (`String[]`/`String`) - A list of protocols (or single protocol) that this listener is able to speak. -* `options` (`{ signal: AbortSignal }`) - an options object containing an AbortSignal - -#### Returns - -`Promise<{ stream, protocol }>` - A stream for the selected protocol and the protocol that was selected from the list of protocols provided to `select`. - -Note that after a protocol is handled `listener` can no longer be used. - -#### Examples - -```js -const { stream, protocol } = await listener.handle([ - '/ipfs-dht/1.0.0', - '/ipfs-bitswap/1.0.0' -]) -// Remote wants to speak `protocol` -``` - -## Contribute - -Contributions welcome. Please check out [the issues](https://github.com/multiformats/js-multistream-select/issues). - -Check out our [contributing document](https://github.com/multiformats/multiformats/blob/master/contributing.md) for more information on how we work, and about contributing in general. Please be aware that all interactions related to multiformats are subject to the IPFS [Code of Conduct](https://github.com/ipfs/community/blob/master/code-of-conduct.md). - -Small note: If editing the README, please conform to the [standard-readme](https://github.com/RichardLitt/standard-readme) specification. - -## License - -[MIT](LICENSE) diff --git a/packages/libp2p-multistream-select/src/constants.ts b/packages/libp2p-multistream-select/src/constants.ts deleted file mode 100644 index b23b8f12b..000000000 --- a/packages/libp2p-multistream-select/src/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ - -export const PROTOCOL_ID = '/multistream/1.0.0' diff --git a/packages/libp2p-multistream-select/src/handle.ts b/packages/libp2p-multistream-select/src/handle.ts deleted file mode 100644 index 5f625f739..000000000 --- a/packages/libp2p-multistream-select/src/handle.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { logger } from '@libp2p/logger' -import * as multistream from './multistream.js' -import { handshake } from 'it-handshake' -import { PROTOCOL_ID } from './constants.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { Uint8ArrayList } from 'uint8arraylist' -import type { AbortOptions } from '@libp2p/interfaces' -import type { Duplex } from 'it-stream-types' - -const log = logger('libp2p:mss:handle') - -export async function handle (stream: Duplex, protocols: string | string[], options?: AbortOptions) { - protocols = Array.isArray(protocols) ? protocols : [protocols] - const { writer, reader, rest, stream: shakeStream } = handshake(stream) - - while (true) { - const protocol = await multistream.readString(reader, options) - log('read "%s"', protocol) - - if (protocol === PROTOCOL_ID) { - log('respond with "%s" for "%s"', PROTOCOL_ID, protocol) - multistream.write(writer, uint8ArrayFromString(PROTOCOL_ID)) - continue - } - - if (protocols.includes(protocol)) { - multistream.write(writer, uint8ArrayFromString(protocol)) - log('respond with "%s" for "%s"', protocol, protocol) - rest() - return { stream: shakeStream, protocol } - } - - if (protocol === 'ls') { - // \n\n\n - multistream.write(writer, new Uint8ArrayList(...protocols.map(p => multistream.encode(uint8ArrayFromString(p))))) - log('respond with "%s" for %s', protocols, protocol) - continue - } - - multistream.write(writer, uint8ArrayFromString('na')) - log('respond with "na" for "%s"', protocol) - } -} diff --git a/packages/libp2p-multistream-select/src/index.ts b/packages/libp2p-multistream-select/src/index.ts deleted file mode 100644 index caca997a0..000000000 --- a/packages/libp2p-multistream-select/src/index.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { select } from './select.js' -import { handle } from './handle.js' -import { ls } from './ls.js' -import { PROTOCOL_ID } from './constants.js' -import type { Duplex } from 'it-stream-types' -import type { AbortOptions } from '@libp2p/interfaces' - -export { PROTOCOL_ID } - -export interface ProtocolStream { - stream: Duplex - protocol: string -} - -class MultistreamSelect { - protected stream: Duplex - protected shaken: boolean - - constructor (stream: Duplex) { - this.stream = stream - this.shaken = false - } - - /** - * Perform the multistream-select handshake - * - * @param {AbortOptions} [options] - */ - async _handshake (options?: AbortOptions): Promise { - if (this.shaken) { - return - } - - const { stream } = await select(this.stream, PROTOCOL_ID, undefined, options) - this.stream = stream - this.shaken = true - } -} - -export class Dialer extends MultistreamSelect { - async select (protocols: string | string[], options?: AbortOptions): Promise { - return await select(this.stream, protocols, this.shaken ? undefined : PROTOCOL_ID, options) - } - - async ls (options?: AbortOptions): Promise { - await this._handshake(options) - const res = await ls(this.stream, options) - const { stream, protocols } = res - this.stream = stream - return protocols - } -} - -export class Listener extends MultistreamSelect { - async handle (protocols: string | string[], options?: AbortOptions): Promise { - return await handle(this.stream, protocols, options) - } -} diff --git a/packages/libp2p-multistream-select/src/ls.ts b/packages/libp2p-multistream-select/src/ls.ts deleted file mode 100644 index b2a84e229..000000000 --- a/packages/libp2p-multistream-select/src/ls.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { reader as createReader } from 'it-reader' -import { logger } from '@libp2p/logger' -import * as multistream from './multistream.js' -import { handshake } from 'it-handshake' -import * as lp from 'it-length-prefixed' -import { pipe } from 'it-pipe' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import type { Duplex } from 'it-stream-types' -import type { AbortOptions } from '@libp2p/interfaces' - -const log = logger('libp2p:mss:ls') - -export async function ls (stream: Duplex, options?: AbortOptions): Promise<{ stream: Duplex, protocols: string[] }> { - const { reader, writer, rest, stream: shakeStream } = handshake(stream) - - log('write "ls"') - multistream.write(writer, uint8ArrayFromString('ls')) - rest() - - // Next message from remote will be (e.g. for 2 protocols): - // \n\n - const res = await multistream.read(reader, options) - - // After reading response we have: - // \n\n - const protocolsReader = createReader([res]) - const protocols: string[] = [] - - // Decode each of the protocols from the reader - await pipe( - protocolsReader, - lp.decode(), - async (source) => { - for await (const protocol of source) { - // Remove the newline - protocols.push(uint8ArrayToString(protocol.slice(0, -1))) - } - } - ) - - const output = { stream: shakeStream, protocols } - - return output -} diff --git a/packages/libp2p-multistream-select/src/multistream.ts b/packages/libp2p-multistream-select/src/multistream.ts deleted file mode 100644 index 316720f19..000000000 --- a/packages/libp2p-multistream-select/src/multistream.ts +++ /dev/null @@ -1,82 +0,0 @@ - -import { Uint8ArrayList } from 'uint8arraylist' -import * as lp from 'it-length-prefixed' -import { pipe } from 'it-pipe' -import errCode from 'err-code' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import first from 'it-first' -import { abortableSource } from 'abortable-iterator' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import type { Pushable } from 'it-pushable' -import type { AbortOptions } from '@libp2p/interfaces' -import type { Source } from 'it-stream-types' -import type { Reader } from 'it-reader' - -const NewLine = uint8ArrayFromString('\n') - -export function encode (buffer: Uint8Array | Uint8ArrayList): Uint8Array { - const list = new Uint8ArrayList(buffer, NewLine) - - return lp.encode.single(list).slice() -} - -/** - * `write` encodes and writes a single buffer - */ -export function write (writer: Pushable, buffer: Uint8Array | Uint8ArrayList) { - writer.push(encode(buffer).slice()) -} - -/** - * `writeAll` behaves like `write`, except it encodes an array of items as a single write - */ -export function writeAll (writer: Pushable, buffers: Uint8Array[]) { - const list = new Uint8ArrayList() - - for (const buf of buffers) { - list.append(encode(buf)) - } - - writer.push(list.slice()) -} - -export async function read (reader: Reader, options?: AbortOptions) { - let byteLength = 1 // Read single byte chunks until the length is known - const varByteSource = { // No return impl - we want the reader to remain readable - [Symbol.asyncIterator]: () => varByteSource, - next: async () => await reader.next(byteLength) - } - - let input: Source = varByteSource - - // If we have been passed an abort signal, wrap the input source in an abortable - // iterator that will throw if the operation is aborted - if (options?.signal != null) { - input = abortableSource(varByteSource, options.signal) - } - - // Once the length has been parsed, read chunk for that length - const onLength = (l: number) => { byteLength = l } - - const buf = await pipe( - input, - lp.decode({ onLength }), - async (source) => await first(source) - ) - - if (buf == null) { - throw errCode(new Error('no buffer returned'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE') - } - - if (buf[buf.length - 1] !== NewLine[0]) { - throw errCode(new Error('missing newline'), 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE') - } - - return buf.slice(0, -1) // Remove newline -} - -export async function readString (reader: Reader, options?: AbortOptions) { - const buf = await read(reader, options) - - return uint8ArrayToString(buf) -} diff --git a/packages/libp2p-multistream-select/src/select.ts b/packages/libp2p-multistream-select/src/select.ts deleted file mode 100644 index 4b1b5ad2a..000000000 --- a/packages/libp2p-multistream-select/src/select.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { logger } from '@libp2p/logger' -import errCode from 'err-code' -import * as multistream from './multistream.js' -import { handshake } from 'it-handshake' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import type { AbortOptions } from '@libp2p/interfaces' -import type { Duplex } from 'it-stream-types' - -const log = logger('libp2p:mss:select') - -export async function select (stream: Duplex, protocols: string | string[], protocolId?: string, options?: AbortOptions) { - protocols = Array.isArray(protocols) ? [...protocols] : [protocols] - const { reader, writer, rest, stream: shakeStream } = handshake(stream) - - const protocol = protocols.shift() - - if (protocol == null) { - throw new Error('At least one protocol must be specified') - } - - if (protocolId != null) { - log('select: write ["%s", "%s"]', protocolId, protocol) - multistream.writeAll(writer, [uint8ArrayFromString(protocolId), uint8ArrayFromString(protocol)]) - } else { - log('select: write "%s"', protocol) - multistream.write(writer, uint8ArrayFromString(protocol)) - } - - let response = await multistream.readString(reader, options) - log('select: read "%s"', response) - - // Read the protocol response if we got the protocolId in return - if (response === protocolId) { - response = await multistream.readString(reader, options) - log('select: read "%s"', response) - } - - // We're done - if (response === protocol) { - rest() - return { stream: shakeStream, protocol } - } - - // We haven't gotten a valid ack, try the other protocols - for (const protocol of protocols) { - log('select: write "%s"', protocol) - multistream.write(writer, uint8ArrayFromString(protocol)) - const response = await multistream.readString(reader, options) - log('select: read "%s" for "%s"', response, protocol) - - if (response === protocol) { - rest() // End our writer so others can start writing to stream - return { stream: shakeStream, protocol } - } - } - - rest() - throw errCode(new Error('protocol selection failed'), 'ERR_UNSUPPORTED_PROTOCOL') -} diff --git a/packages/libp2p-multistream-select/test/dialer.spec.ts b/packages/libp2p-multistream-select/test/dialer.spec.ts deleted file mode 100644 index 04a8cf1e4..000000000 --- a/packages/libp2p-multistream-select/test/dialer.spec.ts +++ /dev/null @@ -1,175 +0,0 @@ -/* eslint-env mocha */ -/* eslint max-nested-callbacks: ["error", 5] */ - -import { expect } from 'aegir/chai' -import { pipe } from 'it-pipe' -import all from 'it-all' -import { Uint8ArrayList } from 'uint8arraylist' -import { pair } from 'it-pair' -import { reader } from 'it-reader' -import pTimeout from 'p-timeout' -import randomBytes from 'iso-random-stream/src/random.js' -import * as Multistream from '../src/multistream.js' -import { Dialer, PROTOCOL_ID } from '../src/index.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import map from 'it-map' -import type { Duplex } from 'it-stream-types' - -describe('Dialer', () => { - describe('dialer.select', () => { - it('should select from single protocol', async () => { - const protocol = '/echo/1.0.0' - const duplex = pair() - - const mss = new Dialer(duplex) - const selection = await mss.select(protocol) - expect(selection.protocol).to.equal(protocol) - - // Ensure stream is usable after selection - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - const output = await pipe(input, selection.stream, async (source) => await all(source)) - expect(new Uint8ArrayList(...output).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - - it('should fail to select twice', async () => { - const protocol = '/echo/1.0.0' - const protocol2 = '/echo/2.0.0' - const duplex = pair() - - const mss = new Dialer(duplex) - const selection = await mss.select(protocol) - expect(selection.protocol).to.equal(protocol) - - // A second select will timeout - await pTimeout(mss.select(protocol2), 1e3) - .then(() => expect.fail('should have timed out'), (err) => { - expect(err).to.exist() - }) - }) - - it('should select from multiple protocols', async () => { - const protocols = ['/echo/2.0.0', '/echo/1.0.0'] - const selectedProtocol = protocols[protocols.length - 1] - const stream = pair() - const duplex: Duplex = { - sink: stream.sink, - source: (async function * () { - const source = reader(stream.source) - let msg: string - - // First message will be multistream-select header - msg = await Multistream.readString(source) - expect(msg).to.equal(PROTOCOL_ID) - - // Echo it back - yield Multistream.encode(uint8ArrayFromString(PROTOCOL_ID)) - - // Reject protocols until selectedProtocol appears - while (true) { - msg = await Multistream.readString(source) - if (msg === selectedProtocol) { - yield Multistream.encode(uint8ArrayFromString(selectedProtocol)) - break - } else { - yield Multistream.encode(uint8ArrayFromString('na')) - } - } - - // Rest is data - yield * map(source, (buf) => buf.slice()) - })() - } - - const mss = new Dialer(duplex) - const selection = await mss.select(protocols) - expect(protocols).to.have.length(2) - expect(selection.protocol).to.equal(selectedProtocol) - - // Ensure stream is usable after selection - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - const output = await pipe(input, selection.stream, async (source) => await all(source)) - expect(new Uint8ArrayList(...output).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - - it('should throw if protocol selection fails', async () => { - const protocol = ['/echo/2.0.0', '/echo/1.0.0'] - const stream = pair() - const duplex = { - sink: stream.sink, - source: (async function * () { - const source = reader(stream.source) - let msg: string - - // First message will be multistream-select header - msg = await Multistream.readString(source) - expect(msg).to.equal(PROTOCOL_ID) - - // Echo it back - yield Multistream.encode(uint8ArrayFromString(PROTOCOL_ID)) - - // Reject all protocols - while (true) { - msg = await Multistream.readString(source) - yield Multistream.encode(uint8ArrayFromString('na')) - } - })() - } - - const mss = new Dialer(duplex) - await expect(mss.select(protocol)).to.eventually.be.rejected().with.property('code', 'ERR_UNSUPPORTED_PROTOCOL') - }) - }) - - describe('dialer.ls', () => { - it('should list remote protocols', async () => { - const protocols = ['/echo/2.0.0', '/echo/1.0.0'] - const selectedProtocol = protocols[protocols.length - 1] - const stream = pair() - const duplex: Duplex = { - sink: stream.sink, - source: (async function * () { - const source = reader(stream.source) - let msg: string - - // First message will be multistream-select header - msg = await Multistream.readString(source) - expect(msg).to.equal(PROTOCOL_ID) - - // Echo it back - yield Multistream.encode(uint8ArrayFromString(PROTOCOL_ID)) - - // Second message will be ls - msg = await Multistream.readString(source) - expect(msg).to.equal('ls') - - // Respond with protocols - yield Multistream.encode(new Uint8ArrayList( - ...protocols.map(p => Multistream.encode(uint8ArrayFromString(p))) - ).slice()) - - // Third message will be selectedProtocol - msg = await Multistream.readString(source) - expect(msg).to.equal(selectedProtocol) - - // Echo it back - yield Multistream.encode(uint8ArrayFromString(selectedProtocol)) - - // Rest is data - yield * map(source, (buf) => buf.slice()) - })() - } - - const mss = new Dialer(duplex) - const lsProtocols = await mss.ls() - expect(lsProtocols).to.eql(protocols) - - const selection = await mss.select(selectedProtocol) - expect(selection.protocol).to.equal(selectedProtocol) - - // Ensure stream is usable after selection - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - const output = await pipe(input, selection.stream, async (source) => await all(source)) - expect(new Uint8ArrayList(...output).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - }) -}) diff --git a/packages/libp2p-multistream-select/test/integration.spec.ts b/packages/libp2p-multistream-select/test/integration.spec.ts deleted file mode 100644 index a41682bd3..000000000 --- a/packages/libp2p-multistream-select/test/integration.spec.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import { pipe } from 'it-pipe' -import all from 'it-all' -import { Uint8ArrayList } from 'uint8arraylist' -import { duplexPair } from 'it-pair/duplex' -import randomBytes from 'iso-random-stream/src/random.js' -import { Dialer, Listener } from '../src/index.js' - -describe('Dialer and Listener integration', () => { - it('should handle and select', async () => { - const protocols = ['/echo/2.0.0', '/echo/1.0.0'] - const selectedProtocol = protocols[protocols.length - 1] - const pair = duplexPair() - - const dialer = new Dialer(pair[0]) - const listener = new Listener(pair[1]) - - const [dialerSelection, listenerSelection] = await Promise.all([ - dialer.select(protocols), - listener.handle(selectedProtocol) - ]) - - expect(dialerSelection.protocol).to.equal(selectedProtocol) - expect(listenerSelection.protocol).to.equal(selectedProtocol) - - // Ensure stream is usable after selection - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - const output = await Promise.all([ - pipe(input, dialerSelection.stream, async (source) => await all(source)), - pipe(listenerSelection.stream, listenerSelection.stream) - ]) - expect(new Uint8ArrayList(...output[0]).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - - it('should handle, ls and select', async () => { - const protocols = ['/echo/2.0.0', '/echo/1.0.0'] - const selectedProtocol = protocols[protocols.length - 1] - const pair = duplexPair() - - const dialer = new Dialer(pair[0]) - const listener = new Listener(pair[1]) - - const [listenerSelection, dialerSelection] = await Promise.all([ - listener.handle(selectedProtocol), - (async () => { - const listenerProtocols = await dialer.ls() - expect(listenerProtocols).to.eql([selectedProtocol]) - return await dialer.select(selectedProtocol) - })() - ]) - - expect(dialerSelection.protocol).to.equal(selectedProtocol) - expect(listenerSelection.protocol).to.equal(selectedProtocol) - - // Ensure stream is usable after selection - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - const output = await Promise.all([ - pipe(input, dialerSelection.stream, async (source) => await all(source)), - pipe(listenerSelection.stream, listenerSelection.stream) - ]) - expect(new Uint8ArrayList(...output[0]).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) -}) diff --git a/packages/libp2p-multistream-select/test/listener.spec.ts b/packages/libp2p-multistream-select/test/listener.spec.ts deleted file mode 100644 index 907278d22..000000000 --- a/packages/libp2p-multistream-select/test/listener.spec.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import { pipe } from 'it-pipe' -import { Uint8ArrayList } from 'uint8arraylist' -import { reader } from 'it-reader' -import all from 'it-all' -import * as Lp from 'it-length-prefixed' -import * as Multistream from '../src/multistream.js' -import randomBytes from 'iso-random-stream/src/random.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { Listener, PROTOCOL_ID } from '../src/index.js' -import map from 'it-map' -import type { Duplex } from 'it-stream-types' - -describe('Listener', () => { - describe('listener.handle', () => { - it('should handle a protocol', async () => { - const protocol = '/echo/1.0.0' - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - let output: Uint8ArrayList[] = [] - - const duplex: Duplex = { - sink: async source => { - const read = reader(source) - let msg: string - - // First message will be multistream-select header - msg = await Multistream.readString(read) - expect(msg).to.equal(PROTOCOL_ID) - - // Second message will be protocol - msg = await Multistream.readString(read) - expect(msg).to.equal(protocol) - - // Rest is data - output = await all(read) - }, - source: (function * () { - yield Multistream.encode(uint8ArrayFromString(PROTOCOL_ID)) - yield Multistream.encode(uint8ArrayFromString(protocol)) - yield * input - })() - } - - const mss = new Listener(duplex) - const selection = await mss.handle(protocol) - expect(selection.protocol).to.equal(protocol) - - await pipe(selection.stream, selection.stream) - - expect(new Uint8ArrayList(...output).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - - it('should reject unhandled protocols', async () => { - const protocols = ['/echo/2.0.0', '/echo/1.0.0'] - const handledProtocols = ['/test/1.0.0', protocols[protocols.length - 1]] - const handledProtocol = protocols[protocols.length - 1] - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - let output: Uint8ArrayList[] = [] - - const duplex: Duplex = { - sink: async source => { - const read = reader(source) - let msg: string - - // First message will be multistream-select header - msg = await Multistream.readString(read) - expect(msg).to.equal(PROTOCOL_ID) - - // Second message will be na - msg = await Multistream.readString(read) - expect(msg).to.equal('na') - - // Third message will be handledProtocol - msg = await Multistream.readString(read) - expect(msg).to.equal(handledProtocol) - - // Rest is data - output = await all(read) - }, - source: (function * () { - yield Multistream.encode(uint8ArrayFromString(PROTOCOL_ID)) - for (const protocol of protocols) { - yield Multistream.encode(uint8ArrayFromString(protocol)) - } - yield * input - })() - } - - const mss = new Listener(duplex) - const selection = await mss.handle(handledProtocols) - expect(selection.protocol).to.equal(handledProtocol) - - await pipe(selection.stream, selection.stream) - - expect(new Uint8ArrayList(...output).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - - it('should handle ls', async () => { - const protocols = ['/echo/2.0.0', '/echo/1.0.0'] - const handledProtocols = ['/test/1.0.0', protocols[protocols.length - 1]] - const handledProtocol = protocols[protocols.length - 1] - const input = [randomBytes(10), randomBytes(64), randomBytes(3)] - let output: Uint8ArrayList[] = [] - - const duplex: Duplex = { - sink: async source => { - const read = reader(source) - let msg: string - - // First message will be multistream-select header - msg = await Multistream.readString(read) - expect(msg).to.equal(PROTOCOL_ID) - - // Second message will be ls response - const buf = await Multistream.read(read) - - const protocolsReader = reader([buf]) - - // Decode each of the protocols from the reader - const lsProtocols = await pipe( - protocolsReader, - Lp.decode(), - // Stringify and remove the newline - (source) => map(source, (buf) => uint8ArrayToString(buf).trim()), - async (source) => await all(source) - ) - - expect(lsProtocols).to.deep.equal(handledProtocols) - - // Third message will be handledProtocol - msg = await Multistream.readString(read) - expect(msg).to.equal(handledProtocol) - - // Rest is data - output = await all(read) - }, - source: (function * () { - yield Multistream.encode(uint8ArrayFromString(PROTOCOL_ID)) - yield Multistream.encode(uint8ArrayFromString('ls')) - yield Multistream.encode(uint8ArrayFromString(handledProtocol)) - yield * input - })() - } - - const mss = new Listener(duplex) - const selection = await mss.handle(handledProtocols) - expect(selection.protocol).to.equal(handledProtocol) - - await pipe(selection.stream, selection.stream) - - expect(new Uint8ArrayList(...output).slice()).to.eql(new Uint8ArrayList(...input).slice()) - }) - }) -}) diff --git a/packages/libp2p-multistream-select/test/multistream.spec.ts b/packages/libp2p-multistream-select/test/multistream.spec.ts deleted file mode 100644 index 3efd823a3..000000000 --- a/packages/libp2p-multistream-select/test/multistream.spec.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* eslint-env mocha */ -/* eslint max-nested-callbacks: ["error", 6] */ - -import { expect } from 'aegir/chai' -import * as Varint from 'varint' -import { Uint8ArrayList } from 'uint8arraylist' -import { reader } from 'it-reader' -import * as Multistream from '../src/multistream.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { concat as uint8ArrayConcat } from 'uint8arrays/concat' -import { pushable } from 'it-pushable' -import all from 'it-all' - -describe('Multistream', () => { - describe('Multistream.encode', () => { - it('should encode data Buffer as a multistream-select message', () => { - const input = uint8ArrayFromString(`TEST${Date.now()}`) - const output = Multistream.encode(input) - - const expected = uint8ArrayConcat([ - Uint8Array.from(Varint.encode(input.length + 1)), // +1 to include newline - input, - uint8ArrayFromString('\n') - ]) - - expect(output.slice()).to.eql(expected) - }) - - it('should encode data Uint8ArrayList as a multistream-select message', () => { - const input = new Uint8ArrayList(uint8ArrayFromString('TEST'), uint8ArrayFromString(`${Date.now()}`)) - const output = Multistream.encode(input.slice()) - - const expected = uint8ArrayConcat([ - Uint8Array.from(Varint.encode(input.length + 1)), // +1 to include newline - input.slice(), - uint8ArrayFromString('\n') - ]) - - expect(output.slice()).to.eql(expected) - }) - }) - - describe('Multistream.write', () => { - it('should encode and write a multistream-select message', async () => { - const input = uint8ArrayFromString(`TEST${Date.now()}`) - const writer = pushable() - - Multistream.write(writer, input) - - const expected = uint8ArrayConcat([ - Uint8Array.from(Varint.encode(input.length + 1)), // +1 to include newline - input, - uint8ArrayFromString('\n') - ]) - - writer.end() - - const output = await all(writer) - expect(output.length).to.equal(1) - expect(output[0]).to.eql(expected) - }) - }) - - describe('Multistream.read', () => { - it('should decode a multistream-select message', async () => { - const input = uint8ArrayFromString(`TEST${Date.now()}`) - - const source = reader([uint8ArrayConcat([ - Uint8Array.from(Varint.encode(input.length + 1)), // +1 to include newline - input, - uint8ArrayFromString('\n') - ])]) - - const output = await Multistream.read(source) - expect(output.slice()).to.eql(input) - }) - - it('should throw for non-newline delimited message', async () => { - const input = uint8ArrayFromString(`TEST${Date.now()}`) - - const source = reader([uint8ArrayConcat([ - Uint8Array.from(Varint.encode(input.length)), - input - ])]) - - await expect(Multistream.read(source)).to.eventually.be.rejected() - .with.property('code', 'ERR_INVALID_MULTISTREAM_SELECT_MESSAGE') - }) - - it('should be abortable', async () => { - const input = uint8ArrayFromString(`TEST${Date.now()}`) - - const source = reader([uint8ArrayConcat([ - Uint8Array.from(Varint.encode(input.length + 1)), // +1 to include newline - input, - uint8ArrayFromString('\n') - ])]) - - const controller = new AbortController() - controller.abort() - - await expect(Multistream.read(source, { - signal: controller.signal - })).to.eventually.be.rejected().with.property('code', 'ABORT_ERR') - }) - }) -}) diff --git a/packages/libp2p-peer-collections/CHANGELOG.md b/packages/libp2p-peer-collections/CHANGELOG.md deleted file mode 100644 index 20b73df3e..000000000 --- a/packages/libp2p-peer-collections/CHANGELOG.md +++ /dev/null @@ -1,32 +0,0 @@ -## [@libp2p/peer-collections-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-collections-v1.0.2...@libp2p/peer-collections-v1.0.3) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/peer-collections-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-collections-v1.0.1...@libp2p/peer-collections-v1.0.2) (2022-04-19) - - -### Bug Fixes - -* move dev deps to prod ([#195](https://github.com/libp2p/js-libp2p-interfaces/issues/195)) ([3e1ffc7](https://github.com/libp2p/js-libp2p-interfaces/commit/3e1ffc7b174e74be483943ad4e5fcab823ae3f6d)) - -## [@libp2p/peer-collections-v1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-collections-v1.0.0...@libp2p/peer-collections-v1.0.1) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## @libp2p/peer-collections-v1.0.0 (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) diff --git a/packages/libp2p-peer-collections/README.md b/packages/libp2p-peer-collections/README.md deleted file mode 100644 index 93685d879..000000000 --- a/packages/libp2p-peer-collections/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# libp2p-peer-connections - -> store values against peer ids - -## Table of Contents - -- [Description](#description) -- [Example](#example) -- [Installation](#installation) -- [License](#license) - - [Contribution](#contribution) - -## Description - - We can't use PeerIds as collection keys because collection keys are compared using same-value-zero equality, so this is just a group of collections that stringifies PeerIds before storing them. - - PeerIds cache stringified versions of themselves so this should be a cheap operation. - -## Example - -```JavaScript -import { peerMap, peerSet, peerList } from '@libp2p/peer-collections' - -const map = peerMap() -map.set(peerId, 'value') - -const set = peerSet() -set.add(peerId) - -const list = peerList() -list.push(peerId) -``` - -## Installation - -```console -$ npm i @libp2p/peer-collections -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-peer-collections/peer-map b/packages/libp2p-peer-collections/peer-map deleted file mode 120000 index 6a3e25651..000000000 --- a/packages/libp2p-peer-collections/peer-map +++ /dev/null @@ -1 +0,0 @@ -peer-map \ No newline at end of file diff --git a/packages/libp2p-peer-collections/src/index.ts b/packages/libp2p-peer-collections/src/index.ts deleted file mode 100644 index db2767e61..000000000 --- a/packages/libp2p-peer-collections/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { PeerMap } from './map.js' -export { PeerSet } from './set.js' -export { PeerList } from './list.js' diff --git a/packages/libp2p-peer-collections/src/list.ts b/packages/libp2p-peer-collections/src/list.ts deleted file mode 100644 index 6c4cfa437..000000000 --- a/packages/libp2p-peer-collections/src/list.ts +++ /dev/null @@ -1,145 +0,0 @@ -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { peerIdFromString } from '@libp2p/peer-id' -import { mapIterable } from './util.js' - -/** - * We can't use PeerIds as list entries because list entries are - * compared using same-value-zero equality, so this is just - * a map that stringifies the PeerIds before storing them. - * - * PeerIds cache stringified versions of themselves so this - * should be a cheap operation. - */ -export class PeerList { - private readonly list: string[] - - constructor (list?: PeerList) { - this.list = [] - - if (list != null) { - for (const value of list) { - this.list.push(value.toString()) - } - } - } - - [Symbol.iterator] () { - return mapIterable<[number, string], PeerId>( - this.list.entries(), - (val) => { - return peerIdFromString(val[1]) - } - ) - } - - concat (list: PeerList) { - const output = new PeerList(this) - - for (const value of list) { - output.push(value) - } - - return output - } - - entries (): IterableIterator<[number, PeerId]> { - return mapIterable<[number, string], [number, PeerId]>( - this.list.entries(), - (val) => { - return [val[0], peerIdFromString(val[1])] - } - ) - } - - every (predicate: (peerId: PeerId, index: number, arr: PeerList) => boolean): boolean { - return this.list.every((str, index) => { - return predicate(peerIdFromString(str), index, this) - }) - } - - filter (predicate: (peerId: PeerId, index: number, arr: PeerList) => boolean): PeerList { - const output = new PeerList() - - this.list.forEach((str, index) => { - const peerId = peerIdFromString(str) - - if (predicate(peerId, index, this)) { - output.push(peerId) - } - }) - - return output - } - - find (predicate: (peerId: PeerId, index: number, arr: PeerList) => boolean): PeerId | undefined { - const str = this.list.find((str, index) => { - return predicate(peerIdFromString(str), index, this) - }) - - if (str == null) { - return undefined - } - - return peerIdFromString(str) - } - - findIndex (predicate: (peerId: PeerId, index: number, arr: PeerList) => boolean): number { - return this.list.findIndex((str, index) => { - return predicate(peerIdFromString(str), index, this) - }) - } - - forEach (predicate: (peerId: PeerId, index: number, arr: PeerList) => void): void { - this.list.forEach((str, index) => { - predicate(peerIdFromString(str), index, this) - }) - } - - includes (peerId: PeerId): boolean { - return this.list.includes(peerId.toString()) - } - - indexOf (peerId: PeerId): number { - return this.list.indexOf(peerId.toString()) - } - - pop (): PeerId | undefined { - const str = this.list.pop() - - if (str == null) { - return undefined - } - - return peerIdFromString(str) - } - - push (...peerIds: PeerId[]) { - for (const peerId of peerIds) { - this.list.push(peerId.toString()) - } - } - - shift (): PeerId | undefined { - const str = this.list.shift() - - if (str == null) { - return undefined - } - - return peerIdFromString(str) - } - - unshift (...peerIds: PeerId[]) { - let len = this.list.length - - for (let i = peerIds.length - 1; i > -1; i--) { - len = this.list.unshift(peerIds[i].toString()) - } - - return len - } - - get length () { - return this.list.length - } -} diff --git a/packages/libp2p-peer-collections/src/map.ts b/packages/libp2p-peer-collections/src/map.ts deleted file mode 100644 index b0f9bc635..000000000 --- a/packages/libp2p-peer-collections/src/map.ts +++ /dev/null @@ -1,81 +0,0 @@ -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { peerIdFromString } from '@libp2p/peer-id' -import { mapIterable } from './util.js' - -/** - * We can't use PeerIds as map keys because map keys are - * compared using same-value-zero equality, so this is just - * a map that stringifies the PeerIds before storing them. - * - * PeerIds cache stringified versions of themselves so this - * should be a cheap operation. - */ -export class PeerMap { - private readonly map: Map - - constructor (map?: PeerMap) { - this.map = new Map() - - if (map != null) { - for (const [key, value] of map.entries()) { - this.map.set(key.toString(), value) - } - } - } - - [Symbol.iterator] () { - return this.entries() - } - - clear () { - this.map.clear() - } - - delete (peer: PeerId) { - this.map.delete(peer.toString()) - } - - entries (): IterableIterator<[PeerId, T]> { - return mapIterable<[string, T], [PeerId, T]>( - this.map.entries(), - (val) => { - return [peerIdFromString(val[0]), val[1]] - } - ) - } - - forEach (fn: (value: T, key: PeerId, map: PeerMap) => void): void { - this.map.forEach((value, key) => { - fn(value, peerIdFromString(key), this) - }) - } - - get (peer: PeerId): T | undefined { - return this.map.get(peer.toString()) - } - - has (peer: PeerId): boolean { - return this.map.has(peer.toString()) - } - - set (peer: PeerId, value: T) { - this.map.set(peer.toString(), value) - } - - keys (): IterableIterator { - return mapIterable( - this.map.keys(), - (val) => { - return peerIdFromString(val) - } - ) - } - - values () { - return this.map.values() - } - - get size () { - return this.map.size - } -} diff --git a/packages/libp2p-peer-collections/src/set.ts b/packages/libp2p-peer-collections/src/set.ts deleted file mode 100644 index 32fa79078..000000000 --- a/packages/libp2p-peer-collections/src/set.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { peerIdFromString } from '@libp2p/peer-id' -import { mapIterable } from './util.js' - -/** - * We can't use PeerIds as set entries because set entries are - * compared using same-value-zero equality, so this is just - * a map that stringifies the PeerIds before storing them. - * - * PeerIds cache stringified versions of themselves so this - * should be a cheap operation. - */ -export class PeerSet { - private readonly set: Set - - constructor (set?: PeerSet | Iterable) { - this.set = new Set() - - if (set != null) { - for (const key of set) { - this.set.add(key.toString()) - } - } - } - - get size () { - return this.set.size - } - - [Symbol.iterator] () { - return this.values() - } - - add (peer: PeerId) { - this.set.add(peer.toString()) - } - - clear () { - this.set.clear() - } - - delete (peer: PeerId) { - this.set.delete(peer.toString()) - } - - entries (): IterableIterator<[PeerId, PeerId]> { - return mapIterable<[string, string], [PeerId, PeerId]>( - this.set.entries(), - (val) => { - const peerId = peerIdFromString(val[0]) - - return [peerId, peerId] - } - ) - } - - forEach (predicate: (peerId: PeerId, index: PeerId, set: PeerSet) => void): void { - this.set.forEach((str) => { - const id = peerIdFromString(str) - - predicate(id, id, this) - }) - } - - has (peer: PeerId): boolean { - return this.set.has(peer.toString()) - } - - values () { - return mapIterable( - this.set.values(), - (val) => { - return peerIdFromString(val) - } - ) - } -} diff --git a/packages/libp2p-peer-collections/src/util.ts b/packages/libp2p-peer-collections/src/util.ts deleted file mode 100644 index 026227c84..000000000 --- a/packages/libp2p-peer-collections/src/util.ts +++ /dev/null @@ -1,28 +0,0 @@ - -export function mapIterable (iter: IterableIterator, map: (val: T) => R): IterableIterator { - const iterator: IterableIterator = { - [Symbol.iterator]: () => { - return iterator - }, - next: () => { - const next = iter.next() - const val = next.value - - if (next.done === true || val == null) { - const result: IteratorReturnResult = { - done: true, - value: undefined - } - - return result - } - - return { - done: false, - value: map(val) - } - } - } - - return iterator -} diff --git a/packages/libp2p-peer-collections/test/list.spec.ts b/packages/libp2p-peer-collections/test/list.spec.ts deleted file mode 100644 index a586aabbe..000000000 --- a/packages/libp2p-peer-collections/test/list.spec.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { expect } from 'aegir/chai' -import { PeerList } from '../src/index.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { peerIdFromBytes } from '@libp2p/peer-id' - -describe('peer-list', () => { - it('should return a list', async () => { - const list = new PeerList() - const peer = await createEd25519PeerId() - - list.push(peer) - - const peer2 = peerIdFromBytes(peer.toBytes()) - - expect(list.indexOf(peer2)).to.equal(0) - }) - - it('should create a list with contents', async () => { - const list1 = new PeerList() - const peer = await createEd25519PeerId() - - list1.push(peer) - - const list2 = new PeerList(list1) - - expect(list2.indexOf(peer)).to.equal(0) - }) -}) diff --git a/packages/libp2p-peer-collections/test/map.spec.ts b/packages/libp2p-peer-collections/test/map.spec.ts deleted file mode 100644 index f1d4ac9c2..000000000 --- a/packages/libp2p-peer-collections/test/map.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { expect } from 'aegir/chai' -import { PeerMap } from '../src/index.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { peerIdFromBytes } from '@libp2p/peer-id' - -describe('peer-map', () => { - it('should return a map', async () => { - const map = new PeerMap() - const value = 5 - const peer = await createEd25519PeerId() - - map.set(peer, value) - - const peer2 = peerIdFromBytes(peer.toBytes()) - - expect(map.get(peer2)).to.equal(value) - }) - - it('should create a map with contents', async () => { - const map1 = new PeerMap() - const value = 5 - const peer = await createEd25519PeerId() - - map1.set(peer, value) - - const map2 = new PeerMap(map1) - - expect(map2.get(peer)).to.equal(value) - }) -}) diff --git a/packages/libp2p-peer-collections/test/set.spec.ts b/packages/libp2p-peer-collections/test/set.spec.ts deleted file mode 100644 index b1efeb008..000000000 --- a/packages/libp2p-peer-collections/test/set.spec.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { expect } from 'aegir/chai' -import { PeerSet } from '../src/index.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { peerIdFromBytes } from '@libp2p/peer-id' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -describe('peer-set', () => { - it('should return a set', async () => { - const set = new PeerSet() - const peer = await createEd25519PeerId() - - set.add(peer) - - const peer2 = peerIdFromBytes(peer.toBytes()) - - expect(set.has(peer2)).to.be.true() - }) - - it('should create a set with PeerSet contents', async () => { - const set1 = new PeerSet() - const peer = await createEd25519PeerId() - - set1.add(peer) - - const set2 = new PeerSet(set1) - - expect(set2.has(peer)).to.be.true() - }) - - it('should create a set with Array contents', async () => { - const peer = await createEd25519PeerId() - const set = new PeerSet([peer]) - - expect(set.has(peer)).to.be.true() - }) - - it('should create a set with Set contents', async () => { - const peer = await createEd25519PeerId() - const s = new Set() - s.add(peer) - const set = new PeerSet(s) - - expect(set.has(peer)).to.be.true() - }) -}) diff --git a/packages/libp2p-peer-id-factory/CHANGELOG.md b/packages/libp2p-peer-id-factory/CHANGELOG.md deleted file mode 100644 index 513c2b829..000000000 --- a/packages/libp2p-peer-id-factory/CHANGELOG.md +++ /dev/null @@ -1,108 +0,0 @@ -## [@libp2p/peer-id-factory-v1.0.11](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.10...@libp2p/peer-id-factory-v1.0.11) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/peer-id-factory-v1.0.10](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.9...@libp2p/peer-id-factory-v1.0.10) (2022-05-10) - - -### Bug Fixes - -* regenerate protobuf code ([#212](https://github.com/libp2p/js-libp2p-interfaces/issues/212)) ([3cf210e](https://github.com/libp2p/js-libp2p-interfaces/commit/3cf210e230863f8049ac6c3ed2e73abb180fb8b2)) - -## [@libp2p/peer-id-factory-v1.0.9](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.8...@libp2p/peer-id-factory-v1.0.9) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/peer-id-factory-v1.0.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.7...@libp2p/peer-id-factory-v1.0.8) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/peer-id-factory-v1.0.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.6...@libp2p/peer-id-factory-v1.0.7) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/peer-id-factory-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.5...@libp2p/peer-id-factory-v1.0.6) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/peer-id-factory-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.4...@libp2p/peer-id-factory-v1.0.5) (2022-02-12) - - -### Bug Fixes - -* hide implementations behind factory methods ([#167](https://github.com/libp2p/js-libp2p-interfaces/issues/167)) ([2fba080](https://github.com/libp2p/js-libp2p-interfaces/commit/2fba0800c9896af6dcc49da4fa904bb4a3e3e40d)) - -## [@libp2p/peer-id-factory-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.3...@libp2p/peer-id-factory-v1.0.4) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## [@libp2p/peer-id-factory-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.2...@libp2p/peer-id-factory-v1.0.3) (2022-01-15) - - -### Trivial Changes - -* update project config ([#149](https://github.com/libp2p/js-libp2p-interfaces/issues/149)) ([6eb8556](https://github.com/libp2p/js-libp2p-interfaces/commit/6eb85562c0da167d222808da10a7914daf12970b)) - -## [@libp2p/peer-id-factory-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-factory-v1.0.1...@libp2p/peer-id-factory-v1.0.2) (2022-01-08) - - -### Trivial Changes - -* add semantic release config ([#141](https://github.com/libp2p/js-libp2p-interfaces/issues/141)) ([5f0de59](https://github.com/libp2p/js-libp2p-interfaces/commit/5f0de59136b6343d2411abb2d6a4dd2cd0b7efe4)) -* update package versions ([#140](https://github.com/libp2p/js-libp2p-interfaces/issues/140)) ([cd844f6](https://github.com/libp2p/js-libp2p-interfaces/commit/cd844f6e39f4ee50d006e86eac8dadf696900eb5)) - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 0.2.0 (2022-01-04) - - -### Features - -* add auto-publish ([7aede5d](https://github.com/libp2p/js-libp2p-interfaces/commit/7aede5df39ea6b5f243348ec9a212b3e33c16a81)) -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) -* update package names ([#133](https://github.com/libp2p/js-libp2p-interfaces/issues/133)) ([337adc9](https://github.com/libp2p/js-libp2p-interfaces/commit/337adc9a9bc0278bdae8cbce9c57d07a83c8b5c2)) - - - - - -## [0.2.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-peer-id-factory@0.2.0...libp2p-peer-id-factory@0.2.1) (2022-01-02) - -**Note:** Version bump only for package libp2p-peer-id-factory - - - - - -# 0.2.0 (2022-01-02) - - -### Features - -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) diff --git a/packages/libp2p-peer-id-factory/README.md b/packages/libp2p-peer-id-factory/README.md deleted file mode 100644 index 984db4654..000000000 --- a/packages/libp2p-peer-id-factory/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# libp2p-peer-id-factory - -> create peer-ids in JavaScript - -## Table of Contents - -- [Description](#description) -- [Example](#example) -- [Installation](#installation) - - [License](#license) - - [Contribution](#contribution) - -# Description - -Generate, import, and export PeerIDs, for use with [IPFS](https://github.com/ipfs/ipfs). - -A Peer ID is the SHA-256 [multihash](https://github.com/multiformats/multihash) of a public key. - -The public key is a base64 encoded string of a protobuf containing an RSA DER buffer. This uses a node buffer to pass the base64 encoded public key protobuf to the multihash for ID generation. - -# Example - -```JavaScript -import { createEd25519PeerId } from '@libp2p/peer-id-factory' - -const peerId = await createEd25519PeerId() -console.log(id.toString()) -``` - -```bash -12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD -``` - -# Installation - -```console -$ npm i libp2p-peer-id-factory -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-peer-id-factory/package.json b/packages/libp2p-peer-id-factory/package.json deleted file mode 100644 index 11e576357..000000000 --- a/packages/libp2p-peer-id-factory/package.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "name": "@libp2p/peer-id-factory", - "version": "1.0.11", - "description": "IPFS Peer Id implementation in Node.js", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-peer-id-factory#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "IPFS" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js", - "types": "./dist/src/index.d.ts" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - }, - "ignorePatterns": [ - "proto.d.ts" - ] - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "generate": "protons src/proto.proto", - "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "release": "aegir release" - }, - "dependencies": { - "@libp2p/crypto": "^0.22.8", - "@libp2p/interfaces": "^2.0.0", - "@libp2p/peer-id": "^1.1.0", - "multiformats": "^9.6.3", - "protons-runtime": "^1.0.4", - "uint8arrays": "^3.0.0" - }, - "devDependencies": { - "aegir": "^37.0.7", - "protons": "^3.0.4", - "util": "^0.12.4" - } -} diff --git a/packages/libp2p-peer-id-factory/src/index.ts b/packages/libp2p-peer-id-factory/src/index.ts deleted file mode 100644 index 7a7875013..000000000 --- a/packages/libp2p-peer-id-factory/src/index.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { generateKeyPair, marshalPrivateKey, unmarshalPrivateKey, marshalPublicKey, unmarshalPublicKey } from '@libp2p/crypto/keys' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { peerIdFromKeys, peerIdFromBytes } from '@libp2p/peer-id' -import { PeerIdProto } from './proto.js' -import type { PublicKey, PrivateKey } from '@libp2p/interfaces/keys' -import type { RSAPeerId, Ed25519PeerId, Secp256k1PeerId } from '@libp2p/interfaces/peer-id' - -export const createEd25519PeerId = async (): Promise => { - const key = await generateKeyPair('Ed25519') - const id = await createFromPrivKey(key) - - if (id.type === 'Ed25519') { - return id - } - - throw new Error(`Generated unexpected PeerId type "${id.type}"`) -} - -export const createSecp256k1PeerId = async (): Promise => { - const key = await generateKeyPair('secp256k1') - const id = await createFromPrivKey(key) - - if (id.type === 'secp256k1') { - return id - } - - throw new Error(`Generated unexpected PeerId type "${id.type}"`) -} - -export const createRSAPeerId = async (opts?: { bits: number }): Promise => { - const key = await generateKeyPair('RSA', opts?.bits ?? 2048) - const id = await createFromPrivKey(key) - - if (id.type === 'RSA') { - return id - } - - throw new Error(`Generated unexpected PeerId type "${id.type}"`) -} - -export async function createFromPubKey (publicKey: PublicKey) { - return await peerIdFromKeys(marshalPublicKey(publicKey)) -} - -export async function createFromPrivKey (privateKey: PrivateKey) { - return await peerIdFromKeys(marshalPublicKey(privateKey.public), marshalPrivateKey(privateKey)) -} - -export function exportToProtobuf (peerId: RSAPeerId | Ed25519PeerId | Secp256k1PeerId, excludePrivateKey?: boolean) { - return PeerIdProto.encode({ - id: peerId.multihash.bytes, - pubKey: peerId.publicKey, - privKey: excludePrivateKey === true || peerId.privateKey == null ? undefined : peerId.privateKey - }) -} - -export async function createFromProtobuf (buf: Uint8Array) { - const { - id, - privKey, - pubKey - } = PeerIdProto.decode(buf) - - return await createFromParts( - id, - privKey, - pubKey - ) -} - -export async function createFromJSON (obj: { id: string, privKey?: string, pubKey?: string }) { - return await createFromParts( - uint8ArrayFromString(obj.id, 'base58btc'), - obj.privKey != null ? uint8ArrayFromString(obj.privKey, 'base64pad') : undefined, - obj.pubKey != null ? uint8ArrayFromString(obj.pubKey, 'base64pad') : undefined - ) -} - -async function createFromParts (multihash: Uint8Array, privKey?: Uint8Array, pubKey?: Uint8Array) { - if (privKey != null) { - const key = await unmarshalPrivateKey(privKey) - - return await createFromPrivKey(key) - } else if (pubKey != null) { - const key = await unmarshalPublicKey(pubKey) - - return await createFromPubKey(key) - } - - return peerIdFromBytes(multihash) -} diff --git a/packages/libp2p-peer-id-factory/src/proto.proto b/packages/libp2p-peer-id-factory/src/proto.proto deleted file mode 100644 index 989958a1e..000000000 --- a/packages/libp2p-peer-id-factory/src/proto.proto +++ /dev/null @@ -1,7 +0,0 @@ -syntax = "proto3"; - -message PeerIdProto { - required bytes id = 1; - optional bytes pubKey = 2; - optional bytes privKey = 3; -} diff --git a/packages/libp2p-peer-id-factory/src/proto.ts b/packages/libp2p-peer-id-factory/src/proto.ts deleted file mode 100644 index 4f72d54dc..000000000 --- a/packages/libp2p-peer-id-factory/src/proto.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* eslint-disable import/export */ -/* eslint-disable @typescript-eslint/no-namespace */ - -import { encodeMessage, decodeMessage, message, bytes } from 'protons-runtime' -import type { Codec } from 'protons-runtime' - -export interface PeerIdProto { - id: Uint8Array - pubKey?: Uint8Array - privKey?: Uint8Array -} - -export namespace PeerIdProto { - export const codec = (): Codec => { - return message({ - 1: { name: 'id', codec: bytes }, - 2: { name: 'pubKey', codec: bytes, optional: true }, - 3: { name: 'privKey', codec: bytes, optional: true } - }) - } - - export const encode = (obj: PeerIdProto): Uint8Array => { - return encodeMessage(obj, PeerIdProto.codec()) - } - - export const decode = (buf: Uint8Array): PeerIdProto => { - return decodeMessage(buf, PeerIdProto.codec()) - } -} diff --git a/packages/libp2p-peer-id-factory/test/fixtures/go-private-key.ts b/packages/libp2p-peer-id-factory/test/fixtures/go-private-key.ts deleted file mode 100644 index 5acd665de..000000000 --- a/packages/libp2p-peer-id-factory/test/fixtures/go-private-key.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export default { - id: 'QmRLoXS3E73psYaUsma1VSbboTa2J8Z9kso1tpiGLk9WQ4', - privKey: 'CAASpwkwggSjAgEAAoIBAQDWBEbO8kc6a5kEks09CKPQargY3p0DCmCczoCT52/RYFqxvH9dI+s+u4ZAvF9aLWOBvFomL7jHZODPxKDrbiNCmyEbViNgZYK+PNbwh0V3ZGbB27X3q8yZtLvYA8dhcNkz/2SHBarSoC4QLA5MXUuSWtVaYMY3MzMnzBF57Jc9Ase7NvHOIUI90M7aN5izP7hxPXpZ+shiN+TyjM8mFxYONG7ZSsY3IxUhtrU5MRzFX+tp1o/gb/aa51mHf7AL3N02j5ABiYbCK97Rbwr03hsBcwgMxoDPJmP3WZ+D5yyPcOIIF1Vd7+4/f7FQJnIw3xr9/jvaFbPyDCVbBOhr9oyxAgMBAAECggEALlrgx2Q8v0+c5hux7p1XdgYXd/OHyKfPw0cLHH4NfylCm6q7X34vLvhJHO5wLMUV/3y/ffPqLu4Pr5DkVfoWExAsvJIMuY1jIzdkStbR2glaJHUlVc7VUxmNcj1nSxi5QwT3TjORC2v8bi5Mroeqnbmk6p15cW1akC0oP+NZ4rG48+WFHRqsBaBusdSOVfA+IiZUqSd1ILysJ1w7aVN3EC7jLjDG43i+P/2BcEHy8TVClGOknJL341bHe3UPdEpmeu6k6aHGlDI4blUMXahCIUh0IdZuj+Vi/TxQME9+3bKIOjQb8RCNm3U3j/uz5gs9SyTjBuYIib9Scj/jDbLh0QKBgQDfLr3go3Q/AR0jb12QjGALJz1lc9ZRX2RQJkqqmYkZwOlHHyl+YJgqOZiO80fUkN0sJ29CmKecXU4gXuHir913Fdceei1ScBSsvZpWtBLhEZXKrRJYq8U0atKUFQADDMGutyB/uGCNeNwR6VcJezHPICvHxQfmWlWHA5VIOEtRPQKBgQD1fID76SkIpF/EaJMnN2alXWWnzKhUBUPGpQtbpwgSfaCBiZ4vr3NQwKBntOOB5QwHmifNZMoqaFQLzC4B/uyTNUcQMQQ6arYav7WQXqXTmW6poTsjUSuSOPx1swsHlYX09SmUwWDfd94XF9UOU0KUfA2/c85ixzNlV5ejkFA4hQKBgEvP3uQN4hD82d8Nl2TgqkdfnvV1cdnWY4buWvK0kOPUqelk5n1tZoMBaZc1gLLuOpMjGiIvJNByyXUpheWxA7POEXLi4b5dIEjFZ0YIiVk21gEw5UiFoMl7d+ihcY2Xqbslrb507SdhZLAY6V3pITRQo06K2XIgQWlJiE4uATepAoGBALZ2vEiBnYZW5vfN4tKbUyhGq3B1pggNgbr8odyV4mIcDlk6OOGov0WeZ5ut0AyUesSLyFnaOIoc0ZuTP/8rxBwG1bMrO8FP39sx83pDX25P9PkQZixyALjGsp+pXOFeOhtAvo9azO5M4j638Bydtjc3neBX62dwOLtyx7tDYN0hAoGAVLmr3w7XMVHTfEuCSzKHyRrOaN2PAuSX31QAji1PwlwVKMylVrb8rRvBOpTicA/wXPX9Q5O/yjegqhqLT/LXAm9ziFzy5b9/9SzXPukKebXXbvc0FOmcsrcxtijlPyUzf9fKM1ShiwqqsgM9eNyZ9GWUJw2GFATCWW7pl7rtnWk=' -} diff --git a/packages/libp2p-peer-id-factory/test/fixtures/sample-id.ts b/packages/libp2p-peer-id-factory/test/fixtures/sample-id.ts deleted file mode 100644 index 79f0645c8..000000000 --- a/packages/libp2p-peer-id-factory/test/fixtures/sample-id.ts +++ /dev/null @@ -1,7 +0,0 @@ - -export default { - id: '122019318b6e5e0cf93a2314bf01269a2cc23cd3dcd452d742cdb9379d8646f6e4a9', - privKey: 'CAASpgkwggSiAgEAAoIBAQC2SKo/HMFZeBml1AF3XijzrxrfQXdJzjePBZAbdxqKR1Mc6juRHXij6HXYPjlAk01BhF1S3Ll4Lwi0cAHhggf457sMg55UWyeGKeUv0ucgvCpBwlR5cQ020i0MgzjPWOLWq1rtvSbNcAi2ZEVn6+Q2EcHo3wUvWRtLeKz+DZSZfw2PEDC+DGPJPl7f8g7zl56YymmmzH9liZLNrzg/qidokUv5u1pdGrcpLuPNeTODk0cqKB+OUbuKj9GShYECCEjaybJDl9276oalL9ghBtSeEv20kugatTvYy590wFlJkkvyl+nPxIH0EEYMKK9XRWlu9XYnoSfboiwcv8M3SlsjAgMBAAECggEAZtju/bcKvKFPz0mkHiaJcpycy9STKphorpCT83srBVQi59CdFU6Mj+aL/xt0kCPMVigJw8P3/YCEJ9J+rS8BsoWE+xWUEsJvtXoT7vzPHaAtM3ci1HZd302Mz1+GgS8Epdx+7F5p80XAFLDUnELzOzKftvWGZmWfSeDnslwVONkL/1VAzwKy7Ce6hk4SxRE7l2NE2OklSHOzCGU1f78ZzVYKSnS5Ag9YrGjOAmTOXDbKNKN/qIorAQ1bovzGoCwx3iGIatQKFOxyVCyO1PsJYT7JO+kZbhBWRRE+L7l+ppPER9bdLFxs1t5CrKc078h+wuUr05S1P1JjXk68pk3+kQKBgQDeK8AR11373Mzib6uzpjGzgNRMzdYNuExWjxyxAzz53NAR7zrPHvXvfIqjDScLJ4NcRO2TddhXAfZoOPVH5k4PJHKLBPKuXZpWlookCAyENY7+Pd55S8r+a+MusrMagYNljb5WbVTgN8cgdpim9lbbIFlpN6SZaVjLQL3J8TWH6wKBgQDSChzItkqWX11CNstJ9zJyUE20I7LrpyBJNgG1gtvz3ZMUQCn3PxxHtQzN9n1P0mSSYs+jBKPuoSyYLt1wwe10/lpgL4rkKWU3/m1Myt0tveJ9WcqHh6tzcAbb/fXpUFT/o4SWDimWkPkuCb+8j//2yiXk0a/T2f36zKMuZvujqQKBgC6B7BAQDG2H2B/ijofp12ejJU36nL98gAZyqOfpLJ+FeMz4TlBDQ+phIMhnHXA5UkdDapQ+zA3SrFk+6yGk9Vw4Hf46B+82SvOrSbmnMa+PYqKYIvUzR4gg34rL/7AhwnbEyD5hXq4dHwMNsIDq+l2elPjwm/U9V0gdAl2+r50HAoGALtsKqMvhv8HucAMBPrLikhXP/8um8mMKFMrzfqZ+otxfHzlhI0L08Bo3jQrb0Z7ByNY6M8epOmbCKADsbWcVre/AAY0ZkuSZK/CaOXNX/AhMKmKJh8qAOPRY02LIJRBCpfS4czEdnfUhYV/TYiFNnKRj57PPYZdTzUsxa/yVTmECgYBr7slQEjb5Onn5mZnGDh+72BxLNdgwBkhO0OCdpdISqk0F0Pxby22DFOKXZEpiyI9XYP1C8wPiJsShGm2yEwBPWXnrrZNWczaVuCbXHrZkWQogBDG3HGXNdU4MAWCyiYlyinIBpPpoAJZSzpGLmWbMWh28+RJS6AQX6KHrK1o2uw==', - pubKey: 'CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2SKo/HMFZeBml1AF3XijzrxrfQXdJzjePBZAbdxqKR1Mc6juRHXij6HXYPjlAk01BhF1S3Ll4Lwi0cAHhggf457sMg55UWyeGKeUv0ucgvCpBwlR5cQ020i0MgzjPWOLWq1rtvSbNcAi2ZEVn6+Q2EcHo3wUvWRtLeKz+DZSZfw2PEDC+DGPJPl7f8g7zl56YymmmzH9liZLNrzg/qidokUv5u1pdGrcpLuPNeTODk0cqKB+OUbuKj9GShYECCEjaybJDl9276oalL9ghBtSeEv20kugatTvYy590wFlJkkvyl+nPxIH0EEYMKK9XRWlu9XYnoSfboiwcv8M3SlsjAgMBAAE=', - marshalled: '0a22122019318b6e5e0cf93a2314bf01269a2cc23cd3dcd452d742cdb9379d8646f6e4a912ab02080012a60230820122300d06092a864886f70d01010105000382010f003082010a0282010100b648aa3f1cc1597819a5d401775e28f3af1adf417749ce378f05901b771a8a47531cea3b911d78a3e875d83e3940934d41845d52dcb9782f08b47001e18207f8e7bb0c839e545b278629e52fd2e720bc2a41c25479710d36d22d0c8338cf58e2d6ab5aedbd26cd7008b6644567ebe43611c1e8df052f591b4b78acfe0d94997f0d8f1030be0c63c93e5edff20ef3979e98ca69a6cc7f658992cdaf383faa2768914bf9bb5a5d1ab7292ee3cd79338393472a281f8e51bb8a8fd1928581020848dac9b24397ddbbea86a52fd82106d49e12fdb492e81ab53bd8cb9f74c05949924bf297e9cfc481f410460c28af5745696ef57627a127dba22c1cbfc3374a5b2302030100011aab09080012a609308204a20201000282010100b648aa3f1cc1597819a5d401775e28f3af1adf417749ce378f05901b771a8a47531cea3b911d78a3e875d83e3940934d41845d52dcb9782f08b47001e18207f8e7bb0c839e545b278629e52fd2e720bc2a41c25479710d36d22d0c8338cf58e2d6ab5aedbd26cd7008b6644567ebe43611c1e8df052f591b4b78acfe0d94997f0d8f1030be0c63c93e5edff20ef3979e98ca69a6cc7f658992cdaf383faa2768914bf9bb5a5d1ab7292ee3cd79338393472a281f8e51bb8a8fd1928581020848dac9b24397ddbbea86a52fd82106d49e12fdb492e81ab53bd8cb9f74c05949924bf297e9cfc481f410460c28af5745696ef57627a127dba22c1cbfc3374a5b2302030100010282010066d8eefdb70abca14fcf49a41e2689729c9ccbd4932a9868ae9093f37b2b055422e7d09d154e8c8fe68bff1b749023cc562809c3c3f7fd808427d27ead2f01b28584fb159412c26fb57a13eefccf1da02d337722d4765ddf4d8ccf5f86812f04a5dc7eec5e69f345c014b0d49c42f33b329fb6f58666659f49e0e7b25c1538d90bff5540cf02b2ec27ba864e12c5113b976344d8e9254873b30865357fbf19cd560a4a74b9020f58ac68ce0264ce5c36ca34a37fa88a2b010d5ba2fcc6a02c31de21886ad40a14ec72542c8ed4fb09613ec93be9196e105645113e2fb97ea693c447d6dd2c5c6cd6de42aca734efc87ec2e52bd394b53f52635e4ebca64dfe9102818100de2bc011d75dfbdccce26fabb3a631b380d44ccdd60db84c568f1cb1033cf9dcd011ef3acf1ef5ef7c8aa30d270b27835c44ed9375d85701f66838f547e64e0f24728b04f2ae5d9a56968a24080c84358efe3dde794bcafe6be32eb2b31a8183658dbe566d54e037c7207698a6f656db20596937a4996958cb40bdc9f13587eb02818100d20a1cc8b64a965f5d4236cb49f73272504db423b2eba720493601b582dbf3dd93144029f73f1c47b50ccdf67d4fd2649262cfa304a3eea12c982edd70c1ed74fe5a602f8ae4296537fe6d4ccadd2dbde27d59ca8787ab737006dbfdf5e95054ffa384960e299690f92e09bfbc8ffff6ca25e4d1afd3d9fdfacca32e66fba3a90281802e81ec10100c6d87d81fe28e87e9d767a3254dfa9cbf7c800672a8e7e92c9f8578ccf84e504343ea6120c8671d70395247436a943ecc0dd2ac593eeb21a4f55c381dfe3a07ef364af3ab49b9a731af8f62a29822f533478820df8acbffb021c276c4c83e615eae1d1f030db080eafa5d9e94f8f09bf53d57481d025dbeaf9d070281802edb0aa8cbe1bfc1ee7003013eb2e29215cfffcba6f2630a14caf37ea67ea2dc5f1f39612342f4f01a378d0adbd19ec1c8d63a33c7a93a66c22800ec6d6715adefc0018d1992e4992bf09a397357fc084c2a628987ca8038f458d362c8251042a5f4b873311d9df521615fd362214d9ca463e7b3cf619753cd4b316bfc954e610281806beec9501236f93a79f99999c60e1fbbd81c4b35d83006484ed0e09da5d212aa4d05d0fc5bcb6d8314e297644a62c88f5760fd42f303e226c4a11a6db213004f5979ebad9356733695b826d71eb664590a200431b71c65cd754e0c0160b28989728a7201a4fa68009652ce918b9966cc5a1dbcf91252e80417e8a1eb2b5a36bb' -} diff --git a/packages/libp2p-peer-id-factory/test/index.spec.ts b/packages/libp2p-peer-id-factory/test/index.spec.ts deleted file mode 100644 index b699922f4..000000000 --- a/packages/libp2p-peer-id-factory/test/index.spec.ts +++ /dev/null @@ -1,313 +0,0 @@ -/* eslint max-nested-callbacks: ["error", 8] */ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import { keys } from '@libp2p/crypto' -import { CID } from 'multiformats/cid' -import * as Digest from 'multiformats/hashes/digest' -import { base16 } from 'multiformats/bases/base16' -import { base36 } from 'multiformats/bases/base36' -import { base58btc } from 'multiformats/bases/base58' -import { identity } from 'multiformats/hashes/identity' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { peerIdFromString, peerIdFromBytes, peerIdFromCID, createPeerId } from '@libp2p/peer-id' -import * as PeerIdFactory from '../src/index.js' -import util from 'util' -import testId from './fixtures/sample-id.js' -import goId from './fixtures/go-private-key.js' - -const LIBP2P_KEY_CODE = 0x72 -const RAW_CODE = 0x55 - -const testIdBytes = base16.decode(`f${testId.id}`) -const testIdDigest = Digest.decode(testIdBytes) -const testIdB58String = base58btc.encode(testIdBytes).substring(1) -const testIdB36String = base36.encode(testIdBytes) -const testIdCID = CID.createV1(LIBP2P_KEY_CODE, testIdDigest) -const testIdCIDString = testIdCID.toString() - -describe('PeerId', () => { - it('create an id without \'new\'', () => { - // @ts-expect-error missing args - expect(() => createPeerId()).to.throw(Error) - }) - - it('create a new id', async () => { - const id = await PeerIdFactory.createEd25519PeerId() - expect(id.toString().length).to.equal(52) - }) - - it('can be created for a secp256k1 key', async () => { - const id = await PeerIdFactory.createSecp256k1PeerId() - const expB58 = base58btc.encode((await identity.digest(id.publicKey)).bytes).slice(1) - expect(id.toString()).to.equal(expB58) - }) - - it('can get the public key from a Secp256k1 key', async () => { - const original = await PeerIdFactory.createSecp256k1PeerId() - const newId = peerIdFromString(original.toString()) - expect(original.publicKey).to.equalBytes(newId.publicKey) - }) - - it('recreate from a Uint8Array', () => { - const id = peerIdFromBytes(testIdBytes) - expect(testId.id).to.equal(uint8ArrayToString(id.multihash.bytes, 'base16')) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('recreate from a B58 String', () => { - const id = peerIdFromString(testIdB58String) - expect(testIdB58String).to.equal(id.toString()) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('recreate from CID object', () => { - const id = peerIdFromCID(testIdCID) - expect(testIdCIDString).to.equal(id.toCID().toString()) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('recreate from Base58 String (CIDv0)', () => { - const id = peerIdFromCID(CID.parse(testIdB58String)) - expect(testIdCIDString).to.equal(id.toCID().toString()) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('recreate from Base36 String', () => { - const id = peerIdFromString(testIdB36String) - expect(testIdCIDString).to.equal(id.toCID().toString()) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('recreate from CIDv1 Base32 (libp2p-key multicodec)', () => { - const cid = CID.createV1(LIBP2P_KEY_CODE, testIdDigest) - const id = peerIdFromCID(cid) - expect(cid.toString()).to.equal(id.toCID().toString()) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('recreate from CID Uint8Array', () => { - const id = peerIdFromBytes(testIdCID.bytes) - expect(testIdCIDString).to.equal(id.toCID().toString()) - expect(testIdBytes).to.equalBytes(id.multihash.bytes) - }) - - it('throws on invalid CID multicodec', () => { - // only libp2p and dag-pb are supported - const invalidCID = CID.createV1(RAW_CODE, testIdDigest) - expect(() => { - peerIdFromCID(invalidCID) - }).to.throw(/invalid/i) - }) - - it('throws on invalid multihash value', () => { - // using function code 0x50 that does not represent valid hash function - // https://github.com/multiformats/js-multihash/blob/b85999d5768bf06f1b0f16b926ef2cb6d9c14265/src/constants.js#L345 - const invalidMultihash = uint8ArrayToString(Uint8Array.from([0x50, 0x1, 0x0]), 'base58btc') - expect(() => { - peerIdFromString(invalidMultihash) - }).to.throw(/Non-base32hexpadupper character/i) - }) - - it('throws on invalid CID object', () => { - const invalidCID = {} - expect(() => { - // @ts-expect-error invalid cid is invalid type - peerIdFromCID(invalidCID) - }).to.throw(/invalid/i) - }) - - it('recreate from a Public Key', async () => { - const id = await PeerIdFactory.createFromPubKey(keys.unmarshalPublicKey(uint8ArrayFromString(testId.pubKey, 'base64pad'))) - - expect(testIdB58String).to.equal(id.toString()) - expect(testIdBytes).to.deep.equal(id.multihash.bytes) - }) - - it('recreate from a Private Key', async () => { - const id = await PeerIdFactory.createFromPrivKey(await keys.unmarshalPrivateKey(uint8ArrayFromString(testId.privKey, 'base64pad'))) - expect(testIdB58String).to.equal(id.toString()) - - const encoded = await keys.unmarshalPrivateKey(uint8ArrayFromString(testId.privKey, 'base64pad')) - const id2 = await PeerIdFactory.createFromPrivKey(encoded) - - if (id.type !== 'RSA') { - throw new Error('Wrong key type found') - } - - expect(testIdB58String).to.equal(id2.toString()) - expect(id.publicKey).to.deep.equal(id2.publicKey) - }) - - it('recreate from Protobuf', async () => { - const id = await PeerIdFactory.createFromProtobuf(uint8ArrayFromString(testId.marshalled, 'base16')) - expect(testIdB58String).to.equal(id.toString()) - - const key = await keys.unmarshalPrivateKey(uint8ArrayFromString(testId.privKey, 'base64pad')) - const id2 = await PeerIdFactory.createFromPrivKey(key) - - expect(testIdB58String).to.equal(id2.toString()) - expect(id.publicKey).to.equalBytes(id2.publicKey) - expect(uint8ArrayToString(PeerIdFactory.exportToProtobuf(id), 'base16')).to.equal(testId.marshalled) - }) - - it('recreate from embedded ed25519 key', async () => { - const key = '12D3KooWRm8J3iL796zPFi2EtGGtUJn58AG67gcqzMFHZnnsTzqD' - const id = await peerIdFromString(key) - expect(id.toString()).to.equal(key) - - if (id.publicKey == null) { - throw new Error('No pubic key found on Ed25519 key') - } - - const expB58 = base58btc.encode((await identity.digest(id.publicKey)).bytes).slice(1) - expect(id.toString()).to.equal(expB58) - }) - - it('recreate from embedded secp256k1 key', async () => { - const key = '16Uiu2HAm5qw8UyXP2RLxQUx5KvtSN8DsTKz8quRGqGNC3SYiaB8E' - const id = await peerIdFromString(key) - expect(id.toString()).to.equal(key) - - if (id.publicKey == null) { - throw new Error('No pubic key found on secp256k1 key') - } - - const expB58 = base58btc.encode((await identity.digest(id.publicKey)).bytes).slice(1) - expect(id.toString()).to.equal(expB58) - }) - - it('recreate from string key', async () => { - const key = 'QmRsooYQasV5f5r834NSpdUtmejdQcpxXkK6qsozZWEihC' - const id = await peerIdFromString(key) - expect(id.toString()).to.equal(key) - }) - - it('can be created from a secp256k1 public key', async () => { - const privKey = await keys.generateKeyPair('secp256k1', 256) - const id = await PeerIdFactory.createFromPubKey(privKey.public) - - if (id.publicKey == null) { - throw new Error('No public key found on peer id created from secp256k1 public key') - } - - const expB58 = base58btc.encode((await identity.digest(id.publicKey)).bytes).slice(1) - expect(id.toString()).to.equal(expB58) - }) - - it('can be created from a Secp256k1 private key', async () => { - const privKey = await keys.generateKeyPair('secp256k1', 256) - const id = await PeerIdFactory.createFromPrivKey(privKey) - - if (id.publicKey == null) { - throw new Error('No public key found on peer id created from secp256k1 private key') - } - - const expB58 = base58btc.encode((await identity.digest(id.publicKey)).bytes).slice(1) - expect(id.toString()).to.equal(expB58) - }) - - it('Compare generated ID with one created from PubKey', async () => { - const id1 = await PeerIdFactory.createSecp256k1PeerId() - const id2 = await PeerIdFactory.createFromPubKey(keys.unmarshalPublicKey(id1.publicKey)) - - expect(id1.multihash.bytes).to.equalBytes(id2.multihash.bytes) - }) - - it('Works with default options', async function () { - const id = await PeerIdFactory.createEd25519PeerId() - expect(id.toString().length).to.equal(52) - }) - - it('Non-default # of bits', async function () { - const shortId = await PeerIdFactory.createRSAPeerId({ bits: 512 }) - const longId = await PeerIdFactory.createRSAPeerId({ bits: 1024 }) - - if (longId.privateKey == null) { - throw new Error('No private key found on peer id') - } - - expect(shortId.privateKey).to.have.property('length').that.is.lessThan(longId.privateKey.length) - }) - - it('equals', async () => { - const ids = await Promise.all([ - PeerIdFactory.createEd25519PeerId(), - PeerIdFactory.createEd25519PeerId() - ]) - - expect(ids[0].equals(ids[0])).to.equal(true) - expect(ids[0].equals(ids[1])).to.equal(false) - expect(ids[0].equals(ids[0].multihash.bytes)).to.equal(true) - expect(ids[0].equals(ids[1].multihash.bytes)).to.equal(false) - }) - - describe('fromJSON', () => { - it('full node', async () => { - const id = await PeerIdFactory.createEd25519PeerId() - const other = await PeerIdFactory.createFromJSON({ - id: id.toString(), - privKey: id.privateKey != null ? uint8ArrayToString(id.privateKey, 'base64pad') : undefined, - pubKey: uint8ArrayToString(id.publicKey, 'base64pad') - }) - expect(id.toString()).to.equal(other.toString()) - expect(id.privateKey).to.equalBytes(other.privateKey) - expect(id.publicKey).to.equalBytes(other.publicKey) - }) - - it('only id', async () => { - const key = await keys.generateKeyPair('RSA', 1024) - const digest = await key.public.hash() - const id = peerIdFromBytes(digest) - expect(id.privateKey).to.not.exist() - expect(id.publicKey).to.not.exist() - const other = await PeerIdFactory.createFromJSON({ - id: id.toString(), - privKey: id.privateKey != null ? uint8ArrayToString(id.privateKey, 'base64pad') : undefined, - pubKey: id.publicKey != null ? uint8ArrayToString(id.publicKey, 'base64pad') : undefined - }) - expect(id.toString()).to.equal(other.toString()) - }) - - it('go interop', async () => { - const id = await PeerIdFactory.createFromJSON(goId) - expect(id.toString()).to.eql(goId.id) - }) - }) - - it('keys are equal after one is stringified', async () => { - const peerId = await PeerIdFactory.createEd25519PeerId() - const peerId1 = peerIdFromString(peerId.toString()) - const peerId2 = peerIdFromString(peerId.toString()) - - expect(peerId1).to.deep.equal(peerId2) - - peerId1.toString() - - expect(peerId1).to.deep.equal(peerId2) - }) - - describe('returns error instead of crashing', () => { - const garbage = [ - uint8ArrayFromString('00010203040506070809', 'base16'), - {}, null, false, undefined, true, 1, 0, - uint8ArrayFromString(''), 'aGVsbG93b3JsZA==', 'helloworld', '' - ] - - const fncs = ['createFromPubKey', 'createFromPrivKey', 'createFromJSON', 'createFromProtobuf'] - - for (const gb of garbage) { - for (const fn of fncs) { - it(`${fn} (${util.inspect(gb)})`, async () => { - try { - // @ts-expect-error cannot use a string to index PeerId - await PeerIdFactory[fn](gb) - } catch (err) { - expect(err).to.exist() - } - }) - } - } - }) -}) diff --git a/packages/libp2p-peer-id/CHANGELOG.md b/packages/libp2p-peer-id/CHANGELOG.md deleted file mode 100644 index a7cf6e15c..000000000 --- a/packages/libp2p-peer-id/CHANGELOG.md +++ /dev/null @@ -1,135 +0,0 @@ -## [@libp2p/peer-id-v1.1.11](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.10...@libp2p/peer-id-v1.1.11) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/peer-id-v1.1.10](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.9...@libp2p/peer-id-v1.1.10) (2022-04-14) - - -### Bug Fixes - -* add logger methods, fix peer id deserialization ([#194](https://github.com/libp2p/js-libp2p-interfaces/issues/194)) ([f0e1fad](https://github.com/libp2p/js-libp2p-interfaces/commit/f0e1fad42701d73eef4233ec2b9a8aafa0b2ab96)) - -## [@libp2p/peer-id-v1.1.9](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.8...@libp2p/peer-id-v1.1.9) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/peer-id-v1.1.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.7...@libp2p/peer-id-v1.1.8) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/peer-id-v1.1.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.6...@libp2p/peer-id-v1.1.7) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/peer-id-v1.1.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.5...@libp2p/peer-id-v1.1.6) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/peer-id-v1.1.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.4...@libp2p/peer-id-v1.1.5) (2022-02-18) - - -### Bug Fixes - -* simpler pubsub ([#172](https://github.com/libp2p/js-libp2p-interfaces/issues/172)) ([98715ed](https://github.com/libp2p/js-libp2p-interfaces/commit/98715ed73183b32e4fda3d878a462389548358d9)) - -## [@libp2p/peer-id-v1.1.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.3...@libp2p/peer-id-v1.1.4) (2022-02-17) - - -### Bug Fixes - -* add multistream-select and update pubsub types ([#170](https://github.com/libp2p/js-libp2p-interfaces/issues/170)) ([b9ecb2b](https://github.com/libp2p/js-libp2p-interfaces/commit/b9ecb2bee8f2abc0c41bfcf7bf2025894e37ddc2)) - -## [@libp2p/peer-id-v1.1.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.2...@libp2p/peer-id-v1.1.3) (2022-02-12) - - -### Bug Fixes - -* hide implementations behind factory methods ([#167](https://github.com/libp2p/js-libp2p-interfaces/issues/167)) ([2fba080](https://github.com/libp2p/js-libp2p-interfaces/commit/2fba0800c9896af6dcc49da4fa904bb4a3e3e40d)) - -## [@libp2p/peer-id-v1.1.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.1...@libp2p/peer-id-v1.1.2) (2022-02-11) - - -### Bug Fixes - -* simpler topologies ([#164](https://github.com/libp2p/js-libp2p-interfaces/issues/164)) ([45fcaa1](https://github.com/libp2p/js-libp2p-interfaces/commit/45fcaa10a6a3215089340ff2eff117d7fd1100e7)) - -## [@libp2p/peer-id-v1.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.1.0...@libp2p/peer-id-v1.1.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## [@libp2p/peer-id-v1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.0.4...@libp2p/peer-id-v1.1.0) (2022-02-09) - - -### Features - -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) - -## [@libp2p/peer-id-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.0.3...@libp2p/peer-id-v1.0.4) (2022-01-29) - - -### Bug Fixes - -* remove extra fields ([#153](https://github.com/libp2p/js-libp2p-interfaces/issues/153)) ([ccd7cf3](https://github.com/libp2p/js-libp2p-interfaces/commit/ccd7cf3f5ac71337baf516d3b0f6fc724ee0d3b4)) - -## [@libp2p/peer-id-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.0.2...@libp2p/peer-id-v1.0.3) (2022-01-15) - - -### Trivial Changes - -* update project config ([#149](https://github.com/libp2p/js-libp2p-interfaces/issues/149)) ([6eb8556](https://github.com/libp2p/js-libp2p-interfaces/commit/6eb85562c0da167d222808da10a7914daf12970b)) - -## [@libp2p/peer-id-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-id-v1.0.1...@libp2p/peer-id-v1.0.2) (2022-01-08) - - -### Trivial Changes - -* add semantic release config ([#141](https://github.com/libp2p/js-libp2p-interfaces/issues/141)) ([5f0de59](https://github.com/libp2p/js-libp2p-interfaces/commit/5f0de59136b6343d2411abb2d6a4dd2cd0b7efe4)) -* update package versions ([#140](https://github.com/libp2p/js-libp2p-interfaces/issues/140)) ([cd844f6](https://github.com/libp2p/js-libp2p-interfaces/commit/cd844f6e39f4ee50d006e86eac8dadf696900eb5)) - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 0.2.0 (2022-01-04) - - -### Features - -* add auto-publish ([7aede5d](https://github.com/libp2p/js-libp2p-interfaces/commit/7aede5df39ea6b5f243348ec9a212b3e33c16a81)) -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) -* update package names ([#133](https://github.com/libp2p/js-libp2p-interfaces/issues/133)) ([337adc9](https://github.com/libp2p/js-libp2p-interfaces/commit/337adc9a9bc0278bdae8cbce9c57d07a83c8b5c2)) - - - - - -# 0.2.0 (2022-01-02) - - -### Features - -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) diff --git a/packages/libp2p-peer-id/README.md b/packages/libp2p-peer-id/README.md deleted file mode 100644 index 2ff405693..000000000 --- a/packages/libp2p-peer-id/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# libp2p-peer-id - -> peer-ids in JavaScript - -## Table of Contents - -- [Description](#description) -- [Example](#example) -- [Installation](#installation) - - [License](#license) - - [Contribution](#contribution) - -# Description - -A basic implementation of a peer id - -# Example - -```JavaScript -import { PeerId } from '@libp2p/peer-id' - -const id = new PeerId(...) - -console.log(id.toCid()) -``` - -# Installation - -```console -$ npm i libp2p-peer-id -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-peer-id/src/index.ts b/packages/libp2p-peer-id/src/index.ts deleted file mode 100644 index d868e4dde..000000000 --- a/packages/libp2p-peer-id/src/index.ts +++ /dev/null @@ -1,247 +0,0 @@ -import { CID } from 'multiformats/cid' -import { bases } from 'multiformats/basics' -import { base58btc } from 'multiformats/bases/base58' -import * as Digest from 'multiformats/hashes/digest' -import { identity } from 'multiformats/hashes/identity' -import { equals as uint8ArrayEquals } from 'uint8arrays/equals' -import { sha256 } from 'multiformats/hashes/sha2' -import errcode from 'err-code' -import { Ed25519PeerId, RSAPeerId, Secp256k1PeerId, symbol } from '@libp2p/interfaces/peer-id' -import type { MultibaseDecoder } from 'multiformats/bases/interface' -import type { MultihashDigest } from 'multiformats/hashes/interface' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -const baseDecoder = Object - .values(bases) - .map(codec => codec.decoder) - // @ts-expect-error https://github.com/multiformats/js-multiformats/issues/141 - .reduce((acc, curr) => acc.or(curr), bases.identity.decoder) - -// these values are from https://github.com/multiformats/multicodec/blob/master/table.csv -const LIBP2P_KEY_CODE = 0x72 - -const MARSHALLED_ED225519_PUBLIC_KEY_LENGTH = 36 -const MARSHALLED_SECP258K1_PUBLIC_KEY_LENGTH = 37 - -interface PeerIdInit { - type: 'RSA' | 'Ed25519' | 'secp256k1' - multihash: MultihashDigest - privateKey?: Uint8Array -} - -interface RSAPeerIdInit { - multihash: MultihashDigest - privateKey?: Uint8Array - publicKey?: Uint8Array -} - -interface Ed25519PeerIdInit { - multihash: MultihashDigest - privateKey?: Uint8Array -} - -interface Secp256k1PeerIdInit { - multihash: MultihashDigest - privateKey?: Uint8Array -} - -class PeerIdImpl { - public type: 'RSA' | 'Ed25519' | 'secp256k1' - public readonly multihash: MultihashDigest - public readonly privateKey?: Uint8Array - public readonly publicKey?: Uint8Array - private string?: string - - constructor (init: PeerIdInit) { - this.type = init.type - this.multihash = init.multihash - this.privateKey = init.privateKey - - // mark string cache as non-enumerable - Object.defineProperty(this, 'string', { - enumerable: false, - writable: true - }) - } - - get [Symbol.toStringTag] () { - return `PeerId(${this.toString()})` - } - - get [symbol] () { - return true - } - - toString () { - if (this.string == null) { - this.string = base58btc.encode(this.multihash.bytes).slice(1) - } - - return this.string - } - - // return self-describing String representation - // in default format from RFC 0001: https://github.com/libp2p/specs/pull/209 - toCID () { - return CID.createV1(LIBP2P_KEY_CODE, this.multihash) - } - - toBytes () { - return this.multihash.bytes - } - - /** - * Returns Multiaddr as a JSON encoded object - */ - toJSON () { - return this.toString() - } - - /** - * Checks the equality of `this` peer against a given PeerId - */ - equals (id: PeerId | Uint8Array | string): boolean { - if (id instanceof Uint8Array) { - return uint8ArrayEquals(this.multihash.bytes, id) - } else if (typeof id === 'string') { - return peerIdFromString(id).equals(this as PeerId) - } else if (id?.multihash?.bytes != null) { - return uint8ArrayEquals(this.multihash.bytes, id.multihash.bytes) - } else { - throw new Error('not valid Id') - } - } -} - -class RSAPeerIdImpl extends PeerIdImpl implements RSAPeerId { - public readonly type = 'RSA' - public readonly publicKey?: Uint8Array - - constructor (init: RSAPeerIdInit) { - super({ ...init, type: 'RSA' }) - - this.publicKey = init.publicKey - } -} - -class Ed25519PeerIdImpl extends PeerIdImpl implements Ed25519PeerId { - public readonly type = 'Ed25519' - public readonly publicKey: Uint8Array - - constructor (init: Ed25519PeerIdInit) { - super({ ...init, type: 'Ed25519' }) - - this.publicKey = init.multihash.digest - } -} - -class Secp256k1PeerIdImpl extends PeerIdImpl implements Secp256k1PeerId { - public readonly type = 'secp256k1' - public readonly publicKey: Uint8Array - - constructor (init: Secp256k1PeerIdInit) { - super({ ...init, type: 'secp256k1' }) - - this.publicKey = init.multihash.digest - } -} - -export function createPeerId (init: PeerIdInit) { - return new PeerIdImpl(init) -} - -export function peerIdFromPeerId (other: any): PeerId { - const err = errcode(new Error('Not a PeerId'), 'ERR_INVALID_PARAMETERS') - - if (other.type === 'RSA') { - return new RSAPeerIdImpl(other) - } - - if (other.type === 'Ed25519') { - return new Ed25519PeerIdImpl(other) - } - - if (other.type === 'secp256k1') { - return new Secp256k1PeerIdImpl(other) - } - - throw err -} - -export function peerIdFromString (str: string, decoder?: MultibaseDecoder): PeerId { - decoder = decoder ?? baseDecoder - - if (str.charAt(0) === '1' || str.charAt(0) === 'Q') { - // identity hash ed25519/secp256k1 key or sha2-256 hash of - // rsa public key - base58btc encoded either way - const multihash = Digest.decode(base58btc.decode(`z${str}`)) - - if (str.startsWith('12D')) { - return new Ed25519PeerIdImpl({ multihash }) - } else if (str.startsWith('16U')) { - return new Secp256k1PeerIdImpl({ multihash }) - } else { - return new RSAPeerIdImpl({ multihash }) - } - } - - return peerIdFromBytes(baseDecoder.decode(str)) -} - -export function peerIdFromBytes (buf: Uint8Array) { - try { - const multihash = Digest.decode(buf) - - if (multihash.code === identity.code) { - if (multihash.digest.length === MARSHALLED_ED225519_PUBLIC_KEY_LENGTH) { - return new Ed25519PeerIdImpl({ multihash }) - } else if (multihash.digest.length === MARSHALLED_SECP258K1_PUBLIC_KEY_LENGTH) { - return new Secp256k1PeerIdImpl({ multihash }) - } - } - - if (multihash.code === sha256.code) { - return new RSAPeerIdImpl({ multihash }) - } - } catch { - return peerIdFromCID(CID.decode(buf)) - } - - throw new Error('Supplied PeerID CID is invalid') -} - -export function peerIdFromCID (cid: CID): PeerId { - if (cid == null || cid.multihash == null || cid.version == null || (cid.version === 1 && cid.code !== LIBP2P_KEY_CODE)) { - throw new Error('Supplied PeerID CID is invalid') - } - - const multihash = cid.multihash - - if (multihash.code === sha256.code) { - return new RSAPeerIdImpl({ multihash: cid.multihash }) - } else if (multihash.code === identity.code) { - if (multihash.digest.length === MARSHALLED_ED225519_PUBLIC_KEY_LENGTH) { - return new Ed25519PeerIdImpl({ multihash: cid.multihash }) - } else if (multihash.digest.length === MARSHALLED_SECP258K1_PUBLIC_KEY_LENGTH) { - return new Secp256k1PeerIdImpl({ multihash: cid.multihash }) - } - } - - throw new Error('Supplied PeerID CID is invalid') -} - -/** - * @param publicKey - A marshalled public key - * @param privateKey - A marshalled private key - */ -export async function peerIdFromKeys (publicKey: Uint8Array, privateKey?: Uint8Array): Promise { - if (publicKey.length === MARSHALLED_ED225519_PUBLIC_KEY_LENGTH) { - return new Ed25519PeerIdImpl({ multihash: Digest.create(identity.code, publicKey), privateKey }) - } - - if (publicKey.length === MARSHALLED_SECP258K1_PUBLIC_KEY_LENGTH) { - return new Secp256k1PeerIdImpl({ multihash: Digest.create(identity.code, publicKey), privateKey }) - } - - return new RSAPeerIdImpl({ multihash: await sha256.digest(publicKey), publicKey, privateKey }) -} diff --git a/packages/libp2p-peer-id/test/index.spec.ts b/packages/libp2p-peer-id/test/index.spec.ts deleted file mode 100644 index e139c6f86..000000000 --- a/packages/libp2p-peer-id/test/index.spec.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* eslint-env mocha */ -import { expect } from 'aegir/chai' -import { createPeerId, peerIdFromBytes, peerIdFromString } from '../src/index.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' - -describe('PeerId', () => { - it('create an id without \'new\'', () => { - // @ts-expect-error missing args - expect(() => createPeerId()).to.throw(Error) - }) - - it('create a new id from multihash', async () => { - const buf = uint8ArrayFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id.equals(buf)).to.be.true() - }) - - it('parses a v1 CID with the libp2p-key codec', async () => { - const str = 'bafzaajaiaejca24q7uhr7adt3rtai4ixtn2r3q72kccwvwzg6wnfetwqyvrs5n2d' - const id = peerIdFromString(str) - expect(id.type).to.equal('Ed25519') - expect(id.toString()).to.equal('12D3KooWH4G2B3x5BZHH3j2ccMsBLhzR8u1uzrAQshg429xGFGPk') - expect(id.toCID().toString()).to.equal('bafzaajaiaejca24q7uhr7adt3rtai4ixtn2r3q72kccwvwzg6wnfetwqyvrs5n2d') - }) - - it('defaults to base58btc when stringifying', async () => { - const buf = uint8ArrayFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id.toString()).to.equal('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa') - }) - - it('turns into a CID', async () => { - const buf = uint8ArrayFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id.toCID().toString()).to.equal('bafzaajaiaejcda3tmul6p2537j5upxpjgz3jabbzxqrjqvhhfnthtnezvwibizjh') - }) - - it('equals a Uint8Array', async () => { - const buf = uint8ArrayFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id.equals(buf)).to.be.true() - }) - - it('equals a PeerId', async () => { - const buf = uint8ArrayFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id.equals(peerIdFromBytes(buf))).to.be.true() - }) - - it('parses a PeerId as Ed25519', async () => { - const id = peerIdFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa') - expect(id).to.have.property('type', 'Ed25519') - }) - - it('parses a PeerId as RSA', async () => { - const id = peerIdFromString('QmZHBBrcBtDk7yVzcNUDJBJsZnVGtPHzpTzu16J7Sk6hbp') - expect(id).to.have.property('type', 'RSA') - }) - - it('parses a PeerId as secp256k1', async () => { - const id = peerIdFromString('16Uiu2HAkxSnqYGDU5iZTQrZyAcQDQHKrZqSNPBmKFifEagS2XfrL') - expect(id).to.have.property('type', 'secp256k1') - }) - - it('decodes a PeerId as Ed25519', async () => { - const buf = uint8ArrayFromString('12D3KooWbtp1AcgweFSArD7dbKWYpAr8MZR1tofwNwLFLjeNGLWa', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id).to.have.property('type', 'Ed25519') - }) - - it('decodes a PeerId as RSA', async () => { - const buf = uint8ArrayFromString('QmZHBBrcBtDk7yVzcNUDJBJsZnVGtPHzpTzu16J7Sk6hbp', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id).to.have.property('type', 'RSA') - }) - - it('decodes a PeerId as secp256k1', async () => { - const buf = uint8ArrayFromString('16Uiu2HAkxSnqYGDU5iZTQrZyAcQDQHKrZqSNPBmKFifEagS2XfrL', 'base58btc') - const id = peerIdFromBytes(buf) - expect(id).to.have.property('type', 'secp256k1') - }) - - it('caches toString output', async () => { - const buf = uint8ArrayFromString('16Uiu2HAkxSnqYGDU5iZTQrZyAcQDQHKrZqSNPBmKFifEagS2XfrL', 'base58btc') - const id = peerIdFromBytes(buf) - - expect(id).to.have.property('string').that.is.not.ok() - - id.toString() - - expect(id).to.have.property('string').that.is.ok() - }) - - it('stringifies as JSON', () => { - const buf = uint8ArrayFromString('16Uiu2HAkxSnqYGDU5iZTQrZyAcQDQHKrZqSNPBmKFifEagS2XfrL', 'base58btc') - const id = peerIdFromBytes(buf) - - const res = JSON.parse(JSON.stringify({ id })) - - expect(res).to.have.property('id', id.toString()) - }) -}) diff --git a/packages/libp2p-peer-record/CHANGELOG.md b/packages/libp2p-peer-record/CHANGELOG.md deleted file mode 100644 index 1609cb198..000000000 --- a/packages/libp2p-peer-record/CHANGELOG.md +++ /dev/null @@ -1,95 +0,0 @@ -## [@libp2p/peer-record-v1.0.12](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.11...@libp2p/peer-record-v1.0.12) (2022-05-20) - - -### Bug Fixes - -* update sibling deps ([#216](https://github.com/libp2p/js-libp2p-interfaces/issues/216)) ([0ceca65](https://github.com/libp2p/js-libp2p-interfaces/commit/0ceca658901e92de554c828105b328b88a1416f8)) - -## [@libp2p/peer-record-v1.0.11](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.10...@libp2p/peer-record-v1.0.11) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/peer-record-v1.0.10](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.9...@libp2p/peer-record-v1.0.10) (2022-05-10) - - -### Trivial Changes - -* **deps:** bump sinon from 13.0.2 to 14.0.0 ([#211](https://github.com/libp2p/js-libp2p-interfaces/issues/211)) ([8859f70](https://github.com/libp2p/js-libp2p-interfaces/commit/8859f70943c0bcdb210f54a338ae901739e5e6f2)) - -## [@libp2p/peer-record-v1.0.9](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.8...@libp2p/peer-record-v1.0.9) (2022-05-10) - - -### Bug Fixes - -* regenerate protobuf code ([#212](https://github.com/libp2p/js-libp2p-interfaces/issues/212)) ([3cf210e](https://github.com/libp2p/js-libp2p-interfaces/commit/3cf210e230863f8049ac6c3ed2e73abb180fb8b2)) - -## [@libp2p/peer-record-v1.0.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.7...@libp2p/peer-record-v1.0.8) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/peer-record-v1.0.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.6...@libp2p/peer-record-v1.0.7) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/peer-record-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.5...@libp2p/peer-record-v1.0.6) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/peer-record-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.4...@libp2p/peer-record-v1.0.5) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/peer-record-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.3...@libp2p/peer-record-v1.0.4) (2022-02-17) - - -### Bug Fixes - -* add multistream-select and update pubsub types ([#170](https://github.com/libp2p/js-libp2p-interfaces/issues/170)) ([b9ecb2b](https://github.com/libp2p/js-libp2p-interfaces/commit/b9ecb2bee8f2abc0c41bfcf7bf2025894e37ddc2)) - -## [@libp2p/peer-record-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.2...@libp2p/peer-record-v1.0.3) (2022-02-12) - - -### Bug Fixes - -* hide implementations behind factory methods ([#167](https://github.com/libp2p/js-libp2p-interfaces/issues/167)) ([2fba080](https://github.com/libp2p/js-libp2p-interfaces/commit/2fba0800c9896af6dcc49da4fa904bb4a3e3e40d)) - -## [@libp2p/peer-record-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.1...@libp2p/peer-record-v1.0.2) (2022-02-11) - - -### Bug Fixes - -* simpler topologies ([#164](https://github.com/libp2p/js-libp2p-interfaces/issues/164)) ([45fcaa1](https://github.com/libp2p/js-libp2p-interfaces/commit/45fcaa10a6a3215089340ff2eff117d7fd1100e7)) - -## [@libp2p/peer-record-v1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-record-v1.0.0...@libp2p/peer-record-v1.0.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## @libp2p/peer-record-v1.0.0 (2022-02-09) - - -### Features - -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) diff --git a/packages/libp2p-peer-record/README.md b/packages/libp2p-peer-record/README.md deleted file mode 100644 index b6c6c9e41..000000000 --- a/packages/libp2p-peer-record/README.md +++ /dev/null @@ -1,179 +0,0 @@ -# libp2p-peer-record - -> Peer records are signed records that contain the address information of network peers - -## Table of Contents - -- [Description](#description) - - [Envelope](#envelope) -- [Usage](#usage) -- [Peer Record](#peer-record) - - [Usage](#usage-1) - - [Libp2p Flows](#libp2p-flows) - - [Self Record](#self-record) - - [Self record Updates](#self-record-updates) - - [Subsystem receiving a record](#subsystem-receiving-a-record) - - [Subsystem providing a record](#subsystem-providing-a-record) - - [Future Work](#future-work) -- [Example](#example) -- [Installation](#installation) -- [License](#license) - - [Contribution](#contribution) - -## Description - -Libp2p nodes need to store data in a public location (e.g. a DHT), or rely on potentially untrustworthy intermediaries to relay information over its lifetime. Accordingly, libp2p nodes need to be able to verify that the data came from a specific peer and that it hasn't been tampered with. - -### Envelope - -Libp2p provides an all-purpose data container called **envelope**. It was created to enable the distribution of verifiable records, which we can prove originated from the addressed peer itself. The envelope includes a signature of the data, so that its authenticity is verified. - -This envelope stores a marshaled record implementing the [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record). These Records are designed to be serialized to bytes and placed inside of the envelopes before being shared with other peers. - -You can read further about the envelope in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). - -## Usage - -- create an envelope with an instance of an [interface-record](https://github.com/libp2p/js-libp2p-interfaces/tree/master/src/record) implementation and prepare it for being exchanged: - -```js -// interface-record implementation example with the "libp2p-example" namespace -const Record = require('libp2p-interfaces/src/record') -const { fromString } = require('uint8arrays/from-string') - -class ExampleRecord extends Record { - constructor () { - super ('libp2p-example', fromString('0302', 'hex')) - } - - marshal () {} - - equals (other) {} -} - -ExampleRecord.createFromProtobuf = () => {} -``` - -```js -const Envelope = require('libp2p/src/record/envelop') -const ExampleRecord = require('./example-record') - -const rec = new ExampleRecord() -const e = await Envelope.seal(rec, peerId) -const wireData = e.marshal() -``` - -- consume a received envelope (`wireData`) and transform it back to a record: - -```js -const Envelope = require('libp2p/src/record/envelop') -const ExampleRecord = require('./example-record') - -const domain = 'libp2p-example' -let e - -try { - e = await Envelope.openAndCertify(wireData, domain) -} catch (err) {} - -const rec = ExampleRecord.createFromProtobuf(e.payload) -``` - -## Peer Record - -All libp2p nodes keep a `PeerStore`, that among other information stores a set of known addresses for each peer, which can come from a variety of sources. - -Libp2p peer records were created to enable the distribution of verifiable address records, which we can prove originated from the addressed peer itself. With such guarantees, libp2p is able to prioritize addresses based on their authenticity, with the most strict strategy being to only dial certified addresses (no strategies have been implemented at the time of writing). - -A peer record contains the peers' publicly reachable listen addresses, and may be extended in the future to contain additional metadata relevant to routing. It also contains a `seqNumber` field, a timestamp per the spec, so that we can verify the most recent record. - -You can read further about the Peer Record in [libp2p/specs#217](https://github.com/libp2p/specs/pull/217). - -### Usage - -- create a new Peer Record - -```js -const PeerRecord = require('libp2p/src/record/peer-record') - -const pr = new PeerRecord({ - peerId: node.peerId, - multiaddrs: node.multiaddrs -}) -``` - -- create a Peer Record from a protobuf - -```js -const PeerRecord = require('libp2p/src/record/peer-record') - -const pr = PeerRecord.createFromProtobuf(data) -``` - -### Libp2p Flows - -#### Self Record - -Once a libp2p node has started and is listening on a set of multiaddrs, its own peer record can be created. - -The identify service is responsible for creating the self record when the identify protocol kicks in for the first time. This record will be stored for future needs of the identify protocol when connecting with other peers. - -#### Self record Updates - -**_NOT_YET_IMPLEMENTED_** - -While creating peer records is fairly trivial, addresses are not static and might be modified at arbitrary times. This can happen via an Address Manager API, or even through AutoRelay/AutoNAT. - -When a libp2p node changes its listen addresses, the identify service will be informed. Once that happens, the identify service creates a new self record and stores it. With the new record, the identify push/delta protocol will be used to communicate this change to the connected peers. - -#### Subsystem receiving a record - -Considering that a node can discover other peers' addresses from a variety of sources, Libp2p Peerstore can differentiate the addresses that were obtained through a signed peer record. - -Once a record is received and its signature properly validated, its envelope is stored in the AddressBook in its byte representation. The `seqNumber` remains unmarshalled so that we can quickly compare it against incoming records to determine the most recent record. - -The AddressBook Addresses will be updated with the content of the envelope with a certified property. This allows other subsystems to identify the known certified addresses of a peer. - -#### Subsystem providing a record - -Libp2p subsystems that exchange other peers information will provide the envelope that they received by those peers. As a result, other peers can verify if the envelope was really created by the addressed peer. - -When a subsystem wants to provide a record, it will get it from the AddressBook, if it exists. Other subsystems are also able to provide the self record, since it is also stored in the AddressBook. - -### Future Work - -- Persistence only considering certified addresses? -- Peers may not know their own addresses. It's often impossible to automatically infer one's own public address, and peers may need to rely on third party peers to inform them of their observed public addresses. -- A peer may inadvertently or maliciously sign an address that they do not control. In other words, a signature isn't a guarantee that a given address is valid. -- Some addresses may be ambiguous. For example, addresses on a private subnet are valid within that subnet but are useless on the public internet. -- Once all these pieces are in place, we will also need a way to prioritize addresses based on their authenticity, that is, the dialer can prioritize self-certified addresses over addresses from an unknown origin. - - Modular dialer? (taken from go PR notes) - - With the modular dialer, users should easily be able to configure precedence. With dialer v1, anything we do to prioritise dials is gonna be spaghetti and adhoc. With the modular dialer, you’d be able to specify the order of dials when instantiating the pipeline. - - Multiple parallel dials. We already have the issue where new addresses aren't added to existing dials. - -## Example - -```JavaScript -import { trackedMap } from '@libp2p/tracked-map' - -const map = trackedMap({ metrics }) - -map.set('key', 'value') -``` - -## Installation - -```console -$ npm i @libp2p/peer-record -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-peer-record/package.json b/packages/libp2p-peer-record/package.json deleted file mode 100644 index 20a57f842..000000000 --- a/packages/libp2p-peer-record/package.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "name": "@libp2p/peer-record", - "version": "1.0.12", - "description": "Used to transfer signed peer data across the network", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-peer-record#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "IPFS" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - }, - "ignorePatterns": [ - "src/envelope/*.d.ts", - "src/envelope/envelope.js", - "src/peer-record/*.d.ts", - "src/peer-record/peer-record.js" - ] - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "generate": "protons src/envelope/envelope.proto src/peer-record/peer-record.proto", - "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "release": "aegir release" - }, - "dependencies": { - "@libp2p/crypto": "^0.22.8", - "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", - "@libp2p/peer-id": "^1.1.0", - "@libp2p/utils": "^1.0.9", - "@multiformats/multiaddr": "^10.1.5", - "err-code": "^3.0.1", - "interface-datastore": "^6.1.0", - "it-all": "^1.0.6", - "it-filter": "^1.0.3", - "it-foreach": "^0.1.1", - "it-map": "^1.0.6", - "it-pipe": "^2.0.3", - "multiformats": "^9.6.3", - "protons-runtime": "^1.0.4", - "uint8arrays": "^3.0.0", - "varint": "^6.0.0" - }, - "devDependencies": { - "@libp2p/interface-compliance-tests": "^2.0.0", - "@libp2p/peer-id-factory": "^1.0.0", - "@types/varint": "^6.0.0", - "aegir": "^37.0.7", - "protons": "^3.0.4", - "sinon": "^14.0.0" - } -} diff --git a/packages/libp2p-peer-record/src/envelope/envelope.proto b/packages/libp2p-peer-record/src/envelope/envelope.proto deleted file mode 100644 index 5b80cf504..000000000 --- a/packages/libp2p-peer-record/src/envelope/envelope.proto +++ /dev/null @@ -1,19 +0,0 @@ -syntax = "proto3"; - -message Envelope { - // public_key is the public key of the keypair the enclosed payload was - // signed with. - bytes public_key = 1; - - // payload_type encodes the type of payload, so that it can be deserialized - // deterministically. - bytes payload_type = 2; - - // payload is the actual payload carried inside this envelope. - bytes payload = 3; - - // signature is the signature produced by the private key corresponding to - // the enclosed public key, over the payload, prefixing a domain string for - // additional security. - bytes signature = 5; -} \ No newline at end of file diff --git a/packages/libp2p-peer-record/src/envelope/envelope.ts b/packages/libp2p-peer-record/src/envelope/envelope.ts deleted file mode 100644 index 43ef968f9..000000000 --- a/packages/libp2p-peer-record/src/envelope/envelope.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable import/export */ -/* eslint-disable @typescript-eslint/no-namespace */ - -import { encodeMessage, decodeMessage, message, bytes } from 'protons-runtime' -import type { Codec } from 'protons-runtime' - -export interface Envelope { - publicKey: Uint8Array - payloadType: Uint8Array - payload: Uint8Array - signature: Uint8Array -} - -export namespace Envelope { - export const codec = (): Codec => { - return message({ - 1: { name: 'publicKey', codec: bytes }, - 2: { name: 'payloadType', codec: bytes }, - 3: { name: 'payload', codec: bytes }, - 5: { name: 'signature', codec: bytes } - }) - } - - export const encode = (obj: Envelope): Uint8Array => { - return encodeMessage(obj, Envelope.codec()) - } - - export const decode = (buf: Uint8Array): Envelope => { - return decodeMessage(buf, Envelope.codec()) - } -} diff --git a/packages/libp2p-peer-record/src/envelope/index.ts b/packages/libp2p-peer-record/src/envelope/index.ts deleted file mode 100644 index f76095dfe..000000000 --- a/packages/libp2p-peer-record/src/envelope/index.ts +++ /dev/null @@ -1,164 +0,0 @@ -import errCode from 'err-code' -import { concat as uint8arraysConcat } from 'uint8arrays/concat' -import { fromString as uint8arraysFromString } from 'uint8arrays/from-string' -import { unmarshalPrivateKey, unmarshalPublicKey } from '@libp2p/crypto/keys' -import varint from 'varint' -import { equals as uint8arraysEquals } from 'uint8arrays/equals' -import { codes } from '../errors.js' -import { Envelope as Protobuf } from './envelope.js' -import { peerIdFromKeys } from '@libp2p/peer-id' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { Record, Envelope } from '@libp2p/interfaces/record' - -export interface EnvelopeInit { - peerId: PeerId - payloadType: Uint8Array - payload: Uint8Array - signature: Uint8Array -} - -export class RecordEnvelope implements Envelope { - /** - * Unmarshal a serialized Envelope protobuf message - */ - static createFromProtobuf = async (data: Uint8Array) => { - const envelopeData = Protobuf.decode(data) - const peerId = await peerIdFromKeys(envelopeData.publicKey) - - return new RecordEnvelope({ - peerId, - payloadType: envelopeData.payloadType, - payload: envelopeData.payload, - signature: envelopeData.signature - }) - } - - /** - * Seal marshals the given Record, places the marshaled bytes inside an Envelope - * and signs it with the given peerId's private key - */ - static seal = async (record: Record, peerId: PeerId) => { - const domain = record.domain - const payloadType = record.codec - const payload = record.marshal() - - const signData = formatSignaturePayload(domain, payloadType, payload) - - if (peerId.privateKey == null) { - throw new Error('Missing private key') - } - - const key = await unmarshalPrivateKey(peerId.privateKey) - const signature = await key.sign(signData) - - return new RecordEnvelope({ - peerId, - payloadType, - payload, - signature - }) - } - - /** - * Open and certify a given marshalled envelope. - * Data is unmarshalled and the signature validated for the given domain. - */ - static openAndCertify = async (data: Uint8Array, domain: string) => { - const envelope = await RecordEnvelope.createFromProtobuf(data) - const valid = await envelope.validate(domain) - - if (!valid) { - throw errCode(new Error('envelope signature is not valid for the given domain'), codes.ERR_SIGNATURE_NOT_VALID) - } - - return envelope - } - - public peerId: PeerId - public payloadType: Uint8Array - public payload: Uint8Array - public signature: Uint8Array - public marshaled?: Uint8Array - - /** - * The Envelope is responsible for keeping an arbitrary signed record - * by a libp2p peer. - */ - constructor (init: EnvelopeInit) { - const { peerId, payloadType, payload, signature } = init - - this.peerId = peerId - this.payloadType = payloadType - this.payload = payload - this.signature = signature - } - - /** - * Marshal the envelope content - */ - marshal () { - if (this.peerId.publicKey == null) { - throw new Error('Missing public key') - } - - if (this.marshaled == null) { - this.marshaled = Protobuf.encode({ - publicKey: this.peerId.publicKey, - payloadType: this.payloadType, - payload: this.payload, - signature: this.signature - }) - } - - return this.marshaled - } - - /** - * Verifies if the other Envelope is identical to this one - */ - equals (other: Envelope) { - return uint8arraysEquals(this.marshal(), other.marshal()) - } - - /** - * Validate envelope data signature for the given domain - */ - async validate (domain: string) { - const signData = formatSignaturePayload(domain, this.payloadType, this.payload) - - if (this.peerId.publicKey == null) { - throw new Error('Missing public key') - } - - const key = unmarshalPublicKey(this.peerId.publicKey) - - return await key.verify(signData, this.signature) - } -} - -/** - * Helper function that prepares a Uint8Array to sign or verify a signature - */ -const formatSignaturePayload = (domain: string, payloadType: Uint8Array, payload: Uint8Array) => { - // When signing, a peer will prepare a Uint8Array by concatenating the following: - // - The length of the domain separation string string in bytes - // - The domain separation string, encoded as UTF-8 - // - The length of the payload_type field in bytes - // - The value of the payload_type field - // - The length of the payload field in bytes - // - The value of the payload field - - const domainUint8Array = uint8arraysFromString(domain) - const domainLength = varint.encode(domainUint8Array.byteLength) - const payloadTypeLength = varint.encode(payloadType.length) - const payloadLength = varint.encode(payload.length) - - return uint8arraysConcat([ - new Uint8Array(domainLength), - domainUint8Array, - new Uint8Array(payloadTypeLength), - payloadType, - new Uint8Array(payloadLength), - payload - ]) -} diff --git a/packages/libp2p-peer-record/src/errors.ts b/packages/libp2p-peer-record/src/errors.ts deleted file mode 100644 index 0c09e34d6..000000000 --- a/packages/libp2p-peer-record/src/errors.ts +++ /dev/null @@ -1,4 +0,0 @@ - -export const codes = { - ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID' -} diff --git a/packages/libp2p-peer-record/src/index.ts b/packages/libp2p-peer-record/src/index.ts deleted file mode 100644 index c05f140aa..000000000 --- a/packages/libp2p-peer-record/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ - -export { RecordEnvelope } from './envelope/index.js' -export { PeerRecord } from './peer-record/index.js' diff --git a/packages/libp2p-peer-record/src/peer-record/consts.js b/packages/libp2p-peer-record/src/peer-record/consts.js deleted file mode 100644 index 8f862e33b..000000000 --- a/packages/libp2p-peer-record/src/peer-record/consts.js +++ /dev/null @@ -1,8 +0,0 @@ - -// The domain string used for peer records contained in a Envelope. -export const ENVELOPE_DOMAIN_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" -export const ENVELOPE_PAYLOAD_TYPE_PEER_RECORD = Uint8Array.from([3, 1]) diff --git a/packages/libp2p-peer-record/src/peer-record/index.ts b/packages/libp2p-peer-record/src/peer-record/index.ts deleted file mode 100644 index 57ab0e6da..000000000 --- a/packages/libp2p-peer-record/src/peer-record/index.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { Multiaddr } from '@multiformats/multiaddr' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { arrayEquals } from '@libp2p/utils/array-equals' -import { peerIdFromBytes } from '@libp2p/peer-id' -import { PeerRecord as Protobuf } from './peer-record.js' -import { - ENVELOPE_DOMAIN_PEER_RECORD, - ENVELOPE_PAYLOAD_TYPE_PEER_RECORD -} from './consts.js' - -export interface PeerRecordInit { - peerId: PeerId - - /** - * Addresses of the associated peer. - */ - multiaddrs?: Multiaddr[] - - /** - * Monotonically-increasing sequence counter that's used to order PeerRecords in time. - */ - seqNumber?: bigint -} - -/** - * The PeerRecord is used for distributing peer routing records across the network. - * It contains the peer's reachable listen addresses. - */ -export class PeerRecord { - /** - * Unmarshal Peer Record Protobuf - */ - static createFromProtobuf = (buf: Uint8Array): PeerRecord => { - const peerRecord = Protobuf.decode(buf) - const peerId = peerIdFromBytes(peerRecord.peerId) - const multiaddrs = (peerRecord.addresses ?? []).map((a) => new Multiaddr(a.multiaddr)) - const seqNumber = peerRecord.seq - - return new PeerRecord({ peerId, multiaddrs, seqNumber }) - } - - static DOMAIN = ENVELOPE_DOMAIN_PEER_RECORD - static CODEC = ENVELOPE_PAYLOAD_TYPE_PEER_RECORD - - public peerId: PeerId - public multiaddrs: Multiaddr[] - public seqNumber: bigint - public domain = PeerRecord.DOMAIN - public codec = PeerRecord.CODEC - private marshaled?: Uint8Array - - constructor (init: PeerRecordInit) { - const { peerId, multiaddrs, seqNumber } = init - - this.peerId = peerId - this.multiaddrs = multiaddrs ?? [] - this.seqNumber = seqNumber ?? BigInt(Date.now()) - } - - /** - * Marshal a record to be used in an envelope - */ - marshal () { - if (this.marshaled == null) { - this.marshaled = Protobuf.encode({ - peerId: this.peerId.toBytes(), - seq: BigInt(this.seqNumber), - addresses: this.multiaddrs.map((m) => ({ - multiaddr: m.bytes - })) - }) - } - - return this.marshaled - } - - /** - * Returns true if `this` record equals the `other` - */ - equals (other: unknown) { - if (!(other instanceof PeerRecord)) { - return false - } - - // Validate PeerId - if (!this.peerId.equals(other.peerId)) { - return false - } - - // Validate seqNumber - if (this.seqNumber !== other.seqNumber) { - return false - } - - // Validate multiaddrs - if (!arrayEquals(this.multiaddrs, other.multiaddrs)) { - return false - } - - return true - } -} diff --git a/packages/libp2p-peer-record/src/peer-record/peer-record.proto b/packages/libp2p-peer-record/src/peer-record/peer-record.proto deleted file mode 100644 index 6b740dc80..000000000 --- a/packages/libp2p-peer-record/src/peer-record/peer-record.proto +++ /dev/null @@ -1,18 +0,0 @@ -syntax = "proto3"; - -message PeerRecord { - // AddressInfo is a wrapper around a binary multiaddr. It is defined as a - // separate message to allow us to add per-address metadata in the future. - message AddressInfo { - bytes multiaddr = 1; - } - - // peer_id contains a libp2p peer id in its binary representation. - bytes peer_id = 1; - - // seq contains a monotonically-increasing sequence counter to order PeerRecords in time. - uint64 seq = 2; - - // addresses is a list of public listen addresses for the peer. - repeated AddressInfo addresses = 3; -} \ No newline at end of file diff --git a/packages/libp2p-peer-record/src/peer-record/peer-record.ts b/packages/libp2p-peer-record/src/peer-record/peer-record.ts deleted file mode 100644 index 946ce3457..000000000 --- a/packages/libp2p-peer-record/src/peer-record/peer-record.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* eslint-disable import/export */ -/* eslint-disable @typescript-eslint/no-namespace */ - -import { encodeMessage, decodeMessage, message, bytes, uint64 } from 'protons-runtime' -import type { Codec } from 'protons-runtime' - -export interface PeerRecord { - peerId: Uint8Array - seq: bigint - addresses: PeerRecord.AddressInfo[] -} - -export namespace PeerRecord { - export interface AddressInfo { - multiaddr: Uint8Array - } - - export namespace AddressInfo { - export const codec = (): Codec => { - return message({ - 1: { name: 'multiaddr', codec: bytes } - }) - } - - export const encode = (obj: AddressInfo): Uint8Array => { - return encodeMessage(obj, AddressInfo.codec()) - } - - export const decode = (buf: Uint8Array): AddressInfo => { - return decodeMessage(buf, AddressInfo.codec()) - } - } - - export const codec = (): Codec => { - return message({ - 1: { name: 'peerId', codec: bytes }, - 2: { name: 'seq', codec: uint64 }, - 3: { name: 'addresses', codec: PeerRecord.AddressInfo.codec(), repeats: true } - }) - } - - export const encode = (obj: PeerRecord): Uint8Array => { - return encodeMessage(obj, PeerRecord.codec()) - } - - export const decode = (buf: Uint8Array): PeerRecord => { - return decodeMessage(buf, PeerRecord.codec()) - } -} diff --git a/packages/libp2p-peer-record/test/envelope.spec.ts b/packages/libp2p-peer-record/test/envelope.spec.ts deleted file mode 100644 index 87648b033..000000000 --- a/packages/libp2p-peer-record/test/envelope.spec.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { expect } from 'aegir/chai' -import { fromString as uint8arrayFromString } from 'uint8arrays/from-string' -import { equals as uint8arrayEquals } from 'uint8arrays/equals' -import { RecordEnvelope } from '../src/envelope/index.js' -import { codes as ErrorCodes } from '../src/errors.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import type { Record } from '@libp2p/interfaces/record' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -const domain = 'libp2p-testing' -const codec = uint8arrayFromString('/libp2p/testdata') - -class TestRecord implements Record { - public domain: string - public codec: Uint8Array - public data: string - - constructor (data: string) { - this.domain = domain - this.codec = codec - this.data = data - } - - marshal () { - return uint8arrayFromString(this.data) - } - - equals (other: Record) { - return uint8arrayEquals(this.marshal(), other.marshal()) - } -} - -describe('Envelope', () => { - const payloadType = codec - let peerId: PeerId - let testRecord: TestRecord - - before(async () => { - peerId = await createEd25519PeerId() - testRecord = new TestRecord('test-data') - }) - - it('creates an envelope with a random key', () => { - const payload = testRecord.marshal() - const signature = uint8arrayFromString(Math.random().toString(36).substring(7)) - - const envelope = new RecordEnvelope({ - peerId, - payloadType, - payload, - signature - }) - - expect(envelope).to.exist() - expect(envelope.peerId.equals(peerId)).to.eql(true) - expect(envelope.payloadType).to.equalBytes(payloadType) - expect(envelope.payload).to.equalBytes(payload) - expect(envelope.signature).to.equalBytes(signature) - }) - - it('can seal a record', async () => { - const envelope = await RecordEnvelope.seal(testRecord, peerId) - expect(envelope).to.exist() - expect(envelope.peerId.equals(peerId)).to.eql(true) - expect(envelope.payloadType).to.eql(payloadType) - expect(envelope.payload).to.exist() - expect(envelope.signature).to.exist() - }) - - it('can open and verify a sealed record', async () => { - const envelope = await RecordEnvelope.seal(testRecord, peerId) - const rawEnvelope = envelope.marshal() - - const unmarshalledEnvelope = await RecordEnvelope.openAndCertify(rawEnvelope, testRecord.domain) - expect(unmarshalledEnvelope).to.exist() - - const equals = envelope.equals(unmarshalledEnvelope) - expect(equals).to.eql(true) - }) - - it('throw on open and verify when a different domain is used', async () => { - const envelope = await RecordEnvelope.seal(testRecord, peerId) - const rawEnvelope = envelope.marshal() - - await expect(RecordEnvelope.openAndCertify(rawEnvelope, '/bad-domain')) - .to.eventually.be.rejected() - .and.to.have.property('code', ErrorCodes.ERR_SIGNATURE_NOT_VALID) - }) -}) diff --git a/packages/libp2p-peer-record/test/peer-record.spec.ts b/packages/libp2p-peer-record/test/peer-record.spec.ts deleted file mode 100644 index 0d02ac30a..000000000 --- a/packages/libp2p-peer-record/test/peer-record.spec.ts +++ /dev/null @@ -1,156 +0,0 @@ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import tests from '@libp2p/interface-compliance-tests/record' -import { Multiaddr } from '@multiformats/multiaddr' -import { peerIdFromKeys } from '@libp2p/peer-id' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { RecordEnvelope } from '../src/envelope/index.js' -import { PeerRecord } from '../src/peer-record/index.js' -import { unmarshalPrivateKey } from '@libp2p/crypto/keys' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -describe('interface-record compliance', () => { - tests({ - async setup () { - const peerId = await createEd25519PeerId() - return new PeerRecord({ peerId }) - }, - async teardown () { - // cleanup resources created by setup() - } - }) -}) - -describe('PeerRecord', () => { - let peerId: PeerId - - before(async () => { - peerId = await createEd25519PeerId() - }) - - 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 key = await unmarshalPrivateKey(privKey) - const peerId = await peerIdFromKeys(key.public.bytes, key.bytes) - - const env = await RecordEnvelope.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 RecordEnvelope.seal(record, peerId) - expect(env.payloadType).to.eql(jsEnv.payloadType) - }) - - it('creates a peer record with peerId', () => { - const peerRecord = new PeerRecord({ peerId }) - - expect(peerRecord).to.exist() - expect(peerRecord.peerId).to.exist() - expect(peerRecord.multiaddrs).to.exist() - expect(peerRecord.multiaddrs).to.have.lengthOf(0) - expect(peerRecord.seqNumber).to.exist() - }) - - it('creates a peer record with provided data', () => { - const multiaddrs = [ - new Multiaddr('/ip4/127.0.0.1/tcp/2000') - ] - const seqNumber = BigInt(Date.now()) - const peerRecord = new PeerRecord({ peerId, multiaddrs, seqNumber }) - - expect(peerRecord).to.exist() - expect(peerRecord.peerId).to.exist() - expect(peerRecord.multiaddrs).to.exist() - expect(peerRecord.multiaddrs).to.eql(multiaddrs) - expect(peerRecord.seqNumber).to.exist() - expect(peerRecord.seqNumber).to.eql(seqNumber) - }) - - it('marshals and unmarshals a peer record', () => { - const multiaddrs = [ - new Multiaddr('/ip4/127.0.0.1/tcp/2000') - ] - const seqNumber = BigInt(Date.now()) - const peerRecord = new PeerRecord({ peerId, multiaddrs, seqNumber }) - - // Marshal - const rawData = peerRecord.marshal() - expect(rawData).to.exist() - - // Unmarshal - const unmarshalPeerRecord = PeerRecord.createFromProtobuf(rawData) - expect(unmarshalPeerRecord).to.exist() - - const equals = peerRecord.equals(unmarshalPeerRecord) - expect(equals).to.eql(true) - }) - - it('equals returns false if the peer record has a different peerId', async () => { - const peerRecord0 = new PeerRecord({ peerId }) - - const peerId1 = await createEd25519PeerId() - const peerRecord1 = new PeerRecord({ peerId: peerId1 }) - - const equals = peerRecord0.equals(peerRecord1) - expect(equals).to.eql(false) - }) - - it('equals returns false if the peer record has a different seqNumber', () => { - const ts0 = BigInt(Date.now()) - const peerRecord0 = new PeerRecord({ peerId, seqNumber: ts0 }) - - const ts1 = ts0 + 20n - const peerRecord1 = new PeerRecord({ peerId, seqNumber: ts1 }) - - const equals = peerRecord0.equals(peerRecord1) - expect(equals).to.eql(false) - }) - - it('equals returns false if the peer record has a different multiaddrs', () => { - const multiaddrs = [ - new Multiaddr('/ip4/127.0.0.1/tcp/2000') - ] - const peerRecord0 = new PeerRecord({ peerId, multiaddrs }) - - const multiaddrs1 = [ - new Multiaddr('/ip4/127.0.0.1/tcp/2001') - ] - const peerRecord1 = new PeerRecord({ peerId, multiaddrs: multiaddrs1 }) - - const equals = peerRecord0.equals(peerRecord1) - expect(equals).to.eql(false) - }) -}) - -describe('PeerRecord inside Envelope', () => { - let peerId: PeerId - let peerRecord: PeerRecord - - before(async () => { - peerId = await createEd25519PeerId() - const multiaddrs = [ - new Multiaddr('/ip4/127.0.0.1/tcp/2000') - ] - const seqNumber = BigInt(Date.now()) - peerRecord = new PeerRecord({ peerId, multiaddrs, seqNumber }) - }) - - it('creates an envelope with the PeerRecord and can unmarshal it', async () => { - const e = await RecordEnvelope.seal(peerRecord, peerId) - const byteE = e.marshal() - - const decodedE = await RecordEnvelope.openAndCertify(byteE, PeerRecord.DOMAIN) - expect(decodedE).to.exist() - - const decodedPeerRecord = PeerRecord.createFromProtobuf(decodedE.payload) - - const equals = peerRecord.equals(decodedPeerRecord) - expect(equals).to.eql(true) - }) -}) diff --git a/packages/libp2p-peer-record/tsconfig.json b/packages/libp2p-peer-record/tsconfig.json deleted file mode 100644 index 3ab2966fd..000000000 --- a/packages/libp2p-peer-record/tsconfig.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "extends": "aegir/src/config/tsconfig.aegir.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": [ - "src", - "test" - ], - "exclude": [ - "src/envelope/envelope.js", - "src/peer-record/peer-record.js" - ], - "references": [ - { - "path": "../libp2p-interface-compliance-tests" - }, - { - "path": "../libp2p-interfaces" - }, - { - "path": "../libp2p-logger" - }, - { - "path": "../libp2p-peer-id" - }, - { - "path": "../libp2p-peer-id-factory" - } - ] -} diff --git a/packages/libp2p-peer-store/CHANGELOG.md b/packages/libp2p-peer-store/CHANGELOG.md deleted file mode 100644 index be6527851..000000000 --- a/packages/libp2p-peer-store/CHANGELOG.md +++ /dev/null @@ -1,123 +0,0 @@ -## [@libp2p/peer-store-v1.0.16](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.15...@libp2p/peer-store-v1.0.16) (2022-05-20) - - -### Bug Fixes - -* update sibling deps ([#216](https://github.com/libp2p/js-libp2p-interfaces/issues/216)) ([0ceca65](https://github.com/libp2p/js-libp2p-interfaces/commit/0ceca658901e92de554c828105b328b88a1416f8)) - -## [@libp2p/peer-store-v1.0.15](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.14...@libp2p/peer-store-v1.0.15) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/peer-store-v1.0.14](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.13...@libp2p/peer-store-v1.0.14) (2022-05-10) - - -### Trivial Changes - -* **deps:** bump sinon from 13.0.2 to 14.0.0 ([#211](https://github.com/libp2p/js-libp2p-interfaces/issues/211)) ([8859f70](https://github.com/libp2p/js-libp2p-interfaces/commit/8859f70943c0bcdb210f54a338ae901739e5e6f2)) - -## [@libp2p/peer-store-v1.0.13](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.12...@libp2p/peer-store-v1.0.13) (2022-05-10) - - -### Bug Fixes - -* regenerate protobuf code ([#212](https://github.com/libp2p/js-libp2p-interfaces/issues/212)) ([3cf210e](https://github.com/libp2p/js-libp2p-interfaces/commit/3cf210e230863f8049ac6c3ed2e73abb180fb8b2)) - -## [@libp2p/peer-store-v1.0.12](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.11...@libp2p/peer-store-v1.0.12) (2022-05-04) - - -### Bug Fixes - -* move startable and events interfaces ([#209](https://github.com/libp2p/js-libp2p-interfaces/issues/209)) ([8ce8a08](https://github.com/libp2p/js-libp2p-interfaces/commit/8ce8a08c94b0738aa32da516558977b195ddd8ed)) - -## [@libp2p/peer-store-v1.0.11](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.10...@libp2p/peer-store-v1.0.11) (2022-05-01) - - -### Bug Fixes - -* move connection manager mock to connection manager module ([#205](https://github.com/libp2p/js-libp2p-interfaces/issues/205)) ([a367375](https://github.com/libp2p/js-libp2p-interfaces/commit/a367375accc690d7b4608c9a3313f91df700efd8)) - -## [@libp2p/peer-store-v1.0.10](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.9...@libp2p/peer-store-v1.0.10) (2022-04-19) - - -### Bug Fixes - -* move dev deps to prod ([#195](https://github.com/libp2p/js-libp2p-interfaces/issues/195)) ([3e1ffc7](https://github.com/libp2p/js-libp2p-interfaces/commit/3e1ffc7b174e74be483943ad4e5fcab823ae3f6d)) - -## [@libp2p/peer-store-v1.0.9](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.8...@libp2p/peer-store-v1.0.9) (2022-04-14) - - -### Bug Fixes - -* add logger methods, fix peer id deserialization ([#194](https://github.com/libp2p/js-libp2p-interfaces/issues/194)) ([f0e1fad](https://github.com/libp2p/js-libp2p-interfaces/commit/f0e1fad42701d73eef4233ec2b9a8aafa0b2ab96)) - -## [@libp2p/peer-store-v1.0.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.7...@libp2p/peer-store-v1.0.8) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/peer-store-v1.0.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.6...@libp2p/peer-store-v1.0.7) (2022-03-24) - - -### Bug Fixes - -* rename peer data to peer info ([#187](https://github.com/libp2p/js-libp2p-interfaces/issues/187)) ([dfea342](https://github.com/libp2p/js-libp2p-interfaces/commit/dfea3429bad57abde040397e4e7a58539829e9c2)) - -## [@libp2p/peer-store-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.5...@libp2p/peer-store-v1.0.6) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/peer-store-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.4...@libp2p/peer-store-v1.0.5) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/peer-store-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.3...@libp2p/peer-store-v1.0.4) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/peer-store-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.2...@libp2p/peer-store-v1.0.3) (2022-02-12) - - -### Bug Fixes - -* hide implementations behind factory methods ([#167](https://github.com/libp2p/js-libp2p-interfaces/issues/167)) ([2fba080](https://github.com/libp2p/js-libp2p-interfaces/commit/2fba0800c9896af6dcc49da4fa904bb4a3e3e40d)) - -## [@libp2p/peer-store-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.1...@libp2p/peer-store-v1.0.2) (2022-02-11) - - -### Bug Fixes - -* simpler topologies ([#164](https://github.com/libp2p/js-libp2p-interfaces/issues/164)) ([45fcaa1](https://github.com/libp2p/js-libp2p-interfaces/commit/45fcaa10a6a3215089340ff2eff117d7fd1100e7)) - -## [@libp2p/peer-store-v1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/peer-store-v1.0.0...@libp2p/peer-store-v1.0.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## @libp2p/peer-store-v1.0.0 (2022-02-09) - - -### Features - -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) diff --git a/packages/libp2p-peer-store/README.md b/packages/libp2p-peer-store/README.md deleted file mode 100644 index 588c13600..000000000 --- a/packages/libp2p-peer-store/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# libp2p-tracked-map - -> allows tracking metrics in libp2p - -## Table of Contents - -- [Description](#description) -- [Example](#example) -- [Installation](#installation) -- [License](#license) - - [Contribution](#contribution) - -## Description - -A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. - -If metrics are disabled a regular map is used. - -## Example - -```JavaScript -import { trackedMap } from '@libp2p/tracked-map' - -const map = trackedMap({ metrics }) - -map.set('key', 'value') -``` - -## Installation - -```console -$ npm i @libp2p/tracked-map -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-peer-store/package.json b/packages/libp2p-peer-store/package.json deleted file mode 100644 index ea162bd6a..000000000 --- a/packages/libp2p-peer-store/package.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "name": "@libp2p/peer-store", - "version": "1.0.16", - "description": "Stores information about peers libp2p knows on the network", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-peer-store#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "IPFS" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - }, - "ignorePatterns": [ - "src/pb/*.d.ts", - "src/pb/peer.js" - ] - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "generate": "protons src/pb/peer.proto", - "build": "aegir build", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "release": "aegir release" - }, - "dependencies": { - "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", - "@libp2p/peer-id": "^1.1.0", - "@libp2p/peer-record": "^1.0.0", - "@multiformats/multiaddr": "^10.1.5", - "err-code": "^3.0.1", - "interface-datastore": "^6.1.0", - "it-all": "^1.0.6", - "it-filter": "^1.0.3", - "it-foreach": "^0.1.1", - "it-map": "^1.0.6", - "it-pipe": "^2.0.3", - "mortice": "^3.0.0", - "multiformats": "^9.6.3", - "protons-runtime": "^1.0.4", - "uint8arrays": "^3.0.0" - }, - "devDependencies": { - "@libp2p/interface-compliance-tests": "^2.0.0", - "@libp2p/peer-id-factory": "^1.0.0", - "@libp2p/utils": "^1.0.9", - "aegir": "^37.0.7", - "datastore-core": "^7.0.1", - "p-defer": "^4.0.0", - "p-wait-for": "^4.1.0", - "protons": "^3.0.4", - "sinon": "^14.0.0" - } -} diff --git a/packages/libp2p-peer-store/src/README.md b/packages/libp2p-peer-store/src/README.md deleted file mode 100644 index 1a8fb6ccb..000000000 --- a/packages/libp2p-peer-store/src/README.md +++ /dev/null @@ -1,145 +0,0 @@ -# PeerStore - -Libp2p's PeerStore is responsible for keeping an updated register with the relevant information of the known peers. It should be the single source of truth for all peer data, where a subsystem can learn about peers' data and where someone can listen for updates. The PeerStore comprises four main components: `addressBook`, `keyBook`, `protocolBook` and `metadataBook`. - -The PeerStore manages the high level operations on its inner books. Moreover, the PeerStore should be responsible for notifying interested parties of relevant events, through its Event Emitter. - -## Submitting records to the PeerStore - -Several libp2p subsystems will perform operations that might gather relevant information about peers. - -### Identify -- The Identify protocol automatically runs on every connection when multiplexing is enabled. The protocol will put the multiaddrs and protocols provided by the peer to the PeerStore. -- In the background, the Identify Service is also waiting for protocol change notifications of peers via the IdentifyPush protocol. Peers may leverage the `identify-push` message to communicate protocol changes to all connected peers, so that their PeerStore can be updated with the updated protocols. -- While it is currently not supported in js-libp2p, future iterations may also support the [IdentifyDelta protocol](https://github.com/libp2p/specs/pull/176). -- Taking into account that the Identify protocol records are directly from the peer, they should be considered the source of truth and weighted accordingly. - -### Peer Discovery -- Libp2p discovery protocols aim to discover new peers in the network. In a typical discovery protocol, addresses of the peer are discovered along with its peer id. Once this happens, a libp2p discovery protocol should emit a `peer` event with the information of the discovered peer and this information will be added to the PeerStore by libp2p. - -### Dialer -- Libp2p API supports dialing a peer given a `multiaddr`, and no prior knowledge of the peer. If the node is able to establish a connection with the peer, it and its multiaddr is added to the PeerStore. -- When a connection is being upgraded, more precisely after its encryption, or even in a discovery protocol, a libp2p node can get to know other parties public keys. In this scenario, libp2p will add the peer's public key to its `KeyBook`. - -### DHT -- On some DHT operations, such as finding providers for a given CID, nodes may exchange peer data as part of the query. This passive peer discovery should result in the DHT emitting the `peer` event in the same way [Peer Discovery](#peerdiscovery) does. - -## Retrieving records from the PeerStore - -When data in the PeerStore is updated the PeerStore will emit events based on the changes, to allow applications and other subsystems to take action on those changes. Any subsystem interested in these notifications should subscribe the [`PeerStore events`][peer-store-events]. - -### Peer -- Each time a new peer is discovered, the PeerStore should emit a [`peer` event][peer-store-events], so that interested parties can leverage this peer and establish a connection with it. - -### Protocols -- When the known protocols of a peer change, the PeerStore emits a [`change:protocols` event][peer-store-events]. - -### Multiaddrs -- When the known listening `multiaddrs` of a peer change, the PeerStore emits a [`change:multiaddrs` event][peer-store-events]. - -## PeerStore implementation - -The PeerStore wraps four main components: `addressBook`, `keyBook`, `protocolBook` and `metadataBook`. Moreover, it provides a high level API for those components, as well as data events. - -### Components - -#### Address Book - -The `addressBook` keeps the known multiaddrs of a peer. The multiaddrs of each peer may change over time and the Address Book must account for this. - -`Map` - -A `peerId.toString()` identifier mapping to a `Address` object, which should have the following structure: - -```js -{ - multiaddr: -} -``` - -#### Key Book - -The `keyBook` tracks the public keys of the peers by keeping their [`PeerId`][peer-id]. - -`Map>` - -A `peerId.toString()` identifier mapping to a `Set` of protocol identifier strings. - -#### Metadata Book - -The `metadataBook` keeps track of the known metadata of a peer. Its metadata is stored in a key value fashion, where a key identifier (`string`) represents a metadata value (`Uint8Array`). - -`Map>` - -A `peerId.toString()` identifier mapping to the peer metadata Map. - -### API - -For the complete API documentation, you should check the [API.md](../../doc/API.md). - -Access to its underlying books: - -- `peerStore.addressBook.*` -- `peerStore.keyBook.*` -- `peerStore.metadataBook.*` -- `peerStore.protoBook.*` - -### Events - -- `peer` - emitted when a new peer is added. -- `change:multiaadrs` - emitted when a known peer has a different set of multiaddrs. -- `change:protocols` - emitted when a known peer supports a different set of protocols. -- `change:pubkey` - emitted when a peer's public key is known. -- `change:metadata` - emitted when known metadata of a peer changes. - -## Data Persistence - -The data stored in the PeerStore can be persisted if configured appropriately. Keeping a record of the peers already discovered by the peer, as well as their known data aims to improve the efficiency of peers joining the network after being offline. - -The libp2p node will need to receive a [datastore](https://github.com/ipfs/interface-datastore), in order to persist this data across restarts. A [datastore](https://github.com/ipfs/interface-datastore) stores its data in a key-value fashion. As a result, we need coherent keys so that we do not overwrite data. - -The PeerStore should not continuously update the datastore whenever data is changed. Instead, it should only store new data after reaching a certain threshold of "dirty" peers, as well as when the node is stopped, in order to batch writes to the datastore. - -The peer id will be appended to the datastore key for each data namespace. The namespaces were defined as follows: - -**AddressBook** - -All the known peer addresses are stored with a key pattern as follows: - -`/peers/addrs/` - -**ProtoBook** - -All the known peer protocols are stored with a key pattern as follows: - -`/peers/protos/` - -**KeyBook** - -All public keys are stored under the following pattern: - -` /peers/keys/` - -**MetadataBook** - -Metadata is stored under the following key pattern: - -`/peers/metadata//` - -## Future Considerations - -- If multiaddr TTLs are added, the PeerStore may schedule jobs to delete all addresses that exceed the TTL to prevent AddressBook bloating -- Further API methods will probably need to be added in the context of multiaddr validity and confidence. -- When improving libp2p configuration for specific runtimes, we should take into account the PeerStore recommended datastore. -- When improving libp2p configuration, we should think about a possible way of allowing the configuration of Bootstrap to be influenced by the persisted peers, as a way to decrease the load on Bootstrap nodes. - -[peer-id]: https://github.com/libp2p/js-peer-id -[peer-store-events]: ../../doc/API.md#libp2ppeerstore diff --git a/packages/libp2p-peer-store/src/address-book.ts b/packages/libp2p-peer-store/src/address-book.ts deleted file mode 100644 index 34df045bb..000000000 --- a/packages/libp2p-peer-store/src/address-book.ts +++ /dev/null @@ -1,365 +0,0 @@ -import { logger } from '@libp2p/logger' -import errcode from 'err-code' -import { Multiaddr } from '@multiformats/multiaddr' -import { codes } from './errors.js' -import { PeerRecord, RecordEnvelope } from '@libp2p/peer-record' -import { pipe } from 'it-pipe' -import all from 'it-all' -import filter from 'it-filter' -import map from 'it-map' -import each from 'it-foreach' -import { peerIdFromPeerId } from '@libp2p/peer-id' -import { CustomEvent } from '@libp2p/interfaces/events' -import type { AddressFilter, Peer, PeerMultiaddrsChangeData, PeerStore } from '@libp2p/interfaces/peer-store' -import type { Store } from './store.js' -import type { Envelope } from '@libp2p/interfaces/record' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { PeerInfo } from '@libp2p/interfaces/peer-info' - -const log = logger('libp2p:peer-store:address-book') -const EVENT_NAME = 'change:multiaddrs' - -async function allowAll () { - return true -} - -export class PeerStoreAddressBook { - private readonly dispatchEvent: PeerStore['dispatchEvent'] - private readonly store: Store - private readonly addressFilter: AddressFilter - - constructor (dispatchEvent: PeerStore['dispatchEvent'], store: Store, addressFilter?: AddressFilter) { - this.dispatchEvent = dispatchEvent - this.store = store - this.addressFilter = addressFilter ?? allowAll - } - - /** - * ConsumePeerRecord adds addresses from a signed peer record contained in a record envelope. - * This will return a boolean that indicates if the record was successfully processed and added - * into the AddressBook. - */ - async consumePeerRecord (envelope: Envelope) { - log.trace('consumePeerRecord await write lock') - const release = await this.store.lock.writeLock() - log.trace('consumePeerRecord got write lock') - - let peerId - let peer: Peer | undefined - let updatedPeer - - try { - let peerRecord - try { - peerRecord = PeerRecord.createFromProtobuf(envelope.payload) - } catch (err: any) { - log.error('invalid peer record received') - return false - } - - peerId = peerRecord.peerId - const multiaddrs = peerRecord.multiaddrs - - // Verify peerId - if (!peerId.equals(envelope.peerId)) { - log('signing key does not match PeerId in the PeerRecord') - return false - } - - // ensure the record has multiaddrs - if (multiaddrs == null || multiaddrs.length === 0) { - return false - } - - if (await this.store.has(peerId)) { - peer = await this.store.load(peerId) - - if (peer.peerRecordEnvelope != null) { - const storedEnvelope = await RecordEnvelope.createFromProtobuf(peer.peerRecordEnvelope) - const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload) - - // ensure seq is greater than, or equal to, the last received - if (storedRecord.seqNumber >= peerRecord.seqNumber) { - log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber) - return false - } - } - } - - const addresses = await filterMultiaddrs(peerId, multiaddrs, this.addressFilter, true) - - // Replace unsigned addresses by the new ones from the record - // TODO: Once we have ttls for the addresses, we should merge these in - updatedPeer = await this.store.patchOrCreate(peerId, { - addresses, - peerRecordEnvelope: envelope.marshal() - }) - - log('stored provided peer record for %p', peerRecord.peerId) - } finally { - log.trace('consumePeerRecord release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - multiaddrs: updatedPeer.addresses.map(({ multiaddr }) => multiaddr), - oldMultiaddrs: peer == null ? [] : peer.addresses.map(({ multiaddr }) => multiaddr) - } - })) - - return true - } - - async getRawEnvelope (peerId: PeerId) { - log.trace('getRawEnvelope await read lock') - const release = await this.store.lock.readLock() - log.trace('getRawEnvelope got read lock') - - try { - const peer = await this.store.load(peerId) - - return peer.peerRecordEnvelope - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('getRawEnvelope release read lock') - release() - } - } - - /** - * Get an Envelope containing a PeerRecord for the given peer. - * Returns undefined if no record exists. - */ - async getPeerRecord (peerId: PeerId) { - const raw = await this.getRawEnvelope(peerId) - - if (raw == null) { - return undefined - } - - return await RecordEnvelope.createFromProtobuf(raw) - } - - async get (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('get wait for read lock') - const release = await this.store.lock.readLock() - log.trace('get got read lock') - - try { - const peer = await this.store.load(peerId) - - return peer.addresses - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('get release read lock') - release() - } - - return [] - } - - async set (peerId: PeerId, multiaddrs: Multiaddr[]) { - peerId = peerIdFromPeerId(peerId) - - if (!Array.isArray(multiaddrs)) { - log.error('multiaddrs must be an array of Multiaddrs') - throw errcode(new Error('multiaddrs must be an array of Multiaddrs'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('set await write lock') - const release = await this.store.lock.writeLock() - log.trace('set got write lock') - - let hasPeer = false - let peer: Peer | undefined - let updatedPeer - - try { - const addresses = await filterMultiaddrs(peerId, multiaddrs, this.addressFilter) - - // No valid addresses found - if (addresses.length === 0) { - return - } - - try { - peer = await this.store.load(peerId) - hasPeer = true - - if (new Set([ - ...addresses.map(({ multiaddr }) => multiaddr.toString()), - ...peer.addresses.map(({ multiaddr }) => multiaddr.toString()) - ]).size === peer.addresses.length && addresses.length === peer.addresses.length) { - // not changing anything, no need to update - return - } - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - updatedPeer = await this.store.patchOrCreate(peerId, { addresses }) - - log('set multiaddrs for %p', peerId) - } finally { - log.trace('set multiaddrs for %p', peerId) - log('set release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - multiaddrs: updatedPeer.addresses.map(addr => addr.multiaddr), - oldMultiaddrs: peer == null ? [] : peer.addresses.map(({ multiaddr }) => multiaddr) - } - })) - - // Notify the existence of a new peer - if (!hasPeer) { - this.dispatchEvent(new CustomEvent('peer', { - detail: { - id: peerId, - multiaddrs: updatedPeer.addresses.map(addr => addr.multiaddr), - protocols: updatedPeer.protocols - } - })) - } - } - - async add (peerId: PeerId, multiaddrs: Multiaddr[]) { - peerId = peerIdFromPeerId(peerId) - - if (!Array.isArray(multiaddrs)) { - log.error('multiaddrs must be an array of Multiaddrs') - throw errcode(new Error('multiaddrs must be an array of Multiaddrs'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('add await write lock') - const release = await this.store.lock.writeLock() - log.trace('add got write lock') - - let hasPeer - let peer: Peer | undefined - let updatedPeer - - try { - const addresses = await filterMultiaddrs(peerId, multiaddrs, this.addressFilter) - - // No valid addresses found - if (addresses.length === 0) { - return - } - - try { - peer = await this.store.load(peerId) - hasPeer = true - - if (new Set([ - ...addresses.map(({ multiaddr }) => multiaddr.toString()), - ...peer.addresses.map(({ multiaddr }) => multiaddr.toString()) - ]).size === peer.addresses.length) { - return - } - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - updatedPeer = await this.store.mergeOrCreate(peerId, { addresses }) - - log('added multiaddrs for %p', peerId) - } finally { - log.trace('set release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - multiaddrs: updatedPeer.addresses.map(addr => addr.multiaddr), - oldMultiaddrs: peer == null ? [] : peer.addresses.map(({ multiaddr }) => multiaddr) - } - })) - - // Notify the existence of a new peer - if (hasPeer === true) { - this.dispatchEvent(new CustomEvent('peer', { - detail: { - id: peerId, - multiaddrs: updatedPeer.addresses.map(addr => addr.multiaddr), - protocols: updatedPeer.protocols - } - })) - } - } - - async delete (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('delete await write lock') - const release = await this.store.lock.writeLock() - log.trace('delete got write lock') - - let peer: Peer | undefined - - try { - try { - peer = await this.store.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - await this.store.patchOrCreate(peerId, { - addresses: [] - }) - } finally { - log.trace('delete release write lock') - release() - } - - if (peer != null) { - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - multiaddrs: [], - oldMultiaddrs: peer == null ? [] : peer.addresses.map(({ multiaddr }) => multiaddr) - } - })) - } - } -} - -async function filterMultiaddrs (peerId: PeerId, multiaddrs: Multiaddr[], addressFilter: AddressFilter, isCertified: boolean = false) { - return await pipe( - multiaddrs, - (source) => each(source, (multiaddr) => { - if (!Multiaddr.isMultiaddr(multiaddr)) { - log.error('multiaddr must be an instance of Multiaddr') - throw errcode(new Error('multiaddr must be an instance of Multiaddr'), codes.ERR_INVALID_PARAMETERS) - } - }), - (source) => filter(source, async (multiaddr) => await addressFilter(peerId, multiaddr)), - (source) => map(source, (multiaddr) => { - return { - multiaddr: new Multiaddr(multiaddr.toString()), - isCertified - } - }), - async (source) => await all(source) - ) -} diff --git a/packages/libp2p-peer-store/src/errors.ts b/packages/libp2p-peer-store/src/errors.ts deleted file mode 100644 index 60efb244d..000000000 --- a/packages/libp2p-peer-store/src/errors.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export const codes = { - ERR_INVALID_PARAMETERS: 'ERR_INVALID_PARAMETERS', - ERR_NOT_FOUND: 'ERR_NOT_FOUND' -} diff --git a/packages/libp2p-peer-store/src/index.ts b/packages/libp2p-peer-store/src/index.ts deleted file mode 100644 index 8ec502f28..000000000 --- a/packages/libp2p-peer-store/src/index.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { logger } from '@libp2p/logger' -import { EventEmitter } from '@libp2p/interfaces/events' -import { PeerStoreAddressBook } from './address-book.js' -import { PeerStoreKeyBook } from './key-book.js' -import { PeerStoreMetadataBook } from './metadata-book.js' -import { PeerStoreProtoBook } from './proto-book.js' -import { PersistentStore, Store } from './store.js' -import type { PeerStore, AddressBook, KeyBook, MetadataBook, ProtoBook, PeerStoreEvents, PeerStoreInit, Peer } from '@libp2p/interfaces/peer-store' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { Components, Initializable } from '@libp2p/interfaces/components' - -const log = logger('libp2p:peer-store') - -/** - * An implementation of PeerStore that stores data in a Datastore - */ -export class PersistentPeerStore extends EventEmitter implements PeerStore, Initializable { - public addressBook: AddressBook - public keyBook: KeyBook - public metadataBook: MetadataBook - public protoBook: ProtoBook - - private components: Components = new Components() - private readonly store: Store - - constructor (init: PeerStoreInit = {}) { - super() - - this.store = new PersistentStore() - this.addressBook = new PeerStoreAddressBook(this.dispatchEvent.bind(this), this.store, init.addressFilter) - this.keyBook = new PeerStoreKeyBook(this.dispatchEvent.bind(this), this.store) - this.metadataBook = new PeerStoreMetadataBook(this.dispatchEvent.bind(this), this.store) - this.protoBook = new PeerStoreProtoBook(this.dispatchEvent.bind(this), this.store) - } - - init (components: Components) { - this.components = components - ;(this.store as PersistentStore).init(components) - } - - async forEach (fn: (peer: Peer) => void) { - log.trace('getPeers await read lock') - const release = await this.store.lock.readLock() - log.trace('getPeers got read lock') - - try { - for await (const peer of this.store.all()) { - if (peer.id.equals(this.components.getPeerId())) { - // Skip self peer if present - continue - } - - fn(peer) - } - } finally { - log.trace('getPeers release read lock') - release() - } - } - - async all (): Promise { - const output: Peer[] = [] - - await this.forEach(peer => { - output.push(peer) - }) - - return output - } - - /** - * Delete the information of the given peer in every book - */ - async delete (peerId: PeerId) { - log.trace('delete await write lock') - const release = await this.store.lock.writeLock() - log.trace('delete got write lock') - - try { - await this.store.delete(peerId) - } finally { - log.trace('delete release write lock') - release() - } - } - - /** - * Get the stored information of a given peer - */ - async get (peerId: PeerId) { - log.trace('get await read lock') - const release = await this.store.lock.readLock() - log.trace('get got read lock') - - try { - return await this.store.load(peerId) - } finally { - log.trace('get release read lock') - release() - } - } - - /** - * Returns true if we have a record of the peer - */ - async has (peerId: PeerId) { - log.trace('has await read lock') - const release = await this.store.lock.readLock() - log.trace('has got read lock') - - try { - return await this.store.has(peerId) - } finally { - log.trace('has release read lock') - release() - } - } -} diff --git a/packages/libp2p-peer-store/src/key-book.ts b/packages/libp2p-peer-store/src/key-book.ts deleted file mode 100644 index 04f71ab3f..000000000 --- a/packages/libp2p-peer-store/src/key-book.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { logger } from '@libp2p/logger' -import errcode from 'err-code' -import { codes } from './errors.js' -import { peerIdFromPeerId } from '@libp2p/peer-id' -import { equals as uint8arrayEquals } from 'uint8arrays/equals' -import { CustomEvent } from '@libp2p/interfaces/events' -import type { Store } from './store.js' -import type { PeerStore, KeyBook, PeerPublicKeyChangeData, Peer } from '@libp2p/interfaces/peer-store' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -const log = logger('libp2p:peer-store:key-book') - -const EVENT_NAME = 'change:pubkey' - -export class PeerStoreKeyBook implements KeyBook { - private readonly dispatchEvent: PeerStore['dispatchEvent'] - private readonly store: Store - - /** - * The KeyBook is responsible for keeping the known public keys of a peer - */ - constructor (dispatchEvent: PeerStore['dispatchEvent'], store: Store) { - this.dispatchEvent = dispatchEvent - this.store = store - } - - /** - * Set the Peer public key - */ - async set (peerId: PeerId, publicKey: Uint8Array) { - peerId = peerIdFromPeerId(peerId) - - if (!(publicKey instanceof Uint8Array)) { - log.error('publicKey must be an instance of Uint8Array to store data') - throw errcode(new Error('publicKey must be an instance of PublicKey'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('set await write lock') - const release = await this.store.lock.writeLock() - log.trace('set got write lock') - - let updatedKey = false - let peer: Peer | undefined - - try { - try { - peer = await this.store.load(peerId) - - if ((peer.pubKey != null) && uint8arrayEquals(peer.pubKey, publicKey)) { - return - } - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - await this.store.patchOrCreate(peerId, { - pubKey: publicKey - }) - updatedKey = true - } finally { - log.trace('set release write lock') - release() - } - - if (updatedKey) { - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - publicKey: publicKey, - oldPublicKey: peer == null ? undefined : peer.pubKey - } - })) - } - } - - /** - * Get Public key of the given PeerId, if stored - */ - async get (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('get await write lock') - const release = await this.store.lock.readLock() - log.trace('get got write lock') - - try { - const peer = await this.store.load(peerId) - - return peer.pubKey - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log('get release write lock') - release() - } - } - - async delete (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('delete await write lock') - const release = await this.store.lock.writeLock() - log.trace('delete got write lock') - - let peer: Peer | undefined - - try { - try { - peer = await this.store.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - await this.store.patchOrCreate(peerId, { - pubKey: undefined - }) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('delete release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - publicKey: undefined, - oldPublicKey: peer == null ? undefined : peer.pubKey - } - })) - } -} diff --git a/packages/libp2p-peer-store/src/metadata-book.ts b/packages/libp2p-peer-store/src/metadata-book.ts deleted file mode 100644 index 72820271b..000000000 --- a/packages/libp2p-peer-store/src/metadata-book.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { logger } from '@libp2p/logger' -import errcode from 'err-code' -import { codes } from './errors.js' -import { peerIdFromPeerId } from '@libp2p/peer-id' -import { equals as uint8ArrayEquals } from 'uint8arrays/equals' -import { CustomEvent } from '@libp2p/interfaces/events' -import type { Store } from './store.js' -import type { PeerStore, MetadataBook, PeerMetadataChangeData, Peer } from '@libp2p/interfaces/peer-store' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -const log = logger('libp2p:peer-store:metadata-book') - -const EVENT_NAME = 'change:metadata' - -export class PeerStoreMetadataBook implements MetadataBook { - private readonly dispatchEvent: PeerStore['dispatchEvent'] - private readonly store: Store - - /** - * The MetadataBook is responsible for keeping metadata - * about known peers - */ - constructor (dispatchEvent: PeerStore['dispatchEvent'], store: Store) { - this.dispatchEvent = dispatchEvent - this.store = store - } - - /** - * Get the known data of a provided peer - */ - async get (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('get await read lock') - const release = await this.store.lock.readLock() - log.trace('get got read lock') - - try { - const peer = await this.store.load(peerId) - - return peer.metadata - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('get release read lock') - release() - } - - return new Map() - } - - /** - * Get specific metadata value, if it exists - */ - async getValue (peerId: PeerId, key: string) { - peerId = peerIdFromPeerId(peerId) - - log.trace('getValue await read lock') - const release = await this.store.lock.readLock() - log.trace('getValue got read lock') - - try { - const peer = await this.store.load(peerId) - - return peer.metadata.get(key) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('getValue release write lock') - release() - } - } - - async set (peerId: PeerId, metadata: Map) { - peerId = peerIdFromPeerId(peerId) - - if (!(metadata instanceof Map)) { - log.error('valid metadata must be provided to store data') - throw errcode(new Error('valid metadata must be provided'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('set await write lock') - const release = await this.store.lock.writeLock() - log.trace('set got write lock') - - let peer: Peer | undefined - - try { - try { - peer = await this.store.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - await this.store.mergeOrCreate(peerId, { - metadata - }) - } finally { - log.trace('set release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - metadata, - oldMetadata: peer == null ? new Map() : peer.metadata - } - })) - } - - /** - * Set metadata key and value of a provided peer - */ - async setValue (peerId: PeerId, key: string, value: Uint8Array) { - peerId = peerIdFromPeerId(peerId) - - if (typeof key !== 'string' || !(value instanceof Uint8Array)) { - log.error('valid key and value must be provided to store data') - throw errcode(new Error('valid key and value must be provided'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('setValue await write lock') - const release = await this.store.lock.writeLock() - log.trace('setValue got write lock') - - let peer: Peer | undefined - let updatedPeer - - try { - try { - peer = await this.store.load(peerId) - const existingValue = peer.metadata.get(key) - - if (existingValue != null && uint8ArrayEquals(value, existingValue)) { - return - } - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - updatedPeer = await this.store.mergeOrCreate(peerId, { - metadata: new Map([[key, value]]) - }) - } finally { - log.trace('setValue release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - metadata: updatedPeer.metadata, - oldMetadata: peer == null ? new Map() : peer.metadata - } - })) - } - - async delete (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('delete await write lock') - const release = await this.store.lock.writeLock() - log.trace('delete got write lock') - - let peer: Peer | undefined - - try { - try { - peer = await this.store.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - if (peer != null) { - await this.store.patch(peerId, { - metadata: new Map() - }) - } - } finally { - log.trace('delete release write lock') - release() - } - - if (peer != null) { - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - metadata: new Map(), - oldMetadata: peer.metadata - } - })) - } - } - - async deleteValue (peerId: PeerId, key: string) { - peerId = peerIdFromPeerId(peerId) - - log.trace('deleteValue await write lock') - const release = await this.store.lock.writeLock() - log.trace('deleteValue got write lock') - - let metadata - let peer: Peer | undefined - - try { - peer = await this.store.load(peerId) - metadata = peer.metadata - - metadata.delete(key) - - await this.store.patch(peerId, { - metadata - }) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('deleteValue release write lock') - release() - } - - if (metadata != null) { - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - metadata, - oldMetadata: peer == null ? new Map() : peer.metadata - } - })) - } - } -} diff --git a/packages/libp2p-peer-store/src/pb/peer.proto b/packages/libp2p-peer-store/src/pb/peer.proto deleted file mode 100644 index 1c9cc166c..000000000 --- a/packages/libp2p-peer-store/src/pb/peer.proto +++ /dev/null @@ -1,31 +0,0 @@ -syntax = "proto3"; - -message Peer { - // Multiaddrs we know about - repeated Address addresses = 1; - - // The protocols the peer supports - repeated string protocols = 2; - - // Any peer metadata - repeated Metadata metadata = 3; - - // The public key of the peer - optional bytes pub_key = 4; - - // The most recently received signed PeerRecord - optional bytes peer_record_envelope = 5; -} - -// Address represents a single multiaddr -message Address { - bytes multiaddr = 1; - - // Flag to indicate if the address comes from a certified source - optional bool isCertified = 2; -} - -message Metadata { - string key = 1; - bytes value = 2; -} diff --git a/packages/libp2p-peer-store/src/pb/peer.ts b/packages/libp2p-peer-store/src/pb/peer.ts deleted file mode 100644 index 3d7c83c65..000000000 --- a/packages/libp2p-peer-store/src/pb/peer.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* eslint-disable import/export */ -/* eslint-disable @typescript-eslint/no-namespace */ - -import { encodeMessage, decodeMessage, message, string, bytes, bool } from 'protons-runtime' -import type { Codec } from 'protons-runtime' - -export interface Peer { - addresses: Address[] - protocols: string[] - metadata: Metadata[] - pubKey?: Uint8Array - peerRecordEnvelope?: Uint8Array -} - -export namespace Peer { - export const codec = (): Codec => { - return message({ - 1: { name: 'addresses', codec: Address.codec(), repeats: true }, - 2: { name: 'protocols', codec: string, repeats: true }, - 3: { name: 'metadata', codec: Metadata.codec(), repeats: true }, - 4: { name: 'pubKey', codec: bytes, optional: true }, - 5: { name: 'peerRecordEnvelope', codec: bytes, optional: true } - }) - } - - export const encode = (obj: Peer): Uint8Array => { - return encodeMessage(obj, Peer.codec()) - } - - export const decode = (buf: Uint8Array): Peer => { - return decodeMessage(buf, Peer.codec()) - } -} - -export interface Address { - multiaddr: Uint8Array - isCertified?: boolean -} - -export namespace Address { - export const codec = (): Codec
=> { - return message
({ - 1: { name: 'multiaddr', codec: bytes }, - 2: { name: 'isCertified', codec: bool, optional: true } - }) - } - - export const encode = (obj: Address): Uint8Array => { - return encodeMessage(obj, Address.codec()) - } - - export const decode = (buf: Uint8Array): Address => { - return decodeMessage(buf, Address.codec()) - } -} - -export interface Metadata { - key: string - value: Uint8Array -} - -export namespace Metadata { - export const codec = (): Codec => { - return message({ - 1: { name: 'key', codec: string }, - 2: { name: 'value', codec: bytes } - }) - } - - export const encode = (obj: Metadata): Uint8Array => { - return encodeMessage(obj, Metadata.codec()) - } - - export const decode = (buf: Uint8Array): Metadata => { - return decodeMessage(buf, Metadata.codec()) - } -} diff --git a/packages/libp2p-peer-store/src/proto-book.ts b/packages/libp2p-peer-store/src/proto-book.ts deleted file mode 100644 index 5cf288a44..000000000 --- a/packages/libp2p-peer-store/src/proto-book.ts +++ /dev/null @@ -1,234 +0,0 @@ -import { logger } from '@libp2p/logger' -import errcode from 'err-code' -import { codes } from './errors.js' -import { peerIdFromPeerId } from '@libp2p/peer-id' -import { CustomEvent } from '@libp2p/interfaces/events' -import type { Store } from './store.js' -import type { Peer, PeerProtocolsChangeData, PeerStore, ProtoBook } from '@libp2p/interfaces/peer-store' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -const log = logger('libp2p:peer-store:proto-book') - -const EVENT_NAME = 'change:protocols' - -export class PeerStoreProtoBook implements ProtoBook { - private readonly dispatchEvent: PeerStore['dispatchEvent'] - private readonly store: Store - - /** - * The ProtoBook is responsible for keeping the known supported - * protocols of a peer - */ - constructor (dispatchEvent: PeerStore['dispatchEvent'], store: Store) { - this.dispatchEvent = dispatchEvent - this.store = store - } - - async get (peerId: PeerId) { - log.trace('get wait for read lock') - const release = await this.store.lock.readLock() - log.trace('get got read lock') - - try { - const peer = await this.store.load(peerId) - - return peer.protocols - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } finally { - log.trace('get release read lock') - release() - } - - return [] - } - - async set (peerId: PeerId, protocols: string[]) { - peerId = peerIdFromPeerId(peerId) - - if (!Array.isArray(protocols)) { - log.error('protocols must be provided to store data') - throw errcode(new Error('protocols must be provided'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('set await write lock') - const release = await this.store.lock.writeLock() - log.trace('set got write lock') - - let peer - let updatedPeer - - try { - try { - peer = await this.store.load(peerId) - - if (new Set([ - ...protocols - ]).size === peer.protocols.length) { - return - } - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - updatedPeer = await this.store.patchOrCreate(peerId, { - protocols - }) - - log('stored provided protocols for %p', peerId) - } finally { - log.trace('set release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - protocols: updatedPeer.protocols, - oldProtocols: peer == null ? [] : peer.protocols - } - })) - } - - async add (peerId: PeerId, protocols: string[]) { - peerId = peerIdFromPeerId(peerId) - - if (!Array.isArray(protocols)) { - log.error('protocols must be provided to store data') - throw errcode(new Error('protocols must be provided'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('add await write lock') - const release = await this.store.lock.writeLock() - log.trace('add got write lock') - - let peer: Peer | undefined - let updatedPeer - - try { - try { - peer = await this.store.load(peerId) - - if (new Set([ - ...peer.protocols, - ...protocols - ]).size === peer.protocols.length) { - return - } - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - updatedPeer = await this.store.mergeOrCreate(peerId, { - protocols - }) - - log('added provided protocols for %p', peerId) - } finally { - log.trace('add release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - protocols: updatedPeer.protocols, - oldProtocols: peer == null ? [] : peer.protocols - } - })) - } - - async remove (peerId: PeerId, protocols: string[]) { - peerId = peerIdFromPeerId(peerId) - - if (!Array.isArray(protocols)) { - log.error('protocols must be provided to store data') - throw errcode(new Error('protocols must be provided'), codes.ERR_INVALID_PARAMETERS) - } - - log.trace('remove await write lock') - const release = await this.store.lock.writeLock() - log.trace('remove got write lock') - - let peer: Peer | undefined - let updatedPeer: Peer - - try { - try { - peer = await this.store.load(peerId) - const protocolSet = new Set(peer.protocols) - - for (const protocol of protocols) { - protocolSet.delete(protocol) - } - - if (peer.protocols.length === protocolSet.size) { - return - } - - protocols = Array.from(protocolSet) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - updatedPeer = await this.store.patchOrCreate(peerId, { - protocols - }) - } finally { - log.trace('remove release write lock') - release() - } - - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - protocols: updatedPeer.protocols, - oldProtocols: peer == null ? [] : peer.protocols - } - })) - } - - async delete (peerId: PeerId) { - peerId = peerIdFromPeerId(peerId) - - log.trace('delete await write lock') - const release = await this.store.lock.writeLock() - log.trace('delete got write lock') - let peer: Peer | undefined - - try { - try { - peer = await this.store.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - } - - await this.store.patchOrCreate(peerId, { - protocols: [] - }) - } finally { - log.trace('delete release write lock') - release() - } - - if (peer != null) { - this.dispatchEvent(new CustomEvent(EVENT_NAME, { - detail: { - peerId, - protocols: [], - oldProtocols: peer.protocols - } - })) - } - } -} diff --git a/packages/libp2p-peer-store/src/store.ts b/packages/libp2p-peer-store/src/store.ts deleted file mode 100644 index c511a9c58..000000000 --- a/packages/libp2p-peer-store/src/store.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { logger } from '@libp2p/logger' -import { peerIdFromBytes } from '@libp2p/peer-id' -import errcode from 'err-code' -import { codes } from './errors.js' -import { Key } from 'interface-datastore/key' -import { base32 } from 'multiformats/bases/base32' -import { Multiaddr } from '@multiformats/multiaddr' -import { Metadata, Peer as PeerPB } from './pb/peer.js' -import mortice from 'mortice' -import { equals as uint8arrayEquals } from 'uint8arrays/equals' -import type { Peer } from '@libp2p/interfaces/peer-store' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { Components } from '@libp2p/interfaces/components' - -const log = logger('libp2p:peer-store:store') - -const NAMESPACE_COMMON = '/peers/' - -export interface Store { - has: (peerId: PeerId) => Promise - save: (peer: Peer) => Promise - load: (peerId: PeerId) => Promise - delete: (peerId: PeerId) => Promise - merge: (peerId: PeerId, data: Partial) => Promise - mergeOrCreate: (peerId: PeerId, data: Partial) => Promise - patch: (peerId: PeerId, data: Partial) => Promise - patchOrCreate: (peerId: PeerId, data: Partial) => Promise - all: () => AsyncIterable - - lock: { - readLock: () => Promise<() => void> - writeLock: () => Promise<() => void> - } -} - -export class PersistentStore { - private components: Components = new Components() - public lock: any - - constructor () { - this.lock = mortice({ - name: 'peer-store', - singleProcess: true - }) - } - - init (components: Components) { - this.components = components - } - - _peerIdToDatastoreKey (peerId: PeerId) { - if (peerId.type == null) { - log.error('peerId must be an instance of peer-id to store data') - throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS) - } - - const b32key = peerId.toCID().toString() - return new Key(`${NAMESPACE_COMMON}${b32key}`) - } - - async has (peerId: PeerId) { - return await this.components.getDatastore().has(this._peerIdToDatastoreKey(peerId)) - } - - async delete (peerId: PeerId) { - await this.components.getDatastore().delete(this._peerIdToDatastoreKey(peerId)) - } - - async load (peerId: PeerId): Promise { - const buf = await this.components.getDatastore().get(this._peerIdToDatastoreKey(peerId)) - const peer = PeerPB.decode(buf) - const metadata = new Map() - - for (const meta of peer.metadata) { - metadata.set(meta.key, meta.value) - } - - return { - ...peer, - id: peerId, - addresses: peer.addresses.map(({ multiaddr, isCertified }) => { - return { - multiaddr: new Multiaddr(multiaddr), - isCertified: isCertified ?? false - } - }), - metadata, - pubKey: peer.pubKey ?? undefined, - peerRecordEnvelope: peer.peerRecordEnvelope ?? undefined - } - } - - async save (peer: Peer) { - if (peer.pubKey != null && peer.id.publicKey != null && !uint8arrayEquals(peer.pubKey, peer.id.publicKey)) { - log.error('peer publicKey bytes do not match peer id publicKey bytes') - throw errcode(new Error('publicKey bytes do not match peer id publicKey bytes'), codes.ERR_INVALID_PARAMETERS) - } - - // dedupe addresses - const addressSet = new Set() - const addresses = peer.addresses - .filter(address => { - if (addressSet.has(address.multiaddr.toString())) { - return false - } - - addressSet.add(address.multiaddr.toString()) - return true - }) - .sort((a, b) => { - return a.multiaddr.toString().localeCompare(b.multiaddr.toString()) - }) - .map(({ multiaddr, isCertified }) => ({ - multiaddr: multiaddr.bytes, - isCertified - })) - - const metadata: Metadata[] = [] - - ;[...peer.metadata.keys()].sort().forEach(key => { - const value = peer.metadata.get(key) - - if (value != null) { - metadata.push({ key, value }) - } - }) - - const buf = PeerPB.encode({ - addresses, - protocols: peer.protocols.sort(), - pubKey: peer.pubKey, - metadata, - peerRecordEnvelope: peer.peerRecordEnvelope - }) - - await this.components.getDatastore().put(this._peerIdToDatastoreKey(peer.id), buf) - - return await this.load(peer.id) - } - - async patch (peerId: PeerId, data: Partial) { - const peer = await this.load(peerId) - - return await this._patch(peerId, data, peer) - } - - async patchOrCreate (peerId: PeerId, data: Partial) { - let peer: Peer - - try { - peer = await this.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - - peer = { id: peerId, addresses: [], protocols: [], metadata: new Map() } - } - - return await this._patch(peerId, data, peer) - } - - async _patch (peerId: PeerId, data: Partial, peer: Peer) { - return await this.save({ - ...peer, - ...data, - id: peerId - }) - } - - async merge (peerId: PeerId, data: Partial) { - const peer = await this.load(peerId) - - return await this._merge(peerId, data, peer) - } - - async mergeOrCreate (peerId: PeerId, data: Partial) { - /** @type {Peer} */ - let peer - - try { - peer = await this.load(peerId) - } catch (err: any) { - if (err.code !== codes.ERR_NOT_FOUND) { - throw err - } - - peer = { id: peerId, addresses: [], protocols: [], metadata: new Map() } - } - - return await this._merge(peerId, data, peer) - } - - async _merge (peerId: PeerId, data: Partial, peer: Peer) { - // if the peer has certified addresses, use those in - // favour of the supplied versions - const addresses = new Map() - - peer.addresses.forEach((addr) => { - addresses.set(addr.multiaddr.toString(), addr.isCertified) - }) - - ;(data.addresses ?? []).forEach(addr => { - const addrString = addr.multiaddr.toString() - const isAlreadyCertified = Boolean(addresses.get(addrString)) - - const isCertified = isAlreadyCertified || addr.isCertified - - addresses.set(addrString, isCertified) - }) - - return await this.save({ - id: peerId, - addresses: Array.from(addresses.entries()).map(([addrStr, isCertified]) => { - return { - multiaddr: new Multiaddr(addrStr), - isCertified - } - }), - protocols: Array.from(new Set([ - ...(peer.protocols ?? []), - ...(data.protocols ?? []) - ])), - metadata: new Map([ - ...(peer.metadata?.entries() ?? []), - ...(data.metadata?.entries() ?? []) - ]), - pubKey: data.pubKey ?? (peer != null ? peer.pubKey : undefined), - peerRecordEnvelope: data.peerRecordEnvelope ?? (peer != null ? peer.peerRecordEnvelope : undefined) - }) - } - - async * all () { - for await (const key of this.components.getDatastore().queryKeys({ - prefix: NAMESPACE_COMMON - })) { - // /peers/${peer-id-as-libp2p-key-cid-string-in-base-32} - const base32Str = key.toString().split('/')[2] - const buf = base32.decode(base32Str) - - yield this.load(peerIdFromBytes(buf)) - } - } -} diff --git a/packages/libp2p-peer-store/test/address-book.spec.ts b/packages/libp2p-peer-store/test/address-book.spec.ts deleted file mode 100644 index f170bc0cb..000000000 --- a/packages/libp2p-peer-store/test/address-book.spec.ts +++ /dev/null @@ -1,670 +0,0 @@ -/* eslint-env mocha */ -/* eslint max-nested-callbacks: ["error", 6] */ - -import { expect } from 'aegir/chai' -import { Multiaddr } from '@multiformats/multiaddr' -import { arrayEquals } from '@libp2p/utils/array-equals' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import pDefer from 'p-defer' -import { MemoryDatastore } from 'datastore-core/memory' -import { PersistentPeerStore } from '../src/index.js' -import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record' -import { codes } from '../src/errors.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import type { AddressBook } from '@libp2p/interfaces/peer-store' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { Components } from '@libp2p/interfaces/components' - -const addr1 = new Multiaddr('/ip4/127.0.0.1/tcp/8000') -const addr2 = new Multiaddr('/ip4/20.0.0.1/tcp/8001') -const addr3 = new Multiaddr('/ip4/127.0.0.1/tcp/8002') - -describe('addressBook', () => { - let peerId: PeerId - - before(async () => { - peerId = await createEd25519PeerId() - }) - - describe('addressBook.set', () => { - let peerStore: PersistentPeerStore - let ab: AddressBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - ab = peerStore.addressBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await ab.set('invalid peerId') - } catch (err: any) { - expect(err).to.have.property('code', codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('throws invalid parameters error if no addresses provided', async () => { - try { - // @ts-expect-error invalid input - await ab.set(peerId) - } catch (err: any) { - expect(err).to.have.property('code', codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('no addresses should throw error') - }) - - it('throws invalid parameters error if invalid multiaddrs are provided', async () => { - try { - // @ts-expect-error invalid input - await ab.set(peerId, ['invalid multiaddr']) - } catch (err: any) { - expect(err).to.have.property('code', codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid multiaddrs should throw error') - }) - - it('replaces the stored content by default and emit change event', async () => { - const defer = pDefer() - const supportedMultiaddrs = [addr1, addr2] - - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId, multiaddrs } = evt.detail - expect(peerId).to.exist() - expect(multiaddrs).to.eql(supportedMultiaddrs) - defer.resolve() - }, { - once: true - }) - - await ab.set(peerId, supportedMultiaddrs) - const addresses = await ab.get(peerId) - const multiaddrs = addresses.map((mi) => mi.multiaddr) - expect(multiaddrs).to.have.deep.members(supportedMultiaddrs) - - return await defer.promise - }) - - it('emits on set if not storing the exact same content', async () => { - const defer = pDefer() - - const supportedMultiaddrsA = [addr1, addr2] - const supportedMultiaddrsB = [addr2] - - let changeCounter = 0 - peerStore.addEventListener('change:multiaddrs', () => { - changeCounter++ - if (changeCounter > 1) { - defer.resolve() - } - }) - - // set 1 - await ab.set(peerId, supportedMultiaddrsA) - - // set 2 (same content) - await ab.set(peerId, supportedMultiaddrsB) - const addresses = await ab.get(peerId) - const multiaddrs = addresses.map((mi) => mi.multiaddr) - expect(multiaddrs).to.have.deep.members(supportedMultiaddrsB) - - await defer.promise - }) - - it('does not emit on set if it is storing the exact same content', async () => { - const defer = pDefer() - - const supportedMultiaddrs = [addr1, addr2] - - let changeCounter = 0 - peerStore.addEventListener('change:multiaddrs', () => { - changeCounter++ - if (changeCounter > 1) { - defer.reject() - } - }) - - // set 1 - await ab.set(peerId, supportedMultiaddrs) - - // set 2 (same content) - await ab.set(peerId, supportedMultiaddrs) - - // Wait 50ms for incorrect second event - setTimeout(() => { - defer.resolve() - }, 50) - - await defer.promise - }) - }) - - describe('addressBook.add', () => { - let peerStore: PersistentPeerStore - let ab: AddressBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - ab = peerStore.addressBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await ab.add('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('throws invalid parameters error if no addresses provided', async () => { - try { - // @ts-expect-error invalid input - await ab.add(peerId) - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('no addresses provided should throw error') - }) - - it('throws invalid parameters error if invalid multiaddrs are provided', async () => { - try { - // @ts-expect-error invalid input - await ab.add(peerId, ['invalid multiaddr']) - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid multiaddr should throw error') - }) - - it('does not emit event if no addresses are added', async () => { - const defer = pDefer() - - peerStore.addEventListener('peer', () => { - defer.reject() - }) - - await ab.add(peerId, []) - - // Wait 50ms for incorrect second event - setTimeout(() => { - defer.resolve() - }, 50) - - await defer.promise - }) - - it('adds the new content and emits change event', async () => { - const defer = pDefer() - - const supportedMultiaddrsA = [addr1, addr2] - const supportedMultiaddrsB = [addr3] - const finalMultiaddrs = supportedMultiaddrsA.concat(supportedMultiaddrsB) - - let changeTrigger = 2 - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { multiaddrs } = evt.detail - changeTrigger-- - if (changeTrigger === 0 && arrayEquals(multiaddrs, finalMultiaddrs)) { - defer.resolve() - } - }) - - // Replace - await ab.set(peerId, supportedMultiaddrsA) - let addresses = await ab.get(peerId) - let multiaddrs = addresses.map((mi) => mi.multiaddr) - expect(multiaddrs).to.have.deep.members(supportedMultiaddrsA) - - // Add - await ab.add(peerId, supportedMultiaddrsB) - addresses = await ab.get(peerId) - multiaddrs = addresses.map((mi) => mi.multiaddr) - expect(multiaddrs).to.have.deep.members(finalMultiaddrs) - - return await defer.promise - }) - - it('emits on add if the content to add not exists', async () => { - const defer = pDefer() - - const supportedMultiaddrsA = [addr1] - const supportedMultiaddrsB = [addr2] - const finalMultiaddrs = supportedMultiaddrsA.concat(supportedMultiaddrsB) - - let changeCounter = 0 - peerStore.addEventListener('change:multiaddrs', () => { - changeCounter++ - if (changeCounter > 1) { - defer.resolve() - } - }) - - // set 1 - await ab.set(peerId, supportedMultiaddrsA) - - // set 2 (content already existing) - await ab.add(peerId, supportedMultiaddrsB) - const addresses = await ab.get(peerId) - const multiaddrs = addresses.map((mi) => mi.multiaddr) - expect(multiaddrs).to.have.deep.members(finalMultiaddrs) - - await defer.promise - }) - - it('does not emit on add if the content to add already exists', async () => { - const defer = pDefer() - - const supportedMultiaddrsA = [addr1, addr2] - const supportedMultiaddrsB = [addr2] - - let changeCounter = 0 - peerStore.addEventListener('change:multiaddrs', () => { - changeCounter++ - if (changeCounter > 1) { - defer.reject() - } - }) - - // set 1 - await ab.set(peerId, supportedMultiaddrsA) - - // set 2 (content already existing) - await ab.add(peerId, supportedMultiaddrsB) - - // Wait 50ms for incorrect second event - setTimeout(() => { - defer.resolve() - }, 50) - - await defer.promise - }) - - it('does not add replicated content', async () => { - // set 1 - await ab.set(peerId, [addr1, addr1]) - - const addresses = await ab.get(peerId) - expect(addresses).to.have.lengthOf(1) - }) - }) - - describe('addressBook.get', () => { - let peerStore: PersistentPeerStore - let ab: AddressBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - ab = peerStore.addressBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await ab.get('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('returns empty if no multiaddrs are known for the provided peer', async () => { - const addresses = await ab.get(peerId) - - expect(addresses).to.be.empty() - }) - - it('returns the multiaddrs stored', async () => { - const supportedMultiaddrs = [addr1, addr2] - - await ab.set(peerId, supportedMultiaddrs) - - const addresses = await ab.get(peerId) - const multiaddrs = addresses.map((mi) => mi.multiaddr) - expect(multiaddrs).to.have.deep.members(supportedMultiaddrs) - }) - }) - - describe('addressBook.delete', () => { - let peerStore: PersistentPeerStore - let ab: AddressBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - ab = peerStore.addressBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await ab.delete('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('does not emit an event if no records exist for the peer', async () => { - const defer = pDefer() - - peerStore.addEventListener('change:multiaddrs', () => { - defer.reject() - }) - - await ab.delete(peerId) - - // Wait 50ms for incorrect invalid event - setTimeout(() => { - defer.resolve() - }, 50) - - return await defer.promise - }) - - it('emits an event if the record exists', async () => { - const defer = pDefer() - - const supportedMultiaddrs = [addr1, addr2] - await ab.set(peerId, supportedMultiaddrs) - - // Listen after set - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { multiaddrs } = evt.detail - expect(multiaddrs.length).to.eql(0) - defer.resolve() - }) - - await ab.delete(peerId) - - return await defer.promise - }) - }) - - describe('certified records', () => { - let peerStore: PersistentPeerStore - let ab: AddressBook - - describe('consumes a valid peer record and stores its data', () => { - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - ab = peerStore.addressBook - }) - - it('no previous data in AddressBook', async () => { - const multiaddrs = [addr1, addr2] - const peerRecord = new PeerRecord({ - peerId, - multiaddrs - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - // consume peer record - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(true) - - // Validate AddressBook addresses - const addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(multiaddrs.length) - addrs.forEach((addr, index) => { - expect(addr.isCertified).to.eql(true) - expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true) - }) - }) - - it('emits change:multiaddrs event when adding multiaddrs', async () => { - const defer = pDefer() - const multiaddrs = [addr1, addr2] - const peerRecord = new PeerRecord({ - peerId, - multiaddrs - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId, multiaddrs } = evt.detail - expect(peerId).to.exist() - expect(multiaddrs).to.eql(multiaddrs) - defer.resolve() - }, { - once: true - }) - - // consume peer record - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(true) - - return await defer.promise - }) - - it('emits change:multiaddrs event with same data currently in AddressBook (not certified)', async () => { - const defer = pDefer() - const multiaddrs = [addr1, addr2] - - // Set addressBook data - await ab.set(peerId, multiaddrs) - - // Validate data exists, but not certified - let addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(multiaddrs.length) - - addrs.forEach((addr, index) => { - expect(addr.isCertified).to.eql(false) - expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true) - }) - - // Create peer record - const peerRecord = new PeerRecord({ - peerId, - multiaddrs - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId, multiaddrs } = evt.detail - expect(peerId).to.exist() - expect(multiaddrs).to.eql(multiaddrs) - defer.resolve() - }, { - once: true - }) - - // consume peer record - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(true) - - // Wait event - await defer.promise - - // Validate data exists and certified - addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(multiaddrs.length) - addrs.forEach((addr, index) => { - expect(addr.isCertified).to.eql(true) - expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true) - }) - }) - - it('emits change:multiaddrs event with previous partial data in AddressBook (not certified)', async () => { - const defer = pDefer() - const multiaddrs = [addr1, addr2] - - // Set addressBook data - await ab.set(peerId, [addr1]) - - // Validate data exists, but not certified - let addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(1) - expect(addrs[0].isCertified).to.eql(false) - expect(addrs[0].multiaddr.equals(addr1)).to.eql(true) - - // Create peer record - const peerRecord = new PeerRecord({ - peerId, - multiaddrs - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId, multiaddrs } = evt.detail - expect(peerId).to.exist() - expect(multiaddrs).to.eql(multiaddrs) - defer.resolve() - }, { - once: true - }) - - // consume peer record - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(true) - - // Wait event - await defer.promise - - // Validate data exists and certified - addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(multiaddrs.length) - addrs.forEach((addr, index) => { - expect(addr.isCertified).to.eql(true) - expect(multiaddrs[index].equals(addr.multiaddr)).to.eql(true) - }) - }) - - it('with previous different data in AddressBook (not certified)', async () => { - const defer = pDefer() - const multiaddrsUncertified = [addr3] - const multiaddrsCertified = [addr1, addr2] - - // Set addressBook data - await ab.set(peerId, multiaddrsUncertified) - - // Validate data exists, but not certified - let addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(multiaddrsUncertified.length) - addrs.forEach((addr, index) => { - expect(addr.isCertified).to.eql(false) - expect(multiaddrsUncertified[index].equals(addr.multiaddr)).to.eql(true) - }) - - // Create peer record - const peerRecord = new PeerRecord({ - peerId, - multiaddrs: multiaddrsCertified - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - peerStore.addEventListener('change:multiaddrs', (evt) => { - const { peerId, multiaddrs } = evt.detail - expect(peerId).to.exist() - expect(multiaddrs).to.eql(multiaddrs) - defer.resolve() - }, { - once: true - }) - - // consume peer record - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(true) - - // Wait event - await defer.promise - - // Validate data exists and certified - addrs = await ab.get(peerId) - expect(addrs).to.exist() - expect(addrs).to.have.lengthOf(multiaddrsCertified.length) - addrs.forEach((addr, index) => { - expect(addr.isCertified).to.eql(true) - expect(multiaddrsCertified[index].equals(addr.multiaddr)).to.eql(true) - }) - }) - }) - - describe('fails to consume invalid peer records', () => { - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - ab = peerStore.addressBook - }) - - it('invalid peer record', async () => { - const invalidEnvelope = { - payload: uint8ArrayFromString('invalid-peerRecord') - } - - // @ts-expect-error invalid input - const consumed = await ab.consumePeerRecord(invalidEnvelope) - expect(consumed).to.eql(false) - }) - - it('peer that created the envelope is not the same as the peer record', async () => { - const multiaddrs = [addr1, addr2] - - // Create peer record - const peerId2 = await createEd25519PeerId() - const peerRecord = new PeerRecord({ - peerId: peerId2, - multiaddrs - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(false) - }) - - it('does not store an outdated record', async () => { - const multiaddrs = [addr1, addr2] - const peerRecord1 = new PeerRecord({ - peerId, - multiaddrs, - seqNumber: BigInt(Date.now()) - }) - const peerRecord2 = new PeerRecord({ - peerId, - multiaddrs, - seqNumber: BigInt(Date.now() - 1) - }) - const envelope1 = await RecordEnvelope.seal(peerRecord1, peerId) - const envelope2 = await RecordEnvelope.seal(peerRecord2, peerId) - - // Consume envelope1 (bigger seqNumber) - let consumed = await ab.consumePeerRecord(envelope1) - expect(consumed).to.eql(true) - - consumed = await ab.consumePeerRecord(envelope2) - expect(consumed).to.eql(false) - }) - - it('empty multiaddrs', async () => { - const peerRecord = new PeerRecord({ - peerId, - multiaddrs: [] - }) - const envelope = await RecordEnvelope.seal(peerRecord, peerId) - - const consumed = await ab.consumePeerRecord(envelope) - expect(consumed).to.eql(false) - }) - }) - }) -}) diff --git a/packages/libp2p-peer-store/test/key-book.spec.ts b/packages/libp2p-peer-store/test/key-book.spec.ts deleted file mode 100644 index 3bde0f36b..000000000 --- a/packages/libp2p-peer-store/test/key-book.spec.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import { MemoryDatastore } from 'datastore-core/memory' -import { PersistentPeerStore } from '../src/index.js' -import pDefer from 'p-defer' -import { codes } from '../src/errors.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { KeyBook } from '@libp2p/interfaces/peer-store' -import { Components } from '@libp2p/interfaces/components' - -describe('keyBook', () => { - let peerId: PeerId - let peerStore: PersistentPeerStore - let kb: KeyBook - let datastore: MemoryDatastore - - beforeEach(async () => { - peerId = await createEd25519PeerId() - datastore = new MemoryDatastore() - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore })) - kb = peerStore.keyBook - }) - - it('throws invalid parameters error if invalid PeerId is provided in set', async () => { - try { - // @ts-expect-error invalid input - await kb.set('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('throws invalid parameters error if invalid PeerId is provided in get', async () => { - try { - // @ts-expect-error invalid input - await kb.get('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('stores the peerId in the book and returns the public key', async () => { - if (peerId.publicKey == null) { - throw new Error('Public key was missing') - } - - // Set PeerId - await kb.set(peerId, peerId.publicKey) - - // Get public key - const pubKey = await kb.get(peerId) - expect(peerId.publicKey).to.equalBytes(pubKey) - }) - - it('should not store if already stored', async () => { - const spy = sinon.spy(datastore, 'put') - const peer = await createEd25519PeerId() - - if (peer.publicKey == null) { - throw new Error('Public key was missing') - } - - // Set PeerId - await kb.set(peer, peer.publicKey) - await kb.set(peer, peer.publicKey) - - expect(spy).to.have.property('callCount', 1) - }) - - it('should emit an event when setting a key', async () => { - const defer = pDefer() - - peerStore.addEventListener('change:pubkey', (evt) => { - const { peerId: id, publicKey } = evt.detail - if (peerId.publicKey == null) { - throw new Error('Public key was missing') - } - - expect(id.toString()).to.equal(peerId.toString()) - expect(publicKey).to.equalBytes(peerId.publicKey) - defer.resolve() - }) - - if (peerId.publicKey == null) { - throw new Error('Public key was missing') - } - - // Set PeerId - await kb.set(peerId, peerId.publicKey) - await defer.promise - }) - - it('should not set when key does not match', async () => { - const edKey = await createEd25519PeerId() - - if (peerId.publicKey == null) { - throw new Error('Public key was missing') - } - - // Set PeerId - await expect(kb.set(edKey, peerId.publicKey)).to.eventually.be.rejectedWith(/bytes do not match/) - }) - - it('should emit an event when deleting a key', async () => { - const defer = pDefer() - - if (peerId.publicKey == null) { - throw new Error('Public key was missing') - } - - await kb.set(peerId, peerId.publicKey) - - peerStore.addEventListener('change:pubkey', (evt) => { - const { peerId: id, publicKey } = evt.detail - expect(id.toString()).to.equal(peerId.toString()) - expect(publicKey).to.be.undefined() - defer.resolve() - }) - - await kb.delete(peerId) - await defer.promise - }) -}) diff --git a/packages/libp2p-peer-store/test/metadata-book.spec.ts b/packages/libp2p-peer-store/test/metadata-book.spec.ts deleted file mode 100644 index cf760297a..000000000 --- a/packages/libp2p-peer-store/test/metadata-book.spec.ts +++ /dev/null @@ -1,364 +0,0 @@ - -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { MemoryDatastore } from 'datastore-core/memory' -import pDefer from 'p-defer' -import { PersistentPeerStore } from '../src/index.js' -import { codes } from '../src/errors.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { MetadataBook } from '@libp2p/interfaces/peer-store' -import { Components } from '@libp2p/interfaces/components' - -describe('metadataBook', () => { - let peerId: PeerId - - before(async () => { - peerId = await createEd25519PeerId() - }) - - describe('metadataBook.set', () => { - let peerStore: PersistentPeerStore - let mb: MetadataBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - mb = peerStore.metadataBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await mb.set('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('throws invalid parameters error if no metadata provided', async () => { - try { - // @ts-expect-error invalid input - await mb.set(peerId) - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('no key provided should throw error') - }) - - it('throws invalid parameters error if no value provided', async () => { - try { - // @ts-expect-error invalid input - await mb.setValue(peerId, 'location') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('no value provided should throw error') - }) - - it('throws invalid parameters error if value is not a buffer', async () => { - try { - // @ts-expect-error invalid input - await mb.setValue(peerId, 'location', 'mars') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid value provided should throw error') - }) - - it('stores the content and emit change event', async () => { - const defer = pDefer() - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('mars') - - peerStore.addEventListener('change:metadata', (evt) => { - const { peerId, metadata } = evt.detail - expect(peerId).to.exist() - expect(metadata.get(metadataKey)).to.equalBytes(metadataValue) - defer.resolve() - }, { - once: true - }) - - await mb.setValue(peerId, metadataKey, metadataValue) - - const value = await mb.getValue(peerId, metadataKey) - expect(value).to.equalBytes(metadataValue) - - const peerMetadata = await mb.get(peerId) - expect(peerMetadata).to.exist() - expect(peerMetadata.get(metadataKey)).to.equalBytes(metadataValue) - - return await defer.promise - }) - - it('emits on set if not storing the exact same content', async () => { - const defer = pDefer() - const metadataKey = 'location' - const metadataValue1 = uint8ArrayFromString('mars') - const metadataValue2 = uint8ArrayFromString('saturn') - - let changeCounter = 0 - peerStore.addEventListener('change:metadata', () => { - changeCounter++ - if (changeCounter > 1) { - defer.resolve() - } - }) - - // set 1 - await mb.setValue(peerId, metadataKey, metadataValue1) - - // set 2 (same content) - await mb.setValue(peerId, metadataKey, metadataValue2) - - const value = await mb.getValue(peerId, metadataKey) - expect(value).to.equalBytes(metadataValue2) - - const peerMetadata = await mb.get(peerId) - expect(peerMetadata).to.exist() - expect(peerMetadata.get(metadataKey)).to.equalBytes(metadataValue2) - - return await defer.promise - }) - - it('does not emit on set if it is storing the exact same content', async () => { - const defer = pDefer() - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('mars') - - let changeCounter = 0 - peerStore.addEventListener('change:metadata', () => { - changeCounter++ - if (changeCounter > 1) { - defer.reject() - } - }) - - // set 1 - await mb.setValue(peerId, metadataKey, metadataValue) - - // set 2 (same content) - await mb.setValue(peerId, metadataKey, metadataValue) - - // Wait 50ms for incorrect second event - setTimeout(() => { - defer.resolve() - }, 50) - - return await defer.promise - }) - }) - - describe('metadataBook.get', () => { - let peerStore: PersistentPeerStore - let mb: MetadataBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - mb = peerStore.metadataBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await mb.get('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('returns empty if no metadata is known for the provided peer', async () => { - const metadata = await mb.get(peerId) - - expect(metadata).to.be.empty() - }) - - it('returns the metadata stored', async () => { - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('mars') - const metadata = new Map() - metadata.set(metadataKey, metadataValue) - - await mb.set(peerId, metadata) - - const peerMetadata = await mb.get(peerId) - expect(peerMetadata).to.exist() - expect(peerMetadata.get(metadataKey)).to.equalBytes(metadataValue) - }) - }) - - describe('metadataBook.getValue', () => { - let peerStore: PersistentPeerStore - let mb: MetadataBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - mb = peerStore.metadataBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await mb.getValue('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('returns undefined if no metadata is known for the provided peer', async () => { - const metadataKey = 'location' - const metadata = await mb.getValue(peerId, metadataKey) - - expect(metadata).to.not.exist() - }) - - it('returns the metadata value stored for the given key', async () => { - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('mars') - - await mb.setValue(peerId, metadataKey, metadataValue) - - const value = await mb.getValue(peerId, metadataKey) - expect(value).to.exist() - expect(value).to.equalBytes(metadataValue) - }) - - it('returns undefined if no metadata is known for the provided peer and key', async () => { - const metadataKey = 'location' - const metadataBadKey = 'nickname' - const metadataValue = uint8ArrayFromString('mars') - - await mb.setValue(peerId, metadataKey, metadataValue) - - const metadata = await mb.getValue(peerId, metadataBadKey) - expect(metadata).to.not.exist() - }) - }) - - describe('metadataBook.delete', () => { - let peerStore: PersistentPeerStore - let mb: MetadataBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - mb = peerStore.metadataBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await mb.delete('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('should not emit event if no records exist for the peer', async () => { - const defer = pDefer() - - peerStore.addEventListener('change:metadata', () => { - defer.reject() - }) - - await mb.delete(peerId) - - // Wait 50ms for incorrect invalid event - setTimeout(() => { - defer.resolve() - }, 50) - - return await defer.promise - }) - - it('should emit an event if the record exists for the peer', async () => { - const defer = pDefer() - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('mars') - - await mb.setValue(peerId, metadataKey, metadataValue) - - // Listen after set - peerStore.addEventListener('change:metadata', () => { - defer.resolve() - }) - - await mb.delete(peerId) - - return await defer.promise - }) - }) - - describe('metadataBook.deleteValue', () => { - let peerStore: PersistentPeerStore - let mb: MetadataBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - mb = peerStore.metadataBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - try { - // @ts-expect-error invalid input - await mb.deleteValue('invalid peerId') - } catch (err: any) { - expect(err.code).to.equal(codes.ERR_INVALID_PARAMETERS) - return - } - throw new Error('invalid peerId should throw error') - }) - - it('should not emit event if no records exist for the peer', async () => { - const defer = pDefer() - const metadataKey = 'location' - - peerStore.addEventListener('change:metadata', () => { - defer.reject() - }) - - await mb.deleteValue(peerId, metadataKey) - - // Wait 50ms for incorrect invalid event - setTimeout(() => { - defer.resolve() - }, 50) - - return await defer.promise - }) - - it('should emit event if a record exists for the peer', async () => { - const defer = pDefer() - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('mars') - - await mb.setValue(peerId, metadataKey, metadataValue) - - // Listen after set - peerStore.addEventListener('change:metadata', () => { - defer.resolve() - }) - - await mb.deleteValue(peerId, metadataKey) - - return await defer.promise - }) - }) -}) diff --git a/packages/libp2p-peer-store/test/peer-store.spec.ts b/packages/libp2p-peer-store/test/peer-store.spec.ts deleted file mode 100644 index 144e998d9..000000000 --- a/packages/libp2p-peer-store/test/peer-store.spec.ts +++ /dev/null @@ -1,217 +0,0 @@ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import { PersistentPeerStore } from '../src/index.js' -import { Multiaddr } from '@multiformats/multiaddr' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { MemoryDatastore } from 'datastore-core/memory' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { Components } from '@libp2p/interfaces/components' - -const addr1 = new Multiaddr('/ip4/127.0.0.1/tcp/8000') -const addr2 = new Multiaddr('/ip4/127.0.0.1/tcp/8001') -const addr3 = new Multiaddr('/ip4/127.0.0.1/tcp/8002') -const addr4 = new Multiaddr('/ip4/127.0.0.1/tcp/8003') - -const proto1 = '/protocol1' -const proto2 = '/protocol2' -const proto3 = '/protocol3' - -describe('peer-store', () => { - let peerIds: PeerId[] - before(async () => { - peerIds = await Promise.all([ - createEd25519PeerId(), - createEd25519PeerId(), - createEd25519PeerId(), - createEd25519PeerId(), - createEd25519PeerId() - ]) - }) - - describe('empty books', () => { - let peerStore: PersistentPeerStore - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId: peerIds[4], datastore: new MemoryDatastore() })) - }) - - it('has an empty map of peers', async () => { - const peers = await peerStore.all() - expect(peers.length).to.equal(0) - }) - - it('deletes a peerId', async () => { - await peerStore.addressBook.set(peerIds[0], [new Multiaddr('/ip4/127.0.0.1/tcp/4001')]) - await expect(peerStore.has(peerIds[0])).to.eventually.be.true() - await peerStore.delete(peerIds[0]) - await expect(peerStore.has(peerIds[0])).to.eventually.be.false() - }) - - it('sets the peer\'s public key to the KeyBook', async () => { - if (peerIds[0].publicKey == null) { - throw new Error('Public key was missing') - } - - await peerStore.keyBook.set(peerIds[0], peerIds[0].publicKey) - await expect(peerStore.keyBook.get(peerIds[0])).to.eventually.deep.equal(peerIds[0].publicKey) - }) - }) - - describe('previously populated books', () => { - let peerStore: PersistentPeerStore - - beforeEach(async () => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId: peerIds[4], datastore: new MemoryDatastore() })) - - // Add peer0 with { addr1, addr2 } and { proto1 } - await peerStore.addressBook.set(peerIds[0], [addr1, addr2]) - await peerStore.protoBook.set(peerIds[0], [proto1]) - - // Add peer1 with { addr3 } and { proto2, proto3 } - await peerStore.addressBook.set(peerIds[1], [addr3]) - await peerStore.protoBook.set(peerIds[1], [proto2, proto3]) - - // Add peer2 with { addr4 } - await peerStore.addressBook.set(peerIds[2], [addr4]) - - // Add peer3 with { addr4 } and { proto2 } - await peerStore.addressBook.set(peerIds[3], [addr4]) - await peerStore.protoBook.set(peerIds[3], [proto2]) - }) - - it('has peers', async () => { - const peers = await peerStore.all() - - expect(peers.length).to.equal(4) - expect(peers.map(peer => peer.id.toString())).to.have.members([ - peerIds[0].toString(), - peerIds[1].toString(), - peerIds[2].toString(), - peerIds[3].toString() - ]) - }) - - it('deletes a stored peer', async () => { - await peerStore.delete(peerIds[0]) - - const peers = await peerStore.all() - expect(peers.length).to.equal(3) - expect(Array.from(peers.keys())).to.not.have.members([peerIds[0].toString()]) - }) - - it('deletes a stored peer which is only on one book', async () => { - await peerStore.delete(peerIds[2]) - - const peers = await peerStore.all() - expect(peers.length).to.equal(3) - }) - - it('gets the stored information of a peer in all its books', async () => { - const peer = await peerStore.get(peerIds[0]) - expect(peer).to.exist() - expect(peer.protocols).to.have.members([proto1]) - - const peerMultiaddrs = peer.addresses.map((mi) => mi.multiaddr) - expect(peerMultiaddrs).to.have.deep.members([addr1, addr2]) - - expect(peer.id.toString()).to.equal(peerIds[0].toString()) - }) - - it('gets the stored information of a peer that is not present in all its books', async () => { - const peers = await peerStore.get(peerIds[2]) - expect(peers).to.exist() - expect(peers.protocols.length).to.eql(0) - - const peerMultiaddrs = peers.addresses.map((mi) => mi.multiaddr) - expect(peerMultiaddrs).to.have.deep.members([addr4]) - }) - - it('can find all the peers supporting a protocol', async () => { - const peerSupporting2 = [] - - for await (const peer of await peerStore.all()) { - if (peer.protocols.includes(proto2)) { - peerSupporting2.push(peer) - } - } - - expect(peerSupporting2.length).to.eql(2) - expect(peerSupporting2[0].id.toString()).to.eql(peerIds[1].toString()) - expect(peerSupporting2[1].id.toString()).to.eql(peerIds[3].toString()) - }) - - it('can find all the peers listening on a given address', async () => { - const peerListening4 = [] - - for await (const peer of await peerStore.all()) { - const multiaddrs = peer.addresses.map((mi) => mi.multiaddr.toString()) - - if (multiaddrs.includes(addr4.toString())) { - peerListening4.push(peer) - } - } - - expect(peerListening4.length).to.eql(2) - expect(peerListening4[0].id.toString()).to.eql(peerIds[2].toString()) - expect(peerListening4[1].id.toString()).to.eql(peerIds[3].toString()) - }) - }) - - describe('peerStore.getPeers', () => { - let peerStore: PersistentPeerStore - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId: peerIds[4], datastore: new MemoryDatastore() })) - }) - - it('returns peers if only addresses are known', async () => { - await peerStore.addressBook.set(peerIds[0], [addr1]) - - const peers = await peerStore.all() - expect(peers.length).to.equal(1) - - const peerData = peers[0] - expect(peerData).to.exist() - expect(peerData.id).to.exist() - expect(peerData.addresses).to.have.lengthOf(1) - expect(peerData.protocols).to.have.lengthOf(0) - expect(peerData.metadata).to.be.empty() - }) - - it('returns peers if only protocols are known', async () => { - await peerStore.protoBook.set(peerIds[0], [proto1]) - - const peers = await peerStore.all() - expect(peers.length).to.equal(1) - - const peerData = peers[0] - expect(peerData).to.exist() - expect(peerData.id).to.exist() - expect(peerData.addresses).to.have.lengthOf(0) - expect(peerData.protocols).to.have.lengthOf(1) - expect(peerData.metadata).to.be.empty() - }) - - it('returns peers if only metadata is known', async () => { - const metadataKey = 'location' - const metadataValue = uint8ArrayFromString('earth') - await peerStore.metadataBook.setValue(peerIds[0], metadataKey, metadataValue) - - const peers = await peerStore.all() - expect(peers.length).to.equal(1) - - const peerData = peers[0] - expect(peerData).to.exist() - expect(peerData.id).to.exist() - expect(peerData.addresses).to.have.lengthOf(0) - expect(peerData.protocols).to.have.lengthOf(0) - expect(peerData.metadata).to.exist() - expect(peerData.metadata.get(metadataKey)).to.equalBytes(metadataValue) - }) - }) -}) diff --git a/packages/libp2p-peer-store/test/proto-book.spec.ts b/packages/libp2p-peer-store/test/proto-book.spec.ts deleted file mode 100644 index 7177cb272..000000000 --- a/packages/libp2p-peer-store/test/proto-book.spec.ts +++ /dev/null @@ -1,394 +0,0 @@ -/* eslint-env mocha */ - -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import { MemoryDatastore } from 'datastore-core/memory' -import pDefer from 'p-defer' -import pWaitFor from 'p-wait-for' -import { PersistentPeerStore } from '../src/index.js' -import { codes } from '../src/errors.js' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { ProtoBook } from '@libp2p/interfaces/peer-store' -import { Components } from '@libp2p/interfaces/components' - -const arraysAreEqual = (a: string[], b: string[]) => { - if (a.length !== b.length) { - return false - } - - return a.sort().every((item, index) => b[index] === item) -} - -describe('protoBook', () => { - let peerId: PeerId - - before(async () => { - peerId = await createEd25519PeerId() - }) - - describe('protoBook.set', () => { - let peerStore: PersistentPeerStore - let pb: ProtoBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - pb = peerStore.protoBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - // @ts-expect-error invalid input - await expect(pb.set('invalid peerId')).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('throws invalid parameters error if no protocols provided', async () => { - // @ts-expect-error invalid input - await expect(pb.set(peerId)).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('replaces the stored content by default and emit change event', async () => { - const defer = pDefer() - const supportedProtocols = ['protocol1', 'protocol2'] - - peerStore.addEventListener('change:protocols', (evt) => { - const { peerId, protocols } = evt.detail - expect(peerId).to.exist() - expect(protocols).to.have.deep.members(supportedProtocols) - defer.resolve() - }, { - once: true - }) - - await pb.set(peerId, supportedProtocols) - const protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(supportedProtocols) - - await defer.promise - }) - - it('emits on set if not storing the exact same content', async () => { - const defer = pDefer() - - const supportedProtocolsA = ['protocol1', 'protocol2'] - const supportedProtocolsB = ['protocol2'] - - let changeCounter = 0 - peerStore.addEventListener('change:protocols', () => { - changeCounter++ - if (changeCounter > 1) { - defer.resolve() - } - }) - - // set 1 - await pb.set(peerId, supportedProtocolsA) - - // set 2 (same content) - await pb.set(peerId, supportedProtocolsB) - const protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(supportedProtocolsB) - - await defer.promise - }) - - it('does not emit on set if it is storing the exact same content', async () => { - const defer = pDefer() - - const supportedProtocols = ['protocol1', 'protocol2'] - - let changeCounter = 0 - peerStore.addEventListener('change:protocols', () => { - changeCounter++ - if (changeCounter > 1) { - defer.reject() - } - }) - - // set 1 - await pb.set(peerId, supportedProtocols) - - // set 2 (same content) - await pb.set(peerId, supportedProtocols) - - // Wait 50ms for incorrect second event - setTimeout(() => { - defer.resolve() - }, 50) - - return await defer.promise - }) - }) - - describe('protoBook.add', () => { - let peerStore: PersistentPeerStore - let pb: ProtoBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - pb = peerStore.protoBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - // @ts-expect-error invalid input - await expect(pb.add('invalid peerId')).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('throws invalid parameters error if no protocols provided', async () => { - // @ts-expect-error invalid input - await expect(pb.add(peerId)).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('adds the new content and emits change event', async () => { - const defer = pDefer() - - const supportedProtocolsA = ['protocol1', 'protocol2'] - const supportedProtocolsB = ['protocol3'] - const finalProtocols = supportedProtocolsA.concat(supportedProtocolsB) - - let changeTrigger = 2 - peerStore.addEventListener('change:protocols', (evt) => { - const { protocols } = evt.detail - changeTrigger-- - if (changeTrigger === 0 && arraysAreEqual(protocols, finalProtocols)) { - defer.resolve() - } - }) - - // Replace - await pb.set(peerId, supportedProtocolsA) - let protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(supportedProtocolsA) - - // Add - await pb.add(peerId, supportedProtocolsB) - protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(finalProtocols) - - return await defer.promise - }) - - it('emits on add if the content to add not exists', async () => { - const defer = pDefer() - - const supportedProtocolsA = ['protocol1'] - const supportedProtocolsB = ['protocol2'] - const finalProtocols = supportedProtocolsA.concat(supportedProtocolsB) - - let changeCounter = 0 - peerStore.addEventListener('change:protocols', () => { - changeCounter++ - if (changeCounter > 1) { - defer.resolve() - } - }) - - // set 1 - await pb.set(peerId, supportedProtocolsA) - - // set 2 (content already existing) - await pb.add(peerId, supportedProtocolsB) - const protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(finalProtocols) - - return await defer.promise - }) - - it('does not emit on add if the content to add already exists', async () => { - const defer = pDefer() - - const supportedProtocolsA = ['protocol1', 'protocol2'] - const supportedProtocolsB = ['protocol2'] - - let changeCounter = 0 - peerStore.addEventListener('change:protocols', () => { - changeCounter++ - if (changeCounter > 1) { - defer.reject() - } - }) - - // set 1 - await pb.set(peerId, supportedProtocolsA) - - // set 2 (content already existing) - await pb.add(peerId, supportedProtocolsB) - - // Wait 50ms for incorrect second event - setTimeout(() => { - defer.resolve() - }, 50) - - return await defer.promise - }) - }) - - describe('protoBook.remove', () => { - let peerStore: PersistentPeerStore - let pb: ProtoBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - pb = peerStore.protoBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - // @ts-expect-error invalid input - await expect(pb.remove('invalid peerId')).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('throws invalid parameters error if no protocols provided', async () => { - // @ts-expect-error invalid input - await expect(pb.remove(peerId)).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('removes the given protocol and emits change event', async () => { - const spy = sinon.spy() - - const supportedProtocols = ['protocol1', 'protocol2'] - const removedProtocols = ['protocol1'] - const finalProtocols = supportedProtocols.filter(p => !removedProtocols.includes(p)) - - peerStore.addEventListener('change:protocols', spy) - - // Replace - await pb.set(peerId, supportedProtocols) - let protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(supportedProtocols) - - // Remove - await pb.remove(peerId, removedProtocols) - protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(finalProtocols) - - await pWaitFor(() => spy.callCount === 2) - - const [firstCallArgs] = spy.firstCall.args - const [secondCallArgs] = spy.secondCall.args - expect(arraysAreEqual(firstCallArgs.detail.protocols, supportedProtocols)) - expect(arraysAreEqual(secondCallArgs.detail.protocols, finalProtocols)) - }) - - it('emits on remove if the content changes', async () => { - const spy = sinon.spy() - - const supportedProtocols = ['protocol1', 'protocol2'] - const removedProtocols = ['protocol2'] - const finalProtocols = supportedProtocols.filter(p => !removedProtocols.includes(p)) - - peerStore.addEventListener('change:protocols', spy) - - // set - await pb.set(peerId, supportedProtocols) - - // remove (content already existing) - await pb.remove(peerId, removedProtocols) - const protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(finalProtocols) - - return await pWaitFor(() => spy.callCount === 2) - }) - - it('does not emit on remove if the content does not change', async () => { - const spy = sinon.spy() - - const supportedProtocols = ['protocol1', 'protocol2'] - const removedProtocols = ['protocol3'] - - peerStore.addEventListener('change:protocols', spy) - - // set - await pb.set(peerId, supportedProtocols) - - // remove - await pb.remove(peerId, removedProtocols) - - // Only one event - expect(spy.callCount).to.eql(1) - }) - }) - - describe('protoBook.get', () => { - let peerStore: PersistentPeerStore - let pb: ProtoBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - pb = peerStore.protoBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - // @ts-expect-error invalid input - await expect(pb.get('invalid peerId')).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('returns empty if no protocols are known for the provided peer', async () => { - const protocols = await pb.get(peerId) - - expect(protocols).to.be.empty() - }) - - it('returns the protocols stored', async () => { - const supportedProtocols = ['protocol1', 'protocol2'] - - await pb.set(peerId, supportedProtocols) - - const protocols = await pb.get(peerId) - expect(protocols).to.have.deep.members(supportedProtocols) - }) - }) - - describe('protoBook.delete', () => { - let peerStore: PersistentPeerStore - let pb: ProtoBook - - beforeEach(() => { - peerStore = new PersistentPeerStore() - peerStore.init(new Components({ peerId, datastore: new MemoryDatastore() })) - pb = peerStore.protoBook - }) - - it('throws invalid parameters error if invalid PeerId is provided', async () => { - // @ts-expect-error invalid input - await expect(pb.delete('invalid peerId')).to.eventually.be.rejected().with.property('code', codes.ERR_INVALID_PARAMETERS) - }) - - it('should not emit event if no records exist for the peer', async () => { - const defer = pDefer() - - peerStore.addEventListener('change:protocols', () => { - defer.reject() - }) - - await pb.delete(peerId) - - // Wait 50ms for incorrect invalid event - setTimeout(() => { - defer.resolve() - }, 50) - - await defer.promise - }) - - it('should emit event if a record exists for the peer', async () => { - const defer = pDefer() - - const supportedProtocols = ['protocol1', 'protocol2'] - await pb.set(peerId, supportedProtocols) - - // Listen after set - peerStore.addEventListener('change:protocols', (evt) => { - const { protocols } = evt.detail - expect(protocols.length).to.eql(0) - defer.resolve() - }) - - await pb.delete(peerId) - - await defer.promise - }) - }) -}) diff --git a/packages/libp2p-peer-store/tsconfig.json b/packages/libp2p-peer-store/tsconfig.json deleted file mode 100644 index 37bbb88c4..000000000 --- a/packages/libp2p-peer-store/tsconfig.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "extends": "aegir/src/config/tsconfig.aegir.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": [ - "src", - "test" - ], - "exclude": [ - "src/pb/peer.js" - ], - "references": [ - { - "path": "../libp2p-interface-compliance-tests" - }, - { - "path": "../libp2p-interfaces" - }, - { - "path": "../libp2p-logger" - }, - { - "path": "../libp2p-peer-id" - }, - { - "path": "../libp2p-peer-id-factory" - }, - { - "path": "../libp2p-peer-record" - } - ] -} diff --git a/packages/libp2p-pubsub/CHANGELOG.md b/packages/libp2p-pubsub/CHANGELOG.md deleted file mode 100644 index 4d364979e..000000000 --- a/packages/libp2p-pubsub/CHANGELOG.md +++ /dev/null @@ -1,306 +0,0 @@ -## [@libp2p/pubsub-v1.3.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.24...@libp2p/pubsub-v1.3.0) (2022-05-23) - - -### Features - -* expose utility methods to convert bigint to bytes and back ([#213](https://github.com/libp2p/js-libp2p-interfaces/issues/213)) ([3d2e59c](https://github.com/libp2p/js-libp2p-interfaces/commit/3d2e59c8fd8af5d618df904ae9d40518a13de547)) - -## [@libp2p/pubsub-v1.2.24](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.23...@libp2p/pubsub-v1.2.24) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/pubsub-v1.2.23](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.22...@libp2p/pubsub-v1.2.23) (2022-05-10) - - -### Trivial Changes - -* **deps:** bump sinon from 13.0.2 to 14.0.0 ([#211](https://github.com/libp2p/js-libp2p-interfaces/issues/211)) ([8859f70](https://github.com/libp2p/js-libp2p-interfaces/commit/8859f70943c0bcdb210f54a338ae901739e5e6f2)) - -## [@libp2p/pubsub-v1.2.22](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.21...@libp2p/pubsub-v1.2.22) (2022-05-10) - - -### Bug Fixes - -* regenerate protobuf code ([#212](https://github.com/libp2p/js-libp2p-interfaces/issues/212)) ([3cf210e](https://github.com/libp2p/js-libp2p-interfaces/commit/3cf210e230863f8049ac6c3ed2e73abb180fb8b2)) - -## [@libp2p/pubsub-v1.2.21](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.20...@libp2p/pubsub-v1.2.21) (2022-05-04) - - -### Bug Fixes - -* move startable and events interfaces ([#209](https://github.com/libp2p/js-libp2p-interfaces/issues/209)) ([8ce8a08](https://github.com/libp2p/js-libp2p-interfaces/commit/8ce8a08c94b0738aa32da516558977b195ddd8ed)) - -## [@libp2p/pubsub-v1.2.20](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.19...@libp2p/pubsub-v1.2.20) (2022-04-22) - - -### Bug Fixes - -* update pubsub interface in line with gossipsub ([#199](https://github.com/libp2p/js-libp2p-interfaces/issues/199)) ([3f55596](https://github.com/libp2p/js-libp2p-interfaces/commit/3f555965cddea3ef03e7217b755c82aa4107e093)) - -## [@libp2p/pubsub-v1.2.19](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.18...@libp2p/pubsub-v1.2.19) (2022-04-21) - - -### Bug Fixes - -* test PubSub interface and not PubSubBaseProtocol ([#198](https://github.com/libp2p/js-libp2p-interfaces/issues/198)) ([96c15c9](https://github.com/libp2p/js-libp2p-interfaces/commit/96c15c9780821a3cb763e48854d64377bf562692)) - -## [@libp2p/pubsub-v1.2.18](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.17...@libp2p/pubsub-v1.2.18) (2022-04-20) - - -### Bug Fixes - -* emit pubsub messages using 'message' event ([#197](https://github.com/libp2p/js-libp2p-interfaces/issues/197)) ([df9b685](https://github.com/libp2p/js-libp2p-interfaces/commit/df9b685cea30653109f2fa2cb5583a3bca7b09bb)) - -## [@libp2p/pubsub-v1.2.17](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.16...@libp2p/pubsub-v1.2.17) (2022-04-19) - - -### Trivial Changes - -* remove extraneous readme ([#196](https://github.com/libp2p/js-libp2p-interfaces/issues/196)) ([ee1d00c](https://github.com/libp2p/js-libp2p-interfaces/commit/ee1d00cc209909836f12f17d62f1165f11689488)) - -## [@libp2p/pubsub-v1.2.16](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.15...@libp2p/pubsub-v1.2.16) (2022-04-19) - - -### Bug Fixes - -* move dev deps to prod ([#195](https://github.com/libp2p/js-libp2p-interfaces/issues/195)) ([3e1ffc7](https://github.com/libp2p/js-libp2p-interfaces/commit/3e1ffc7b174e74be483943ad4e5fcab823ae3f6d)) - -## [@libp2p/pubsub-v1.2.15](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.14...@libp2p/pubsub-v1.2.15) (2022-04-13) - - -### Bug Fixes - -* add keychain types, fix bigint types ([#193](https://github.com/libp2p/js-libp2p-interfaces/issues/193)) ([9ceadf9](https://github.com/libp2p/js-libp2p-interfaces/commit/9ceadf9d5c42a12d88d74ddd9140e34f7fa63537)) - -## [@libp2p/pubsub-v1.2.14](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.13...@libp2p/pubsub-v1.2.14) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/pubsub-v1.2.13](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.12...@libp2p/pubsub-v1.2.13) (2022-03-24) - - -### Bug Fixes - -* rename peer data to peer info ([#187](https://github.com/libp2p/js-libp2p-interfaces/issues/187)) ([dfea342](https://github.com/libp2p/js-libp2p-interfaces/commit/dfea3429bad57abde040397e4e7a58539829e9c2)) - -## [@libp2p/pubsub-v1.2.12](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.11...@libp2p/pubsub-v1.2.12) (2022-03-21) - - -### Bug Fixes - -* handle empty pubsub messages ([#185](https://github.com/libp2p/js-libp2p-interfaces/issues/185)) ([0db8d84](https://github.com/libp2p/js-libp2p-interfaces/commit/0db8d84dd98ff6e99776c01a6b5bab404033bffa)) - -## [@libp2p/pubsub-v1.2.11](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.10...@libp2p/pubsub-v1.2.11) (2022-03-20) - - -### Bug Fixes - -* update pubsub types ([#183](https://github.com/libp2p/js-libp2p-interfaces/issues/183)) ([7ef4baa](https://github.com/libp2p/js-libp2p-interfaces/commit/7ef4baad0fe30f783f3eecd5199ef92af08b7f57)) - -## [@libp2p/pubsub-v1.2.10](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.9...@libp2p/pubsub-v1.2.10) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/pubsub-v1.2.9](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.8...@libp2p/pubsub-v1.2.9) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/pubsub-v1.2.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.7...@libp2p/pubsub-v1.2.8) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/pubsub-v1.2.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.6...@libp2p/pubsub-v1.2.7) (2022-02-18) - - -### Bug Fixes - -* simpler pubsub ([#172](https://github.com/libp2p/js-libp2p-interfaces/issues/172)) ([98715ed](https://github.com/libp2p/js-libp2p-interfaces/commit/98715ed73183b32e4fda3d878a462389548358d9)) - -## [@libp2p/pubsub-v1.2.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.5...@libp2p/pubsub-v1.2.6) (2022-02-17) - - -### Bug Fixes - -* update deps ([#171](https://github.com/libp2p/js-libp2p-interfaces/issues/171)) ([d0d2564](https://github.com/libp2p/js-libp2p-interfaces/commit/d0d2564a84a0722ab587a3aa6ec01e222442b100)) - -## [@libp2p/pubsub-v1.2.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.4...@libp2p/pubsub-v1.2.5) (2022-02-17) - - -### Bug Fixes - -* add multistream-select and update pubsub types ([#170](https://github.com/libp2p/js-libp2p-interfaces/issues/170)) ([b9ecb2b](https://github.com/libp2p/js-libp2p-interfaces/commit/b9ecb2bee8f2abc0c41bfcf7bf2025894e37ddc2)) - -## [@libp2p/pubsub-v1.2.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.3...@libp2p/pubsub-v1.2.4) (2022-02-12) - - -### Bug Fixes - -* hide implementations behind factory methods ([#167](https://github.com/libp2p/js-libp2p-interfaces/issues/167)) ([2fba080](https://github.com/libp2p/js-libp2p-interfaces/commit/2fba0800c9896af6dcc49da4fa904bb4a3e3e40d)) - -## [@libp2p/pubsub-v1.2.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.2...@libp2p/pubsub-v1.2.3) (2022-02-11) - - -### Bug Fixes - -* simpler topologies ([#164](https://github.com/libp2p/js-libp2p-interfaces/issues/164)) ([45fcaa1](https://github.com/libp2p/js-libp2p-interfaces/commit/45fcaa10a6a3215089340ff2eff117d7fd1100e7)) - -## [@libp2p/pubsub-v1.2.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.1...@libp2p/pubsub-v1.2.2) (2022-02-10) - - -### Bug Fixes - -* make registrar simpler ([#163](https://github.com/libp2p/js-libp2p-interfaces/issues/163)) ([d122f3d](https://github.com/libp2p/js-libp2p-interfaces/commit/d122f3daaccc04039d90814960da92b513265644)) - -## [@libp2p/pubsub-v1.2.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.2.0...@libp2p/pubsub-v1.2.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## [@libp2p/pubsub-v1.2.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.1.0...@libp2p/pubsub-v1.2.0) (2022-02-09) - - -### Features - -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) - -## [@libp2p/pubsub-v1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.0.6...@libp2p/pubsub-v1.1.0) (2022-02-07) - - -### Features - -* add logger package ([#158](https://github.com/libp2p/js-libp2p-interfaces/issues/158)) ([f327cd2](https://github.com/libp2p/js-libp2p-interfaces/commit/f327cd24825d9ce2f45a02fdb9b47c9735c847e0)) - -## [@libp2p/pubsub-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.0.5...@libp2p/pubsub-v1.0.6) (2022-02-05) - - -### Bug Fixes - -* fix muxer tests ([#157](https://github.com/libp2p/js-libp2p-interfaces/issues/157)) ([7233c44](https://github.com/libp2p/js-libp2p-interfaces/commit/7233c4438479dff56a682f45209ef7a938d63857)) - -## [@libp2p/pubsub-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.0.4...@libp2p/pubsub-v1.0.5) (2022-01-15) - - -### Bug Fixes - -* remove abort controller dep ([#151](https://github.com/libp2p/js-libp2p-interfaces/issues/151)) ([518bce1](https://github.com/libp2p/js-libp2p-interfaces/commit/518bce1f9bd1f8b2922338e0c65c9934af7da3af)) - -## [@libp2p/pubsub-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.0.3...@libp2p/pubsub-v1.0.4) (2022-01-15) - - -### Trivial Changes - -* update project config ([#149](https://github.com/libp2p/js-libp2p-interfaces/issues/149)) ([6eb8556](https://github.com/libp2p/js-libp2p-interfaces/commit/6eb85562c0da167d222808da10a7914daf12970b)) - -## [@libp2p/pubsub-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.0.2...@libp2p/pubsub-v1.0.3) (2022-01-14) - - -### Bug Fixes - -* update it-* deps to ts versions ([#148](https://github.com/libp2p/js-libp2p-interfaces/issues/148)) ([7a6fdd7](https://github.com/libp2p/js-libp2p-interfaces/commit/7a6fdd7622ce2870b89dbb849ab421d0dd714b43)) - -## [@libp2p/pubsub-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/pubsub-v1.0.1...@libp2p/pubsub-v1.0.2) (2022-01-08) - - -### Trivial Changes - -* add semantic release config ([#141](https://github.com/libp2p/js-libp2p-interfaces/issues/141)) ([5f0de59](https://github.com/libp2p/js-libp2p-interfaces/commit/5f0de59136b6343d2411abb2d6a4dd2cd0b7efe4)) -* update package versions ([#140](https://github.com/libp2p/js-libp2p-interfaces/issues/140)) ([cd844f6](https://github.com/libp2p/js-libp2p-interfaces/commit/cd844f6e39f4ee50d006e86eac8dadf696900eb5)) - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 0.2.0 (2022-01-04) - - -### chore - -* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) - - -### Features - -* add auto-publish ([7aede5d](https://github.com/libp2p/js-libp2p-interfaces/commit/7aede5df39ea6b5f243348ec9a212b3e33c16a81)) -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) -* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) -* update package names ([#133](https://github.com/libp2p/js-libp2p-interfaces/issues/133)) ([337adc9](https://github.com/libp2p/js-libp2p-interfaces/commit/337adc9a9bc0278bdae8cbce9c57d07a83c8b5c2)) - - -### BREAKING CHANGES - -* requires node 15+ -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out - - - - - -## [0.9.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-pubsub@0.9.0...libp2p-pubsub@0.9.1) (2022-01-02) - -**Note:** Version bump only for package libp2p-pubsub - - - - - -# [0.9.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-pubsub@0.8.0...libp2p-pubsub@0.9.0) (2022-01-02) - - -### Features - -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) - - - - - -# [0.8.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-pubsub@0.7.0...libp2p-pubsub@0.8.0) (2021-12-02) - - -### chore - -* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) - - -### BREAKING CHANGES - -* requires node 15+ - - - - - -# 0.7.0 (2021-11-22) - - -### Features - -* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) - - -### BREAKING CHANGES - -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out diff --git a/packages/libp2p-pubsub/README.md b/packages/libp2p-pubsub/README.md deleted file mode 100644 index 8140010ff..000000000 --- a/packages/libp2p-pubsub/README.md +++ /dev/null @@ -1,35 +0,0 @@ -# libp2p-pubsub - -> Contains an implementation of the [Pubsub](https://github.com/libp2p/js-libp2p-interfaces/blob/master/packages/libp2p-interfaces/src/pubsub/index.ts) interface - -## Table of contents - -- [Usage](#usage) -- [Contribute](#contribute) -- [License](#license) - -## Usage - -```console -npm i libp2p-pubsub -``` - -```javascript -import { PubSubBaseProtocol } from '@libp2p/pubsub' - -class MyPubsubImplementation extends PubSubBaseProtocol { - // .. extra methods here -} -``` - -## Contribute - -The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: - - - Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - - **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - - **Add tests**. There can never be enough tests. - -## License - -[Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) © Protocol Labs diff --git a/packages/libp2p-pubsub/package.json b/packages/libp2p-pubsub/package.json deleted file mode 100644 index f22de1735..000000000 --- a/packages/libp2p-pubsub/package.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "name": "@libp2p/pubsub", - "version": "1.3.0", - "description": "libp2p pubsub base class", - "license": "Apache-2.0 OR MIT", - "homepage": "https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-pubsub#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/libp2p/js-libp2p-interfaces.git" - }, - "bugs": { - "url": "https://github.com/libp2p/js-libp2p-interfaces/issues" - }, - "keywords": [ - "interface", - "libp2p" - ], - "engines": { - "node": ">=16.0.0", - "npm": ">=7.0.0" - }, - "type": "module", - "types": "./dist/src/index.d.ts", - "typesVersions": { - "*": { - "*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ], - "src/*": [ - "*", - "dist/*", - "dist/src/*", - "dist/src/*/index" - ] - } - }, - "files": [ - "src", - "dist/src", - "!dist/test", - "!**/*.tsbuildinfo" - ], - "exports": { - ".": { - "import": "./dist/src/index.js", - "types": "./dist/src/index.d.ts" - }, - "./errors": { - "import": "./dist/src/errors.js", - "types": "./dist/src/errors.d.ts" - }, - "./peer-streams": { - "import": "./dist/src/peer-streams.js", - "types": "./dist/src/peer-streams.d.ts" - }, - "./signature-policy": { - "import": "./dist/src/signature-policy.js", - "types": "./dist/src/signature-policy.d.ts" - }, - "./utils": { - "import": "./dist/src/utils.js", - "types": "./dist/src/utils.d.ts" - } - }, - "eslintConfig": { - "extends": "ipfs", - "parserOptions": { - "sourceType": "module" - }, - "ignorePatterns": [ - "test/message/*.d.ts", - "test/message/*.js" - ] - }, - "release": { - "branches": [ - "master" - ], - "plugins": [ - [ - "@semantic-release/commit-analyzer", - { - "preset": "conventionalcommits", - "releaseRules": [ - { - "breaking": true, - "release": "major" - }, - { - "revert": true, - "release": "patch" - }, - { - "type": "feat", - "release": "minor" - }, - { - "type": "fix", - "release": "patch" - }, - { - "type": "chore", - "release": "patch" - }, - { - "type": "docs", - "release": "patch" - }, - { - "type": "test", - "release": "patch" - }, - { - "scope": "no-release", - "release": false - } - ] - } - ], - [ - "@semantic-release/release-notes-generator", - { - "preset": "conventionalcommits", - "presetConfig": { - "types": [ - { - "type": "feat", - "section": "Features" - }, - { - "type": "fix", - "section": "Bug Fixes" - }, - { - "type": "chore", - "section": "Trivial Changes" - }, - { - "type": "docs", - "section": "Trivial Changes" - }, - { - "type": "test", - "section": "Tests" - } - ] - } - } - ], - "@semantic-release/changelog", - "@semantic-release/npm", - "@semantic-release/github", - "@semantic-release/git" - ] - }, - "scripts": { - "clean": "aegir clean", - "lint": "aegir lint", - "dep-check": "aegir dep-check", - "build": "aegir build", - "generate": "protons test/message/rpc.proto", - "test": "aegir test", - "test:chrome": "aegir test -t browser --cov", - "test:chrome-webworker": "aegir test -t webworker", - "test:firefox": "aegir test -t browser -- --browser firefox", - "test:firefox-webworker": "aegir test -t webworker -- --browser firefox", - "test:node": "aegir test -t node --cov", - "test:electron-main": "aegir test -t electron-main", - "release": "aegir release" - }, - "dependencies": { - "@libp2p/crypto": "^0.22.8", - "@libp2p/interfaces": "^2.0.0", - "@libp2p/logger": "^1.1.0", - "@libp2p/peer-collections": "^1.0.0", - "@libp2p/peer-id": "^1.1.0", - "@libp2p/topology": "^1.1.0", - "@multiformats/multiaddr": "^10.1.5", - "abortable-iterator": "^4.0.2", - "err-code": "^3.0.1", - "iso-random-stream": "^2.0.0", - "it-length-prefixed": "^7.0.1", - "it-pipe": "^2.0.3", - "it-pushable": "^2.0.1", - "multiformats": "^9.6.3", - "p-queue": "^7.2.0", - "uint8arrays": "^3.0.0" - }, - "devDependencies": { - "@libp2p/peer-id-factory": "^1.0.0", - "aegir": "^37.0.7", - "delay": "^5.0.0", - "it-pair": "^2.0.2", - "p-defer": "^4.0.0", - "p-wait-for": "^4.1.0", - "protons": "^3.0.4", - "protons-runtime": "^1.0.4", - "sinon": "^14.0.0", - "util": "^0.12.4" - } -} diff --git a/packages/libp2p-pubsub/src/errors.ts b/packages/libp2p-pubsub/src/errors.ts deleted file mode 100644 index cbdeb51da..000000000 --- a/packages/libp2p-pubsub/src/errors.ts +++ /dev/null @@ -1,53 +0,0 @@ - -export const codes = { - /** - * Signature policy is invalid - */ - ERR_INVALID_SIGNATURE_POLICY: 'ERR_INVALID_SIGNATURE_POLICY', - /** - * Signature policy is unhandled - */ - ERR_UNHANDLED_SIGNATURE_POLICY: 'ERR_UNHANDLED_SIGNATURE_POLICY', - - // Strict signing codes - - /** - * Message expected to have a `signature`, but doesn't - */ - ERR_MISSING_SIGNATURE: 'ERR_MISSING_SIGNATURE', - /** - * Message expected to have a `seqno`, but doesn't - */ - ERR_MISSING_SEQNO: 'ERR_MISSING_SEQNO', - /** - * Message expected to have a `key`, but doesn't - */ - ERR_MISSING_KEY: 'ERR_MISSING_KEY', - /** - * Message `signature` is invalid - */ - ERR_INVALID_SIGNATURE: 'ERR_INVALID_SIGNATURE', - /** - * Message expected to have a `from`, but doesn't - */ - ERR_MISSING_FROM: 'ERR_MISSING_FROM', - - // Strict no-signing codes - - /** - * Message expected to not have a `from`, but does - */ - ERR_UNEXPECTED_FROM: 'ERR_UNEXPECTED_FROM', - /** - * Message expected to not have a `signature`, but does - */ - ERR_UNEXPECTED_SIGNATURE: 'ERR_UNEXPECTED_SIGNATURE', - /** - * Message expected to not have a `key`, but does - */ - ERR_UNEXPECTED_KEY: 'ERR_UNEXPECTED_KEY', - /** - * Message expected to not have a `seqno`, but does - */ - ERR_UNEXPECTED_SEQNO: 'ERR_UNEXPECTED_SEQNO' -} diff --git a/packages/libp2p-pubsub/src/index.ts b/packages/libp2p-pubsub/src/index.ts deleted file mode 100644 index 06d64dcd6..000000000 --- a/packages/libp2p-pubsub/src/index.ts +++ /dev/null @@ -1,686 +0,0 @@ -import { logger } from '@libp2p/logger' -import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events' -import errcode from 'err-code' -import { pipe } from 'it-pipe' -import Queue from 'p-queue' -import { createTopology } from '@libp2p/topology' -import { codes } from './errors.js' -import { PeerStreams as PeerStreamsImpl } from './peer-streams.js' -import { toMessage, ensureArray, randomSeqno, noSignMsgId, msgId, toRpcMessage } from './utils.js' -import { - signMessage, - verifySignature -} from './sign.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { IncomingStreamData } from '@libp2p/interfaces/registrar' -import type { Connection } from '@libp2p/interfaces/connection' -import type { PubSub, Message, StrictNoSign, StrictSign, PubSubInit, PubSubEvents, PeerStreams, PubSubRPCMessage, PubSubRPC, PubSubRPCSubscription, SubscriptionChangeData, PublishResult } from '@libp2p/interfaces/pubsub' -import { PeerMap, PeerSet } from '@libp2p/peer-collections' -import { Components, Initializable } from '@libp2p/interfaces/components' - -const log = logger('libp2p:pubsub') - -export interface TopicValidator { (topic: string, message: Message): Promise } - -/** - * PubSubBaseProtocol handles the peers and connections logic for pubsub routers - * and specifies the API that pubsub routers should have. - */ -export abstract class PubSubBaseProtocol extends EventEmitter implements PubSub, Initializable { - public started: boolean - /** - * Map of topics to which peers are subscribed to - */ - public topics: Map - /** - * List of our subscriptions - */ - public subscriptions: Set - /** - * Map of peer streams - */ - public peers: PeerMap - /** - * The signature policy to follow by default - */ - public globalSignaturePolicy: typeof StrictNoSign | typeof StrictSign - /** - * If router can relay received messages, even if not subscribed - */ - public canRelayMessage: boolean - /** - * if publish should emit to self, if subscribed - */ - public emitSelf: boolean - /** - * Topic validator map - * - * Keyed by topic - * Topic validators are functions with the following input: - */ - public topicValidators: Map - public queue: Queue - public multicodecs: string[] - public components: Components = new Components() - - private _registrarTopologyId: string | undefined - protected enabled: boolean - - constructor (props: PubSubInit) { - super() - - const { - multicodecs = [], - globalSignaturePolicy = 'StrictSign', - canRelayMessage = false, - emitSelf = false, - messageProcessingConcurrency = 10 - } = props - - this.multicodecs = ensureArray(multicodecs) - this.enabled = props.enabled !== false - this.started = false - this.topics = new Map() - this.subscriptions = new Set() - this.peers = new PeerMap() - this.globalSignaturePolicy = globalSignaturePolicy === 'StrictNoSign' ? 'StrictNoSign' : 'StrictSign' - this.canRelayMessage = canRelayMessage - this.emitSelf = emitSelf - this.topicValidators = new Map() - this.queue = new Queue({ concurrency: messageProcessingConcurrency }) - - this._onIncomingStream = this._onIncomingStream.bind(this) - this._onPeerConnected = this._onPeerConnected.bind(this) - this._onPeerDisconnected = this._onPeerDisconnected.bind(this) - } - - init (components: Components) { - this.components = components - } - - // LIFECYCLE METHODS - - /** - * Register the pubsub protocol onto the libp2p node. - * - * @returns {void} - */ - async start () { - if (this.started || !this.enabled) { - return - } - - log('starting') - - // Incoming streams - // Called after a peer dials us - await this.components.getRegistrar().handle(this.multicodecs, this._onIncomingStream) - - // register protocol with topology - // Topology callbacks called on connection manager changes - const topology = createTopology({ - onConnect: this._onPeerConnected, - onDisconnect: this._onPeerDisconnected - }) - this._registrarTopologyId = await this.components.getRegistrar().register(this.multicodecs, topology) - - log('started') - this.started = true - } - - /** - * Unregister the pubsub protocol and the streams with other peers will be closed. - */ - async stop () { - if (!this.started || !this.enabled) { - return - } - - // unregister protocol and handlers - if (this._registrarTopologyId != null) { - this.components.getRegistrar().unregister(this._registrarTopologyId) - } - - await this.components.getRegistrar().unhandle(this.multicodecs) - - log('stopping') - for (const peerStreams of this.peers.values()) { - peerStreams.close() - } - - this.peers.clear() - this.subscriptions = new Set() - this.started = false - log('stopped') - } - - isStarted () { - return this.started - } - - /** - * On an inbound stream opened - */ - protected _onIncomingStream (data: IncomingStreamData) { - const { protocol, stream, connection } = data - const peerId = connection.remotePeer - const peer = this.addPeer(peerId, protocol) - const inboundStream = peer.attachInboundStream(stream) - - this.processMessages(peerId, inboundStream, peer) - .catch(err => log(err)) - } - - /** - * Registrar notifies an established connection with pubsub protocol - */ - protected _onPeerConnected (peerId: PeerId, conn: Connection) { - log('connected %p', peerId) - - void Promise.resolve().then(async () => { - try { - const { stream, protocol } = await conn.newStream(this.multicodecs) - const peer = this.addPeer(peerId, protocol) - await peer.attachOutboundStream(stream) - } catch (err: any) { - log.error(err) - } - - // Immediately send my own subscriptions to the newly established conn - this.send(peerId, { subscriptions: Array.from(this.subscriptions).map(sub => sub.toString()), subscribe: true }) - }) - .catch(err => { - log.error(err) - }) - } - - /** - * Registrar notifies a closing connection with pubsub protocol - */ - protected _onPeerDisconnected (peerId: PeerId, conn?: Connection) { - const idB58Str = peerId.toString() - - log('connection ended', idB58Str) - this._removePeer(peerId) - } - - /** - * Notifies the router that a peer has been connected - */ - addPeer (peerId: PeerId, protocol: string): PeerStreams { - const existing = this.peers.get(peerId) - - // If peer streams already exists, do nothing - if (existing != null) { - return existing - } - - // else create a new peer streams - log('new peer %p', peerId) - - const peerStreams: PeerStreams = new PeerStreamsImpl({ - id: peerId, - protocol - }) - - this.peers.set(peerId, peerStreams) - peerStreams.addEventListener('close', () => this._removePeer(peerId), { - once: true - }) - - return peerStreams - } - - /** - * Notifies the router that a peer has been disconnected - */ - protected _removePeer (peerId: PeerId) { - const peerStreams = this.peers.get(peerId) - if (peerStreams == null) { - return - } - - // close peer streams - peerStreams.close() - - // delete peer streams - log('delete peer %p', peerId) - this.peers.delete(peerId) - - // remove peer from topics map - for (const peers of this.topics.values()) { - peers.delete(peerId) - } - - return peerStreams - } - - // MESSAGE METHODS - - /** - * Responsible for processing each RPC message received by other peers. - */ - async processMessages (peerId: PeerId, stream: AsyncIterable, peerStreams: PeerStreams) { - try { - await pipe( - stream, - async (source) => { - for await (const data of source) { - const rpcMsg = this.decodeRpc(data) - const messages: PubSubRPCMessage[] = [] - - for (const msg of (rpcMsg.messages ?? [])) { - if (msg.from == null || msg.data == null || msg.topic == null) { - log('message from %p was missing from, data or topic fields, dropping', peerId) - continue - } - - messages.push({ - from: msg.from, - data: msg.data, - topic: msg.topic, - sequenceNumber: msg.sequenceNumber ?? undefined, - signature: msg.signature ?? undefined, - key: msg.key ?? undefined - }) - } - - // Since processRpc may be overridden entirely in unsafe ways, - // the simplest/safest option here is to wrap in a function and capture all errors - // to prevent a top-level unhandled exception - // This processing of rpc messages should happen without awaiting full validation/execution of prior messages - this.processRpc(peerId, peerStreams, { - subscriptions: (rpcMsg.subscriptions ?? []).map(sub => ({ - subscribe: Boolean(sub.subscribe), - topic: sub.topic ?? '' - })), - messages - }) - .catch(err => log(err)) - } - } - ) - } catch (err: any) { - this._onPeerDisconnected(peerStreams.id, err) - } - } - - /** - * Handles an rpc request from a peer - */ - async processRpc (from: PeerId, peerStreams: PeerStreams, rpc: PubSubRPC): Promise { - if (!this.acceptFrom(from)) { - log('received message from unacceptable peer %p', from) - return false - } - - log('rpc from %p', from) - - const { subscriptions, messages } = rpc - - if (subscriptions != null && subscriptions.length > 0) { - log('subscription update from %p', from) - - // update peer subscriptions - subscriptions.forEach((subOpt) => { - this.processRpcSubOpt(from, subOpt) - }) - - super.dispatchEvent(new CustomEvent('subscription-change', { - detail: { - peerId: peerStreams.id, - subscriptions: subscriptions.map(({ topic, subscribe }) => ({ - topic: `${topic ?? ''}`, - subscribe: Boolean(subscribe) - })) - } - })) - } - - if (messages != null && messages.length > 0) { - log('messages from %p', from) - - this.queue.addAll(messages.map(message => async () => { - if (message.topic == null || (!this.subscriptions.has(message.topic) && !this.canRelayMessage)) { - log('received message we didn\'t subscribe to. Dropping.') - return false - } - - try { - const msg = await toMessage(message) - - await this.processMessage(from, msg) - } catch (err: any) { - log.error(err) - } - })) - .catch(err => log(err)) - } - - return true - } - - /** - * Handles a subscription change from a peer - */ - processRpcSubOpt (id: PeerId, subOpt: PubSubRPCSubscription) { - const t = subOpt.topic - - if (t == null) { - return - } - - let topicSet = this.topics.get(t) - if (topicSet == null) { - topicSet = new PeerSet() - this.topics.set(t, topicSet) - } - - if (subOpt.subscribe === true) { - // subscribe peer to new topic - topicSet.add(id) - } else { - // unsubscribe from existing topic - topicSet.delete(id) - } - } - - /** - * Handles a message from a peer - */ - async processMessage (from: PeerId, msg: Message) { - if (this.components.getPeerId().equals(from) && !this.emitSelf) { - return - } - - // Ensure the message is valid before processing it - try { - await this.validate(msg) - } catch (err: any) { - log('Message is invalid, dropping it. %O', err) - return - } - - if (this.subscriptions.has(msg.topic)) { - const isFromSelf = this.components.getPeerId().equals(from) - - if (!isFromSelf || this.emitSelf) { - super.dispatchEvent(new CustomEvent('message', { - detail: msg - })) - } - } - - await this.publishMessage(from, msg) - } - - /** - * The default msgID implementation - * Child class can override this. - */ - getMsgId (msg: Message) { - const signaturePolicy = this.globalSignaturePolicy - switch (signaturePolicy) { - case 'StrictSign': - if (msg.sequenceNumber == null) { - throw errcode(new Error('Need seqno when signature policy is StrictSign but it was missing'), codes.ERR_MISSING_SEQNO) - } - - if (msg.key == null) { - throw errcode(new Error('Need key when signature policy is StrictSign but it was missing'), codes.ERR_MISSING_KEY) - } - - return msgId(msg.key, msg.sequenceNumber) - case 'StrictNoSign': - return noSignMsgId(msg.data) - default: - throw errcode(new Error('Cannot get message id: unhandled signature policy'), codes.ERR_UNHANDLED_SIGNATURE_POLICY) - } - } - - /** - * Whether to accept a message from a peer - * Override to create a graylist - */ - acceptFrom (id: PeerId) { - return true - } - - /** - * Decode Uint8Array into an RPC object. - * This can be override to use a custom router protobuf. - */ - abstract decodeRpc (bytes: Uint8Array): PubSubRPC - - /** - * Encode RPC object into a Uint8Array. - * This can be override to use a custom router protobuf. - */ - abstract encodeRpc (rpc: PubSubRPC): Uint8Array - - /** - * Encode RPC object into a Uint8Array. - * This can be override to use a custom router protobuf. - */ - abstract encodeMessage (rpc: PubSubRPCMessage): Uint8Array - - /** - * Send an rpc object to a peer - */ - send (peer: PeerId, data: { messages?: Message[], subscriptions?: string[], subscribe?: boolean }) { - const { messages, subscriptions, subscribe } = data - - return this.sendRpc(peer, { - subscriptions: (subscriptions ?? []).map(str => ({ topic: str, subscribe: Boolean(subscribe) })), - messages: (messages ?? []).map(toRpcMessage) - }) - } - - /** - * Send an rpc object to a peer - */ - sendRpc (peer: PeerId, rpc: PubSubRPC) { - const peerStreams = this.peers.get(peer) - - if (peerStreams == null || !peerStreams.isWritable) { - log.error('Cannot send RPC to %p as there is no open stream to it available', peer) - - return - } - - peerStreams.write(this.encodeRpc(rpc)) - } - - /** - * Validates the given message. The signature will be checked for authenticity. - * Throws an error on invalid messages - */ - async validate (message: Message) { // eslint-disable-line require-await - const signaturePolicy = this.globalSignaturePolicy - switch (signaturePolicy) { - case 'StrictNoSign': - if (message.signature != null) { - throw errcode(new Error('StrictNoSigning: signature should not be present'), codes.ERR_UNEXPECTED_SIGNATURE) - } - if (message.key != null) { - throw errcode(new Error('StrictNoSigning: key should not be present'), codes.ERR_UNEXPECTED_KEY) - } - if (message.sequenceNumber != null) { - throw errcode(new Error('StrictNoSigning: seqno should not be present'), codes.ERR_UNEXPECTED_SEQNO) - } - break - case 'StrictSign': - if (message.signature == null) { - throw errcode(new Error('StrictSigning: Signing required and no signature was present'), codes.ERR_MISSING_SIGNATURE) - } - if (message.sequenceNumber == null) { - throw errcode(new Error('StrictSigning: Signing required and no seqno was present'), codes.ERR_MISSING_SEQNO) - } - if (!(await verifySignature(message, this.encodeMessage.bind(this)))) { - throw errcode(new Error('StrictSigning: Invalid message signature'), codes.ERR_INVALID_SIGNATURE) - } - break - default: - throw errcode(new Error('Cannot validate message: unhandled signature policy'), codes.ERR_UNHANDLED_SIGNATURE_POLICY) - } - - const validatorFn = this.topicValidators.get(message.topic) - - if (validatorFn != null) { - await validatorFn(message.topic, message) - } - } - - /** - * Normalizes the message and signs it, if signing is enabled. - * Should be used by the routers to create the message to send. - */ - async buildMessage (message: Message) { - const signaturePolicy = this.globalSignaturePolicy - switch (signaturePolicy) { - case 'StrictSign': - message.sequenceNumber = randomSeqno() - return await signMessage(this.components.getPeerId(), message, this.encodeMessage.bind(this)) - case 'StrictNoSign': - return await Promise.resolve(message) - default: - throw errcode(new Error('Cannot build message: unhandled signature policy'), codes.ERR_UNHANDLED_SIGNATURE_POLICY) - } - } - - // API METHODS - - /** - * Get a list of the peer-ids that are subscribed to one topic. - */ - getSubscribers (topic: string) { - if (!this.started) { - throw errcode(new Error('not started yet'), 'ERR_NOT_STARTED_YET') - } - - if (topic == null) { - throw errcode(new Error('topic is required'), 'ERR_NOT_VALID_TOPIC') - } - - const peersInTopic = this.topics.get(topic.toString()) - - if (peersInTopic == null) { - return [] - } - - return Array.from(peersInTopic.values()) - } - - /** - * Publishes messages to all subscribed peers - */ - async publish (topic: string, data?: Uint8Array): Promise { - if (!this.started) { - throw new Error('Pubsub has not started') - } - - const message: Message = { - from: this.components.getPeerId(), - topic, - data: data ?? new Uint8Array(0) - } - - log('publish topic: %s from: %p data: %m', topic, message.from, message.data) - - const rpcMessage = await this.buildMessage(message) - let emittedToSelf = false - - // dispatch the event if we are interested - if (this.emitSelf) { - if (this.subscriptions.has(topic)) { - emittedToSelf = true - super.dispatchEvent(new CustomEvent('message', { - detail: rpcMessage - })) - - if (this.listenerCount(topic) === 0) { - this.unsubscribe(topic) - } - } - } - - // send to all the other peers - const result = await this.publishMessage(this.components.getPeerId(), rpcMessage) - - if (emittedToSelf) { - result.recipients = [...result.recipients, this.components.getPeerId()] - } - - return result - } - - /** - * Overriding the implementation of publish should handle the appropriate algorithms for the publish/subscriber implementation. - * For example, a Floodsub implementation might simply publish each message to each topic for every peer. - * - * `sender` might be this peer, or we might be forwarding a message on behalf of another peer, in which case sender - * is the peer we received the message from, which may not be the peer the message was created by. - */ - abstract publishMessage (sender: PeerId, message: Message): Promise - - /** - * Subscribes to a given topic. - */ - subscribe (topic: string) { - if (!this.started) { - throw new Error('Pubsub has not started') - } - - if (!this.subscriptions.has(topic)) { - this.subscriptions.add(topic) - - for (const peerId of this.peers.keys()) { - this.send(peerId, { subscriptions: [topic], subscribe: true }) - } - } - } - - /** - * Unsubscribe from the given topic - */ - unsubscribe (topic: string) { - if (!this.started) { - throw new Error('Pubsub is not started') - } - - // @ts-expect-error topic should be a key of the event map - super.removeEventListener(topic) - - const wasSubscribed = this.subscriptions.has(topic) - const listeners = this.listenerCount(topic) - - log('unsubscribe from %s - am subscribed %s, listeners %d', topic, wasSubscribed, listeners) - - if (wasSubscribed && listeners === 0) { - this.subscriptions.delete(topic) - - for (const peerId of this.peers.keys()) { - this.send(peerId, { subscriptions: [topic], subscribe: false }) - } - } - } - - /** - * Get the list of topics which the peer is subscribed to. - */ - getTopics () { - if (!this.started) { - throw new Error('Pubsub is not started') - } - - return Array.from(this.subscriptions) - } - - getPeers () { - if (!this.started) { - throw new Error('Pubsub is not started') - } - - return Array.from(this.peers.keys()) - } -} diff --git a/packages/libp2p-pubsub/src/peer-streams.ts b/packages/libp2p-pubsub/src/peer-streams.ts deleted file mode 100644 index 0235a9deb..000000000 --- a/packages/libp2p-pubsub/src/peer-streams.ts +++ /dev/null @@ -1,174 +0,0 @@ -import { logger } from '@libp2p/logger' -import { EventEmitter, CustomEvent } from '@libp2p/interfaces/events' -import * as lp from 'it-length-prefixed' -import { pushable } from 'it-pushable' -import { pipe } from 'it-pipe' -import { abortableSource } from 'abortable-iterator' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { Stream } from '@libp2p/interfaces/connection' -import type { Pushable } from 'it-pushable' -import type { PeerStreamEvents } from '@libp2p/interfaces/pubsub' - -const log = logger('libp2p-pubsub:peer-streams') - -export interface PeerStreamsInit { - id: PeerId - protocol: string -} - -/** - * Thin wrapper around a peer's inbound / outbound pubsub streams - */ -export class PeerStreams extends EventEmitter { - public readonly id: PeerId - public readonly protocol: string - /** - * Write stream - it's preferable to use the write method - */ - public outboundStream?: Pushable - /** - * Read stream - */ - public inboundStream?: AsyncIterable - /** - * The raw outbound stream, as retrieved from conn.newStream - */ - private _rawOutboundStream?: Stream - /** - * The raw inbound stream, as retrieved from the callback from libp2p.handle - */ - private _rawInboundStream?: Stream - /** - * An AbortController for controlled shutdown of the inbound stream - */ - private readonly _inboundAbortController: AbortController - private closed: boolean - - constructor (init: PeerStreamsInit) { - super() - - this.id = init.id - this.protocol = init.protocol - - this._inboundAbortController = new AbortController() - this.closed = false - } - - /** - * Do we have a connection to read from? - */ - get isReadable () { - return Boolean(this.inboundStream) - } - - /** - * Do we have a connection to write on? - */ - get isWritable () { - return Boolean(this.outboundStream) - } - - /** - * Send a message to this peer. - * Throws if there is no `stream` to write to available. - */ - write (data: Uint8Array) { - if (this.outboundStream == null) { - const id = this.id.toString() - throw new Error('No writable connection to ' + id) - } - - this.outboundStream.push(data) - } - - /** - * Attach a raw inbound stream and setup a read stream - */ - attachInboundStream (stream: Stream) { - // Create and attach a new inbound stream - // The inbound stream is: - // - abortable, set to only return on abort, rather than throw - // - transformed with length-prefix transform - this._rawInboundStream = stream - this.inboundStream = abortableSource( - pipe( - this._rawInboundStream, - lp.decode() - ), - this._inboundAbortController.signal, - { returnOnAbort: true } - ) - - this.dispatchEvent(new CustomEvent('stream:inbound')) - return this.inboundStream - } - - /** - * Attach a raw outbound stream and setup a write stream - */ - async attachOutboundStream (stream: Stream) { - // If an outbound stream already exists, gently close it - const _prevStream = this.outboundStream - if (this.outboundStream != null) { - // End the stream without emitting a close event - await this.outboundStream.end() - } - - this._rawOutboundStream = stream - this.outboundStream = pushable({ - onEnd: (shouldEmit) => { - // close writable side of the stream - if (this._rawOutboundStream != null && this._rawOutboundStream.reset != null) { // eslint-disable-line @typescript-eslint/prefer-optional-chain - this._rawOutboundStream.reset() - } - - this._rawOutboundStream = undefined - this.outboundStream = undefined - if (shouldEmit != null) { - this.dispatchEvent(new CustomEvent('close')) - } - } - }) - - pipe( - this.outboundStream, - lp.encode(), - this._rawOutboundStream - ).catch((err: Error) => { - log.error(err) - }) - - // Only emit if the connection is new - if (_prevStream == null) { - this.dispatchEvent(new CustomEvent('stream:outbound')) - } - - return this.outboundStream - } - - /** - * Closes the open connection to peer - */ - close () { - if (this.closed) { - return - } - - this.closed = true - - // End the outbound stream - if (this.outboundStream != null) { - this.outboundStream.end() - } - // End the inbound stream - if (this.inboundStream != null) { - this._inboundAbortController.abort() - } - - this._rawOutboundStream = undefined - this.outboundStream = undefined - this._rawInboundStream = undefined - this.inboundStream = undefined - this.dispatchEvent(new CustomEvent('close')) - } -} diff --git a/packages/libp2p-pubsub/src/sign.ts b/packages/libp2p-pubsub/src/sign.ts deleted file mode 100644 index e156cfff6..000000000 --- a/packages/libp2p-pubsub/src/sign.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { concat as uint8ArrayConcat } from 'uint8arrays/concat' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toRpcMessage } from './utils.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { keys } from '@libp2p/crypto' -import type { Message, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' -import { peerIdFromKeys } from '@libp2p/peer-id' - -export const SignPrefix = uint8ArrayFromString('libp2p-pubsub:') - -/** - * Signs the provided message with the given `peerId` - */ -export async function signMessage (peerId: PeerId, message: Message, encode: (rpc: PubSubRPCMessage) => Uint8Array) { - // Get the message in bytes, and prepend with the pubsub prefix - const bytes = uint8ArrayConcat([ - SignPrefix, - encode(toRpcMessage(message)) - ]) - - if (peerId.privateKey == null) { - throw new Error('Cannot sign message, no private key present') - } - - if (peerId.publicKey == null) { - throw new Error('Cannot sign message, no public key present') - } - - const privateKey = await keys.unmarshalPrivateKey(peerId.privateKey) - const signature = await privateKey.sign(bytes) - - const outputMessage: Message = { - ...message, - signature: signature, - key: peerId.publicKey - } - - return outputMessage -} - -/** - * Verifies the signature of the given message - */ -export async function verifySignature (message: Message, encode: (rpc: PubSubRPCMessage) => Uint8Array) { - if (message.signature == null) { - throw new Error('Message must contain a signature to be verified') - } - - if (message.from == null) { - throw new Error('Message must contain a from property to be verified') - } - - // Get message sans the signature - const bytes = uint8ArrayConcat([ - SignPrefix, - encode({ - ...toRpcMessage(message), - signature: undefined, - key: undefined - }) - ]) - - // Get the public key - const pubKeyBytes = await messagePublicKey(message) - const pubKey = keys.unmarshalPublicKey(pubKeyBytes) - - // verify the base message - return await pubKey.verify(bytes, message.signature) -} - -/** - * Returns the PublicKey associated with the given message. - * If no valid PublicKey can be retrieved an error will be returned. - */ -export async function messagePublicKey (message: Message) { - // should be available in the from property of the message (peer id) - if (message.from == null) { - throw new Error('Could not get the public key from the originator id') - } - - if (message.key != null) { - const keyPeerId = await peerIdFromKeys(message.key) - - if (keyPeerId.publicKey != null) { - return keyPeerId.publicKey - } - } - - if (message.from.publicKey != null) { - return message.from.publicKey - } - - // We couldn't validate pubkey is from the originator, error - throw new Error('Could not get the public key from the originator id') -} diff --git a/packages/libp2p-pubsub/src/utils.ts b/packages/libp2p-pubsub/src/utils.ts deleted file mode 100644 index 1d9e6df35..000000000 --- a/packages/libp2p-pubsub/src/utils.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { randomBytes } from 'iso-random-stream' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { toString as uint8ArrayToString } from 'uint8arrays/to-string' -import { sha256 } from 'multiformats/hashes/sha2' -import type { Message, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' -import { peerIdFromBytes } from '@libp2p/peer-id' -import { codes } from './errors.js' -import errcode from 'err-code' - -/** - * Generate a random sequence number - */ -export function randomSeqno (): bigint { - return BigInt(`0x${uint8ArrayToString(randomBytes(8), 'base16')}`) -} - -/** - * Generate a message id, based on the `key` and `seqno` - */ -export const msgId = (key: Uint8Array, seqno: bigint) => { - const seqnoBytes = uint8ArrayFromString(seqno.toString(16).padStart(16, '0'), 'base16') - - const msgId = new Uint8Array(key.length + seqnoBytes.length) - msgId.set(key, 0) - msgId.set(seqnoBytes, key.length) - - return msgId -} - -/** - * Generate a message id, based on message `data` - */ -export const noSignMsgId = (data: Uint8Array) => { - return sha256.encode(data) -} - -/** - * Check if any member of the first set is also a member - * of the second set - */ -export const anyMatch = (a: Set | number[], b: Set | number[]) => { - let bHas - if (Array.isArray(b)) { - bHas = (val: number) => b.includes(val) - } else { - bHas = (val: number) => b.has(val) - } - - for (const val of a) { - if (bHas(val)) { - return true - } - } - - return false -} - -/** - * Make everything an array - */ -export const ensureArray = function (maybeArray: T | T[]) { - if (!Array.isArray(maybeArray)) { - return [maybeArray] - } - - return maybeArray -} - -export const toMessage = (message: PubSubRPCMessage): Message => { - if (message.from == null) { - throw errcode(new Error('RPC message was missing from'), codes.ERR_MISSING_FROM) - } - - return { - from: peerIdFromBytes(message.from), - topic: message.topic ?? '', - sequenceNumber: message.sequenceNumber == null ? undefined : bigIntFromBytes(message.sequenceNumber), - data: message.data ?? new Uint8Array(0), - signature: message.signature ?? undefined, - key: message.key ?? undefined - } -} - -export const toRpcMessage = (message: Message): PubSubRPCMessage => { - return { - from: message.from.multihash.bytes, - data: message.data, - sequenceNumber: message.sequenceNumber == null ? undefined : bigIntToBytes(message.sequenceNumber), - topic: message.topic, - signature: message.signature, - key: message.key - } -} - -export const bigIntToBytes = (num: bigint): Uint8Array => { - let str = num.toString(16) - - if (str.length % 2 !== 0) { - str = `0${str}` - } - - return uint8ArrayFromString(str, 'base16') -} - -export const bigIntFromBytes = (num: Uint8Array): bigint => { - return BigInt(`0x${uint8ArrayToString(num, 'base16')}`) -} diff --git a/packages/libp2p-pubsub/test/emit-self.spec.ts b/packages/libp2p-pubsub/test/emit-self.spec.ts deleted file mode 100644 index 438134b8c..000000000 --- a/packages/libp2p-pubsub/test/emit-self.spec.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { expect } from 'aegir/chai' -import { - createPeerId, - MockRegistrar, - PubsubImplementation -} from './utils/index.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import delay from 'delay' -import { Components } from '@libp2p/interfaces/components' - -const protocol = '/pubsub/1.0.0' -const topic = 'foo' -const data = uint8ArrayFromString('bar') -const shouldNotHappen = () => expect.fail() - -describe('emitSelf', () => { - let pubsub: PubsubImplementation - - describe('enabled', () => { - before(async () => { - const peerId = await createPeerId() - - pubsub = new PubsubImplementation({ - multicodecs: [protocol], - emitSelf: true - }) - pubsub.init(new Components({ - peerId, - registrar: new MockRegistrar() - })) - }) - - before(async () => { - await pubsub.start() - pubsub.subscribe(topic) - }) - - after(async () => { - await pubsub.stop() - }) - - it('should emit to self on publish', async () => { - pubsub.subscribe(topic) - - const promise = new Promise((resolve) => { - pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic === topic) { - resolve() - } - }) - }) - - await pubsub.publish(topic, data) - - return await promise - }) - - it('should publish a message without data', async () => { - pubsub.subscribe(topic) - - const promise = new Promise((resolve) => { - pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic === topic) { - resolve() - } - }) - }) - - await pubsub.publish(topic) - - return await promise - }) - }) - - describe('disabled', () => { - before(async () => { - const peerId = await createPeerId() - - pubsub = new PubsubImplementation({ - multicodecs: [protocol], - emitSelf: false - }) - pubsub.init(new Components({ - peerId, - registrar: new MockRegistrar() - })) - }) - - before(async () => { - await pubsub.start() - pubsub.subscribe(topic) - }) - - after(async () => { - await pubsub.stop() - }) - - it('should not emit to self on publish', async () => { - pubsub.subscribe(topic) - pubsub.addEventListener('message', shouldNotHappen) - - await pubsub.publish(topic, data) - - // Wait 1 second to guarantee that self is not noticed - await delay(1000) - }) - }) -}) diff --git a/packages/libp2p-pubsub/test/instance.spec.ts b/packages/libp2p-pubsub/test/instance.spec.ts deleted file mode 100644 index 2b153a3bc..000000000 --- a/packages/libp2p-pubsub/test/instance.spec.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { expect } from 'aegir/chai' -import { PubSubBaseProtocol } from '../src/index.js' -import type { PublishResult, PubSubRPC, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' - -class PubsubProtocol extends PubSubBaseProtocol { - decodeRpc (bytes: Uint8Array): PubSubRPC { - throw new Error('Method not implemented.') - } - - encodeRpc (rpc: PubSubRPC): Uint8Array { - throw new Error('Method not implemented.') - } - - decodeMessage (bytes: Uint8Array): PubSubRPCMessage { - throw new Error('Method not implemented.') - } - - encodeMessage (rpc: PubSubRPCMessage): Uint8Array { - throw new Error('Method not implemented.') - } - - async publishMessage (): Promise { - throw new Error('Method not implemented.') - } -} - -describe('pubsub instance', () => { - it('should throw if no init is provided', () => { - expect(() => { - // @ts-expect-error incorrect constructor args - new PubsubProtocol() // eslint-disable-line no-new - }).to.throw() - }) - - it('should accept valid parameters', () => { - expect(() => { - new PubsubProtocol({ // eslint-disable-line no-new - multicodecs: ['/pubsub/1.0.0'] - }) - }).not.to.throw() - }) -}) diff --git a/packages/libp2p-pubsub/test/lifecycle.spec.ts b/packages/libp2p-pubsub/test/lifecycle.spec.ts deleted file mode 100644 index 49ecb4b79..000000000 --- a/packages/libp2p-pubsub/test/lifecycle.spec.ts +++ /dev/null @@ -1,261 +0,0 @@ -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import { PubSubBaseProtocol } from '../src/index.js' -import { - createPeerId, - PubsubImplementation, - ConnectionPair, - MockRegistrar, - mockIncomingStreamEvent -} from './utils/index.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { Registrar } from '@libp2p/interfaces/registrar' -import type { PublishResult, PubSubRPC, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' -import { Components } from '@libp2p/interfaces/components' - -class PubsubProtocol extends PubSubBaseProtocol { - decodeRpc (bytes: Uint8Array): PubSubRPC { - throw new Error('Method not implemented.') - } - - encodeRpc (rpc: PubSubRPC): Uint8Array { - throw new Error('Method not implemented.') - } - - decodeMessage (bytes: Uint8Array): PubSubRPCMessage { - throw new Error('Method not implemented.') - } - - encodeMessage (rpc: PubSubRPCMessage): Uint8Array { - throw new Error('Method not implemented.') - } - - async publishMessage (): Promise { - throw new Error('Method not implemented.') - } -} - -describe('pubsub base lifecycle', () => { - describe('should start and stop properly', () => { - let pubsub: PubsubProtocol - let sinonMockRegistrar: Registrar - - beforeEach(async () => { - const peerId = await createPeerId() - // @ts-expect-error incomplete implementation - sinonMockRegistrar = { - handle: sinon.stub(), - unhandle: sinon.stub(), - register: sinon.stub().returns(`id-${Math.random()}`), - unregister: sinon.stub() - } - - pubsub = new PubsubProtocol({ - multicodecs: ['/pubsub/1.0.0'] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: sinonMockRegistrar - })) - - expect(pubsub.peers.size).to.be.eql(0) - }) - - afterEach(() => { - sinon.restore() - }) - - it('should be able to start and stop', async () => { - await pubsub.start() - expect(sinonMockRegistrar.handle).to.have.property('calledOnce', true) - expect(sinonMockRegistrar.register).to.have.property('calledOnce', true) - - await pubsub.stop() - expect(sinonMockRegistrar.unhandle).to.have.property('calledOnce', true) - expect(sinonMockRegistrar.unregister).to.have.property('calledOnce', true) - }) - - it('starting should not throw if already started', async () => { - await pubsub.start() - await pubsub.start() - expect(sinonMockRegistrar.handle).to.have.property('calledOnce', true) - expect(sinonMockRegistrar.register).to.have.property('calledOnce', true) - - await pubsub.stop() - expect(sinonMockRegistrar.unhandle).to.have.property('calledOnce', true) - expect(sinonMockRegistrar.unregister).to.have.property('calledOnce', true) - }) - - it('stopping should not throw if not started', async () => { - await pubsub.stop() - expect(sinonMockRegistrar.handle).to.have.property('calledOnce', false) - expect(sinonMockRegistrar.unhandle).to.have.property('calledOnce', false) - expect(sinonMockRegistrar.register).to.have.property('calledOnce', false) - expect(sinonMockRegistrar.unregister).to.have.property('calledOnce', false) - }) - }) - - describe('should be able to register two nodes', () => { - const protocol = '/pubsub/1.0.0' - let pubsubA: PubsubImplementation, pubsubB: PubsubImplementation - let peerIdA: PeerId, peerIdB: PeerId - let registrarA: MockRegistrar - let registrarB: MockRegistrar - - // mount pubsub - beforeEach(async () => { - peerIdA = await createPeerId() - peerIdB = await createPeerId() - - registrarA = new MockRegistrar() - registrarB = new MockRegistrar() - - pubsubA = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsubA.init(new Components({ - peerId: peerIdA, - registrar: registrarA - })) - pubsubB = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsubB.init(new Components({ - peerId: peerIdB, - registrar: registrarB - })) - }) - - // start pubsub - beforeEach(async () => { - await Promise.all([ - pubsubA.start(), - pubsubB.start() - ]) - - expect(registrarA.getHandler(protocol)).to.be.ok() - expect(registrarB.getHandler(protocol)).to.be.ok() - }) - - afterEach(async () => { - sinon.restore() - - await Promise.all([ - pubsubA.stop(), - pubsubB.stop() - ]) - }) - - it('should handle onConnect as expected', async () => { - const topologyA = registrarA.getTopologies(protocol)[0] - const handlerB = registrarB.getHandler(protocol) - - if (topologyA == null || handlerB == null) { - throw new Error(`No handler registered for ${protocol}`) - } - - const [c0, c1] = ConnectionPair() - - // Notify peers of connection - await topologyA.onConnect(peerIdB, c0) - await handlerB(await mockIncomingStreamEvent(protocol, c1, peerIdA)) - - expect(pubsubA.peers.size).to.be.eql(1) - expect(pubsubB.peers.size).to.be.eql(1) - }) - - it('should use the latest connection if onConnect is called more than once', async () => { - const topologyA = registrarA.getTopologies(protocol)[0] - const handlerB = registrarB.getHandler(protocol) - - if (topologyA == null || handlerB == null) { - throw new Error(`No handler registered for ${protocol}`) - } - - // Notify peers of connection - const [c0, c1] = ConnectionPair() - const [c2] = ConnectionPair() - - sinon.spy(c0, 'newStream') - - await topologyA.onConnect(peerIdB, c0) - await handlerB(await mockIncomingStreamEvent(protocol, c1, peerIdA)) - expect(c0.newStream).to.have.property('callCount', 1) - - // @ts-expect-error _removePeer is a protected method - sinon.spy(pubsubA, '_removePeer') - - sinon.spy(c2, 'newStream') - - await topologyA?.onConnect(peerIdB, c2) - expect(c2.newStream).to.have.property('callCount', 1) - - // @ts-expect-error _removePeer is a protected method - expect(pubsubA._removePeer).to.have.property('callCount', 0) - - // Verify the first stream was closed - // @ts-expect-error .returnValues is a sinon property - const { stream: firstStream } = await c0.newStream.returnValues[0] - try { - await firstStream.sink(['test']) - } catch (err: any) { - expect(err).to.exist() - return - } - expect.fail('original stream should have ended') - }) - - it('should handle newStream errors in onConnect', async () => { - const topologyA = registrarA.getTopologies(protocol)[0] - const handlerB = registrarB.getHandler(protocol) - - if (topologyA == null || handlerB == null) { - throw new Error(`No handler registered for ${protocol}`) - } - - // Notify peers of connection - const [c0, c1] = ConnectionPair() - const error = new Error('new stream error') - sinon.stub(c0, 'newStream').throws(error) - - await topologyA.onConnect(peerIdB, c0) - await handlerB(await mockIncomingStreamEvent(protocol, c1, peerIdA)) - - expect(c0.newStream).to.have.property('callCount', 1) - }) - - it('should handle onDisconnect as expected', async () => { - const topologyA = registrarA.getTopologies(protocol)[0] - const topologyB = registrarB.getTopologies(protocol)[0] - const handlerB = registrarB.getHandler(protocol) - - if (topologyA == null || handlerB == null) { - throw new Error(`No handler registered for ${protocol}`) - } - - // Notify peers of connection - const [c0, c1] = ConnectionPair() - - await topologyA.onConnect(peerIdB, c0) - await handlerB(await mockIncomingStreamEvent(protocol, c1, peerIdA)) - - // Notice peers of disconnect - topologyA?.onDisconnect(peerIdB) - topologyB?.onDisconnect(peerIdA) - - expect(pubsubA.peers.size).to.be.eql(0) - expect(pubsubB.peers.size).to.be.eql(0) - }) - - it('should handle onDisconnect for unknown peers', () => { - const topologyA = registrarA.getTopologies(protocol)[0] - - expect(pubsubA.peers.size).to.be.eql(0) - - // Notice peers of disconnect - topologyA?.onDisconnect(peerIdB) - - expect(pubsubA.peers.size).to.be.eql(0) - }) - }) -}) diff --git a/packages/libp2p-pubsub/test/message.spec.ts b/packages/libp2p-pubsub/test/message.spec.ts deleted file mode 100644 index efab59d70..000000000 --- a/packages/libp2p-pubsub/test/message.spec.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* eslint-env mocha */ -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { - createPeerId, - MockRegistrar, - PubsubImplementation -} from './utils/index.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { Message } from '@libp2p/interfaces/pubsub' -import { Components } from '@libp2p/interfaces/components' - -describe('pubsub base messages', () => { - let peerId: PeerId - let pubsub: PubsubImplementation - - before(async () => { - peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: ['/pubsub/1.0.0'] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - }) - - afterEach(() => { - sinon.restore() - }) - - it('buildMessage normalizes and signs messages', async () => { - const message: Message = { - from: peerId, - data: uint8ArrayFromString('hello'), - topic: 'test-topic' - } - - const signedMessage = await pubsub.buildMessage(message) - - await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected() - }) - - it('validate with StrictNoSign will reject a message with from, signature, key, seqno present', async () => { - const message: Message = { - from: peerId, - data: uint8ArrayFromString('hello'), - topic: 'test-topic' - } - - sinon.stub(pubsub, 'globalSignaturePolicy').value('StrictSign') - - const signedMessage = await pubsub.buildMessage(message) - - sinon.stub(pubsub, 'globalSignaturePolicy').value('StrictNoSign') - await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() - // @ts-expect-error this field is not optional - delete signedMessage.from - await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() - delete signedMessage.signature - await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() - delete signedMessage.key - await expect(pubsub.validate(signedMessage)).to.eventually.be.rejected() - delete signedMessage.sequenceNumber - await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected() - }) - - it('validate with StrictNoSign will validate a message without a signature, key, and seqno', async () => { - const message: Message = { - from: peerId, - data: uint8ArrayFromString('hello'), - topic: 'test-topic' - } - - sinon.stub(pubsub, 'globalSignaturePolicy').value('StrictNoSign') - - const signedMessage = await pubsub.buildMessage(message) - await expect(pubsub.validate(signedMessage)).to.eventually.not.be.rejected() - }) - - it('validate with StrictSign requires a signature', async () => { - const message: Message = { - from: peerId, - data: uint8ArrayFromString('hello'), - topic: 'test-topic' - } - - await expect(pubsub.validate(message)).to.be.rejectedWith(Error, 'Signing required and no signature was present') - }) -}) diff --git a/packages/libp2p-pubsub/test/message/rpc.proto b/packages/libp2p-pubsub/test/message/rpc.proto deleted file mode 100644 index 5e32c35a5..000000000 --- a/packages/libp2p-pubsub/test/message/rpc.proto +++ /dev/null @@ -1,52 +0,0 @@ -syntax = "proto3"; - -message RPC { - repeated SubOpts subscriptions = 1; - repeated Message messages = 2; - optional ControlMessage control = 3; - - message SubOpts { - optional bool subscribe = 1; // subscribe or unsubcribe - optional string topic = 2; - } - - message Message { - optional bytes from = 1; - optional bytes data = 2; - optional bytes seqno = 3; - optional string topic = 4; - optional bytes signature = 5; - optional bytes key = 6; - } -} - -message ControlMessage { - repeated ControlIHave ihave = 1; - repeated ControlIWant iwant = 2; - repeated ControlGraft graft = 3; - repeated ControlPrune prune = 4; -} - -message ControlIHave { - optional string topic = 1; - repeated bytes messageIDs = 2; -} - -message ControlIWant { - repeated bytes messageIDs = 1; -} - -message ControlGraft { - optional string topic = 1; -} - -message ControlPrune { - optional string topic = 1; - repeated PeerInfo peers = 2; - optional uint64 backoff = 3; -} - -message PeerInfo { - optional bytes peerID = 1; - optional bytes signedPeerRecord = 2; -} diff --git a/packages/libp2p-pubsub/test/message/rpc.ts b/packages/libp2p-pubsub/test/message/rpc.ts deleted file mode 100644 index 4440d48a0..000000000 --- a/packages/libp2p-pubsub/test/message/rpc.ts +++ /dev/null @@ -1,215 +0,0 @@ -/* eslint-disable import/export */ -/* eslint-disable @typescript-eslint/no-namespace */ - -import { encodeMessage, decodeMessage, message, bool, string, bytes, uint64 } from 'protons-runtime' -import type { Codec } from 'protons-runtime' - -export interface RPC { - subscriptions: RPC.SubOpts[] - messages: RPC.Message[] - control?: ControlMessage -} - -export namespace RPC { - export interface SubOpts { - subscribe?: boolean - topic?: string - } - - export namespace SubOpts { - export const codec = (): Codec => { - return message({ - 1: { name: 'subscribe', codec: bool, optional: true }, - 2: { name: 'topic', codec: string, optional: true } - }) - } - - export const encode = (obj: SubOpts): Uint8Array => { - return encodeMessage(obj, SubOpts.codec()) - } - - export const decode = (buf: Uint8Array): SubOpts => { - return decodeMessage(buf, SubOpts.codec()) - } - } - - export interface Message { - from?: Uint8Array - data?: Uint8Array - seqno?: Uint8Array - topic?: string - signature?: Uint8Array - key?: Uint8Array - } - - export namespace Message { - export const codec = (): Codec => { - return message({ - 1: { name: 'from', codec: bytes, optional: true }, - 2: { name: 'data', codec: bytes, optional: true }, - 3: { name: 'seqno', codec: bytes, optional: true }, - 4: { name: 'topic', codec: string, optional: true }, - 5: { name: 'signature', codec: bytes, optional: true }, - 6: { name: 'key', codec: bytes, optional: true } - }) - } - - export const encode = (obj: Message): Uint8Array => { - return encodeMessage(obj, Message.codec()) - } - - export const decode = (buf: Uint8Array): Message => { - return decodeMessage(buf, Message.codec()) - } - } - - export const codec = (): Codec => { - return message({ - 1: { name: 'subscriptions', codec: RPC.SubOpts.codec(), repeats: true }, - 2: { name: 'messages', codec: RPC.Message.codec(), repeats: true }, - 3: { name: 'control', codec: ControlMessage.codec(), optional: true } - }) - } - - export const encode = (obj: RPC): Uint8Array => { - return encodeMessage(obj, RPC.codec()) - } - - export const decode = (buf: Uint8Array): RPC => { - return decodeMessage(buf, RPC.codec()) - } -} - -export interface ControlMessage { - ihave: ControlIHave[] - iwant: ControlIWant[] - graft: ControlGraft[] - prune: ControlPrune[] -} - -export namespace ControlMessage { - export const codec = (): Codec => { - return message({ - 1: { name: 'ihave', codec: ControlIHave.codec(), repeats: true }, - 2: { name: 'iwant', codec: ControlIWant.codec(), repeats: true }, - 3: { name: 'graft', codec: ControlGraft.codec(), repeats: true }, - 4: { name: 'prune', codec: ControlPrune.codec(), repeats: true } - }) - } - - export const encode = (obj: ControlMessage): Uint8Array => { - return encodeMessage(obj, ControlMessage.codec()) - } - - export const decode = (buf: Uint8Array): ControlMessage => { - return decodeMessage(buf, ControlMessage.codec()) - } -} - -export interface ControlIHave { - topic?: string - messageIDs: Uint8Array[] -} - -export namespace ControlIHave { - export const codec = (): Codec => { - return message({ - 1: { name: 'topic', codec: string, optional: true }, - 2: { name: 'messageIDs', codec: bytes, repeats: true } - }) - } - - export const encode = (obj: ControlIHave): Uint8Array => { - return encodeMessage(obj, ControlIHave.codec()) - } - - export const decode = (buf: Uint8Array): ControlIHave => { - return decodeMessage(buf, ControlIHave.codec()) - } -} - -export interface ControlIWant { - messageIDs: Uint8Array[] -} - -export namespace ControlIWant { - export const codec = (): Codec => { - return message({ - 1: { name: 'messageIDs', codec: bytes, repeats: true } - }) - } - - export const encode = (obj: ControlIWant): Uint8Array => { - return encodeMessage(obj, ControlIWant.codec()) - } - - export const decode = (buf: Uint8Array): ControlIWant => { - return decodeMessage(buf, ControlIWant.codec()) - } -} - -export interface ControlGraft { - topic?: string -} - -export namespace ControlGraft { - export const codec = (): Codec => { - return message({ - 1: { name: 'topic', codec: string, optional: true } - }) - } - - export const encode = (obj: ControlGraft): Uint8Array => { - return encodeMessage(obj, ControlGraft.codec()) - } - - export const decode = (buf: Uint8Array): ControlGraft => { - return decodeMessage(buf, ControlGraft.codec()) - } -} - -export interface ControlPrune { - topic?: string - peers: PeerInfo[] - backoff?: bigint -} - -export namespace ControlPrune { - export const codec = (): Codec => { - return message({ - 1: { name: 'topic', codec: string, optional: true }, - 2: { name: 'peers', codec: PeerInfo.codec(), repeats: true }, - 3: { name: 'backoff', codec: uint64, optional: true } - }) - } - - export const encode = (obj: ControlPrune): Uint8Array => { - return encodeMessage(obj, ControlPrune.codec()) - } - - export const decode = (buf: Uint8Array): ControlPrune => { - return decodeMessage(buf, ControlPrune.codec()) - } -} - -export interface PeerInfo { - peerID?: Uint8Array - signedPeerRecord?: Uint8Array -} - -export namespace PeerInfo { - export const codec = (): Codec => { - return message({ - 1: { name: 'peerID', codec: bytes, optional: true }, - 2: { name: 'signedPeerRecord', codec: bytes, optional: true } - }) - } - - export const encode = (obj: PeerInfo): Uint8Array => { - return encodeMessage(obj, PeerInfo.codec()) - } - - export const decode = (buf: Uint8Array): PeerInfo => { - return decodeMessage(buf, PeerInfo.codec()) - } -} diff --git a/packages/libp2p-pubsub/test/pubsub.spec.ts b/packages/libp2p-pubsub/test/pubsub.spec.ts deleted file mode 100644 index 0d8a4ecdf..000000000 --- a/packages/libp2p-pubsub/test/pubsub.spec.ts +++ /dev/null @@ -1,505 +0,0 @@ -/* eslint max-nested-callbacks: ["error", 6] */ -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import pWaitFor from 'p-wait-for' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { PeerStreams } from '../src/peer-streams.js' -import { - createPeerId, - MockRegistrar, - ConnectionPair, - PubsubImplementation, - mockIncomingStreamEvent -} from './utils/index.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import { PeerSet } from '@libp2p/peer-collections' -import { Components } from '@libp2p/interfaces/components' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { noSignMsgId } from '../src/utils.js' -import type { PubSubRPC } from '@libp2p/interfaces/src/pubsub' -import delay from 'delay' -import pDefer from 'p-defer' - -const protocol = '/pubsub/1.0.0' -const topic = 'test-topic' -const message = uint8ArrayFromString('hello') - -describe('pubsub base implementation', () => { - describe('publish', () => { - let pubsub: PubsubImplementation - - beforeEach(async () => { - const peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - }) - - afterEach(async () => await pubsub.stop()) - - it('calls _publish for router to forward messages', async () => { - sinon.spy(pubsub, 'publishMessage') - - await pubsub.start() - await pubsub.publish(topic, message) - - // event dispatch is async - await pWaitFor(() => { - // @ts-expect-error .callCount is a added by sinon - return pubsub.publishMessage.callCount === 1 - }) - - // @ts-expect-error .callCount is a added by sinon - expect(pubsub.publishMessage.callCount).to.eql(1) - }) - - it('should sign messages on publish', async () => { - sinon.spy(pubsub, 'publishMessage') - - await pubsub.start() - await pubsub.publish(topic, message) - - // event dispatch is async - await pWaitFor(() => { - // @ts-expect-error .callCount is a added by sinon - return pubsub.publishMessage.callCount === 1 - }) - - // Get the first message sent to _publish, and validate it - // @ts-expect-error .getCall is a added by sinon - const signedMessage: Message = pubsub.publishMessage.getCall(0).lastArg - - await expect(pubsub.validate(signedMessage)).to.eventually.be.undefined() - }) - }) - - describe('subscribe', () => { - describe('basics', () => { - let pubsub: PubsubImplementation - - beforeEach(async () => { - const peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - await pubsub.start() - }) - - afterEach(async () => await pubsub.stop()) - - it('should add subscription', () => { - pubsub.subscribe(topic) - - expect(pubsub.subscriptions.size).to.eql(1) - expect(pubsub.subscriptions.has(topic)).to.be.true() - }) - }) - - describe('two nodes', () => { - let pubsubA: PubsubImplementation, pubsubB: PubsubImplementation - let peerIdA: PeerId, peerIdB: PeerId - let registrarA: MockRegistrar - let registrarB: MockRegistrar - - beforeEach(async () => { - peerIdA = await createPeerId() - peerIdB = await createPeerId() - - registrarA = new MockRegistrar() - registrarB = new MockRegistrar() - - pubsubA = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsubA.init(new Components({ - peerId: peerIdA, - registrar: registrarA - })) - pubsubB = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsubB.init(new Components({ - peerId: peerIdB, - registrar: registrarB - })) - }) - - // start pubsub and connect nodes - beforeEach(async () => { - await Promise.all([ - pubsubA.start(), - pubsubB.start() - ]) - const topologyA = registrarA.getTopologies(protocol)[0] - const handlerB = registrarB.getHandler(protocol) - - if (topologyA == null || handlerB == null) { - throw new Error(`No handler registered for ${protocol}`) - } - - // Notify peers of connection - const [c0, c1] = ConnectionPair() - - await topologyA.onConnect(peerIdB, c0) - await handlerB(await mockIncomingStreamEvent(protocol, c1, peerIdA)) - }) - - afterEach(async () => { - await Promise.all([ - pubsubA.stop(), - pubsubB.stop() - ]) - }) - - it('should send subscribe message to connected peers', async () => { - sinon.spy(pubsubA, 'send') - sinon.spy(pubsubB, 'processRpcSubOpt') - - pubsubA.subscribe(topic) - - // Should send subscriptions to a peer - // @ts-expect-error .callCount is a added by sinon - expect(pubsubA.send.callCount).to.eql(1) - - // Other peer should receive subscription message - await pWaitFor(() => { - const subscribers = pubsubB.getSubscribers(topic) - - return subscribers.length === 1 - }) - - // @ts-expect-error .callCount is a added by sinon - expect(pubsubB.processRpcSubOpt.callCount).to.eql(1) - }) - }) - }) - - describe('unsubscribe', () => { - describe('basics', () => { - let pubsub: PubsubImplementation - - beforeEach(async () => { - const peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - await pubsub.start() - }) - - afterEach(async () => await pubsub.stop()) - - it('should remove all subscriptions for a topic', () => { - pubsub.subscribe(topic) - pubsub.subscribe(topic) - - expect(pubsub.subscriptions.size).to.eql(1) - - pubsub.unsubscribe(topic) - - expect(pubsub.subscriptions.size).to.eql(0) - }) - }) - - describe('two nodes', () => { - let pubsubA: PubsubImplementation, pubsubB: PubsubImplementation - let peerIdA: PeerId, peerIdB: PeerId - let registrarA: MockRegistrar - let registrarB: MockRegistrar - - beforeEach(async () => { - peerIdA = await createPeerId() - peerIdB = await createPeerId() - - registrarA = new MockRegistrar() - registrarB = new MockRegistrar() - - pubsubA = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsubA.init(new Components({ - peerId: peerIdA, - registrar: registrarA - })) - pubsubB = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsubB.init(new Components({ - peerId: peerIdB, - registrar: registrarB - })) - }) - - // start pubsub and connect nodes - beforeEach(async () => { - await Promise.all([ - pubsubA.start(), - pubsubB.start() - ]) - - const topologyA = registrarA.getTopologies(protocol)[0] - const handlerB = registrarB.getHandler(protocol) - - if (topologyA == null || handlerB == null) { - throw new Error(`No handler registered for ${protocol}`) - } - - // Notify peers of connection - const [c0, c1] = ConnectionPair() - - await topologyA.onConnect(peerIdB, c0) - await handlerB(await mockIncomingStreamEvent(protocol, c1, peerIdA)) - }) - - afterEach(async () => { - await Promise.all([ - pubsubA.stop(), - pubsubB.stop() - ]) - }) - - it('should send unsubscribe message to connected peers', async () => { - const pubsubASendSpy = sinon.spy(pubsubA, 'send') - const pubsubBProcessRpcSubOptSpy = sinon.spy(pubsubB, 'processRpcSubOpt') - - pubsubA.subscribe(topic) - // Should send subscriptions to a peer - expect(pubsubASendSpy.callCount).to.eql(1) - - // Other peer should receive subscription message - await pWaitFor(() => { - const subscribers = pubsubB.getSubscribers(topic) - - return subscribers.length === 1 - }) - - expect(pubsubBProcessRpcSubOptSpy.callCount).to.eql(1) - - // Unsubscribe - pubsubA.unsubscribe(topic) - - // Should send subscriptions to a peer - expect(pubsubASendSpy.callCount).to.eql(2) - - // Other peer should receive subscription message - await pWaitFor(() => { - const subscribers = pubsubB.getSubscribers(topic) - - return subscribers.length === 0 - }) - - // @ts-expect-error .callCount is a property added by sinon - expect(pubsubB.processRpcSubOpt.callCount).to.eql(2) - }) - - it('should not send unsubscribe message to connected peers if not subscribed', () => { - const pubsubASendSpy = sinon.spy(pubsubA, 'send') - - // Unsubscribe - pubsubA.unsubscribe(topic) - - // Should send subscriptions to a peer - expect(pubsubASendSpy.callCount).to.eql(0) - }) - }) - }) - - describe('getTopics', () => { - let peerId: PeerId - let pubsub: PubsubImplementation - - beforeEach(async () => { - peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - await pubsub.start() - }) - - afterEach(async () => await pubsub.stop()) - - it('returns the subscribed topics', () => { - let subsTopics = pubsub.getTopics() - expect(subsTopics).to.have.lengthOf(0) - - pubsub.subscribe(topic) - - subsTopics = pubsub.getTopics() - expect(subsTopics).to.have.lengthOf(1) - expect(subsTopics[0]).to.eql(topic) - }) - }) - - describe('getSubscribers', () => { - let peerId: PeerId - let pubsub: PubsubImplementation - - beforeEach(async () => { - peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - }) - - afterEach(async () => await pubsub.stop()) - - it('should fail if pubsub is not started', () => { - const topic = 'test-topic' - - try { - pubsub.getSubscribers(topic) - } catch (err: any) { - expect(err).to.exist() - expect(err.code).to.eql('ERR_NOT_STARTED_YET') - return - } - throw new Error('should fail if pubsub is not started') - }) - - it('should fail if no topic is provided', async () => { - // start pubsub - await pubsub.start() - - try { - // @ts-expect-error invalid params - pubsub.getSubscribers() - } catch (err: any) { - expect(err).to.exist() - expect(err.code).to.eql('ERR_NOT_VALID_TOPIC') - return - } - throw new Error('should fail if no topic is provided') - }) - - it('should get peer subscribed to one topic', async () => { - const topic = 'test-topic' - - // start pubsub - await pubsub.start() - - let peersSubscribed = pubsub.getSubscribers(topic) - expect(peersSubscribed).to.be.empty() - - // Set mock peer subscribed - const peer = new PeerStreams({ id: peerId, protocol: 'a-protocol' }) - const id = peer.id - - const set = new PeerSet() - set.add(id) - - pubsub.topics.set(topic, set) - pubsub.peers.set(peer.id, peer) - - peersSubscribed = pubsub.getSubscribers(topic) - - expect(peersSubscribed).to.not.be.empty() - expect(id.equals(peersSubscribed[0])).to.be.true() - }) - }) - - describe('verification', () => { - let peerId: PeerId - let pubsub: PubsubImplementation - const data = uint8ArrayFromString('bar') - - beforeEach(async () => { - peerId = await createPeerId() - pubsub = new PubsubImplementation({ - multicodecs: [protocol] - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - await pubsub.start() - }) - - afterEach(async () => await pubsub.stop()) - - it('should drop unsigned messages', async () => { - const publishSpy = sinon.spy(pubsub, 'publishMessage') - sinon.spy(pubsub, 'validate') - - const peerStream = new PeerStreams({ - id: await createEd25519PeerId(), - protocol: 'test' - }) - const rpc: PubSubRPC = { - subscriptions: [], - messages: [{ - from: peerStream.id.toBytes(), - data, - sequenceNumber: await noSignMsgId(data), - topic: topic - }] - } - - pubsub.subscribe(topic) - - await pubsub.processRpc(peerStream.id, peerStream, rpc) - - // message should not be delivered - await delay(1000) - - expect(publishSpy).to.have.property('called', false) - }) - - it('should not drop unsigned messages if strict signing is disabled', async () => { - pubsub.globalSignaturePolicy = 'StrictNoSign' - - const publishSpy = sinon.spy(pubsub, 'publishMessage') - sinon.spy(pubsub, 'validate') - - const peerStream = new PeerStreams({ - id: await createEd25519PeerId(), - protocol: 'test' - }) - - const rpc: PubSubRPC = { - subscriptions: [], - messages: [{ - from: peerStream.id.toBytes(), - data, - topic - }] - } - - pubsub.subscribe(topic) - - const deferred = pDefer() - - pubsub.addEventListener('message', (evt) => { - if (evt.detail.topic === topic) { - deferred.resolve() - } - }) - - await pubsub.processRpc(peerStream.id, peerStream, rpc) - - // await message delivery - await deferred.promise - - expect(pubsub.validate).to.have.property('callCount', 1) - expect(publishSpy).to.have.property('callCount', 1) - }) - }) -}) diff --git a/packages/libp2p-pubsub/test/sign.spec.ts b/packages/libp2p-pubsub/test/sign.spec.ts deleted file mode 100644 index 94e7e1959..000000000 --- a/packages/libp2p-pubsub/test/sign.spec.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { expect } from 'aegir/chai' -import { concat as uint8ArrayConcat } from 'uint8arrays/concat' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { RPC } from './message/rpc.js' -import { - signMessage, - SignPrefix, - verifySignature -} from '../src/sign.js' -import * as PeerIdFactory from '@libp2p/peer-id-factory' -import { randomSeqno, toRpcMessage } from '../src/utils.js' -import { keys } from '@libp2p/crypto' -import type { Message, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' -import type { PeerId } from '@libp2p/interfaces/peer-id' - -function encodeMessage (message: PubSubRPCMessage) { - return RPC.Message.encode(message) -} - -describe('message signing', () => { - let peerId: PeerId - - before(async () => { - peerId = await PeerIdFactory.createRSAPeerId({ - bits: 1024 - }) - }) - - it('should be able to sign and verify a message', async () => { - const message: Message = { - from: peerId, - data: uint8ArrayFromString('hello'), - sequenceNumber: randomSeqno(), - topic: 'test-topic' - } - - const bytesToSign = uint8ArrayConcat([SignPrefix, RPC.Message.encode(toRpcMessage(message))]) - - if (peerId.privateKey == null) { - throw new Error('No private key found on PeerId') - } - - const privateKey = await keys.unmarshalPrivateKey(peerId.privateKey) - const expectedSignature = await privateKey.sign(bytesToSign) - - const signedMessage = await signMessage(peerId, message, encodeMessage) - - // Check the signature and public key - expect(signedMessage.signature).to.equalBytes(expectedSignature) - expect(signedMessage.key).to.equalBytes(peerId.publicKey) - - // Verify the signature - const verified = await verifySignature({ - ...signedMessage, - from: peerId - }, encodeMessage) - expect(verified).to.eql(true) - }) - - it('should be able to extract the public key from an inlined key', async () => { - const secPeerId = await PeerIdFactory.createSecp256k1PeerId() - - const message: Message = { - from: secPeerId, - data: uint8ArrayFromString('hello'), - sequenceNumber: randomSeqno(), - topic: 'test-topic' - } - - const bytesToSign = uint8ArrayConcat([SignPrefix, RPC.Message.encode(toRpcMessage(message))]) - - if (secPeerId.privateKey == null) { - throw new Error('No private key found on PeerId') - } - - const privateKey = await keys.unmarshalPrivateKey(secPeerId.privateKey) - const expectedSignature = await privateKey.sign(bytesToSign) - - const signedMessage = await signMessage(secPeerId, message, encodeMessage) - - // Check the signature and public key - expect(signedMessage.signature).to.eql(expectedSignature) - signedMessage.key = undefined - - // Verify the signature - const verified = await verifySignature({ - ...signedMessage, - from: secPeerId - }, encodeMessage) - expect(verified).to.eql(true) - }) - - it('should be able to extract the public key from the message', async () => { - const message: Message = { - from: peerId, - data: uint8ArrayFromString('hello'), - sequenceNumber: randomSeqno(), - topic: 'test-topic' - } - - const bytesToSign = uint8ArrayConcat([SignPrefix, RPC.Message.encode(toRpcMessage(message))]) - - if (peerId.privateKey == null) { - throw new Error('No private key found on PeerId') - } - - const privateKey = await keys.unmarshalPrivateKey(peerId.privateKey) - const expectedSignature = await privateKey.sign(bytesToSign) - - const signedMessage = await signMessage(peerId, message, encodeMessage) - - // Check the signature and public key - expect(signedMessage.signature).to.equalBytes(expectedSignature) - expect(signedMessage.key).to.equalBytes(peerId.publicKey) - - // Verify the signature - const verified = await verifySignature({ - ...signedMessage, - from: peerId - }, encodeMessage) - expect(verified).to.eql(true) - }) -}) diff --git a/packages/libp2p-pubsub/test/topic-validators.spec.ts b/packages/libp2p-pubsub/test/topic-validators.spec.ts deleted file mode 100644 index b48cd2c77..000000000 --- a/packages/libp2p-pubsub/test/topic-validators.spec.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { expect } from 'aegir/chai' -import sinon from 'sinon' -import pWaitFor from 'p-wait-for' -import errCode from 'err-code' -import { createEd25519PeerId } from '@libp2p/peer-id-factory' -import { equals as uint8ArrayEquals } from 'uint8arrays/equals' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import { PeerStreams } from '../src/peer-streams.js' -import { - MockRegistrar, - PubsubImplementation -} from './utils/index.js' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { PubSubRPC } from '@libp2p/interfaces/pubsub' -import { Components } from '@libp2p/interfaces/components' - -const protocol = '/pubsub/1.0.0' - -describe('topic validators', () => { - let pubsub: PubsubImplementation - let peerId: PeerId - let otherPeerId: PeerId - - beforeEach(async () => { - peerId = await createEd25519PeerId() - otherPeerId = await createEd25519PeerId() - - pubsub = new PubsubImplementation({ - multicodecs: [protocol], - globalSignaturePolicy: 'StrictNoSign' - }) - pubsub.init(new Components({ - peerId: peerId, - registrar: new MockRegistrar() - })) - - await pubsub.start() - }) - - afterEach(() => { - sinon.restore() - }) - - it('should filter messages by topic validator', async () => { - // use publishMessage.callCount() to see if a message is valid or not - sinon.spy(pubsub, 'publishMessage') - // @ts-expect-error not all fields are implemented in return value - sinon.stub(pubsub.peers, 'get').returns({}) - const filteredTopic = 't' - const peer = new PeerStreams({ id: otherPeerId, protocol: 'a-protocol' }) - - // Set a trivial topic validator - pubsub.topicValidators.set(filteredTopic, async (topic, message) => { - if (!uint8ArrayEquals(message.data, uint8ArrayFromString('a message'))) { - throw errCode(new Error(), 'ERR_TOPIC_VALIDATOR_REJECT') - } - }) - - // valid case - const validRpc: PubSubRPC = { - subscriptions: [], - messages: [{ - from: otherPeerId.multihash.bytes, - data: uint8ArrayFromString('a message'), - topic: filteredTopic - }] - } - - // process valid message - pubsub.subscribe(filteredTopic) - void pubsub.processRpc(peer.id, peer, validRpc) - - // @ts-expect-error .callCount is a property added by sinon - await pWaitFor(() => pubsub.publishMessage.callCount === 1) - - // invalid case - const invalidRpc = { - subscriptions: [], - messages: [{ - data: uint8ArrayFromString('a different message'), - topic: filteredTopic - }] - } - - void pubsub.processRpc(peer.id, peer, invalidRpc) - - // @ts-expect-error .callCount is a property added by sinon - expect(pubsub.publishMessage.callCount).to.eql(1) - - // remove topic validator - pubsub.topicValidators.delete(filteredTopic) - - // another invalid case - const invalidRpc2: PubSubRPC = { - subscriptions: [], - messages: [{ - from: otherPeerId.multihash.bytes, - data: uint8ArrayFromString('a different message'), - topic: filteredTopic - }] - } - - // process previously invalid message, now is valid - void pubsub.processRpc(peer.id, peer, invalidRpc2) - pubsub.unsubscribe(filteredTopic) - - // @ts-expect-error .callCount is a property added by sinon - await pWaitFor(() => pubsub.publishMessage.callCount === 2) - }) -}) diff --git a/packages/libp2p-pubsub/test/utils.spec.ts b/packages/libp2p-pubsub/test/utils.spec.ts deleted file mode 100644 index 874f1128d..000000000 --- a/packages/libp2p-pubsub/test/utils.spec.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { expect } from 'aegir/chai' -import * as utils from '../src/utils.js' -import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' -import type { Message, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' -import { peerIdFromBytes, peerIdFromString } from '@libp2p/peer-id' - -describe('utils', () => { - it('randomSeqno', () => { - const first = utils.randomSeqno() - const second = utils.randomSeqno() - - expect(first).to.be.a('BigInt') - expect(second).to.be.a('BigInt') - expect(first).to.not.equal(second) - }) - - it('msgId should not generate same ID for two different Uint8Arrays', () => { - const peerId = peerIdFromString('QmPNdSYk5Rfpo5euNqwtyizzmKXMNHdXeLjTQhcN4yfX22') - const msgId0 = utils.msgId(peerId.multihash.bytes, 1n) - const msgId1 = utils.msgId(peerId.multihash.bytes, 2n) - expect(msgId0).to.not.deep.equal(msgId1) - }) - - it('anyMatch', () => { - [ - { a: [1, 2, 3], b: [4, 5, 6], result: false }, - { a: [1, 2], b: [1, 2], result: true }, - { a: [1, 2, 3], b: [4, 5, 1], result: true }, - { a: [5, 6, 1], b: [1, 2, 3], result: true }, - { a: [], b: [], result: false }, - { a: [1], b: [2], result: false } - ].forEach((test) => { - expect(utils.anyMatch(new Set(test.a), new Set(test.b))).to.equal(test.result) - expect(utils.anyMatch(new Set(test.a), test.b)).to.equal(test.result) - }) - }) - - it('ensureArray', () => { - expect(utils.ensureArray('hello')).to.be.eql(['hello']) - expect(utils.ensureArray([1, 2])).to.be.eql([1, 2]) - }) - - it('converts an OUT msg.from to binary', () => { - const binaryId = uint8ArrayFromString('1220e2187eb3e6c4fb3e7ff9ad4658610624a6315e0240fc6f37130eedb661e939cc', 'base16') - const stringId = 'QmdZEWgtaWAxBh93fELFT298La1rsZfhiC2pqwMVwy3jZM' - const m: Message[] = [{ - from: peerIdFromBytes(binaryId), - topic: '', - data: new Uint8Array() - }, { - from: peerIdFromString(stringId), - topic: '', - data: new Uint8Array() - }] - const expected: PubSubRPCMessage[] = [{ - from: binaryId, - topic: '', - data: new Uint8Array(), - sequenceNumber: undefined, - signature: undefined, - key: undefined - }, { - from: binaryId, - topic: '', - data: new Uint8Array(), - sequenceNumber: undefined, - signature: undefined, - key: undefined - }] - for (let i = 0; i < m.length; i++) { - expect(utils.toRpcMessage(m[i])).to.deep.equal(expected[i]) - } - }) - - it('converts non-negative BigInts to bytes and back', () => { - expect(utils.bigIntFromBytes(utils.bigIntToBytes(1n))).to.equal(1n) - - const values = [ - 0n, - 1n, - 100n, - 192832190818383818719287373223131n - ] - - values.forEach(val => { - expect(utils.bigIntFromBytes(utils.bigIntToBytes(val))).to.equal(val) - }) - }) -}) diff --git a/packages/libp2p-pubsub/test/utils/index.ts b/packages/libp2p-pubsub/test/utils/index.ts deleted file mode 100644 index 9c6ea11e5..000000000 --- a/packages/libp2p-pubsub/test/utils/index.ts +++ /dev/null @@ -1,158 +0,0 @@ -import { duplexPair } from 'it-pair/duplex' -import * as PeerIdFactory from '@libp2p/peer-id-factory' -import { PubSubBaseProtocol } from '../../src/index.js' -import { RPC } from '../message/rpc.js' -import type { IncomingStreamData, Registrar, StreamHandler } from '@libp2p/interfaces/registrar' -import type { Topology } from '@libp2p/interfaces/topology' -import type { Connection } from '@libp2p/interfaces/connection' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { PubSubRPC, PubSubRPCMessage } from '@libp2p/interfaces/pubsub' - -export const createPeerId = async (): Promise => { - const peerId = await PeerIdFactory.createEd25519PeerId() - - return peerId -} - -export class PubsubImplementation extends PubSubBaseProtocol { - async publishMessage () { - return { - recipients: [] - } - } - - decodeRpc (bytes: Uint8Array): PubSubRPC { - return RPC.decode(bytes) - } - - encodeRpc (rpc: PubSubRPC): Uint8Array { - return RPC.encode(rpc) - } - - decodeMessage (bytes: Uint8Array): PubSubRPCMessage { - return RPC.Message.decode(bytes) - } - - encodeMessage (rpc: PubSubRPCMessage): Uint8Array { - return RPC.Message.encode(rpc) - } -} - -export class MockRegistrar implements Registrar { - private readonly topologies: Map = new Map() - private readonly handlers: Map = new Map() - - getProtocols () { - const protocols = new Set() - - for (const topology of this.topologies.values()) { - topology.protocols.forEach(protocol => protocols.add(protocol)) - } - - for (const protocol of this.handlers.keys()) { - protocols.add(protocol) - } - - return Array.from(protocols).sort() - } - - async handle (protocols: string | string[], handler: StreamHandler): Promise { - const protocolList = Array.isArray(protocols) ? protocols : [protocols] - - for (const protocol of protocolList) { - if (this.handlers.has(protocol)) { - throw new Error(`Handler already registered for protocol ${protocol}`) - } - - this.handlers.set(protocol, handler) - } - } - - async unhandle (protocols: string | string[]) { - const protocolList = Array.isArray(protocols) ? protocols : [protocols] - - protocolList.forEach(protocol => { - this.handlers.delete(protocol) - }) - } - - getHandler (protocol: string) { - const handler = this.handlers.get(protocol) - - if (handler == null) { - throw new Error(`No handler registered for protocol ${protocol}`) - } - - return handler - } - - async register (protocols: string | string[], topology: Topology) { - if (!Array.isArray(protocols)) { - protocols = [protocols] - } - - const id = `topology-id-${Math.random()}` - - this.topologies.set(id, { - topology, - protocols - }) - - return id - } - - unregister (id: string | string[]) { - if (!Array.isArray(id)) { - id = [id] - } - - id.forEach(id => this.topologies.delete(id)) - } - - getTopologies (protocol: string) { - const output: Topology[] = [] - - for (const { topology, protocols } of this.topologies.values()) { - if (protocols.includes(protocol)) { - output.push(topology) - } - } - - if (output.length > 0) { - return output - } - - throw new Error(`No topologies registered for protocol ${protocol}`) - } -} - -export const ConnectionPair = (): [Connection, Connection] => { - const [d0, d1] = duplexPair() - - return [ - { - // @ts-expect-error incomplete implementation - newStream: async (protocol: string[]) => await Promise.resolve({ - protocol: protocol[0], - stream: d0 - }) - }, - { - // @ts-expect-error incomplete implementation - newStream: async (protocol: string[]) => await Promise.resolve({ - protocol: protocol[0], - stream: d1 - }) - } - ] -} - -export async function mockIncomingStreamEvent (protocol: string, conn: Connection, remotePeer: PeerId): Promise { - return { - ...await conn.newStream([protocol]), - // @ts-expect-error incomplete implementation - connection: { - remotePeer - } - } -} diff --git a/packages/libp2p-pubsub/tsconfig.json b/packages/libp2p-pubsub/tsconfig.json deleted file mode 100644 index 92794a30c..000000000 --- a/packages/libp2p-pubsub/tsconfig.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "extends": "aegir/src/config/tsconfig.aegir.json", - "compilerOptions": { - "outDir": "dist" - }, - "include": [ - "src", - "test" - ], - "exclude": [ - "test/message/rpc.js" - ], - "references": [ - { - "path": "../libp2p-interfaces" - }, - { - "path": "../libp2p-logger" - }, - { - "path": "../libp2p-peer-collections" - }, - { - "path": "../libp2p-peer-id" - }, - { - "path": "../libp2p-peer-id-factory" - }, - { - "path": "../libp2p-topology" - } - ] -} diff --git a/packages/libp2p-topology/CHANGELOG.md b/packages/libp2p-topology/CHANGELOG.md deleted file mode 100644 index fa46745f0..000000000 --- a/packages/libp2p-topology/CHANGELOG.md +++ /dev/null @@ -1,159 +0,0 @@ -## [@libp2p/topology-v1.1.8](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.7...@libp2p/topology-v1.1.8) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/topology-v1.1.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.6...@libp2p/topology-v1.1.7) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/topology-v1.1.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.5...@libp2p/topology-v1.1.6) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/topology-v1.1.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.4...@libp2p/topology-v1.1.5) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/topology-v1.1.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.3...@libp2p/topology-v1.1.4) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/topology-v1.1.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.2...@libp2p/topology-v1.1.3) (2022-02-11) - - -### Bug Fixes - -* simpler topologies ([#164](https://github.com/libp2p/js-libp2p-interfaces/issues/164)) ([45fcaa1](https://github.com/libp2p/js-libp2p-interfaces/commit/45fcaa10a6a3215089340ff2eff117d7fd1100e7)) - -## [@libp2p/topology-v1.1.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.1...@libp2p/topology-v1.1.2) (2022-02-10) - - -### Bug Fixes - -* make registrar simpler ([#163](https://github.com/libp2p/js-libp2p-interfaces/issues/163)) ([d122f3d](https://github.com/libp2p/js-libp2p-interfaces/commit/d122f3daaccc04039d90814960da92b513265644)) - -## [@libp2p/topology-v1.1.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.1.0...@libp2p/topology-v1.1.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## [@libp2p/topology-v1.1.0](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.0.3...@libp2p/topology-v1.1.0) (2022-02-09) - - -### Features - -* add peer store/records, and streams are just streams ([#160](https://github.com/libp2p/js-libp2p-interfaces/issues/160)) ([8860a0c](https://github.com/libp2p/js-libp2p-interfaces/commit/8860a0cd46b359a5648402d83870f7ff957222fe)) - -## [@libp2p/topology-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.0.2...@libp2p/topology-v1.0.3) (2022-01-15) - - -### Trivial Changes - -* update project config ([#149](https://github.com/libp2p/js-libp2p-interfaces/issues/149)) ([6eb8556](https://github.com/libp2p/js-libp2p-interfaces/commit/6eb85562c0da167d222808da10a7914daf12970b)) - -## [@libp2p/topology-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/topology-v1.0.1...@libp2p/topology-v1.0.2) (2022-01-08) - - -### Trivial Changes - -* add semantic release config ([#141](https://github.com/libp2p/js-libp2p-interfaces/issues/141)) ([5f0de59](https://github.com/libp2p/js-libp2p-interfaces/commit/5f0de59136b6343d2411abb2d6a4dd2cd0b7efe4)) -* update package versions ([#140](https://github.com/libp2p/js-libp2p-interfaces/issues/140)) ([cd844f6](https://github.com/libp2p/js-libp2p-interfaces/commit/cd844f6e39f4ee50d006e86eac8dadf696900eb5)) - -# Change Log - -All notable changes to this project will be documented in this file. -See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. - -# 0.2.0 (2022-01-04) - - -### chore - -* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) - - -### Features - -* add auto-publish ([7aede5d](https://github.com/libp2p/js-libp2p-interfaces/commit/7aede5df39ea6b5f243348ec9a212b3e33c16a81)) -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) -* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) -* update package names ([#133](https://github.com/libp2p/js-libp2p-interfaces/issues/133)) ([337adc9](https://github.com/libp2p/js-libp2p-interfaces/commit/337adc9a9bc0278bdae8cbce9c57d07a83c8b5c2)) - - -### BREAKING CHANGES - -* requires node 15+ -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out - - - - - -## [0.3.1](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-topology@0.3.0...libp2p-topology@0.3.1) (2022-01-02) - -**Note:** Version bump only for package libp2p-topology - - - - - -# [0.3.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-topology@0.2.0...libp2p-topology@0.3.0) (2022-01-02) - - -### Features - -* simpler peer id ([#117](https://github.com/libp2p/js-libp2p-interfaces/issues/117)) ([fa2c4f5](https://github.com/libp2p/js-libp2p-interfaces/commit/fa2c4f5be74a5cfc11489771881e57b4e53bf174)) - - - - - -# [0.2.0](https://github.com/libp2p/js-libp2p-interfaces/compare/libp2p-topology@0.1.0...libp2p-topology@0.2.0) (2021-12-02) - - -### chore - -* update libp2p-crypto and peer-id ([c711e8b](https://github.com/libp2p/js-libp2p-interfaces/commit/c711e8bd4d606f6974b13fad2eeb723f93cebb87)) - - -### BREAKING CHANGES - -* requires node 15+ - - - - - -# 0.1.0 (2021-11-22) - - -### Features - -* split out code, convert to typescript ([#111](https://github.com/libp2p/js-libp2p-interfaces/issues/111)) ([e174bba](https://github.com/libp2p/js-libp2p-interfaces/commit/e174bba889388269b806643c79a6b53c8d6a0f8c)), closes [#110](https://github.com/libp2p/js-libp2p-interfaces/issues/110) [#101](https://github.com/libp2p/js-libp2p-interfaces/issues/101) - - -### BREAKING CHANGES - -* not all fields from concrete classes have been added to the interfaces, some adjustment may be necessary as this gets rolled out diff --git a/packages/libp2p-topology/README.md b/packages/libp2p-topology/README.md deleted file mode 100644 index 750efa1ae..000000000 --- a/packages/libp2p-topology/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# libp2p-topology - -> Contains an implementation of the [Topology](https://github.com/libp2p/js-libp2p-interfaces/blob/master/packages/libp2p-interfaces/src/topology/index.ts) interface - -## Table of contents - -- [Usage](#usage) -- [Contribute](#contribute) -- [License](#license) - -## Usage - -```console -npm i libp2p-connection -``` - -```javascript -import { createTopology } from '@libp2p/topology' - -const topology = createTopology({ ... }) -``` - -## Contribute - -The libp2p implementation in JavaScript is a work in progress. As such, there are a few things you can do right now to help out: - - - Go through the modules and **check out existing issues**. This would be especially useful for modules in active development. Some knowledge of IPFS/libp2p may be required, as well as the infrastructure behind it - for instance, you may need to read up on p2p and more complex operations like muxing to be able to help technically. - - **Perform code reviews**. More eyes will help a) speed the project along b) ensure quality and c) reduce possible future bugs. - - **Add tests**. There can never be enough tests. - -## License - -[Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT) © Protocol Labs diff --git a/packages/libp2p-topology/src/index.ts b/packages/libp2p-topology/src/index.ts deleted file mode 100644 index 0351609b7..000000000 --- a/packages/libp2p-topology/src/index.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { symbol } from '@libp2p/interfaces/topology' -import type { PeerId } from '@libp2p/interfaces/peer-id' -import type { Topology, TopologyInit, onConnectHandler, onDisconnectHandler } from '@libp2p/interfaces/topology' -import type { Registrar } from '@libp2p/interfaces/registrar' - -const noop = () => {} - -class TopologyImpl implements Topology { - public min: number - public max: number - - /** - * Set of peers that support the protocol - */ - public peers: Set - public onConnect: onConnectHandler - public onDisconnect: onDisconnectHandler - - protected registrar: Registrar | undefined - - constructor (init: TopologyInit) { - this.min = init.min ?? 0 - this.max = init.max ?? Infinity - this.peers = new Set() - - this.onConnect = init.onConnect ?? noop - this.onDisconnect = init.onDisconnect ?? noop - } - - get [Symbol.toStringTag] () { - return symbol.toString() - } - - get [symbol] () { - return true - } - - async setRegistrar (registrar: Registrar) { - this.registrar = registrar - } - - /** - * Notify about peer disconnected event - */ - disconnect (peerId: PeerId) { - this.onDisconnect(peerId) - } -} - -export function createTopology (init: TopologyInit): Topology { - return new TopologyImpl(init) -} diff --git a/packages/libp2p-tracked-map/CHANGELOG.md b/packages/libp2p-tracked-map/CHANGELOG.md deleted file mode 100644 index d4949fda7..000000000 --- a/packages/libp2p-tracked-map/CHANGELOG.md +++ /dev/null @@ -1,60 +0,0 @@ -## [@libp2p/tracked-map-v1.0.7](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.6...@libp2p/tracked-map-v1.0.7) (2022-05-20) - - -### Bug Fixes - -* update interfaces ([#215](https://github.com/libp2p/js-libp2p-interfaces/issues/215)) ([72e6890](https://github.com/libp2p/js-libp2p-interfaces/commit/72e6890826dadbd6e7cbba5536bde350ca4286e6)) - -## [@libp2p/tracked-map-v1.0.6](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.5...@libp2p/tracked-map-v1.0.6) (2022-05-10) - - -### Trivial Changes - -* **deps:** bump sinon from 13.0.2 to 14.0.0 ([#211](https://github.com/libp2p/js-libp2p-interfaces/issues/211)) ([8859f70](https://github.com/libp2p/js-libp2p-interfaces/commit/8859f70943c0bcdb210f54a338ae901739e5e6f2)) - -## [@libp2p/tracked-map-v1.0.5](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.4...@libp2p/tracked-map-v1.0.5) (2022-04-08) - - -### Bug Fixes - -* swap protobufjs for protons ([#191](https://github.com/libp2p/js-libp2p-interfaces/issues/191)) ([d72b30c](https://github.com/libp2p/js-libp2p-interfaces/commit/d72b30cfca4b9145e0b31db28e8fa3329a180e83)) - - -### Trivial Changes - -* update aegir ([#192](https://github.com/libp2p/js-libp2p-interfaces/issues/192)) ([41c1494](https://github.com/libp2p/js-libp2p-interfaces/commit/41c14941e8b67d6601a90b4d48a2776573d55e60)) - -## [@libp2p/tracked-map-v1.0.4](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.3...@libp2p/tracked-map-v1.0.4) (2022-03-15) - - -### Bug Fixes - -* simplify transport interface, update interfaces for use with libp2p ([#180](https://github.com/libp2p/js-libp2p-interfaces/issues/180)) ([ec81622](https://github.com/libp2p/js-libp2p-interfaces/commit/ec81622e5b7c6d256e0f8aed6d3695642473293b)) - -## [@libp2p/tracked-map-v1.0.3](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.2...@libp2p/tracked-map-v1.0.3) (2022-02-27) - - -### Bug Fixes - -* rename crypto to connection-encrypter ([#179](https://github.com/libp2p/js-libp2p-interfaces/issues/179)) ([d197f55](https://github.com/libp2p/js-libp2p-interfaces/commit/d197f554d7cdadb3b05ed2d6c69fda2c4362b1eb)) - -## [@libp2p/tracked-map-v1.0.2](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.1...@libp2p/tracked-map-v1.0.2) (2022-02-27) - - -### Bug Fixes - -* update package config and add connection gater interface ([#178](https://github.com/libp2p/js-libp2p-interfaces/issues/178)) ([c6079a6](https://github.com/libp2p/js-libp2p-interfaces/commit/c6079a6367f004788062df3e30ad2e26330d947b)) - -## [@libp2p/tracked-map-v1.0.1](https://github.com/libp2p/js-libp2p-interfaces/compare/@libp2p/tracked-map-v1.0.0...@libp2p/tracked-map-v1.0.1) (2022-02-10) - - -### Bug Fixes - -* remove node event emitters ([#161](https://github.com/libp2p/js-libp2p-interfaces/issues/161)) ([221fb6a](https://github.com/libp2p/js-libp2p-interfaces/commit/221fb6a024430dc56288d73d8b8ce1aa88427701)) - -## @libp2p/tracked-map-v1.0.0 (2022-02-05) - - -### Features - -* add tracked-map ([#156](https://github.com/libp2p/js-libp2p-interfaces/issues/156)) ([c17730f](https://github.com/libp2p/js-libp2p-interfaces/commit/c17730f8bca172db85507740eaba81b3cf514d04)) diff --git a/packages/libp2p-tracked-map/README.md b/packages/libp2p-tracked-map/README.md deleted file mode 100644 index 588c13600..000000000 --- a/packages/libp2p-tracked-map/README.md +++ /dev/null @@ -1,44 +0,0 @@ -# libp2p-tracked-map - -> allows tracking metrics in libp2p - -## Table of Contents - -- [Description](#description) -- [Example](#example) -- [Installation](#installation) -- [License](#license) - - [Contribution](#contribution) - -## Description - -A map that reports it's size to the libp2p [Metrics](https://github.com/libp2p/js-libp2p-interfaces/tree/master/packages/libp2p-interfaces/src/metrics#readme) system. - -If metrics are disabled a regular map is used. - -## Example - -```JavaScript -import { trackedMap } from '@libp2p/tracked-map' - -const map = trackedMap({ metrics }) - -map.set('key', 'value') -``` - -## Installation - -```console -$ npm i @libp2p/tracked-map -``` - -## License - -Licensed under either of - - * Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / http://www.apache.org/licenses/LICENSE-2.0) - * MIT ([LICENSE-MIT](LICENSE-MIT) / http://opensource.org/licenses/MIT) - -### Contribution - -Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. diff --git a/packages/libp2p-tracked-map/src/index.ts b/packages/libp2p-tracked-map/src/index.ts deleted file mode 100644 index 0c4d9f448..000000000 --- a/packages/libp2p-tracked-map/src/index.ts +++ /dev/null @@ -1,73 +0,0 @@ -import type { ComponentMetricsTracker } from '@libp2p/interfaces/metrics' - -export interface TrackedMapInit { - metrics: ComponentMetricsTracker - system?: string - component: string - metric: string -} - -class TrackedMap extends Map { - private readonly system: string - private readonly component: string - private readonly metric: string - private readonly metrics: ComponentMetricsTracker - - constructor (init: TrackedMapInit) { - super() - - const { system, component, metric, metrics } = init - this.system = system ?? 'libp2p' - this.component = component - this.metric = metric - this.metrics = metrics - - this.updateComponentMetric() - } - - set (key: K, value: V) { - super.set(key, value) - this.updateComponentMetric() - return this - } - - delete (key: K) { - const deleted = super.delete(key) - this.updateComponentMetric() - return deleted - } - - clear () { - super.clear() - this.updateComponentMetric() - } - - private updateComponentMetric () { - this.metrics.updateComponentMetric({ - system: this.system, - component: this.component, - metric: this.metric, - value: this.size - }) - } -} - -export interface CreateTrackedMapOptions { - metrics?: ComponentMetricsTracker - system?: string - component: string - metric: string -} - -export function trackedMap (config: CreateTrackedMapOptions): Map { - const { system, component, metric, metrics } = config - let map: Map - - if (metrics != null) { - map = new TrackedMap({ system, component, metric, metrics }) - } else { - map = new Map() - } - - return map -} diff --git a/packages/libp2p-tracked-map/test/index.spec.ts b/packages/libp2p-tracked-map/test/index.spec.ts deleted file mode 100644 index 5747c5dde..000000000 --- a/packages/libp2p-tracked-map/test/index.spec.ts +++ /dev/null @@ -1,125 +0,0 @@ -import { expect } from 'aegir/chai' -import { trackedMap } from '../src/index.js' -import sinon from 'sinon' -import type { ComponentMetricsTracker, ComponentMetricsUpdate } from '@libp2p/interfaces/metrics' -import type { SinonStub } from 'sinon' - -describe('tracked-map', () => { - let metrics: ComponentMetricsTracker - let updateComponentMetricStub: SinonStub<[ComponentMetricsUpdate], void> - - beforeEach(() => { - updateComponentMetricStub = sinon.stub() - - metrics = { - updateComponentMetric: updateComponentMetricStub, - getComponentMetrics: sinon.stub() - } - }) - - it('should return a map with metrics', () => { - const system = 'system' - const component = 'component' - const metric = 'metric' - - const map = trackedMap({ - metrics, - system, - component, - metric - }) - - expect(map).to.be.an.instanceOf(Map) - expect(updateComponentMetricStub.calledWith({ - system, - component, - metric, - value: 0 - })).to.be.true() - }) - - it('should return a map without metrics', () => { - const system = 'system' - const component = 'component' - const metric = 'metric' - - const map = trackedMap({ - system, - component, - metric - }) - - expect(map).to.be.an.instanceOf(Map) - expect(updateComponentMetricStub.called).to.be.false() - }) - - it('should default system to libp2p', () => { - const component = 'component' - const metric = 'metric' - - const map = trackedMap({ - metrics, - component, - metric - }) - - expect(map).to.be.an.instanceOf(Map) - expect(updateComponentMetricStub.calledWith({ - system: 'libp2p', - component, - metric, - value: 0 - })).to.be.true() - }) - - it('should track metrics', () => { - const system = 'system' - const component = 'component' - const metric = 'metric' - let value = 0 - let callCount = 0 - - metrics.updateComponentMetric = (data) => { - expect(data.system).to.equal(system) - expect(data.component).to.equal(component) - expect(data.metric).to.equal(metric) - value = data.value - callCount++ - } - - const map = trackedMap({ - metrics, - system, - component, - metric - }) - - expect(map).to.be.an.instanceOf(Map) - expect(callCount).to.equal(1) - - map.set('key1', 'value1') - - expect(value).to.equal(1) - expect(callCount).to.equal(2) - - map.set('key1', 'value2') - - expect(value).to.equal(1) - expect(callCount).to.equal(3) - - map.set('key2', 'value3') - - expect(value).to.equal(2) - expect(callCount).to.equal(4) - - map.delete('key2') - - expect(value).to.equal(1) - expect(callCount).to.equal(5) - - map.clear() - - expect(value).to.equal(0) - expect(callCount).to.equal(6) - }) -})