From 147304449e5f8d3acb8b00bdd9588b56830667c6 Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Thu, 14 Apr 2022 18:00:21 +0100 Subject: [PATCH] fix: expose getPublicKey (#1188) This is used externally by IPFS so expose the method --- src/dialer/index.ts | 3 -- src/index.ts | 6 +++ src/libp2p.ts | 8 +++- test/core/get-public-key.spec.ts | 78 ++++++++++++++++++++++++++++++++ 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 test/core/get-public-key.spec.ts diff --git a/src/dialer/index.ts b/src/dialer/index.ts index 30dc731e..a0352fd6 100644 --- a/src/dialer/index.ts +++ b/src/dialer/index.ts @@ -244,9 +244,6 @@ export class DefaultDialer implements Dialer, Startable { const addrs: Multiaddr[] = [] for (const a of knownAddrs) { const resolvedAddrs = await this._resolve(a) - - log('resolved %s to %s', a, resolvedAddrs) - resolvedAddrs.forEach(ra => addrs.push(ra)) } diff --git a/src/index.ts b/src/index.ts index d64bb224..7196ba3f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -223,6 +223,12 @@ export interface Libp2p extends Startable, EventEmitter { * Sends a request to fetch the value associated with the given key from the given peer. */ fetch: (peer: PeerId | Multiaddr | string, key: string) => Promise + + /** + * Returns the public key for the passed PeerId. If the PeerId is of the 'RSA' type + * this may mean searching the DHT if the key is not present in the KeyStore. + */ + getPublicKey: (peer: PeerId, options?: AbortOptions) => Promise } export type Libp2pOptions = RecursivePartial diff --git a/src/libp2p.ts b/src/libp2p.ts index 62f412bf..c26dc0ac 100644 --- a/src/libp2p.ts +++ b/src/libp2p.ts @@ -412,9 +412,13 @@ export class Libp2pNode extends EventEmitter implements Libp2p { /** * Get the public key for the given peer id */ - async getPublicKey (peer: PeerId, options: AbortOptions = {}) { + async getPublicKey (peer: PeerId, options: AbortOptions = {}): Promise { log('getPublicKey %p', peer) + if (peer.publicKey != null) { + return peer.publicKey + } + const peerInfo = await this.peerStore.get(peer) if (peerInfo.pubKey != null) { @@ -437,7 +441,7 @@ export class Libp2pNode extends EventEmitter implements Libp2p { await this.peerStore.keyBook.set(peer, event.value) - return key + return key.bytes } } diff --git a/test/core/get-public-key.spec.ts b/test/core/get-public-key.spec.ts new file mode 100644 index 00000000..c72f695d --- /dev/null +++ b/test/core/get-public-key.spec.ts @@ -0,0 +1,78 @@ +/* eslint-env mocha */ + +import { expect } from 'aegir/chai' +import { WebSockets } from '@libp2p/websockets' +import { NOISE } from '@chainsafe/libp2p-noise' +import { createPeerId } from '../utils/creators/peer.js' +import { createLibp2pNode, Libp2pNode } from '../../src/libp2p.js' +import type { Libp2pOptions } from '../../src/index.js' +import sinon from 'sinon' +import { KadDHT } from '@libp2p/kad-dht' + +describe('getPublicKey', () => { + let libp2p: Libp2pNode + + beforeEach(async () => { + const peerId = await createPeerId() + const config: Libp2pOptions = { + peerId, + transports: [ + new WebSockets() + ], + connectionEncryption: [ + NOISE + ], + dht: new KadDHT() + } + libp2p = await createLibp2pNode(config) + + await libp2p.start() + }) + + afterEach(async () => { + await libp2p.stop() + }) + + it('should extract embedded public key', async () => { + const otherPeer = await createPeerId() + + const key = await libp2p.getPublicKey(otherPeer) + + expect(otherPeer.publicKey).to.equalBytes(key) + }) + + it('should get key from the keystore', async () => { + const otherPeer = await createPeerId({ opts: { type: 'rsa' } }) + + if (otherPeer.publicKey == null) { + throw new Error('Public key was missing') + } + + await libp2p.peerStore.keyBook.set(otherPeer, otherPeer.publicKey) + + const key = await libp2p.getPublicKey(otherPeer) + + expect(otherPeer.publicKey).to.equalBytes(key) + }) + + it('should query the DHT when the key is not in the keystore', async () => { + const otherPeer = await createPeerId({ opts: { type: 'rsa' } }) + + if (otherPeer.publicKey == null) { + throw new Error('Public key was missing') + } + + if (libp2p.dht == null) { + throw new Error('DHT was not configured') + } + + libp2p.dht.get = sinon.stub().returns([{ + name: 'VALUE', + value: otherPeer.publicKey + }]) + + const key = await libp2p.getPublicKey(otherPeer) + + expect(otherPeer.publicKey).to.equalBytes(key) + }) +})