705: Handle Results of waiting for timelocks to expire r=rishflab a=da-kami

Fixes an issue where the CLI is transitioning into a `CancelTimelockExpired` state but the timelock is actually not expired yet. 
This happened because watching for confirmations errored and the error was not handled but the same behaviour as reaching the cancel timelock height was applied.

For now this PR will fail the execution in case of the block height watching logic failing. Eventually there should be a more resilient strategy that includes retries. 

Co-authored-by: Daniel Karzel <daniel@comit.network>
Co-authored-by: rishflab <rishflab@hotmail.com>
This commit is contained in:
bors[bot] 2021-09-01 00:11:29 +00:00 committed by GitHub
commit a27048cece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 25 additions and 10 deletions

View File

@ -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. - 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. 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. 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 ## [0.8.1] - 2021-08-16

View File

@ -48,7 +48,10 @@ impl Wallet {
env_config: env::Config, env_config: env::Config,
target_block: usize, target_block: usize,
) -> Result<Self> { ) -> Result<Self> {
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")?; .context("Failed to initialize Electrum RPC client")?;
let db = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?; let db = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?;

View File

@ -54,7 +54,7 @@ impl EventLoop {
) -> Result<(Self, EventLoopHandle)> { ) -> Result<(Self, EventLoopHandle)> {
let execution_setup = bmrng::channel_with_timeout(1, Duration::from_secs(60)); 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 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 quote = bmrng::channel_with_timeout(1, Duration::from_secs(60));
let event_loop = EventLoop { let event_loop = EventLoop {
@ -248,7 +248,7 @@ impl EventLoopHandle {
pub async fn send_encrypted_signature( pub async fn send_encrypted_signature(
&mut self, &mut self,
tx_redeem_encsig: EncryptedSignature, tx_redeem_encsig: EncryptedSignature,
) -> Result<()> { ) -> Result<(), bmrng::error::RequestError<EncryptedSignature>> {
Ok(self Ok(self
.encrypted_signature .encrypted_signature
.send_receive(tx_redeem_encsig) .send_receive(tx_redeem_encsig)

View File

@ -195,7 +195,8 @@ where
select! { select! {
biased; // make sure the cancel timelock expiry future is polled first 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 { AliceState::CancelTimelockExpired {
monero_wallet_restore_blockheight, monero_wallet_restore_blockheight,
transfer_proof, transfer_proof,

View File

@ -128,7 +128,7 @@ async fn next_state(
let state4 = state3.cancel(); let state4 = state3.cancel();
BobState::CancelTimelockExpired(state4) BobState::CancelTimelockExpired(state4)
} },
} }
} else { } else {
let state4 = state3.cancel(); 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()) BobState::CancelTimelockExpired(state.cancel())
} }
} }
@ -175,10 +176,15 @@ async fn next_state(
// Bob sends Alice his key // Bob sends Alice his key
select! { select! {
_ = event_loop_handle.send_encrypted_signature(state.tx_redeem_encsig()) => { result = event_loop_handle.send_encrypted_signature(state.tx_redeem_encsig()) => {
BobState::EncSigSent(state) 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()) BobState::CancelTimelockExpired(state.cancel())
} }
} }
@ -194,7 +200,8 @@ async fn next_state(
state5 = state.watch_for_redeem_btc(bitcoin_wallet) => { state5 = state.watch_for_redeem_btc(bitcoin_wallet) => {
BobState::BtcRedeemed(state5?) 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()) BobState::CancelTimelockExpired(state.cancel())
} }
} }