Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement K-DHT for spartan-farmer #27

Closed
wants to merge 57 commits into from

Conversation

whereistejas
Copy link

@whereistejas whereistejas commented Sep 20, 2021

This PR creates a submodule dht in the commands module, that acts as a wrapper around rust-libp2p.

The dht module is logically divided into two sections:

  1. Client API - these are the methods that we will be using inside spartan-farmer to interact with the DHT.
  2. EventLoop - this is the part of code that handles the actual network events from the Kademlia protocol.

The EventLoop object is spawned as a background task, so that it works in an async manner.

Design patterns used here were picked up from the following PR in rust-libp2p:

  1. PR 2186

TODO

  • Add support for bootstrap.
  • Add Result to method return values.
  • Add ClientConfig to be able to create bootstrap nodes.
  • Use oneshot channels to get Ok/Err from ClientEvents to NetworkEvents to ClientEvents.
  • Add tests.

Tejas Sanap added 24 commits September 19, 2021 00:24
1. Update `oneshot` to receive errors.
2. Add `ClientType` enum.
3. Add methods to create bootstrap node.
1. Add `listen_addr` in `ClientConfig` for bootstrap nodes.
2. Add code in `dial_bootstrap` methods.
3. Add more comments.
1. Return Peer ID with `Client` object.
2. Add `enum` for `ClientType`.
3. Add methods to create bootstrap and normal nodes.
1. Add `ClientEvent` and `NetworkEvent` for `Bootstrap`.
2. Add flag for inputting bootstrap nodes through the CLI.
@whereistejas
Copy link
Author

CC @nazar-pc @rg3l3dr

@nazar-pc nazar-pc self-requested a review September 20, 2021 21:07
@whereistejas whereistejas marked this pull request as draft September 21, 2021 18:49
@whereistejas
Copy link
Author

whereistejas commented Sep 22, 2021

This code is ready for review. It currently supports bootstrapping but does not yet support peer-discovery. The core methods for peer-discovery are in place, but I need to give more thought about how to setup recurring peer-discovery after specified time interval/delays. For example, in sc-network peer-discovery happens once every 60 seconds. I would prefer to handle it in a seperate PR.

@whereistejas whereistejas marked this pull request as ready for review September 22, 2021 13:21
Copy link
Member

@nazar-pc nazar-pc left a comment

Choose a reason for hiding this comment

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

Thanks for working on this!

A few comments on general architecture and approaches, please work on those and I'll look again after since quite a few things will change by then. I will also read some more on libp2p to better review business logic next time.

.gitignore Outdated Show resolved Hide resolved
rustfmt.toml Outdated Show resolved Hide resolved
crates/spartan-farmer/Cargo.toml Outdated Show resolved Hide resolved
crates/spartan-farmer/Cargo.toml Outdated Show resolved Hide resolved
crates/spartan-farmer/src/commands.rs Outdated Show resolved Hide resolved
crates/spartan-farmer/src/commands/dht/client.rs Outdated Show resolved Hide resolved
Comment on lines 17 to 58
pub enum ClientEvent {
// Event for adding a listening address.
Listen {
addr: Multiaddr,
sender: oneshot::Sender<OneshotType>,
},
// Kademlia Random Walk for Peer Discovery. (GetClosestPeer)
#[allow(dead_code)]
RandomWalk {
key: Option<PeerId>,
sender: oneshot::Sender<QueryId>,
},
// List all known peers.
#[allow(dead_code)]
KnownPeers {
sender: oneshot::Sender<Vec<PeerId>>,
},
// Dial another peer.
#[allow(dead_code)]
Dial {
addr: Multiaddr,
peer: PeerId,
sender: oneshot::Sender<OneshotType>,
},
// Bootstrap during the initial connection to the DHT.
// NOTE: All the bootstrap nodes must already be connected to the swarm before we can start the
// bootstrap process.
Bootstrap {
sender: oneshot::Sender<QueryId>,
},
// Get all listening addresses.
#[allow(dead_code)]
Listeners {
sender: oneshot::Sender<Vec<Multiaddr>>,
},
// Read Kademlia Query Result.
#[allow(dead_code)]
QueryResult {
qid: QueryId,
sender: oneshot::Sender<String>,
},
}
Copy link
Member

Choose a reason for hiding this comment

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

It would be much better to remove this and have implementation in methods that you have already added..

There is a similar construction in plot module, but the reason it is there is because we have both read and write operations that should have different priorities, hence we have a custom loop there that prefers read operations over writes whenever possible. It doesn't seem like we have such requirements here, so it would be better to have async methods with necessary code in them. Much easier to read and maintain.

Copy link
Member

Choose a reason for hiding this comment

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

I would very much prefer to use async mutex to access mutable state rather than even loop. Event loop still woks with channels that have locks inside of them one way or another.

Copy link
Author

Choose a reason for hiding this comment

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

Can we keep this for now just to get bootstrap and peer discovery working and then, replace it async mutex's later on? The entire "eventloop and client API" depends on the ClientEvent enum.

Copy link
Member

Choose a reason for hiding this comment

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

That is the point, I would very much prefer to not get the entire event loop into the code base in the first place.

crates/spartan-farmer/src/commands/dht/client.rs Outdated Show resolved Hide resolved
pub listen_addr: Option<Multiaddr>,
}

pub struct Client {
Copy link
Member

Choose a reason for hiding this comment

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

This crate will become a library, think carefully what should actually be pub and what is only necessary as implementation detail and should be pub(super) or pub(crate). I think at least some of the stuff in this file if not all shouldn't be public.

Copy link
Member

Choose a reason for hiding this comment

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

Client and its config are still public, while constructor isn't. Are they supposed to be public or it can be made more limited in visibility too?

Copy link
Author

Choose a reason for hiding this comment

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

Actually we are not supposed to use Client::new(). In the current implementation, we use the create_connection method that gives us the Client and EventLoop objects in return. We need create_connection and ClientConfig to be public.

crates/spartan-farmer/src/commands/dht/client.rs Outdated Show resolved Hide resolved
@whereistejas whereistejas marked this pull request as draft September 24, 2021 13:40
Copy link
Member

@nazar-pc nazar-pc left a comment

Choose a reason for hiding this comment

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

A couple of comments on recent changes

.gitignore Outdated Show resolved Hide resolved
pub listen_addr: Option<Multiaddr>,
}

pub struct Client {
Copy link
Member

Choose a reason for hiding this comment

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

Client and its config are still public, while constructor isn't. Are they supposed to be public or it can be made more limited in visibility too?

@whereistejas whereistejas marked this pull request as ready for review September 26, 2021 19:10
@whereistejas whereistejas marked this pull request as draft September 26, 2021 19:10
@nazar-pc
Copy link
Member

Closing for now since we can't merge it as is. Feel free to submit another PR once you have time to work on this again.

@nazar-pc nazar-pc closed this Nov 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants