-
Notifications
You must be signed in to change notification settings - Fork 247
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
Conversation
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.
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 |
There was a problem hiding this 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.
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>, | ||
}, | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
pub listen_addr: Option<Multiaddr>, | ||
} | ||
|
||
pub struct Client { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this 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
pub listen_addr: Option<Multiaddr>, | ||
} | ||
|
||
pub struct Client { |
There was a problem hiding this comment.
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?
…nto impletement-dht2
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. |
This PR creates a submodule
dht
in thecommands
module, that acts as a wrapper aroundrust-libp2p
.The
dht
module is logically divided into two sections:Client
API - these are the methods that we will be using insidespartan-farmer
to interact with the DHT.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
:TODO
bootstrap
.Result
to method return values.ClientConfig
to be able to create bootstrap nodes.oneshot
channels to getOk
/Err
from ClientEvents to NetworkEvents to ClientEvents.