From 3840c39f3f9bc76298c4d812d7d35e67c092b56c Mon Sep 17 00:00:00 2001 From: leonardo Date: Sun, 20 Mar 2022 21:49:27 +0100 Subject: [PATCH 1/5] Check if binary is latest version --- swap/src/bin/swap.rs | 107 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 92010783..f3312f29 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -67,6 +67,12 @@ async fn main() -> Result<()> { let swap_id = Uuid::new_v4(); cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -149,6 +155,11 @@ async fn main() -> Result<()> { Command::History => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let swaps = db.all().await?; @@ -173,6 +184,11 @@ async fn main() -> Result<()> { Command::Config => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + tracing::info!(path=%data_dir.display(), "Data directory"); tracing::info!(path=%format!("{}/logs", data_dir.display()), "Log files directory"); tracing::info!(path=%format!("{}/sqlite", data_dir.display()), "Sqlite file location"); @@ -187,6 +203,12 @@ async fn main() -> Result<()> { address, } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -220,6 +242,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -245,6 +273,12 @@ async fn main() -> Result<()> { tor_socks5_port, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -306,6 +340,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -328,6 +368,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -353,6 +399,11 @@ async fn main() -> Result<()> { .context("Rendezvous node address must contain peer ID")?; cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let identity = seed.derive_libp2p_identity(); @@ -433,6 +484,11 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -447,6 +503,13 @@ async fn main() -> Result<()> { tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet"); } Command::MoneroRecovery { swap_id } => { + cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let swap_state: BobState = db.get_state(swap_id).await?.try_into()?; @@ -629,10 +692,43 @@ where Ok((btc_swap_amount, fees)) } +pub async fn check_latest_version() -> Result<()> { + const GITHUB_LATEST_VERSION_URL: &str = + "https://github.com/comit-network/xmr-btc-swap/releases/latest"; + + let response = match reqwest::get(GITHUB_LATEST_VERSION_URL).await { + Ok(res) => res, + Err(_) => bail!( + "could not request the website {}", + GITHUB_LATEST_VERSION_URL + ), + }; + + let last_version_from_url: &str = match response.url().path_segments() { + Some(split_segments) => match split_segments.last() { + Some(seg) => seg, + None => bail!("could not check the latest version"), + }, + None => bail!("could not check the latest version"), + }; + + let version_from_binary: &str = env!("CARGO_PKG_VERSION"); + + if last_version_from_url != version_from_binary { + tracing::warn!( + "You are not on the lastest version {}, it's available on Github: {}", + last_version_from_url, + GITHUB_LATEST_VERSION_URL + ); + }; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; - use crate::determine_btc_to_swap; + use crate::{check_latest_version, determine_btc_to_swap}; use ::bitcoin::Amount; use std::sync::Mutex; use swap::tracing_ext::capture_logs; @@ -995,4 +1091,13 @@ mod tests { async fn get_dummy_address() -> Result { Ok("1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6".parse()?) } + + #[tokio::test] + async fn check_correct_latest_version() { + let writer = capture_logs(LevelFilter::INFO); + + check_latest_version().await.unwrap(); + + assert_eq!(writer.captured(), r""); + } } From 9fb0d7b733d52893d255e07447641d38d110baac Mon Sep 17 00:00:00 2001 From: leonardo Date: Sun, 20 Mar 2022 21:49:27 +0100 Subject: [PATCH 2/5] Check if binary is latest version --- swap/src/bin/swap.rs | 107 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 92010783..f3312f29 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -67,6 +67,12 @@ async fn main() -> Result<()> { let swap_id = Uuid::new_v4(); cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -149,6 +155,11 @@ async fn main() -> Result<()> { Command::History => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let swaps = db.all().await?; @@ -173,6 +184,11 @@ async fn main() -> Result<()> { Command::Config => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + tracing::info!(path=%data_dir.display(), "Data directory"); tracing::info!(path=%format!("{}/logs", data_dir.display()), "Log files directory"); tracing::info!(path=%format!("{}/sqlite", data_dir.display()), "Sqlite file location"); @@ -187,6 +203,12 @@ async fn main() -> Result<()> { address, } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -220,6 +242,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -245,6 +273,12 @@ async fn main() -> Result<()> { tor_socks5_port, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -306,6 +340,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -328,6 +368,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -353,6 +399,11 @@ async fn main() -> Result<()> { .context("Rendezvous node address must contain peer ID")?; cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let identity = seed.derive_libp2p_identity(); @@ -433,6 +484,11 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -447,6 +503,13 @@ async fn main() -> Result<()> { tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet"); } Command::MoneroRecovery { swap_id } => { + cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let swap_state: BobState = db.get_state(swap_id).await?.try_into()?; @@ -629,10 +692,43 @@ where Ok((btc_swap_amount, fees)) } +pub async fn check_latest_version() -> Result<()> { + const GITHUB_LATEST_VERSION_URL: &str = + "https://github.com/comit-network/xmr-btc-swap/releases/latest"; + + let response = match reqwest::get(GITHUB_LATEST_VERSION_URL).await { + Ok(res) => res, + Err(_) => bail!( + "could not request the website {}", + GITHUB_LATEST_VERSION_URL + ), + }; + + let last_version_from_url: &str = match response.url().path_segments() { + Some(split_segments) => match split_segments.last() { + Some(seg) => seg, + None => bail!("could not check the latest version"), + }, + None => bail!("could not check the latest version"), + }; + + let version_from_binary: &str = env!("CARGO_PKG_VERSION"); + + if last_version_from_url != version_from_binary { + tracing::warn!( + "You are not on the lastest version {}, it's available on Github: {}", + last_version_from_url, + GITHUB_LATEST_VERSION_URL + ); + }; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; - use crate::determine_btc_to_swap; + use crate::{check_latest_version, determine_btc_to_swap}; use ::bitcoin::Amount; use std::sync::Mutex; use swap::tracing_ext::capture_logs; @@ -995,4 +1091,13 @@ mod tests { async fn get_dummy_address() -> Result { Ok("1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6".parse()?) } + + #[tokio::test] + async fn check_correct_latest_version() { + let writer = capture_logs(LevelFilter::INFO); + + check_latest_version().await.unwrap(); + + assert_eq!(writer.captured(), r""); + } } From 658b44c4a5b7f470607a0a5a164240a3e64bfe87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Feb 2022 13:31:40 +0000 Subject: [PATCH 3/5] Bump tempfile from 3.2.0 to 3.3.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 341a6006..d9cfbd2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1050,6 +1050,15 @@ dependencies = [ "syn", ] +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "filetime" version = "0.2.14" @@ -4059,13 +4068,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.3", "redox_syscall", "remove_dir_all", "winapi 0.3.9", From 8fc9b05a66ea8c4957db1d032d62ad616be10aa8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jan 2022 08:30:00 +0000 Subject: [PATCH 4/5] Check if binary is latest version Bumps [serde](https://github.com/serde-rs/serde) from 1.0.130 to 1.0.133. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.130...v1.0.133) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Add rfc3339 removal changelog entry Bump anyhow from 1.0.51 to 1.0.52 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.51 to 1.0.52. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.51...1.0.52) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump serde_json from 1.0.68 to 1.0.74 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.68 to 1.0.74. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.68...v1.0.74) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Fix failing CI tests due to deleted xmrto docker hub images Fix failing CI tests due to deleted xmrto docker hub images by moving to the docker images provided by melotools Bump tempfile from 3.2.0 to 3.3.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Bump tempfile from 3.2.0 to 3.3.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.2.0...v3.3.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Always write logs as JSON to files Bump torut from 0.2.0 to 0.2.1 Bumps [torut](https://github.com/teawithsand/torut) from 0.2.0 to 0.2.1. - [Release notes](https://github.com/teawithsand/torut/releases) - [Commits](https://github.com/teawithsand/torut/commits) --- updated-dependencies: - dependency-name: torut dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump time from 0.3.3 to 0.3.7 Bumps [time](https://github.com/time-rs/time) from 0.3.3 to 0.3.7. - [Release notes](https://github.com/time-rs/time/releases) - [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md) - [Commits](https://github.com/time-rs/time/compare/v0.3.3...v0.3.7) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump tokio from 1.12.0 to 1.16.1 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.12.0 to 1.16.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.12.0...tokio-1.16.1) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Bump dialoguer from 0.8.0 to 0.10.0 Bumps [dialoguer](https://github.com/mitsuhiko/dialoguer) from 0.8.0 to 0.10.0. - [Release notes](https://github.com/mitsuhiko/dialoguer/releases) - [Changelog](https://github.com/mitsuhiko/dialoguer/blob/master/CHANGELOG.md) - [Commits](https://github.com/mitsuhiko/dialoguer/compare/0.8.0...v0.10.0) --- updated-dependencies: - dependency-name: dialoguer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Bump reqwest from 0.11.7 to 0.11.9 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.7 to 0.11.9. - [Release notes](https://github.com/seanmonstar/reqwest/releases) - [Changelog](https://github.com/seanmonstar/reqwest/blob/master/CHANGELOG.md) - [Commits](https://github.com/seanmonstar/reqwest/compare/v0.11.7...v0.11.9) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump actions/setup-python from 2.3.1 to 2.3.2 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2.3.1...v2.3.2) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Adjust quote based on Bitcoin balance Update dependencies and rust-toolchain to 1.59 This commit updates the rust-toolchain to the current stable version 1.59, and fixes a number of new clippy warnings from that change. Other changes: - updates backoff to 0.4 - updates swap to 2021 edition - updates comfy-table to 5.0 - updates monero-wallet to 2021 edition - updates moneor-harness to 2021 edition - updates bdk and rust_decimal - updates tokio-util to 0.7 - updates workflow to use actions/setup-python@3 - updates pem and serde_with - adds stable rust toolchain notice to readme Change to rino nodes Update dprint plugins to fix CI error Bump futures from 0.3.17 to 0.3.21 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.17 to 0.3.21. - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.17...0.3.21) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump structopt from 0.3.25 to 0.3.26 Bumps [structopt](https://github.com/TeXitoi/structopt) from 0.3.25 to 0.3.26. - [Release notes](https://github.com/TeXitoi/structopt/releases) - [Changelog](https://github.com/TeXitoi/structopt/blob/master/CHANGELOG.md) - [Commits](https://github.com/TeXitoi/structopt/compare/v0.3.25...v0.3.26) --- updated-dependencies: - dependency-name: structopt dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump serde from 1.0.133 to 1.0.136 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.133 to 1.0.136. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.133...v1.0.136) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Bump hyper from 0.14.16 to 0.14.18 Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.16 to 0.14.18. - [Release notes](https://github.com/hyperium/hyper/releases) - [Changelog](https://github.com/hyperium/hyper/blob/master/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper/compare/v0.14.16...v0.14.18) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Inform Bob that he has been punished Reduce required confirmations for Bitcoin transactions from 2 to 1 Don't wait for refund transaction to receive confirmations Don't wait for refund transaction to receive confirmations to mitigate a scenario where the swap is stuck in `BtcCancelled` because it's not resumable. Check if binary is latest version Check if binary is latest version --- .github/workflows/build-release-binaries.yml | 4 +- CHANGELOG.md | 14 +- Cargo.lock | 405 +++++++++++-------- README.md | 5 + docs/asb/README.md | 2 +- dprint.json | 4 +- monero-harness/Cargo.toml | 2 +- monero-harness/src/image.rs | 24 +- monero-harness/src/lib.rs | 12 +- monero-rpc/Cargo.toml | 2 +- monero-rpc/src/wallet.rs | 9 +- monero-wallet/Cargo.toml | 2 +- monero-wallet/src/lib.rs | 4 +- rust-toolchain.toml | 2 +- swap/Cargo.toml | 12 +- swap/src/asb/event_loop.rs | 39 +- swap/src/bin/swap.rs | 160 +++++++- swap/src/bitcoin.rs | 6 +- swap/src/bitcoin/lock.rs | 7 +- swap/src/bitcoin/redeem.rs | 2 +- swap/src/bitcoin/refund.rs | 2 +- swap/src/bitcoin/wallet.rs | 6 +- swap/src/cli/command.rs | 81 +++- swap/src/cli/event_loop.rs | 5 +- swap/src/cli/list_sellers.rs | 4 +- swap/src/cli/tracing.rs | 27 +- swap/src/env.rs | 6 +- swap/src/kraken.rs | 8 +- swap/src/monero.rs | 38 ++ swap/src/network/quote.rs | 4 + swap/src/proptest.rs | 2 +- swap/src/protocol/bob/state.rs | 3 +- swap/src/protocol/bob/swap.rs | 9 +- swap/tests/harness/bitcoind.rs | 2 +- swap/tests/harness/electrs.rs | 2 - swap/tests/harness/mod.rs | 10 +- 36 files changed, 625 insertions(+), 301 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 08aed6ee..a4a651e5 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -67,9 +67,9 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help # Remove once python 3 is the default - - uses: actions/setup-python@v2.3.1 + - uses: actions/setup-python@v3 with: - python-version: '3.x' + python-version: "3.x" - id: create-archive-name shell: python # Use python to have a prettier name for the archive on Windows. diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bfc696d..6c09cdce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Change Monero nodes to [Rino tool nodes](https://community.rino.io/nodes.html) +- Revert logs to use rfc3339 local time formatting. +- Always write logs as JSON to files + +### Added + +- Adjust quote based on Bitcoin balance. + If the max_buy_btc in the ASB config is higher than the available balance to trade it will return the max available balance discounting the locking fees for monero, in the case the balance is lower than the min_buy_btc config it will return 0 to the CLI. If the ASB returns a quote of 0 the CLI will not allow you continue with a trade. +- Reduce required confirmations for Bitcoin transactions from 2 to 1 + ## [0.10.2] - 2021-12-25 ### Changed @@ -300,7 +312,7 @@ It is possible to migrate critical data from the old db to the sqlite but there - Fixed an issue where Alice would not verify if Bob's Bitcoin lock transaction is semantically correct, i.e. pays the agreed upon amount to an output owned by both of them. Fixing this required a **breaking change** on the network layer and hence old versions are not compatible with this version. -[Unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.2...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.2...HEAD [0.10.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.1...0.10.2 [0.10.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.0...0.10.1 [0.10.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.9.0...0.10.0 diff --git a/Cargo.lock b/Cargo.lock index f2dd135e..72ee11dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,9 +74,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" +checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27" [[package]] name = "arrayref" @@ -90,6 +90,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +[[package]] +name = "arrayvec" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" + [[package]] name = "asn1_der" version = "0.7.4" @@ -105,7 +111,7 @@ dependencies = [ "bzip2", "futures-core", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", "tokio", ] @@ -130,7 +136,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", ] [[package]] @@ -176,14 +182,14 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backoff" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fe17f59a06fe8b87a6fc8bf53bb70b3aba76d7685f432487a68cd5552853625" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", "getrandom 0.2.2", "instant", - "pin-project 1.0.5", + "pin-project-lite 0.2.8", "rand 0.8.3", "tokio", ] @@ -235,9 +241,9 @@ dependencies = [ [[package]] name = "bdk" -version = "0.12.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecf7e997526ceefbab7dd99fc0da6834ed8853bd051f53523415ed1dc82b870d" +checksum = "3face7de38293a2f7e2a9f69a48b442f28e864da0fc7a6a977388e31bdc367d7" dependencies = [ "async-trait", "bdk-macros", @@ -364,9 +370,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake2" @@ -562,13 +568,13 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "comfy-table" -version = "4.1.1" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11e95a3e867422fd8d04049041f5671f94d53c32a9dcd82e2be268714942f3f3" +checksum = "b103d85ca6e209388771bfb7aa6b68a7aeec4afbf6f0a0264bfbf50360e5212e" dependencies = [ "crossterm", - "strum 0.21.0", - "strum_macros 0.21.0", + "strum", + "strum_macros", "unicode-width", ] @@ -601,13 +607,13 @@ checksum = "e763eef8846b13b380f37dfecda401770b0ca4e56e95170237bd7c25c7db3582" [[package]] name = "console" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" dependencies = [ "encode_unicode", - "lazy_static", "libc", + "once_cell", "regex", "terminal_size", "unicode-width", @@ -729,15 +735,15 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.20.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d" +checksum = "77b75a27dc8d220f1f8521ea69cd55a34d720a200ebb3a624d9aa19193d3b432" dependencies = [ "bitflags", "crossterm_winapi", "libc", "mio", - "parking_lot", + "parking_lot 0.12.0", "signal-hook", "signal-hook-mio", "winapi 0.3.9", @@ -745,9 +751,9 @@ dependencies = [ [[package]] name = "crossterm_winapi" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507" +checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" dependencies = [ "winapi 0.3.9", ] @@ -891,12 +897,11 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9dd058f8b65922819fabb4a41e7d1964e56344042c26efbccd465202c23fa0c" +checksum = "349d6b4fabcd9e97e1df1ae15395ac7e49fb144946a0d453959dc2696273b9da" dependencies = [ "console", - "lazy_static", "tempfile", "zeroize", ] @@ -1050,6 +1055,15 @@ dependencies = [ "syn", ] +[[package]] +name = "fastrand" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + [[package]] name = "filetime" version = "0.2.14" @@ -1127,9 +1141,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -1142,9 +1156,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -1152,15 +1166,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -1176,23 +1190,21 @@ checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e" dependencies = [ "futures-core", "lock_api", - "parking_lot", + "parking_lot 0.11.2", ] [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote", "syn", @@ -1211,15 +1223,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-timer" @@ -1229,11 +1241,10 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1241,10 +1252,8 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -1335,9 +1344,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" +checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" dependencies = [ "bytes", "fnv", @@ -1348,7 +1357,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util", + "tokio-util 0.6.9", "tracing", ] @@ -1466,7 +1475,7 @@ checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 0.4.7", ] [[package]] @@ -1481,9 +1490,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "9100414882e15fb7feccb4897e5f0ff0ff1ca7d1a86a23208ada4d7a18e6c6c4" [[package]] name = "httpdate" @@ -1493,9 +1502,9 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.16" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes", "futures-channel", @@ -1506,8 +1515,8 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", - "pin-project-lite 0.2.6", + "itoa 1.0.1", + "pin-project-lite 0.2.8", "socket2 0.4.0", "tokio", "tower-service", @@ -1632,6 +1641,12 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "jobserver" version = "0.1.22" @@ -1726,7 +1741,7 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374" dependencies = [ - "arrayvec", + "arrayvec 0.5.2", "bitflags", "cfg-if 1.0.0", "ryu", @@ -1735,9 +1750,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.101" +version = "0.2.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" +checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" [[package]] name = "libgit2-sys" @@ -1774,7 +1789,7 @@ dependencies = [ "libp2p-websocket", "libp2p-yamux", "multiaddr", - "parking_lot", + "parking_lot 0.11.2", "pin-project 1.0.5", "smallvec", "wasm-timer", @@ -1798,7 +1813,7 @@ dependencies = [ "multiaddr", "multihash", "multistream-select", - "parking_lot", + "parking_lot 0.11.2", "pin-project 1.0.5", "prost", "prost-build", @@ -1847,7 +1862,7 @@ dependencies = [ "libp2p-core", "log", "nohash-hasher", - "parking_lot", + "parking_lot 0.11.2", "rand 0.7.3", "smallvec", "unsigned-varint", @@ -1991,7 +2006,7 @@ source = "git+https://github.com/libp2p/rust-libp2p.git#6d3ab8a3debe8d69dcd00417 dependencies = [ "futures", "libp2p-core", - "parking_lot", + "parking_lot 0.11.2", "thiserror", "yamux", ] @@ -2075,9 +2090,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b" dependencies = [ "scopeguard", ] @@ -2474,6 +2489,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ba99ba6393e2c3734791401b66902d981cb03bf190af674ca69949b6d5fb15" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" version = "1.7.2" @@ -2493,7 +2517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7337d80c23c2d8b1349563981bc4fb531220733743ba8115454a67b181173f0d" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.7", "open-metrics-client-derive-text-encode", "owning_ref", ] @@ -2532,7 +2556,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.5", +] + +[[package]] +name = "parking_lot" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.1", ] [[package]] @@ -2550,14 +2584,25 @@ dependencies = [ ] [[package]] -name = "pem" -version = "1.0.1" +name = "parking_lot_core" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06673860db84d02a63942fa69cd9543f2624a5df3aea7f33173048fa7ad5cf1a" +checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "redox_syscall", + "smallvec", + "windows-sys", +] + +[[package]] +name = "pem" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9a3b09a20e374558580a4914d3b7d89bd61b954a5a5e1dcbea98753addb1947" dependencies = [ "base64 0.13.0", - "once_cell", - "regex", ] [[package]] @@ -2633,9 +2678,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905" +checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c" [[package]] name = "pin-utils" @@ -2727,18 +2772,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "1.0.27" @@ -3134,15 +3167,16 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.7" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bea77bc708afa10e59905c3d4af7c8fd43c9214251673095ff8b14345fcbc5" +checksum = "87f242f1488a539a79bac6dbe7c8609ae43b7914b7736210f239a37cccb32525" dependencies = [ "base64 0.13.0", "bytes", "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "hyper", @@ -3153,7 +3187,7 @@ dependencies = [ "log", "mime", "percent-encoding", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", "rustls 0.20.2", "rustls-pemfile", "serde", @@ -3162,12 +3196,12 @@ dependencies = [ "tokio", "tokio-rustls 0.23.1", "tokio-socks", - "tokio-util", + "tokio-util 0.6.9", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots 0.21.0", + "webpki-roots 0.22.2", "winreg 0.7.0", ] @@ -3198,20 +3232,20 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.18.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b5a9625a7e6060b23db692facf49082cc78889a7e6ac94a735356ae49db4b0" +checksum = "d37baa70cf8662d2ba1c1868c5983dda16ef32b105cce41fb5c47e72936a90b3" dependencies = [ - "arrayvec", + "arrayvec 0.7.2", "num-traits", "serde", ] [[package]] name = "rust_decimal_macros" -version = "1.18.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2a71e447554613b11da876d63d04e78fc3e8e86769488d3b58887671e23bc86" +checksum = "184abaf7b434800e1a5a8aad3ebc8cd7498df33af72d65371d797a264713a59b" dependencies = [ "quote", "rust_decimal", @@ -3453,9 +3487,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] @@ -3482,9 +3516,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -3493,12 +3527,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "ee2bb9cd061c5865d345bb02ca49fcef1391741b672b54a0bf7b679badec3142" dependencies = [ "indexmap", - "itoa", + "itoa 1.0.1", "ryu", "serde", ] @@ -3510,16 +3544,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.7", "ryu", "serde", ] [[package]] name = "serde_with" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad6056b4cb69b6e43e3a0f055def223380baecc99da683884f205bf347f7c4b3" +checksum = "ec1e6ec4d8950e5b1e894eac0d360742f3b1407a6078a604a731c4b3f49cefbc" dependencies = [ "rustversion", "serde", @@ -3600,9 +3634,9 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" +checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" dependencies = [ "libc", "signal-hook-registry", @@ -3653,7 +3687,7 @@ dependencies = [ "fxhash", "libc", "log", - "parking_lot", + "parking_lot 0.11.2", ] [[package]] @@ -3788,13 +3822,13 @@ dependencies = [ "hashlink", "hex", "indexmap", - "itoa", + "itoa 0.4.7", "libc", "libsqlite3-sys", "log", "memchr", "once_cell", - "parking_lot", + "parking_lot 0.11.2", "percent-encoding", "rustls 0.19.0", "serde", @@ -3880,9 +3914,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "structopt" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -3902,31 +3936,13 @@ dependencies = [ "syn", ] -[[package]] -name = "strum" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf86bbcfd1fa9670b7a129f64fc0c9fcbbfe4f1bc4210e9e98fe71ffc12cde2" - [[package]] name = "strum" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cae14b91c7d11c9a851d3fbc80a963198998c2a64eec840477fa92d8ce9b70bb" dependencies = [ - "strum_macros 0.23.0", -] - -[[package]] -name = "strum_macros" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb076d8b589fde927ec90d05920d610554ca3a4d9dddb177481cadd071a19c2e" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", + "strum_macros", ] [[package]] @@ -4005,16 +4021,16 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum 0.23.0", + "strum", "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.3", + "time 0.3.7", "tokio", "tokio-socks", "tokio-tar", "tokio-tungstenite", - "tokio-util", + "tokio-util 0.7.0", "toml", "torut", "tracing", @@ -4053,13 +4069,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.3", "redox_syscall", "remove_dir_all", "winapi 0.3.9", @@ -4156,11 +4172,12 @@ dependencies = [ [[package]] name = "time" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde1cf55178e0293453ba2cca0d5f8392a922e52aa958aee9c28ed02becc6d03" +checksum = "004cbc98f30fa233c61a38bc77e96a9106e65c88f2d3bef182ae952027e5753d" dependencies = [ "libc", + "num_threads", ] [[package]] @@ -4189,9 +4206,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.12.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +checksum = "b9d0183f6f6001549ab68f8c7585093bb732beefbcf6d23a10b9b95c73a1dd49" dependencies = [ "autocfg 1.0.1", "bytes", @@ -4200,8 +4217,8 @@ dependencies = [ "mio", "num_cpus", "once_cell", - "parking_lot", - "pin-project-lite 0.2.6", + "parking_lot 0.11.2", + "pin-project-lite 0.2.8", "signal-hook-registry", "tokio-macros", "winapi 0.3.9", @@ -4209,9 +4226,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.1.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf7b11a536f46a809a8a9f0bb4237020f70ecbf115b842360afb127ea2fda57" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -4259,7 +4276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c535f53c0cfa1acace62995a8994fc9cc1f12d202420da96ff306ee24d576469" dependencies = [ "futures-core", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", "tokio", ] @@ -4297,15 +4314,29 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" +checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" dependencies = [ "bytes", "futures-core", "futures-sink", "log", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64910e1b9c1901aaf5375561e35b9c057d95ff41a44ede043a03e09279eabaf1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "log", + "pin-project-lite 0.2.8", "tokio", ] @@ -4320,9 +4351,9 @@ dependencies = [ [[package]] name = "torut" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb506186a6ad032c4b50bd92c35307a32f95146e7d07ee28b93cc1410dfc384" +checksum = "99febc413f26cf855b3a309c5872edff5c31e0ffe9c2fce5681868761df36f69" dependencies = [ "base32", "base64 0.13.0", @@ -4349,7 +4380,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", - "pin-project-lite 0.2.6", + "pin-project-lite 0.2.8", "tracing-attributes", "tracing-core", ] @@ -4476,7 +4507,7 @@ dependencies = [ "lazy_static", "log", "lru-cache", - "parking_lot", + "parking_lot 0.11.2", "resolv-conf", "smallvec", "thiserror", @@ -4780,7 +4811,7 @@ checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" dependencies = [ "futures", "js-sys", - "parking_lot", + "parking_lot 0.11.2", "pin-utils", "wasm-bindgen", "wasm-bindgen-futures", @@ -4835,6 +4866,15 @@ dependencies = [ "webpki 0.21.4", ] +[[package]] +name = "webpki-roots" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552ceb903e957524388c4d3475725ff2c8b7960922063af6ce53c9a43da07449" +dependencies = [ + "webpki 0.22.0", +] + [[package]] name = "which" version = "4.0.2" @@ -4895,6 +4935,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" + +[[package]] +name = "windows_i686_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" + +[[package]] +name = "windows_i686_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" + [[package]] name = "winreg" version = "0.6.2" @@ -4952,7 +5035,7 @@ dependencies = [ "futures", "log", "nohash-hasher", - "parking_lot", + "parking_lot 0.11.2", "rand 0.8.3", "static_assertions", ] diff --git a/README.md b/README.md index 9b03089a..5a8e39ec 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,11 @@ It is not recommended to bump fees when swapping because it can have unpredictab We are encourage community contributions whether it be a bug fix or an improvement to the documentation. Please have a look at the [contribution guidelines](./CONTRIBUTING.md). +## Rust Version Support + +Please note that only the latest stable Rust toolchain is supported. +All stable toolchains since 1.58 _should_ work. + ## Contact Feel free to reach out to us in the [COMIT-Monero Matrix channel](https://matrix.to/#/#comit-monero:matrix.org). diff --git a/docs/asb/README.md b/docs/asb/README.md index 60fcdcf3..e39375a9 100644 --- a/docs/asb/README.md +++ b/docs/asb/README.md @@ -12,7 +12,7 @@ This quickstart guide assumes that you are running the software on testnet (i.e. 3. Run the ASB in terminal: `./asb --testnet start` 4. Follow the setup wizard in the terminal -Public Monero nodes for running the Monero Wallet RPC can be found [here](https://melo.tools/nodes.html). +Public Monero nodes for running the Monero Wallet RPC can be found [here](https://community.rino.io/nodes.html). Run `./asb --help` for more information. diff --git a/dprint.json b/dprint.json index c73d9690..3f1eab87 100644 --- a/dprint.json +++ b/dprint.json @@ -18,8 +18,8 @@ "includes": ["**/*.{md}", "**/*.{toml}", "**/*.{rs}"], "excludes": [ "target/" ], "plugins": [ - "https://plugins.dprint.dev/markdown-0.6.1.wasm", + "https://plugins.dprint.dev/markdown-0.13.1.wasm", "https://github.com/thomaseizinger/dprint-plugin-cargo-toml/releases/download/0.1.0/cargo-toml-0.1.0.wasm", - "https://plugins.dprint.dev/rustfmt-0.4.0.exe-plugin@c6bb223ef6e5e87580177f6461a0ab0554ac9ea6b54f78ea7ae8bf63b14f5bc2" + "https://plugins.dprint.dev/rustfmt-0.6.1.exe-plugin@99b89a0599fd3a63e597e03436862157901f3facae2f0c2fbd0b9f656cdbc2a5" ] } diff --git a/monero-harness/Cargo.toml b/monero-harness/Cargo.toml index b30066c8..b659220b 100644 --- a/monero-harness/Cargo.toml +++ b/monero-harness/Cargo.toml @@ -2,7 +2,7 @@ name = "monero-harness" version = "0.1.0" authors = [ "CoBloX Team " ] -edition = "2018" +edition = "2021" publish = false [dependencies] diff --git a/monero-harness/src/image.rs b/monero-harness/src/image.rs index f7cc21ed..20370288 100644 --- a/monero-harness/src/image.rs +++ b/monero-harness/src/image.rs @@ -13,7 +13,7 @@ pub const MONEROD_DEFAULT_NETWORK: &str = "monero_network"; /// this doesn't matter. pub const RPC_PORT: u16 = 18081; -#[derive(Debug)] +#[derive(Debug, Default)] pub struct Monerod { args: MonerodArgs, } @@ -25,7 +25,7 @@ impl Image for Monerod { type EntryPoint = str; fn descriptor(&self) -> String { - "xmrto/monero:v0.17.2.0".to_owned() + "rinocommunity/monero:v0.17.2.0".to_owned() } fn wait_until_ready(&self, container: &Container<'_, D, Self>) { @@ -58,15 +58,7 @@ impl Image for Monerod { } } -impl Default for Monerod { - fn default() -> Self { - Self { - args: MonerodArgs::default(), - } - } -} - -#[derive(Debug)] +#[derive(Debug, Default)] pub struct MoneroWalletRpc { args: MoneroWalletRpcArgs, } @@ -78,7 +70,7 @@ impl Image for MoneroWalletRpc { type EntryPoint = str; fn descriptor(&self) -> String { - "xmrto/monero:v0.17.2.0".to_owned() + "rinocommunity/monero:v0.17.2.0".to_owned() } fn wait_until_ready(&self, container: &Container<'_, D, Self>) { @@ -111,14 +103,6 @@ impl Image for MoneroWalletRpc { } } -impl Default for MoneroWalletRpc { - fn default() -> Self { - Self { - args: MoneroWalletRpcArgs::default(), - } - } -} - impl MoneroWalletRpc { pub fn new(name: &str, daemon_address: String) -> Self { Self { diff --git a/monero-harness/src/lib.rs b/monero-harness/src/lib.rs index 0fc42880..0267c754 100644 --- a/monero-harness/src/lib.rs +++ b/monero-harness/src/lib.rs @@ -71,7 +71,7 @@ impl<'c> Monero { let miner = "miner"; tracing::info!("Starting miner wallet: {}", miner); let (miner_wallet, miner_container) = - MoneroWalletRpc::new(cli, &miner, &monerod, prefix.clone()).await?; + MoneroWalletRpc::new(cli, miner, &monerod, prefix.clone()).await?; wallets.push(miner_wallet); containers.push(miner_container); @@ -83,7 +83,7 @@ impl<'c> Monero { // trying for 5 minutes let (wallet, container) = tokio::time::timeout(Duration::from_secs(300), async { loop { - let result = MoneroWalletRpc::new(cli, &wallet, &monerod, prefix.clone()).await; + let result = MoneroWalletRpc::new(cli, wallet, &monerod, prefix.clone()).await; match result { Ok(tuple) => { return tuple; } @@ -188,7 +188,6 @@ fn random_prefix() -> String { #[derive(Clone, Debug)] pub struct Monerod { - rpc_port: u16, name: String, network: String, client: monerod::Client, @@ -196,9 +195,7 @@ pub struct Monerod { #[derive(Clone, Debug)] pub struct MoneroWalletRpc { - rpc_port: u16, name: String, - network: String, client: wallet::Client, } @@ -220,7 +217,6 @@ impl<'c> Monerod { Ok(( Self { - rpc_port: monerod_rpc_port, name, network, client: monerod::Client::localhost(monerod_rpc_port)?, @@ -252,7 +248,7 @@ impl<'c> MoneroWalletRpc { prefix: String, ) -> Result<(Self, Container<'c, Cli, image::MoneroWalletRpc>)> { let daemon_address = format!("{}:{}", monerod.name, RPC_PORT); - let image = image::MoneroWalletRpc::new(&name, daemon_address); + let image = image::MoneroWalletRpc::new(name, daemon_address); let network = monerod.network.clone(); let run_args = RunArgs::default() @@ -272,9 +268,7 @@ impl<'c> MoneroWalletRpc { Ok(( Self { - rpc_port: wallet_rpc_port, name: name.to_string(), - network, client, }, container, diff --git a/monero-rpc/Cargo.toml b/monero-rpc/Cargo.toml index 758e843b..6bd76ad4 100644 --- a/monero-rpc/Cargo.toml +++ b/monero-rpc/Cargo.toml @@ -2,7 +2,7 @@ name = "monero-rpc" version = "0.1.0" authors = [ "CoBloX Team " ] -edition = "2018" +edition = "2021" [dependencies] anyhow = "1" diff --git a/monero-rpc/src/wallet.rs b/monero-rpc/src/wallet.rs index db4e318d..b0f59b82 100644 --- a/monero-rpc/src/wallet.rs +++ b/monero-rpc/src/wallet.rs @@ -184,12 +184,7 @@ pub struct Refreshed { #[derive(Debug, Clone, Deserialize)] pub struct SweepAll { - amount_list: Vec, - fee_list: Vec, - multisig_txset: String, pub tx_hash_list: Vec, - unsigned_txset: String, - weight_list: Vec, } #[derive(Debug, Copy, Clone, Deserialize)] @@ -244,7 +239,7 @@ mod tests { } }"#; - let _: Response = serde_json::from_str(&response).unwrap(); + let _: Response = serde_json::from_str(response).unwrap(); } #[test] @@ -256,6 +251,6 @@ mod tests { } }"#; - let _: Response = serde_json::from_str(&response).unwrap(); + let _: Response = serde_json::from_str(response).unwrap(); } } diff --git a/monero-wallet/Cargo.toml b/monero-wallet/Cargo.toml index 4e97bbe8..f767b08e 100644 --- a/monero-wallet/Cargo.toml +++ b/monero-wallet/Cargo.toml @@ -2,7 +2,7 @@ name = "monero-wallet" version = "0.1.0" authors = [ "CoBloX Team " ] -edition = "2018" +edition = "2021" [dependencies] anyhow = "1" diff --git a/monero-wallet/src/lib.rs b/monero-wallet/src/lib.rs index 292e828e..2058f476 100644 --- a/monero-wallet/src/lib.rs +++ b/monero-wallet/src/lib.rs @@ -77,8 +77,8 @@ mod tests { let result = rpc_client .get_outs( key_offsets - .to_vec() - .into_iter() + .iter() + .cloned() .map(|varint| GetOutputsOut { amount: 0, index: varint.0, diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 5c4233dd..04d5285c 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.53" +channel = "1.59" components = ["clippy"] targets = ["armv7-unknown-linux-gnueabihf"] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 151cff7a..c631260a 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -2,7 +2,7 @@ name = "swap" version = "0.10.2" authors = [ "The COMIT guys " ] -edition = "2018" +edition = "2021" description = "XMR/BTC trustless atomic swaps." [lib] @@ -13,18 +13,18 @@ anyhow = "1" async-compression = { version = "0.3", features = [ "bzip2", "tokio" ] } async-trait = "0.1" atty = "0.2" -backoff = { version = "0.3", features = [ "tokio" ] } +backoff = { version = "0.4", features = [ "tokio" ] } base64 = "0.13" -bdk = "0.12" +bdk = "0.16" big-bytes = "1" bitcoin = { version = "0.27", features = [ "rand", "use-serde" ] } bmrng = "0.5" -comfy-table = "4.1.1" +comfy-table = "5.0" config = { version = "0.11", default-features = false, features = [ "toml" ] } conquer-once = "0.3" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } data-encoding = "2.3" -dialoguer = "0.8" +dialoguer = "0.10" directories-next = "2" ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "libsecp_compat", "serde" ] } ed25519-dalek = "1" @@ -56,7 +56,7 @@ time = "0.3" tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } tokio-socks = "0.5" tokio-tungstenite = { version = "0.15", features = [ "rustls-tls" ] } -tokio-util = { version = "0.6", features = [ "io" ] } +tokio-util = { version = "0.7", features = [ "io", "codec" ] } toml = "0.5" torut = { version = "0.2", default-features = false, features = [ "v3", "control" ] } tracing = { version = "0.1", features = [ "attributes" ] } diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index a5ad678f..1a06d95f 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -319,13 +319,46 @@ where min_buy: bitcoin::Amount, max_buy: bitcoin::Amount, ) -> Result { - let rate = self + let ask_price = self .latest_rate .latest_rate() - .context("Failed to get latest rate")?; + .context("Failed to get latest rate")? + .ask() + .context("Failed to compute asking price")?; + + let max_bitcoin_for_monero = self + .monero_wallet + .get_balance() + .await? + .max_bitcoin_for_price(ask_price); + + if min_buy > max_bitcoin_for_monero { + tracing::warn!( + "Your Monero balance is too low to initiate a swap, as your minimum swap amount is {}. You could at most swap {}", + min_buy, max_bitcoin_for_monero + ); + + return Ok(BidQuote { + price: ask_price, + min_quantity: bitcoin::Amount::ZERO, + max_quantity: bitcoin::Amount::ZERO, + }); + } + + if max_buy > max_bitcoin_for_monero { + tracing::warn!( + "Your Monero balance is too low to initiate a swap with the maximum swap amount {} that you have specified in your config. You can at most swap {}", + max_buy, max_bitcoin_for_monero + ); + return Ok(BidQuote { + price: ask_price, + min_quantity: min_buy, + max_quantity: max_bitcoin_for_monero, + }); + } Ok(BidQuote { - price: rate.ask().context("Failed to compute asking price")?, + price: ask_price, min_quantity: min_buy, max_quantity: max_buy, }) diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index bac3ae94..f3312f29 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -29,7 +29,7 @@ use swap::cli::{list_sellers, EventLoop, SellerStatus}; use swap::database::open_db; use swap::env::Config; use swap::libp2p_ext::MultiAddrExt; -use swap::network::quote::BidQuote; +use swap::network::quote::{BidQuote, ZeroQuoteReceived}; use swap::network::swarm; use swap::protocol::bob; use swap::protocol::bob::{BobState, Swap}; @@ -47,7 +47,7 @@ async fn main() -> Result<()> { json, cmd, } = match parse_args_and_apply_defaults(env::args_os())? { - ParseResult::Arguments(args) => args, + ParseResult::Arguments(args) => *args, ParseResult::PrintAndExitZero { message } => { println!("{}", message); std::process::exit(0); @@ -67,6 +67,12 @@ async fn main() -> Result<()> { let swap_id = Uuid::new_v4(); cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -95,11 +101,11 @@ async fn main() -> Result<()> { tracing::debug!(peer_id = %swarm.local_peer_id(), "Network layer initialized"); let (event_loop, mut event_loop_handle) = - EventLoop::new(swap_id, swarm, seller_peer_id, env_config)?; + EventLoop::new(swap_id, swarm, seller_peer_id)?; let event_loop = tokio::spawn(event_loop.run()); let max_givable = || bitcoin_wallet.max_giveable(TxLock::script_size()); - let (amount, fees) = determine_btc_to_swap( + let (amount, fees) = match determine_btc_to_swap( json, event_loop_handle.request_quote(), bitcoin_wallet.new_address(), @@ -107,7 +113,16 @@ async fn main() -> Result<()> { max_givable, || bitcoin_wallet.sync(), ) - .await?; + .await + { + Ok(val) => val, + Err(error) => match error.downcast::() { + Ok(_) => { + bail!("Seller's XMR balance is currently too low to initiate a swap, please try again later") + } + Err(other) => bail!(other), + }, + }; tracing::info!(%amount, %fees, "Determined swap amount"); @@ -140,6 +155,11 @@ async fn main() -> Result<()> { Command::History => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let swaps = db.all().await?; @@ -164,6 +184,11 @@ async fn main() -> Result<()> { Command::Config => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + tracing::info!(path=%data_dir.display(), "Data directory"); tracing::info!(path=%format!("{}/logs", data_dir.display()), "Log files directory"); tracing::info!(path=%format!("{}/sqlite", data_dir.display()), "Sqlite file location"); @@ -178,6 +203,12 @@ async fn main() -> Result<()> { address, } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -211,6 +242,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -236,6 +273,12 @@ async fn main() -> Result<()> { tor_socks5_port, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -267,8 +310,7 @@ async fn main() -> Result<()> { .add_address(seller_peer_id, seller_address); } - let (event_loop, event_loop_handle) = - EventLoop::new(swap_id, swarm, seller_peer_id, env_config)?; + let (event_loop, event_loop_handle) = EventLoop::new(swap_id, swarm, seller_peer_id)?; let handle = tokio::spawn(event_loop.run()); let monero_receive_address = db.get_monero_address(swap_id).await?; @@ -298,6 +340,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -320,6 +368,12 @@ async fn main() -> Result<()> { bitcoin_target_block, } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -345,6 +399,11 @@ async fn main() -> Result<()> { .context("Rendezvous node address must contain peer ID")?; cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let identity = seed.derive_libp2p_identity(); @@ -425,6 +484,11 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -439,6 +503,13 @@ async fn main() -> Result<()> { tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet"); } Command::MoneroRecovery { swap_id } => { + cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; + + match check_latest_version().await { + Ok(()) => (), + Err(error) => tracing::error!("{}", error), + }; + let db = open_db(data_dir.join("sqlite")).await?; let swap_state: BobState = db.get_state(swap_id).await?.try_into()?; @@ -556,6 +627,11 @@ where { tracing::debug!("Requesting quote"); let bid_quote = bid_quote.await?; + + if bid_quote.max_quantity == bitcoin::Amount::ZERO { + bail!(ZeroQuoteReceived) + } + tracing::info!( price = %bid_quote.price, minimum_amount = %bid_quote.min_quantity, @@ -616,10 +692,43 @@ where Ok((btc_swap_amount, fees)) } +pub async fn check_latest_version() -> Result<()> { + const GITHUB_LATEST_VERSION_URL: &str = + "https://github.com/comit-network/xmr-btc-swap/releases/latest"; + + let response = match reqwest::get(GITHUB_LATEST_VERSION_URL).await { + Ok(res) => res, + Err(_) => bail!( + "could not request the website {}", + GITHUB_LATEST_VERSION_URL + ), + }; + + let last_version_from_url: &str = match response.url().path_segments() { + Some(split_segments) => match split_segments.last() { + Some(seg) => seg, + None => bail!("could not check the latest version"), + }, + None => bail!("could not check the latest version"), + }; + + let version_from_binary: &str = env!("CARGO_PKG_VERSION"); + + if last_version_from_url != version_from_binary { + tracing::warn!( + "You are not on the lastest version {}, it's available on Github: {}", + last_version_from_url, + GITHUB_LATEST_VERSION_URL + ); + }; + + Ok(()) +} + #[cfg(test)] mod tests { use super::*; - use crate::determine_btc_to_swap; + use crate::{check_latest_version, determine_btc_to_swap}; use ::bitcoin::Amount; use std::sync::Mutex; use swap::tracing_ext::capture_logs; @@ -915,6 +1024,32 @@ mod tests { ); } + #[tokio::test] + async fn given_bid_quote_max_amount_0_return_errorq() { + let givable = Arc::new(Mutex::new(MaxGiveable::new(vec![ + Amount::from_btc(0.0001).unwrap(), + Amount::from_btc(0.01).unwrap(), + ]))); + + let determination_error = determine_btc_to_swap( + true, + async { Ok(quote_with_max(0.00)) }, + get_dummy_address(), + || async { Ok(Amount::from_btc(0.0101)?) }, + || async { + let mut result = givable.lock().unwrap(); + result.give() + }, + || async { Ok(()) }, + ) + .await + .err() + .unwrap() + .to_string(); + + assert_eq!("Received quote of 0", determination_error); + } + struct MaxGiveable { amounts: Vec, call_counter: usize, @@ -956,4 +1091,13 @@ mod tests { async fn get_dummy_address() -> Result { Ok("1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6".parse()?) } + + #[tokio::test] + async fn check_correct_latest_version() { + let writer = capture_logs(LevelFilter::INFO); + + check_latest_version().await.unwrap(); + + assert_eq!(writer.captured(), r""); + } } diff --git a/swap/src/bitcoin.rs b/swap/src/bitcoin.rs index 53fc5197..cc9095e3 100644 --- a/swap/src/bitcoin.rs +++ b/swap/src/bitcoin.rs @@ -171,7 +171,7 @@ pub fn verify_sig( ) -> Result<()> { let ecdsa = ECDSA::verify_only(); - if ecdsa.verify(&verification_key.0, &transaction_sighash.into_inner(), &sig) { + if ecdsa.verify(&verification_key.0, &transaction_sighash.into_inner(), sig) { Ok(()) } else { bail!(InvalidSignature) @@ -194,7 +194,7 @@ pub fn verify_encsig( &verification_key.0, &encryption_key.0, &digest.into_inner(), - &encsig, + encsig, ) { Ok(()) } else { @@ -213,7 +213,7 @@ pub fn build_shared_output_descriptor(A: Point, B: Point) -> Descriptor::from_str(&miniscript) diff --git a/swap/src/bitcoin/lock.rs b/swap/src/bitcoin/lock.rs index ea6c5cdd..c9efff2b 100644 --- a/swap/src/bitcoin/lock.rs +++ b/swap/src/bitcoin/lock.rs @@ -200,9 +200,10 @@ mod tests { #[tokio::test] async fn bob_can_fund_without_a_change_output() { let (A, B) = alice_and_bob(); - let fees = 610; + let fees = 300; let agreed_amount = Amount::from_sat(10000); - let wallet = WalletBuilder::new(agreed_amount.as_sat() + fees).build(); + let amount = agreed_amount.as_sat() + fees; + let wallet = WalletBuilder::new(amount).build(); let psbt = bob_make_psbt(A, B, &wallet, agreed_amount).await; assert_eq!( @@ -262,7 +263,7 @@ mod tests { amount: Amount, ) -> PartiallySignedTransaction { let change = wallet.new_address().await.unwrap(); - TxLock::new(&wallet, amount, A, B, change) + TxLock::new(wallet, amount, A, B, change) .await .unwrap() .into() diff --git a/swap/src/bitcoin/redeem.rs b/swap/src/bitcoin/redeem.rs index a244b0cd..8c8b502e 100644 --- a/swap/src/bitcoin/redeem.rs +++ b/swap/src/bitcoin/redeem.rs @@ -128,7 +128,7 @@ impl TxRedeem { let sig = sigs .into_iter() - .find(|sig| verify_sig(&B, &self.digest(), &sig).is_ok()) + .find(|sig| verify_sig(&B, &self.digest(), sig).is_ok()) .context("Neither signature on witness stack verifies against B")?; Ok(sig) diff --git a/swap/src/bitcoin/refund.rs b/swap/src/bitcoin/refund.rs index 6f6cade0..f5fb44c5 100644 --- a/swap/src/bitcoin/refund.rs +++ b/swap/src/bitcoin/refund.rs @@ -132,7 +132,7 @@ impl TxRefund { let sig = sigs .into_iter() - .find(|sig| verify_sig(&B, &self.digest(), &sig).is_ok()) + .find(|sig| verify_sig(&B, &self.digest(), sig).is_ok()) .context("Neither signature on witness stack verifies against B")?; Ok(sig) diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index d9631bf9..fc615911 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -102,7 +102,7 @@ impl Wallet { self.wallet .lock() .await - .broadcast(transaction) + .broadcast(&transaction) .with_context(|| { format!("Failed to broadcast Bitcoin {} transaction {}", kind, txid) })?; @@ -152,13 +152,13 @@ impl Wallet { ScriptStatus::Retrying } }; - + if new_status != ScriptStatus::Retrying { last_status = Some(print_status_change(txid, last_status, new_status)); let all_receivers_gone = sender.send(new_status).is_err(); - + if all_receivers_gone { tracing::debug!(%txid, "All receivers gone, removing subscription"); client.lock().await.subscriptions.remove(&(txid, script)); diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index f2d57ceb..ae793e1d 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -15,8 +15,8 @@ use url::Url; use uuid::Uuid; // See: https://moneroworld.com/ -pub const DEFAULT_MONERO_DAEMON_ADDRESS: &str = "node.melo.tools:18081"; -pub const DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET: &str = "stagenet.melo.tools:38081"; +pub const DEFAULT_MONERO_DAEMON_ADDRESS: &str = "node.community.rino.io:18081"; +pub const DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET: &str = "stagenet.community.rino.io:38081"; // See: https://1209k.com/bitcoin-eye/ele.php?chain=btc const DEFAULT_ELECTRUM_RPC_URL: &str = "ssl://blockstream.info:700"; @@ -41,7 +41,7 @@ pub struct Arguments { #[derive(Debug, PartialEq)] pub enum ParseResult { /// The arguments we were invoked in. - Arguments(Arguments), + Arguments(Box), /// A flag or command was given that does not need further processing other /// than printing the provided message. /// @@ -260,7 +260,7 @@ where }, }; - Ok(ParseResult::Arguments(arguments)) + Ok(ParseResult::Arguments(Box::new(arguments))) } #[derive(Debug, PartialEq)] @@ -693,7 +693,8 @@ mod tests { MULTI_ADDRESS, ]; - let expected_args = ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults()); + let expected_args = + ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().into_boxed()); let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!(expected_args, args); @@ -717,7 +718,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults()) + ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().into_boxed()) ); } @@ -778,7 +779,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::resume_mainnet_defaults()) + ParseResult::Arguments(Arguments::resume_mainnet_defaults().into_boxed()) ); } @@ -790,7 +791,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::resume_testnet_defaults()) + ParseResult::Arguments(Arguments::resume_testnet_defaults().into_boxed()) ); } @@ -802,7 +803,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::cancel_mainnet_defaults()) + ParseResult::Arguments(Arguments::cancel_mainnet_defaults().into_boxed()) ); } @@ -814,7 +815,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::cancel_testnet_defaults()) + ParseResult::Arguments(Arguments::cancel_testnet_defaults().into_boxed()) ); } @@ -826,7 +827,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::refund_mainnet_defaults()) + ParseResult::Arguments(Arguments::refund_mainnet_defaults().into_boxed()) ); } @@ -838,7 +839,7 @@ mod tests { assert_eq!( args, - ParseResult::Arguments(Arguments::refund_testnet_defaults()) + ParseResult::Arguments(Arguments::refund_testnet_defaults().into_boxed()) ); } @@ -866,6 +867,7 @@ mod tests { ParseResult::Arguments( Arguments::buy_xmr_mainnet_defaults() .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("mainnet")) + .into_boxed() ) ); @@ -890,6 +892,7 @@ mod tests { ParseResult::Arguments( Arguments::buy_xmr_testnet_defaults() .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("testnet")) + .into_boxed() ) ); @@ -909,6 +912,7 @@ mod tests { ParseResult::Arguments( Arguments::resume_mainnet_defaults() .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("mainnet")) + .into_boxed() ) ); @@ -929,6 +933,7 @@ mod tests { ParseResult::Arguments( Arguments::resume_testnet_defaults() .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("testnet")) + .into_boxed() ) ); } @@ -950,7 +955,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().with_debug()) + ParseResult::Arguments( + Arguments::buy_xmr_mainnet_defaults() + .with_debug() + .into_boxed() + ) ); let raw_ars = vec![ @@ -969,7 +978,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_debug()) + ParseResult::Arguments( + Arguments::buy_xmr_testnet_defaults() + .with_debug() + .into_boxed() + ) ); let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID]; @@ -977,7 +990,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::resume_mainnet_defaults().with_debug()) + ParseResult::Arguments( + Arguments::resume_mainnet_defaults() + .with_debug() + .into_boxed() + ) ); let raw_ars = vec![ @@ -992,7 +1009,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::resume_testnet_defaults().with_debug()) + ParseResult::Arguments( + Arguments::resume_testnet_defaults() + .with_debug() + .into_boxed() + ) ); } @@ -1013,7 +1034,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().with_json()) + ParseResult::Arguments( + Arguments::buy_xmr_mainnet_defaults() + .with_json() + .into_boxed() + ) ); let raw_ars = vec![ @@ -1032,7 +1057,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().with_json()) + ParseResult::Arguments( + Arguments::buy_xmr_testnet_defaults() + .with_json() + .into_boxed() + ) ); let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID]; @@ -1040,7 +1069,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::resume_mainnet_defaults().with_json()) + ParseResult::Arguments( + Arguments::resume_mainnet_defaults() + .with_json() + .into_boxed() + ) ); let raw_ars = vec![ @@ -1055,7 +1088,11 @@ mod tests { let args = parse_args_and_apply_defaults(raw_ars).unwrap(); assert_eq!( args, - ParseResult::Arguments(Arguments::resume_testnet_defaults().with_json()) + ParseResult::Arguments( + Arguments::resume_testnet_defaults() + .with_json() + .into_boxed() + ) ); } @@ -1303,6 +1340,10 @@ mod tests { self.json = true; self } + + pub fn into_boxed(self) -> Box { + Box::new(self) + } } fn data_dir_path_cli() -> PathBuf { diff --git a/swap/src/cli/event_loop.rs b/swap/src/cli/event_loop.rs index d8c0d453..3d376449 100644 --- a/swap/src/cli/event_loop.rs +++ b/swap/src/cli/event_loop.rs @@ -1,10 +1,10 @@ use crate::bitcoin::EncryptedSignature; use crate::cli::behaviour::{Behaviour, OutEvent}; +use crate::monero; use crate::network::encrypted_signature; use crate::network::quote::BidQuote; use crate::network::swap_setup::bob::NewSwap; use crate::protocol::bob::State2; -use crate::{env, monero}; use anyhow::{Context, Result}; use futures::future::{BoxFuture, OptionFuture}; use futures::{FutureExt, StreamExt}; @@ -50,7 +50,6 @@ impl EventLoop { swap_id: Uuid, swarm: Swarm, alice_peer_id: PeerId, - env_config: env::Config, ) -> Result<(Self, EventLoopHandle)> { let execution_setup = bmrng::channel_with_timeout(1, Duration::from_secs(60)); let transfer_proof = bmrng::channel_with_timeout(1, Duration::from_secs(60)); @@ -76,7 +75,6 @@ impl EventLoop { transfer_proof: transfer_proof.1, encrypted_signature: encrypted_signature.0, quote: quote.0, - env_config, }; Ok((event_loop, handle)) @@ -220,7 +218,6 @@ pub struct EventLoopHandle { transfer_proof: bmrng::RequestReceiver, encrypted_signature: bmrng::RequestSender, quote: bmrng::RequestSender<(), BidQuote>, - env_config: env::Config, } impl EventLoopHandle { diff --git a/swap/src/cli/list_sellers.rs b/swap/src/cli/list_sellers.rs index 84a9887d..90816e2f 100644 --- a/swap/src/cli/list_sellers.rs +++ b/swap/src/cli/list_sellers.rs @@ -271,7 +271,7 @@ impl EventLoop { QuoteStatus::Received(Status::Online(quote)) => { let address = self .reachable_asb_address - .get(&peer_id) + .get(peer_id) .expect("if we got a quote we must have stored an address"); Ok(Seller { @@ -282,7 +282,7 @@ impl EventLoop { QuoteStatus::Received(Status::Unreachable) => { let address = self .unreachable_asb_address - .get(&peer_id) + .get(peer_id) .expect("if we got a quote we must have stored an address"); Ok(Seller { diff --git a/swap/src/cli/tracing.rs b/swap/src/cli/tracing.rs index 5ed58231..3bafc229 100644 --- a/swap/src/cli/tracing.rs +++ b/swap/src/cli/tracing.rs @@ -20,27 +20,22 @@ pub fn init(debug: bool, json: bool, dir: impl AsRef, swap_id: Option "stagenet", Network::Testnet => "testnet", }; - s.serialize_str(&str) + s.serialize_str(str) } } diff --git a/swap/src/kraken.rs b/swap/src/kraken.rs index 4a47bf9c..9e43ac2c 100644 --- a/swap/src/kraken.rs +++ b/swap/src/kraken.rs @@ -45,7 +45,7 @@ pub fn connect(price_ticker_ws_url: Url) -> Result { } } - Err(backoff::Error::Transient(anyhow!("stream ended"))) + Err(backoff::Error::transient(anyhow!("stream ended"))) } }, |error, next: Duration| { @@ -108,8 +108,8 @@ fn to_backoff(e: connection::Error) -> backoff::Error { match e { // Connection closures and websocket errors will be retried - connection::Error::ConnectionClosed => Transient(anyhow::Error::from(e)), - connection::Error::WebSocket(_) => Transient(anyhow::Error::from(e)), + connection::Error::ConnectionClosed => backoff::Error::transient(anyhow::Error::from(e)), + connection::Error::WebSocket(_) => backoff::Error::transient(anyhow::Error::from(e)), // Failures while parsing a message are permanent because they most likely present a // programmer error @@ -275,8 +275,6 @@ mod wire { pub struct TickerData { #[serde(rename = "a")] ask: Vec, - #[serde(rename = "b")] - bid: Vec, } #[derive(Debug, Deserialize)] diff --git a/swap/src/monero.rs b/swap/src/monero.rs index 86c97eba..bf3045ce 100644 --- a/swap/src/monero.rs +++ b/swap/src/monero.rs @@ -99,6 +99,20 @@ impl Amount { self.0 } + pub fn max_bitcoin_for_price(&self, ask_price: bitcoin::Amount) -> bitcoin::Amount { + let piconero_minus_fee = self.as_piconero().saturating_sub(MONERO_FEE.as_piconero()); + + if piconero_minus_fee == 0 { + return bitcoin::Amount::ZERO; + } + + // There needs to be an offset for difference in zeroes beetween Piconeros and + // Satoshis + let piconero_calc = (piconero_minus_fee * ask_price.as_sat()) / PICONERO_OFFSET; + + bitcoin::Amount::from_sat(piconero_calc) + } + pub fn from_monero(amount: f64) -> Result { let decimal = Decimal::try_from(amount)?; Self::from_decimal(decimal) @@ -360,6 +374,30 @@ mod tests { ); } + #[test] + fn geting_max_bitcoin_to_trade() { + let amount = Amount::parse_monero("10").unwrap(); + let bitcoin_price_sats = bitcoin::Amount::from_sat(382_900); + + let monero_max_from_bitcoin = amount.max_bitcoin_for_price(bitcoin_price_sats); + + assert_eq!( + bitcoin::Amount::from_sat(3_828_988), + monero_max_from_bitcoin + ); + } + + #[test] + fn geting_max_bitcoin_to_trade_with_balance_smaller_than_locking_fee() { + let monero = "0.00001"; + let amount = Amount::parse_monero(monero).unwrap(); + let bitcoin_price_sats = bitcoin::Amount::from_sat(382_900); + + let monero_max_from_bitcoin = amount.max_bitcoin_for_price(bitcoin_price_sats); + + assert_eq!(bitcoin::Amount::ZERO, monero_max_from_bitcoin); + } + use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; diff --git a/swap/src/network/quote.rs b/swap/src/network/quote.rs index 67640d65..caf99e09 100644 --- a/swap/src/network/quote.rs +++ b/swap/src/network/quote.rs @@ -37,6 +37,10 @@ pub struct BidQuote { pub max_quantity: bitcoin::Amount, } +#[derive(Clone, Copy, Debug, thiserror::Error)] +#[error("Received quote of 0")] +pub struct ZeroQuoteReceived; + /// Constructs a new instance of the `quote` behaviour to be used by the ASB. /// /// The ASB is always listening and only supports inbound connections, i.e. diff --git a/swap/src/proptest.rs b/swap/src/proptest.rs index 41b28785..0a7ab460 100644 --- a/swap/src/proptest.rs +++ b/swap/src/proptest.rs @@ -6,7 +6,7 @@ pub mod ecdsa_fun { use ::ecdsa_fun::fun::{Point, Scalar, G}; pub fn point() -> impl Strategy { - scalar().prop_map(|mut scalar| Point::from_scalar_mul(&G, &mut scalar).mark::()) + scalar().prop_map(|mut scalar| Point::from_scalar_mul(G, &mut scalar).mark::()) } pub fn scalar() -> impl Strategy { diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index baedbdba..90e5f9f8 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -659,8 +659,7 @@ impl State6 { pub async fn publish_refund_btc(&self, bitcoin_wallet: &bitcoin::Wallet) -> Result<()> { let signed_tx_refund = self.signed_refund_transaction()?; - let (_, subscription) = bitcoin_wallet.broadcast(signed_tx_refund, "refund").await?; - subscription.wait_until_final().await?; + bitcoin_wallet.broadcast(signed_tx_refund, "refund").await?; Ok(()) } diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index f8367ca9..c82bf10e 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -278,9 +278,12 @@ async fn next_state( state.publish_refund_btc(bitcoin_wallet).await?; BobState::BtcRefunded(state) } - ExpiredTimelocks::Punish => BobState::BtcPunished { - tx_lock_id: state.tx_lock_id(), - }, + ExpiredTimelocks::Punish => { + tracing::info!("You have been punished for not refunding in time"); + BobState::BtcPunished { + tx_lock_id: state.tx_lock_id(), + } + } } } BobState::BtcRefunded(state4) => BobState::BtcRefunded(state4), diff --git a/swap/tests/harness/bitcoind.rs b/swap/tests/harness/bitcoind.rs index 9f1fcd03..13aa5658 100644 --- a/swap/tests/harness/bitcoind.rs +++ b/swap/tests/harness/bitcoind.rs @@ -29,7 +29,7 @@ impl Image for Bitcoind { container .logs() .stdout - .wait_for_message(&"init message: Done loading") + .wait_for_message("init message: Done loading") .unwrap(); } diff --git a/swap/tests/harness/electrs.rs b/swap/tests/harness/electrs.rs index 46eff15a..538fbf27 100644 --- a/swap/tests/harness/electrs.rs +++ b/swap/tests/harness/electrs.rs @@ -14,7 +14,6 @@ pub struct Electrs { entrypoint: Option, wait_for_message: String, volume: String, - bitcoind_container_name: String, } impl Image for Electrs { @@ -73,7 +72,6 @@ impl Default for Electrs { entrypoint: Some("/build/electrs".into()), wait_for_message: "Running accept thread".to_string(), volume: uuid::Uuid::new_v4().to_string(), - bitcoind_container_name: uuid::Uuid::new_v4().to_string(), } } } diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index e50cfe2f..b23201e0 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -146,14 +146,14 @@ async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) { let prefix = random_prefix(); let bitcoind_name = format!("{}_{}", prefix, "bitcoind"); let (bitcoind, bitcoind_url) = - init_bitcoind_container(&cli, prefix.clone(), bitcoind_name.clone(), prefix.clone()) + init_bitcoind_container(cli, prefix.clone(), bitcoind_name.clone(), prefix.clone()) .await .expect("could not init bitcoind"); - let electrs = init_electrs_container(&cli, prefix.clone(), bitcoind_name, prefix) + let electrs = init_electrs_container(cli, prefix.clone(), bitcoind_name, prefix) .await .expect("could not init electrs"); let (monero, monerod_container, monero_wallet_rpc_containers) = - Monero::new(&cli, vec![MONERO_WALLET_NAME_ALICE, MONERO_WALLET_NAME_BOB]) + Monero::new(cli, vec![MONERO_WALLET_NAME_ALICE, MONERO_WALLET_NAME_BOB]) .await .unwrap(); @@ -237,7 +237,7 @@ async fn start_alice( let resume_only = false; let mut swarm = swarm::asb( - &seed, + seed, min_buy, max_buy, latest_rate, @@ -485,7 +485,7 @@ impl BobParams { .behaviour_mut() .add_address(self.alice_peer_id, self.alice_address.clone()); - cli::EventLoop::new(swap_id, swarm, self.alice_peer_id, self.env_config) + cli::EventLoop::new(swap_id, swarm, self.alice_peer_id) } } From 4b09ffd4dfd2f73746588666cec4a4f516815f94 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 8 Aug 2022 13:24:02 +0200 Subject: [PATCH 5/5] refactor: check for latest release DRYs up the code for checking latest release from github. --- swap/src/bin/asb.rs | 5 +++ swap/src/bin/swap.rs | 103 +++---------------------------------------- swap/src/common.rs | 57 ++++++++++++++++++++++++ swap/src/lib.rs | 1 + 4 files changed, 69 insertions(+), 97 deletions(-) create mode 100644 swap/src/common.rs diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index a0e9b5e3..fd2da1f9 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -29,6 +29,7 @@ use swap::asb::config::{ initial_setup, query_user_for_initial_config, read_config, Config, ConfigNotInitialized, }; use swap::asb::{cancel, punish, redeem, refund, safely_abort, EventLoop, Finality, KrakenRate}; +use swap::common::check_latest_version; use swap::database::open_db; use swap::monero::Amount; use swap::network::rendezvous::XmrBtcNamespace; @@ -68,6 +69,10 @@ async fn main() -> Result<()> { } }; + if let Err(e) = check_latest_version(env!("CARGO_PKG_VERSION")).await { + eprintln!("{}", e); + } + asb::tracing::init(LevelFilter::DEBUG, json, !disable_timestamp).expect("initialize tracing"); let config = match read_config(config_path.clone())? { diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 580b7d23..be5a92cc 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -26,6 +26,7 @@ use std::time::Duration; use swap::bitcoin::TxLock; use swap::cli::command::{parse_args_and_apply_defaults, Arguments, Command, ParseResult}; use swap::cli::{list_sellers, EventLoop, SellerStatus}; +use swap::common::check_latest_version; use swap::database::open_db; use swap::env::Config; use swap::libp2p_ext::MultiAddrExt; @@ -54,6 +55,10 @@ async fn main() -> Result<()> { } }; + if let Err(e) = check_latest_version(env!("CARGO_PKG_VERSION")).await { + eprintln!("{}", e); + } + match cmd { Command::BuyXmr { seller, @@ -69,11 +74,6 @@ async fn main() -> Result<()> { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -164,11 +164,6 @@ async fn main() -> Result<()> { Command::History => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let db = open_db(data_dir.join("sqlite")).await?; let swaps = db.all().await?; @@ -193,11 +188,6 @@ async fn main() -> Result<()> { Command::Config => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - tracing::info!(path=%data_dir.display(), "Data directory"); tracing::info!(path=%format!("{}/logs", data_dir.display()), "Log files directory"); tracing::info!(path=%format!("{}/sqlite", data_dir.display()), "Sqlite file location"); @@ -213,11 +203,6 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -252,11 +237,6 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -284,11 +264,6 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -356,11 +331,6 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -384,11 +354,6 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let db = open_db(data_dir.join("sqlite")).await?; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -414,10 +379,6 @@ async fn main() -> Result<()> { .context("Rendezvous node address must contain peer ID")?; cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; @@ -499,11 +460,6 @@ async fn main() -> Result<()> { } => { cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read in seed file")?; let bitcoin_wallet = init_bitcoin_wallet( @@ -520,11 +476,6 @@ async fn main() -> Result<()> { Command::MoneroRecovery { swap_id } => { cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - match check_latest_version().await { - Ok(()) => (), - Err(error) => tracing::error!("{}", error), - }; - let db = open_db(data_dir.join("sqlite")).await?; let swap_state: BobState = db.get_state(swap_id).await?.try_into()?; @@ -717,43 +668,10 @@ where Ok((btc_swap_amount, fees)) } -pub async fn check_latest_version() -> Result<()> { - const GITHUB_LATEST_VERSION_URL: &str = - "https://github.com/comit-network/xmr-btc-swap/releases/latest"; - - let response = match reqwest::get(GITHUB_LATEST_VERSION_URL).await { - Ok(res) => res, - Err(_) => bail!( - "could not request the website {}", - GITHUB_LATEST_VERSION_URL - ), - }; - - let last_version_from_url: &str = match response.url().path_segments() { - Some(split_segments) => match split_segments.last() { - Some(seg) => seg, - None => bail!("could not check the latest version"), - }, - None => bail!("could not check the latest version"), - }; - - let version_from_binary: &str = env!("CARGO_PKG_VERSION"); - - if last_version_from_url != version_from_binary { - tracing::warn!( - "You are not on the lastest version {}, it's available on Github: {}", - last_version_from_url, - GITHUB_LATEST_VERSION_URL - ); - }; - - Ok(()) -} - #[cfg(test)] mod tests { use super::*; - use crate::{check_latest_version, determine_btc_to_swap}; + use crate::determine_btc_to_swap; use ::bitcoin::Amount; use std::sync::Mutex; use swap::tracing_ext::capture_logs; @@ -1130,13 +1048,4 @@ mod tests { async fn get_dummy_address() -> Result { Ok("1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6".parse()?) } - - #[tokio::test] - async fn check_correct_latest_version() { - let writer = capture_logs(LevelFilter::INFO); - - check_latest_version().await.unwrap(); - - assert_eq!(writer.captured(), r""); - } } diff --git a/swap/src/common.rs b/swap/src/common.rs new file mode 100644 index 00000000..66adca83 --- /dev/null +++ b/swap/src/common.rs @@ -0,0 +1,57 @@ +use anyhow::anyhow; + +const LATEST_RELEASE_URL: &str = "https://github.com/comit-network/xmr-btc-swap/releases/latest"; + +#[derive(Clone, Debug, PartialEq)] +pub enum Version { + Current, + Available, +} + +/// Check the latest release from GitHub API. +pub async fn check_latest_version(current: &str) -> anyhow::Result { + let response = reqwest::get(LATEST_RELEASE_URL).await?; + let e = "Failed to get latest release."; + let url = response.url(); + let segments = url.path_segments().ok_or_else(|| anyhow!(e))?; + let latest = segments.last().ok_or_else(|| anyhow!(e))?; + + let result = if is_latest_version(current, latest) { + Version::Current + } else { + println!( + "You are not on the latest version: {} is available. \n{}", + latest, url + ); + Version::Available + }; + + Ok(result) +} + +// todo: naive implementation can be improved using semver +fn is_latest_version(current: &str, latest: &str) -> bool { + current == latest +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn it_compares_versions() { + assert!(is_latest_version("0.10.2", "0.10.2")); + assert!(!is_latest_version("0.10.2", "0.10.3")); + assert!(!is_latest_version("0.10.2", "0.11.0")); + } + + #[tokio::test] + #[ignore = "For local testing, makes http requests to github."] + async fn it_compares_with_github() { + let result = check_latest_version("0.10.1").await.unwrap(); + assert_eq!(result, Version::Available); + + let result = check_latest_version("0.10.2").await.unwrap(); + assert_eq!(result, Version::Current); + } +} diff --git a/swap/src/lib.rs b/swap/src/lib.rs index 1b050ae2..4865187b 100644 --- a/swap/src/lib.rs +++ b/swap/src/lib.rs @@ -19,6 +19,7 @@ pub mod asb; pub mod bitcoin; pub mod cli; +pub mod common; pub mod database; pub mod env; pub mod fs;