diff --git a/CHANGELOG.md b/CHANGELOG.md index 8992f81c..89ae41d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - An issue where the ASB was unable to use the Monero wallet in case `monero-wallet-rpc` has been restarted. In case no wallet is loaded when we try to interact with the `monero-wallet-rpc` daemon, we now load the correct wallet on-demand. See issue https://github.com/comit-network/xmr-btc-swap/issues/652. +- An issue where swap protocol was getting stuck trying to submit the cancel transaction. + We were not handling the error when TxCancel submission fails. + We also configured the electrum client to retry 5 times in order to help with this problem. + See issues: https://github.com/comit-network/xmr-btc-swap/issues/709 https://github.com/comit-network/xmr-btc-swap/issues/688, https://github.com/comit-network/xmr-btc-swap/issues/701. ## [0.8.1] - 2021-08-16 diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index b2554e80..4bdc6388 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -48,7 +48,10 @@ impl Wallet { env_config: env::Config, target_block: usize, ) -> Result { - let client = bdk::electrum_client::Client::new(electrum_rpc_url.as_str()) + let config = bdk::electrum_client::ConfigBuilder::default() + .retry(5) + .build(); + let client = bdk::electrum_client::Client::from_config(electrum_rpc_url.as_str(), config) .context("Failed to initialize Electrum RPC client")?; let db = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?; diff --git a/swap/src/cli/event_loop.rs b/swap/src/cli/event_loop.rs index 2ed37b26..d8c0d453 100644 --- a/swap/src/cli/event_loop.rs +++ b/swap/src/cli/event_loop.rs @@ -54,7 +54,7 @@ impl EventLoop { ) -> Result<(Self, EventLoopHandle)> { let execution_setup = bmrng::channel_with_timeout(1, Duration::from_secs(60)); let transfer_proof = bmrng::channel_with_timeout(1, Duration::from_secs(60)); - let encrypted_signature = bmrng::channel_with_timeout(1, Duration::from_secs(60)); + let encrypted_signature = bmrng::channel(1); let quote = bmrng::channel_with_timeout(1, Duration::from_secs(60)); let event_loop = EventLoop { @@ -248,7 +248,7 @@ impl EventLoopHandle { pub async fn send_encrypted_signature( &mut self, tx_redeem_encsig: EncryptedSignature, - ) -> Result<()> { + ) -> Result<(), bmrng::error::RequestError> { Ok(self .encrypted_signature .send_receive(tx_redeem_encsig) diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index b09658f0..c3808103 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -195,7 +195,8 @@ where select! { biased; // make sure the cancel timelock expiry future is polled first - _ = tx_lock_status.wait_until_confirmed_with(state3.cancel_timelock) => { + result = tx_lock_status.wait_until_confirmed_with(state3.cancel_timelock) => { + let _ = result?; AliceState::CancelTimelockExpired { monero_wallet_restore_blockheight, transfer_proof, diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 0ebab92b..45c5a3b1 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -128,7 +128,7 @@ async fn next_state( let state4 = state3.cancel(); BobState::CancelTimelockExpired(state4) - } + }, } } else { let state4 = state3.cancel(); @@ -159,7 +159,8 @@ async fn next_state( }, } } - _ = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { + result = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { + let _ = result?; BobState::CancelTimelockExpired(state.cancel()) } } @@ -175,10 +176,15 @@ async fn next_state( // Bob sends Alice his key select! { - _ = event_loop_handle.send_encrypted_signature(state.tx_redeem_encsig()) => { - BobState::EncSigSent(state) + result = event_loop_handle.send_encrypted_signature(state.tx_redeem_encsig()) => { + match result { + Ok(_) => BobState::EncSigSent(state), + Err(bmrng::error::RequestError::RecvError | bmrng::error::RequestError::SendError(_)) => bail!("Failed to communicate encrypted signature through event loop channel"), + Err(bmrng::error::RequestError::RecvTimeoutError) => unreachable!("We construct the channel with no timeout"), + } }, - _ = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { + result = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { + let _ = result?; BobState::CancelTimelockExpired(state.cancel()) } } @@ -194,7 +200,8 @@ async fn next_state( state5 = state.watch_for_redeem_btc(bitcoin_wallet) => { BobState::BtcRedeemed(state5?) }, - _ = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { + result = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { + let _ = result?; BobState::CancelTimelockExpired(state.cancel()) } }