Skip to content

Commit

Permalink
feat: add RPC calls for p2p module and tests for them (#52)
Browse files Browse the repository at this point in the history
* feat: add RPC calls for p2p module and tests for them

* fix node test

* remove not needed dev-dependencies

* fix dev-dependencies properly

* add files to fix formatting

* Address PR comments, add libp2p feature

* fix feature flag and last asserts

* remove not directly needed libp2p-identity

* and fmt

* appease clippy

* run clippy for all targets

* simplify ser/de of PeerId, add note about the go-jsonrpc workaround

* make figuring out node ip better

* remove task handle return

* split libp2p and add style changes for Yannis review

* fmt

* fmt

* fixup doc-comments, tighten feature flag

* feature libp2p->p2p rename

* Update rpc/tests/p2p.rs

Co-authored-by: Maciej Zwoliński <mac.zwolinski@gmail.com>

---------

Co-authored-by: Maciej Zwoliński <mac.zwolinski@gmail.com>
  • Loading branch information
fl0rek and zvolin authored Sep 7, 2023
1 parent 3a4f432 commit aa810b7
Show file tree
Hide file tree
Showing 15 changed files with 533 additions and 28 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}

- name: Run clippy
run: cargo clippy --all -- -D warnings
run: cargo clippy --all --all-targets -- -D warnings


fmt:
Expand Down
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 4 additions & 8 deletions celestia/src/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::env;
use anyhow::{Context, Result};
use celestia_node::node::{Node, NodeConfig};
use celestia_rpc::prelude::*;
use libp2p::{core::upgrade::Version, identity, noise, tcp, yamux, Multiaddr, Transport};
use libp2p::{core::upgrade::Version, identity, noise, tcp, yamux, Transport};

const WS_URL: &str = "ws://localhost:26658";

Expand All @@ -15,15 +15,11 @@ pub async fn run() -> Result<()> {
let auth_token = env::var("CELESTIA_NODE_AUTH_TOKEN_ADMIN")?;
let client = celestia_rpc::client::new_websocket(WS_URL, Some(&auth_token)).await?;
let bridge_info = client.p2p_info().await?;
let bridge_maddrs: Vec<Multiaddr> = bridge_info
.addrs
.into_iter()
.map(|addr| addr.parse().context("Parsing addr failed"))
.collect::<Result<_>>()?;
println!("bridge id: {:?}", bridge_info.id);
println!("bridge listens on: {bridge_maddrs:?}");
println!("bridge listens on: {:?}", bridge_info.addrs);

let bridge_ma = bridge_maddrs
let bridge_ma = bridge_info
.addrs
.into_iter()
.find(|ma| ma.protocol_stack().any(|protocol| protocol == "tcp"))
.context("Bridge doesn't listen on tcp")?;
Expand Down
9 changes: 2 additions & 7 deletions node/tests/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,9 @@ async fn get_bridge_tcp_ma() -> Multiaddr {
.unwrap();

let bridge_info = client.p2p_info().await.unwrap();
let bridge_maddrs: Vec<Multiaddr> = bridge_info
.addrs
.into_iter()
.map(|addr| addr.parse())
.collect::<Result<_, _>>()
.unwrap();

bridge_maddrs
bridge_info
.addrs
.into_iter()
.find(|ma| ma.protocol_stack().any(|protocol| protocol == "tcp"))
.expect("Bridge doesn't listen on tcp")
Expand Down
7 changes: 7 additions & 0 deletions rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,12 @@ jsonrpsee = { version = "0.20", features = ["http-client", "ws-client"] }
[dev-dependencies]
anyhow = "1.0.71"
dotenvy = "0.15.7"
futures = "0.3.28"
libp2p = "0.52.3"
log = "0.4"
rand = "0.8.5"
tokio = { version = "1.32.0", features = ["rt", "macros"] }

[features]
default = ["p2p"]
p2p = ["celestia-types/p2p"]
3 changes: 3 additions & 0 deletions rpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@ mod blob;
pub mod client;
mod error;
mod header;
#[cfg(feature = "p2p")]
pub mod p2p;
mod share;
mod state;

pub use crate::blob::BlobClient;
pub use crate::error::{Error, Result};
pub use crate::header::HeaderClient;
#[cfg(feature = "p2p")]
pub use crate::p2p::P2PClient;
pub use crate::share::ShareClient;
pub use crate::state::StateClient;

pub mod prelude {
pub use crate::BlobClient;
pub use crate::HeaderClient;
#[cfg(feature = "p2p")]
pub use crate::P2PClient;
pub use crate::ShareClient;
pub use crate::StateClient;
Expand Down
88 changes: 78 additions & 10 deletions rpc/src/p2p.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,85 @@
use celestia_types::p2p::{
AddrInfo, BandwidthStats, Connectedness, PeerId, Reachability, ResourceManagerStats,
};
use jsonrpsee::proc_macros::rpc;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct AddrInfo {
#[serde(rename = "ID")]
pub id: String,
// TODO: multiaddr
#[serde(rename = "Addrs")]
pub addrs: Vec<String>,
}

#[rpc(client)]
pub trait P2P {
/// BandwidthForPeer returns a Stats struct with bandwidth metrics associated with the given peer.ID. The metrics returned include all traffic sent / received for the peer, regardless of protocol.
#[method(name = "p2p.BandwidthForPeer")]
async fn p2p_bandwidth_for_peer(&self, peer_id: &PeerId) -> Result<BandwidthStats, Error>;

/// BandwidthForProtocol returns a Stats struct with bandwidth metrics associated with the given protocol.ID.
#[method(name = "p2p.BandwidthForProtocol")]
async fn p2p_bandwidth_for_protocol(&self, protocol_id: &str) -> Result<BandwidthStats, Error>;

/// BandwidthStats returns a Stats struct with bandwidth metrics for all data sent/received by the local peer, regardless of protocol or remote peer IDs.
#[method(name = "p2p.BandwidthStats")]
async fn p2p_bandwidth_stats(&self) -> Result<BandwidthStats, Error>;

// This method does not report errors due to a workaround to a go-jsonrpc bug, see https://github.com/eigerco/celestia-node-rs/issues/53
/// BlockPeer adds a peer to the set of blocked peers.
#[method(name = "p2p.BlockPeer")]
async fn p2p_block_peer(&self, peer_id: &PeerId);

// This method does not report errors due to a workaround to a go-jsonrpc bug, see https://github.com/eigerco/celestia-node-rs/issues/53
/// ClosePeer closes the connection to a given peer.
#[method(name = "p2p.ClosePeer")]
async fn p2p_close_peer(&self, peer_id: &PeerId);

// This method does not report errors due to a workaround to a go-jsonrpc bug, see https://github.com/eigerco/celestia-node-rs/issues/53
/// Connect ensures there is a connection between this host and the peer with given peer.
#[method(name = "p2p.Connect")]
async fn p2p_connect(&self, address: &AddrInfo);

/// Connectedness returns a state signaling connection capabilities.
#[method(name = "p2p.Connectedness")]
async fn p2p_connectedness(&self, peer_id: &PeerId) -> Result<Connectedness, Error>;

/// Info returns address information about the host.
#[method(name = "p2p.Info")]
async fn p2p_info(&self) -> Result<AddrInfo, Error>;

/// IsProtected returns whether the given peer is protected.
#[method(name = "p2p.IsProtected")]
async fn p2p_is_protected(&self, peer_id: &PeerId, tag: &str) -> Result<bool, Error>;

/// ListBlockedPeers returns a list of blocked peers.
#[method(name = "p2p.ListBlockedPeers")]
async fn p2p_list_blocked_peers(&self) -> Result<Vec<PeerId>, Error>;

/// NATStatus returns the current NAT status.
#[method(name = "p2p.NATStatus")]
async fn p2p_nat_status(&self) -> Result<Reachability, Error>;

/// PeerInfo returns a small slice of information Peerstore has on the given peer.
#[method(name = "p2p.PeerInfo")]
async fn p2p_peer_info(&self, peer_id: &PeerId) -> Result<AddrInfo, Error>;

/// Peers returns connected peers.
#[method(name = "p2p.Peers")]
async fn p2p_peers(&self) -> Result<Vec<PeerId>, Error>;

// This method does not report errors due to a workaround to a go-jsonrpc bug, see https://github.com/eigerco/celestia-node-rs/issues/53
/// Protect adds a peer to the list of peers who have a bidirectional peering agreement that they are protected from being trimmed, dropped or negatively scored.
#[method(name = "p2p.Protect")]
async fn p2p_protect(&self, peer_id: &PeerId, tag: &str);

// We might get null in response here, so Option is needed
/// PubSubPeers returns the peer IDs of the peers joined on the given topic.
#[method(name = "p2p.PubSubPeers")]
async fn p2p_pub_sub_peers(&self, topic: &str) -> Result<Option<Vec<PeerId>>, Error>;

/// ResourceState returns the state of the resource manager.
#[method(name = "p2p.ResourceState")]
async fn p2p_resource_state(&self) -> Result<ResourceManagerStats, Error>;

// This method does not report errors due to a workaround to a go-jsonrpc bug, see https://github.com/eigerco/celestia-node-rs/issues/53
/// UnblockPeer removes a peer from the set of blocked peers.
#[method(name = "p2p.UnblockPeer")]
async fn p2p_unblock_peer(&self, peer_id: &PeerId);

/// Unprotect removes a peer from the list of peers who have a bidirectional peering agreement that they are protected from being trimmed, dropped or negatively scored, returning a bool representing whether the given peer is protected or not.
#[method(name = "p2p.Unprotect")]
async fn p2p_unprotect(&self, peer_id: &PeerId, tag: &str) -> Result<bool, Error>;
}
Loading

0 comments on commit aa810b7

Please sign in to comment.