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 0f9490c0..b3561281 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -64,10 +64,16 @@ 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( &self, + file_name: &str, private_spend_key: PrivateKey, private_view_key: PrivateViewKey, restore_height: BlockHeight, @@ -85,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(), @@ -101,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, @@ -119,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 e926c12d..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,11 +196,23 @@ 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 - .create_from_and_load(spend_key, view_key, state.monero_wallet_restore_blockheight) - .await?; + let generated_wallet_file_name = &swap_id.to_string(); + if monero_wallet + .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. + 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 monero_wallet.refresh().await?;