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

Survey applicable functions in libp2p #2

Open
junha1 opened this issue Jul 9, 2022 · 6 comments
Open

Survey applicable functions in libp2p #2

junha1 opened this issue Jul 9, 2022 · 6 comments
Assignees

Comments

@junha1
Copy link
Member

junha1 commented Jul 9, 2022

We need a brief overview of the functionality of the library, which should be enough to finalize the interface of networking module

@f2koi
Copy link
Contributor

f2koi commented Jul 9, 2022

Ok. I'll work on it through the next few days.

@f2koi
Copy link
Contributor

f2koi commented Jul 12, 2022

libp2p-rs

Core interfaces

transports

An interface (Transport trait) for network transport methods.
Several implementations for pre-existing protocol like TCP and WebSocket are included in the library.

swarm

Defines how to send data to a external node or respond to an incoming connection (by implementing NetworkBehavior trait).
Also, it is an overall network manager.
E.g.:

let mut swarm = Swarm::new(transport, behaviour, local_peer_id);
swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse::<Multiaddr>());

application-level protocols

  • floodsub: pubsub + flooding
  • gossipsub: pubsub + gossipping
  • Kademlia: defining specific network structure to enable node lookup and resource finding
  • identify: exchanging basic information with other peers including addresses, public keys, and capabilities
  • autonat: NAT traversal
  • relay: relay nodes
  • request-response: a generic request/response protocol

encryption schemes

noise protocol (DH key exchange)

stream muxers

  • mplex
  • yamux

Supported asynchronous environments

  • async-std
  • tokio

Node representation

  • peer_id (hash(pubkey))
  • provides keypair generation methods
  • address representation as Multiaddr used in libp2p: /ip4/141.123.145.99/tcp/12764

@f2koi
Copy link
Contributor

f2koi commented Jul 12, 2022

It seems we need to implement a peer-finding protocol on the application-level, for I couldn't find a proper module in the libp2p.
Floodsub/Gossipsub protocols could be used to propagate blocks and votings, otherwise, we should implement our own protocol for that.
For querying information like a block at a specific height, we could use request-response protocol which is designed for general purposes.

@f2koi
Copy link
Contributor

f2koi commented Aug 13, 2022

As I wrote above, libp2p has several modules with different roles. In this comment, I introduce two high-level modules, FloodSub and Kademlia, and explain how they are and will be used throughout our project.

Kademlia

Kademlia dynamic hash table (DHT) with its own protocol is a way to store data or resources over a p2p network and retrieve them as needed. It's core idea was introduced in 2002, in this paper.

Each network node that obeys the Kademlia protocol fills its DHT with other peers' addresses. It keeps almost all of its nearest peers in its DHT but smaller portion of its farthest peers. For example, a node keeps k peers in each bucket and each bucket has peers at distance of 1~2, 2~4, 4~8, 8~16, and so on. libp2p implements these Kademlia DHT and protocol. I'll use them to maintain a robust mesh network over which the participating nodes are uniformly connected. This mesh structure is more lightweight compared to a densely connected structure. However, there might be limitations to some tasks that require the entire nodes' addresses.

Although Kademlia protocol supports storing and retrieving hashable data, those features are none of our interest and won't be used in our project.

FloodSub

FloodSub is an implementation of PubSub(Publish & Subscribe model). It is named so because it's strategy to pass a message is to flood the network with the message (every node just forwards or broadcasts received messages).

A message is related with one or more topics, and subscribers of a specific topic receive messages related with that topic. When a publisher creates a message, it assigns the message with several topics and broadcast it to a group of nodes called FloodSub neighbors.

Integrations

Since Kademlia doesn't support initial launch of the network and bootstrapping of a node, initial connections should be made manually for a newly joined node. This is implemented in #41, and will be merged once reviewed.

FloodSub doesn't mention how to discover peers and maintain the connections between them. Kademlia will be used to provide those functions. I'll maintain the group of FloodSub neighbors as the same as the group of Kademlia k-closest peers.

These two modules emit events to notify the upper layer that they did important operations or encountered important network events. These emitted events are the major interfaces libp2p offers. They will be captured by the background task spawned by the network instance, PropagationNetwork, and will be used to implement peer discovery and broadcasting.

Plan for Implementing Public Interfaces

The following is the public interfaces of an authorized network.

#[async_trait]
pub trait AuthorizedNetwork {
    /// Joins the network with an authorized identity.
    async fn new([OMITTED]) -> Result<Self, String> where Self: Sized;
    /// Broadcasts a message to the network, after signed by the key given to this instance.
    async fn broadcast(&self, message: &[u8]) -> Result<BroadcastToken, String>;
    /// Stops a currently broadcasting message.
    async fn stop_broadcast(&self, token: BroadcastToken) -> Result<(), String>;
    /// Gets the current status of a broadcasting message.
    async fn get_broadcast_status(&self, token: BroadcastToken) -> Result<BroadcastStatus, String>;
    /// Creates a receiver for every message broadcast to the network, except the one sent by this instance.
    async fn create_recv_queue(&self) -> Result<broadcast::Receiver<Vec<u8>>, ()>;
    /// Provides the estimated list of live nodes that are eligible and identified by their public keys.
    async fn get_live_list(&self) -> Result<Vec<PublicKey>, ()>;
}

Currently we have four unimplemented public interfaces (broadcast, stop_broadcast, get_broadcast_status, get_live_list).

broadcast

I expect it to be easy to implement, since FloodSub does the job.

stop_broadcast

I'll add two configurable parameters; one for the time interval between broadcast messages and the other for the timeout that specifies when to stop broadcasting the same message.

get_broadcast_status

This feature can't be implemented using FloodSub functions. Instead, I'll make every node dial directly to the message sender, once it receives a message, to notify the sender that it received the message successfully. The sender will collect this information to provide broadcast status.

The way to notify the sender is subject to change.

get_live_list

This will be implemented based on the broadcasting logic. Every node will regularly broadcast an "alive" message with some interval and collect the "alive" messages from other nodes to maintain the live list.

@posgnu
Copy link

posgnu commented Aug 13, 2022

Why don't we just assume the fully connected network? I guess we won't have that many validators, so having a network structure such as Kademlia is a little overkill?

@f2koi
Copy link
Contributor

f2koi commented Aug 14, 2022

@posgnu How many validators do you assume? Simperby is a general solution with its own consensus mechanism. I think it should be easily scalable to the maximum number of nodes assumed in the consensus specs (I guess up to several hundred ~ one thousand).

Many of the nodes might delegate their voting power to others and go offline, but we should assume the worst condition.

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

No branches or pull requests

3 participants