mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-02-02 10:35:22 -05:00
Monero wallet refresh fix (#1487)
* Upgrade monero-wallet-rpc to `v0.18.3.1` * Give feedback to user about state of monero refresh and retry if fails This commit changes the following behaviour in the refresh functionality of the monero wallet - Allows for multiple retries because in some cases users have experienced an issue where the wallet rpc returns `no connection to daemon` even though the daemon is available. I'm not 100% sure why this happens but retrying often fixes the issue - Attempt to print the current sync height while the wallet is syncing. This only works to some degree because the `monero-wallet-rpc` stops responding (or takes a long time to respond) while it's refreshing - The `monero-wallet-rpc` is started with the `--no-initial-sync` flag which ensures that as soon as it's started, it's ready to respond to requests --------- Co-authored-by: Byron Hambly <bhambly@blockstream.com> Co-authored-by: Byron Hambly <byron@hambly.dev>
This commit is contained in:
parent
eb15f477fa
commit
d8dacbdee9
@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
- Minimum Supported Rust Version (MSRV) bumped to 1.70
|
- Minimum Supported Rust Version (MSRV) bumped to 1.70
|
||||||
|
- Update monero-wallet-rpc version to v0.18.3.1
|
||||||
|
- Add retry logic to monero-wallet-rpc wallet refresh
|
||||||
|
|
||||||
## [0.12.3] - 2023-09-20
|
## [0.12.3] - 2023-09-20
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@ impl Wallet {
|
|||||||
pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result<Self> {
|
pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result<Self> {
|
||||||
let main_address =
|
let main_address =
|
||||||
monero::Address::from_str(client.get_address(0).await?.address.as_str())?;
|
monero::Address::from_str(client.get_address(0).await?.address.as_str())?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
inner: Mutex::new(client),
|
inner: Mutex::new(client),
|
||||||
network: env_config.monero_network,
|
network: env_config.monero_network,
|
||||||
@ -144,7 +145,7 @@ impl Wallet {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Try to send all the funds from the generated wallet to the default wallet
|
// Try to send all the funds from the generated wallet to the default wallet
|
||||||
match wallet.refresh().await {
|
match self.refresh(3).await {
|
||||||
Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await {
|
Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await {
|
||||||
Ok(sweep_all) => {
|
Ok(sweep_all) => {
|
||||||
for tx in sweep_all.tx_hash_list {
|
for tx in sweep_all.tx_hash_list {
|
||||||
@ -261,8 +262,70 @@ impl Wallet {
|
|||||||
self.main_address
|
self.main_address
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn refresh(&self) -> Result<Refreshed> {
|
pub async fn refresh(&self, max_attempts: usize) -> Result<Refreshed> {
|
||||||
Ok(self.inner.lock().await.refresh().await?)
|
const GET_HEIGHT_INTERVAL: Duration = Duration::from_secs(5);
|
||||||
|
const RETRY_INTERVAL: Duration = Duration::from_secs(2);
|
||||||
|
|
||||||
|
let inner = self.inner.lock().await;
|
||||||
|
|
||||||
|
// Cloning this is relatively cheap because reqwest::Client is a wrapper around an Arc
|
||||||
|
let inner_clone = inner.clone();
|
||||||
|
let wallet_name_clone = self.name.clone();
|
||||||
|
|
||||||
|
let refresh_task = tokio::task::spawn(async move {
|
||||||
|
loop {
|
||||||
|
let height = inner_clone.get_height().await;
|
||||||
|
|
||||||
|
match height {
|
||||||
|
Err(error) => {
|
||||||
|
tracing::debug!(name = %wallet_name_clone, %error, "Failed to get current Monero wallet sync height");
|
||||||
|
}
|
||||||
|
Ok(height) => {
|
||||||
|
tracing::debug!(name = %wallet_name_clone, current_sync_height = height.height, "Syncing Monero wallet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::time::sleep(GET_HEIGHT_INTERVAL).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let refresh_result = tokio::select! {
|
||||||
|
biased;
|
||||||
|
_ = refresh_task => {
|
||||||
|
unreachable!("Current sync height refresh task should never finish")
|
||||||
|
}
|
||||||
|
refresh_result = async {
|
||||||
|
for i in 1..=max_attempts {
|
||||||
|
tracing::info!(name = %self.name, attempt=i, "Syncing Monero wallet");
|
||||||
|
|
||||||
|
let result = inner.refresh().await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(refreshed) => {
|
||||||
|
tracing::info!(name = %self.name, "Monero wallet synced");
|
||||||
|
return Ok(refreshed);
|
||||||
|
}
|
||||||
|
Err(error) => {
|
||||||
|
let attempts_left = max_attempts - i;
|
||||||
|
tracing::warn!(attempt=i, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet");
|
||||||
|
|
||||||
|
if attempts_left == 0 {
|
||||||
|
tracing::error!(name = %self.name, %error, "Failed to sync Monero wallet");
|
||||||
|
return Err(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tokio::time::sleep(RETRY_INTERVAL).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!("Loop should always return before it breaks")
|
||||||
|
} => {
|
||||||
|
refresh_result
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(refresh_result?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,30 +46,30 @@ const MONERO_DAEMONS: [MoneroDaemon; 17] = [
|
|||||||
compile_error!("unsupported operating system");
|
compile_error!("unsupported operating system");
|
||||||
|
|
||||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||||
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2";
|
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.3.1.tar.bz2";
|
||||||
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
|
||||||
const DOWNLOAD_HASH: &str = "ba1108c7a5e5efe15b6a628fb007c50f01c231f61137bba7427605286dbc6f01";
|
const DOWNLOAD_HASH: &str = "7f8bd9364ef16482b418aa802a65be0e4cc660c794bb5d77b2d17bc84427883a";
|
||||||
|
|
||||||
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
||||||
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.1.2.tar.bz2";
|
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.3.1.tar.bz2";
|
||||||
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
||||||
const DOWNLOAD_HASH: &str = "620b825c04f84845ed09de03b207a3230a34f74b30a8a07dde504a7d376ee4b9";
|
const DOWNLOAD_HASH: &str = "915288b023cb5811e626e10052adc6ac5323dd283c5a25b91059b0fb86a21fb6";
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||||
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2";
|
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.3.1.tar.bz2";
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
||||||
const DOWNLOAD_HASH: &str = "7d51e7072351f65d0c7909e745827cfd3b00abe5e7c4cc4c104a3c9b526da07e";
|
const DOWNLOAD_HASH: &str = "23af572fdfe3459b9ab97e2e9aa7e3c11021c955d6064b801a27d7e8c21ae09d";
|
||||||
|
|
||||||
#[cfg(all(target_os = "linux", target_arch = "arm"))]
|
#[cfg(all(target_os = "linux", target_arch = "arm"))]
|
||||||
const DOWNLOAD_URL: &str =
|
const DOWNLOAD_URL: &str =
|
||||||
"https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2";
|
"https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2";
|
||||||
#[cfg(all(target_os = "linux", target_arch = "arm"))]
|
#[cfg(all(target_os = "linux", target_arch = "arm"))]
|
||||||
const DOWNLOAD_HASH: &str = "94ece435ed60f85904114643482c2b6716f74bf97040a7af237450574a9cf06d";
|
const DOWNLOAD_HASH: &str = "2ea2c8898cbab88f49423f4f6c15f2a94046cb4bbe827493dd061edc0fd5f1ca";
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip";
|
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.3.1.zip";
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const DOWNLOAD_HASH: &str = "0a3d4d1af7e094c05352c31b2dafcc6ccbc80edc195ca9eaedc919c36accd05a";
|
const DOWNLOAD_HASH: &str = "35dcc4bee4caad3442659d37837e0119e4649a77f2e3b5e80dd6d9b8fc4fb6ad";
|
||||||
|
|
||||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||||
const PACKED_FILE: &str = "monero-wallet-rpc";
|
const PACKED_FILE: &str = "monero-wallet-rpc";
|
||||||
@ -77,7 +77,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc";
|
|||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const PACKED_FILE: &str = "monero-wallet-rpc.exe";
|
const PACKED_FILE: &str = "monero-wallet-rpc.exe";
|
||||||
|
|
||||||
const WALLET_RPC_VERSION: &str = "v0.18.1.2";
|
const WALLET_RPC_VERSION: &str = "v0.18.3.1";
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, thiserror::Error)]
|
#[derive(Debug, Clone, Copy, thiserror::Error)]
|
||||||
#[error("monero wallet rpc executable not found in downloaded archive")]
|
#[error("monero wallet rpc executable not found in downloaded archive")]
|
||||||
@ -233,9 +233,10 @@ impl WalletRpc {
|
|||||||
.parse::<u64>()?;
|
.parse::<u64>()?;
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"Downloading monero-wallet-rpc ({}) from {}",
|
progress="0%",
|
||||||
content_length.big_byte(2),
|
size=%content_length.big_byte(2),
|
||||||
DOWNLOAD_URL
|
download_url=DOWNLOAD_URL,
|
||||||
|
"Downloading monero-wallet-rpc",
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
@ -268,12 +269,24 @@ impl WalletRpc {
|
|||||||
let total = 3 * content_length;
|
let total = 3 * content_length;
|
||||||
let percent = 100 * received as u64 / total;
|
let percent = 100 * received as u64 / total;
|
||||||
if percent != notified && percent % 10 == 0 {
|
if percent != notified && percent % 10 == 0 {
|
||||||
tracing::debug!("{}%", percent);
|
tracing::info!(
|
||||||
|
progress=format!("{}%", percent),
|
||||||
|
size=%content_length.big_byte(2),
|
||||||
|
download_url=DOWNLOAD_URL,
|
||||||
|
"Downloading monero-wallet-rpc",
|
||||||
|
);
|
||||||
notified = percent;
|
notified = percent;
|
||||||
}
|
}
|
||||||
file.write_all(&bytes).await?;
|
file.write_all(&bytes).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tracing::info!(
|
||||||
|
progress="100%",
|
||||||
|
size=%content_length.big_byte(2),
|
||||||
|
download_url=DOWNLOAD_URL,
|
||||||
|
"Downloading monero-wallet-rpc",
|
||||||
|
);
|
||||||
|
|
||||||
let result = hasher.finalize();
|
let result = hasher.finalize();
|
||||||
let result_hash = HEXLOWER.encode(result.as_ref());
|
let result_hash = HEXLOWER.encode(result.as_ref());
|
||||||
if result_hash != DOWNLOAD_HASH {
|
if result_hash != DOWNLOAD_HASH {
|
||||||
@ -339,6 +352,7 @@ impl WalletRpc {
|
|||||||
.arg("--disable-rpc-login")
|
.arg("--disable-rpc-login")
|
||||||
.arg("--wallet-dir")
|
.arg("--wallet-dir")
|
||||||
.arg(self.working_dir.join("monero-data"))
|
.arg(self.working_dir.join("monero-data"))
|
||||||
|
.arg("--no-initial-sync")
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
||||||
let stdout = child
|
let stdout = child
|
||||||
|
@ -227,6 +227,9 @@ async fn next_state(
|
|||||||
let (spend_key, view_key) = state.xmr_keys();
|
let (spend_key, view_key) = state.xmr_keys();
|
||||||
|
|
||||||
let wallet_file_name = swap_id.to_string();
|
let wallet_file_name = swap_id.to_string();
|
||||||
|
|
||||||
|
tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero");
|
||||||
|
|
||||||
if let Err(e) = monero_wallet
|
if let Err(e) = monero_wallet
|
||||||
.create_from_and_load(
|
.create_from_and_load(
|
||||||
wallet_file_name.clone(),
|
wallet_file_name.clone(),
|
||||||
@ -247,7 +250,7 @@ async fn next_state(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the generated wallet is synced so we have a proper balance
|
// Ensure that the generated wallet is synced so we have a proper balance
|
||||||
monero_wallet.refresh().await?;
|
monero_wallet.refresh(3).await?;
|
||||||
// Sweep (transfer all funds) to the given address
|
// Sweep (transfer all funds) to the given address
|
||||||
let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?;
|
let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?;
|
||||||
|
|
||||||
|
@ -863,7 +863,7 @@ impl Wallet for monero::Wallet {
|
|||||||
type Amount = monero::Amount;
|
type Amount = monero::Amount;
|
||||||
|
|
||||||
async fn refresh(&self) -> Result<()> {
|
async fn refresh(&self) -> Result<()> {
|
||||||
self.refresh().await?;
|
self.refresh(1).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user