From 1836e40b9f4f7eded1c28a5d514b0e7a10d00059 Mon Sep 17 00:00:00 2001 From: Daniel Norman <1992255+2color@users.noreply.github.com> Date: Wed, 23 Oct 2024 16:49:23 +0200 Subject: [PATCH] fix: allow passing cid encoded ipns keys (#117) * fix: allow passing cid encoded ipns keys * fix: handle cid encoded peerid in parse-url-string * chore: remove unused import --------- Co-authored-by: Daniel N <2color@users.noreply.github.com> Co-authored-by: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> --- .../src/utils/parse-url-string.ts | 10 ++++++-- .../test/utils/parse-url-string.spec.ts | 25 +++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/verified-fetch/src/utils/parse-url-string.ts b/packages/verified-fetch/src/utils/parse-url-string.ts index afd1ca80..337fe7b6 100644 --- a/packages/verified-fetch/src/utils/parse-url-string.ts +++ b/packages/verified-fetch/src/utils/parse-url-string.ts @@ -1,4 +1,4 @@ -import { peerIdFromString } from '@libp2p/peer-id' +import { peerIdFromCID, peerIdFromString } from '@libp2p/peer-id' import { CID } from 'multiformats/cid' import { TLRU } from './tlru.js' import type { RequestFormatShorthand } from '../types.js' @@ -177,7 +177,13 @@ export async function parseUrlString ({ urlString, ipns, logger }: ParseUrlStrin let peerId: PeerId | undefined try { // try resolving as an IPNS name - peerId = peerIdFromString(cidOrPeerIdOrDnsLink) + + if (cidOrPeerIdOrDnsLink.charAt(0) === '1' || cidOrPeerIdOrDnsLink.charAt(0) === 'Q') { + peerId = peerIdFromString(cidOrPeerIdOrDnsLink) + } else { + // try resolving as a base36 CID + peerId = peerIdFromCID(CID.parse(cidOrPeerIdOrDnsLink)) + } if (peerId.publicKey == null) { throw new TypeError('cidOrPeerIdOrDnsLink contains no public key') } diff --git a/packages/verified-fetch/test/utils/parse-url-string.spec.ts b/packages/verified-fetch/test/utils/parse-url-string.spec.ts index 54edfcf6..5e7d588b 100644 --- a/packages/verified-fetch/test/utils/parse-url-string.spec.ts +++ b/packages/verified-fetch/test/utils/parse-url-string.spec.ts @@ -4,6 +4,7 @@ import { defaultLogger } from '@libp2p/logger' import { peerIdFromPrivateKey } from '@libp2p/peer-id' import { type Answer } from '@multiformats/dns' import { expect } from 'aegir/chai' +import { base36 } from 'multiformats/bases/base36' import { CID } from 'multiformats/cid' import { match } from 'sinon' import { stubInterface } from 'sinon-ts' @@ -76,7 +77,7 @@ describe('parseUrlString', () => { ipns, logger }) - ).to.eventually.be.rejected.with.property('message', 'Could not parse PeerId in ipns url "mydomain.com", Please pass a multibase decoder for strings that do not start with "1" or "Q"') + ).to.eventually.be.rejected.with.property('message', 'Could not parse PeerId in ipns url "mydomain.com", To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided') }) }) @@ -161,7 +162,7 @@ describe('parseUrlString', () => { await expect(parseUrlString({ urlString: 'ipns://mydomain.com', ipns, logger })).to.eventually.be.rejected .with.property('errors').that.deep.equals([ - new TypeError('Could not parse PeerId in ipns url "mydomain.com", Please pass a multibase decoder for strings that do not start with "1" or "Q"'), + new TypeError('Could not parse PeerId in ipns url "mydomain.com", To parse non base32, base36 or base58btc encoded CID multibase decoder must be provided'), new Error('Unexpected failure from ipns dns query') ]) }) @@ -459,10 +460,13 @@ describe('parseUrlString', () => { describe('ipns:// URLs', () => { let testPeerId: PeerId + let base36CidPeerId: string beforeEach(async () => { const key = await generateKeyPair('Ed25519') testPeerId = peerIdFromPrivateKey(key) + + base36CidPeerId = key.publicKey.toCID().toString(base36) }) it('handles invalid PeerIds', async () => { @@ -504,6 +508,23 @@ describe('parseUrlString', () => { ) }) + it('can parse a base36 PeerId CID', async () => { + ipns.resolve.withArgs(matchPeerId(testPeerId)).resolves({ + cid: CID.parse('QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr'), + path: '', + record: ipnsRecordStub({ peerId: testPeerId }) + }) + + await assertMatchUrl( + `ipns://${base36CidPeerId}`, { + protocol: 'ipns', + cid: 'QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr', + path: '', + query: {} + } + ) + }) + it('can parse a URL with PeerId+path', async () => { ipns.resolve.withArgs(matchPeerId(testPeerId)).resolves({ cid: CID.parse('QmQJ8fxavY54CUsxMSx9aE9Rdcmvhx8awJK2jzJp4iAqCr'),