You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Provide: announce different CID sets to different routing systems (HTTP vs DHT), and select the target router per provide once / routing provide call #11411
There is currently no way to announce one set of CIDs to HTTP routers and a different, smaller set to the Amino DHT. Three things combine to make it impossible:
Provide.Strategy is global. It produces a single key stream, and routing/composer.go has a single ProvideRouter used by both Composer.Provide and Composer.ProvideMany. Whatever Routing.Methods.provide points at receives everything.
ipfs provide once / /api/v0/routing/provide cannot target a routing system. The only option is --recursive, and nd.Provider.ProvideOnce(mh) has no notion of a destination. Applications that announce explicitly, rather than relying on the reprovide cycle, cannot express the split either.
The IPNS-over-pubsub rendezvous key shares that same single ProvideRouter.TopicDiscovery() builds routing.NewRoutingDiscovery(ContentRouting), so advertising a topic is an ordinary ContentRouting.Provide(CID(sha256("floodsub:<topic>"))). There is therefore no way to keep a pubsub topic discoverable in the DHT while keeping content CIDs out of it, which is precisely the case where we most want DHT reach.
Motivation
I maintain pkc-js, a pubsub-based social protocol built on kubo. Each community node publishes an IPNS record, subscribes to a pubsub topic for that community, and stores a large and constantly growing set of content blocks whose root rotates on every update.
My intention is simple: announce to the DHT only the few CIDs related to a community's IPNS and its pubsub swarm, specifically the IPNS-over-pubsub rendezvous CID for the topic and the current root, and let the HTTP routers carry everything else. Once a reader has found the swarm for a community, the peers in that topic mesh serve its blocks over bitswap, and our clients also query delegated HTTP routers, so per-block DHT provider records are not what makes content retrievable in our system. They are just the expensive part of the announce path, and they scale with the whole pinset rather than with the handful of keys that actually need global reach.
Today the only expressible options are "everything to both" or "everything to one".
No workaround exists today
I could not find any way to express this with current config or CLI:
Routing.Methods.provide accepts exactly one router, shared by the reprovide cycle and by topic advertisement.
Provide.Strategy filters which CIDs are announced, but applies identically to every routing system behind that one router.
Provide.Enabled=false disables the provide system wholesale, and takes application-driven announcements down with it: ipfs provide once fails outright with cannot provide: Provide.Enabled is false, and the deprecated ipfs routing provide silently succeeds while doing nothing, since nd.Provider is a NoopProvider.
ipfs provide once has no router or system selector.
So with a mixed DHT plus HTTP configuration there is no supported way to get a single CID into the DHT without dragging the entire strategy set along with it.
Proposed solutions
Either would work; (B) alone is sufficient for my use case, since pkc-js announces explicitly rather than relying on the reprovide cycle.
(A) Per-routing-system provide strategy. The Provide docs already state the section is "designed to support multiple routing systems in the future", so this fits the existing schema:
with Provide.Strategy remaining the default for any system that does not override it.
(B) Per-call router selection. A selector on the imperative announce path:
$ ipfs provide once <cid> --routing-system=http
$ ipfs provide once <cid> --routing-system=dht
or, under Routing.Type=custom, naming an entry from Routing.Routers:
$ ipfs provide once <cid> --routers=HttpRoutersParallel
with a matching query parameter on /api/v0/provide/once and /api/v0/routing/provide so that HTTP RPC clients can pass it through. On the JS side this would surface as a field on RoutingProvideOptions in kubo-rpc-client, which today carries only recursive.
Notes and relation to existing issues
On the supported routing path this is currently moot, because constructDefaultHTTPRouters hardcodes ProvideRouter: noopRouter ("we don't have spec for sending provides to /routing/v1"), and with Routing.Type=auto the sweeping provider is DHT-only. HTTP providing is therefore only reachable via Routing.Type=custom, which the docs mark experimental and not for production. I understand that gates prioritisation, and that the real unblocker is IPIP-526 (IPIP-0526: Historic Bitswap Provider Publishing API specs#526), where I have commented with this use case.
Question for maintainers: once IPIP-526 lands, is there an intended way to express "announce to delegated routers, not to the DHT" on the supported Routing.Type=auto plus Routing.DelegatedRouters path, or is Routing.Type=custom expected to remain the only place this is possible?
Checklist
Version
Description
There is currently no way to announce one set of CIDs to HTTP routers and a different, smaller set to the Amino DHT. Three things combine to make it impossible:
Provide.Strategyis global. It produces a single key stream, androuting/composer.gohas a singleProvideRouterused by bothComposer.ProvideandComposer.ProvideMany. WhateverRouting.Methods.providepoints at receives everything.ipfs provide once//api/v0/routing/providecannot target a routing system. The only option is--recursive, andnd.Provider.ProvideOnce(mh)has no notion of a destination. Applications that announce explicitly, rather than relying on the reprovide cycle, cannot express the split either.The IPNS-over-pubsub rendezvous key shares that same single
ProvideRouter.TopicDiscovery()buildsrouting.NewRoutingDiscovery(ContentRouting), so advertising a topic is an ordinaryContentRouting.Provide(CID(sha256("floodsub:<topic>"))). There is therefore no way to keep a pubsub topic discoverable in the DHT while keeping content CIDs out of it, which is precisely the case where we most want DHT reach.Motivation
I maintain pkc-js, a pubsub-based social protocol built on kubo. Each community node publishes an IPNS record, subscribes to a pubsub topic for that community, and stores a large and constantly growing set of content blocks whose root rotates on every update.
My intention is simple: announce to the DHT only the few CIDs related to a community's IPNS and its pubsub swarm, specifically the IPNS-over-pubsub rendezvous CID for the topic and the current root, and let the HTTP routers carry everything else. Once a reader has found the swarm for a community, the peers in that topic mesh serve its blocks over bitswap, and our clients also query delegated HTTP routers, so per-block DHT provider records are not what makes content retrievable in our system. They are just the expensive part of the announce path, and they scale with the whole pinset rather than with the handful of keys that actually need global reach.
Today the only expressible options are "everything to both" or "everything to one".
No workaround exists today
I could not find any way to express this with current config or CLI:
Routing.Methods.provideaccepts exactly one router, shared by the reprovide cycle and by topic advertisement.Provide.Strategyfilters which CIDs are announced, but applies identically to every routing system behind that one router.Provide.Enabled=falsedisables the provide system wholesale, and takes application-driven announcements down with it:ipfs provide oncefails outright withcannot provide: Provide.Enabled is false, and the deprecatedipfs routing providesilently succeeds while doing nothing, sincend.Provideris aNoopProvider.ipfs provide oncehas no router or system selector.So with a mixed DHT plus HTTP configuration there is no supported way to get a single CID into the DHT without dragging the entire strategy set along with it.
Proposed solutions
Either would work; (B) alone is sufficient for my use case, since pkc-js announces explicitly rather than relying on the reprovide cycle.
(A) Per-routing-system provide strategy. The
Providedocs already state the section is "designed to support multiple routing systems in the future", so this fits the existing schema:{ "Provide": { "Strategy": "all", "DHT": { "Strategy": "roots" }, "HTTP": { "Strategy": "all" } } }with
Provide.Strategyremaining the default for any system that does not override it.(B) Per-call router selection. A selector on the imperative announce path:
or, under
Routing.Type=custom, naming an entry fromRouting.Routers:$ ipfs provide once <cid> --routers=HttpRoutersParallelwith a matching query parameter on
/api/v0/provide/onceand/api/v0/routing/provideso that HTTP RPC clients can pass it through. On the JS side this would surface as a field onRoutingProvideOptionsinkubo-rpc-client, which today carries onlyrecursive.Notes and relation to existing issues
constructDefaultHTTPRoutershardcodesProvideRouter: noopRouter("we don't have spec for sending provides to /routing/v1"), and withRouting.Type=autothe sweeping provider is DHT-only. HTTP providing is therefore only reachable viaRouting.Type=custom, which the docs mark experimental and not for production. I understand that gates prioritisation, and that the real unblocker is IPIP-526 (IPIP-0526: Historic Bitswap Provider Publishing API specs#526), where I have commented with this use case.routing provideand fast-provide do not provide to HTTP router (kubo 0.38 and 0.39) #11089 (HTTP router provides regressed, fixed in fix(routing): use LegacyProvider for HTTP-only custom routing #11112),ipfs routing providefails for pubsub routing keys that should be announcable #11123 (ipfs routing providefails for pubsub routing keys).Routing.Type=autoplusRouting.DelegatedRouterspath, or isRouting.Type=customexpected to remain the only place this is possible?