mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2024-10-01 01:45:40 -04:00
Refactor transports to construct them specific for each application
Instead of splitting up the transports into capabilities, we compose them directly for each application. This allows us to remove the websocket transport for the CLI which is really only needed for the ASB to allow retrieval of quotes via the browser.
This commit is contained in:
parent
90deb6451c
commit
8a30ef725c
@ -12,6 +12,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Printing the deposit address to the terminal as a QR code.
|
||||
To not break automated scripts or integrations with other software, this behaviour is disabled if `--json` is passed to the application.
|
||||
|
||||
### Removed
|
||||
|
||||
- The websocket transport from the CLI.
|
||||
Websockets were only ever intended to be used for the ASB side to allow websites to retrieve quotes.
|
||||
The CLI can use regular TCP connections and having both - TCP and websockets - causes problems and unnecessary overhead.
|
||||
|
||||
## [0.7.0] - 2021-05-28
|
||||
|
||||
### Fixed
|
||||
|
@ -2,5 +2,6 @@ pub mod command;
|
||||
pub mod config;
|
||||
mod rate;
|
||||
pub mod tracing;
|
||||
pub mod transport;
|
||||
|
||||
pub use rate::Rate;
|
||||
|
19
swap/src/asb/transport.rs
Normal file
19
swap/src/asb/transport.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use crate::network::transport::authenticate_and_multiplex;
|
||||
use anyhow::Result;
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::transport::Boxed;
|
||||
use libp2p::dns::TokioDnsConfig;
|
||||
use libp2p::tcp::TokioTcpConfig;
|
||||
use libp2p::websocket::WsConfig;
|
||||
use libp2p::{identity, PeerId, Transport};
|
||||
|
||||
/// Creates the libp2p transport for the ASB.
|
||||
pub fn new(identity: &identity::Keypair) -> Result<Boxed<(PeerId, StreamMuxerBox)>> {
|
||||
let tcp = TokioTcpConfig::new().nodelay(true);
|
||||
let tcp_with_dns = TokioDnsConfig::system(tcp)?;
|
||||
let websocket_with_dns = WsConfig::new(tcp_with_dns.clone());
|
||||
|
||||
let transport = tcp_with_dns.or_transport(websocket_with_dns).boxed();
|
||||
|
||||
authenticate_and_multiplex(transport, identity)
|
||||
}
|
@ -1,2 +1,3 @@
|
||||
pub mod command;
|
||||
pub mod tracing;
|
||||
pub mod transport;
|
||||
|
32
swap/src/cli/transport.rs
Normal file
32
swap/src/cli/transport.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::network::tor_transport::TorDialOnlyTransport;
|
||||
use crate::network::transport::authenticate_and_multiplex;
|
||||
use anyhow::Result;
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::transport::{Boxed, OptionalTransport};
|
||||
use libp2p::dns::TokioDnsConfig;
|
||||
use libp2p::tcp::TokioTcpConfig;
|
||||
use libp2p::{identity, PeerId, Transport};
|
||||
|
||||
/// Creates the libp2p transport for the swap CLI.
|
||||
///
|
||||
/// The CLI's transport needs the following capabilities:
|
||||
/// - Establish TCP connections
|
||||
/// - Resolve DNS entries
|
||||
/// - Dial onion-addresses through a running Tor daemon by connecting to the
|
||||
/// socks5 port. If the port is not given, we will fall back to the regular
|
||||
/// TCP transport.
|
||||
pub fn new(
|
||||
identity: &identity::Keypair,
|
||||
maybe_tor_socks5_port: Option<u16>,
|
||||
) -> Result<Boxed<(PeerId, StreamMuxerBox)>> {
|
||||
let tcp = TokioTcpConfig::new().nodelay(true);
|
||||
let tcp_with_dns = TokioDnsConfig::system(tcp)?;
|
||||
let maybe_tor_transport = match maybe_tor_socks5_port {
|
||||
Some(port) => OptionalTransport::some(TorDialOnlyTransport::new(port)),
|
||||
None => OptionalTransport::none(),
|
||||
};
|
||||
|
||||
let transport = maybe_tor_transport.or_transport(tcp_with_dns).boxed();
|
||||
|
||||
authenticate_and_multiplex(transport, identity)
|
||||
}
|
@ -1,10 +1,9 @@
|
||||
use crate::network::transport;
|
||||
use crate::protocol::alice::event_loop::LatestRate;
|
||||
use crate::protocol::{alice, bob};
|
||||
use crate::seed::Seed;
|
||||
use crate::{env, monero, tor};
|
||||
use crate::{asb, cli, env, monero, tor};
|
||||
use anyhow::Result;
|
||||
use libp2p::swarm::{NetworkBehaviour, SwarmBuilder};
|
||||
use libp2p::swarm::SwarmBuilder;
|
||||
use libp2p::{PeerId, Swarm};
|
||||
use std::fmt::Debug;
|
||||
|
||||
@ -22,9 +21,7 @@ pub fn asb<LR>(
|
||||
where
|
||||
LR: LatestRate + Send + 'static + Debug,
|
||||
{
|
||||
with_clear_net(
|
||||
seed,
|
||||
alice::Behaviour::new(
|
||||
let behaviour = alice::Behaviour::new(
|
||||
balance,
|
||||
lock_fee,
|
||||
min_buy,
|
||||
@ -32,8 +29,19 @@ where
|
||||
latest_rate,
|
||||
resume_only,
|
||||
env_config,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
let identity = seed.derive_libp2p_identity();
|
||||
let transport = asb::transport::new(&identity)?;
|
||||
let peer_id = identity.public().into_peer_id();
|
||||
|
||||
let swarm = SwarmBuilder::new(transport, behaviour, peer_id)
|
||||
.executor(Box::new(|f| {
|
||||
tokio::spawn(f);
|
||||
}))
|
||||
.build();
|
||||
|
||||
Ok(swarm)
|
||||
}
|
||||
|
||||
pub async fn cli(
|
||||
@ -41,41 +49,16 @@ pub async fn cli(
|
||||
alice: PeerId,
|
||||
tor_socks5_port: u16,
|
||||
) -> Result<Swarm<bob::Behaviour>> {
|
||||
let client = tor::Client::new(tor_socks5_port);
|
||||
if client.assert_tor_running().await.is_ok() {
|
||||
return with_tor(seed, bob::Behaviour::new(alice), tor_socks5_port).await;
|
||||
}
|
||||
with_clear_net(seed, bob::Behaviour::new(alice))
|
||||
}
|
||||
let maybe_tor_socks5_port = match tor::Client::new(tor_socks5_port).assert_tor_running().await {
|
||||
Ok(()) => Some(tor_socks5_port),
|
||||
Err(_) => None,
|
||||
};
|
||||
|
||||
let behaviour = bob::Behaviour::new(alice);
|
||||
|
||||
fn with_clear_net<B>(seed: &Seed, behaviour: B) -> Result<Swarm<B>>
|
||||
where
|
||||
B: NetworkBehaviour,
|
||||
{
|
||||
tracing::info!("All connections will go through clear net");
|
||||
let identity = seed.derive_libp2p_identity();
|
||||
let transport = transport::build_clear_net(&identity)?;
|
||||
let transport = cli::transport::new(&identity, maybe_tor_socks5_port)?;
|
||||
let peer_id = identity.public().into_peer_id();
|
||||
tracing::debug!(%peer_id, "Our peer-id");
|
||||
|
||||
let swarm = SwarmBuilder::new(transport, behaviour, peer_id)
|
||||
.executor(Box::new(|f| {
|
||||
tokio::spawn(f);
|
||||
}))
|
||||
.build();
|
||||
|
||||
Ok(swarm)
|
||||
}
|
||||
|
||||
async fn with_tor<B>(seed: &Seed, behaviour: B, tor_socks5_port: u16) -> Result<Swarm<B>>
|
||||
where
|
||||
B: NetworkBehaviour,
|
||||
{
|
||||
tracing::info!("All connections will go through Tor socks5 proxy");
|
||||
let identity = seed.derive_libp2p_identity();
|
||||
let transport = transport::build_tor(&identity, tor_socks5_port)?;
|
||||
let peer_id = identity.public().into_peer_id();
|
||||
tracing::debug!(%peer_id, "Our peer-id");
|
||||
|
||||
let swarm = SwarmBuilder::new(transport, behaviour, peer_id)
|
||||
.executor(Box::new(|f| {
|
||||
|
@ -1,74 +1,39 @@
|
||||
use crate::network::tor_transport::TorDialOnlyTransport;
|
||||
use anyhow::Result;
|
||||
use futures::{AsyncRead, AsyncWrite};
|
||||
use libp2p::core::muxing::StreamMuxerBox;
|
||||
use libp2p::core::transport::Boxed;
|
||||
use libp2p::core::upgrade::{SelectUpgrade, Version};
|
||||
use libp2p::dns::TokioDnsConfig;
|
||||
use libp2p::mplex::MplexConfig;
|
||||
use libp2p::noise::{self, NoiseConfig, X25519Spec};
|
||||
use libp2p::tcp::TokioTcpConfig;
|
||||
use libp2p::websocket::WsConfig;
|
||||
use libp2p::{identity, yamux, PeerId, Transport};
|
||||
use std::time::Duration;
|
||||
|
||||
/// Builds a libp2p transport with the following features:
|
||||
/// - TcpConnection
|
||||
/// - WebSocketConnection
|
||||
/// - DNS name resolution
|
||||
/// - authentication via noise
|
||||
/// - multiplexing via yamux or mplex
|
||||
pub fn build_clear_net(id_keys: &identity::Keypair) -> Result<SwapTransport> {
|
||||
let dh_keys = noise::Keypair::<X25519Spec>::new().into_authentic(id_keys)?;
|
||||
let noise = NoiseConfig::xx(dh_keys).into_authenticated();
|
||||
/// "Completes" a transport by applying the authentication and multiplexing
|
||||
/// upgrades.
|
||||
///
|
||||
/// Even though the actual transport technology in use might be different, for
|
||||
/// two libp2p applications to be compatible, the authentication and
|
||||
/// multiplexing upgrades need to be compatible.
|
||||
pub fn authenticate_and_multiplex<T>(
|
||||
transport: Boxed<T>,
|
||||
identity: &identity::Keypair,
|
||||
) -> Result<Boxed<(PeerId, StreamMuxerBox)>>
|
||||
where
|
||||
T: AsyncRead + AsyncWrite + Unpin + Send + 'static,
|
||||
{
|
||||
let auth_upgrade = {
|
||||
let noise_identity = noise::Keypair::<X25519Spec>::new().into_authentic(identity)?;
|
||||
NoiseConfig::xx(noise_identity).into_authenticated()
|
||||
};
|
||||
let multiplex_upgrade = SelectUpgrade::new(yamux::YamuxConfig::default(), MplexConfig::new());
|
||||
|
||||
let tcp = TokioTcpConfig::new().nodelay(true);
|
||||
let dns = TokioDnsConfig::system(tcp)?;
|
||||
let websocket = WsConfig::new(dns.clone());
|
||||
|
||||
let transport = websocket
|
||||
.or_transport(dns)
|
||||
let transport = transport
|
||||
.upgrade(Version::V1)
|
||||
.authenticate(noise)
|
||||
.multiplex(SelectUpgrade::new(
|
||||
yamux::YamuxConfig::default(),
|
||||
MplexConfig::new(),
|
||||
))
|
||||
.authenticate(auth_upgrade)
|
||||
.multiplex(multiplex_upgrade)
|
||||
.timeout(Duration::from_secs(20))
|
||||
.map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer)))
|
||||
.boxed();
|
||||
|
||||
Ok(transport)
|
||||
}
|
||||
|
||||
/// Builds a libp2p transport with the following features:
|
||||
/// - TorTcpConnection
|
||||
/// - WebSocketConnection
|
||||
/// - DNS name resolution
|
||||
/// - authentication via noise
|
||||
/// - multiplexing via yamux or mplex
|
||||
pub fn build_tor(id_keys: &identity::Keypair, tor_socks5_port: u16) -> Result<SwapTransport> {
|
||||
let dh_keys = noise::Keypair::<X25519Spec>::new().into_authentic(id_keys)?;
|
||||
let noise = NoiseConfig::xx(dh_keys).into_authenticated();
|
||||
|
||||
let tcp = TokioTcpConfig::new().nodelay(true);
|
||||
let tcp_with_dns = TokioDnsConfig::system(tcp)?;
|
||||
let websocket_with_dns = WsConfig::new(tcp_with_dns.clone());
|
||||
let tor_dial_only = TorDialOnlyTransport::new(tor_socks5_port);
|
||||
|
||||
let transport = tor_dial_only
|
||||
.or_transport(tcp_with_dns)
|
||||
.or_transport(websocket_with_dns)
|
||||
.upgrade(Version::V1)
|
||||
.authenticate(noise)
|
||||
.multiplex(SelectUpgrade::new(
|
||||
yamux::YamuxConfig::default(),
|
||||
MplexConfig::new(),
|
||||
))
|
||||
.timeout(Duration::from_secs(20))
|
||||
.map(|(peer, muxer), _| (peer, StreamMuxerBox::new(muxer)))
|
||||
.boxed();
|
||||
|
||||
Ok(transport)
|
||||
}
|
||||
|
||||
pub type SwapTransport = Boxed<(PeerId, StreamMuxerBox)>;
|
||||
|
Loading…
Reference in New Issue
Block a user