mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-02-22 23:59:49 -05:00
203 lines
5.3 KiB
Rust
203 lines
5.3 KiB
Rust
use libp2p::core::muxing::StreamMuxerBox;
|
|
use libp2p::core::transport;
|
|
use libp2p::core::upgrade::Version;
|
|
use libp2p::ping::{Ping, PingEvent};
|
|
use libp2p::swarm::{SwarmBuilder, SwarmEvent};
|
|
use libp2p::tcp::tokio::TcpStream;
|
|
use libp2p::{noise, yamux, Swarm, Transport};
|
|
use libp2p_tor::torut_ext::AuthenticatedConnectionExt;
|
|
use libp2p_tor::{dial_only, duplex};
|
|
use rand::Rng;
|
|
use std::collections::HashMap;
|
|
use std::convert::Infallible;
|
|
use std::future::Future;
|
|
use std::time::Duration;
|
|
use testcontainers::{Container, Docker, Image, WaitForMessage};
|
|
use torut::control::AuthenticatedConn;
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
async fn create_ephemeral_service() {
|
|
tracing_subscriber::fmt().with_env_filter("debug").init();
|
|
let wildcard_multiaddr =
|
|
"/onion3/WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW:8080"
|
|
.parse()
|
|
.unwrap();
|
|
|
|
// let docker = Cli::default();
|
|
//
|
|
// let tor1 = docker.run(TorImage::default().with_args(TorArgs {
|
|
// control_port: Some(9051),
|
|
// socks_port: None
|
|
// }));
|
|
// let tor2 = docker.run(TorImage::default());
|
|
//
|
|
// let tor1_control_port = tor1.get_host_port(9051).unwrap();
|
|
// let tor2_socks_port = tor2.get_host_port(9050).unwrap();
|
|
|
|
let mut listen_swarm = make_swarm(async move {
|
|
let mut onion_key_bytes = [0u8; 64];
|
|
rand::thread_rng().fill(&mut onion_key_bytes);
|
|
|
|
duplex::TorConfig::new(
|
|
AuthenticatedConn::with_password(9051, "supersecret")
|
|
.await
|
|
.unwrap(),
|
|
onion_key_bytes.into(),
|
|
)
|
|
.await
|
|
.unwrap()
|
|
.boxed()
|
|
})
|
|
.await;
|
|
let mut dial_swarm = make_swarm(async { dial_only::TorConfig::new(9050).boxed() }).await;
|
|
|
|
listen_swarm.listen_on(wildcard_multiaddr).unwrap();
|
|
|
|
let onion_listen_addr = loop {
|
|
let event = listen_swarm.next_event().await;
|
|
|
|
tracing::info!("{:?}", event);
|
|
|
|
if let SwarmEvent::NewListenAddr(addr) = event {
|
|
break addr;
|
|
}
|
|
};
|
|
|
|
dial_swarm.dial_addr(onion_listen_addr).unwrap();
|
|
|
|
loop {
|
|
tokio::select! {
|
|
event = listen_swarm.next_event() => {
|
|
tracing::info!("{:?}", event);
|
|
},
|
|
event = dial_swarm.next_event() => {
|
|
tracing::info!("{:?}", event);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
async fn make_swarm(
|
|
transport_future: impl Future<Output = transport::Boxed<TcpStream>>,
|
|
) -> Swarm<Behaviour> {
|
|
let identity = libp2p::identity::Keypair::generate_ed25519();
|
|
|
|
let dh_keys = noise::Keypair::<noise::X25519Spec>::new()
|
|
.into_authentic(&identity)
|
|
.unwrap();
|
|
let noise = noise::NoiseConfig::xx(dh_keys).into_authenticated();
|
|
|
|
let transport = transport_future
|
|
.await
|
|
.upgrade(Version::V1)
|
|
.authenticate(noise)
|
|
.multiplex(yamux::YamuxConfig::default())
|
|
.timeout(Duration::from_secs(20))
|
|
.map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer)))
|
|
.boxed();
|
|
|
|
SwarmBuilder::new(
|
|
transport,
|
|
Behaviour::default(),
|
|
identity.public().into_peer_id(),
|
|
)
|
|
.executor(Box::new(|f| {
|
|
tokio::spawn(f);
|
|
}))
|
|
.build()
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
enum OutEvent {
|
|
Ping(PingEvent),
|
|
}
|
|
|
|
impl From<PingEvent> for OutEvent {
|
|
fn from(e: PingEvent) -> Self {
|
|
OutEvent::Ping(e)
|
|
}
|
|
}
|
|
|
|
#[derive(libp2p::NetworkBehaviour, Default)]
|
|
#[behaviour(event_process = false, out_event = "OutEvent")]
|
|
struct Behaviour {
|
|
ping: Ping,
|
|
}
|
|
|
|
#[derive(Default)]
|
|
struct TorImage {
|
|
args: TorArgs,
|
|
}
|
|
|
|
impl TorImage {
|
|
// fn control_port_password(&self) -> String {
|
|
// "supersecret".to_owned()
|
|
// }
|
|
}
|
|
|
|
#[derive(Default, Copy, Clone)]
|
|
struct TorArgs {
|
|
control_port: Option<u16>,
|
|
socks_port: Option<u16>,
|
|
}
|
|
|
|
impl IntoIterator for TorArgs {
|
|
type Item = String;
|
|
type IntoIter = std::vec::IntoIter<String>;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
let mut args = Vec::new();
|
|
|
|
if let Some(port) = self.socks_port {
|
|
args.push("SocksPort".to_string());
|
|
args.push(format!("0.0.0.0:{}", port));
|
|
}
|
|
|
|
if let Some(port) = self.control_port {
|
|
args.push("ControlPort".to_string());
|
|
args.push(format!("0.0.0.0:{}", port));
|
|
args.push("HashedControlPassword".to_string());
|
|
args.push("16:436B425404AA332A60B4F341C2023146C4B3A80548D757F0BB10DE81B4"
|
|
.to_string())
|
|
}
|
|
|
|
args.into_iter()
|
|
}
|
|
}
|
|
|
|
impl Image for TorImage {
|
|
type Args = TorArgs;
|
|
type EnvVars = HashMap<String, String>;
|
|
type Volumes = HashMap<String, String>;
|
|
type EntryPoint = Infallible;
|
|
|
|
fn descriptor(&self) -> String {
|
|
"testcontainers-tor:latest".to_owned() // this is build locally using
|
|
// the buildscript
|
|
}
|
|
|
|
fn wait_until_ready<D: Docker>(&self, container: &Container<'_, D, Self>) {
|
|
container
|
|
.logs()
|
|
.stdout
|
|
.wait_for_message("Bootstrapped 100% (done): Done")
|
|
.unwrap();
|
|
}
|
|
|
|
fn args(&self) -> Self::Args {
|
|
self.args
|
|
}
|
|
|
|
fn env_vars(&self) -> Self::EnvVars {
|
|
HashMap::new()
|
|
}
|
|
|
|
fn volumes(&self) -> Self::Volumes {
|
|
HashMap::new()
|
|
}
|
|
|
|
fn with_args(self, args: Self::Args) -> Self {
|
|
Self { args }
|
|
}
|
|
}
|