diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index 0d6de9a7..a2073d66 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -18,6 +18,7 @@ use std::collections::HashMap; use std::convert::{Infallible, TryInto}; use std::fmt::Debug; use std::sync::Arc; +use std::time::Duration; use tokio::sync::mpsc; use uuid::Uuid; @@ -44,6 +45,7 @@ where latest_rate: LR, min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, external_redeem_address: Option, swap_sender: mpsc::Sender, @@ -77,6 +79,7 @@ where latest_rate: LR, min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, external_redeem_address: Option, ) -> Result<(Self, mpsc::Receiver)> { let swap_channel = MpscChannels::default(); @@ -91,6 +94,7 @@ where swap_sender: swap_channel.sender, min_buy, max_buy, + max_swap_timeout, external_redeem_address, recv_encrypted_signature: Default::default(), inflight_encrypted_signatures: Default::default(), @@ -186,7 +190,7 @@ where tracing::warn!(%peer, "Ignoring spot price request: {}", error); } SwarmEvent::Behaviour(OutEvent::QuoteRequested { channel, peer }) => { - let quote = match self.make_quote(self.min_buy, self.max_buy).await { + let quote = match self.make_quote(self.min_buy, self.max_buy, self.max_swap_timeout).await { Ok(quote) => quote, Err(error) => { tracing::warn!(%peer, "Failed to make quote: {:#}", error); @@ -322,6 +326,7 @@ where &mut self, min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, ) -> Result { let ask_price = self .latest_rate @@ -351,6 +356,7 @@ where price: ask_price, min_quantity: bitcoin::Amount::ZERO, max_quantity: bitcoin::Amount::ZERO, + valid_duration: Some(max_swap_timeout), }); } @@ -363,6 +369,7 @@ where price: ask_price, min_quantity: min_buy, max_quantity: max_bitcoin_for_monero, + valid_duration: Some(max_swap_timeout), }); } @@ -370,6 +377,7 @@ where price: ask_price, min_quantity: min_buy, max_quantity: max_buy, + valid_duration: Some(max_swap_timeout), }) } diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index 7b85f8fb..215656a7 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -127,9 +127,11 @@ pub mod behaviour { where LR: LatestRate + Send + 'static, { + #[allow(clippy::too_many_arguments)] pub fn new( min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, latest_rate: LR, resume_only: bool, env_config: env::Config, @@ -154,6 +156,7 @@ pub mod behaviour { swap_setup: alice::Behaviour::new( min_buy, max_buy, + max_swap_timeout, env_config, latest_rate, resume_only, diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index ff3b0e4c..36d11d2f 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -22,6 +22,7 @@ use std::convert::TryInto; use std::env; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Arc; +use std::time::Duration; use structopt::clap; use structopt::clap::ErrorKind; use swap::asb::command::{parse_args, Arguments, Command}; @@ -170,6 +171,7 @@ async fn main() -> Result<()> { &seed, config.maker.min_buy_btc, config.maker.max_buy_btc, + Duration::from_secs(120), kraken_rate.clone(), resume_only, env_config, @@ -201,6 +203,7 @@ async fn main() -> Result<()> { kraken_rate.clone(), config.maker.min_buy_btc, config.maker.max_buy_btc, + Duration::from_secs(120), config.maker.external_bitcoin_redeem_address, ) .unwrap(); diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 06be7b40..9b7b57b9 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -403,6 +403,7 @@ mod tests { price: Amount::from_btc(0.001).unwrap(), max_quantity: Amount::from_btc(btc).unwrap(), min_quantity: Amount::ZERO, + valid_duration: Some(Duration::from_secs(120)), } } @@ -411,6 +412,7 @@ mod tests { price: Amount::from_btc(0.001).unwrap(), max_quantity: Amount::max_value(), min_quantity: Amount::from_btc(btc).unwrap(), + valid_duration: Some(Duration::from_secs(120)), } } diff --git a/swap/src/cli.rs b/swap/src/cli.rs index f0faf146..b23af125 100644 --- a/swap/src/cli.rs +++ b/swap/src/cli.rs @@ -78,6 +78,7 @@ mod tests { price: bitcoin::Amount::from_sat(1337), min_quantity: bitcoin::Amount::from_sat(42), max_quantity: bitcoin::Amount::from_sat(9001), + valid_duration: Some(Duration::from_secs(120)), }; let mut asb = new_swarm(|_, identity| { diff --git a/swap/src/cli/list_sellers.rs b/swap/src/cli/list_sellers.rs index 381c561f..c0d2e924 100644 --- a/swap/src/cli/list_sellers.rs +++ b/swap/src/cli/list_sellers.rs @@ -344,6 +344,7 @@ mod tests { price: Default::default(), min_quantity: Default::default(), max_quantity: Default::default(), + valid_duration: Some(Duration::from_secs(120)), }), }, ]; @@ -359,6 +360,7 @@ mod tests { price: Default::default(), min_quantity: Default::default(), max_quantity: Default::default(), + valid_duration: Some(Duration::from_secs(120)), }) }, Seller { diff --git a/swap/src/network/quote.rs b/swap/src/network/quote.rs index caf99e09..a1d28bc0 100644 --- a/swap/src/network/quote.rs +++ b/swap/src/network/quote.rs @@ -7,6 +7,7 @@ use libp2p::request_response::{ }; use libp2p::PeerId; use serde::{Deserialize, Serialize}; +use std::time::Duration; const PROTOCOL: &str = "/comit/xmr/btc/bid-quote/1.0.0"; pub type OutEvent = RequestResponseEvent<(), BidQuote>; @@ -35,6 +36,7 @@ pub struct BidQuote { /// The maximum quantity the maker is willing to buy. #[serde(with = "::bitcoin::util::amount::serde::as_sat")] pub max_quantity: bitcoin::Amount, + pub valid_duration: Option, } #[derive(Clone, Copy, Debug, thiserror::Error)] diff --git a/swap/src/network/swap_setup/alice.rs b/swap/src/network/swap_setup/alice.rs index 25a80e0e..95cd395f 100644 --- a/swap/src/network/swap_setup/alice.rs +++ b/swap/src/network/swap_setup/alice.rs @@ -118,6 +118,7 @@ pub struct Behaviour { events: VecDeque, min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, env_config: env::Config, latest_rate: LR, @@ -128,6 +129,7 @@ impl Behaviour { pub fn new( min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, env_config: env::Config, latest_rate: LR, resume_only: bool, @@ -136,6 +138,7 @@ impl Behaviour { events: Default::default(), min_buy, max_buy, + max_swap_timeout, env_config, latest_rate, resume_only, @@ -154,6 +157,7 @@ where Handler::new( self.min_buy, self.max_buy, + self.max_swap_timeout, self.env_config, self.latest_rate.clone(), self.resume_only, @@ -214,7 +218,7 @@ pub struct Handler { latest_rate: LR, resume_only: bool, - timeout: Duration, + max_swap_timeout: Duration, keep_alive: KeepAlive, } @@ -222,6 +226,7 @@ impl Handler { fn new( min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, env_config: env::Config, latest_rate: LR, resume_only: bool, @@ -234,7 +239,7 @@ impl Handler { env_config, latest_rate, resume_only, - timeout: Duration::from_secs(120), + max_swap_timeout, keep_alive: KeepAlive::Until(Instant::now() + Duration::from_secs(10)), } } @@ -280,7 +285,7 @@ where let latest_rate = self.latest_rate.latest_rate(); let env_config = self.env_config; - let protocol = tokio::time::timeout(self.timeout, async move { + let protocol = tokio::time::timeout(self.max_swap_timeout, async move { let request = swap_setup::read_cbor_message::(&mut substream) .await .context("Failed to read spot price request")?; @@ -404,7 +409,7 @@ where Ok((swap_id, state3)) }); - let max_seconds = self.timeout.as_secs(); + let max_seconds = self.max_swap_timeout.as_secs(); self.inbound_stream = OptionFuture::from(Some( async move { protocol.await.with_context(|| { diff --git a/swap/src/network/swarm.rs b/swap/src/network/swarm.rs index 37bb0a5e..c57a4174 100644 --- a/swap/src/network/swarm.rs +++ b/swap/src/network/swarm.rs @@ -7,12 +7,14 @@ use anyhow::Result; use libp2p::swarm::{NetworkBehaviour, SwarmBuilder}; use libp2p::{identity, Multiaddr, Swarm}; use std::fmt::Debug; +use std::time::Duration; #[allow(clippy::too_many_arguments)] pub fn asb( seed: &Seed, min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, + max_swap_timeout: Duration, latest_rate: LR, resume_only: bool, env_config: env::Config, @@ -38,6 +40,7 @@ where let behaviour = asb::Behaviour::new( min_buy, max_buy, + max_swap_timeout, latest_rate, resume_only, env_config, diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 028b0935..6acf5b19 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -242,6 +242,7 @@ async fn start_alice( seed, min_buy, max_buy, + Duration::from_secs(120), latest_rate, resume_only, env_config, @@ -260,6 +261,7 @@ async fn start_alice( FixedRate::default(), min_buy, max_buy, + Duration::from_secs(120), None, ) .unwrap();