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

Awesome Endeavour: DHT Part II#856

Merged
alanshaw merged 11 commits intomasterfrom
feat/dht-part-ii
Feb 8, 2019
Merged

Awesome Endeavour: DHT Part II#856
alanshaw merged 11 commits intomasterfrom
feat/dht-part-ii

Conversation

@daviddias
Copy link
Member

@daviddias daviddias commented May 19, 2017

This PR is the second part of the DHT integration in js-ipfs

Remaining tasks

Main work tracker: libp2p/js-libp2p-kad-dht#1

Needs the following PRs:

Blocked PRs:

@daviddias
Copy link
Member Author

daviddias commented Jul 20, 2017

@daviddias
Copy link
Member Author

It might actually be good to enable the DHT if it proves to not break things and then figure out the interop of the DHT with go-ipfs as we go.

@daviddias
Copy link
Member Author

Updated deps including all the latest changes in Bitswap. DHT tests in JS land are fine. Still no love between JS and Go 😢

@daviddias
Copy link
Member Author

CI is still not happy as well


  1) interface-ipfs-core tests .dht callback API .findpeer finds other peers:
     Uncaught AssertionError: expected [Error] to not exist
      at nodeA.dht.findpeer (node_modules/interface-ipfs-core/src/dht.js:90:32)
      at self._libp2pNode.peerRouting.findPeer (src/core/components/dht.js:81:18)
      at node_modules/async/internal/once.js:12:16
      at next (node_modules/async/waterfall.js:21:29)
      at node_modules/async/internal/onlyOnce.js:12:16
      at waterfall (node_modules/libp2p-kad-dht/src/index.js:449:20)
      at nextTask (node_modules/async/waterfall.js:16:14)
      at next (node_modules/async/waterfall.js:23:9)
      at node_modules/async/internal/onlyOnce.js:12:16
      at setImmediate (node_modules/multihashing-async/src/utils.js:8:7)
      at Immediate.<anonymous> (node_modules/async/internal/setImmediate.js:27:16)

  2) interface-ipfs-core tests .dht callback API .query returns the other node in the query:
     Uncaught AssertionError: expected [] to include 'QmS72d5n39h2zWXHQFFQs2Xub7GADbYimayvJYkocJv98D'
      at nodeA.dht.query (node_modules/interface-ipfs-core/src/dht.js:139:47)
      at self._libp2pNode._dht.getClosestPeers (src/core/components/dht.js:157:9)
      at q.run (node_modules/libp2p-kad-dht/src/index.js:172:18)
      at Query.run (node_modules/libp2p-kad-dht/src/query.js:47:14)
      at utils.convertBuffer (node_modules/libp2p-kad-dht/src/index.js:166:9)
      at setImmediate (node_modules/multihashing-async/src/utils.js:8:7)
      at Immediate.<anonymous> (node_modules/async/internal/setImmediate.js:27:16)

@daviddias daviddias added P0 Critical: Tackled by core team ASAP status/ready Ready to be worked and removed status/ready Ready to be worked labels Oct 17, 2017
@hoffmabc
Copy link

Is this PR still up to date?

@daviddias
Copy link
Member Author

@hoffmabc it is as with regards to status, DHT is still a WIP. Lot's of work happening on js-libp2p land itself -- https://github.com/libp2p/js-libp2p --. Currently focused on libp2p/js-libp2p#159

@dryajov dryajov mentioned this pull request Mar 26, 2018
@alanshaw
Copy link
Member

Is there any prior docs I can read about the technical challenges involved in go <-> js DHT interop?

@daviddias
Copy link
Member Author

Let's unblock this endeavour with the delegated routing as soon as 0.29.0 gets released.

@rmisio
Copy link

rmisio commented Jan 3, 2019

@BazaarDog Those seem to be links to different tests. Does that mean that this PR here should already have the go interop baked in and just the tests are seperate?

@alanshaw
Copy link
Member

alanshaw commented Jan 3, 2019

@rmisio this PR should be interoperable with go-ipfs

@rmisio
Copy link

rmisio commented Jan 3, 2019

I can't seem to get the dht working right between two ipfs-js nodes:

// package.json
"ipfs": "github:ipfs/js-ipfs#feat/dht-part-ii",
// node config
{
      EXPERIMENTAL: {
        pubsub: true,
        dht: true,
      },
      relay: {
        "enabled": true,
      },
      repo: `./ipfs/${peerId}`,
      init: { privateKey },
    }
// receiving node puts item in the dht keyed by their peerId
        node.on('ready', () => {
          node.libp2p.start(() => {
            const val = `${peerId} - slick willy willy`;

            node._libp2pNode.dht.put(
              identity.peerId,
              Buffer.from(val),
              err => {
                if (err) {
                  throw err;
                }

                console.log(`"${val}" has been stored in the dht. Kudos.`);
              }
            );

I could verify that the node that puts the item in the dht is able to retrieve it.

But, a different node cannot:

    this.node._libp2pNode.dht.get(
      createFromB58String(receiver).id,
      {},
      (err, content) => {
        if (err) {
          throw err;
        }

        console.log(`for ${receiver} the dht has "${content.toString()}"`);
      }
    );

The main error I seem to get is Callback function "anonymous" timed out.:

image

I can confirm via node._libp2pNode.stats.peers() I have plenty of peers at the time of the dht.get call... often times over 90.

FWIW, the web nodes I'm using are each connected to a ipfs-go node acting as a relay. Not sure if that has anything to do with anything here :)

@joeykrug
Copy link

What's the status of getting this merged + functional? Looking to use this for faster sync by sharing db's over ipfs for AugurProject/augur#771

@vasco-santos
Copy link
Member

Hey all!

This PR is interoperable with the go-ipfs DHT implementation. I intend to continue the work on this PR after the 21st January, in order to get this finished and merged.

**Please read this:** DHT (automatic content discovery) and Circuit Relay (pierce through NATs and dial between any node in the network) are two fundamental pieces that are not finalized yet. There are multiple applications that can be built without these two services but nevertheless they are fundamental to get that magic IPFS experience. If you want to track progress or contribute, please follow:

- DHT: https://github.com/ipfs/js-ipfs/pull/856
- ✅ Relay: https://github.com/ipfs/js-ipfs/pull/1063
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.



- `pubsub` (boolean): Enable libp2p pub-sub. (Default: `false`)
- `ipnsPubsub` (boolean): Enable pub-sub on IPNS. (Default: `false`)
- `sharding` (boolean): Enable directory sharding. Directories that have many child objects will be represented by multiple DAG nodes instead of just one. It can improve lookup performance when a directory has several thousand files or more. (Default: `false`)
- `dht` (boolean): Enable KadDHT. **This is currently not interoperable with `go-ipfs`.**
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the DHT start automatically in the browser too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the current state of this PR it is starting automatically in both browser and node. Do you think we should start by having only node.js nodes first?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend to start with node only and look at adding it to the browser as a default later, if ever. Until we get more performance benchmarking for the browser I'm hesitant to just turn it on there for everyone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that's a good point!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so, I'm half inclined to just enable it in the browser by default, expose ourselves to the issues and get them fixed asap. That said, since this is such a big feature perhaps not having it enabled by default in the browser initially will give us some scope to test it out first and fix the bigger issues, so that we don't expose all our users to the bugs and make everyone mad.

We do need a way to enable/disable it though - if the dht config option is being removed from EXPERIMENTAL, is it being added to the top level?


handler (argv) {
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the DHT full implemented on http api and CLI as well? Mind updating https://github.com/ipfs/ipfs/blob/master/IMPLEMENTATION_STATUS.md#dht ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done in ipfs/ipfs#388

} catch (err) {
log.error(err)

return setImmediate(() => callback(errcode(err, 'ERR_INVALID_CID')))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't there a push to change setImmediate for nextTick?

if (typeof opts === 'function') {
callback = opts
opts = {}
return setImmediate(() => callback(errcode(err, 'ERR_INVALID_CID')))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

},
EXPERIMENTAL: {
dht: get(options, 'EXPERIMENTAL.dht', false),
dht: !(get(options, 'local', false)),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this mean?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have an option (local currently) that aims to:

Run offline. Do not connect to the rest of the network but provide local API.

Regarding this, go-ipfs changed recently this option name to offline. So, I created a PR now for renaming this option to offline #1850.

Once it is merged, I will rebase this PR and, if we go with DHT enabled by default in libp2p config, I will change this logic to not add the dht to the libp2p modules, if we are running offline.

},
EXPERIMENTAL: {
dht: false,
dht: true,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need anymore, right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the libp2p side, it is still marked as experimental. I am totally up to make it enabled by default and running if libp2p receives the DHT in the modules object.

Should we release a new version of libp2p removing the experimental flag now? If you all agree, I will make the PR later today.

cc @jacobheun

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we release a new version of libp2p removing the experimental flag now? If you all agree, I will make the PR later today.

I agree 👍 💯

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also agree, set it free!

},
EXPERIMENTAL: {
dht: false,
dht: true,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need anymore, right?

}).code(500)
}

reply({})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why send back an empty objective?

Copy link
Member

@alanshaw alanshaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally the CLI command handlers may soon need to be updated to use getIpfs instead of ipfs. See #1860 for details.

- `pubsub` (boolean): Enable libp2p pub-sub. (Default: `false`)
- `ipnsPubsub` (boolean): Enable pub-sub on IPNS. (Default: `false`)
- `sharding` (boolean): Enable directory sharding. Directories that have many child objects will be represented by multiple DAG nodes instead of just one. It can improve lookup performance when a directory has several thousand files or more. (Default: `false`)
- `dht` (boolean): Enable KadDHT. **This is currently not interoperable with `go-ipfs`.**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, so, I'm half inclined to just enable it in the browser by default, expose ourselves to the issues and get them fixed asap. That said, since this is such a big feature perhaps not having it enabled by default in the browser initially will give us some scope to test it out first and fix the bigger issues, so that we don't expose all our users to the bugs and make everyone mad.

We do need a way to enable/disable it though - if the dht config option is being removed from EXPERIMENTAL, is it being added to the top level?

const peers = await ipfs.dht.findPeer(peerID)
const addresses = peers.multiaddrs.toArray().map((ma) => ma.toString())

print(addresses)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

print is just console.log which will give you output like:

[ '/ip4/127.0.0.1/tcp/4001',
  '/ip4/169.254.83.88/tcp/4001',
  '/ip4/192.168.1.95/tcp/4001' ]

In comparison go-ipfs outputs:

$ ipfs dht findpeer QmZMxNdpMkewiVZLMRxaNxUeZpDUb34pWjZ1kZvsd16Zic
/ip6/2001:19f0:5:66d1::/tcp/4001
/ip4/149.28.228.162/tcp/33154
/ip4/45.77.150.82/tcp/4001
/ip6/::1/tcp/4001
/ip6/2001:19f0:5:5d40:5400:1ff:fec1:ce94/tcp/4001
/ip4/127.0.0.1/tcp/4001
/ip4/149.28.228.162/tcp/4001
/ip4/127.0.0.1/tcp/8081/ws

},

handler ({ ipfs, key, resolve }) {
// TODO add recursive option
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pass this option to ipfs.dht.provide so it can throw and inform the user the option is not implemented yet.

},
dht: {
kBucketSize: get(options, 'dht.kBucketSize', 20),
enabled: get(options, 'dht.enabled', true) && !(get(options, 'local', false)),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"local" is now "offline"?

const some = require('async/some')
const eachOf = require('async/eachOf')
const someSeries = require('async/someSeries')
const eachOfSeries = require('async/eachOfSeries')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this change do?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using some is making a lot of parallel dht find and connect requests.

So, everything will get queried even if we find the target node, as the find takes longer than initiating the requests.

In the long run, we should refactor the pin-set, in order to try to parallelize some operations, but this is the safest option currently.

arg: Joi.string().required()
}).unknown()
},
handler: (request, reply) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These handlers now need to change for Hapi 18 - please shout if you have any questions!

@alanshaw alanshaw mentioned this pull request Feb 6, 2019
@vasco-santos vasco-santos mentioned this pull request Feb 8, 2019
4 tasks
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

awesome endeavour exp/wizard Extensive knowledge (implications, ramifications) required P1 High: Likely tackled by core team if no one steps up

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants