Skip to content

Commit 3a2d6a0

Browse files
refactor!: remove libp2p.keychain (#2084)
* refactor!: remove libp2p.keychain * chore: remove @libp2p/keychain dep from libp2p * chore: add migration documentation --------- Co-authored-by: Alex Potsides <[email protected]>
1 parent fc8f89b commit 3a2d6a0

File tree

7 files changed

+33
-181
lines changed

7 files changed

+33
-181
lines changed

doc/migrations/v0.46-v1.0.md

+32
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,38 @@ __Describe__
3232
3333
-->
3434

35+
### KeyChain
36+
37+
The KeyChain object is no longer included on Libp2p and must be instantiated explicitly if desired.
38+
39+
**Before**
40+
41+
```ts
42+
import type { KeyChain } from '@libp2p/interface/keychain'
43+
44+
const libp2p = await createLibp2p(...)
45+
46+
const keychain: KeyChain = libp2p.keychain
47+
```
48+
49+
***After***
50+
51+
```ts
52+
import { DefaultKeyChain } from '@libp2p/keychain'
53+
import type { KeyChain } from '@libp2p/interface/keychain'
54+
55+
const libp2p = await createLibp2p({
56+
...
57+
services: {
58+
keychain: (components) => new DefaultKeyChain(components, {
59+
...DefaultKeyChain.generateOptions()
60+
})
61+
}
62+
})
63+
64+
const keychain: KeyChain = libp2p.services.keychain
65+
```
66+
3567
## Module Updates
3668

3769
With this release you should update the following libp2p modules if you are relying on them:

packages/interface/src/index.ts

-15
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import type { Connection, NewStreamOptions, Stream } from './connection/index.js'
1818
import type { ContentRouting } from './content-routing/index.js'
1919
import type { TypedEventTarget } from './events.js'
20-
import type { KeyChain } from './keychain/index.js'
2120
import type { Metrics } from './metrics/index.js'
2221
import type { PeerId } from './peer-id/index.js'
2322
import type { PeerInfo } from './peer-info/index.js'
@@ -372,20 +371,6 @@ export interface Libp2p<T extends ServiceMap = ServiceMap> extends Startable, Ty
372371
*/
373372
contentRouting: ContentRouting
374373

375-
/**
376-
* The keychain contains the keys used by the current node, and can create new
377-
* keys, export them, import them, etc.
378-
*
379-
* @example
380-
*
381-
* ```js
382-
* const keyInfo = await libp2p.keychain.createKey('new key')
383-
* console.info(keyInfo)
384-
* // { id: '...', name: 'new key' }
385-
* ```
386-
*/
387-
keychain: KeyChain
388-
389374
/**
390375
* The metrics subsystem allows recording values to assess the health/performance
391376
* of the running node.

packages/libp2p/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,6 @@
124124
"@libp2p/crypto": "^2.0.6",
125125
"@libp2p/interface": "^0.1.4",
126126
"@libp2p/interface-internal": "^0.1.7",
127-
"@libp2p/keychain": "^3.0.6",
128127
"@libp2p/logger": "^3.0.4",
129128
"@libp2p/multistream-select": "^4.0.4",
130129
"@libp2p/peer-collections": "^4.0.6",

packages/libp2p/src/errors.ts

-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ export enum codes {
4848
ERR_NO_ROUTERS_AVAILABLE = 'ERR_NO_ROUTERS_AVAILABLE',
4949
ERR_CONNECTION_NOT_MULTIPLEXED = 'ERR_CONNECTION_NOT_MULTIPLEXED',
5050
ERR_NO_DIAL_TOKENS = 'ERR_NO_DIAL_TOKENS',
51-
ERR_KEYCHAIN_REQUIRED = 'ERR_KEYCHAIN_REQUIRED',
5251
ERR_INVALID_CMS = 'ERR_INVALID_CMS',
5352
ERR_MISSING_KEYS = 'ERR_MISSING_KEYS',
5453
ERR_NO_KEY = 'ERR_NO_KEY',

packages/libp2p/src/index.ts

-6
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import type { PeerId } from '@libp2p/interface/peer-id'
3030
import type { PeerRouting } from '@libp2p/interface/peer-routing'
3131
import type { StreamMuxerFactory } from '@libp2p/interface/stream-muxer'
3232
import type { Transport } from '@libp2p/interface/transport'
33-
import type { KeyChainInit } from '@libp2p/keychain'
3433
import type { PersistentPeerStoreInit } from '@libp2p/peer-store'
3534
import type { Datastore } from 'interface-datastore'
3635

@@ -79,11 +78,6 @@ export interface Libp2pInit<T extends ServiceMap = { x: Record<string, unknown>
7978
*/
8079
peerStore: PersistentPeerStoreInit
8180

82-
/**
83-
* keychain configuration
84-
*/
85-
keychain: KeyChainInit
86-
8781
/**
8882
* An array that must include at least 1 compliant transport
8983
*/

packages/libp2p/src/libp2p.ts

+1-42
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@ import { CodeError } from '@libp2p/interface/errors'
55
import { TypedEventEmitter, CustomEvent } from '@libp2p/interface/events'
66
import { peerDiscovery } from '@libp2p/interface/peer-discovery'
77
import { type PeerRouting, peerRouting } from '@libp2p/interface/peer-routing'
8-
import { DefaultKeyChain } from '@libp2p/keychain'
98
import { logger } from '@libp2p/logger'
109
import { PeerSet } from '@libp2p/peer-collections'
1110
import { peerIdFromString } from '@libp2p/peer-id'
1211
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
1312
import { PersistentPeerStore } from '@libp2p/peer-store'
1413
import { isMultiaddr, type Multiaddr } from '@multiformats/multiaddr'
1514
import { MemoryDatastore } from 'datastore-core/memory'
16-
import mergeOptions from 'merge-options'
1715
import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
1816
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
1917
import { DefaultAddressManager } from './address-manager/index.js'
@@ -31,14 +29,12 @@ import type { Components } from './components.js'
3129
import type { Libp2p, Libp2pInit, Libp2pOptions } from './index.js'
3230
import type { Libp2pEvents, PendingDial, ServiceMap, AbortOptions } from '@libp2p/interface'
3331
import type { Connection, NewStreamOptions, Stream } from '@libp2p/interface/connection'
34-
import type { KeyChain } from '@libp2p/interface/keychain'
3532
import type { Metrics } from '@libp2p/interface/metrics'
3633
import type { PeerId } from '@libp2p/interface/peer-id'
3734
import type { PeerInfo } from '@libp2p/interface/peer-info'
3835
import type { PeerStore } from '@libp2p/interface/peer-store'
3936
import type { Topology } from '@libp2p/interface/topology'
4037
import type { StreamHandler, StreamHandlerOptions } from '@libp2p/interface-internal/registrar'
41-
import type { Datastore } from 'interface-datastore'
4238

4339
const log = logger('libp2p')
4440

@@ -47,7 +43,6 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
4743
public peerStore: PeerStore
4844
public contentRouting: ContentRouting
4945
public peerRouting: PeerRouting
50-
public keychain: KeyChain
5146
public metrics?: Metrics
5247
public services: T
5348

@@ -133,13 +128,6 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
133128
// Addresses {listen, announce, noAnnounce}
134129
this.configureComponent('addressManager', new DefaultAddressManager(this.components, init.addresses))
135130

136-
// Create keychain
137-
const keychainOpts = DefaultKeyChain.generateOptions()
138-
this.keychain = this.configureComponent('keyChain', new DefaultKeyChain(this.components, {
139-
...keychainOpts,
140-
...init.keychain
141-
}))
142-
143131
// Peer routers
144132
const peerRouters: PeerRouting[] = (init.peerRouters ?? []).map((fn, index) => this.configureComponent(`peer-router-${index}`, fn(this.components)))
145133
this.peerRouting = this.components.peerRouting = this.configureComponent('peerRouting', new DefaultPeerRouting(this.components, {
@@ -222,13 +210,6 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
222210

223211
log('libp2p is starting')
224212

225-
const keys = await this.keychain.listKeys()
226-
227-
if (keys.find(key => key.name === 'self') == null) {
228-
log('importing self key into keychain')
229-
await this.keychain.importPeer('self', this.components.peerId)
230-
}
231-
232213
try {
233214
await this.components.beforeStart?.()
234215
await this.components.start()
@@ -411,29 +392,7 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
411392
* libp2p interface and is useful for testing and debugging.
412393
*/
413394
export async function createLibp2pNode <T extends ServiceMap = Record<string, unknown>> (options: Libp2pOptions<T>): Promise<Libp2pNode<T>> {
414-
if (options.peerId == null) {
415-
const datastore = options.datastore as Datastore | undefined
416-
417-
if (datastore != null) {
418-
try {
419-
// try load the peer id from the keychain
420-
const keyChain = new DefaultKeyChain({
421-
datastore
422-
}, mergeOptions(DefaultKeyChain.generateOptions(), options.keychain))
423-
424-
options.peerId = await keyChain.exportPeerId('self')
425-
} catch (err: any) {
426-
if (err.code !== 'ERR_NOT_FOUND') {
427-
throw err
428-
}
429-
}
430-
}
431-
}
432-
433-
if (options.peerId == null) {
434-
// no peer id in the keychain, create a new peer id
435-
options.peerId = await createEd25519PeerId()
436-
}
395+
options.peerId ??= await createEd25519PeerId()
437396

438397
return new Libp2pNode(validateConfig(options))
439398
}

packages/libp2p/test/core/peer-id.spec.ts

-116
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import { webSockets } from '@libp2p/websockets'
44
import { expect } from 'aegir/chai'
5-
import { MemoryDatastore } from 'datastore-core'
65
import { createLibp2p, type Libp2p } from '../../src/index.js'
76
import { plaintext } from '../../src/insecure/index.js'
87

@@ -27,119 +26,4 @@ describe('peer-id', () => {
2726

2827
expect(libp2p.peerId).to.be.ok()
2928
})
30-
31-
it('should retrieve the PeerId from the datastore', async () => {
32-
const datastore = new MemoryDatastore()
33-
34-
libp2p = await createLibp2p({
35-
datastore,
36-
transports: [
37-
webSockets()
38-
],
39-
connectionEncryption: [
40-
plaintext()
41-
]
42-
})
43-
44-
// this PeerId was created by default
45-
const peerId = libp2p.peerId
46-
47-
await libp2p.stop()
48-
49-
// create a new node from the same datastore
50-
libp2p = await createLibp2p({
51-
datastore,
52-
transports: [
53-
webSockets()
54-
],
55-
connectionEncryption: [
56-
plaintext()
57-
]
58-
})
59-
60-
// the new node should have read the PeerId from the datastore
61-
// instead of creating a new one
62-
expect(libp2p.peerId.toString()).to.equal(peerId.toString())
63-
})
64-
65-
it('should retrieve the PeerId from the datastore with a keychain password', async () => {
66-
const datastore = new MemoryDatastore()
67-
const keychain = {
68-
pass: 'very-long-password-must-be-over-twenty-characters-long',
69-
dek: {
70-
salt: 'CpjNIxMqAZ+aJg+ezLfuzG4a'
71-
}
72-
}
73-
74-
libp2p = await createLibp2p({
75-
datastore,
76-
keychain,
77-
transports: [
78-
webSockets()
79-
],
80-
connectionEncryption: [
81-
plaintext()
82-
]
83-
})
84-
85-
// this PeerId was created by default
86-
const peerId = libp2p.peerId
87-
88-
await libp2p.stop()
89-
90-
// create a new node from the same datastore
91-
libp2p = await createLibp2p({
92-
datastore,
93-
keychain,
94-
transports: [
95-
webSockets()
96-
],
97-
connectionEncryption: [
98-
plaintext()
99-
]
100-
})
101-
102-
// the new node should have read the PeerId from the datastore
103-
// instead of creating a new one
104-
expect(libp2p.peerId.toString()).to.equal(peerId.toString())
105-
})
106-
107-
it('should fail to start if retrieving the PeerId from the datastore fails', async () => {
108-
const datastore = new MemoryDatastore()
109-
const keychain = {
110-
pass: 'very-long-password-must-be-over-twenty-characters-long',
111-
dek: {
112-
salt: 'CpjNIxMqAZ+aJg+ezLfuzG4a'
113-
}
114-
}
115-
116-
libp2p = await createLibp2p({
117-
datastore,
118-
keychain,
119-
transports: [
120-
webSockets()
121-
],
122-
connectionEncryption: [
123-
plaintext()
124-
]
125-
})
126-
await libp2p.stop()
127-
128-
// creating a new node from the same datastore but with the wrong keychain config should fail
129-
await expect(createLibp2p({
130-
datastore,
131-
keychain: {
132-
pass: 'different-very-long-password-must-be-over-twenty-characters-long',
133-
dek: {
134-
salt: 'different-CpjNIxMqAZ+aJg+ezLfuzG4a'
135-
}
136-
},
137-
transports: [
138-
webSockets()
139-
],
140-
connectionEncryption: [
141-
plaintext()
142-
]
143-
})).to.eventually.rejectedWith('Invalid PEM formatted message')
144-
})
14529
})

0 commit comments

Comments
 (0)