Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

The IPNS Example Doesn't Work #3549

Closed
justinmchase opened this issue Feb 14, 2021 · 12 comments
Closed

The IPNS Example Doesn't Work #3549

justinmchase opened this issue Feb 14, 2021 · 12 comments
Labels
need/triage Needs initial labeling and prioritization

Comments

@justinmchase
Copy link

justinmchase commented Feb 14, 2021

Version:

PS D:\code\ipfs-rss> npx jsipfs version --all
js-ipfs version: 0.5.2-ff76e7cda441d66d327e03e3ca1dea6e901ec918
interface-ipfs-core version: ^0.144.1
ipfs-http-client version: undefined
Repo version: 10
System version: x64/win32
Node.js version: v14.15.4
Commit: ff76e7cda441d66d327e03e3ca1dea6e901ec918

Platform:

$ uname -a
MINGW64_NT-10.0 DESKTOP-KQ2J7VI 2.10.0(0.325/5/3) 2018-06-13 23:34 x86_64 Msys

Subsystem:

unknown

Severity:

High - The main functionality of the application does not work, API breakage, repo format breakage, etc.

Description:

Following the example on ipfs.name.publish and then visiting the gateway and using the published name does not work.

I am using the ipfs node package and am running my ipfs in the main process of an electron app.

import { create, IPFS } from 'ipfs'

class IpfsService {
  private ipfs?: IPFS
  public async start() {
    this.ipfs = await create({
      start: true,
    });
  }
}

I'm then adding a file:

  public async add(arg: IpfsAddArg): Promise<IpfsAddResponse> {
    const { content } = arg
    const { cid } = await this.ipfs!.add(content)
    return {
      hash: cid.toString()
    }
  }

I'm then implementing this example:
https://github.com/ipfs/js-ipfs/blob/master/docs/core-api/NAME.md#example

But when I call the name.publish exactly as in the example it hangs forever:

  public async publish(arg: IpfsPublishArg): Promise<void> {
    const { hash } = arg
    const { name, value } = await this.ipfs!.name.publish(`/ipfs/${hash}`)
    console.log('published:', { name, value })
  }

If I modify the call to have the options { resolve: false } then it immediately completes the call but The name returned from the result differs from the documentation, it lacks the prefix /ipns/ as shown in the documentation. The value does contain the prefix /ipfs/ as documented however. I'm not sure if that matters.

published: {
  name: 'QmRTsbswwFBq7GxQ36igMf2s1K7wfQ6af6vib1RY1N144T',
  value: '/ipfs/QmU927tWyxx46g2ZMfRd5PGoLjyXk4q4Wpvyu8pKRRMgFH'
}

The name does not resolve through the gateway.
image

Steps to reproduce the error:

I'm not sure exactly what I'm missing. beyond just calling the api with a hash.

@justinmchase justinmchase added the need/triage Needs initial labeling and prioritization label Feb 14, 2021
@justinmchase
Copy link
Author

Ok, I fixed the hanging issue...

I was actually using the files.write api and then hashing the content to get the hash. But it turns out the hash of the file is not the same as the hash of the content. I changed it to stat the file instead and now the publish function with { resolve: true } works.

I can even resolve the IPNS address to the hash locally and it works... but going through the gateway still doesn't ever resolve to anything.

  public async writeFile(arg: IpfsWriteFileArg): Promise<IpfsWriteFileResponse> {
    console.log(IpfsInvokeKind.WriteFile, arg)
    const { file, content } = arg
    // const dirname = path.dirname(file)
    // await this.mkdirp(dirname)
    await this.ipfs!.files.write(file, content, {
      create: true,
      parents: true
    })

    const { cid } = await this.ipfs!.files.stat(file) // not the same as the content hash
    return {
      hash: cid.toString()
    }
  }

@TJKoury
Copy link
Contributor

TJKoury commented Mar 6, 2021

I have a similar issue, local resolution but does not work through https://gateway.ipfs.io/.

let peerID = await PeerId.create({ bits: 256, keyType: "secp256k1" });

let options = { privateKey: peerID };

const node = await IPFS.create(options);

const fileAdded = await node.add({
  path: "hello.txt",
  content: "Test Content",
});

const addr = `/ipfs/${fileAdded.cid}`;

node.name.publish(addr).then(function (res) {
     //Visiting this link results in:  could not resolve name
     console.log(`https://gateway.ipfs.io/ipns/${res.name}`);

});

@TJKoury
Copy link
Contributor

TJKoury commented Mar 6, 2021

I did configure NAT correctly, and I can resolve the file's CID from gateway and my other external nodes.

@vasco-santos
Copy link
Member

vasco-santos commented Mar 15, 2021

The JS DHT is not running by default and still needs to be tested and enhanced, in order to be reliable. This means that IPNS records will not be pushed into the DHT and other peers will not be able to resolved them, unless IPNS over Pubsub is used. Probably the gateway does not have IPNS over Pubsub enabled, nor the example.

The IPNS example should have more information on what are the current conditions where it is expected to work.

@BigLep
Copy link
Contributor

BigLep commented Mar 21, 2021

@vasco-santos: is there an issue about the JS DHT's status that we can link so interested parties can learn more as this evolves?

@justinmchase
Copy link
Author

Ok, so what you're saying is that for this to work, not only do I need to have IPNS over pubsub enabled but so do all of the nodes in the network? Or at least the one hosting the DHT and the one the request originates in? Does the pubsub message get propagated through the network and simply the gateway ignores it or does the pubsub message not even propagate at all?

@TJKoury
Copy link
Contributor

TJKoury commented Mar 22, 2021

Looks like the answer here to get it functional is just to run a go-IPFS node by itself, and write a script that will pin and publish in that node if connected to by the client, outside of the current framework.

@vasco-santos
Copy link
Member

@vasco-santos: is there an issue about the JS DHT's status that we can link so interested parties can learn more as this evolves?

Improving js libp2p discoverability connectivity is the meta issue including the DHT: libp2p/js-libp2p#703

Ok, so what you're saying is that for this to work, not only do I need to have IPNS over pubsub enabled but so do all of the nodes in the network? Or at least the one hosting the DHT and the one the request originates in? Does the pubsub message get propagated through the network and simply the gateway ignores it or does the pubsub message not even propagate at all?

For pubsub to work reliably, you will need to be connected to a subset of peers which are interested in the same topic as you. Accordingly, for you to use IPNS over Pubsub you need one of:

  • be connected to the peer who publishes the IPNS records you care about
  • be connected to a subset of the peers interested on the topic (IPNS Record in this case), so that gossipsub can propagate messages reliably

Another caveat is that IPNS over Pubsub is not enabled by default, so you need the IPNS Record publisher to have it enabled. As well as the node who is resolving records.

DHT is not required, unless you want to resolve the past record. So, this means a flow like:

  • Node B attempts to resolve IPNS Record from Node A (ipns over pubsub enabled)
    • Fails as there is no record yet (if you would have the DHT, it would fallback to try to find via the DHT if it exists)
  • Node A publishes an IPNS Record (first or followings as the IPNS record must be published before the end of its validity)
  • Node B attempts to resolve IPNS Record, and it will be stored there already has NodeA published over Pubsub and NodeB was already subscribing it on the previous resolve attempt.

A quick win to improve the IPNS reliability in JS, would be to update the Pubsub fallback to the same as go currently does. This basically is using DHT Provider records, which means we would be able to just use the delegate nodes (now configured by default in js-ipfs) to find the provider of the IPNS Record and connect to it. This needs to be implemented in JS though

@justinmchase
Copy link
Author

justinmchase commented Mar 23, 2021

Ok thanks for the details. It sounds like though maybe just holding off and waiting would be the right solution for me. Meaning, this feature is in progress and will eventually be enabled but right now its just in a funky state and if you absolutely need it right now then you have to do some complex work arounds but if you don't then just wait a bit for the proper feature.

@lidel
Copy link
Member

lidel commented May 10, 2021

For now IPFS over pubsub should act as a workaround for some use cases.
Closing this until something like protocol/web3-dev-team#30 lands.

@lidel lidel closed this as completed May 10, 2021
@TJKoury
Copy link
Contributor

TJKoury commented May 10, 2021

@lidel just to be clear for anyone who shows up here in search of an answer, IPNS name publishing over PubSub does not “work” in JS, there are no working solutions that allow publishing an IPNS hash and having it resolve content for everyone connected to IPFS nodes regardless of when they connected / what specific nodes they connected.

Use Go-IPFS if you need a solution right now.

@whiteowl3
Copy link

would really appreciate clarification on whether or not ipns over pubsub will work in js-ipfs for resolving names.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
need/triage Needs initial labeling and prioritization
Projects
None yet
Development

No branches or pull requests

6 participants