You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wow-btc-swap/libp2p-tor/examples/listener.rs

147 lines
4.9 KiB

use libp2p::core::muxing::StreamMuxerBox;
use libp2p::core::upgrade::{SelectUpgrade, Version};
use libp2p::identity::Keypair;
use libp2p::mplex::MplexConfig;
use libp2p::ping::{Ping, PingEvent, PingSuccess};
use libp2p::swarm::{SwarmBuilder, SwarmEvent};
use libp2p::{identity, noise, yamux, Multiaddr, Swarm, Transport};
use libp2p_tor::duplex;
use libp2p_tor::torut_ext::AuthenticatedConnectionExt;
use noise::NoiseConfig;
use std::str::FromStr;
use std::time::Duration;
use torut::control::AuthenticatedConn;
use torut::onion::TorSecretKeyV3;
use tracing_subscriber::util::SubscriberInitExt;
use libp2p_tor::duplex::TorutAsyncEventHandler;
use libp2p::tcp::TokioTcpConfig;
#[tokio::main(flavor = "multi_thread")]
async fn main() {
tracing_subscriber::fmt()
.with_env_filter("trace") // add `reqwest::connect::verbose=trace` if you want to logs of the RPC clients
.init();
let key = fixed_onion_identity();
let onion_address = key
.public()
.get_onion_address()
.get_address_without_dot_onion();
tracing::info!("{}", onion_address);
let onion_port = 7654;
let mut client = AuthenticatedConn::new(9051).await.unwrap();
client
.add_ephemeral_service(&key, onion_port, onion_port)
.await
.unwrap();
let mut swarm = new_swarm(client, key).await;
let peer_id = *swarm.local_peer_id();
tracing::info!("Peer-ID: {}", peer_id);
// TODO: Figure out what to with the port, we could also set it to 0 and then
// imply it from the assigned port swarm.listen_on(Multiaddr::
// from_str(format!("/onion3/{}:{}", onion_address,
// onion_port).as_str()).unwrap()).unwrap();
// swarm
// .listen_on(
// Multiaddr::from_str(format!("/onion3/{}:{}", onion_address, onion_port).as_str()).unwrap(),
// )
// .unwrap();
swarm
.listen_on(
Multiaddr::from_str(format!("/ip4/127.0.0.1/tcp/{}", onion_port).as_str()).unwrap(),
)
.unwrap();
loop {
match swarm.next_event().await {
SwarmEvent::NewListenAddr(addr) => {
tracing::info!("Listening on {}", addr);
tracing::info!("Connection string: {}/p2p/{}", addr, peer_id);
}
SwarmEvent::ConnectionEstablished {
peer_id, endpoint, ..
} => {
tracing::info!(
"Connected to {} via {}",
peer_id,
endpoint.get_remote_address()
);
}
SwarmEvent::Behaviour(PingEvent { result, peer }) => match result {
Ok(PingSuccess::Pong) => {
tracing::info!("Got pong from {}", peer);
}
Ok(PingSuccess::Ping { rtt }) => {
tracing::info!("Pinged {} with rtt of {}s", peer, rtt.as_secs());
}
Err(failure) => {
tracing::info!("Failed to ping {}: {}", peer, failure)
}
},
event => {
tracing::debug!("Swarm event: {:?}", event)
}
}
}
}
/// Builds a new swarm that is capable of listening and dialling on the Tor
/// network.
///
/// In particular, this swarm can create ephemeral hidden services on the
/// configured Tor node.
async fn new_swarm(client: AuthenticatedConn<tokio::net::TcpStream, TorutAsyncEventHandler>, key: TorSecretKeyV3) -> Swarm<Ping> {
let identity = fixed_libp2p_identity();
SwarmBuilder::new(
TokioTcpConfig::new().nodelay(true)
.boxed()
.upgrade(Version::V1)
.authenticate(
NoiseConfig::xx(
noise::Keypair::<noise::X25519Spec>::new()
.into_authentic(&identity)
.unwrap(),
)
.into_authenticated(),
)
.multiplex(SelectUpgrade::new(
yamux::YamuxConfig::default(),
MplexConfig::new(),
))
.timeout(Duration::from_secs(20))
.map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer)))
.boxed(),
Ping::default(),
identity.public().into_peer_id(),
)
.executor(Box::new(|f| {
tokio::spawn(f);
}))
.build()
}
fn fixed_onion_identity() -> TorSecretKeyV3 {
TorSecretKeyV3::generate()
}
fn fixed_libp2p_identity() -> Keypair {
// randomly venerated bytes, corresponding peer-id:
// 12D3KooWHKqGyK4hVtf5BQY8GpbY6fSGKDZ8eBXMQ3H2RsdnKVzC
let fixed_identity = [
75, 146, 26, 107, 50, 252, 71, 2, 238, 224, 92, 112, 216, 238, 131, 57, 84, 9, 218, 120,
195, 9, 129, 102, 42, 206, 165, 102, 32, 238, 158, 248,
];
let key =
identity::ed25519::SecretKey::from_bytes(fixed_identity).expect("we always pass 32 bytes");
identity::Keypair::Ed25519(key.into())
}