Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add private key to libp2p components #2348

Merged
merged 4 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/libp2p/src/components.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { CodeError } from '@libp2p/interface'
import { isStartable, type Startable, type Libp2pEvents, type ComponentLogger, type NodeInfo, type ConnectionProtector, type ConnectionGater, type ContentRouting, type TypedEventTarget, type Metrics, type PeerId, type PeerRouting, type PeerStore, type Upgrader } from '@libp2p/interface'
import { isStartable, type Startable, type Libp2pEvents, type ComponentLogger, type NodeInfo, type ConnectionProtector, type ConnectionGater, type ContentRouting, type TypedEventTarget, type Metrics, type PeerId, type PeerRouting, type PeerStore, type PrivateKey, type Upgrader } from '@libp2p/interface'
import { defaultLogger } from '@libp2p/logger'
import type { AddressManager, ConnectionManager, Registrar, TransportManager } from '@libp2p/interface-internal'
import type { Datastore } from 'interface-datastore'

export interface Components extends Record<string, any>, Startable {
peerId: PeerId
privateKey: PrivateKey
nodeInfo: NodeInfo
logger: ComponentLogger
events: TypedEventTarget<Libp2pEvents>
Expand All @@ -25,6 +26,7 @@ export interface Components extends Record<string, any>, Startable {

export interface ComponentsInit {
peerId?: PeerId
privateKey?: PrivateKey
nodeInfo?: NodeInfo
logger?: ComponentLogger
events?: TypedEventTarget<Libp2pEvents>
Expand Down
7 changes: 6 additions & 1 deletion packages/libp2p/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CodeError, FaultTolerance } from '@libp2p/interface'
import { peerIdFromKeys } from '@libp2p/peer-id'
import { defaultAddressSort } from '@libp2p/utils/address-sort'
import { dnsaddrResolver } from '@multiformats/multiaddr/resolvers'
import mergeOptions from 'merge-options'
Expand All @@ -25,12 +26,16 @@ const DefaultConfig: Partial<Libp2pInit> = {
}
}

export function validateConfig <T extends ServiceMap = Record<string, unknown>> (opts: RecursivePartial<Libp2pInit<T>>): Libp2pInit<T> {
export async function validateConfig <T extends ServiceMap = Record<string, unknown>> (opts: RecursivePartial<Libp2pInit<T>>): Promise<Libp2pInit<T>> {
const resultingOptions: Libp2pInit<T> = mergeOptions(DefaultConfig, opts)

if (resultingOptions.connectionProtector === null && globalThis.process?.env?.LIBP2P_FORCE_PNET != null) { // eslint-disable-line no-undef
throw new CodeError(messages.ERR_PROTECTOR_REQUIRED, codes.ERR_PROTECTOR_REQUIRED)
}

if (!(await peerIdFromKeys(resultingOptions.privateKey.public.bytes, resultingOptions.privateKey.bytes)).equals(resultingOptions.peerId)) {
throw new CodeError('Private key doesn\'t match peer id', codes.ERR_INVALID_KEY)
}

return resultingOptions
}
7 changes: 6 additions & 1 deletion packages/libp2p/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { AddressManagerInit } from './address-manager/index.js'
import type { Components } from './components.js'
import type { ConnectionManagerInit } from './connection-manager/index.js'
import type { TransportManagerInit } from './transport-manager.js'
import type { Libp2p, ServiceMap, RecursivePartial, ComponentLogger, NodeInfo, ConnectionProtector, ConnectionEncrypter, ConnectionGater, ContentRouting, Metrics, PeerDiscovery, PeerId, PeerRouting, StreamMuxerFactory, Transport } from '@libp2p/interface'
import type { Libp2p, ServiceMap, RecursivePartial, ComponentLogger, NodeInfo, ConnectionProtector, ConnectionEncrypter, ConnectionGater, ContentRouting, Metrics, PeerDiscovery, PeerId, PeerRouting, StreamMuxerFactory, Transport, PrivateKey } from '@libp2p/interface'
import type { PersistentPeerStoreInit } from '@libp2p/peer-store'
import type { Datastore } from 'interface-datastore'

Expand All @@ -36,6 +36,11 @@ export interface Libp2pInit<T extends ServiceMap = { x: Record<string, unknown>
*/
peerId: PeerId

/**
* Private key associated with the peerId
*/
privateKey: PrivateKey

/**
* Metadata about the node - implementation name, version number, etc
*/
Expand Down
13 changes: 10 additions & 3 deletions packages/libp2p/src/libp2p.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { unmarshalPublicKey } from '@libp2p/crypto/keys'
import { unmarshalPrivateKey, unmarshalPublicKey } from '@libp2p/crypto/keys'
import { contentRoutingSymbol, CodeError, TypedEventEmitter, CustomEvent, setMaxListeners, peerDiscoverySymbol, peerRoutingSymbol } from '@libp2p/interface'
import { defaultLogger } from '@libp2p/logger'
import { PeerSet } from '@libp2p/peer-collections'
Expand Down Expand Up @@ -67,6 +67,7 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
this.services = {}
const components = this.components = defaultComponents({
peerId: init.peerId,
privateKey: init.privateKey,
nodeInfo: init.nodeInfo ?? {
name: pkg.name,
version: pkg.version
Expand Down Expand Up @@ -397,7 +398,13 @@ export class Libp2pNode<T extends ServiceMap = Record<string, unknown>> extends
* libp2p interface and is useful for testing and debugging.
*/
export async function createLibp2pNode <T extends ServiceMap = Record<string, unknown>> (options: Libp2pOptions<T> = {}): Promise<Libp2pNode<T>> {
options.peerId ??= await createEd25519PeerId()
const peerId = options.peerId ??= await createEd25519PeerId()

return new Libp2pNode(validateConfig(options))
if (peerId.privateKey == null) {
throw new CodeError('peer id was missing private key', 'ERR_MISSING_PRIVATE_KEY')
}

options.privateKey ??= await unmarshalPrivateKey(peerId.privateKey as Uint8Array)

return new Libp2pNode(await validateConfig(options))
}