Skip to content

Commit

Permalink
feat: Add initial peer-resolver lib implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
aidan46 committed Dec 17, 2024
1 parent 48893f3 commit 6ac62f9
Show file tree
Hide file tree
Showing 10 changed files with 1,159 additions and 72 deletions.
776 changes: 704 additions & 72 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ repository = "https://github.com/eigerco/polka-storage"

[workspace]
members = [
"lib/peer-resolver",
"lib/polka-storage-proofs",
"maat",
"mater/cli",
Expand Down Expand Up @@ -78,6 +79,7 @@ ipld-core = "0.4.1"
ipld-dagpb = "0.2.1"
itertools = "0.13.0"
jsonrpsee = { version = "0.24.7" }
libp2p = { git = "https://github.com/libp2p/rust-libp2p", version = "0.54.2", default-features = false }
log = { version = "0.4.21", default-features = false }
multihash-codetable = { version = "0.1.1", default-features = false }
num-bigint = { version = "0.4.5", default-features = false }
Expand Down
22 changes: 22 additions & 0 deletions lib/peer-resolver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
authors.workspace = true
edition.workspace = true
homepage.workspace = true
license-file.workspace = true
name = "peer-resolver"
repository.workspace = true
version = "0.1.0"

[dependencies]
anyhow.workspace = true
libp2p = { workspace = true, features = ["identify", "macros", "noise", "rendezvous", "tcp", "tokio", "yamux"] }
thiserror.workspace = true
tokio = { workspace = true, features = ["macros", "time"] }
tracing.workspace = true

[dev-dependencies]
tokio = { workspace = true, features = ["rt-multi-thread"] }
tracing-subscriber = { workspace = true, features = ["env-filter"] }

[lints]
workspace = true
20 changes: 20 additions & 0 deletions lib/peer-resolver/examples/bootstrap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use anyhow::Result;
use peer_resolver::BootstrapSwarm;
use tracing_subscriber::EnvFilter;

#[tokio::main]
async fn main() -> Result<()> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();

// Results in PeerID 12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN which is
// used as the rendezvous point by the other peer examples.
let keypair = libp2p::identity::Keypair::ed25519_from_bytes([0; 32]).unwrap();

let mut swarm = BootstrapSwarm::new(keypair)?;

swarm.run("/ip4/0.0.0.0/tcp/62649".parse()?).await?;

Ok(())
}
25 changes: 25 additions & 0 deletions lib/peer-resolver/examples/discovery.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use anyhow::Result;
use libp2p::{Multiaddr, PeerId};
use peer_resolver::ClientSwarm;
use tracing_subscriber::EnvFilter;

#[tokio::main]
async fn main() -> Result<()> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();

let rendezvous_point =
"12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN".parse::<PeerId>()?;
let rendezvous_point_address = "/ip4/127.0.0.1/tcp/62649".parse::<Multiaddr>()?;
// Results in peer id 12D3KooWJWoaqZhDaoEFshF7Rh1bpY9ohihFhzcW6d69Lr2NASuq
let keypair = libp2p::identity::Keypair::ed25519_from_bytes([2; 32]).unwrap();

let mut swarm = ClientSwarm::new(keypair, "rendezvous".to_string())?;

swarm
.initial_discovery(rendezvous_point, rendezvous_point_address)
.await?;
swarm.discovery(1, rendezvous_point).await?;
Ok(())
}
24 changes: 24 additions & 0 deletions lib/peer-resolver/examples/register.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use anyhow::Result;
use libp2p::{Multiaddr, PeerId};
use peer_resolver::ClientSwarm;
use tracing_subscriber::EnvFilter;

#[tokio::main]
async fn main() -> Result<()> {
let _ = tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env())
.try_init();

let rendezvous_point_address = "/ip4/127.0.0.1/tcp/62649".parse::<Multiaddr>()?;
let rendezvous_point =
"12D3KooWDpJ7As7BWAwRMfu1VU2WCqNjvq387JEYKDBj4kx6nXTN".parse::<PeerId>()?;
// Results in peer id 12D3KooWK99VoVxNE7XzyBwXEzW7xhK7Gpv85r9F3V3fyKSUKPH5
let keypair = libp2p::identity::Keypair::ed25519_from_bytes([1; 32]).unwrap();

let mut swarm = ClientSwarm::new(keypair, "rendezvous".to_string())?;

swarm
.register(rendezvous_point, rendezvous_point_address)
.await?;
Ok(())
}
86 changes: 86 additions & 0 deletions lib/peer-resolver/src/bootstrap.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
use libp2p::{
futures::StreamExt,
identity::Keypair,
rendezvous::server,
swarm::{NetworkBehaviour, SwarmEvent},
{noise, rendezvous, tcp, yamux, Multiaddr, Swarm},
};

use crate::error::ResolverError;

/// This struct holds all the behaviour for the bootstrap node.
#[derive(NetworkBehaviour)]
pub struct BootstrapBehaviour {
/// Rendezvous server behaviour for peer discovery
rendezvous: server::Behaviour,
}

/// This struct is used by bootstrap nodes running a swarm aiding in peer discovery
pub struct BootstrapSwarm {
/// Swarm with [`BootstrapBehaviour`]
swarm: Swarm<BootstrapBehaviour>,
}

impl BootstrapSwarm {
/// Create a new [`BootstrapSwarm`] with the given keypair.
pub fn new(keypair: Keypair) -> Result<BootstrapSwarm, ResolverError> {
let swarm = libp2p::SwarmBuilder::with_existing_identity(keypair)
.with_tokio()
.with_tcp(
tcp::Config::default(),
noise::Config::new,
yamux::Config::default,
)
.map_err(|_| ResolverError::InvalidTCPConfig)?
.with_behaviour(|_| BootstrapBehaviour {
rendezvous: rendezvous::server::Behaviour::new(
rendezvous::server::Config::default(),
),
})
.map_err(|_| ResolverError::InvalidBehaviourConfig)?
.build();

Ok(BootstrapSwarm { swarm })
}

/// Run the rendezvous point (bootstrap node).
/// Listens on the given [`Multiaddr`]
pub async fn run(&mut self, addr: Multiaddr) -> Result<(), ResolverError> {
self.swarm
.listen_on(addr)
.map_err(|_| ResolverError::ListenError)?;
while let Some(event) = self.swarm.next().await {
match event {
SwarmEvent::ConnectionEstablished { peer_id, .. } => {
tracing::info!("Connected to {}", peer_id);
}
SwarmEvent::ConnectionClosed { peer_id, .. } => {
tracing::info!("Disconnected from {}", peer_id);
}
SwarmEvent::Behaviour(BootstrapBehaviourEvent::Rendezvous(
rendezvous::server::Event::PeerRegistered { peer, registration },
)) => {
tracing::info!(
"Peer {} registered for namespace '{}'",
peer,
registration.namespace
);
}
SwarmEvent::Behaviour(BootstrapBehaviourEvent::Rendezvous(
rendezvous::server::Event::DiscoverServed {
enquirer,
registrations,
},
)) => {
tracing::info!(
"Served peer {} with {} registrations",
enquirer,
registrations.len()
);
}
_other => {}
}
}
Ok(())
}
}
Loading

0 comments on commit 6ac62f9

Please sign in to comment.