diff --git a/packages/ipns/src/dnslink.ts b/packages/ipns/src/dnslink.ts index 8ccf9ce6..48f34cab 100644 --- a/packages/ipns/src/dnslink.ts +++ b/packages/ipns/src/dnslink.ts @@ -1,10 +1,10 @@ import { } from '@libp2p/interface' -import { peerIdFromString } from '@libp2p/peer-id' +import { peerIdFromCID, peerIdFromString } from '@libp2p/peer-id' import { RecordType } from '@multiformats/dns' import { CID } from 'multiformats/cid' import { DNSLinkNotFoundError } from './errors.js' import type { ResolveDNSLinkOptions } from './index.js' -import type { Logger } from '@libp2p/interface' +import type { Logger, PeerId } from '@libp2p/interface' import type { Answer, DNS } from '@multiformats/dns' const MAX_RECURSIVE_DEPTH = 32 @@ -66,7 +66,15 @@ async function recursiveResolveDnslink (domain: string, depth: number, dns: DNS, } catch {} } else if (protocol === 'ipns') { try { - const peerId = peerIdFromString(domainOrCID) + let peerId: PeerId + + // eslint-disable-next-line max-depth + if (domainOrCID.charAt(0) === '1' || domainOrCID.charAt(0) === 'Q') { + peerId = peerIdFromString(domainOrCID) + } else { + // try parsing as a CID + peerId = peerIdFromCID(CID.parse(domainOrCID)) + } // if the result is a PeerId, we've reached the end of the recursion return { diff --git a/packages/ipns/test/resolve-dnslink.spec.ts b/packages/ipns/test/resolve-dnslink.spec.ts index 588a37f0..bc5e1902 100644 --- a/packages/ipns/test/resolve-dnslink.spec.ts +++ b/packages/ipns/test/resolve-dnslink.spec.ts @@ -7,6 +7,7 @@ import { peerIdFromPrivateKey } from '@libp2p/peer-id' import { RecordType } from '@multiformats/dns' import { expect } from 'aegir/chai' import { MemoryDatastore } from 'datastore-core' +import { base36 } from 'multiformats/bases/base36' import { CID } from 'multiformats/cid' import { stubInterface } from 'sinon-ts' import { ipns } from '../src/index.js' @@ -172,6 +173,30 @@ describe('resolveDNSLink', () => { expect(result.path).to.equal('foobar/path/123') }) + it('should resolve recursive dnslink -> /', async () => { + const cid = CID.parse('QmUNLLsPACCz1vLxQVkXqqLX5R1X345qqfHbsf67hvA3Nn') + const key = await generateKeyPair('Ed25519') + const peerId = peerIdFromPrivateKey(key) + const peerIdBase36CID = peerId.toCID().toString(base36) + dns.query.withArgs('_dnslink.foobar.baz').resolves(dnsResponse([{ + name: 'foobar.baz.', + TTL: 60, + type: RecordType.TXT, + data: `dnslink=/ipns/${peerIdBase36CID}/foobar/path/123` + }])) + + await name.publish(key, cid) + + const result = await name.resolveDNSLink('foobar.baz') + + if (result == null) { + throw new Error('Did not resolve entry') + } + + expect(result.cid.toString()).to.equal(cid.toV1().toString()) + expect(result.path).to.equal('foobar/path/123') + }) + it('should follow CNAMES to delegated DNSLink domains', async () => { const cid = CID.parse('bafybeifcaqowoyito3qvsmbwbiugsu4umlxn4ehu223hvtubbfvwyuxjoe') const key = await generateKeyPair('Ed25519')