ipfs / ipfs/helia

@helia/ipns: fetch cold IPNS-over-pubsub records from rendezvous-CID providers instead of waiting for subscription-change?

Open
#1,082 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1.3k
Forks
159
Avg merge
2h 11m
Merged PRs (30d)
16

Description

### Package

`@helia/ipns` (`packages/ipns`), current npm `9.2.1`

### Context

Since #906, `PubSubRouting` can fetch an IPNS record over the `libp2p/fetch` protocol instead of only waiting for a gossipsub push. That's great. But `get()` today only fetches from peers gossipsub *already* reports as subscribers:

```js
for (const peerId of this.libp2p.services.pubsub.getSubscribers(topic)) {
promises.push(this.#fetchFromPeer(topic, routingKey, peerId, ...))
}
if (promises.length > 0) { /* Promise.any */ }
throw new NotFoundError('Pubsub routing does not actively query peers')
```

On a cold resolve, `getSubscribers(topic)` is empty, so `get()` throws immediately. The record only becomes fetchable after the topic's peers re-announce via a `subscription-change` event (the `#fetchFromPeer` triggered from the `subscription-change` listener). In practice that adds a real latency floor before the first fetch can happen, even though the publisher (kubo's go-libp2p-pubsub-router, or another Helia via `registerLookupFunction`) will answer a `libp2p/fetch` request for the record regardless of the subscription handshake.

### Idea

IPNS-over-pubsub publishers announce themselves as **providers of the topic's rendezvous CID** — the standard go-libp2p-pubsub discovery key, `CID(sha256("floodsub:" + topic))`. So on a cold `get()`, in parallel with the existing subscriber-fetch, `PubSubRouting` could:

1. `contentRouting.findProviders(rendezvousCidForTopic(topic))`
2. dial each discovered provider
3. `fetch(peerId, routingKey)` the moment the dial completes

First signature-valid record wins; losers get aborted. This skips the wait for `subscription-change` entirely and reuses the exact `libp2p/fetch` path #906 added — it just sources candidate peers from content routing instead of waiting for gossipsub to confirm them.

We've implemented exactly this downstream (fetch in parallel from both current subscribers *and* freshly-discovered providers of the rendezvous CID, first valid record wins) and it reliably resolves cold IPNS names well under the subscription-wait floor, then falls back to the existing path on a miss.

### Question

Does this belong in `@helia/ipns` `PubSubRouting` itself, or is it better kept as downstream orchestration around the router?

Reasons it might fit upstream:
- The rendezvous CID (`floodsub:` → sha256 → CID) is a standard libp2p-pubsub discovery key, not app-specific.
- It reuses the fetch path from #906 verbatim; only the peer-sourcing changes.
- Every Helia-over-pubsub consumer would get faster cold resolves.

Reasons it might not:
- `get()` currently never actively queries the network ("Pubsub routing does not actively query peers") — provider discovery + dialing is a deliberate behavior/cost change and may warrant an opt-in (e.g. an init flag).
- It introduces a `contentRouting` dependency and dial amplification into a router that today only listens.

If you'd welcome it upstream I'm happy to open a PR (likely gated behind an init option, defaulting off). Wanted to check direction before writing it.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in packages/ipns at PubSubRouting.get() and the existing #fetchFromPeer path added in #906. Read how current subscribers are obtained and how subscription-change triggers fetching, then inspect the proposed contentRouting.findProviders flow and rendezvous CID handling. Done means the upstream direction and any opt-in behavior are settled before implementation.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
distributed-systems, networking
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.