How to register as provider?

I’m trying to register as a provider of a CID against my local js-libp2p instance by calling libp2p.contentRouting.provide(cid). But when I do, I get an error:

Error: Failed to provide - no peers found
    at DualKadDHT.provide (/home/spencer/tempBugRepo/node_modules/libp2p-kad-dht/src/dual-kad-dht.js:242:21)
    at async drain (/home/spencer/tempBugRepo/node_modules/it-drain/index.js:12:20)
    at async DHTContentRouting.provide (/home/spencer/tempBugRepo/node_modules/libp2p/src/dht/dht-content-routing.js:28:5)
    at async Promise.all (index 0)
    at async ContentRouting.provide (/home/spencer/tempBugRepo/node_modules/libp2p/src/content-routing/index.js:83:5)
    at async main (/home/spencer/tempBugRepo/main.js:33:5) {
  code: 'ERR_PROVIDES_FAILED'
}

I actually don’t even need this node to actually walk the DHT and tell the peers closest to the CID that it is a provider, as I am doing that manually to avoid relying on the js-libp2p DHT. I only need to make sure that the local js-libp2p instance itself knows that it is a provider of the given CID. What am I doing wrong? Code below:

const TCP = require('libp2p-tcp')
const mplex = require('libp2p-mplex')
const { NOISE } = require('@chainsafe/libp2p-noise')
const defaultsDeep = require('@nodeutils/defaults-deep')
const libp2p = require('libp2p')
const KadDHT = require('libp2p-kad-dht')
const {CID} = require('multiformats/cid')

async function createLibp2p(_options) {
    const defaults = {
        modules: {
            transport: [TCP],
            streamMuxer: [mplex],
            connEncryption: [NOISE],
            dht: KadDHT,
        },
        config: {
            dht: {
                enabled: true,
            }
        }
    }

    return libp2p.create(defaultsDeep(_options, defaults))
}

async function main() {
    const libp2p = await createLibp2p()
    await libp2p.start()

    const cid = CID.parse('zU7azfWNQtCXi5bRmKWSZLMxXxeXx3hQEcGGgczavvWUfb3JZ6K1tv3XcVF9').toV1()

    await libp2p.contentRouting.provide(cid)

    console.log('all done!')
    await libp2p.stop()
}


main()

In order for a DHT provide to succeed, you need some peers in your routing table.

This is because a DHT provide involves sending the provider record to some peers. If there are no peers, you can’t send the record, so the operation fails.

The local node does not hold a provider record for own CIDs because it’ll never be asked for it since the provider record gets send to up to K (e.g. 20) peers with PeerIDs that are KAD-close to the CID’s multihash.

hmm… so you’re saying I shouldn’t actually need to place the provider record on the local instance? That does seem to happen as part of the standard provide path though: js-libp2p-kad-dht/index.js at 3997d67134df84ae091c6fa06f479635315ee957 · libp2p/js-libp2p-kad-dht · GitHub

I had assumed that when looking providers for a CID in the DHT, after the K closest peers have told you that a given PeerID is a provider you would still contact that peer directly to confirm before accepting the information that that peer is a provider - is that not the case?

If it isn’t required for a node to know that it is a provider for a CID, so long as the K closest nodes to the CID agree that it is a provider, then that means there’s some other problem in my code. I am manually reaching out to the K closest nodes and sending the ADD_PROVIDER RPC to them directly, but then when I query the DHT for providers for the CID, I get an empty set back. I really thought the issue was going to be that I needed to inform my local node that it should consider itself a provider…

Actually, no you’re quite right the impl does store a provider record for its own CIDs. I guess this should make the queries for your own data run faster, though if the record isn’t going out to the network, no-one is going to be able to resolve the records as your PeerID isn’t necessary KAD-closest to the CID multihash.

When you run the provider query, do you get results if you paste the relevant query params into https://ipfs-check.on.fleek.co/ ?

ooph, I get all the errors on that ipfs-check website:
:x: Could not connect to multiaddr: no good addresses
:x: Could not find the given multiaddr in the dht. Instead found:
:x: Could not find the multihash in the dht
:x: There was an error downloading the CID from the peer: could not connect to peer

FYI the code I’m running is available here: GitHub - stbrody/tipsync-poc
There’s really not that much to it.

I still don’t understand why libp2p.contentRouting.provide() is failing with a “no peers found” error given that I’m explicitly calling libp2p.peerStore.addressBook.add() several times with peers/multiaddrs looked up from a go-ipfs node’s DHT.