Skip to content

ipfs routing provide fails for pubsub routing keys that should be announcable #11123

@Rinse12

Description

@Rinse12

Checklist

Installation method

dist.ipfs.tech or ipfs-update

Version

Kubo version: 0.39.0
Repo version: 18
System version: amd64/linux
Golang version: go1.25.4

Config

{
  "API": {
    "HTTPHeaders": {}
  },
  "Addresses": {
    "API": "/ip4/127.0.0.1/tcp/5001",
    "Announce": [],
    "AppendAnnounce": [],
    "Gateway": "/ip4/127.0.0.1/tcp/8080",
    "NoAnnounce": [],
    "Swarm": [
      "/ip4/0.0.0.0/tcp/4001",
      "/ip6/::/tcp/4001",
      "/ip4/0.0.0.0/udp/4001/webrtc-direct",
      "/ip4/0.0.0.0/udp/4001/quic-v1",
      "/ip4/0.0.0.0/udp/4001/quic-v1/webtransport",
      "/ip6/::/udp/4001/webrtc-direct",
      "/ip6/::/udp/4001/quic-v1",
      "/ip6/::/udp/4001/quic-v1/webtransport"
    ]
  },
  "AutoNAT": {},
  "AutoTLS": {},
  "Bootstrap": [
    "/ip4/104.131.131.82/tcp/4001/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
    "/ip4/104.131.131.82/udp/4001/quic-v1/p2p/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
    "/dnsaddr/bootstrap.libp2p.io/p2p/QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt"
  ],
  "DNS": {
    "Resolvers": {}
  },
  "Datastore": {
    "BloomFilterSize": 0,
    "GCPeriod": "1h",
    "HashOnRead": false,
    "Spec": {
      "mounts": [
        {
          "child": {
            "path": "blocks",
            "shardFunc": "/repo/flatfs/shard/v1/next-to-last/2",
            "sync": true,
            "type": "flatfs"
          },
          "mountpoint": "/blocks",
          "prefix": "flatfs.datastore",
          "type": "measure"
        },
        {
          "child": {
            "compression": "none",
            "path": "datastore",
            "type": "levelds"
          },
          "mountpoint": "/",
          "prefix": "leveldb.datastore",
          "type": "measure"
        }
      ],
      "type": "mount"
    },
    "StorageGCWatermark": 90,
    "StorageMax": "10GB"
  },
  "Discovery": {
    "MDNS": {
      "Enabled": true
    }
  },
  "Experimental": {
    "FilestoreEnabled": false,
    "Libp2pStreamMounting": false,
    "OptimisticProvide": false,
    "OptimisticProvideJobsPoolSize": 0,
    "P2pHttpProxy": false,
    "StrategicProviding": false,
    "UrlstoreEnabled": false
  },
  "Gateway": {
    "DeserializedResponses": null,
    "DisableHTMLErrors": null,
    "ExposeRoutingAPI": null,
    "HTTPHeaders": {},
    "NoDNSLink": false,
    "NoFetch": false,
    "PublicGateways": null,
    "RootRedirect": ""
  },
  "Identity": {
    "PeerID": "12D3KooWBJNtmfaDN1G1enLgEuWVXAHGR98fjYDH2d3wNsKqWr4s"
  },
  "Import": {
    "CidVersion": null,
    "HashFunction": null,
    "UnixFSChunker": null,
    "UnixFSRawLeaves": null
  },
  "Internal": {},
  "Ipns": {
    "RecordLifetime": "",
    "RepublishPeriod": "24h",
    "ResolveCacheSize": 128
  },
  "Migration": {
    "DownloadSources": [],
    "Keep": ""
  },
  "Mounts": {
    "FuseAllowOther": false,
    "IPFS": "/ipfs",
    "IPNS": "/ipns"
  },
  "Peering": {
    "Peers": null
  },
  "Pinning": {
    "RemoteServices": {}
  },
  "Plugins": {
    "Plugins": null
  },
  "Provider": {
    "Strategy": ""
  },
  "Pubsub": {
    "DisableSigning": false,
    "Router": ""
  },
  "Reprovider": {},
  "Routing": {
    "Methods": {
      "find-peers": {
        "RouterName": "HttpRouterNotSupported"
      },
      "find-providers": {
        "RouterName": "HttpRoutersParallel"
      },
      "get-ipns": {
        "RouterName": "HttpRouterNotSupported"
      },
      "provide": {
        "RouterName": "HttpRoutersParallel"
      },
      "put-ipns": {
        "RouterName": "HttpRouterNotSupported"
      }
    },
    "Routers": {
      "HttpRouter1": {
        "Parameters": {
          "Endpoint": "http://127.0.0.1:19575"
        },
        "Type": "http"
      },
      "HttpRouter2": {
        "Parameters": {
          "Endpoint": "http://127.0.0.1:19576"
        },
        "Type": "http"
      },
      "HttpRouter3": {
        "Parameters": {
          "Endpoint": "http://127.0.0.1:19577"
        },
        "Type": "http"
      },
      "HttpRouter4": {
        "Parameters": {
          "Endpoint": "http://127.0.0.1:19578"
        },
        "Type": "http"
      },
      "HttpRouterNotSupported": {
        "Parameters": {
          "Endpoint": "http://kubohttprouternotsupported"
        },
        "Type": "http"
      },
      "HttpRoutersParallel": {
        "Parameters": {
          "Routers": [
            {
              "IgnoreErrors": true,
              "RouterName": "HttpRouter1",
              "Timeout": "10s"
            },
            {
              "IgnoreErrors": true,
              "RouterName": "HttpRouter2",
              "Timeout": "10s"
            },
            {
              "IgnoreErrors": true,
              "RouterName": "HttpRouter3",
              "Timeout": "10s"
            },
            {
              "IgnoreErrors": true,
              "RouterName": "HttpRouter4",
              "Timeout": "10s"
            }
          ]
        },
        "Type": "parallel"
      }
    },
    "Type": "custom"
  },
  "Swarm": {
    "AddrFilters": null,
    "ConnMgr": {},
    "DisableBandwidthMetrics": false,
    "DisableNatPortMap": false,
    "RelayClient": {},
    "RelayService": {},
    "ResourceMgr": {},
    "Transports": {
      "Multiplexers": {},
      "Network": {},
      "Security": {}
    }
  },
  "Version": {}
}

Description

We are running IPNS-over-Pubsub and want to announce provider records for pubsub routing keys (not content CIDs) without waiting for kubo to announce them. ipfs routing provide <routing-cid> fails with “block not found locally” even though these are routing keys that Kubo could technically advertise.

What we were doing when the bug occurred

We tried to manually announce provider records for pubsub routing keys used by IPNS-over-Pubsub so peers can discover each other without DHT content.

These are standard pubsub routing keys (derived from the pubsub topic, not content):

  1. pubsubTopicRoutingCid
  • routing key: floodsub:${pubsubTopic}
  • bytes: UTF-8
  • hash: SHA-256
  • CID: CIDv1, codec 0x55 (raw), multihash SHA-256
  • equivalent: CID.createV1(0x55, sha256(floodsub:<topic>))
  1. ipnsPubsubTopicRoutingCid
  • ipns pubsub topic: /record/ + base64url(/ipns/ + PeerIdBytes(ipnsName))
  • routing key: floodsub:${ipnsPubsubTopic}
  • bytes: UTF-8
  • hash: SHA-256
  • CID: CIDv1, codec 0x55 (raw), multihash SHA-256

Error message and where we saw it

From the CLI:

ipfs routing provide <pubsubTopicRoutingCid>
ipfs routing provide <ipnsPubsubTopicRoutingCid>

Result:

Error: block <cid> not found locally, cannot provide

Steps to reliably reproduce

Run:

git clone https://github.com/Rinse12/providing_ipns_pubsub_topic_routing_cid_bug
cd providing_ipns_pubsub_topic_routing_cid_bug
npm i
npm run repro

Expected behavior

Kubo should allow routing provide to advertise provider records for these pubsub routing keys even though there is no block in the blockstore (they are routing keys, not content). This is needed so peers can discover IPNS-over-Pubsub participants without needing to wait for kubo to announce them.

Why this matters

In our case we need to announce a peer to http routers the moment its IPNS is created, and kubo is not consistent in announcing its providing of routing cids. We need to explicitly call ipfs provide <routing-cid> to make sure a provider is discoverable by the network immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium: Good to have, but can wait until someone steps upkind/bugA bug in existing code (including security flaws)topic/ipnsTopic ipnstopic/pubsub

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions