diff --git a/doc/migrations/v0.46-v1.0.md b/doc/migrations/v0.46-v1.0.md index 184b266cf0..420048289a 100644 --- a/doc/migrations/v0.46-v1.0.md +++ b/doc/migrations/v0.46-v1.0.md @@ -32,6 +32,38 @@ __Describe__ --> +### KeyChain + +The KeyChain object is no longer included on Libp2p and must be instantiated explicitly if desired. + +**Before** + +```ts +import type { KeyChain } from '@libp2p/interface/keychain' + +const libp2p = await createLibp2p(...) + +const keychain: KeyChain = libp2p.keychain +``` + +***After*** + +```ts +import { DefaultKeyChain } from '@libp2p/keychain' +import type { KeyChain } from '@libp2p/interface/keychain' + +const libp2p = await createLibp2p({ + ... + services: { + keychain: (components) => new DefaultKeyChain(components, { + ...DefaultKeyChain.generateOptions() + }) + } +}) + +const keychain: KeyChain = libp2p.services.keychain +``` + ## Module Updates With this release you should update the following libp2p modules if you are relying on them: diff --git a/packages/interface/src/index.ts b/packages/interface/src/index.ts index 0dd02078f8..f9c6d87503 100644 --- a/packages/interface/src/index.ts +++ b/packages/interface/src/index.ts @@ -17,7 +17,6 @@ import type { Connection, NewStreamOptions, Stream } from './connection/index.js' import type { ContentRouting } from './content-routing/index.js' import type { EventEmitter } from './events.js' -import type { KeyChain } from './keychain/index.js' import type { Metrics } from './metrics/index.js' import type { PeerId } from './peer-id/index.js' import type { PeerInfo } from './peer-info/index.js' @@ -372,20 +371,6 @@ export interface Libp2p extends Startable, Ev */ contentRouting: ContentRouting - /** - * The keychain contains the keys used by the current node, and can create new - * keys, export them, import them, etc. - * - * @example - * - * ```js - * const keyInfo = await libp2p.keychain.createKey('new key') - * console.info(keyInfo) - * // { id: '...', name: 'new key' } - * ``` - */ - keychain: KeyChain - /** * The metrics subsystem allows recording values to assess the health/performance * of the running node. diff --git a/packages/libp2p/package.json b/packages/libp2p/package.json index 14ec1b4da7..1208236b26 100644 --- a/packages/libp2p/package.json +++ b/packages/libp2p/package.json @@ -124,7 +124,6 @@ "@libp2p/crypto": "^2.0.5", "@libp2p/interface": "^0.1.3", "@libp2p/interface-internal": "^0.1.6", - "@libp2p/keychain": "^3.0.5", "@libp2p/logger": "^3.0.3", "@libp2p/multistream-select": "^4.0.3", "@libp2p/peer-collections": "^4.0.5", diff --git a/packages/libp2p/src/errors.ts b/packages/libp2p/src/errors.ts index a2d2ffb6c6..a895c1b5b2 100644 --- a/packages/libp2p/src/errors.ts +++ b/packages/libp2p/src/errors.ts @@ -48,7 +48,6 @@ export enum codes { ERR_NO_ROUTERS_AVAILABLE = 'ERR_NO_ROUTERS_AVAILABLE', ERR_CONNECTION_NOT_MULTIPLEXED = 'ERR_CONNECTION_NOT_MULTIPLEXED', ERR_NO_DIAL_TOKENS = 'ERR_NO_DIAL_TOKENS', - ERR_KEYCHAIN_REQUIRED = 'ERR_KEYCHAIN_REQUIRED', ERR_INVALID_CMS = 'ERR_INVALID_CMS', ERR_MISSING_KEYS = 'ERR_MISSING_KEYS', ERR_NO_KEY = 'ERR_NO_KEY', diff --git a/packages/libp2p/src/index.ts b/packages/libp2p/src/index.ts index 8fa5882135..b83ee40512 100644 --- a/packages/libp2p/src/index.ts +++ b/packages/libp2p/src/index.ts @@ -30,7 +30,6 @@ import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerRouting } from '@libp2p/interface/peer-routing' import type { StreamMuxerFactory } from '@libp2p/interface/stream-muxer' import type { Transport } from '@libp2p/interface/transport' -import type { KeyChainInit } from '@libp2p/keychain' import type { PersistentPeerStoreInit } from '@libp2p/peer-store' import type { Datastore } from 'interface-datastore' @@ -79,11 +78,6 @@ export interface Libp2pInit */ peerStore: PersistentPeerStoreInit - /** - * keychain configuration - */ - keychain: KeyChainInit - /** * An array that must include at least 1 compliant transport */ diff --git a/packages/libp2p/src/libp2p.ts b/packages/libp2p/src/libp2p.ts index 29c80f0cc7..3cf608d06d 100644 --- a/packages/libp2p/src/libp2p.ts +++ b/packages/libp2p/src/libp2p.ts @@ -5,7 +5,6 @@ import { CodeError } from '@libp2p/interface/errors' import { EventEmitter, CustomEvent } from '@libp2p/interface/events' import { peerDiscovery } from '@libp2p/interface/peer-discovery' import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing' -import { DefaultKeyChain } from '@libp2p/keychain' import { logger } from '@libp2p/logger' import { PeerSet } from '@libp2p/peer-collections' import { peerIdFromString } from '@libp2p/peer-id' @@ -13,7 +12,6 @@ import { createEd25519PeerId } from '@libp2p/peer-id-factory' import { PersistentPeerStore } from '@libp2p/peer-store' import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr' import { MemoryDatastore } from 'datastore-core/memory' -import mergeOptions from 'merge-options' import { concat as uint8ArrayConcat } from 'uint8arrays/concat' import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string' import { DefaultAddressManager } from './address-manager/index.js' @@ -31,14 +29,12 @@ import type { Components } from './components.js' import type { Libp2p, Libp2pInit, Libp2pOptions } from './index.js' import type { Libp2pEvents, PendingDial, ServiceMap, AbortOptions } from '@libp2p/interface' import type { Connection, NewStreamOptions, Stream } from '@libp2p/interface/connection' -import type { KeyChain } from '@libp2p/interface/keychain' import type { Metrics } from '@libp2p/interface/metrics' import type { PeerId } from '@libp2p/interface/peer-id' import type { PeerInfo } from '@libp2p/interface/peer-info' import type { PeerStore } from '@libp2p/interface/peer-store' import type { Topology } from '@libp2p/interface/topology' import type { StreamHandler, StreamHandlerOptions } from '@libp2p/interface-internal/registrar' -import type { Datastore } from 'interface-datastore' const log = logger('libp2p') @@ -47,7 +43,6 @@ export class Libp2pNode> extends public peerStore: PeerStore public contentRouting: ContentRouting public peerRouting: PeerRouting - public keychain: KeyChain public metrics?: Metrics public services: T @@ -133,13 +128,6 @@ export class Libp2pNode> extends // Addresses {listen, announce, noAnnounce} this.configureComponent('addressManager', new DefaultAddressManager(this.components, init.addresses)) - // Create keychain - const keychainOpts = DefaultKeyChain.generateOptions() - this.keychain = this.configureComponent('keyChain', new DefaultKeyChain(this.components, { - ...keychainOpts, - ...init.keychain - })) - // Peer routers const peerRouters: PeerRouting[] = (init.peerRouters ?? []).map((fn, index) => this.configureComponent(`peer-router-${index}`, fn(this.components))) this.peerRouting = this.components.peerRouting = this.configureComponent('peerRouting', new DefaultPeerRouting(this.components, { @@ -222,13 +210,6 @@ export class Libp2pNode> extends log('libp2p is starting') - const keys = await this.keychain.listKeys() - - if (keys.find(key => key.name === 'self') == null) { - log('importing self key into keychain') - await this.keychain.importPeer('self', this.components.peerId) - } - try { await this.components.beforeStart?.() await this.components.start() @@ -411,29 +392,7 @@ export class Libp2pNode> extends * libp2p interface and is useful for testing and debugging. */ export async function createLibp2pNode > (options: Libp2pOptions): Promise> { - if (options.peerId == null) { - const datastore = options.datastore as Datastore | undefined - - if (datastore != null) { - try { - // try load the peer id from the keychain - const keyChain = new DefaultKeyChain({ - datastore - }, mergeOptions(DefaultKeyChain.generateOptions(), options.keychain)) - - options.peerId = await keyChain.exportPeerId('self') - } catch (err: any) { - if (err.code !== 'ERR_NOT_FOUND') { - throw err - } - } - } - } - - if (options.peerId == null) { - // no peer id in the keychain, create a new peer id - options.peerId = await createEd25519PeerId() - } + options.peerId ??= await createEd25519PeerId() return new Libp2pNode(validateConfig(options)) } diff --git a/packages/libp2p/test/core/peer-id.spec.ts b/packages/libp2p/test/core/peer-id.spec.ts index 663610c6a4..220a9fbe16 100644 --- a/packages/libp2p/test/core/peer-id.spec.ts +++ b/packages/libp2p/test/core/peer-id.spec.ts @@ -2,7 +2,6 @@ import { webSockets } from '@libp2p/websockets' import { expect } from 'aegir/chai' -import { MemoryDatastore } from 'datastore-core' import { createLibp2p, type Libp2p } from '../../src/index.js' import { plaintext } from '../../src/insecure/index.js' @@ -27,119 +26,4 @@ describe('peer-id', () => { expect(libp2p.peerId).to.be.ok() }) - - it('should retrieve the PeerId from the datastore', async () => { - const datastore = new MemoryDatastore() - - libp2p = await createLibp2p({ - datastore, - transports: [ - webSockets() - ], - connectionEncryption: [ - plaintext() - ] - }) - - // this PeerId was created by default - const peerId = libp2p.peerId - - await libp2p.stop() - - // create a new node from the same datastore - libp2p = await createLibp2p({ - datastore, - transports: [ - webSockets() - ], - connectionEncryption: [ - plaintext() - ] - }) - - // the new node should have read the PeerId from the datastore - // instead of creating a new one - expect(libp2p.peerId.toString()).to.equal(peerId.toString()) - }) - - it('should retrieve the PeerId from the datastore with a keychain password', async () => { - const datastore = new MemoryDatastore() - const keychain = { - pass: 'very-long-password-must-be-over-twenty-characters-long', - dek: { - salt: 'CpjNIxMqAZ+aJg+ezLfuzG4a' - } - } - - libp2p = await createLibp2p({ - datastore, - keychain, - transports: [ - webSockets() - ], - connectionEncryption: [ - plaintext() - ] - }) - - // this PeerId was created by default - const peerId = libp2p.peerId - - await libp2p.stop() - - // create a new node from the same datastore - libp2p = await createLibp2p({ - datastore, - keychain, - transports: [ - webSockets() - ], - connectionEncryption: [ - plaintext() - ] - }) - - // the new node should have read the PeerId from the datastore - // instead of creating a new one - expect(libp2p.peerId.toString()).to.equal(peerId.toString()) - }) - - it('should fail to start if retrieving the PeerId from the datastore fails', async () => { - const datastore = new MemoryDatastore() - const keychain = { - pass: 'very-long-password-must-be-over-twenty-characters-long', - dek: { - salt: 'CpjNIxMqAZ+aJg+ezLfuzG4a' - } - } - - libp2p = await createLibp2p({ - datastore, - keychain, - transports: [ - webSockets() - ], - connectionEncryption: [ - plaintext() - ] - }) - await libp2p.stop() - - // creating a new node from the same datastore but with the wrong keychain config should fail - await expect(createLibp2p({ - datastore, - keychain: { - pass: 'different-very-long-password-must-be-over-twenty-characters-long', - dek: { - salt: 'different-CpjNIxMqAZ+aJg+ezLfuzG4a' - } - }, - transports: [ - webSockets() - ], - connectionEncryption: [ - plaintext() - ] - })).to.eventually.rejectedWith('Invalid PEM formatted message') - }) })