mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-04-20 07:56:05 -04:00
Merge branch 'master' into issues-1459
This commit is contained in:
commit
4f0f2eedca
@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
## [Unreleased]
|
||||
|
||||
- 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
|
||||
|
||||
|
25
Cargo.lock
generated
25
Cargo.lock
generated
@ -145,9 +145,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.77"
|
||||
version = "0.1.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
|
||||
checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -722,7 +722,7 @@ dependencies = [
|
||||
"nom",
|
||||
"pathdiff",
|
||||
"serde",
|
||||
"toml 0.8.11",
|
||||
"toml 0.8.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3247,9 +3247,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reqwest"
|
||||
version = "0.11.26"
|
||||
version = "0.11.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2"
|
||||
checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
@ -4245,6 +4245,7 @@ dependencies = [
|
||||
"curve25519-dalek-ng",
|
||||
"data-encoding",
|
||||
"dialoguer",
|
||||
"digest 0.10.7",
|
||||
"directories-next",
|
||||
"ecdsa_fun",
|
||||
"ed25519-dalek",
|
||||
@ -4286,7 +4287,7 @@ dependencies = [
|
||||
"tokio-tar",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"toml 0.8.11",
|
||||
"toml 0.8.12",
|
||||
"torut",
|
||||
"tracing",
|
||||
"tracing-appender",
|
||||
@ -4646,9 +4647,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.11"
|
||||
version = "0.8.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e"
|
||||
checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
@ -4667,9 +4668,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.7"
|
||||
version = "0.22.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992"
|
||||
checksum = "c12219811e0c1ba077867254e5ad62ee2c9c190b0d957110750ac0cda1ae96cd"
|
||||
dependencies = [
|
||||
"indexmap 2.1.0",
|
||||
"serde",
|
||||
@ -5031,9 +5032,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
|
||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||
dependencies = [
|
||||
"getrandom 0.2.11",
|
||||
"serde",
|
||||
|
@ -25,6 +25,7 @@ conquer-once = "0.4"
|
||||
curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" }
|
||||
data-encoding = "2.5"
|
||||
dialoguer = "0.11"
|
||||
digest = "0.10.7"
|
||||
directories-next = "2"
|
||||
ecdsa_fun = { version = "0.10", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] }
|
||||
ed25519-dalek = "1"
|
||||
@ -64,7 +65,7 @@ tracing-appender = "0.2"
|
||||
tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] }
|
||||
tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] }
|
||||
url = { version = "2", features = [ "serde" ] }
|
||||
uuid = { version = "1.7", features = [ "serde", "v4" ] }
|
||||
uuid = { version = "1.8", features = [ "serde", "v4" ] }
|
||||
void = "1"
|
||||
|
||||
[target.'cfg(not(windows))'.dependencies]
|
||||
|
@ -45,6 +45,7 @@ impl Wallet {
|
||||
pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result<Self> {
|
||||
let main_address =
|
||||
monero::Address::from_str(client.get_address(0).await?.address.as_str())?;
|
||||
|
||||
Ok(Self {
|
||||
inner: Mutex::new(client),
|
||||
network: env_config.monero_network,
|
||||
@ -144,7 +145,7 @@ impl Wallet {
|
||||
.await?;
|
||||
|
||||
// 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(sweep_all) => {
|
||||
for tx in sweep_all.tx_hash_list {
|
||||
@ -261,8 +262,70 @@ impl Wallet {
|
||||
self.main_address
|
||||
}
|
||||
|
||||
pub async fn refresh(&self) -> Result<Refreshed> {
|
||||
Ok(self.inner.lock().await.refresh().await?)
|
||||
pub async fn refresh(&self, max_attempts: usize) -> Result<Refreshed> {
|
||||
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?)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
use ::monero::Network;
|
||||
use anyhow::{bail, Context, Error, Result};
|
||||
use big_bytes::BigByte;
|
||||
use data_encoding::HEXLOWER;
|
||||
use futures::{StreamExt, TryStreamExt};
|
||||
use monero_rpc::wallet::{Client, MoneroWalletRpc as _};
|
||||
use reqwest::header::CONTENT_LENGTH;
|
||||
use reqwest::Url;
|
||||
use serde::Deserialize;
|
||||
use sha2::{Digest, Sha256};
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use std::io::ErrorKind;
|
||||
@ -44,20 +46,30 @@ const MONERO_DAEMONS: [MoneroDaemon; 17] = [
|
||||
compile_error!("unsupported operating system");
|
||||
|
||||
#[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"))]
|
||||
const DOWNLOAD_HASH: &str = "7f8bd9364ef16482b418aa802a65be0e4cc660c794bb5d77b2d17bc84427883a";
|
||||
|
||||
#[cfg(all(target_os = "macos", target_arch = "aarch64"))]
|
||||
const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.0.0.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"))]
|
||||
const DOWNLOAD_HASH: &str = "915288b023cb5811e626e10052adc6ac5323dd283c5a25b91059b0fb86a21fb6";
|
||||
|
||||
#[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"))]
|
||||
const DOWNLOAD_HASH: &str = "23af572fdfe3459b9ab97e2e9aa7e3c11021c955d6064b801a27d7e8c21ae09d";
|
||||
|
||||
#[cfg(all(target_os = "linux", target_arch = "arm"))]
|
||||
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"))]
|
||||
const DOWNLOAD_HASH: &str = "2ea2c8898cbab88f49423f4f6c15f2a94046cb4bbe827493dd061edc0fd5f1ca";
|
||||
|
||||
#[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")]
|
||||
const DOWNLOAD_HASH: &str = "35dcc4bee4caad3442659d37837e0119e4649a77f2e3b5e80dd6d9b8fc4fb6ad";
|
||||
|
||||
#[cfg(any(target_os = "macos", target_os = "linux"))]
|
||||
const PACKED_FILE: &str = "monero-wallet-rpc";
|
||||
@ -65,7 +77,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc";
|
||||
#[cfg(target_os = "windows")]
|
||||
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)]
|
||||
#[error("monero wallet rpc executable not found in downloaded archive")]
|
||||
@ -221,13 +233,20 @@ impl WalletRpc {
|
||||
.parse::<u64>()?;
|
||||
|
||||
tracing::info!(
|
||||
"Downloading monero-wallet-rpc ({}) from {}",
|
||||
content_length.big_byte(2),
|
||||
DOWNLOAD_URL
|
||||
progress="0%",
|
||||
size=%content_length.big_byte(2),
|
||||
download_url=DOWNLOAD_URL,
|
||||
"Downloading monero-wallet-rpc",
|
||||
);
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
|
||||
let byte_stream = response
|
||||
.bytes_stream()
|
||||
.map_ok(|bytes| {
|
||||
hasher.update(&bytes);
|
||||
bytes
|
||||
})
|
||||
.map_err(|err| std::io::Error::new(ErrorKind::Other, err));
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
@ -250,12 +269,36 @@ impl WalletRpc {
|
||||
let total = 3 * content_length;
|
||||
let percent = 100 * received as u64 / total;
|
||||
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;
|
||||
}
|
||||
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_hash = HEXLOWER.encode(result.as_ref());
|
||||
if result_hash != DOWNLOAD_HASH {
|
||||
bail!(
|
||||
"SHA256 of download ({}) does not match expected ({})!",
|
||||
result_hash,
|
||||
DOWNLOAD_HASH
|
||||
);
|
||||
} else {
|
||||
tracing::debug!("Hashes match");
|
||||
}
|
||||
|
||||
file.flush().await?;
|
||||
|
||||
tracing::debug!("Extracting archive");
|
||||
@ -309,6 +352,7 @@ impl WalletRpc {
|
||||
.arg("--disable-rpc-login")
|
||||
.arg("--wallet-dir")
|
||||
.arg(self.working_dir.join("monero-data"))
|
||||
.arg("--no-initial-sync")
|
||||
.spawn()?;
|
||||
|
||||
let stdout = child
|
||||
|
@ -227,6 +227,9 @@ async fn next_state(
|
||||
let (spend_key, view_key) = state.xmr_keys();
|
||||
|
||||
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
|
||||
.create_from_and_load(
|
||||
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
|
||||
monero_wallet.refresh().await?;
|
||||
monero_wallet.refresh(3).await?;
|
||||
// Sweep (transfer all funds) to the given address
|
||||
let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?;
|
||||
|
||||
|
@ -863,7 +863,7 @@ impl Wallet for monero::Wallet {
|
||||
type Amount = monero::Amount;
|
||||
|
||||
async fn refresh(&self) -> Result<()> {
|
||||
self.refresh().await?;
|
||||
self.refresh(1).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user