mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-12-24 15:09:35 -05:00
Extract transport creation and remove tor conditional compile
The numerous tor conditional compile flags were removed by extracting transport creation to the main statement. A tor transport is created if Alice specifies a tor port using the CLI.
This commit is contained in:
parent
0ca511bf8a
commit
796d0b3439
@ -32,7 +32,8 @@ structopt = "0.3"
|
||||
tempfile = "3"
|
||||
time = "0.2"
|
||||
tokio = { version = "0.2", features = ["rt-threaded", "time", "macros", "sync"] }
|
||||
torut = { version = "0.1", optional = true }
|
||||
#torut = { version = "0.1", optional = true }
|
||||
torut = { version = "0.1"}
|
||||
tracing = { version = "0.1", features = ["attributes"] }
|
||||
tracing-core = "0.1"
|
||||
tracing-futures = { version = "0.2", features = ["std-future", "futures-03"] }
|
||||
@ -49,6 +50,6 @@ spectral = "0.6"
|
||||
tempfile = "3"
|
||||
testcontainers = "0.10"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
tor = ["torut"]
|
||||
#[features]
|
||||
#default = []
|
||||
#tor = ["torut"]
|
||||
|
@ -28,7 +28,9 @@ use crate::{
|
||||
network::{
|
||||
peer_tracker::{self, PeerTracker},
|
||||
request_response::AliceToBob,
|
||||
transport, TokioExecutor,
|
||||
transport,
|
||||
transport::SwapTransport,
|
||||
TokioExecutor,
|
||||
},
|
||||
SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
|
||||
};
|
||||
@ -43,7 +45,10 @@ pub async fn swap(
|
||||
bitcoin_wallet: Arc<bitcoin::Wallet>,
|
||||
monero_wallet: Arc<monero::Wallet>,
|
||||
listen: Multiaddr,
|
||||
local_port: Option<u16>,
|
||||
redeem_address: ::bitcoin::Address,
|
||||
punish_address: ::bitcoin::Address,
|
||||
transport: SwapTransport,
|
||||
behaviour: Alice,
|
||||
) -> Result<()> {
|
||||
struct Network {
|
||||
swarm: Arc<Mutex<Swarm>>,
|
||||
@ -96,7 +101,7 @@ pub async fn swap(
|
||||
}
|
||||
}
|
||||
|
||||
let mut swarm = new_swarm(listen, local_port)?;
|
||||
let mut swarm = new_swarm(listen, transport, behaviour)?;
|
||||
let message0: bob::Message0;
|
||||
let mut state0: Option<alice::State0> = None;
|
||||
let mut last_amounts: Option<SwapAmounts> = None;
|
||||
@ -230,30 +235,11 @@ pub async fn swap(
|
||||
|
||||
pub type Swarm = libp2p::Swarm<Alice>;
|
||||
|
||||
fn new_swarm(listen: Multiaddr, port: Option<u16>) -> Result<Swarm> {
|
||||
fn new_swarm(listen: Multiaddr, transport: SwapTransport, behaviour: Alice) -> Result<Swarm> {
|
||||
use anyhow::Context as _;
|
||||
|
||||
let behaviour = Alice::default();
|
||||
|
||||
let local_key_pair = behaviour.identity();
|
||||
let local_peer_id = behaviour.peer_id();
|
||||
|
||||
let transport;
|
||||
#[cfg(feature = "tor")]
|
||||
{
|
||||
transport = match port {
|
||||
Some(port) => transport::build(local_key_pair, Some((listen.clone(), port)))?,
|
||||
None => anyhow::bail!("Must supply local port"),
|
||||
};
|
||||
}
|
||||
#[cfg(not(feature = "tor"))]
|
||||
{
|
||||
transport = match port {
|
||||
None => transport::build(local_key_pair)?,
|
||||
Some(_) => anyhow::bail!("local port should not be provided for non-tor usage"),
|
||||
};
|
||||
}
|
||||
|
||||
let mut swarm = libp2p::swarm::SwarmBuilder::new(transport, behaviour, local_peer_id.clone())
|
||||
.executor(Box::new(TokioExecutor {
|
||||
handle: tokio::runtime::Handle::current(),
|
||||
|
@ -27,7 +27,9 @@ use crate::{
|
||||
monero,
|
||||
network::{
|
||||
peer_tracker::{self, PeerTracker},
|
||||
transport, TokioExecutor,
|
||||
transport,
|
||||
transport::SwapTransport,
|
||||
TokioExecutor,
|
||||
},
|
||||
Cmd, Rsp, SwapAmounts, PUNISH_TIMELOCK, REFUND_TIMELOCK,
|
||||
};
|
||||
@ -45,6 +47,8 @@ pub async fn swap(
|
||||
addr: Multiaddr,
|
||||
mut cmd_tx: Sender<Cmd>,
|
||||
mut rsp_rx: Receiver<Rsp>,
|
||||
transport: SwapTransport,
|
||||
behaviour: Bob,
|
||||
) -> Result<()> {
|
||||
struct Network(Swarm);
|
||||
|
||||
@ -80,7 +84,7 @@ pub async fn swap(
|
||||
}
|
||||
}
|
||||
|
||||
let mut swarm = new_swarm()?;
|
||||
let mut swarm = new_swarm(transport, behaviour)?;
|
||||
|
||||
libp2p::Swarm::dial_addr(&mut swarm, addr)?;
|
||||
let alice = match swarm.next().await {
|
||||
@ -202,23 +206,9 @@ pub async fn swap(
|
||||
|
||||
pub type Swarm = libp2p::Swarm<Bob>;
|
||||
|
||||
fn new_swarm() -> Result<Swarm> {
|
||||
let behaviour = Bob::default();
|
||||
|
||||
let local_key_pair = behaviour.identity();
|
||||
fn new_swarm(transport: SwapTransport, behaviour: Bob) -> Result<Swarm> {
|
||||
let local_peer_id = behaviour.peer_id();
|
||||
|
||||
let transport = {
|
||||
#[cfg(feature = "tor")]
|
||||
{
|
||||
transport::build(local_key_pair, None)?
|
||||
}
|
||||
#[cfg(not(feature = "tor"))]
|
||||
{
|
||||
transport::build(local_key_pair)?
|
||||
}
|
||||
};
|
||||
|
||||
let swarm = libp2p::swarm::SwarmBuilder::new(transport, behaviour, local_peer_id.clone())
|
||||
.executor(Box::new(TokioExecutor {
|
||||
handle: tokio::runtime::Handle::current(),
|
||||
|
@ -4,41 +4,32 @@ use url::Url;
|
||||
#[derive(structopt::StructOpt, Debug)]
|
||||
pub enum Options {
|
||||
Alice {
|
||||
/// Run the swap as Bob and try to swap this many BTC (in satoshi).
|
||||
#[structopt(long = "sats")]
|
||||
satoshis: u64,
|
||||
|
||||
// /// Run the swap as Bob and try to swap this many XMR (in piconero).
|
||||
// #[structopt(long = "picos", conflicts_with = "sats"))]
|
||||
// pub piconeros: u64,
|
||||
#[structopt(default_value = "http://127.0.0.1:8332", long = "bitcoind")]
|
||||
bitcoind_url: Url,
|
||||
|
||||
#[structopt(default_value = "127.0.0.1", long = "listen_addr")]
|
||||
listen_addr: String,
|
||||
#[structopt(default_value = "/ip4/127.0.0.1/tcp/9876", long = "listen-addr")]
|
||||
listen_addr: Multiaddr,
|
||||
|
||||
#[structopt(default_value = 9876, long = "list_port")]
|
||||
listen_port: u16,
|
||||
/// Run the swap as Bob and try to swap this many BTC (in satoshi).
|
||||
// #[cfg(feature = "tor")]
|
||||
#[structopt(long = "tor-port")]
|
||||
tor_port: Option<u16>,
|
||||
},
|
||||
Bob {
|
||||
/// Alice's multitaddr (only required for Bob, Alice will autogenerate
|
||||
/// one)
|
||||
#[structopt(long = "alice_addr")]
|
||||
alice_addr: Multiaddr,
|
||||
|
||||
/// Run the swap as Bob and try to swap this many BTC (in satoshi).
|
||||
#[structopt(long = "sats")]
|
||||
satoshis: u64,
|
||||
|
||||
#[structopt(long = "alice-addr")]
|
||||
alice_addr: Multiaddr,
|
||||
|
||||
// /// Run the swap as Bob and try to swap this many XMR (in piconero).
|
||||
// #[structopt(long = "picos", conflicts_with = "sats"))]
|
||||
// pub piconeros: u64,
|
||||
#[structopt(default_value = "http://127.0.0.1:8332", long = "bitcoind")]
|
||||
bitcoind_url: Url,
|
||||
// #[structopt(default_value = "/ip4/127.0.0.1/tcp/9876", long = "dial")]
|
||||
// alice_addr: String,
|
||||
#[cfg(feature = "tor")]
|
||||
#[structopt(long = "tor")]
|
||||
tor_port: u16,
|
||||
},
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ pub mod bob;
|
||||
pub mod monero;
|
||||
pub mod network;
|
||||
pub mod storage;
|
||||
#[cfg(feature = "tor")]
|
||||
//#[cfg(feature = "tor")]
|
||||
pub mod tor;
|
||||
|
||||
const REFUND_TIMELOCK: u32 = 10; // Relative timelock, this is number of blocks. TODO: What should it be?
|
||||
|
118
swap/src/main.rs
118
swap/src/main.rs
@ -12,14 +12,24 @@
|
||||
)]
|
||||
#![forbid(unsafe_code)]
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use anyhow::Result;
|
||||
use futures::{channel::mpsc, StreamExt};
|
||||
use libp2p::core::Multiaddr;
|
||||
use log::LevelFilter;
|
||||
use std::{io, io::Write, process, sync::Arc};
|
||||
use structopt::StructOpt;
|
||||
use swap::{
|
||||
alice,
|
||||
alice::Alice,
|
||||
bitcoin::Wallet,
|
||||
bob,
|
||||
bob::Bob,
|
||||
network::transport::{build, build_tor, SwapTransport},
|
||||
Cmd, Rsp, SwapAmounts,
|
||||
};
|
||||
use tracing::info;
|
||||
use url::Url;
|
||||
use xmr_btc::bitcoin::{BroadcastSignedTransaction, BuildTxLockPsbt, SignTxLock};
|
||||
|
||||
mod cli;
|
||||
mod trace;
|
||||
@ -29,15 +39,6 @@ use swap::{alice, bitcoin, bob, monero, Cmd, Rsp, SwapAmounts};
|
||||
|
||||
// TODO: Add root seed file instead of generating new seed each run.
|
||||
|
||||
// // TODO: Add a config file with these in it.
|
||||
// // Alice's address and port until we have a config file.
|
||||
// pub const LISTEN_PORT: u16 = 9876; // Arbitrarily chosen.
|
||||
// pub const LISTEN_ADDR: &str = "127.0.0.1";
|
||||
// pub const BITCOIND_JSON_RPC_URL: &str = "http://127.0.0.1:8332";
|
||||
//
|
||||
// #[cfg(feature = "tor")]
|
||||
// pub const TOR_PORT: u16 = LISTEN_PORT + 1;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
let opt: Options = Options::from_args();
|
||||
@ -48,29 +49,31 @@ async fn main() -> Result<()> {
|
||||
Options::Alice {
|
||||
bitcoind_url: url,
|
||||
listen_addr,
|
||||
listen_port,
|
||||
tor_port,
|
||||
..
|
||||
} => {
|
||||
info!("running swap node as Alice ...");
|
||||
|
||||
#[cfg(feature = "tor")]
|
||||
let (alice, _ac) = {
|
||||
let tor_secret_key = torut::onion::TorSecretKeyV3::generate();
|
||||
let onion_address = tor_secret_key
|
||||
.public()
|
||||
.get_onion_address()
|
||||
.get_address_without_dot_onion();
|
||||
let onion_address_string = format!("/onion3/{}:{}", onion_address, TOR_PORT);
|
||||
let addr: Multiaddr = onion_address_string.parse()?;
|
||||
let behaviour = Alice::default();
|
||||
let local_key_pair = behaviour.identity();
|
||||
|
||||
(addr, create_tor_service(tor_secret_key).await?)
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "tor"))]
|
||||
let alice = {
|
||||
let alice: Multiaddr = listen_addr
|
||||
.parse()
|
||||
.expect("failed to parse Alice's address");
|
||||
let (listen_addr, ac, transport) = match tor_port {
|
||||
Some(tor_port) => {
|
||||
let tor_secret_key = torut::onion::TorSecretKeyV3::generate();
|
||||
let onion_address = tor_secret_key
|
||||
.public()
|
||||
.get_onion_address()
|
||||
.get_address_without_dot_onion();
|
||||
let onion_address_string = format!("/onion3/{}:{}", onion_address, tor_port);
|
||||
let addr: Multiaddr = onion_address_string.parse()?;
|
||||
let ac = create_tor_service(tor_secret_key, tor_port).await?;
|
||||
let transport = build_tor(local_key_pair, addr.clone(), tor_port)?;
|
||||
(addr, Some(ac), transport)
|
||||
}
|
||||
None => {
|
||||
let transport = build(local_key_pair)?;
|
||||
(listen_addr, None, transport)
|
||||
}
|
||||
};
|
||||
|
||||
let bitcoin_wallet = bitcoin::Wallet::new("alice", &url)
|
||||
@ -80,31 +83,44 @@ async fn main() -> Result<()> {
|
||||
|
||||
let monero_wallet = Arc::new(monero::Wallet::localhost(MONERO_WALLET_RPC_PORT));
|
||||
|
||||
swap_as_alice(bitcoin_wallet, monero_wallet, alice.clone()).await?;
|
||||
swap_as_alice(listen_addr, redeem, punish, transport, behaviour).await?;
|
||||
}
|
||||
Options::Bob {
|
||||
alice_addr: alice_address,
|
||||
alice_addr,
|
||||
satoshis,
|
||||
bitcoind_url: url,
|
||||
} => {
|
||||
info!("running swap node as Bob ...");
|
||||
|
||||
let behaviour = Bob::default();
|
||||
let local_key_pair = behaviour.identity();
|
||||
|
||||
let transport = build(local_key_pair)?;
|
||||
|
||||
let bitcoin_wallet = Wallet::new("bob", &url)
|
||||
.await
|
||||
.expect("failed to create bitcoin wallet");
|
||||
|
||||
let monero_wallet = Arc::new(monero::Wallet::localhost(MONERO_WALLET_RPC_PORT));
|
||||
|
||||
swap_as_bob(satoshis, alice_address, refund, bitcoin_wallet).await?;
|
||||
swap_as_bob(
|
||||
satoshis,
|
||||
alice_addr,
|
||||
refund,
|
||||
bitcoin_wallet,
|
||||
transport,
|
||||
behaviour,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "tor")]
|
||||
async fn create_tor_service(
|
||||
tor_secret_key: torut::onion::TorSecretKeyV3,
|
||||
tor_port: u16,
|
||||
) -> Result<swap::tor::AuthenticatedConnection> {
|
||||
// TODO use configurable ports for tor connection
|
||||
let mut authenticated_connection = swap::tor::UnauthenticatedConnection::default()
|
||||
@ -113,7 +129,7 @@ async fn create_tor_service(
|
||||
tracing::info!("Tor authenticated.");
|
||||
|
||||
authenticated_connection
|
||||
.add_service(TOR_PORT, &tor_secret_key)
|
||||
.add_service(tor_port, &tor_secret_key)
|
||||
.await?;
|
||||
tracing::info!("Tor service added.");
|
||||
|
||||
@ -124,15 +140,12 @@ async fn swap_as_alice(
|
||||
bitcoin_wallet: Arc<swap::bitcoin::Wallet>,
|
||||
monero_wallet: Arc<swap::monero::Wallet>,
|
||||
addr: Multiaddr,
|
||||
redeem: bitcoin::Address,
|
||||
punish: bitcoin::Address,
|
||||
transport: SwapTransport,
|
||||
behaviour: Alice,
|
||||
) -> Result<()> {
|
||||
#[cfg(not(feature = "tor"))]
|
||||
{
|
||||
alice::swap(bitcoin_wallet, monero_wallet, addr, None).await
|
||||
}
|
||||
#[cfg(feature = "tor")]
|
||||
{
|
||||
alice::swap(bitcoin_wallet, monero_wallet, addr, Some(LISTEN_PORT)).await
|
||||
}
|
||||
alice::swap(addr, redeem, punish, transport, behaviour).await
|
||||
}
|
||||
|
||||
async fn swap_as_bob(
|
||||
@ -140,16 +153,18 @@ async fn swap_as_bob(
|
||||
monero_wallet: Arc<swap::monero::Wallet>,
|
||||
sats: u64,
|
||||
alice: Multiaddr,
|
||||
) -> Result<()> {
|
||||
refund: bitcoin::Address,
|
||||
wallet: W,
|
||||
transport: SwapTransport,
|
||||
behaviour: Bob,
|
||||
) -> Result<()>
|
||||
where
|
||||
W: BuildTxLockPsbt + SignTxLock + BroadcastSignedTransaction + Send + Sync + 'static,
|
||||
{
|
||||
let (cmd_tx, mut cmd_rx) = mpsc::channel(1);
|
||||
let (mut rsp_tx, rsp_rx) = mpsc::channel(1);
|
||||
tokio::spawn(bob::swap(
|
||||
bitcoin_wallet,
|
||||
monero_wallet,
|
||||
sats,
|
||||
alice,
|
||||
cmd_tx,
|
||||
rsp_rx,
|
||||
sats, alice, cmd_tx, rsp_rx, refund, wallet, transport, behaviour,
|
||||
));
|
||||
|
||||
loop {
|
||||
@ -201,10 +216,3 @@ fn verify(amounts: SwapAmounts) -> Rsp {
|
||||
fn is_yes(s: &str) -> bool {
|
||||
matches!(s, "y" | "Y" | "yes" | "YES" | "Yes")
|
||||
}
|
||||
|
||||
fn multiaddr(s: &str) -> Result<Multiaddr> {
|
||||
let addr = s
|
||||
.parse()
|
||||
.with_context(|| format!("failed to parse multiaddr: {}", s))?;
|
||||
Ok(addr)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use libp2p::{
|
||||
muxing::StreamMuxerBox,
|
||||
transport::Boxed,
|
||||
upgrade::{SelectUpgrade, Version},
|
||||
Transport,
|
||||
Multiaddr, Transport,
|
||||
},
|
||||
dns::DnsConfig,
|
||||
mplex::MplexConfig,
|
||||
@ -18,7 +18,7 @@ use libp2p::{
|
||||
/// - DNS name resolution
|
||||
/// - authentication via noise
|
||||
/// - multiplexing via yamux or mplex
|
||||
#[cfg(not(feature = "tor"))]
|
||||
/// #[cfg(not(feature = "tor"))]
|
||||
pub fn build(id_keys: identity::Keypair) -> Result<SwapTransport> {
|
||||
use libp2p::tcp::TokioTcpConfig;
|
||||
|
||||
@ -40,24 +40,21 @@ pub fn build(id_keys: identity::Keypair) -> Result<SwapTransport> {
|
||||
|
||||
Ok(transport)
|
||||
}
|
||||
|
||||
/// Builds a libp2p transport with Tor and with the following features:
|
||||
/// - TCP connection over the Tor network
|
||||
/// - DNS name resolution
|
||||
/// - authentication via noise
|
||||
/// - multiplexing via yamux or mplex
|
||||
#[cfg(feature = "tor")]
|
||||
pub fn build(
|
||||
// #[cfg(feature = "tor")]
|
||||
pub fn build_tor(
|
||||
id_keys: identity::Keypair,
|
||||
address_port_pair: Option<(libp2p::core::Multiaddr, u16)>,
|
||||
addr: libp2p::core::Multiaddr,
|
||||
port: u16,
|
||||
) -> Result<SwapTransport> {
|
||||
use libp2p_tokio_socks5::Socks5TokioTcpConfig;
|
||||
use std::collections::HashMap;
|
||||
|
||||
let mut map = HashMap::new();
|
||||
if let Some((addr, port)) = address_port_pair {
|
||||
map.insert(addr, port);
|
||||
}
|
||||
let map: HashMap<Multiaddr, u16> = [(addr, port)].iter().cloned().collect();
|
||||
|
||||
let dh_keys = noise::Keypair::<X25519Spec>::new().into_authentic(&id_keys)?;
|
||||
let noise = NoiseConfig::xx(dh_keys).into_authenticated();
|
||||
|
Loading…
Reference in New Issue
Block a user