From 548f057726c7c608b463854bc1b805448a994a5c Mon Sep 17 00:00:00 2001 From: Daniel Karzel Date: Thu, 8 Apr 2021 15:27:00 +1000 Subject: [PATCH 1/2] Try to open wallet in case generate_from_keys fails --- swap/src/monero/wallet.rs | 5 +++++ swap/src/protocol/bob/swap.rs | 15 +++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 0f9490c0..c01c74e3 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -64,6 +64,11 @@ impl Wallet { Ok(()) } + pub async fn open(&self, filename: &str) -> Result<()> { + self.inner.lock().await.open_wallet(filename).await?; + Ok(()) + } + /// Close the wallet and open (load) another wallet by generating it from /// keys. The generated wallet will remain loaded. pub async fn create_from_and_load( diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index e926c12d..a14725ba 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -193,11 +193,18 @@ async fn next_state( BobState::BtcRedeemed(state) => { let (spend_key, view_key) = state.xmr_keys(); - // NOTE: This actually generates and opens a new wallet, closing the currently - // open one. - monero_wallet + if monero_wallet .create_from_and_load(spend_key, view_key, state.monero_wallet_restore_blockheight) - .await?; + .await + .is_err() + { + // In case we failed to refresh/sweep, when resuming the wallet might already + // exist! This is a very unlikely scenario, but if we don't take care of it we + // might not be able to ever transfer the Monero. + let wallet_name = &monero::PrivateKey::from(view_key).to_string(); + tracing::warn!("Failed to generate monero wallet from keys, falling back to trying to open the the wallet if it already exists: {}", wallet_name); + monero_wallet.open(wallet_name).await?; + } // Ensure that the generated wallet is synced so we have a proper balance monero_wallet.refresh().await?; From 489696ee08d5f8bc125916bcaa876a53d16a460d Mon Sep 17 00:00:00 2001 From: Daniel Karzel Date: Thu, 8 Apr 2021 15:35:21 +1000 Subject: [PATCH 2/2] Swap-id as file name for generated Monero wallet Instead of using the private view-key as wallet filename we use the swap-id, to be able to identify which wallet is associated with which swap. --- monero-rpc/src/rpc/wallet.rs | 3 ++- swap/src/monero/wallet.rs | 4 ++++ swap/src/protocol/alice/swap.rs | 10 +++++++++- swap/src/protocol/bob/swap.rs | 16 ++++++++++++---- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/monero-rpc/src/rpc/wallet.rs b/monero-rpc/src/rpc/wallet.rs index abad399b..dad66764 100644 --- a/monero-rpc/src/rpc/wallet.rs +++ b/monero-rpc/src/rpc/wallet.rs @@ -287,6 +287,7 @@ impl Client { pub async fn generate_from_keys( &self, + filename: &str, address: &str, spend_key: &str, view_key: &str, @@ -294,7 +295,7 @@ impl Client { ) -> Result { let params = GenerateFromKeysParams { restore_height, - filename: view_key.into(), + filename: filename.into(), address: address.into(), spendkey: spend_key.into(), viewkey: view_key.into(), diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index c01c74e3..b3561281 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -73,6 +73,7 @@ impl Wallet { /// keys. The generated wallet will remain loaded. pub async fn create_from_and_load( &self, + file_name: &str, private_spend_key: PrivateKey, private_view_key: PrivateViewKey, restore_height: BlockHeight, @@ -90,6 +91,7 @@ impl Wallet { let _ = wallet .generate_from_keys( + file_name, &address.to_string(), &private_spend_key.to_string(), &PrivateKey::from(private_view_key).to_string(), @@ -106,6 +108,7 @@ impl Wallet { /// stored name. pub async fn create_from( &self, + file_name: &str, private_spend_key: PrivateKey, private_view_key: PrivateViewKey, restore_height: BlockHeight, @@ -124,6 +127,7 @@ impl Wallet { let _ = wallet .generate_from_keys( + file_name, &temp_wallet_address.to_string(), &private_spend_key.to_string(), &PrivateKey::from(private_view_key).to_string(), diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 2f2b1c86..63382faf 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -11,6 +11,7 @@ use anyhow::{bail, Context, Result}; use tokio::select; use tokio::time::timeout; use tracing::{error, info}; +use uuid::Uuid; pub async fn run(swap: alice::Swap) -> Result { run_until(swap, |_| false).await @@ -25,6 +26,7 @@ pub async fn run_until( while !is_complete(¤t_state) && !exit_early(¤t_state) { current_state = next_state( + swap.swap_id, current_state, &mut swap.event_loop_handle, swap.bitcoin_wallet.as_ref(), @@ -43,6 +45,7 @@ pub async fn run_until( } async fn next_state( + swap_id: Uuid, state: AliceState, event_loop_handle: &mut EventLoopHandle, bitcoin_wallet: &bitcoin::Wallet, @@ -296,7 +299,12 @@ async fn next_state( .await?; monero_wallet - .create_from(spend_key, view_key, monero_wallet_restore_blockheight) + .create_from( + &swap_id.to_string(), + spend_key, + view_key, + monero_wallet_restore_blockheight, + ) .await?; AliceState::XmrRefunded diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index a14725ba..cdb0ea18 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -8,6 +8,7 @@ use crate::{bitcoin, monero}; use anyhow::{bail, Context, Result}; use rand::rngs::OsRng; use tokio::select; +use uuid::Uuid; pub fn is_complete(state: &BobState) -> bool { matches!( @@ -32,6 +33,7 @@ pub async fn run_until( while !is_target_state(¤t_state) { current_state = next_state( + swap.swap_id, current_state, &mut swap.event_loop_handle, swap.bitcoin_wallet.as_ref(), @@ -51,6 +53,7 @@ pub async fn run_until( } async fn next_state( + swap_id: Uuid, state: BobState, event_loop_handle: &mut EventLoopHandle, bitcoin_wallet: &bitcoin::Wallet, @@ -193,17 +196,22 @@ async fn next_state( BobState::BtcRedeemed(state) => { let (spend_key, view_key) = state.xmr_keys(); + let generated_wallet_file_name = &swap_id.to_string(); if monero_wallet - .create_from_and_load(spend_key, view_key, state.monero_wallet_restore_blockheight) + .create_from_and_load( + generated_wallet_file_name, + spend_key, + view_key, + state.monero_wallet_restore_blockheight, + ) .await .is_err() { // In case we failed to refresh/sweep, when resuming the wallet might already // exist! This is a very unlikely scenario, but if we don't take care of it we // might not be able to ever transfer the Monero. - let wallet_name = &monero::PrivateKey::from(view_key).to_string(); - tracing::warn!("Failed to generate monero wallet from keys, falling back to trying to open the the wallet if it already exists: {}", wallet_name); - monero_wallet.open(wallet_name).await?; + tracing::warn!("Failed to generate monero wallet from keys, falling back to trying to open the the wallet if it already exists: {}", swap_id); + monero_wallet.open(generated_wallet_file_name).await?; } // Ensure that the generated wallet is synced so we have a proper balance