From 9346cb7baf17f56eb8dd8ace5edd98d0c9583159 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 10 Jan 2023 13:38:19 +0200 Subject: [PATCH 001/395] fix: add debug log for opening monero wallet error --- swap/src/monero/wallet.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index a8fccc5d..3f548c41 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -26,15 +26,16 @@ impl Wallet { pub async fn open_or_create(url: Url, name: String, env_config: Config) -> Result { let client = wallet::Client::new(url)?; - let open_wallet_response = client.open_wallet(name.clone()).await; - if open_wallet_response.is_err() { - client.create_wallet(name.clone(), "English".to_owned()).await.context( - "Unable to create Monero wallet, please ensure that the monero-wallet-rpc is available", - )?; + match client.open_wallet(name.clone()).await { + Err(error) => { + tracing::debug!(%error, "Open wallet response error"); + client.create_wallet(name.clone(), "English".to_owned()).await.context( + "Unable to create Monero wallet, please ensure that the monero-wallet-rpc is available", + )?; - tracing::debug!(monero_wallet_name = %name, "Created Monero wallet"); - } else { - tracing::debug!(monero_wallet_name = %name, "Opened Monero wallet"); + tracing::debug!(monero_wallet_name = %name, "Created Monero wallet"); + } + Ok(_) => tracing::debug!(monero_wallet_name = %name, "Opened Monero wallet"), } Self::connect(client, name, env_config).await From 4ca1f8da5ef7e6964bfd02fd8859bba56084afff Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 10 Jan 2023 14:43:07 +0200 Subject: [PATCH 002/395] ci: update msrv and github actions toolchains --- .github/workflows/build-release-binaries.yml | 3 ++- .github/workflows/ci.yml | 3 ++- CHANGELOG.md | 6 +++++- README.md | 2 +- monero-rpc/src/monerod.rs | 6 +++--- monero-rpc/src/wallet.rs | 2 +- rust-toolchain.toml | 2 +- swap/src/asb/command.rs | 6 +++--- swap/src/asb/config.rs | 14 +++++++------- swap/src/asb/rate.rs | 2 +- swap/src/bitcoin.rs | 2 +- swap/src/bitcoin/lock.rs | 2 +- swap/src/bitcoin/timelocks.rs | 2 +- swap/src/bitcoin/wallet.rs | 4 ++-- swap/src/cli/command.rs | 10 +++++----- swap/src/common.rs | 2 +- swap/src/database/alice.rs | 2 +- swap/src/env.rs | 2 +- swap/src/kraken.rs | 2 +- swap/src/monero.rs | 14 +++++++------- swap/src/network/rendezvous.rs | 2 +- swap/src/network/swap_setup.rs | 2 +- swap/src/network/swap_setup/bob.rs | 2 +- swap/src/protocol.rs | 4 ++-- swap/src/protocol/bob/state.rs | 2 +- 25 files changed, 53 insertions(+), 47 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index e95c7e32..9c856a53 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -52,8 +52,9 @@ jobs: - uses: Swatinem/rust-cache@v2.2.0 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@master with: + toolchain: 1.63 targets: armv7-unknown-linux-gnueabihf - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 695da64a..0fa9eae1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,8 +75,9 @@ jobs: - uses: Swatinem/rust-cache@v2.2.0 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@master with: + toolchain: 1.63 targets: armv7-unknown-linux-gnueabihf - name: Build binary diff --git a/CHANGELOG.md b/CHANGELOG.md index 9af3e634..51a1b67a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- Minimum Supported Rust Version (MSRV) bumped to 1.63 + ## [0.12.1] - 2023-01-09 ### Changed @@ -338,7 +342,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.12.1...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.1...HEAD [0.12.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.2...0.11.0 diff --git a/README.md b/README.md index 9b4a0476..3e6c3765 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ 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.62 _should_ work. +All stable toolchains since 1.63 _should_ work. ## Contact diff --git a/monero-rpc/src/monerod.rs b/monero-rpc/src/monerod.rs index 32e79cec..830aafdb 100644 --- a/monero-rpc/src/monerod.rs +++ b/monero-rpc/src/monerod.rs @@ -157,7 +157,7 @@ pub struct OutKey { pub unlocked: bool, } -#[derive(Clone, Debug, Deserialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct BaseResponse { pub credits: u64, pub status: Status, @@ -165,7 +165,7 @@ pub struct BaseResponse { pub untrusted: bool, } -#[derive(Clone, Debug, Deserialize, PartialEq)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] pub struct GetOIndexesResponse { #[serde(flatten)] pub base: BaseResponse, @@ -173,7 +173,7 @@ pub struct GetOIndexesResponse { pub o_indexes: Vec, } -#[derive(Clone, Copy, Debug, Deserialize, PartialEq)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq)] pub enum Status { #[serde(rename = "OK")] Ok, diff --git a/monero-rpc/src/wallet.rs b/monero-rpc/src/wallet.rs index 404e9693..bc78e7a6 100644 --- a/monero-rpc/src/wallet.rs +++ b/monero-rpc/src/wallet.rs @@ -157,7 +157,7 @@ pub struct Transfer { pub unsigned_txset: String, } -#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)] +#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq, Eq)] pub struct BlockHeight { pub height: u32, } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 54776f48..8e45b7f1 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.62" +channel = "1.63" # also update this in the readme, changelog, and github actions components = ["clippy"] targets = ["armv7-unknown-linux-gnueabihf"] diff --git a/swap/src/asb/command.rs b/swap/src/asb/command.rs index 9355568e..6831e595 100644 --- a/swap/src/asb/command.rs +++ b/swap/src/asb/command.rs @@ -171,7 +171,7 @@ fn env_config(is_testnet: bool) -> env::Config { } } -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Serialize)] +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, Serialize)] #[error("Invalid Bitcoin address provided, expected address on network {expected:?} but address provided is on {actual:?}")] pub struct BitcoinAddressNetworkMismatch { #[serde(with = "crate::bitcoin::network")] @@ -180,7 +180,7 @@ pub struct BitcoinAddressNetworkMismatch { actual: bitcoin::Network, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct Arguments { pub testnet: bool, pub json: bool, @@ -190,7 +190,7 @@ pub struct Arguments { pub cmd: Command, } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum Command { Start { resume_only: bool, diff --git a/swap/src/asb/config.rs b/swap/src/asb/config.rs index 0aef46bc..7e8492ec 100644 --- a/swap/src/asb/config.rs +++ b/swap/src/asb/config.rs @@ -84,7 +84,7 @@ const DEFAULT_MIN_BUY_AMOUNT: f64 = 0.002f64; const DEFAULT_MAX_BUY_AMOUNT: f64 = 0.02f64; const DEFAULT_SPREAD: f64 = 0.02f64; -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq)] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq)] #[serde(deny_unknown_fields)] pub struct Config { pub data: Data, @@ -123,13 +123,13 @@ impl TryFrom for Config { } } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct Data { pub dir: PathBuf, } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct Network { #[serde(deserialize_with = "addr_list::deserialize")] @@ -181,7 +181,7 @@ mod addr_list { } } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct Bitcoin { pub electrum_rpc_url: Url, @@ -191,7 +191,7 @@ pub struct Bitcoin { pub network: bitcoin::Network, } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct Monero { pub wallet_rpc_url: Url, @@ -200,14 +200,14 @@ pub struct Monero { pub network: monero::Network, } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct TorConf { pub control_port: u16, pub socks5_port: u16, } -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Eq, Serialize)] #[serde(deny_unknown_fields)] pub struct Maker { #[serde(with = "::bitcoin::util::amount::serde::as_btc")] diff --git a/swap/src/asb/rate.rs b/swap/src/asb/rate.rs index c394e91f..70208e0e 100644 --- a/swap/src/asb/rate.rs +++ b/swap/src/asb/rate.rs @@ -5,7 +5,7 @@ use rust_decimal::Decimal; use std::fmt::{Debug, Display, Formatter}; /// Represents the rate at which we are willing to trade 1 XMR. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Rate { /// Represents the asking price from the market. ask: bitcoin::Amount, diff --git a/swap/src/bitcoin.rs b/swap/src/bitcoin.rs index a375aaf9..925f48e6 100644 --- a/swap/src/bitcoin.rs +++ b/swap/src/bitcoin.rs @@ -108,7 +108,7 @@ impl SecretKey { } } -#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct PublicKey(Point); impl PublicKey { diff --git a/swap/src/bitcoin/lock.rs b/swap/src/bitcoin/lock.rs index 9e2b8795..42819ad5 100644 --- a/swap/src/bitcoin/lock.rs +++ b/swap/src/bitcoin/lock.rs @@ -13,7 +13,7 @@ use serde::{Deserialize, Serialize}; const SCRIPT_SIZE: usize = 34; const TX_LOCK_WEIGHT: usize = 485; -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct TxLock { inner: PartiallySignedTransaction, pub(in crate::bitcoin) output_descriptor: Descriptor<::bitcoin::PublicKey>, diff --git a/swap/src/bitcoin/timelocks.rs b/swap/src/bitcoin/timelocks.rs index 04f589a9..e8b72ea6 100644 --- a/swap/src/bitcoin/timelocks.rs +++ b/swap/src/bitcoin/timelocks.rs @@ -37,7 +37,7 @@ impl Add for BlockHeight { } } -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ExpiredTimelocks { None, Cancel, diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index 61bff14d..cf1530d1 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -876,7 +876,7 @@ impl EstimateFeeRate for Client { } } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ScriptStatus { Unseen, InMempool, @@ -893,7 +893,7 @@ impl ScriptStatus { } } -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct Confirmed { /// The depth of this transaction within the blockchain. /// diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 51bf7b39..e4da8e7d 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -28,7 +28,7 @@ const DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET: usize = 1; const DEFAULT_TOR_SOCKS5_PORT: &str = "9050"; -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct Arguments { pub env_config: env::Config, pub debug: bool, @@ -38,7 +38,7 @@ pub struct Arguments { } /// Represents the result of parsing the command-line parameters. -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum ParseResult { /// The arguments we were invoked in. Arguments(Box), @@ -246,7 +246,7 @@ where Ok(ParseResult::Arguments(Box::new(arguments))) } -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub enum Command { BuyXmr { seller: Multiaddr, @@ -610,14 +610,14 @@ fn parse_monero_address(s: &str) -> Result { }) } -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)] +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)] #[error("Invalid monero address provided, expected address on network {expected:?} but address provided is on {actual:?}")] pub struct MoneroAddressNetworkMismatch { expected: monero::Network, actual: monero::Network, } -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Serialize)] +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, Serialize)] #[error("Invalid Bitcoin address provided, expected address on network {expected:?} but address provided is on {actual:?}")] pub struct BitcoinAddressNetworkMismatch { #[serde(with = "crate::bitcoin::network")] diff --git a/swap/src/common.rs b/swap/src/common.rs index 959d0a3b..98b9b99d 100644 --- a/swap/src/common.rs +++ b/swap/src/common.rs @@ -2,7 +2,7 @@ use anyhow::anyhow; const LATEST_RELEASE_URL: &str = "https://github.com/comit-network/xmr-btc-swap/releases/latest"; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Eq)] pub enum Version { Current, Available, diff --git a/swap/src/database/alice.rs b/swap/src/database/alice.rs index 1262d04a..4ed61790 100644 --- a/swap/src/database/alice.rs +++ b/swap/src/database/alice.rs @@ -70,7 +70,7 @@ pub enum Alice { Done(AliceEndState), } -#[derive(Copy, Clone, strum::Display, Debug, Deserialize, Serialize, PartialEq)] +#[derive(Copy, Clone, strum::Display, Debug, Deserialize, Serialize, PartialEq, Eq)] pub enum AliceEndState { SafelyAborted, BtcRedeemed, diff --git a/swap/src/env.rs b/swap/src/env.rs index 73c6d665..a80d402d 100644 --- a/swap/src/env.rs +++ b/swap/src/env.rs @@ -5,7 +5,7 @@ use std::cmp::max; use std::time::Duration; use time::ext::NumericalStdDuration; -#[derive(Debug, Copy, Clone, PartialEq, Serialize)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize)] pub struct Config { pub bitcoin_lock_mempool_timeout: Duration, pub bitcoin_lock_confirmed_timeout: Duration, diff --git a/swap/src/kraken.rs b/swap/src/kraken.rs index 9e43ac2c..29062114 100644 --- a/swap/src/kraken.rs +++ b/swap/src/kraken.rs @@ -230,7 +230,7 @@ mod wire { use bitcoin::util::amount::ParseAmountError; use serde_json::Value; - #[derive(Debug, Deserialize, PartialEq)] + #[derive(Debug, Deserialize, PartialEq, Eq)] #[serde(tag = "event")] pub enum Event { #[serde(rename = "systemStatus")] diff --git a/swap/src/monero.rs b/swap/src/monero.rs index e5163f77..d46fc157 100644 --- a/swap/src/monero.rs +++ b/swap/src/monero.rs @@ -39,7 +39,7 @@ pub fn private_key_from_secp256k1_scalar(scalar: bitcoin::Scalar) -> PrivateKey PrivateKey::from_scalar(Scalar::from_bytes_mod_order(bytes)) } -#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct PrivateViewKey(#[serde(with = "monero_private_key")] PrivateKey); impl PrivateViewKey { @@ -78,7 +78,7 @@ impl From for PublicKey { #[derive(Clone, Copy, Debug)] pub struct PublicViewKey(PublicKey); -#[derive(Debug, Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd)] +#[derive(Debug, Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd)] pub struct Amount(u64); // Median tx fees on Monero as found here: https://www.monero.how/monero-transaction-fees, XMR 0.000_008 * 2 (to be on the safe side) @@ -185,7 +185,7 @@ impl fmt::Display for Amount { } } -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct TransferProof { tx_hash: TxHash, #[serde(with = "monero_private_key")] @@ -205,7 +205,7 @@ impl TransferProof { } // TODO: add constructor/ change String to fixed length byte array -#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct TxHash(pub String); impl From for String { @@ -227,7 +227,7 @@ pub struct InsufficientFunds { pub actual: Amount, } -#[derive(thiserror::Error, Debug, Clone, PartialEq)] +#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] #[error("Overflow, cannot convert {0} to u64")] pub struct OverflowError(pub String); @@ -470,10 +470,10 @@ mod tests { use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; - #[derive(Debug, Serialize, Deserialize, PartialEq)] + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct MoneroPrivateKey(#[serde(with = "monero_private_key")] crate::monero::PrivateKey); - #[derive(Debug, Serialize, Deserialize, PartialEq)] + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct MoneroAmount(#[serde(with = "monero_amount")] crate::monero::Amount); #[test] diff --git a/swap/src/network/rendezvous.rs b/swap/src/network/rendezvous.rs index 86a698a2..bbc0276b 100644 --- a/swap/src/network/rendezvous.rs +++ b/swap/src/network/rendezvous.rs @@ -1,7 +1,7 @@ use libp2p::rendezvous::Namespace; use std::fmt; -#[derive(Debug, PartialEq, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum XmrBtcNamespace { Mainnet, Testnet, diff --git a/swap/src/network/swap_setup.rs b/swap/src/network/swap_setup.rs index 4b9cf3c2..eb48a2f2 100644 --- a/swap/src/network/swap_setup.rs +++ b/swap/src/network/swap_setup.rs @@ -37,7 +37,7 @@ pub mod protocol { >; } -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] pub struct BlockchainNetwork { #[serde(with = "crate::bitcoin::network")] pub bitcoin: bitcoin::Network, diff --git a/swap/src/network/swap_setup/bob.rs b/swap/src/network/swap_setup/bob.rs index ae0b921f..18972319 100644 --- a/swap/src/network/swap_setup/bob.rs +++ b/swap/src/network/swap_setup/bob.rs @@ -258,7 +258,7 @@ impl From for Result { } } -#[derive(Clone, Debug, thiserror::Error, PartialEq)] +#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)] pub enum Error { #[error("Seller currently does not accept incoming swap requests, please try again later")] NoSwapsAccepted, diff --git a/swap/src/protocol.rs b/swap/src/protocol.rs index 5bf1f5b4..9389e3ae 100644 --- a/swap/src/protocol.rs +++ b/swap/src/protocol.rs @@ -101,11 +101,11 @@ impl From for State { } } -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)] +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)] #[error("Not in the role of Alice")] pub struct NotAlice; -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)] +#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)] #[error("Not in the role of Bob")] pub struct NotBob; diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index 36ad3228..4d0e5a31 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -560,7 +560,7 @@ impl State4 { } } -#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] +#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)] pub struct State5 { #[serde(with = "monero_private_key")] s_a: monero::PrivateKey, From 43f06f0705b529e0b43b1d0650f417f21a359438 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 9 Jan 2023 15:54:23 +0200 Subject: [PATCH 003/395] build(deps): bump base64 to 0.21 closes #1271 --- Cargo.lock | 6 +++--- swap/Cargo.toml | 2 +- swap/src/seed.rs | 5 ++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 57bdbe74..c2349626 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,9 +220,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bdk" @@ -4022,7 +4022,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.20.0", + "base64 0.21.0", "bdk", "big-bytes", "bitcoin", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 3f40ce71..747a195a 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -14,7 +14,7 @@ async-compression = { version = "0.3", features = [ "bzip2", "tokio" ] } async-trait = "0.1" atty = "0.2" backoff = { version = "0.4", features = [ "tokio" ] } -base64 = "0.20" +base64 = "0.21" bdk = "0.25" big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } diff --git a/swap/src/seed.rs b/swap/src/seed.rs index 9e34c2db..2230ccef 100644 --- a/swap/src/seed.rs +++ b/swap/src/seed.rs @@ -187,6 +187,9 @@ mod tests { #[test] fn seed_from_pem_works() { + use base64::engine::general_purpose; + use base64::Engine; + let payload: &str = "syl9wSYaruvgxg9P5Q1qkZaq5YkM6GvXkxe+VYrL/XM="; // 32 bytes base64 encoded. @@ -195,7 +198,7 @@ syl9wSYaruvgxg9P5Q1qkZaq5YkM6GvXkxe+VYrL/XM= -----END SEED----- "; - let want = base64::decode(payload).unwrap(); + let want = general_purpose::STANDARD.decode(payload).unwrap(); let pem = pem::parse(pem_string).unwrap(); let got = Seed::from_pem(pem).unwrap(); From 30fbb0cdb2d3b257bd76fbc7e5401c7bb69c2190 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 9 Jan 2023 19:10:02 +0200 Subject: [PATCH 004/395] build(deps): bump vergen to 7.5 closes #1266 --- Cargo.lock | 8 ++++---- swap/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c2349626..900dd586 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1124,9 +1124,9 @@ dependencies = [ [[package]] name = "enum-iterator" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401" +checksum = "91a4ec26efacf4aeff80887a175a419493cb6f8b5480d26387eb0bd038976187" dependencies = [ "enum-iterator-derive", ] @@ -4772,9 +4772,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "7.4.4" +version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efadd36bc6fde40c6048443897d69511a19161c0756cb704ed403f8dfd2b7d1c" +checksum = "571b69f690c855821462709b6f41d42ceccc316fbd17b60bd06d06928cfe6a99" dependencies = [ "anyhow", "cfg-if 1.0.0", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 747a195a..eba197df 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -88,4 +88,4 @@ testcontainers = "0.12" [build-dependencies] anyhow = "1" -vergen = { version = "7", default-features = false, features = [ "git", "build" ] } +vergen = { version = "7.5", default-features = false, features = [ "git", "build" ] } From 7aa6227cbeb78e5eca3bad1bac828564c8bb9544 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 11 Jan 2023 19:41:18 +0200 Subject: [PATCH 005/395] build(deps): bump bdk to 0.26 closes #1264 --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 900dd586..ac71787f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,9 +226,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bdk" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1e7eb54c6288eca1b698e6e33dd82ebe6c08a93ec1a96bb6926ddceed22c703" +checksum = "b238a07736baee43ba9663933e44b1c6c27b43ef871b9486e175902335d83880" dependencies = [ "async-trait", "bdk-macros", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index eba197df..a1832fce 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1" atty = "0.2" backoff = { version = "0.4", features = [ "tokio" ] } base64 = "0.21" -bdk = "0.25" +bdk = "0.26" big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bmrng = "0.5" From ce2253128711515f2838e98b2e542226e85df225 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Jan 2023 08:36:46 +0000 Subject: [PATCH 006/395] build(deps): bump pem from 1.1.0 to 1.1.1 Bumps [pem](https://github.com/jcreekmore/pem-rs) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/jcreekmore/pem-rs/releases) - [Changelog](https://github.com/jcreekmore/pem-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/jcreekmore/pem-rs/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: pem dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac71787f..c6472a03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2641,9 +2641,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pem" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" dependencies = [ "base64 0.13.1", ] From c5151e1ad4d4e94f5820a428b825ccc9252a9b2c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Jan 2023 11:04:38 +0000 Subject: [PATCH 007/395] build(deps): bump dialoguer from 0.10.2 to 0.10.3 Bumps [dialoguer](https://github.com/mitsuhiko/dialoguer) from 0.10.2 to 0.10.3. - [Release notes](https://github.com/mitsuhiko/dialoguer/releases) - [Changelog](https://github.com/console-rs/dialoguer/blob/master/CHANGELOG.md) - [Commits](https://github.com/mitsuhiko/dialoguer/compare/v0.10.2...0.10.3) --- updated-dependencies: - dependency-name: dialoguer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c6472a03..d0466c4b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -972,11 +972,12 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92e7e37ecef6857fdc0c0c5d42fd5b0938e46590c2183cc92dd310a6d078eb1" +checksum = "af3c796f3b0b408d9fd581611b47fa850821fcb84aa640b83a3c1a5be2d691f2" dependencies = [ "console", + "shell-words", "tempfile", "zeroize", ] @@ -3664,6 +3665,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" + [[package]] name = "sigma_fun" version = "0.4.1" From 633027dd66a526acd22a5a0dd7a9e8543d538b93 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 11:02:15 +0000 Subject: [PATCH 008/395] build(deps): bump serial_test from 0.10.0 to 1.0.0 Bumps [serial_test](https://github.com/palfrey/serial_test) from 0.10.0 to 1.0.0. - [Release notes](https://github.com/palfrey/serial_test/releases) - [Commits](https://github.com/palfrey/serial_test/compare/v0.10.0...v1.0.0) --- updated-dependencies: - dependency-name: serial_test dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- swap/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0466c4b..44f952e6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3584,9 +3584,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "0.10.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c789ec87f4687d022a2405cf46e0cd6284889f1839de292cadeb6c6019506f2" +checksum = "538c30747ae860d6fb88330addbbd3e0ddbe46d662d032855596d8a8ca260611" dependencies = [ "dashmap", "futures", @@ -3598,9 +3598,9 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "0.10.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64f9e531ce97c88b4778aad0ceee079216071cffec6ac9b904277f8f92e7fe3" +checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index a1832fce..bda21d25 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -81,7 +81,7 @@ monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" serde_cbor = "0.11" -serial_test = "0.10" +serial_test = "1.0" spectral = "0.6" tempfile = "3" testcontainers = "0.12" From 27a8e2aee6bb0abc0e3a2e88468d0799e480891b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 11:02:35 +0000 Subject: [PATCH 009/395] build(deps): bump async-trait from 0.1.61 to 0.1.62 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.61 to 0.1.62. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.61...0.1.62) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0466c4b..e2d0be08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.61" +version = "0.1.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +checksum = "689894c2db1ea643a50834b999abf1c110887402542955ff5451dab8f861f9ed" dependencies = [ "proc-macro2", "quote", From 533807aa0b86caab374e4a1b26d107e745657364 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 11:03:06 +0000 Subject: [PATCH 010/395] build(deps): bump reqwest from 0.11.13 to 0.11.14 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.13 to 0.11.14. - [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.13...v0.11.14) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0466c4b..6bc3a4d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3162,11 +3162,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" +checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" dependencies = [ - "base64 0.13.1", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -3196,6 +3196,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "webpki-roots 0.22.2", "winreg 0.10.1", @@ -4844,9 +4845,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -4854,13 +4855,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -4881,9 +4882,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4891,9 +4892,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -4904,9 +4905,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.71" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" + +[[package]] +name = "wasm-streams" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] [[package]] name = "web-sys" From 1b52804abcd71c9ff990a95c040d97ad9434daba Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 20 Jan 2023 11:03:20 +0000 Subject: [PATCH 011/395] build(deps): bump toml from 0.5.10 to 0.5.11 Bumps [toml](https://github.com/toml-rs/toml) from 0.5.10 to 0.5.11. - [Release notes](https://github.com/toml-rs/toml/releases) - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.5.10...toml-v0.5.11) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0466c4b..ca4e0ccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4411,9 +4411,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] From 53abde3f8885e7f013aacabf2bfa56d322b670c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 09:09:24 +0000 Subject: [PATCH 012/395] build(deps): bump rust_decimal_macros from 1.27.0 to 1.28.0 Bumps [rust_decimal_macros](https://github.com/paupino/rust-decimal) from 1.27.0 to 1.28.0. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.27.0...1.28.0) --- updated-dependencies: - dependency-name: rust_decimal_macros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 028c257b..f270d0b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3254,9 +3254,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.27.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" +checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" dependencies = [ "arrayvec", "borsh", @@ -3272,9 +3272,9 @@ dependencies = [ [[package]] name = "rust_decimal_macros" -version = "1.27.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7e2dba1342e9f1166786a4329ba0d6d6b8d9db7e81d702ec9ba3b39591ddff" +checksum = "d71a78314ee3b7e684f34f1574fe0935cac8eb453217974473be82f032d9b4ee" dependencies = [ "quote", "rust_decimal", From 921bac0af8b242b756af9e55dc348312d479f803 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 09:09:40 +0000 Subject: [PATCH 013/395] build(deps): bump rust_decimal from 1.27.0 to 1.28.0 Bumps [rust_decimal](https://github.com/paupino/rust-decimal) from 1.27.0 to 1.28.0. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.27.0...1.28.0) --- updated-dependencies: - dependency-name: rust_decimal dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 028c257b..87ab8603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3254,9 +3254,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.27.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" +checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" dependencies = [ "arrayvec", "borsh", From 4d44fab0dd15cea7393f5b4f58154e490741f116 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Jan 2023 09:09:57 +0000 Subject: [PATCH 014/395] build(deps): bump async-trait from 0.1.62 to 0.1.63 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.62 to 0.1.63. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.62...0.1.63) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 028c257b..c9f8f7bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.62" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "689894c2db1ea643a50834b999abf1c110887402542955ff5451dab8f861f9ed" +checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1" dependencies = [ "proc-macro2", "quote", From ada5df740f28df8b08f0f030a5d4f445a8fbba41 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Jan 2023 11:01:45 +0000 Subject: [PATCH 015/395] build(deps): bump dprint/check from 2.1 to 2.2 Bumps [dprint/check](https://github.com/dprint/check) from 2.1 to 2.2. - [Release notes](https://github.com/dprint/check/releases) - [Commits](https://github.com/dprint/check/compare/v2.1...v2.2) --- updated-dependencies: - dependency-name: dprint/check dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0fa9eae1..04461afd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: - uses: Swatinem/rust-cache@v2.2.0 - name: Check formatting - uses: dprint/check@v2.1 + uses: dprint/check@v2.2 - name: Run clippy with default features run: cargo clippy --workspace --all-targets -- -D warnings From 0f31a612e4b3e4fc8f594609df2dcaca75f3846f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 11:02:21 +0000 Subject: [PATCH 016/395] build(deps): bump async-trait from 0.1.63 to 0.1.64 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.63 to 0.1.64. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.63...0.1.64) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 450767e0..a4479e6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", From a42380830d484c336ddd1cc2b640cb6f9c1fded8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Jan 2023 11:02:38 +0000 Subject: [PATCH 017/395] build(deps): bump futures from 0.3.25 to 0.3.26 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.25 to 0.3.26. - [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.25...0.3.26) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 450767e0..8b4e5a5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1246,9 +1246,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" +checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" dependencies = [ "futures-channel", "futures-core", @@ -1261,9 +1261,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1271,15 +1271,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-executor" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" +checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" dependencies = [ "futures-core", "futures-task", @@ -1300,15 +1300,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb" +checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1328,15 +1328,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-timer" @@ -1346,9 +1346,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-channel", "futures-core", From a02d84e2b47377e63cc316150359f781244578d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Feb 2023 11:04:59 +0000 Subject: [PATCH 018/395] build(deps): bump uuid from 1.2.2 to 1.3.0 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.2.2 to 1.3.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.2.2...1.3.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0c900fe..43b130ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4752,9 +4752,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.2.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" +checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" dependencies = [ "getrandom 0.2.6", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index bda21d25..127c23e8 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -64,7 +64,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.2", features = [ "serde", "v4" ] } +uuid = { version = "1.3", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From 63d6204bd7ff02851a1fd3784cbe5f61479fab88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Feb 2023 11:02:28 +0000 Subject: [PATCH 019/395] build(deps): bump hyper from 0.14.23 to 0.14.24 Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.23 to 0.14.24. - [Release notes](https://github.com/hyperium/hyper/releases) - [Changelog](https://github.com/hyperium/hyper/blob/v0.14.24/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper/compare/v0.14.23...v0.14.24) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43b130ff..66fb4107 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1611,9 +1611,9 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.23" +version = "0.14.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" +checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" dependencies = [ "bytes", "futures-channel", From 5477dd9f04fdd6b7ca83bf7307535a2575e2d7f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:05:58 +0000 Subject: [PATCH 020/395] build(deps): bump proptest from 1.0.0 to 1.1.0 Bumps [proptest](https://github.com/proptest-rs/proptest) from 1.0.0 to 1.1.0. - [Release notes](https://github.com/proptest-rs/proptest/releases) - [Changelog](https://github.com/proptest-rs/proptest/blob/master/CHANGELOG.md) - [Commits](https://github.com/proptest-rs/proptest/compare/1.0.0...v1.1.0) --- updated-dependencies: - dependency-name: proptest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66fb4107..618defaa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1837,6 +1837,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libp2p" version = "0.42.2" @@ -2513,11 +2519,12 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2836,9 +2843,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" +checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" dependencies = [ "bit-set", "bitflags", @@ -2852,6 +2859,7 @@ dependencies = [ "regex-syntax", "rusty-fork", "tempfile", + "unarray", ] [[package]] @@ -4656,6 +4664,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + [[package]] name = "unicode-bidi" version = "0.3.4" From 20d8c9225ab54f0bad824f0bd0ef3b924ae59bf1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:06:12 +0000 Subject: [PATCH 021/395] build(deps): bump serde_json from 1.0.91 to 1.0.92 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.91 to 1.0.92. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.91...v1.0.92) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66fb4107..c62977f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3540,9 +3540,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a" dependencies = [ "itoa 1.0.1", "ryu", From 9ffcf16917a6ce97f0d40bdeaa35b68794384893 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:06:55 +0000 Subject: [PATCH 022/395] build(deps): bump rust_decimal_macros from 1.28.0 to 1.28.1 Bumps [rust_decimal_macros](https://github.com/paupino/rust-decimal) from 1.28.0 to 1.28.1. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.28.0...1.28.1) --- updated-dependencies: - dependency-name: rust_decimal_macros dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66fb4107..524ceab9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3272,9 +3272,9 @@ dependencies = [ [[package]] name = "rust_decimal_macros" -version = "1.28.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71a78314ee3b7e684f34f1574fe0935cac8eb453217974473be82f032d9b4ee" +checksum = "f79c1532c5088b44236d74c7dd9d80a1c57a433e02694fced7b5a670dc562ce5" dependencies = [ "quote", "rust_decimal", From 76c5b3efa35dfe2e94a4cdeee81a7dad5dfa7bb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:07:09 +0000 Subject: [PATCH 023/395] build(deps): bump anyhow from 1.0.68 to 1.0.69 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.68 to 1.0.69. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.68...1.0.69) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66fb4107..4d027c34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" [[package]] name = "arrayref" From 912a5b482682c9a038f00b081df633045af54638 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:07:22 +0000 Subject: [PATCH 024/395] build(deps): bump rust_decimal from 1.28.0 to 1.28.1 Bumps [rust_decimal](https://github.com/paupino/rust-decimal) from 1.28.0 to 1.28.1. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.28.0...1.28.1) --- updated-dependencies: - dependency-name: rust_decimal dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 66fb4107..94644657 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,19 +418,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "822462c1e7b17b31961798a6874b36daea6818e99e0cb7d3b7b0fa3c477751c3" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown 0.12.3", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "37626c9e941a687ee9abef6065b44c379478ae563b7483c613dd705ef1dff59e" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -441,9 +441,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "61820b4c5693eafb998b1e67485423c923db4a75f72585c247bdee32bad81e7b" dependencies = [ "proc-macro2", "quote", @@ -452,9 +452,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "c76cdbfa13def20d1f8af3ae7b3c6771f06352a74221d8851262ac384c122b8e" dependencies = [ "proc-macro2", "quote", @@ -3254,9 +3254,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.28.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe32e8c89834541077a5c5bbe5691aa69324361e27e6aeb3552a737db4a70c8" +checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" dependencies = [ "arrayvec", "borsh", From fca5402cc5cef6eb47ccb57797b23f422ed487d0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:02:42 +0000 Subject: [PATCH 025/395] build(deps): bump vergen from 7.5.0 to 7.5.1 Bumps [vergen](https://github.com/rustyhorde/vergen) from 7.5.0 to 7.5.1. - [Release notes](https://github.com/rustyhorde/vergen/releases) - [Commits](https://github.com/rustyhorde/vergen/compare/7.5.0...7.5.1) --- updated-dependencies: - dependency-name: vergen dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d76d809..6c326143 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1434,9 +1434,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.15.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" +checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ "bitflags", "libc", @@ -1827,9 +1827,9 @@ checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "libgit2-sys" -version = "0.14.0+1.5.0" +version = "0.14.2+1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" +checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" dependencies = [ "cc", "libc", @@ -3357,9 +3357,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "rusty-fork" @@ -4794,9 +4794,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "7.5.0" +version = "7.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "571b69f690c855821462709b6f41d42ceccc316fbd17b60bd06d06928cfe6a99" +checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" dependencies = [ "anyhow", "cfg-if 1.0.0", From 1496c656b5fb7b7d267d70ab1404cba952be2a71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Feb 2023 11:03:02 +0000 Subject: [PATCH 026/395] build(deps): bump serde_json from 1.0.92 to 1.0.93 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.92 to 1.0.93. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.92...v1.0.93) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d76d809..e7a813e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3548,9 +3548,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.92" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7434af0dc1cbd59268aa98b4c22c131c0584d2232f6fb166efb993e2832e896a" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa 1.0.1", "ryu", From 5b40fe30bb449414db1642ceaa132e72d2831b89 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Feb 2023 12:01:22 +0000 Subject: [PATCH 027/395] build(deps): bump bdk from 0.26.0 to 0.27.0 Bumps [bdk](https://github.com/bitcoindevkit/bdk) from 0.26.0 to 0.27.0. - [Release notes](https://github.com/bitcoindevkit/bdk/releases) - [Changelog](https://github.com/bitcoindevkit/bdk/blob/master/CHANGELOG.md) - [Commits](https://github.com/bitcoindevkit/bdk/compare/v0.26.0...v0.27.0) --- updated-dependencies: - dependency-name: bdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- swap/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce8bc516..73425425 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,9 +226,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bdk" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b238a07736baee43ba9663933e44b1c6c27b43ef871b9486e175902335d83880" +checksum = "f8761f371822c53afda671a6217aa89438646af05f05aef0ecd4c647b66ee1d3" dependencies = [ "async-trait", "bdk-macros", @@ -2250,9 +2250,9 @@ checksum = "0c835948974f68e0bd58636fc6c5b1fbff7b297e3046f11b3b3c18bbac012c6d" [[package]] name = "miniscript" -version = "8.0.0" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4975078076f0b7b914a3044ad7432d2a7fcec38edb855afdc672e24ca35b69" +checksum = "123a10aae81d0712ecc09b780f6f0ae0b0f506a5c4c912974725760d59ba073e" dependencies = [ "bitcoin", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 127c23e8..1a054c48 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1" atty = "0.2" backoff = { version = "0.4", features = [ "tokio" ] } base64 = "0.21" -bdk = "0.26" +bdk = "0.27" big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bmrng = "0.5" From 35cd7ddd4d80e9b7e7e9351575350b73ba56fe67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Feb 2023 11:59:11 +0000 Subject: [PATCH 028/395] build(deps): bump time from 0.3.17 to 0.3.18 Bumps [time](https://github.com/time-rs/time) from 0.3.17 to 0.3.18. - [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.17...v0.3.18) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73425425..64cb33da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4085,7 +4085,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.17", + "time 0.3.18", "tokio", "tokio-socks", "tokio-tar", @@ -4233,9 +4233,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" +checksum = "af0097eaf301d576d0b2aead7a59facab6d53cc636340f0291fab8446a2e8613" dependencies = [ "itoa 1.0.1", "serde", @@ -4470,7 +4470,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", - "time 0.3.17", + "time 0.3.18", "tracing-subscriber 0.3.15", ] @@ -4560,7 +4560,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.17", + "time 0.3.18", "tracing", "tracing-core", "tracing-log", @@ -4805,7 +4805,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.17", + "time 0.3.18", ] [[package]] From c1f0998b0d47edaffa554f467b82d8c25c0efcf0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 Feb 2023 12:00:59 +0000 Subject: [PATCH 029/395] build(deps): bump time from 0.3.18 to 0.3.19 Bumps [time](https://github.com/time-rs/time) from 0.3.18 to 0.3.19. - [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.18...v0.3.19) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64cb33da..bcb174df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4085,7 +4085,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.18", + "time 0.3.19", "tokio", "tokio-socks", "tokio-tar", @@ -4233,9 +4233,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0097eaf301d576d0b2aead7a59facab6d53cc636340f0291fab8446a2e8613" +checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" dependencies = [ "itoa 1.0.1", "serde", @@ -4251,9 +4251,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" +checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" dependencies = [ "time-core", ] @@ -4470,7 +4470,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", - "time 0.3.18", + "time 0.3.19", "tracing-subscriber 0.3.15", ] @@ -4560,7 +4560,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.18", + "time 0.3.19", "tracing", "tracing-core", "tracing-log", @@ -4805,7 +4805,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.18", + "time 0.3.19", ] [[package]] From 99d847da51cad7149fe1fb93bf483ed7721a218c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 12:01:56 +0000 Subject: [PATCH 030/395] build(deps): bump bdk from 0.27.0 to 0.27.1 Bumps [bdk](https://github.com/bitcoindevkit/bdk) from 0.27.0 to 0.27.1. - [Release notes](https://github.com/bitcoindevkit/bdk/releases) - [Changelog](https://github.com/bitcoindevkit/bdk/blob/master/CHANGELOG.md) - [Commits](https://github.com/bitcoindevkit/bdk/compare/v0.27.0...v0.27.1) --- updated-dependencies: - dependency-name: bdk dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bcb174df..45cf52b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,9 +226,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bdk" -version = "0.27.0" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8761f371822c53afda671a6217aa89438646af05f05aef0ecd4c647b66ee1d3" +checksum = "51c878ac60a45c41523ff790df555ccb1fbfd634a667220104dcae3e64d7ed9f" dependencies = [ "async-trait", "bdk-macros", From 9b07c4e0b643ff3c70f83e4e1784273e296dab82 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Feb 2023 11:20:07 +0000 Subject: [PATCH 031/395] build(deps): bump Swatinem/rust-cache from 2.2.0 to 2.2.1 Bumps [Swatinem/rust-cache](https://github.com/Swatinem/rust-cache) from 2.2.0 to 2.2.1. - [Release notes](https://github.com/Swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/Swatinem/rust-cache/compare/v2.2.0...v2.2.1) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 9c856a53..3dace62f 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.2.0 + - uses: Swatinem/rust-cache@v2.2.1 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04461afd..b4f5164f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 - - uses: Swatinem/rust-cache@v2.2.0 + - uses: Swatinem/rust-cache@v2.2.1 - name: Check formatting uses: dprint/check@v2.2 @@ -32,7 +32,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 - - uses: Swatinem/rust-cache@v2.0.2 + - uses: Swatinem/rust-cache@v2.2.1 - name: Build swap run: cargo build --bin swap @@ -46,7 +46,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 - - uses: Swatinem/rust-cache@v2.0.2 + - uses: Swatinem/rust-cache@v2.2.1 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -73,7 +73,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 - - uses: Swatinem/rust-cache@v2.2.0 + - uses: Swatinem/rust-cache@v2.2.1 - uses: dtolnay/rust-toolchain@master with: @@ -113,7 +113,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 - - uses: Swatinem/rust-cache@v2.2.0 + - uses: Swatinem/rust-cache@v2.2.1 - name: Build tests run: cargo build --tests --workspace --all-features @@ -150,7 +150,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 - - uses: Swatinem/rust-cache@v2.2.0 + - uses: Swatinem/rust-cache@v2.2.1 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From 485f6d4a12beefa6505aa4a1d556d6c9dbe159be Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 12:01:45 +0000 Subject: [PATCH 032/395] build(deps): bump time from 0.3.19 to 0.3.20 Bumps [time](https://github.com/time-rs/time) from 0.3.19 to 0.3.20. - [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.19...v0.3.20) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45cf52b8..c90655dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4085,7 +4085,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.19", + "time 0.3.20", "tokio", "tokio-socks", "tokio-tar", @@ -4233,9 +4233,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53250a3b3fed8ff8fd988587d8925d26a83ac3845d9e03b220b37f34c2b8d6c2" +checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ "itoa 1.0.1", "serde", @@ -4251,9 +4251,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a460aeb8de6dcb0f381e1ee05f1cd56fcf5a5f6eb8187ff3d8f0b11078d38b7c" +checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" dependencies = [ "time-core", ] @@ -4470,7 +4470,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", - "time 0.3.19", + "time 0.3.20", "tracing-subscriber 0.3.15", ] @@ -4560,7 +4560,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.19", + "time 0.3.20", "tracing", "tracing-core", "tracing-log", @@ -4805,7 +4805,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.19", + "time 0.3.20", ] [[package]] From 4458e00e949a0718786148423cfad39b3dcba1d4 Mon Sep 17 00:00:00 2001 From: Steve Russo Date: Mon, 27 Feb 2023 15:13:17 -0500 Subject: [PATCH 033/395] readme: fix minor grammar error --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3e6c3765..bae39780 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ It is not recommended to bump fees when swapping because it can have unpredictab ## Contributing -We are encourage community contributions whether it be a bug fix or an improvement to the documentation. +We 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 From a23bf2129a3ad771a4ebb1b2548811febfd420da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Mar 2023 12:10:49 +0000 Subject: [PATCH 034/395] build(deps): bump tempfile from 3.3.0 to 3.4.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.3.0 to 3.4.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/commits) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 150 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 136 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c90655dc..d6a24035 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1143,6 +1143,27 @@ dependencies = [ "syn", ] +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1716,6 +1737,16 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "io-lifetimes" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +dependencies = [ + "libc", + "windows-sys 0.45.0", +] + [[package]] name = "ipconfig" version = "0.2.2" @@ -2155,6 +2186,12 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + [[package]] name = "lock_api" version = "0.4.6" @@ -3150,15 +3187,6 @@ version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" -[[package]] -name = "remove_dir_all" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] - [[package]] name = "rend" version = "0.3.6" @@ -3309,6 +3337,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.36.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.45.0", +] + [[package]] name = "rustls" version = "0.19.0" @@ -4129,16 +4171,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" dependencies = [ "cfg-if 1.0.0", "fastrand", - "libc", "redox_syscall", - "remove_dir_all", - "winapi", + "rustix", + "windows-sys 0.42.0", ] [[package]] @@ -5048,6 +5089,51 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.1", + "windows_i686_gnu 0.42.1", + "windows_i686_msvc 0.42.1", + "windows_x86_64_gnu 0.42.1", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" @@ -5060,6 +5146,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" + [[package]] name = "windows_i686_gnu" version = "0.32.0" @@ -5072,6 +5164,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +[[package]] +name = "windows_i686_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" + [[package]] name = "windows_i686_msvc" version = "0.32.0" @@ -5084,6 +5182,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +[[package]] +name = "windows_i686_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" + [[package]] name = "windows_x86_64_gnu" version = "0.32.0" @@ -5096,6 +5200,18 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" + [[package]] name = "windows_x86_64_msvc" version = "0.32.0" @@ -5108,6 +5224,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" + [[package]] name = "winreg" version = "0.6.2" From 4c59117a00f956c0e9fc8a7bf038dc2b56203721 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 10:26:34 +0000 Subject: [PATCH 035/395] build(deps): bump async-trait from 0.1.64 to 0.1.66 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.64 to 0.1.66. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.64...0.1.66) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6a24035..fb74539a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" dependencies = [ "proc-macro2", "quote", From f5567ebfd730e2505003a09f48dd8d9eae9bf957 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 10:27:28 +0000 Subject: [PATCH 036/395] build(deps): bump serde_json from 1.0.93 to 1.0.94 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.93 to 1.0.94. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.93...v1.0.94) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6a24035..9a37dd10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3590,9 +3590,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa 1.0.1", "ryu", From c5067dc8d7e85c331245a3f6987fe4a87f4087d4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 10:27:48 +0000 Subject: [PATCH 037/395] build(deps): bump thiserror from 1.0.38 to 1.0.39 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.38 to 1.0.39. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.38...1.0.39) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6a24035..2fa4d86d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4235,18 +4235,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" dependencies = [ "proc-macro2", "quote", From e75f589915923f37e065879ed899365da97de7e9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 9 Mar 2023 11:58:03 +0000 Subject: [PATCH 038/395] build(deps): bump serde from 1.0.152 to 1.0.154 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.152 to 1.0.154. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.152...v1.0.154) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 313e362f..3dd26418 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3550,9 +3550,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.152" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e" dependencies = [ "serde_derive", ] @@ -3579,9 +3579,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217" dependencies = [ "proc-macro2", "quote", From 00cfce57c77f251467f204e05bea5c50f9767cc0 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 15 Mar 2023 14:12:28 +0200 Subject: [PATCH 039/395] chore: fix dprint config and run fmt --- .github/workflows/ci.yml | 5 +++ dprint.json | 16 +++------- monero-rpc/src/monerod.rs | 7 +++-- swap/src/bitcoin/cancel.rs | 22 +++++++++----- swap/src/bitcoin/punish.rs | 22 +++++++++----- swap/src/bitcoin/redeem.rs | 22 +++++++++----- swap/src/bitcoin/refund.rs | 22 +++++++++----- swap/src/cli/list_sellers.rs | 39 +++++++++++++----------- swap/src/network/swap_setup/bob.rs | 15 +++++---- swap/src/protocol/alice/state.rs | 49 ++++++++++++++++-------------- swap/tests/harness/mod.rs | 17 ++++++----- 11 files changed, 136 insertions(+), 100 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4f5164f..f36e5b01 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,11 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.3.0 + - uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.63 + components: clippy,rustfmt + - uses: Swatinem/rust-cache@v2.2.1 - name: Check formatting diff --git a/dprint.json b/dprint.json index 18c300b2..8f18b0bf 100644 --- a/dprint.json +++ b/dprint.json @@ -3,22 +3,16 @@ "projectType": "openSource", "incremental": true, "markdown": {}, - "rustfmt": { - "edition": 2021, - "condense_wildcard_suffixes": true, - "format_macro_matchers": true, - "imports_granularity": "Module", - "use_field_init_shorthand": true, - "format_code_in_doc_comments": true, - "normalize_comments": true, - "wrap_comments": true, - "overflow_delimited_expr": true + "exec": { + "associations": "**/*.{rs}", + "rustfmt": "rustfmt --edition 2021", + "rustfmt.associations": "**/*.rs" }, "includes": ["**/*.{md}", "**/*.{toml}", "**/*.{rs}"], "excludes": ["target/"], "plugins": [ "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.6.1.exe-plugin@99b89a0599fd3a63e597e03436862157901f3facae2f0c2fbd0b9f656cdbc2a5" + "https://plugins.dprint.dev/exec-0.3.5.json@d687dda57be0fe9a0088ccdaefa5147649ff24127d8b3ea227536c68ee7abeab" ] } diff --git a/monero-rpc/src/monerod.rs b/monero-rpc/src/monerod.rs index 830aafdb..c2cde67c 100644 --- a/monero-rpc/src/monerod.rs +++ b/monero-rpc/src/monerod.rs @@ -47,9 +47,10 @@ impl Client { } pub async fn get_o_indexes(&self, txid: Hash) -> Result { - self.binary_request(self.get_o_indexes_bin_url.clone(), GetOIndexesPayload { - txid, - }) + self.binary_request( + self.get_o_indexes_bin_url.clone(), + GetOIndexesPayload { txid }, + ) .await } diff --git a/swap/src/bitcoin/cancel.rs b/swap/src/bitcoin/cancel.rs index 354b0c00..35b6b197 100644 --- a/swap/src/bitcoin/cancel.rs +++ b/swap/src/bitcoin/cancel.rs @@ -210,14 +210,20 @@ impl TxCancel { }; // The order in which these are inserted doesn't matter - satisfier.insert(A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), - hash_ty: EcdsaSighashType::All, - }); - satisfier.insert(B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), - hash_ty: EcdsaSighashType::All, - }); + satisfier.insert( + A, + ::bitcoin::EcdsaSig { + sig: sig_a.into(), + hash_ty: EcdsaSighashType::All, + }, + ); + satisfier.insert( + B, + ::bitcoin::EcdsaSig { + sig: sig_b.into(), + hash_ty: EcdsaSighashType::All, + }, + ); satisfier }; diff --git a/swap/src/bitcoin/punish.rs b/swap/src/bitcoin/punish.rs index df7a1367..247c904f 100644 --- a/swap/src/bitcoin/punish.rs +++ b/swap/src/bitcoin/punish.rs @@ -65,14 +65,20 @@ impl TxPunish { let B = B.try_into()?; // The order in which these are inserted doesn't matter - satisfier.insert(A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), - hash_ty: EcdsaSighashType::All, - }); - satisfier.insert(B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), - hash_ty: EcdsaSighashType::All, - }); + satisfier.insert( + A, + ::bitcoin::EcdsaSig { + sig: sig_a.into(), + hash_ty: EcdsaSighashType::All, + }, + ); + satisfier.insert( + B, + ::bitcoin::EcdsaSig { + sig: sig_b.into(), + hash_ty: EcdsaSighashType::All, + }, + ); satisfier }; diff --git a/swap/src/bitcoin/redeem.rs b/swap/src/bitcoin/redeem.rs index d94f03d9..e91c25ee 100644 --- a/swap/src/bitcoin/redeem.rs +++ b/swap/src/bitcoin/redeem.rs @@ -87,14 +87,20 @@ impl TxRedeem { }; // The order in which these are inserted doesn't matter - satisfier.insert(A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), - hash_ty: EcdsaSighashType::All, - }); - satisfier.insert(B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), - hash_ty: EcdsaSighashType::All, - }); + satisfier.insert( + A, + ::bitcoin::EcdsaSig { + sig: sig_a.into(), + hash_ty: EcdsaSighashType::All, + }, + ); + satisfier.insert( + B, + ::bitcoin::EcdsaSig { + sig: sig_b.into(), + hash_ty: EcdsaSighashType::All, + }, + ); satisfier }; diff --git a/swap/src/bitcoin/refund.rs b/swap/src/bitcoin/refund.rs index 55aa6c25..a73dd0e3 100644 --- a/swap/src/bitcoin/refund.rs +++ b/swap/src/bitcoin/refund.rs @@ -70,14 +70,20 @@ impl TxRefund { }; // The order in which these are inserted doesn't matter - satisfier.insert(A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), - hash_ty: EcdsaSighashType::All, - }); - satisfier.insert(B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), - hash_ty: EcdsaSighashType::All, - }); + satisfier.insert( + A, + ::bitcoin::EcdsaSig { + sig: sig_a.into(), + hash_ty: EcdsaSighashType::All, + }, + ); + satisfier.insert( + B, + ::bitcoin::EcdsaSig { + sig: sig_b.into(), + hash_ty: EcdsaSighashType::All, + }, + ); satisfier }; diff --git a/swap/src/cli/list_sellers.rs b/swap/src/cli/list_sellers.rs index 95a52386..381c561f 100644 --- a/swap/src/cli/list_sellers.rs +++ b/swap/src/cli/list_sellers.rs @@ -350,23 +350,26 @@ mod tests { list.sort(); - assert_eq!(list, vec![ - Seller { - multiaddr: "/ip4/127.0.0.1/tcp/5678".parse().unwrap(), - status: Status::Online(BidQuote { - price: Default::default(), - min_quantity: Default::default(), - max_quantity: Default::default(), - }) - }, - Seller { - multiaddr: Multiaddr::empty(), - status: Status::Unreachable - }, - Seller { - multiaddr: "/ip4/127.0.0.1/tcp/1234".parse().unwrap(), - status: Status::Unreachable - }, - ]) + assert_eq!( + list, + vec![ + Seller { + multiaddr: "/ip4/127.0.0.1/tcp/5678".parse().unwrap(), + status: Status::Online(BidQuote { + price: Default::default(), + min_quantity: Default::default(), + max_quantity: Default::default(), + }) + }, + Seller { + multiaddr: Multiaddr::empty(), + status: Status::Unreachable + }, + Seller { + multiaddr: "/ip4/127.0.0.1/tcp/1234".parse().unwrap(), + status: Status::Unreachable + }, + ] + ) } } diff --git a/swap/src/network/swap_setup/bob.rs b/swap/src/network/swap_setup/bob.rs index 18972319..bee70c24 100644 --- a/swap/src/network/swap_setup/bob.rs +++ b/swap/src/network/swap_setup/bob.rs @@ -155,13 +155,16 @@ impl ProtocolsHandler for Handler { let env_config = self.env_config; let protocol = tokio::time::timeout(self.timeout, async move { - write_cbor_message(&mut substream, SpotPriceRequest { - btc: info.btc, - blockchain_network: BlockchainNetwork { - bitcoin: env_config.bitcoin_network, - monero: env_config.monero_network, + write_cbor_message( + &mut substream, + SpotPriceRequest { + btc: info.btc, + blockchain_network: BlockchainNetwork { + bitcoin: env_config.bitcoin_network, + monero: env_config.monero_network, + }, }, - }) + ) .await?; let xmr = Result::from(read_cbor_message::(&mut substream).await?)?; diff --git a/swap/src/protocol/alice/state.rs b/swap/src/protocol/alice/state.rs index 9dcf3f46..b34e0326 100644 --- a/swap/src/protocol/alice/state.rs +++ b/swap/src/protocol/alice/state.rs @@ -184,29 +184,32 @@ impl State0 { let v = self.v_a + msg.v_b; - Ok((msg.swap_id, State1 { - a: self.a, - B: msg.B, - s_a: self.s_a, - S_a_monero: self.S_a_monero, - S_a_bitcoin: self.S_a_bitcoin, - S_b_monero: msg.S_b_monero, - S_b_bitcoin: msg.S_b_bitcoin, - v, - v_a: self.v_a, - dleq_proof_s_a: self.dleq_proof_s_a, - btc: self.btc, - xmr: self.xmr, - cancel_timelock: self.cancel_timelock, - punish_timelock: self.punish_timelock, - refund_address: msg.refund_address, - redeem_address: self.redeem_address, - punish_address: self.punish_address, - tx_redeem_fee: self.tx_redeem_fee, - tx_punish_fee: self.tx_punish_fee, - tx_refund_fee: msg.tx_refund_fee, - tx_cancel_fee: msg.tx_cancel_fee, - })) + Ok(( + msg.swap_id, + State1 { + a: self.a, + B: msg.B, + s_a: self.s_a, + S_a_monero: self.S_a_monero, + S_a_bitcoin: self.S_a_bitcoin, + S_b_monero: msg.S_b_monero, + S_b_bitcoin: msg.S_b_bitcoin, + v, + v_a: self.v_a, + dleq_proof_s_a: self.dleq_proof_s_a, + btc: self.btc, + xmr: self.xmr, + cancel_timelock: self.cancel_timelock, + punish_timelock: self.punish_timelock, + refund_address: msg.refund_address, + redeem_address: self.redeem_address, + punish_address: self.punish_address, + tx_redeem_fee: self.tx_redeem_fee, + tx_punish_fee: self.tx_punish_fee, + tx_refund_fee: msg.tx_refund_fee, + tx_cancel_fee: msg.tx_cancel_fee, + }, + )) } } diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 74afcc83..e10ce19e 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -158,13 +158,16 @@ async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) { .await .unwrap(); - (monero, Containers { - bitcoind_url, - bitcoind, - monerod_container, - monero_wallet_rpc_containers, - electrs, - }) + ( + monero, + Containers { + bitcoind_url, + bitcoind, + monerod_container, + monero_wallet_rpc_containers, + electrs, + }, + ) } async fn init_bitcoind_container( From 1723ddf133329a09e61c9c583e74d73cc580325f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:23:28 +0000 Subject: [PATCH 040/395] build(deps): bump serde from 1.0.154 to 1.0.156 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.154 to 1.0.156. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.154...v1.0.156) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dd26418..9225f999 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3550,9 +3550,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.154" +version = "1.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cdd151213925e7f1ab45a9bbfb129316bd00799784b174b7cc7bcd16961c49e" +checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" dependencies = [ "serde_derive", ] @@ -3579,9 +3579,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.154" +version = "1.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc80d722935453bcafdc2c9a73cd6fac4dc1938f0346035d84bf99fa9e33217" +checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" dependencies = [ "proc-macro2", "quote", From c788094e4a7040f66718c93f1cba7046f86bc925 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:23:32 +0000 Subject: [PATCH 041/395] build(deps): bump hyper from 0.14.24 to 0.14.25 Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.24 to 0.14.25. - [Release notes](https://github.com/hyperium/hyper/releases) - [Changelog](https://github.com/hyperium/hyper/blob/v0.14.25/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper/compare/v0.14.24...v0.14.25) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dd26418..7b208868 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1632,9 +1632,9 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.24" +version = "0.14.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c" +checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" dependencies = [ "bytes", "futures-channel", From c176bef55555a63b76e23a29ed44533ce9d3cd8d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:23:35 +0000 Subject: [PATCH 042/395] build(deps): bump rust_decimal from 1.28.1 to 1.29.0 Bumps [rust_decimal](https://github.com/paupino/rust-decimal) from 1.28.1 to 1.29.0. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.28.1...1.29.0) --- updated-dependencies: - dependency-name: rust_decimal dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dd26418..49a2ba9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3290,9 +3290,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.28.1" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" +checksum = "2b1b21b8760b0ef8ae5b43d40913ff711a2053cb7ff892a34facff7a6365375a" dependencies = [ "arrayvec", "borsh", From eb2818da572808da1416d6022fa27440da7d1304 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:23:41 +0000 Subject: [PATCH 043/395] build(deps): bump futures from 0.3.26 to 0.3.27 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.26 to 0.3.27. - [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.26...0.3.27) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dd26418..bfbfba90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1267,9 +1267,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84" +checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" dependencies = [ "futures-channel", "futures-core", @@ -1282,9 +1282,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" dependencies = [ "futures-core", "futures-sink", @@ -1292,15 +1292,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" [[package]] name = "futures-executor" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e" +checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83" dependencies = [ "futures-core", "futures-task", @@ -1321,15 +1321,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" +checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", @@ -1349,15 +1349,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" [[package]] name = "futures-timer" @@ -1367,9 +1367,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" dependencies = [ "futures-channel", "futures-core", From 0d70cd8d025e7f75cc62328672b8605444631e3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 Mar 2023 13:23:47 +0000 Subject: [PATCH 044/395] build(deps): bump rust_decimal_macros from 1.28.1 to 1.29.0 Bumps [rust_decimal_macros](https://github.com/paupino/rust-decimal) from 1.28.1 to 1.29.0. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.28.1...1.29.0) --- updated-dependencies: - dependency-name: rust_decimal_macros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dd26418..42e5bd8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3290,9 +3290,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.28.1" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" +checksum = "2b1b21b8760b0ef8ae5b43d40913ff711a2053cb7ff892a34facff7a6365375a" dependencies = [ "arrayvec", "borsh", @@ -3308,9 +3308,9 @@ dependencies = [ [[package]] name = "rust_decimal_macros" -version = "1.28.1" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79c1532c5088b44236d74c7dd9d80a1c57a433e02694fced7b5a670dc562ce5" +checksum = "7f4709403426683ccd5e1ef02b24a2468fe87f8df8a2a792743bb369d7656efa" dependencies = [ "quote", "rust_decimal", From 559292498f2dbb38669d8ba74c967b0c7a338691 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:59:01 +0000 Subject: [PATCH 045/395] build(deps): bump anyhow from 1.0.69 to 1.0.70 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.69 to 1.0.70. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.69...1.0.70) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7941edeb..533fb029 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "arrayref" From d6e0f2d379b5ba663a964d6f4c9d785914fdda59 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Mar 2023 11:59:25 +0000 Subject: [PATCH 046/395] build(deps): bump thiserror from 1.0.39 to 1.0.40 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.39 to 1.0.40. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.39...1.0.40) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 99 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7941edeb..3ea5b954 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -126,7 +126,7 @@ checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -253,7 +253,7 @@ checksum = "81c1980e50ae23bb6efa9283ae8679d6ea2c6fa6a99fe62533f65f4a25a1a56c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -436,7 +436,7 @@ dependencies = [ "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", "proc-macro2", - "syn", + "syn 1.0.104", ] [[package]] @@ -447,7 +447,7 @@ checksum = "61820b4c5693eafb998b1e67485423c923db4a75f72585c247bdee32bad81e7b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -458,7 +458,7 @@ checksum = "c76cdbfa13def20d1f8af3ae7b3c6771f06352a74221d8851262ac384c122b8e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -491,7 +491,7 @@ checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -926,7 +926,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn", + "syn 1.0.104", ] [[package]] @@ -937,7 +937,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -967,7 +967,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 1.0.104", ] [[package]] @@ -1120,7 +1120,7 @@ dependencies = [ "heck 0.3.2", "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -1140,7 +1140,7 @@ checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -1333,7 +1333,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -1440,7 +1440,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -1825,7 +1825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97c11e429f0eaa41fe659013680b459d2368d8f0a3e69dccfb7a35800b0dc27b" dependencies = [ "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -2106,7 +2106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b4d0acd47739fe0b570728d8d11bbb535050d84c0cf05d6477a4891fceae10" dependencies = [ "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -2433,7 +2433,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.104", "synstructure", ] @@ -2606,7 +2606,7 @@ checksum = "a15c83b586f00268c619c1cb3340ec1a6f59dd9ba1d9833a273a68e6d5cd8ffc" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -2744,7 +2744,7 @@ checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -2755,7 +2755,7 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -2854,7 +2854,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn", + "syn 1.0.104", "version_check", ] @@ -2871,9 +2871,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" dependencies = [ "unicode-ident", ] @@ -2939,7 +2939,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -2969,7 +2969,7 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -3007,9 +3007,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -3285,7 +3285,7 @@ checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -3585,7 +3585,7 @@ checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -3630,7 +3630,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -3655,7 +3655,7 @@ checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -3964,7 +3964,7 @@ dependencies = [ "sha2 0.10.6", "sqlx-core", "sqlx-rt", - "syn", + "syn 1.0.104", "url", ] @@ -4034,7 +4034,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -4056,7 +4056,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn", + "syn 1.0.104", ] [[package]] @@ -4157,6 +4157,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8234ae35e70582bfa0f1fedffa6daa248e41dd045310b19800c4a36382c8f60" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "synstructure" version = "0.12.4" @@ -4165,7 +4176,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", "unicode-xid", ] @@ -4235,22 +4246,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ab016db510546d856297882807df8da66a16fb8c4101cb8b30054b0d5b2d9c" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5420d42e90af0c38c3290abcca25b9b3bdf379fc9f55c528f53a269d9c9a267e" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.3", ] [[package]] @@ -4351,7 +4362,7 @@ checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -4523,7 +4534,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", ] [[package]] @@ -4919,7 +4930,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.104", "wasm-bindgen-shared", ] @@ -4953,7 +4964,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5299,7 +5310,7 @@ checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.104", "synstructure", ] From b475208a9f02aaa884add1f71a9072991dad12b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 Mar 2023 11:58:56 +0000 Subject: [PATCH 047/395] build(deps): bump reqwest from 0.11.14 to 0.11.15 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.14 to 0.11.15. - [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.14...v0.11.15) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7941edeb..ad462d4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3198,9 +3198,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9" +checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949" dependencies = [ "base64 0.21.0", "bytes", From eb900f30e5511b337749df62f7b5f850aa350f2b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Mar 2023 12:01:57 +0000 Subject: [PATCH 048/395] build(deps): bump actions/checkout from 3.3.0 to 3.5.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.3.0...v3.5.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 3dace62f..a54feb64 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f36e5b01..b5d686f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 - uses: Swatinem/rust-cache@v2.2.1 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 - uses: Swatinem/rust-cache@v2.2.1 @@ -76,7 +76,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 - uses: Swatinem/rust-cache@v2.2.1 @@ -116,7 +116,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 - uses: Swatinem/rust-cache@v2.2.1 @@ -153,7 +153,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.3.0 + uses: actions/checkout@v3.5.0 - uses: Swatinem/rust-cache@v2.2.1 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 40e79474..6a5505b7 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.3.0 + - uses: actions/checkout@v3.5.0 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index bd9a8298..b75db9ed 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.3.0 + - uses: actions/checkout@v3.5.0 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 180b8ebb..f174129c 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.3.0 + - uses: actions/checkout@v3.5.0 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From d8a5a646b787562e616be34f989cc428a6a235f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:40:43 +0000 Subject: [PATCH 049/395] build(deps): bump serde from 1.0.156 to 1.0.160 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.156 to 1.0.160. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.156...v1.0.160) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7670ab8..f6eb206f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3550,9 +3550,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.156" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] @@ -3579,13 +3579,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.156" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 2.0.3", ] [[package]] From 11841090086b68d47dee440a4c28062ee5f26f2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 09:40:47 +0000 Subject: [PATCH 050/395] build(deps): bump async-trait from 0.1.66 to 0.1.68 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.66 to 0.1.68. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.66...0.1.68) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7670ab8..dbc2999f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,13 +120,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.66" +version = "0.1.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84f9ebcc6c1f5b8cb160f6990096a5c127f423fcb6e1ccc46c370cbdfb75dfc" +checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 2.0.3", ] [[package]] From 10056c58763b4a728581c4d9b9a60c46297afb5a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 11:57:45 +0000 Subject: [PATCH 051/395] build(deps): bump uuid from 1.3.0 to 1.3.1 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.3.0...1.3.1) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7670ab8..519bd9ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4818,9 +4818,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" dependencies = [ "getrandom 0.2.6", "serde", From c00330901c9bf63e70ad23043f5ecef227d105b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 11:58:13 +0000 Subject: [PATCH 052/395] build(deps): bump dialoguer from 0.10.3 to 0.10.4 Bumps [dialoguer](https://github.com/mitsuhiko/dialoguer) from 0.10.3 to 0.10.4. - [Release notes](https://github.com/mitsuhiko/dialoguer/releases) - [Changelog](https://github.com/console-rs/dialoguer/blob/master/CHANGELOG.md) - [Commits](https://github.com/mitsuhiko/dialoguer/compare/0.10.3...v0.10.4) --- updated-dependencies: - dependency-name: dialoguer dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7670ab8..273639ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -972,9 +972,9 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.10.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af3c796f3b0b408d9fd581611b47fa850821fcb84aa640b83a3c1a5be2d691f2" +checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" dependencies = [ "console", "shell-words", From 5a13e2bede7bcd2afd35bd46c2bbfc29f0f6bb2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 12 Apr 2023 11:59:20 +0000 Subject: [PATCH 053/395] build(deps): bump bdk from 0.27.1 to 0.28.0 Bumps [bdk](https://github.com/bitcoindevkit/bdk) from 0.27.1 to 0.28.0. - [Release notes](https://github.com/bitcoindevkit/bdk/releases) - [Changelog](https://github.com/bitcoindevkit/bdk/blob/master/CHANGELOG.md) - [Commits](https://github.com/bitcoindevkit/bdk/compare/v0.27.1...v0.28.0) --- updated-dependencies: - dependency-name: bdk dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d7670ab8..9765a2f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,9 +226,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bdk" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51c878ac60a45c41523ff790df555ccb1fbfd634a667220104dcae3e64d7ed9f" +checksum = "e9b650f45ae7dc8558544448253f3e1ae443433637ccd9f9d14d2089ff913480" dependencies = [ "async-trait", "bdk-macros", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 1a054c48..283aeb77 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -15,7 +15,7 @@ async-trait = "0.1" atty = "0.2" backoff = { version = "0.4", features = [ "tokio" ] } base64 = "0.21" -bdk = "0.27" +bdk = "0.28" big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bmrng = "0.5" From 6629b73a56d21b7ba6b0226d3f218869c9e2e4ce Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 11:58:14 +0000 Subject: [PATCH 054/395] build(deps): bump sqlx from 0.6.2 to 0.6.3 Bumps [sqlx](https://github.com/launchbadge/sqlx) from 0.6.2 to 0.6.3. - [Release notes](https://github.com/launchbadge/sqlx/releases) - [Changelog](https://github.com/launchbadge/sqlx/blob/v0.6.3/CHANGELOG.md) - [Commits](https://github.com/launchbadge/sqlx/compare/v0.6.2...v0.6.3) --- updated-dependencies: - dependency-name: sqlx dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 86 +++++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b891bb5c..bd179fb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -253,7 +253,7 @@ checksum = "81c1980e50ae23bb6efa9283ae8679d6ea2c6fa6a99fe62533f65f4a25a1a56c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -436,7 +436,7 @@ dependencies = [ "borsh-schema-derive-internal", "proc-macro-crate 0.1.5", "proc-macro2", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -447,7 +447,7 @@ checksum = "61820b4c5693eafb998b1e67485423c923db4a75f72585c247bdee32bad81e7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -458,7 +458,7 @@ checksum = "c76cdbfa13def20d1f8af3ae7b3c6771f06352a74221d8851262ac384c122b8e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -491,7 +491,7 @@ checksum = "13e576ebe98e605500b3c8041bb888e966653577172df6dd97398714eb30b9bf" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -926,7 +926,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -937,7 +937,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -967,7 +967,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -1120,7 +1120,7 @@ dependencies = [ "heck 0.3.2", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -1140,7 +1140,7 @@ checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -1333,7 +1333,7 @@ checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -1440,7 +1440,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -1825,7 +1825,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97c11e429f0eaa41fe659013680b459d2368d8f0a3e69dccfb7a35800b0dc27b" dependencies = [ "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -2106,7 +2106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33b4d0acd47739fe0b570728d8d11bbb535050d84c0cf05d6477a4891fceae10" dependencies = [ "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -2433,7 +2433,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "synstructure", ] @@ -2606,7 +2606,7 @@ checksum = "a15c83b586f00268c619c1cb3340ec1a6f59dd9ba1d9833a273a68e6d5cd8ffc" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -2744,7 +2744,7 @@ checksum = "851c8d0ce9bebe43790dedfc86614c23494ac9f423dd618d3a61fc693eafe61e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -2755,7 +2755,7 @@ checksum = "758669ae3558c6f74bd2a18b41f7ac0b5a195aea6639d6a9b5e5d1ad5ba24c0b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -2854,7 +2854,7 @@ dependencies = [ "proc-macro-error-attr", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "version_check", ] @@ -2939,7 +2939,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -2969,7 +2969,7 @@ checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -3285,7 +3285,7 @@ checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -3630,7 +3630,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -3655,7 +3655,7 @@ checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -3891,9 +3891,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9249290c05928352f71c077cc44a464d880c63f26f7534728cca008e135c0428" +checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" dependencies = [ "sqlx-core", "sqlx-macros", @@ -3901,9 +3901,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbc16ddba161afc99e14d1713a453747a2b07fc097d2009f4c300ec99286105" +checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ "ahash", "atoi", @@ -3948,9 +3948,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b850fa514dc11f2ee85be9d055c512aa866746adfacd1cb42d867d68e6a5b0d9" +checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" dependencies = [ "dotenvy", "either", @@ -3964,15 +3964,15 @@ dependencies = [ "sha2 0.10.6", "sqlx-core", "sqlx-rt", - "syn 1.0.104", + "syn 1.0.109", "url", ] [[package]] name = "sqlx-rt" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24c5b2d25fa654cc5f841750b8e1cdedbe21189bf9a9382ee90bfa9dd3562396" +checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" dependencies = [ "once_cell", "tokio", @@ -4034,7 +4034,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -4056,7 +4056,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -4148,9 +4148,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.104" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", "quote", @@ -4176,7 +4176,7 @@ checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "unicode-xid", ] @@ -4362,7 +4362,7 @@ checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -4534,7 +4534,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", ] [[package]] @@ -4930,7 +4930,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "wasm-bindgen-shared", ] @@ -4964,7 +4964,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5310,7 +5310,7 @@ checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" dependencies = [ "proc-macro2", "quote", - "syn 1.0.104", + "syn 1.0.109", "synstructure", ] From 521ac041dd447a7c830989f4b0def11405449c6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 11:59:45 +0000 Subject: [PATCH 055/395] build(deps): bump reqwest from 0.11.15 to 0.11.16 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.15 to 0.11.16. - [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.15...v0.11.16) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b891bb5c..43e5329b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3198,9 +3198,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.15" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ "base64 0.21.0", "bytes", From fbf222ea9fbbb929863d416873d611fff3fef642 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 12:01:07 +0000 Subject: [PATCH 056/395] build(deps): bump serde_json from 1.0.94 to 1.0.96 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.94 to 1.0.96. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.94...v1.0.96) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b891bb5c..effabab2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3590,9 +3590,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa 1.0.1", "ryu", From 2173e3c678b24947d90af7e9c1e65fe2145f39b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 12:05:47 +0000 Subject: [PATCH 057/395] build(deps): bump tempfile from 3.4.0 to 3.5.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.4.0 to 3.5.0. - [Release notes](https://github.com/Stebalien/tempfile/releases) - [Changelog](https://github.com/Stebalien/tempfile/blob/master/NEWS) - [Commits](https://github.com/Stebalien/tempfile/commits) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 151 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b891bb5c..3bd9a403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,7 +166,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.18", "libc", "winapi", ] @@ -1145,13 +1145,13 @@ dependencies = [ [[package]] name = "errno" -version = "0.2.8" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1187,7 +1187,7 @@ checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.2.10", "winapi", ] @@ -1545,6 +1545,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hex" version = "0.4.3" @@ -1739,12 +1745,13 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ + "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1852,9 +1859,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.137" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "libgit2-sys" @@ -2188,9 +2195,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" [[package]] name = "lock_api" @@ -2570,7 +2577,7 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.18", "libc", ] @@ -2654,7 +2661,7 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.10", "smallvec", "winapi", ] @@ -2667,7 +2674,7 @@ checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.2.10", "smallvec", "windows-sys 0.32.0", ] @@ -3150,6 +3157,15 @@ dependencies = [ "bitflags", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_users" version = "0.4.0" @@ -3157,7 +3173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom 0.2.6", - "redox_syscall", + "redox_syscall 0.2.10", ] [[package]] @@ -3339,16 +3355,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.8" +version = "0.37.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -4182,15 +4198,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if 1.0.0", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -4419,7 +4435,7 @@ dependencies = [ "filetime", "futures-core", "libc", - "redox_syscall", + "redox_syscall 0.2.10", "tokio", "tokio-stream", "xattr", @@ -5100,28 +5116,22 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.1", -] - [[package]] name = "windows-sys" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.1", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", ] [[package]] @@ -5130,21 +5140,42 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.42.1", "windows_aarch64_msvc 0.42.1", "windows_i686_gnu 0.42.1", "windows_i686_msvc 0.42.1", "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.42.1", "windows_x86_64_msvc 0.42.1", ] +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" @@ -5163,6 +5194,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.32.0" @@ -5181,6 +5218,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.32.0" @@ -5199,6 +5242,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.32.0" @@ -5217,12 +5266,24 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.32.0" @@ -5241,6 +5302,12 @@ version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + [[package]] name = "winreg" version = "0.6.2" From fd8b1b49d0062eecc27d6bf88773b868f16f0513 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Apr 2023 11:58:03 +0000 Subject: [PATCH 058/395] build(deps): bump actions/checkout from 3.5.0 to 3.5.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.0...v3.5.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index a54feb64..05041a0d 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b5d686f9..3cb704a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 - uses: Swatinem/rust-cache@v2.2.1 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 - uses: Swatinem/rust-cache@v2.2.1 @@ -76,7 +76,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 - uses: Swatinem/rust-cache@v2.2.1 @@ -116,7 +116,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 - uses: Swatinem/rust-cache@v2.2.1 @@ -153,7 +153,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.0 + uses: actions/checkout@v3.5.2 - uses: Swatinem/rust-cache@v2.2.1 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 6a5505b7..4d9149b0 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.0 + - uses: actions/checkout@v3.5.2 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index b75db9ed..b7b9298b 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.0 + - uses: actions/checkout@v3.5.2 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index f174129c..19f31c37 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.0 + - uses: actions/checkout@v3.5.2 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From 4c7c4509cf5f8fcb9b877c607f8c730962fd68f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:58:10 +0000 Subject: [PATCH 059/395] build(deps): bump rust_decimal from 1.29.0 to 1.29.1 Bumps [rust_decimal](https://github.com/paupino/rust-decimal) from 1.29.0 to 1.29.1. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/commits) --- updated-dependencies: - dependency-name: rust_decimal dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea9d5af5..6c55161b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3306,9 +3306,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.29.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b1b21b8760b0ef8ae5b43d40913ff711a2053cb7ff892a34facff7a6365375a" +checksum = "26bd36b60561ee1fb5ec2817f198b6fd09fa571c897a5e86d1487cfc2b096dfc" dependencies = [ "arrayvec", "borsh", From 9970b4a32838984a7843aebd652b7140e7a526e0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:58:22 +0000 Subject: [PATCH 060/395] build(deps): bump hex-literal from 0.3.4 to 0.4.1 Bumps [hex-literal](https://github.com/RustCrypto/utils) from 0.3.4 to 0.4.1. - [Release notes](https://github.com/RustCrypto/utils/releases) - [Commits](https://github.com/RustCrypto/utils/compare/hex-literal-v0.3.4...hex-literal-v0.4.1) --- updated-dependencies: - dependency-name: hex-literal dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 ++++++++-- monero-rpc/Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea9d5af5..1de20862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1563,6 +1563,12 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + [[package]] name = "hmac" version = "0.10.1" @@ -2332,7 +2338,7 @@ dependencies = [ "curve25519-dalek-ng", "fixed-hash", "hex", - "hex-literal", + "hex-literal 0.3.4", "keccak-hash", "serde", "serde-big-array", @@ -2371,7 +2377,7 @@ dependencies = [ "anyhow", "curve25519-dalek", "hex", - "hex-literal", + "hex-literal 0.4.1", "jsonrpc_client", "monero", "monero-epee-bin-serde", diff --git a/monero-rpc/Cargo.toml b/monero-rpc/Cargo.toml index 427345d6..6da1e88a 100644 --- a/monero-rpc/Cargo.toml +++ b/monero-rpc/Cargo.toml @@ -19,5 +19,5 @@ serde_json = "1.0" tracing = "0.1" [dev-dependencies] -hex-literal = "0.3" +hex-literal = "0.4" tokio = { version = "1", features = [ "full" ] } From 924e2fea7025f80ea0901170d423d489c249a82a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:58:35 +0000 Subject: [PATCH 061/395] build(deps): bump hyper from 0.14.25 to 0.14.26 Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.25 to 0.14.26. - [Release notes](https://github.com/hyperium/hyper/releases) - [Changelog](https://github.com/hyperium/hyper/blob/v0.14.26/CHANGELOG.md) - [Commits](https://github.com/hyperium/hyper/compare/v0.14.25...v0.14.26) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea9d5af5..1ef0b45b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1468,9 +1468,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.11" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e" +checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" dependencies = [ "bytes", "fnv", @@ -1481,7 +1481,7 @@ dependencies = [ "indexmap", "slab", "tokio", - "tokio-util 0.6.9", + "tokio-util", "tracing", ] @@ -1638,9 +1638,9 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -3243,7 +3243,7 @@ dependencies = [ "tokio", "tokio-rustls 0.23.1", "tokio-socks", - "tokio-util 0.7.3", + "tokio-util", "tower-service", "url", "wasm-bindgen", @@ -4148,7 +4148,7 @@ dependencies = [ "tokio-socks", "tokio-tar", "tokio-tungstenite", - "tokio-util 0.7.3", + "tokio-util", "toml", "torut", "tracing", @@ -4458,20 +4458,6 @@ dependencies = [ "webpki-roots 0.21.0", ] -[[package]] -name = "tokio-util" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "log", - "pin-project-lite 0.2.9", - "tokio", -] - [[package]] name = "tokio-util" version = "0.7.3" From 4c8d5aecb74ff2e18618ed4729d79454340e4e70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:58:44 +0000 Subject: [PATCH 062/395] build(deps): bump rust_decimal_macros from 1.29.0 to 1.29.1 Bumps [rust_decimal_macros](https://github.com/paupino/rust-decimal) from 1.29.0 to 1.29.1. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/commits) --- updated-dependencies: - dependency-name: rust_decimal_macros dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ea9d5af5..edbbbbe6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3324,9 +3324,9 @@ dependencies = [ [[package]] name = "rust_decimal_macros" -version = "1.29.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4709403426683ccd5e1ef02b24a2468fe87f8df8a2a792743bb369d7656efa" +checksum = "0e773fd3da1ed42472fdf3cfdb4972948a555bc3d73f5e0bdb99d17e7b54c687" dependencies = [ "quote", "rust_decimal", From 64461dec93f5f4ec7553b89f61be6dd614519122 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 12:00:28 +0000 Subject: [PATCH 063/395] build(deps): bump conquer-once from 0.3.2 to 0.4.0 Bumps [conquer-once](https://github.com/oliver-giersch/conquer-once) from 0.3.2 to 0.4.0. - [Release notes](https://github.com/oliver-giersch/conquer-once/releases) - [Changelog](https://github.com/oliver-giersch/conquer-once/blob/master/RELEASES.md) - [Commits](https://github.com/oliver-giersch/conquer-once/compare/v0.3.2...v0.4.0) --- updated-dependencies: - dependency-name: conquer-once dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a3fa3bd..097d16c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -657,9 +657,9 @@ dependencies = [ [[package]] name = "conquer-once" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c6d3a9775a69f6d1fe2cc888999b67ed30257d3da4d2af91984e722f2ec918a" +checksum = "5d008a441c0f269f36ca13712528069a86a3e60dffee1d98b976eb3b0b2160b4" dependencies = [ "conquer-util", ] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 283aeb77..f689038e 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -21,7 +21,7 @@ bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bmrng = "0.5" comfy-table = "6.1" config = { version = "0.13", default-features = false, features = [ "toml" ] } -conquer-once = "0.3" +conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } data-encoding = "2.3" dialoguer = "0.10" From af7fbc708dc99b3d37aedc6d56b05966dbcdc29e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 12:00:43 +0000 Subject: [PATCH 064/395] build(deps): bump serial_test from 1.0.0 to 2.0.0 Bumps [serial_test](https://github.com/palfrey/serial_test) from 1.0.0 to 2.0.0. - [Release notes](https://github.com/palfrey/serial_test/releases) - [Commits](https://github.com/palfrey/serial_test/compare/v1.0.0...v2.0.0) --- updated-dependencies: - dependency-name: serial_test dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 +++++----- swap/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a3fa3bd..274b1423 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3657,9 +3657,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "538c30747ae860d6fb88330addbbd3e0ddbe46d662d032855596d8a8ca260611" +checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" dependencies = [ "dashmap", "futures", @@ -3671,13 +3671,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "1.0.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "079a83df15f85d89a68d64ae1238f142f172b1fa915d0d76b26a7cba1b659a69" +checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.3", ] [[package]] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 283aeb77..bcc07dc0 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -81,7 +81,7 @@ monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" serde_cbor = "0.11" -serial_test = "1.0" +serial_test = "2.0" spectral = "0.6" tempfile = "3" testcontainers = "0.12" From acc3d8af3c5c8ef00a291e1f46f2288146527ea3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Apr 2023 12:01:10 +0000 Subject: [PATCH 065/395] build(deps): bump async-trait from 0.1.67 to 0.1.68 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.67 to 0.1.68. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.67...0.1.68) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0a3fa3bd..fb5c085d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -120,13 +120,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.67" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.3", + "syn 2.0.15", ] [[package]] @@ -2884,9 +2884,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -3607,7 +3607,7 @@ checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote", - "syn 2.0.3", + "syn 2.0.15", ] [[package]] @@ -4181,9 +4181,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.3" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8234ae35e70582bfa0f1fedffa6daa248e41dd045310b19800c4a36382c8f60" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote", @@ -4283,7 +4283,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.3", + "syn 2.0.15", ] [[package]] From 59c1de91ac74f977ba4cf71d3904923336034727 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 13:19:08 +0000 Subject: [PATCH 066/395] build(deps): bump futures from 0.3.27 to 0.3.28 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.27 to 0.3.28. - [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.27...0.3.28) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 862a3933..c99ba2f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1267,9 +1267,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -1282,9 +1282,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -1292,15 +1292,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -1321,19 +1321,19 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -1349,15 +1349,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-timer" @@ -1367,9 +1367,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -3677,7 +3677,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.3", + "syn 2.0.15", ] [[package]] From 96cbb375c75ea9ed433e585ef09807b5090595cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Apr 2023 11:58:04 +0000 Subject: [PATCH 067/395] build(deps): bump tracing from 0.1.37 to 0.1.38 Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.37 to 0.1.38. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.37...tracing-0.1.38) --- updated-dependencies: - dependency-name: tracing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c99ba2f7..db509ca4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4513,11 +4513,10 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite 0.2.9", "tracing-attributes", "tracing-core", @@ -4536,13 +4535,13 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] From f3fb3c26e1e21cb41440ef1621bbeee23e7ab403 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 12:03:22 +0000 Subject: [PATCH 068/395] build(deps): bump reqwest from 0.11.16 to 0.11.17 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.16 to 0.11.17. - [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.16...v0.11.17) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db509ca4..8d6f4035 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3220,9 +3220,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.16" +version = "0.11.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" dependencies = [ "base64 0.21.0", "bytes", From 0d39d52712fedccd5c1f734dbbcab21d6b9bd965 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 12:03:56 +0000 Subject: [PATCH 069/395] build(deps): bump uuid from 1.3.1 to 1.3.2 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.3.1 to 1.3.2. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.3.1...1.3.2) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db509ca4..86d950b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4825,9 +4825,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" +checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" dependencies = [ "getrandom 0.2.6", "serde", From 5b3ce51b4a2fafcb0d1b73444829c8035ca57a76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 May 2023 12:04:31 +0000 Subject: [PATCH 070/395] build(deps): bump anyhow from 1.0.70 to 1.0.71 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.70 to 1.0.71. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.70...1.0.71) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index db509ca4..bb0491cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -83,9 +83,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "arrayref" From 7f6f3af3f9bb7dfd126a0f6a7f35b2ece6ac2ce8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 May 2023 11:58:22 +0000 Subject: [PATCH 071/395] build(deps): bump serde from 1.0.160 to 1.0.162 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.160 to 1.0.162. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.160...1.0.162) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1bf8d16f..03f47547 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3572,9 +3572,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.160" +version = "1.0.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" dependencies = [ "serde_derive", ] @@ -3601,9 +3601,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.162" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" dependencies = [ "proc-macro2", "quote", From 4c774b3d9a3d621d9eeb9d320f0995740697c5d3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 May 2023 11:58:06 +0000 Subject: [PATCH 072/395] build(deps): bump serde from 1.0.162 to 1.0.163 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.162 to 1.0.163. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.162...v1.0.163) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03f47547..a4c3ccd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3572,9 +3572,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.162" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] @@ -3601,9 +3601,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.162" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", From 1148bdcd1c15ecbd00c9f01d3b119edc7b6db2ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 11:57:30 +0000 Subject: [PATCH 073/395] build(deps): bump Swatinem/rust-cache from 2.2.1 to 2.3.0 Bumps [Swatinem/rust-cache](https://github.com/Swatinem/rust-cache) from 2.2.1 to 2.3.0. - [Release notes](https://github.com/Swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/Swatinem/rust-cache/compare/v2.2.1...v2.3.0) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 05041a0d..1dfbbbe8 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3cb704a7..19e30ed6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.63 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - name: Check formatting uses: dprint/check@v2.2 @@ -37,7 +37,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - name: Build swap run: cargo build --bin swap @@ -51,7 +51,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -78,7 +78,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - uses: dtolnay/rust-toolchain@master with: @@ -118,7 +118,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - name: Build tests run: cargo build --tests --workspace --all-features @@ -155,7 +155,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.2.1 + - uses: Swatinem/rust-cache@v2.3.0 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From 65ee11501fec176192b8a56251fc7a88632c3114 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 May 2023 12:00:19 +0000 Subject: [PATCH 074/395] build(deps): bump uuid from 1.3.2 to 1.3.3 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.3.2 to 1.3.3. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.3.2...1.3.3) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4c3ccd4..3591d40e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4825,9 +4825,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dad5567ad0cf5b760e5665964bec1b47dfd077ba8a2544b513f3556d3d239a2" +checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" dependencies = [ "getrandom 0.2.6", "serde", From d1b95c8c5d6cd0e04d9d0fb5e06106ca1f2b5eb4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 May 2023 11:59:35 +0000 Subject: [PATCH 075/395] build(deps): bump reqwest from 0.11.17 to 0.11.18 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.17 to 0.11.18. - [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.17...v0.11.18) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 48 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3591d40e..86852b29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1668,15 +1668,15 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" dependencies = [ "http", "hyper", - "rustls 0.20.2", + "rustls 0.21.1", "tokio", - "tokio-rustls 0.23.1", + "tokio-rustls 0.24.0", ] [[package]] @@ -3220,9 +3220,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.17" +version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13293b639a097af28fc8a90f22add145a9c954e49d77da06263d58cf44d5fb91" +checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ "base64 0.21.0", "bytes", @@ -3241,13 +3241,13 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.9", - "rustls 0.20.2", + "rustls 0.21.1", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "tokio", - "tokio-rustls 0.23.1", + "tokio-rustls 0.24.0", "tokio-socks", "tokio-util", "tower-service", @@ -3398,6 +3398,18 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "rustls" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct 0.7.0", +] + [[package]] name = "rustls-native-certs" version = "0.5.0" @@ -3419,6 +3431,16 @@ dependencies = [ "base64 0.13.1", ] +[[package]] +name = "rustls-webpki" +version = "0.100.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.11" @@ -4409,6 +4431,16 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "tokio-rustls" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" +dependencies = [ + "rustls 0.21.1", + "tokio", +] + [[package]] name = "tokio-socks" version = "0.5.1" From fbce61c4218d0312d616f073a3aa2f557291b738 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 11:57:32 +0000 Subject: [PATCH 076/395] build(deps): bump Swatinem/rust-cache from 2.3.0 to 2.4.0 Bumps [Swatinem/rust-cache](https://github.com/Swatinem/rust-cache) from 2.3.0 to 2.4.0. - [Release notes](https://github.com/Swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/Swatinem/rust-cache/compare/v2.3.0...v2.4.0) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 1dfbbbe8..255d6ee0 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19e30ed6..26d2c2ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.63 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - name: Check formatting uses: dprint/check@v2.2 @@ -37,7 +37,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - name: Build swap run: cargo build --bin swap @@ -51,7 +51,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -78,7 +78,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - uses: dtolnay/rust-toolchain@master with: @@ -118,7 +118,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - name: Build tests run: cargo build --tests --workspace --all-features @@ -155,7 +155,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.2 - - uses: Swatinem/rust-cache@v2.3.0 + - uses: Swatinem/rust-cache@v2.4.0 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From 89e8731a7ae3175a00ff7e4a47bdd53a55876013 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 11:59:34 +0000 Subject: [PATCH 077/395] build(deps): bump data-encoding from 2.3.3 to 2.4.0 Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.3.3 to 2.4.0. - [Commits](https://github.com/ia0/data-encoding/commits/v2.4.0) --- updated-dependencies: - dependency-name: data-encoding dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86852b29..8d0708f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -953,9 +953,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d8666cb01533c39dde32bcbab8e227b4ed6679b2c925eba05feabea39508fb" +checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" [[package]] name = "derive_more" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 564b1071..73b9798d 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -23,7 +23,7 @@ comfy-table = "6.1" config = { version = "0.13", default-features = false, features = [ "toml" ] } conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } -data-encoding = "2.3" +data-encoding = "2.4" dialoguer = "0.10" directories-next = "2" ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] } From cb9978f52f416061666cde43ebae7ad1538a840f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 May 2023 12:00:26 +0000 Subject: [PATCH 078/395] build(deps): bump base64 from 0.21.0 to 0.21.1 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.0 to 0.21.1. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/commits) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 86852b29..40d36603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,9 +220,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" [[package]] name = "bdk" @@ -3224,7 +3224,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.0", + "base64 0.21.1", "bytes", "encoding_rs", "futures-core", @@ -4124,7 +4124,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.21.0", + "base64 0.21.1", "bdk", "big-bytes", "bitcoin", From 6c0d3007e5390da5767813d9ea76eb28ab0a2c0d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 May 2023 11:59:31 +0000 Subject: [PATCH 079/395] build(deps): bump proptest from 1.1.0 to 1.2.0 Bumps [proptest](https://github.com/proptest-rs/proptest) from 1.1.0 to 1.2.0. - [Release notes](https://github.com/proptest-rs/proptest/releases) - [Changelog](https://github.com/proptest-rs/proptest/blob/master/CHANGELOG.md) - [Commits](https://github.com/proptest-rs/proptest/compare/v1.1.0...v1.2.0) --- updated-dependencies: - dependency-name: proptest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d54d7cd4..39b254e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2893,16 +2893,15 @@ dependencies = [ [[package]] name = "proptest" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f1b898011ce9595050a68e60f90bad083ff2987a695a42357134c8381fba70" +checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" dependencies = [ "bit-set", "bitflags", "byteorder", "lazy_static", "num-traits", - "quick-error 2.0.0", "rand 0.8.3", "rand_chacha 0.3.1", "rand_xorshift", @@ -3001,12 +3000,6 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -[[package]] -name = "quick-error" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ac73b1112776fc109b2e61909bc46c7e1bf0d7f690ffb1676553acce16d5cda" - [[package]] name = "quicksink" version = "0.1.2" @@ -3267,7 +3260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" dependencies = [ "hostname", - "quick-error 1.2.3", + "quick-error", ] [[package]] @@ -3454,7 +3447,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" dependencies = [ "fnv", - "quick-error 1.2.3", + "quick-error", "tempfile", "wait-timeout", ] From 5e34dfc40e7a9ba98f793e6583807229fa506710 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 11:59:33 +0000 Subject: [PATCH 080/395] build(deps): bump base64 from 0.21.1 to 0.21.2 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.1 to 0.21.2. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.1...v0.21.2) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39b254e0..78ec8c13 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -220,9 +220,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.1" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bdk" @@ -3217,7 +3217,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.1", + "base64 0.21.2", "bytes", "encoding_rs", "futures-core", @@ -4117,7 +4117,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.21.1", + "base64 0.21.2", "bdk", "big-bytes", "bitcoin", From 491f18169507443755cdcba665a64e448ff1238a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 11:58:39 +0000 Subject: [PATCH 081/395] build(deps): bump url from 2.3.1 to 2.4.0 Bumps [url](https://github.com/servo/rust-url) from 2.3.1 to 2.4.0. - [Release notes](https://github.com/servo/rust-url/releases) - [Commits](https://github.com/servo/rust-url/compare/v2.3.1...v2.4.0) --- updated-dependencies: - dependency-name: url dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78ec8c13..3454401a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1242,9 +1242,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -1698,9 +1698,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2708,9 +2708,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" @@ -4756,12 +4756,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.4" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -dependencies = [ - "matches", -] +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" @@ -4771,9 +4768,9 @@ checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" [[package]] name = "unicode-normalization" -version = "0.1.17" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] @@ -4832,12 +4829,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", - "idna 0.3.0", + "idna 0.4.0", "percent-encoding", "serde", ] From e8981708ba1be7c7db06559d3ce97031a1ecc3c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jun 2023 11:58:08 +0000 Subject: [PATCH 082/395] build(deps): bump tempfile from 3.5.0 to 3.6.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.5.0 to 3.6.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.5.0...v3.6.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 79 +++++------------------------------------------------- 1 file changed, 7 insertions(+), 72 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3454401a..a4c7fbca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4219,15 +4219,16 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -5129,37 +5130,13 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.1", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.1", - "windows_aarch64_msvc 0.42.1", - "windows_i686_gnu 0.42.1", - "windows_i686_msvc 0.42.1", - "windows_x86_64_gnu 0.42.1", - "windows_x86_64_gnullvm 0.42.1", - "windows_x86_64_msvc 0.42.1", + "windows-targets", ] [[package]] @@ -5168,21 +5145,15 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_gnullvm", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_gnullvm", "windows_x86_64_msvc 0.48.0", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" @@ -5201,12 +5172,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -5225,12 +5190,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" -[[package]] -name = "windows_i686_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" - [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -5249,12 +5208,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" -[[package]] -name = "windows_i686_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" - [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -5273,24 +5226,12 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" @@ -5309,12 +5250,6 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" From 2577710f0d57f47969c88a6423a6925c678cd8e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Jun 2023 12:01:09 +0000 Subject: [PATCH 083/395] build(deps): bump serde from 1.0.163 to 1.0.164 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.163 to 1.0.164. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.163...v1.0.164) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4c7fbca..913673b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3587,9 +3587,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] @@ -3616,9 +3616,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", From bb8d8fbd8aa75e10017e7fafc32391ef2283ed25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:57:21 +0000 Subject: [PATCH 084/395] build(deps): bump actions/checkout from 3.5.2 to 3.5.3 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.2...v3.5.3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 255d6ee0..b2545986 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 26d2c2ee..4a8ade9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - uses: Swatinem/rust-cache@v2.4.0 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - uses: Swatinem/rust-cache@v2.4.0 @@ -76,7 +76,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - uses: Swatinem/rust-cache@v2.4.0 @@ -116,7 +116,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - uses: Swatinem/rust-cache@v2.4.0 @@ -153,7 +153,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.2 + uses: actions/checkout@v3.5.3 - uses: Swatinem/rust-cache@v2.4.0 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 4d9149b0..f3bee225 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.2 + - uses: actions/checkout@v3.5.3 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index b7b9298b..8d7c797a 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.2 + - uses: actions/checkout@v3.5.3 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 19f31c37..37e04333 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.2 + - uses: actions/checkout@v3.5.3 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From fad91d15badeb31a2e9ea878764cae376f1b3308 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Jun 2023 11:58:30 +0000 Subject: [PATCH 085/395] build(deps): bump rust_decimal from 1.29.1 to 1.30.0 Bumps [rust_decimal](https://github.com/paupino/rust-decimal) from 1.29.1 to 1.30.0. - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/commits) --- updated-dependencies: - dependency-name: rust_decimal dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 913673b1..44c25521 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3305,9 +3305,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.29.1" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26bd36b60561ee1fb5ec2817f198b6fd09fa571c897a5e86d1487cfc2b096dfc" +checksum = "d0446843641c69436765a35a5a77088e28c2e6a12da93e84aa3ab1cd4aa5a042" dependencies = [ "arrayvec", "borsh", From acdba8474bf52787ef4bfd02e6fd7017ba4ca0e4 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 31 Jul 2023 10:32:15 +0200 Subject: [PATCH 086/395] build(deps): update rust-toolchain to 1.67 and bump uuid to 1.4 some of the dependency updates are requiring a higher version of the rust toolchain. bump to 1.67 and fix new clippy lints. also fix dprint to 0.39.1 because 0.40 has breaking changes. --- .github/workflows/ci.yml | 6 +++-- Cargo.lock | 37 ++++++++++++++++++------------- README.md | 2 +- monero-harness/src/lib.rs | 2 +- monero-rpc/src/monerod.rs | 2 +- rust-toolchain.toml | 2 +- swap/Cargo.toml | 2 +- swap/src/bitcoin/wallet.rs | 9 +++++--- swap/src/network/test.rs | 2 +- swap/src/seed.rs | 2 +- swap/tests/ensure_same_swap_id.rs | 2 +- swap/tests/harness/mod.rs | 2 +- 12 files changed, 41 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a8ade9d..7788a9bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,13 +17,15 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.63 + toolchain: 1.67 components: clippy,rustfmt - uses: Swatinem/rust-cache@v2.4.0 - name: Check formatting uses: dprint/check@v2.2 + with: + dprint-version: 0.39.1 - name: Run clippy with default features run: cargo clippy --workspace --all-targets -- -D warnings @@ -82,7 +84,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.63 + toolchain: 1.67 targets: armv7-unknown-linux-gnueabihf - name: Build binary diff --git a/Cargo.lock b/Cargo.lock index 913673b1..1e5d878a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -423,7 +423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "822462c1e7b17b31961798a6874b36daea6818e99e0cb7d3b7b0fa3c477751c3" dependencies = [ "borsh-derive", - "hashbrown 0.12.3", + "hashbrown 0.11.2", ] [[package]] @@ -957,6 +957,12 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +[[package]] +name = "deranged" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8810e7e2cf385b1e9b50d68264908ec367ba642c96d02edfe61c39e88e2a3c01" + [[package]] name = "derive_more" version = "0.99.16" @@ -3305,9 +3311,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.29.1" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26bd36b60561ee1fb5ec2817f198b6fd09fa571c897a5e86d1487cfc2b096dfc" +checksum = "d0446843641c69436765a35a5a77088e28c2e6a12da93e84aa3ab1cd4aa5a042" dependencies = [ "arrayvec", "borsh", @@ -4164,7 +4170,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.20", + "time 0.3.24", "tokio", "tokio-socks", "tokio-tar", @@ -4323,10 +4329,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.20" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "b79eabcd964882a646b3584543ccabeae7869e9ac32a46f6f22b7a5bd405308b" dependencies = [ + "deranged", "itoa 1.0.1", "serde", "time-core", @@ -4335,15 +4342,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" dependencies = [ "time-core", ] @@ -4555,7 +4562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", - "time 0.3.20", + "time 0.3.24", "tracing-subscriber 0.3.15", ] @@ -4645,7 +4652,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.20", + "time 0.3.24", "tracing", "tracing-core", "tracing-log", @@ -4848,9 +4855,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.3.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ "getrandom 0.2.6", "serde", @@ -4887,7 +4894,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.20", + "time 0.3.24", ] [[package]] diff --git a/README.md b/README.md index bae39780..7cbccc5a 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ 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.63 _should_ work. +All stable toolchains since 1.67 _should_ work. ## Contact diff --git a/monero-harness/src/lib.rs b/monero-harness/src/lib.rs index f762d5c5..46a03002 100644 --- a/monero-harness/src/lib.rs +++ b/monero-harness/src/lib.rs @@ -249,7 +249,7 @@ impl<'c> Monerod { /// address pub async fn start_miner(&self, miner_wallet_address: &str) -> Result<()> { let monerod = self.client().clone(); - let _ = tokio::spawn(mine(monerod, miner_wallet_address.to_string())); + tokio::spawn(mine(monerod, miner_wallet_address.to_string())); Ok(()) } } diff --git a/monero-rpc/src/monerod.rs b/monero-rpc/src/monerod.rs index c2cde67c..debb999f 100644 --- a/monero-rpc/src/monerod.rs +++ b/monero-rpc/src/monerod.rs @@ -195,7 +195,7 @@ mod monero_serde_hex_block { { let hex = String::deserialize(deserializer)?; - let bytes = hex::decode(&hex).map_err(D::Error::custom)?; + let bytes = hex::decode(hex).map_err(D::Error::custom)?; let mut cursor = Cursor::new(bytes); let block = monero::Block::consensus_decode(&mut cursor).map_err(D::Error::custom)?; diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8e45b7f1..d6b509dd 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.63" # also update this in the readme, changelog, and github actions +channel = "1.67" # also update this in the readme, changelog, and github actions components = ["clippy"] targets = ["armv7-unknown-linux-gnueabihf"] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 73b9798d..7d0e1141 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -64,7 +64,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.3", features = [ "serde", "v4" ] } +uuid = { version = "1.4", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index cf1530d1..9a8500b6 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -54,7 +54,7 @@ impl Wallet { ) -> Result { let data_dir = data_dir.as_ref(); let wallet_dir = data_dir.join(WALLET); - let database = bdk::sled::open(&wallet_dir)?.open_tree(SLED_TREE_NAME)?; + let database = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?; let network = env_config.bitcoin_network; let wallet = match bdk::Wallet::new( @@ -97,7 +97,7 @@ impl Wallet { std::fs::rename(from, to)?; let wallet_dir = data_dir.join(WALLET); - let database = bdk::sled::open(&wallet_dir)?.open_tree(SLED_TREE_NAME)?; + let database = bdk::sled::open(wallet_dir)?.open_tree(SLED_TREE_NAME)?; let wallet = bdk::Wallet::new( bdk::template::Bip84(xprivkey, KeychainKind::External), @@ -738,12 +738,15 @@ impl Client { let client = bdk::electrum_client::Client::new(electrum_rpc_url.as_str()) .context("Failed to initialize Electrum RPC client")?; let blockchain = ElectrumBlockchain::from(client); + let last_sync = Instant::now() + .checked_sub(interval) + .expect("no underflow since block time is only 600 secs"); Ok(Self { electrum, blockchain, latest_block_height: BlockHeight::try_from(latest_block)?, - last_sync: Instant::now() - interval, + last_sync, sync_interval: interval, script_history: Default::default(), subscriptions: Default::default(), diff --git a/swap/src/network/test.rs b/swap/src/network/test.rs index da5bac77..a5c316b1 100644 --- a/swap/src/network/test.rs +++ b/swap/src/network/test.rs @@ -21,7 +21,7 @@ struct GlobalSpawnTokioExecutor; impl Executor for GlobalSpawnTokioExecutor { fn exec(&self, future: Pin + Send>>) { - let _ = tokio::spawn(future); + tokio::spawn(future); } } diff --git a/swap/src/seed.rs b/swap/src/seed.rs index 2230ccef..f89215b9 100644 --- a/swap/src/seed.rs +++ b/swap/src/seed.rs @@ -61,7 +61,7 @@ impl Seed { let file_path = Path::new(&file_path_buf); if file_path.exists() { - return Self::from_file(&file_path); + return Self::from_file(file_path); } tracing::debug!("No seed file found, creating at {}", file_path.display()); diff --git a/swap/tests/ensure_same_swap_id.rs b/swap/tests/ensure_same_swap_id.rs index 48758ecd..28f09823 100644 --- a/swap/tests/ensure_same_swap_id.rs +++ b/swap/tests/ensure_same_swap_id.rs @@ -8,7 +8,7 @@ async fn ensure_same_swap_id_for_alice_and_bob() { harness::setup_test(SlowCancelConfig, |mut ctx| async move { let (bob_swap, _) = ctx.bob_swap().await; let bob_swap_id = bob_swap.id; - let _ = tokio::spawn(bob::run(bob_swap)); + tokio::spawn(bob::run(bob_swap)); // once Bob's swap is spawned we can retrieve Alice's swap and assert on the // swap ID diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index e10ce19e..0c896055 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -928,7 +928,7 @@ async fn init_bitcoind(node_url: Url, spendable_quantity: u32) -> Result bitcoind_client .generatetoaddress(101 + spendable_quantity, reward_address.clone()) .await?; - let _ = tokio::spawn(mine(bitcoind_client.clone(), reward_address)); + tokio::spawn(mine(bitcoind_client.clone(), reward_address)); Ok(bitcoind_client) } From 5dee0896ff626b12043f0fca1b5e415972ab9af3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:09:36 +0000 Subject: [PATCH 087/395] build(deps): bump thomaseizinger/create-pull-request from 1.3.0 to 1.3.1 Bumps [thomaseizinger/create-pull-request](https://github.com/thomaseizinger/create-pull-request) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/thomaseizinger/create-pull-request/releases) - [Changelog](https://github.com/thomaseizinger/create-pull-request/blob/master/CHANGELOG.md) - [Commits](https://github.com/thomaseizinger/create-pull-request/compare/1.3.0...1.3.1) --- updated-dependencies: - dependency-name: thomaseizinger/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/draft-new-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 8d7c797a..338ff7c5 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -54,7 +54,7 @@ jobs: run: git push origin release/${{ github.event.inputs.version }} --force - name: Create pull request - uses: thomaseizinger/create-pull-request@1.3.0 + uses: thomaseizinger/create-pull-request@1.3.1 with: GITHUB_TOKEN: ${{ secrets.BOTTY_GITHUB_TOKEN }} head: release/${{ github.event.inputs.version }} From 5207d10d08bc1b6169b18e9730ef9a329037fc8e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Aug 2023 09:23:52 +0000 Subject: [PATCH 088/395] build(deps): bump Swatinem/rust-cache from 2.4.0 to 2.5.1 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.4.0 to 2.5.1. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.4.0...v2.5.1) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index b2545986..5ad8c862 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7788a9bb..3e178078 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.67 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - name: Check formatting uses: dprint/check@v2.2 @@ -39,7 +39,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - name: Build swap run: cargo build --bin swap @@ -53,7 +53,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -80,7 +80,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - uses: dtolnay/rust-toolchain@master with: @@ -120,7 +120,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - name: Build tests run: cargo build --tests --workspace --all-features @@ -157,7 +157,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.4.0 + - uses: Swatinem/rust-cache@v2.5.1 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From 3d744a3470ab548e153f85fd980b98c9328a4320 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:48:03 +0000 Subject: [PATCH 089/395] build(deps): bump Swatinem/rust-cache from 2.5.1 to 2.6.0 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.5.1 to 2.6.0. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.5.1...v2.6.0) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 5ad8c862..8e842a00 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3e178078..055e61b5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.67 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - name: Check formatting uses: dprint/check@v2.2 @@ -39,7 +39,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - name: Build swap run: cargo build --bin swap @@ -53,7 +53,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -80,7 +80,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - uses: dtolnay/rust-toolchain@master with: @@ -120,7 +120,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - name: Build tests run: cargo build --tests --workspace --all-features @@ -157,7 +157,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.5.1 + - uses: Swatinem/rust-cache@v2.6.0 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From 5e192acac29b67c15e9366ea88cc2d96434c4546 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 1 Aug 2023 15:42:10 +0200 Subject: [PATCH 090/395] feat(asb): allow asb to register with mulitple rendezvous nodes --- CHANGELOG.md | 3 +- docs/asb/README.md | 7 +- swap/src/asb.rs | 3 +- swap/src/asb/config.rs | 45 +++-- swap/src/asb/event_loop.rs | 4 +- swap/src/asb/network.rs | 332 ++++++++++++++++++++++++------------- swap/src/bin/asb.rs | 15 +- swap/src/cli.rs | 35 ++-- swap/src/network/swarm.rs | 25 +-- swap/tests/harness/mod.rs | 2 +- 10 files changed, 300 insertions(+), 171 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51a1b67a..16f4730b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed -- Minimum Supported Rust Version (MSRV) bumped to 1.63 +- Minimum Supported Rust Version (MSRV) bumped to 1.67 +- ASB can now register with multiple rendezvous nodes. The `rendezvous_point` option in `config.toml` can be a string with comma separated addresses, or a toml array of address strings. ## [0.12.1] - 2023-01-09 diff --git a/docs/asb/README.md b/docs/asb/README.md index e0991d8d..1c924252 100644 --- a/docs/asb/README.md +++ b/docs/asb/README.md @@ -42,13 +42,16 @@ Since the ASB is a long running task we specify the person running an ASB as ser The ASB daemon supports the libp2p [rendezvous-protocol](https://github.com/libp2p/specs/tree/master/rendezvous). Usage of the rendezvous functionality is entirely optional. -You can configure a rendezvous point in the `[network]` section of your config file. +You can configure one or more rendezvous point in the `[network]` section of your config file. For the registration to be successful, you also need to configure the externally reachable addresses within the `[network]` section. For example: ```toml [network] -rendezvous_point = "/dns4/discover.unstoppableswap.net/tcp/8888/p2p/12D3KooWA6cnqJpVnreBVnoro8midDL9Lpzmg8oJPoAGi7YYaamE" +rendezvous_point = [ + "/dns4/discover.unstoppableswap.net/tcp/8888/p2p/12D3KooWA6cnqJpVnreBVnoro8midDL9Lpzmg8oJPoAGi7YYaamE", + "/dns4/eratosthen.es/tcp/7798/p2p/12D3KooWAh7EXXa2ZyegzLGdjvj1W4G3EXrTGrf6trraoT1MEobs", +] external_addresses = ["/dns4/example.com/tcp/9939"] ``` diff --git a/swap/src/asb.rs b/swap/src/asb.rs index fccd2f8b..b5ed8ac1 100644 --- a/swap/src/asb.rs +++ b/swap/src/asb.rs @@ -8,6 +8,7 @@ pub mod tracing; pub use event_loop::{EventLoop, EventLoopHandle, FixedRate, KrakenRate, LatestRate}; pub use network::behaviour::{Behaviour, OutEvent}; +pub use network::rendezvous::RendezvousNode; pub use network::transport; pub use rate::Rate; pub use recovery::cancel::cancel; @@ -18,4 +19,4 @@ pub use recovery::safely_abort::safely_abort; pub use recovery::{cancel, refund}; #[cfg(test)] -pub use network::rendezous; +pub use network::rendezvous; diff --git a/swap/src/asb/config.rs b/swap/src/asb/config.rs index 7e8492ec..ac651c71 100644 --- a/swap/src/asb/config.rs +++ b/swap/src/asb/config.rs @@ -134,8 +134,8 @@ pub struct Data { pub struct Network { #[serde(deserialize_with = "addr_list::deserialize")] pub listen: Vec, - #[serde(default)] - pub rendezvous_point: Option, + #[serde(default, deserialize_with = "addr_list::deserialize")] + pub rendezvous_point: Vec, #[serde(default, deserialize_with = "addr_list::deserialize")] pub external_addresses: Vec, } @@ -156,7 +156,7 @@ mod addr_list { let list: Result, _> = s .split(',') .filter(|s| !s.is_empty()) - .map(|s| s.parse().map_err(de::Error::custom)) + .map(|s| s.trim().parse().map_err(de::Error::custom)) .collect(); Ok(list?) } @@ -165,7 +165,7 @@ mod addr_list { .iter() .map(|v| { if let Value::String(s) = v { - s.parse().map_err(de::Error::custom) + s.trim().parse().map_err(de::Error::custom) } else { Err(de::Error::custom("expected a string")) } @@ -347,10 +347,27 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result { } let ask_spread = Decimal::from_f64(ask_spread).context("Unable to parse spread")?; - let rendezvous_point = Input::::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you want to advertise your ASB instance with a rendezvous node? Enter an empty string if not.") - .allow_empty(true) - .interact_text()?; + let mut number = 1; + let mut done = false; + let mut rendezvous_points = Vec::new(); + println!("ASB can register with multiple rendezvous nodes for discoverability. This can also be edited in the config file later."); + while !done { + let prompt = format!( + "Enter the address for rendezvous node ({number}). Or just hit Enter to continue." + ); + let rendezvous_addr = Input::::with_theme(&ColorfulTheme::default()) + .with_prompt(prompt) + .allow_empty(true) + .interact_text()?; + if rendezvous_addr.is_empty() { + done = true; + } else if rendezvous_points.contains(&rendezvous_addr) { + println!("That rendezvous address is already in the list."); + } else { + rendezvous_points.push(rendezvous_addr); + number += 1; + } + } println!(); @@ -358,11 +375,7 @@ pub fn query_user_for_initial_config(testnet: bool) -> Result { data: Data { dir: data_dir }, network: Network { listen: listen_addresses, - rendezvous_point: if rendezvous_point.is_empty() { - None - } else { - Some(rendezvous_point) - }, + rendezvous_point: rendezvous_points, // keeping the singular key name for backcompat external_addresses: vec![], }, bitcoin: Bitcoin { @@ -417,7 +430,7 @@ mod tests { }, network: Network { listen: vec![defaults.listen_address_tcp, defaults.listen_address_ws], - rendezvous_point: None, + rendezvous_point: vec![], external_addresses: vec![], }, monero: Monero { @@ -461,7 +474,7 @@ mod tests { }, network: Network { listen: vec![defaults.listen_address_tcp, defaults.listen_address_ws], - rendezvous_point: None, + rendezvous_point: vec![], external_addresses: vec![], }, monero: Monero { @@ -515,7 +528,7 @@ mod tests { }, network: Network { listen, - rendezvous_point: None, + rendezvous_point: vec![], external_addresses, }, monero: Monero { diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index 130494bc..4083f130 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -253,8 +253,8 @@ where channel }.boxed()); } - SwarmEvent::Behaviour(OutEvent::Rendezvous(libp2p::rendezvous::client::Event::Registered { .. })) => { - tracing::info!("Successfully registered with rendezvous node"); + SwarmEvent::Behaviour(OutEvent::Rendezvous(libp2p::rendezvous::client::Event::Registered { rendezvous_node, ttl, namespace })) => { + tracing::info!("Successfully registered with rendezvous node: {} with namespace: {} and TTL: {:?}", rendezvous_node, namespace, ttl); } SwarmEvent::Behaviour(OutEvent::Rendezvous(libp2p::rendezvous::client::Event::RegisterFailed(error))) => { tracing::error!("Registration with rendezvous node failed: {:?}", error); diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index 41b62c31..181ec9bc 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -44,7 +44,9 @@ pub mod transport { } pub mod behaviour { - use super::*; + use libp2p::swarm::behaviour::toggle::Toggle; + + use super::{rendezvous::RendezvousNode, *}; #[allow(clippy::large_enum_variant)] #[derive(Debug)] @@ -108,7 +110,7 @@ pub mod behaviour { where LR: LatestRate + Send + 'static, { - pub rendezvous: libp2p::swarm::behaviour::toggle::Toggle, + pub rendezvous: Toggle, pub quote: quote::Behaviour, pub swap_setup: alice::Behaviour, pub transfer_proof: transfer_proof::Behaviour, @@ -132,25 +134,22 @@ pub mod behaviour { resume_only: bool, env_config: env::Config, identify_params: (identity::Keypair, XmrBtcNamespace), - rendezvous_params: Option<(identity::Keypair, PeerId, Multiaddr, XmrBtcNamespace)>, + rendezvous_nodes: Vec, ) -> Self { - let agentVersion = format!("asb/{} ({})", env!("CARGO_PKG_VERSION"), identify_params.1); - let protocolVersion = "/comit/xmr/btc/1.0.0".to_string(); - let identifyConfig = IdentifyConfig::new(protocolVersion, identify_params.0.public()) - .with_agent_version(agentVersion); + let (identity, namespace) = identify_params; + let agent_version = format!("asb/{} ({})", env!("CARGO_PKG_VERSION"), namespace); + let protocol_version = "/comit/xmr/btc/1.0.0".to_string(); + let identifyConfig = IdentifyConfig::new(protocol_version, identity.public()) + .with_agent_version(agent_version); + + let behaviour = if rendezvous_nodes.is_empty() { + None + } else { + Some(rendezvous::Behaviour::new(identity, rendezvous_nodes)) + }; Self { - rendezvous: libp2p::swarm::behaviour::toggle::Toggle::from(rendezvous_params.map( - |(identity, rendezvous_peer_id, rendezvous_address, namespace)| { - rendezous::Behaviour::new( - identity, - rendezvous_peer_id, - rendezvous_address, - namespace, - None, // use default ttl on rendezvous point - ) - }, - )), + rendezvous: Toggle::from(behaviour), quote: quote::asb(), swap_setup: alice::Behaviour::new( min_buy, @@ -186,13 +185,14 @@ pub mod behaviour { } } -pub mod rendezous { +pub mod rendezvous { use super::*; use libp2p::swarm::dial_opts::DialOpts; use libp2p::swarm::DialError; + use std::collections::VecDeque; use std::pin::Pin; - #[derive(PartialEq)] + #[derive(Clone, PartialEq)] enum ConnectionStatus { Disconnected, Dialling, @@ -209,39 +209,59 @@ pub mod rendezous { pub struct Behaviour { inner: libp2p::rendezvous::client::Behaviour, - rendezvous_point: Multiaddr, - rendezvous_peer_id: PeerId, - namespace: XmrBtcNamespace, - registration_status: RegistrationStatus, - connection_status: ConnectionStatus, - registration_ttl: Option, + rendezvous_nodes: Vec, + to_dial: VecDeque, } - impl Behaviour { + pub struct RendezvousNode { + pub address: Multiaddr, + connection_status: ConnectionStatus, + pub peer_id: PeerId, + registration_status: RegistrationStatus, + pub registration_ttl: Option, + pub namespace: XmrBtcNamespace, + } + + impl RendezvousNode { pub fn new( - identity: identity::Keypair, - rendezvous_peer_id: PeerId, - rendezvous_address: Multiaddr, + address: &Multiaddr, + peer_id: PeerId, namespace: XmrBtcNamespace, registration_ttl: Option, ) -> Self { Self { - inner: libp2p::rendezvous::client::Behaviour::new(identity), - rendezvous_point: rendezvous_address, - rendezvous_peer_id, - namespace, - registration_status: RegistrationStatus::RegisterOnNextConnection, + address: address.to_owned(), connection_status: ConnectionStatus::Disconnected, + namespace, + peer_id, + registration_status: RegistrationStatus::RegisterOnNextConnection, registration_ttl, } } - fn register(&mut self) { - self.inner.register( - self.namespace.into(), - self.rendezvous_peer_id, - self.registration_ttl, - ); + fn set_connection(&mut self, status: ConnectionStatus) { + self.connection_status = status; + } + + fn set_registration(&mut self, status: RegistrationStatus) { + self.registration_status = status; + } + } + + impl Behaviour { + pub fn new(identity: identity::Keypair, rendezvous_nodes: Vec) -> Self { + Self { + inner: libp2p::rendezvous::client::Behaviour::new(identity), + rendezvous_nodes, + to_dial: VecDeque::new(), + } + } + + /// Calls the rendezvous register method of the node at node_index in the Vec of rendezvous nodes + fn register(&mut self, node_index: usize) { + let node = &self.rendezvous_nodes[node_index]; + self.inner + .register(node.namespace.into(), node.peer_id, node.registration_ttl); } } @@ -255,31 +275,37 @@ pub mod rendezous { } fn addresses_of_peer(&mut self, peer_id: &PeerId) -> Vec { - if peer_id == &self.rendezvous_peer_id { - return vec![self.rendezvous_point.clone()]; + for node in self.rendezvous_nodes.iter() { + if peer_id == &node.peer_id { + return vec![node.address.clone()]; + } } vec![] } fn inject_connected(&mut self, peer_id: &PeerId) { - if peer_id == &self.rendezvous_peer_id { - self.connection_status = ConnectionStatus::Connected; - - match &self.registration_status { - RegistrationStatus::RegisterOnNextConnection => { - self.register(); - self.registration_status = RegistrationStatus::Pending; + for i in 0..self.rendezvous_nodes.len() { + if peer_id == &self.rendezvous_nodes[i].peer_id { + self.rendezvous_nodes[i].set_connection(ConnectionStatus::Connected); + match &self.rendezvous_nodes[i].registration_status { + RegistrationStatus::RegisterOnNextConnection => { + self.register(i); + self.rendezvous_nodes[i].set_registration(RegistrationStatus::Pending); + } + RegistrationStatus::Registered { .. } => {} + RegistrationStatus::Pending => {} } - RegistrationStatus::Registered { .. } => {} - RegistrationStatus::Pending => {} } } } fn inject_disconnected(&mut self, peer_id: &PeerId) { - if peer_id == &self.rendezvous_peer_id { - self.connection_status = ConnectionStatus::Disconnected; + for i in 0..self.rendezvous_nodes.len() { + let mut node = &mut self.rendezvous_nodes[i]; + if peer_id == &node.peer_id { + node.connection_status = ConnectionStatus::Disconnected; + } } } @@ -298,9 +324,12 @@ pub mod rendezous { _handler: Self::ProtocolsHandler, _error: &DialError, ) { - if let Some(id) = peer_id { - if id == self.rendezvous_peer_id { - self.connection_status = ConnectionStatus::Disconnected; + for i in 0..self.rendezvous_nodes.len() { + let mut node = &mut self.rendezvous_nodes[i]; + if let Some(id) = peer_id { + if id == node.peer_id { + node.connection_status = ConnectionStatus::Disconnected; + } } } } @@ -311,62 +340,73 @@ pub mod rendezous { cx: &mut std::task::Context<'_>, params: &mut impl PollParameters, ) -> Poll> { - match &mut self.registration_status { - RegistrationStatus::RegisterOnNextConnection => match self.connection_status { - ConnectionStatus::Disconnected => { - self.connection_status = ConnectionStatus::Dialling; + if let Some(peer_id) = self.to_dial.pop_front() { + return Poll::Ready(NetworkBehaviourAction::Dial { + opts: DialOpts::peer_id(peer_id) + .condition(PeerCondition::Disconnected) + .build(), - return Poll::Ready(NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(self.rendezvous_peer_id) - .condition(PeerCondition::Disconnected) - .build(), - - handler: Self::ProtocolsHandler::new(Duration::from_secs(30)), - }); - } - ConnectionStatus::Dialling => {} - ConnectionStatus::Connected => { - self.registration_status = RegistrationStatus::Pending; - self.register(); - } - }, - RegistrationStatus::Registered { re_register_in } => { - if let Poll::Ready(()) = re_register_in.poll_unpin(cx) { - match self.connection_status { - ConnectionStatus::Connected => { - self.registration_status = RegistrationStatus::Pending; - self.register(); + handler: Self::ProtocolsHandler::new(Duration::from_secs(30)), + }); + } + // check the status of each rendezvous node + for i in 0..self.rendezvous_nodes.len() { + let connection_status = self.rendezvous_nodes[i].connection_status.clone(); + match &mut self.rendezvous_nodes[i].registration_status { + RegistrationStatus::RegisterOnNextConnection => match connection_status { + ConnectionStatus::Disconnected => { + self.rendezvous_nodes[i].set_connection(ConnectionStatus::Dialling); + self.to_dial.push_back(self.rendezvous_nodes[i].peer_id); + } + ConnectionStatus::Dialling => {} + ConnectionStatus::Connected => { + self.rendezvous_nodes[i].set_registration(RegistrationStatus::Pending); + self.register(i); + } + }, + RegistrationStatus::Registered { re_register_in } => { + if let Poll::Ready(()) = re_register_in.poll_unpin(cx) { + match connection_status { + ConnectionStatus::Connected => { + self.rendezvous_nodes[i] + .set_registration(RegistrationStatus::Pending); + self.register(i); + } + ConnectionStatus::Disconnected => { + self.rendezvous_nodes[i].set_registration( + RegistrationStatus::RegisterOnNextConnection, + ); + self.to_dial.push_back(self.rendezvous_nodes[i].peer_id); + } + ConnectionStatus::Dialling => {} } - ConnectionStatus::Disconnected => { - self.registration_status = - RegistrationStatus::RegisterOnNextConnection; - - return Poll::Ready(NetworkBehaviourAction::Dial { - opts: DialOpts::peer_id(self.rendezvous_peer_id) - .condition(PeerCondition::Disconnected) - .build(), - handler: Self::ProtocolsHandler::new(Duration::from_secs(30)), - }); - } - ConnectionStatus::Dialling => {} } } + RegistrationStatus::Pending => {} } - RegistrationStatus::Pending => {} } let inner_poll = self.inner.poll(cx, params); - // reset the timer if we successfully registered + // reset the timer for the specific rendezvous node if we successfully registered if let Poll::Ready(NetworkBehaviourAction::GenerateEvent( - libp2p::rendezvous::client::Event::Registered { ttl, .. }, + libp2p::rendezvous::client::Event::Registered { + ttl, + rendezvous_node, + .. + }, )) = &inner_poll { - let half_of_ttl = Duration::from_secs(*ttl) / 2; - - self.registration_status = RegistrationStatus::Registered { - re_register_in: Box::pin(tokio::time::sleep(half_of_ttl)), - }; + if let Some(i) = self + .rendezvous_nodes + .iter() + .position(|n| &n.peer_id == rendezvous_node) + { + let half_of_ttl = Duration::from_secs(*ttl) / 2; + let re_register_in = Box::pin(tokio::time::sleep(half_of_ttl)); + let status = RegistrationStatus::Registered { re_register_in }; + self.rendezvous_nodes[i].set_registration(status); + } } inner_poll @@ -380,6 +420,7 @@ pub mod rendezous { use futures::StreamExt; use libp2p::rendezvous; use libp2p::swarm::SwarmEvent; + use std::collections::HashMap; #[tokio::test] async fn given_no_initial_connection_when_constructed_asb_connects_and_registers_with_rendezvous_node( @@ -387,16 +428,16 @@ pub mod rendezous { let mut rendezvous_node = new_swarm(|_, _| { rendezvous::server::Behaviour::new(rendezvous::server::Config::default()) }); - let rendezvous_address = rendezvous_node.listen_on_random_memory_address().await; + let address = rendezvous_node.listen_on_random_memory_address().await; + let rendezvous_point = RendezvousNode::new( + &address, + rendezvous_node.local_peer_id().to_owned(), + XmrBtcNamespace::Testnet, + None, + ); let mut asb = new_swarm(|_, identity| { - rendezous::Behaviour::new( - identity, - *rendezvous_node.local_peer_id(), - rendezvous_address, - XmrBtcNamespace::Testnet, - None, - ) + super::rendezvous::Behaviour::new(identity, vec![rendezvous_point]) }); asb.listen_on_random_memory_address().await; // this adds an external address @@ -428,16 +469,16 @@ pub mod rendezous { rendezvous::server::Config::default().with_min_ttl(2), ) }); - let rendezvous_address = rendezvous_node.listen_on_random_memory_address().await; + let address = rendezvous_node.listen_on_random_memory_address().await; + let rendezvous_point = RendezvousNode::new( + &address, + rendezvous_node.local_peer_id().to_owned(), + XmrBtcNamespace::Testnet, + Some(5), + ); let mut asb = new_swarm(|_, identity| { - rendezous::Behaviour::new( - identity, - *rendezvous_node.local_peer_id(), - rendezvous_address, - XmrBtcNamespace::Testnet, - Some(5), - ) + super::rendezvous::Behaviour::new(identity, vec![rendezvous_point]) }); asb.listen_on_random_memory_address().await; // this adds an external address @@ -467,5 +508,62 @@ pub mod rendezous { .unwrap() .unwrap(); } + + #[tokio::test] + async fn asb_registers_multiple() { + let registration_ttl = Some(10); + let mut rendezvous_nodes = Vec::new(); + let mut registrations = HashMap::new(); + // register with 5 rendezvous nodes + for _ in 0..5 { + let mut rendezvous = new_swarm(|_, _| { + rendezvous::server::Behaviour::new( + rendezvous::server::Config::default().with_min_ttl(2), + ) + }); + let address = rendezvous.listen_on_random_memory_address().await; + let id = *rendezvous.local_peer_id(); + registrations.insert(id, 0); + rendezvous_nodes.push(RendezvousNode::new( + &address, + *rendezvous.local_peer_id(), + XmrBtcNamespace::Testnet, + registration_ttl, + )); + tokio::spawn(async move { + loop { + rendezvous.next().await; + } + }); + } + + let mut asb = new_swarm(|_, identity| { + super::rendezvous::Behaviour::new(identity, rendezvous_nodes) + }); + asb.listen_on_random_memory_address().await; // this adds an external address + + let handle = tokio::spawn(async move { + loop { + if let SwarmEvent::Behaviour(rendezvous::client::Event::Registered { + rendezvous_node, + .. + }) = asb.select_next_some().await + { + registrations + .entry(rendezvous_node) + .and_modify(|counter| *counter += 1); + } + + if registrations.iter().all(|(_, &count)| count >= 4) { + break; + } + } + }); + + tokio::time::timeout(Duration::from_secs(30), handle) + .await + .unwrap() + .unwrap(); + } } } diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index d05a0dbb..ff3b0e4c 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -102,6 +102,19 @@ async fn main() -> Result<()> { match cmd { Command::Start { resume_only } => { + // check and warn for duplicate rendezvous points + let mut rendezvous_addrs = config.network.rendezvous_point.clone(); + let prev_len = rendezvous_addrs.len(); + rendezvous_addrs.sort(); + rendezvous_addrs.dedup(); + let new_len = rendezvous_addrs.len(); + if new_len < prev_len { + tracing::warn!( + "`rendezvous_point` config has {} duplicate entries, they are being ignored.", + prev_len - new_len + ); + } + let monero_wallet = init_monero_wallet(&config, env_config).await?; let monero_address = monero_wallet.get_main_address(); tracing::info!(%monero_address, "Monero wallet address"); @@ -161,7 +174,7 @@ async fn main() -> Result<()> { resume_only, env_config, namespace, - config.network.rendezvous_point, + &rendezvous_addrs, )?; for listen in config.network.listen.clone() { diff --git a/swap/src/cli.rs b/swap/src/cli.rs index c98634d2..f0faf146 100644 --- a/swap/src/cli.rs +++ b/swap/src/cli.rs @@ -15,6 +15,7 @@ pub use list_sellers::{list_sellers, Seller, Status as SellerStatus}; mod tests { use super::*; use crate::asb; + use crate::asb::rendezvous::RendezvousNode; use crate::cli::list_sellers::{Seller, Status}; use crate::network::quote; use crate::network::quote::BidQuote; @@ -33,10 +34,8 @@ mod tests { async fn list_sellers_should_report_all_registered_asbs_with_a_quote() { let namespace = XmrBtcNamespace::Mainnet; let (rendezvous_address, rendezvous_peer_id) = setup_rendezvous_point().await; - let expected_seller_1 = - setup_asb(rendezvous_peer_id, rendezvous_address.clone(), namespace).await; - let expected_seller_2 = - setup_asb(rendezvous_peer_id, rendezvous_address.clone(), namespace).await; + let expected_seller_1 = setup_asb(rendezvous_peer_id, &rendezvous_address, namespace).await; + let expected_seller_2 = setup_asb(rendezvous_peer_id, &rendezvous_address, namespace).await; let list_sellers = list_sellers( rendezvous_peer_id, @@ -72,7 +71,7 @@ mod tests { async fn setup_asb( rendezvous_peer_id: PeerId, - rendezvous_address: Multiaddr, + rendezvous_address: &Multiaddr, namespace: XmrBtcNamespace, ) -> Seller { let static_quote = BidQuote { @@ -81,18 +80,18 @@ mod tests { max_quantity: bitcoin::Amount::from_sat(9001), }; - let mut asb = new_swarm(|_, identity| StaticQuoteAsbBehaviour { - rendezvous: asb::rendezous::Behaviour::new( - identity, - rendezvous_peer_id, - rendezvous_address, - namespace, - None, - ), - ping: Default::default(), - quote: quote::asb(), - static_quote, - registered: false, + let mut asb = new_swarm(|_, identity| { + let rendezvous_node = + RendezvousNode::new(rendezvous_address, rendezvous_peer_id, namespace, None); + let rendezvous = asb::rendezvous::Behaviour::new(identity, vec![rendezvous_node]); + + StaticQuoteAsbBehaviour { + rendezvous, + ping: Default::default(), + quote: quote::asb(), + static_quote, + registered: false, + } }); let asb_address = asb.listen_on_tcp_localhost().await; @@ -121,7 +120,7 @@ mod tests { #[derive(libp2p::NetworkBehaviour)] #[behaviour(event_process = true)] struct StaticQuoteAsbBehaviour { - rendezvous: asb::rendezous::Behaviour, + rendezvous: asb::rendezvous::Behaviour, // Support `Ping` as a workaround until https://github.com/libp2p/rust-libp2p/issues/2109 is fixed. ping: libp2p::ping::Ping, quote: quote::Behaviour, diff --git a/swap/src/network/swarm.rs b/swap/src/network/swarm.rs index 21bbfc4d..37bb0a5e 100644 --- a/swap/src/network/swarm.rs +++ b/swap/src/network/swarm.rs @@ -1,9 +1,9 @@ -use crate::asb::LatestRate; +use crate::asb::{LatestRate, RendezvousNode}; use crate::libp2p_ext::MultiAddrExt; use crate::network::rendezvous::XmrBtcNamespace; use crate::seed::Seed; use crate::{asb, bitcoin, cli, env, tor}; -use anyhow::{Context, Result}; +use anyhow::Result; use libp2p::swarm::{NetworkBehaviour, SwarmBuilder}; use libp2p::{identity, Multiaddr, Swarm}; use std::fmt::Debug; @@ -17,22 +17,23 @@ pub fn asb( resume_only: bool, env_config: env::Config, namespace: XmrBtcNamespace, - rendezvous_point: Option, + rendezvous_addrs: &[Multiaddr], ) -> Result>> where LR: LatestRate + Send + 'static + Debug + Clone, { let identity = seed.derive_libp2p_identity(); - let rendezvous_params = if let Some(address) = rendezvous_point { - let peer_id = address - .extract_peer_id() - .context("Rendezvous node address must contain peer ID")?; + let rendezvous_nodes = rendezvous_addrs + .iter() + .map(|addr| { + let peer_id = addr + .extract_peer_id() + .expect("Rendezvous node address must contain peer ID"); - Some((identity.clone(), peer_id, address, namespace)) - } else { - None - }; + RendezvousNode::new(addr, peer_id, namespace, None) + }) + .collect(); let behaviour = asb::Behaviour::new( min_buy, @@ -41,7 +42,7 @@ where resume_only, env_config, (identity.clone(), namespace), - rendezvous_params, + rendezvous_nodes, ); let transport = asb::transport::new(&identity)?; diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 0c896055..4f3f5fee 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -248,7 +248,7 @@ async fn start_alice( resume_only, env_config, XmrBtcNamespace::Testnet, - None, + &[], ) .unwrap(); swarm.listen_on(listen_address).unwrap(); From 3fa7cbbc15eeba1eae266c87991d4135c5453a86 Mon Sep 17 00:00:00 2001 From: icy-ux <> Date: Fri, 4 Aug 2023 19:15:04 +0000 Subject: [PATCH 091/395] fix typo --- docs/asb/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/asb/README.md b/docs/asb/README.md index 1c924252..16e0a602 100644 --- a/docs/asb/README.md +++ b/docs/asb/README.md @@ -42,7 +42,7 @@ Since the ASB is a long running task we specify the person running an ASB as ser The ASB daemon supports the libp2p [rendezvous-protocol](https://github.com/libp2p/specs/tree/master/rendezvous). Usage of the rendezvous functionality is entirely optional. -You can configure one or more rendezvous point in the `[network]` section of your config file. +You can configure one or more rendezvous points in the `[network]` section of your config file. For the registration to be successful, you also need to configure the externally reachable addresses within the `[network]` section. For example: From e741de1c08d4df42a25f8167c666474a0f8ea15d Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 7 Aug 2023 15:31:09 +0200 Subject: [PATCH 092/395] ci: fix dprint version for draft action --- .github/workflows/draft-new-release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 338ff7c5..efe398b3 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -41,8 +41,10 @@ jobs: - name: Commit changelog and manifest files id: make-commit + env: + DPRINT_VERSION: 0.39.1 run: | - curl -fsSL https://dprint.dev/install.sh | sh + curl -fsSL https://dprint.dev/install.sh | sh -s $DPRINT_VERSION /home/runner/.dprint/bin/dprint fmt git add CHANGELOG.md Cargo.lock swap/Cargo.toml From bde151f535590e8e72adb5f90e2a6834286ddbd7 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 8 Aug 2023 09:48:44 +0200 Subject: [PATCH 093/395] ci: add rustfmt to draft-new-release since changes to dprint --- .github/workflows/draft-new-release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index efe398b3..b25b6fdc 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -43,7 +43,9 @@ jobs: id: make-commit env: DPRINT_VERSION: 0.39.1 + RUST_TOOLCHAIN: 1.67 run: | + rustup component add rustfmt --toolchain "$RUST_TOOLCHAIN-x86_64-unknown-linux-gnu" curl -fsSL https://dprint.dev/install.sh | sh -s $DPRINT_VERSION /home/runner/.dprint/bin/dprint fmt From 94febeca03cf59abee3f508b8d1efe316a8264c1 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface Date: Tue, 8 Aug 2023 08:17:28 +0000 Subject: [PATCH 094/395] Prepare release 0.12.2 --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16f4730b..0768910b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.12.2] - 2023-08-08 + ### Changed - Minimum Supported Rust Version (MSRV) bumped to 1.67 @@ -343,7 +345,8 @@ 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.12.1...HEAD +[Unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...HEAD +[0.12.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.1...0.12.2 [0.12.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.11.0...0.12.0 [0.11.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.10.2...0.11.0 diff --git a/Cargo.lock b/Cargo.lock index 1e5d878a..f0b51599 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4116,7 +4116,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.12.1" +version = "0.12.2" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 7d0e1141..3ef9e09c 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.12.1" +version = "0.12.2" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From d7d87d96ac438746838aab86c52f1e05fc596ef3 Mon Sep 17 00:00:00 2001 From: pokkst Date: Tue, 8 Aug 2023 16:37:09 -0500 Subject: [PATCH 095/395] Maybe fix issue on Windows where the wallet cannot open during XMR locking phase (cherry picked from commit 879cb8bc0131b8a059466ca00ae9f7842c4ac018) --- swap/src/monero/wallet.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 3f548c41..56fd8e60 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -174,11 +174,6 @@ impl Wallet { pub async fn transfer(&self, request: TransferRequest) -> Result { let inner = self.inner.lock().await; - inner - .open_wallet(self.name.clone()) - .await - .with_context(|| format!("Failed to open wallet {}", self.name))?; - let TransferRequest { public_spend_key, public_view_key, From 2e181dac9cb479883aa7139636188d23acb8f1de Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Sun, 13 Aug 2023 14:23:34 +0200 Subject: [PATCH 096/395] Immediately sync bitcoin tx status upon subscribing --- swap/src/bitcoin/wallet.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index 9a8500b6..2e5732f8 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -761,9 +761,10 @@ impl Client { self.blockchain.get_tx(txid) } - fn update_state(&mut self) -> Result<()> { + fn update_state(&mut self, force_sync: bool) -> Result<()> { let now = Instant::now(); - if now < self.last_sync + self.sync_interval { + + if !force_sync && now < self.last_sync + self.sync_interval { return Ok(()); } @@ -783,9 +784,14 @@ impl Client { if !self.script_history.contains_key(&script) { self.script_history.insert(script.clone(), vec![]); - } - self.update_state()?; + // When we first subscribe to a script we want to immediately fetch its status + // Otherwise we would have to wait for the next sync interval, which can take a minute + // This would result in potentially inaccurate status updates until that next sync interval is hit + self.update_state(true)?; + } else { + self.update_state(false)?; + } let history = self.script_history.entry(script).or_default(); From 5aadfbf9963817a0235f8c68c4fd033c2d6c45d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:37:40 +0000 Subject: [PATCH 097/395] build(deps): bump Swatinem/rust-cache from 2.6.0 to 2.6.1 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.6.0 to 2.6.1. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.6.0...v2.6.1) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 8e842a00..3c77b457 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 055e61b5..a4810395 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.67 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - name: Check formatting uses: dprint/check@v2.2 @@ -39,7 +39,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - name: Build swap run: cargo build --bin swap @@ -53,7 +53,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -80,7 +80,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - uses: dtolnay/rust-toolchain@master with: @@ -120,7 +120,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - name: Build tests run: cargo build --tests --workspace --all-features @@ -157,7 +157,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.0 + - uses: Swatinem/rust-cache@v2.6.1 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From ca90c97b5d0ff1b786277b8a874f192d971f20b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Aug 2023 11:49:48 +0000 Subject: [PATCH 098/395] build(deps): bump Swatinem/rust-cache from 2.6.1 to 2.6.2 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.6.1 to 2.6.2. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.6.1...v2.6.2) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 3c77b457..b14e24e8 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4810395..5aec5a6a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.67 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - name: Check formatting uses: dprint/check@v2.2 @@ -39,7 +39,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - name: Build swap run: cargo build --bin swap @@ -53,7 +53,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - name: Install sqlx-cli run: cargo install sqlx-cli @@ -80,7 +80,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - uses: dtolnay/rust-toolchain@master with: @@ -120,7 +120,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - name: Build tests run: cargo build --tests --workspace --all-features @@ -157,7 +157,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v3.5.3 - - uses: Swatinem/rust-cache@v2.6.1 + - uses: Swatinem/rust-cache@v2.6.2 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From dd388d471af778caa545d8ee994d3e57c5cfd3f0 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 30 Aug 2023 22:39:14 +0200 Subject: [PATCH 099/395] Use older version sqlx-cli to be compatible with MSRV --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5aec5a6a..1ca2bbb3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: - uses: Swatinem/rust-cache@v2.6.2 - name: Install sqlx-cli - run: cargo install sqlx-cli + run: cargo install sqlx-cli --locked - name: Run sqlite_dev_setup.sh script run: | From 844ebc7de3479c99f0bf1c55b2cc07ea25c8defd Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 31 Aug 2023 00:42:25 +0200 Subject: [PATCH 100/395] Refresh monero monitoring wallet at startup to ensure daemon is is available --- swap/src/bin/swap.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 33c718c3..c1b37d0d 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -541,6 +541,11 @@ async fn init_monero_wallet( ) .await?; + monero_wallet + .refresh() + .await + .context("Failed to connect to monero daemon")?; + Ok((monero_wallet, monero_wallet_rpc_process)) } From 2e1909685da2b34165f19a4b4163e1b40b974e28 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 1 Sep 2023 17:36:00 +0200 Subject: [PATCH 101/395] =?UTF-8?q?Revert=20"Refresh=20monero=20monitoring?= =?UTF-8?q?=20wallet=20at=20startup=20to=20ensure=20daemon=20is=20is=20av?= =?UTF-8?q?=E2=80=A6"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- swap/src/bin/swap.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index c1b37d0d..33c718c3 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -541,11 +541,6 @@ async fn init_monero_wallet( ) .await?; - monero_wallet - .refresh() - .await - .context("Failed to connect to monero daemon")?; - Ok((monero_wallet, monero_wallet_rpc_process)) } From 16c1daea78be17f9ce68c28c407d220800022628 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Sat, 2 Sep 2023 19:15:15 +0200 Subject: [PATCH 102/395] Update build-release-binaries.yml rustc version to 1.67 --- .github/workflows/build-release-binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index b14e24e8..d397e4ea 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -54,7 +54,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.63 + toolchain: 1.67 targets: armv7-unknown-linux-gnueabihf - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary From a96527fc2a1c081120d5e4dc6ccace84f0e20bd2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:38:13 +0000 Subject: [PATCH 103/395] build(deps): bump actions/checkout from 3.5.3 to 4.0.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 4.0.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.5.3...v4.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index d397e4ea..3db89051 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ca2bbb3..af335076 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: dtolnay/rust-toolchain@master with: @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: Swatinem/rust-cache@v2.6.2 @@ -51,7 +51,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: Swatinem/rust-cache@v2.6.2 @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: Swatinem/rust-cache@v2.6.2 @@ -118,7 +118,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: Swatinem/rust-cache@v2.6.2 @@ -155,7 +155,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v3.5.3 + uses: actions/checkout@v4.0.0 - uses: Swatinem/rust-cache@v2.6.2 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index f3bee225..c95f8d22 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v4.0.0 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index b25b6fdc..2e89fd6c 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v4.0.0 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 37e04333..6e557033 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.5.3 + - uses: actions/checkout@v4.0.0 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From 346752384980553f32ffb6bbfe30895162c49f7f Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Sun, 3 Sep 2023 01:17:42 +0200 Subject: [PATCH 104/395] Dynamically choose monero daemon to connect to --- Cargo.lock | 284 +++++++++++++++++++++++----------- swap/Cargo.toml | 1 + swap/src/bin/swap.rs | 4 +- swap/src/cli/command.rs | 34 ++-- swap/src/monero/wallet_rpc.rs | 246 ++++++++++++++++++++++++++++- 5 files changed, 452 insertions(+), 117 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0b51599..6f37fab9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler32" version = "1.2.0" @@ -105,6 +120,16 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d6e24d2cce90c53b948c46271bfb053e4bdc2db9b5d3f65e20f8cf28a1b7fc3" +[[package]] +name = "assert-json-diff" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e4f2b81832e72834d7518d8487a0396a28cc408186a2e8854c0f98011faf12" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "async-compression" version = "0.3.15" @@ -114,7 +139,7 @@ dependencies = [ "bzip2", "futures-core", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", ] @@ -139,7 +164,7 @@ dependencies = [ "futures-sink", "futures-util", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", ] [[package]] @@ -186,11 +211,26 @@ dependencies = [ "futures-core", "getrandom 0.2.6", "instant", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rand 0.8.3", "tokio", ] +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide 0.7.1", + "object", + "rustc-demangle", +] + [[package]] name = "base32" version = "0.4.0" @@ -359,6 +399,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + [[package]] name = "blake2" version = "0.9.2" @@ -423,7 +469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "822462c1e7b17b31961798a6874b36daea6818e99e0cb7d3b7b0fa3c477751c3" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown 0.12.3", ] [[package]] @@ -616,7 +662,7 @@ checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term 0.11.0", "atty", - "bitflags", + "bitflags 1.3.2", "strsim 0.8.0", "textwrap", "unicode-width", @@ -629,6 +675,17 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colored" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +dependencies = [ + "is-terminal", + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "comfy-table" version = "6.1.4" @@ -804,7 +861,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crossterm_winapi", "libc", "mio", @@ -1225,7 +1282,7 @@ dependencies = [ "crc32fast", "libc", "libz-sys", - "miniz_oxide", + "miniz_oxide 0.3.7", ] [[package]] @@ -1384,7 +1441,7 @@ dependencies = [ "futures-sink", "futures-task", "memchr", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "pin-utils", "slab", ] @@ -1459,13 +1516,19 @@ dependencies = [ "polyval", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "git2" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" dependencies = [ - "bitflags", + "bitflags 1.3.2", "libc", "libgit2-sys", "log", @@ -1664,7 +1727,7 @@ dependencies = [ "httparse", "httpdate", "itoa 1.0.1", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "socket2 0.4.7", "tokio", "tower-service", @@ -1784,6 +1847,17 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" +[[package]] +name = "is-terminal" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi 0.3.1", + "rustix 0.38.11", + "windows-sys 0.48.0", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1871,9 +1945,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libgit2-sys" @@ -2211,6 +2285,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +[[package]] +name = "linux-raw-sys" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" + [[package]] name = "lock_api" version = "0.4.6" @@ -2324,15 +2404,44 @@ dependencies = [ ] [[package]] -name = "mio" -version = "0.8.4" +name = "miniz_oxide" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.36.1", + "windows-sys 0.48.0", +] + +[[package]] +name = "mockito" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09c762b6267c4593555bb38f1df19e9318985bc4de60b5e8462890856a9a5b4c" +dependencies = [ + "assert-json-diff", + "colored", + "futures", + "hyper", + "lazy_static", + "log", + "rand 0.8.3", + "regex", + "serde_json", + "serde_urlencoded", + "similar", + "tokio", ] [[package]] @@ -2593,6 +2702,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.13.0" @@ -2785,9 +2903,9 @@ checksum = "257b64915a082f7811703966789728173279bdebb956b143dbcd23f6f970a777" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -2904,7 +3022,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" dependencies = [ "bit-set", - "bitflags", + "bitflags 1.3.2", "byteorder", "lazy_static", "num-traits", @@ -3159,7 +3277,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3168,7 +3286,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -3183,9 +3301,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.5" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", @@ -3204,9 +3322,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "rend" @@ -3239,7 +3357,7 @@ dependencies = [ "mime", "once_cell", "percent-encoding", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "rustls 0.21.1", "rustls-pemfile", "serde", @@ -3337,6 +3455,12 @@ dependencies = [ "rust_decimal", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -3364,11 +3488,24 @@ version = "0.37.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" dependencies = [ - "bitflags", + "bitflags 1.3.2", "errno", "io-lifetimes", "libc", - "linux-raw-sys", + "linux-raw-sys 0.3.1", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +dependencies = [ + "bitflags 2.4.0", + "errno", + "libc", + "linux-raw-sys 0.4.5", "windows-sys 0.48.0", ] @@ -3556,7 +3693,7 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -3814,6 +3951,12 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" +[[package]] +name = "similar" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" + [[package]] name = "slab" version = "0.4.2" @@ -3881,6 +4024,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "soketto" version = "0.7.0" @@ -3950,7 +4103,7 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" dependencies = [ "ahash", "atoi", - "bitflags", + "bitflags 1.3.2", "byteorder", "bytes", "crc", @@ -4144,6 +4297,7 @@ dependencies = [ "hyper", "itertools", "libp2p", + "mockito", "monero", "monero-harness", "monero-rpc", @@ -4233,7 +4387,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.11", "windows-sys 0.48.0", ] @@ -4381,33 +4535,32 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", - "once_cell", "parking_lot 0.12.0", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2 0.4.7", + "socket2 0.5.3", "tokio-macros", - "winapi", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.7.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -4461,7 +4614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" dependencies = [ "futures-core", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", ] @@ -4506,7 +4659,7 @@ dependencies = [ "bytes", "futures-core", "futures-sink", - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tokio", "tracing", ] @@ -4550,7 +4703,7 @@ version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d" dependencies = [ - "pin-project-lite 0.2.9", + "pin-project-lite 0.2.13", "tracing-attributes", "tracing-core", ] @@ -5124,19 +5277,6 @@ dependencies = [ "windows_x86_64_msvc 0.32.0", ] -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -5173,12 +5313,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5" -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" @@ -5191,12 +5325,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615" -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - [[package]] name = "windows_i686_gnu" version = "0.48.0" @@ -5209,12 +5337,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172" -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - [[package]] name = "windows_i686_msvc" version = "0.48.0" @@ -5227,12 +5349,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc" -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" @@ -5251,12 +5367,6 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316" -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 3ef9e09c..074ad0df 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -77,6 +77,7 @@ zip = "0.5" bitcoin-harness = "0.2.2" get-port = "3" hyper = "0.14" +mockito = "1.1.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 33c718c3..292a4586 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -521,7 +521,7 @@ async fn init_bitcoin_wallet( async fn init_monero_wallet( data_dir: PathBuf, - monero_daemon_address: String, + monero_daemon_address: Option, env_config: Config, ) -> Result<(monero::Wallet, monero::WalletRpcProcess)> { let network = env_config.monero_network; @@ -531,7 +531,7 @@ async fn init_monero_wallet( let monero_wallet_rpc = monero::WalletRpc::new(data_dir.join("monero")).await?; let monero_wallet_rpc_process = monero_wallet_rpc - .run(network, monero_daemon_address.as_str()) + .run(network, monero_daemon_address) .await?; let monero_wallet = monero::Wallet::open_or_create( diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index e4da8e7d..ee48428a 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -14,10 +14,6 @@ use structopt::{clap, StructOpt}; use url::Url; use uuid::Uuid; -// See: https://moneroworld.com/ -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"; // See: https://1209k.com/bitcoin-eye/ele.php?chain=tbtc @@ -80,11 +76,11 @@ where } => { let (bitcoin_electrum_rpc_url, bitcoin_target_block) = bitcoin.apply_defaults(is_testnet)?; - let monero_daemon_address = monero.apply_defaults(is_testnet); let monero_receive_address = validate_monero_address(monero_receive_address, is_testnet)?; let bitcoin_change_address = validate_bitcoin_address(bitcoin_change_address, is_testnet)?; + let monero_daemon_address = monero.monero_daemon_address; Arguments { env_config: env_config_from(is_testnet), @@ -167,7 +163,7 @@ where } => { let (bitcoin_electrum_rpc_url, bitcoin_target_block) = bitcoin.apply_defaults(is_testnet)?; - let monero_daemon_address = monero.apply_defaults(is_testnet); + let monero_daemon_address = monero.monero_daemon_address; Arguments { env_config: env_config_from(is_testnet), @@ -254,7 +250,7 @@ pub enum Command { bitcoin_target_block: usize, bitcoin_change_address: bitcoin::Address, monero_receive_address: monero::Address, - monero_daemon_address: String, + monero_daemon_address: Option, tor_socks5_port: u16, namespace: XmrBtcNamespace, }, @@ -274,7 +270,7 @@ pub enum Command { swap_id: Uuid, bitcoin_electrum_rpc_url: Url, bitcoin_target_block: usize, - monero_daemon_address: String, + monero_daemon_address: Option, tor_socks5_port: u16, namespace: XmrBtcNamespace, }, @@ -436,23 +432,11 @@ enum RawCommand { struct Monero { #[structopt( long = "monero-daemon-address", - help = "Specify to connect to a monero daemon of your choice: :" + help = "Specify to connect to a monero daemon of your choice: :. If none is specified, we will connect to a public node." )] monero_daemon_address: Option, } -impl Monero { - fn apply_defaults(self, testnet: bool) -> String { - if let Some(address) = self.monero_daemon_address { - address - } else if testnet { - DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string() - } else { - DEFAULT_MONERO_DAEMON_ADDRESS.to_string() - } - } -} - #[derive(structopt::StructOpt, Debug)] struct Bitcoin { #[structopt(long = "electrum-rpc", help = "Provide the Bitcoin Electrum RPC URL")] @@ -1174,7 +1158,7 @@ mod tests { bitcoin_change_address: BITCOIN_TESTNET_ADDRESS.parse().unwrap(), monero_receive_address: monero::Address::from_str(MONERO_STAGENET_ADDRESS) .unwrap(), - monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string(), + monero_daemon_address: None, tor_socks5_port: DEFAULT_SOCKS5_PORT, namespace: XmrBtcNamespace::Testnet, }, @@ -1194,7 +1178,7 @@ mod tests { bitcoin_change_address: BITCOIN_MAINNET_ADDRESS.parse().unwrap(), monero_receive_address: monero::Address::from_str(MONERO_MAINNET_ADDRESS) .unwrap(), - monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS.to_string(), + monero_daemon_address: None, tor_socks5_port: DEFAULT_SOCKS5_PORT, namespace: XmrBtcNamespace::Mainnet, }, @@ -1212,7 +1196,7 @@ mod tests { bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET) .unwrap(), bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET, - monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string(), + monero_daemon_address: None, tor_socks5_port: DEFAULT_SOCKS5_PORT, namespace: XmrBtcNamespace::Testnet, }, @@ -1229,7 +1213,7 @@ mod tests { swap_id: Uuid::from_str(SWAP_ID).unwrap(), bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(), bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET, - monero_daemon_address: DEFAULT_MONERO_DAEMON_ADDRESS.to_string(), + monero_daemon_address: None, tor_socks5_port: DEFAULT_SOCKS5_PORT, namespace: XmrBtcNamespace::Mainnet, }, diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index 819eeccb..e44d800e 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -1,19 +1,45 @@ use ::monero::Network; -use anyhow::{Context, Result}; +use anyhow::{bail, Context, Error, Result}; use big_bytes::BigByte; use futures::{StreamExt, TryStreamExt}; use monero_rpc::wallet::{Client, MoneroWalletRpc as _}; use reqwest::header::CONTENT_LENGTH; use reqwest::Url; +use serde::Deserialize; +use std::fmt; +use std::fmt::{Debug, Display, Formatter}; use std::io::ErrorKind; use std::path::{Path, PathBuf}; use std::process::Stdio; +use std::time::Duration; use tokio::fs::{remove_file, OpenOptions}; use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; use tokio::process::{Child, Command}; use tokio_util::codec::{BytesCodec, FramedRead}; use tokio_util::io::StreamReader; +// See: https://www.moneroworld.com/#nodes, https://monero.fail +// We don't need any testnet nodes because we don't support testnet at all +const MONERO_DAEMONS: [MoneroDaemon; 17] = [ + MoneroDaemon::new("xmr-node.cakewallet.com", 18081, Network::Mainnet), + MoneroDaemon::new("nodex.monerujo.io", 18081, Network::Mainnet), + MoneroDaemon::new("node.moneroworld.com", 18089, Network::Mainnet), + MoneroDaemon::new("nodes.hashvault.pro", 18081, Network::Mainnet), + MoneroDaemon::new("p2pmd.xmrvsbeast.com", 18081, Network::Mainnet), + MoneroDaemon::new("node.monerodevs.org", 18089, Network::Mainnet), + MoneroDaemon::new("xmr-node-usa-east.cakewallet.com", 18081, Network::Mainnet), + MoneroDaemon::new("xmr-node-uk.cakewallet.com", 18081, Network::Mainnet), + MoneroDaemon::new("node.community.rino.io", 18081, Network::Mainnet), + MoneroDaemon::new("testingjohnross.com", 20031, Network::Mainnet), + MoneroDaemon::new("xmr.litepay.ch", 18081, Network::Mainnet), + MoneroDaemon::new("node.trocador.app", 18089, Network::Mainnet), + MoneroDaemon::new("stagenet.xmr-tw.org", 38081, Network::Stagenet), + MoneroDaemon::new("node.monerodevs.org", 38089, Network::Stagenet), + MoneroDaemon::new("singapore.node.xmr.pm", 38081, Network::Stagenet), + MoneroDaemon::new("xmr-lux.boldsuck.org", 38081, Network::Stagenet), + MoneroDaemon::new("stagenet.community.rino.io", 38081, Network::Stagenet), +]; + #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))] compile_error!("unsupported operating system"); @@ -50,6 +76,91 @@ pub struct WalletRpcProcess { port: u16, } +struct MoneroDaemon { + address: &'static str, + port: u16, + network: Network, +} + +impl MoneroDaemon { + const fn new(address: &'static str, port: u16, network: Network) -> Self { + Self { + address, + port, + network, + } + } + + /// Checks if the Monero daemon is available by sending a request to its `get_info` endpoint. + async fn is_available(&self, client: &reqwest::Client) -> Result { + let url = format!("http://{}:{}/get_info", self.address, self.port); + let res = client + .get(url) + .send() + .await + .context("Failed to send request to get_info endpoint")?; + + let json: MoneroDaemonGetInfoResponse = res + .json() + .await + .context("Failed to deserialize daemon get_info response")?; + + let is_status_ok = json.status == "OK"; + let is_synchronized = json.synchronized; + let is_correct_network = match self.network { + Network::Mainnet => json.mainnet, + Network::Stagenet => json.stagenet, + Network::Testnet => json.testnet, + }; + + Ok(is_status_ok && is_synchronized && is_correct_network) + } +} + +impl Display for MoneroDaemon { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.address, self.port) + } +} + +#[derive(Deserialize)] +struct MoneroDaemonGetInfoResponse { + status: String, + synchronized: bool, + mainnet: bool, + stagenet: bool, + testnet: bool, +} + +/// Chooses an available Monero daemon based on the specified network. +async fn choose_monero_daemon(network: Network) -> Result<&'static MoneroDaemon, Error> { + let client = reqwest::Client::builder() + .timeout(Duration::from_secs(30)) + .https_only(false) + .build()?; + + // We only want to check for daemons that match the specified network + let network_matching_daemons = MONERO_DAEMONS + .iter() + .filter(|daemon| daemon.network == network); + + for daemon in network_matching_daemons { + match daemon.is_available(&client).await { + Ok(true) => { + tracing::debug!(%daemon, "Found available Monero daemon"); + return Ok(daemon); + } + Err(err) => { + tracing::debug!(%err, %daemon, "Failed to connect to Monero daemon"); + continue; + } + Ok(false) => continue, + } + } + + bail!("No Monero daemon could be found. Please specify one manually or try again later.") +} + impl WalletRpcProcess { pub fn endpoint(&self) -> Url { Url::parse(&format!("http://127.0.0.1:{}/json_rpc", self.port)) @@ -153,13 +264,23 @@ impl WalletRpc { Ok(monero_wallet_rpc) } - pub async fn run(&self, network: Network, daemon_address: &str) -> Result { + pub async fn run( + &self, + network: Network, + daemon_address: Option, + ) -> Result { let port = tokio::net::TcpListener::bind("127.0.0.1:0") .await? .local_addr()? .port(); + let daemon_address = match daemon_address { + Some(daemon_address) => daemon_address, + None => choose_monero_daemon(network).await?.to_string(), + }; + tracing::debug!( + %daemon_address, %port, "Starting monero-wallet-rpc" ); @@ -232,7 +353,6 @@ impl WalletRpc { #[cfg(not(target_os = "windows"))] async fn extract_archive(monero_wallet_rpc: &Self) -> Result<()> { - use anyhow::bail; use tokio_tar::Archive; let mut options = OpenOptions::new(); @@ -297,3 +417,123 @@ impl WalletRpc { Ok(()) } } + +#[cfg(test)] +mod tests { + use super::*; + + fn extract_host_and_port(address: String) -> (&'static str, u16) { + let parts: Vec<&str> = address.split(':').collect(); + + if parts.len() == 2 { + let host = parts[0].to_string(); + let port = parts[1].parse::().unwrap(); + let static_str_host: &'static str = Box::leak(host.into_boxed_str()); + return (static_str_host, port); + } + panic!("Could not extract host and port from address: {}", address) + } + + #[tokio::test] + async fn test_is_daemon_available_success() { + let mut server = mockito::Server::new(); + + let _ = server + .mock("GET", "/get_info") + .with_status(200) + .with_body( + r#" + { + "status": "OK", + "synchronized": true, + "mainnet": true, + "stagenet": false, + "testnet": false + } + "#, + ) + .create(); + + let (host, port) = extract_host_and_port(server.host_with_port()); + + let client = reqwest::Client::new(); + let result = MoneroDaemon::new(host, port, Network::Mainnet) + .is_available(&client) + .await; + + assert!(result.is_ok()); + assert!(result.unwrap()); + } + + #[tokio::test] + async fn test_is_daemon_available_wrong_network_failure() { + let mut server = mockito::Server::new(); + + let _ = server + .mock("GET", "/get_info") + .with_status(200) + .with_body( + r#" + { + "status": "OK", + "synchronized": true, + "mainnet": true, + "stagenet": false, + "testnet": false + } + "#, + ) + .create(); + + let (host, port) = extract_host_and_port(server.host_with_port()); + + let client = reqwest::Client::new(); + let result = MoneroDaemon::new(host, port, Network::Stagenet) + .is_available(&client) + .await; + + assert!(result.is_ok()); + assert!(!result.unwrap()); + } + + #[tokio::test] + async fn test_is_daemon_available_not_synced_failure() { + let mut server = mockito::Server::new(); + + let _ = server + .mock("GET", "/get_info") + .with_status(200) + .with_body( + r#" + { + "status": "OK", + "synchronized": false, + "mainnet": true, + "stagenet": false, + "testnet": false + } + "#, + ) + .create(); + + let (host, port) = extract_host_and_port(server.host_with_port()); + + let client = reqwest::Client::new(); + let result = MoneroDaemon::new(host, port, Network::Mainnet) + .is_available(&client) + .await; + + assert!(result.is_ok()); + assert!(!result.unwrap()); + } + + #[tokio::test] + async fn test_is_daemon_available_network_error_failure() { + let client = reqwest::Client::new(); + let result = MoneroDaemon::new("does.not.exist.com", 18081, Network::Mainnet) + .is_available(&client) + .await; + + assert!(result.is_err()); + } +} From 332fd39164d4ebd6ba738252c65069dd78ead978 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 8 Sep 2023 11:45:10 +0200 Subject: [PATCH 105/395] Add CHANGELOG entry for PR 1441 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0768910b..c4b857c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Swap: If no Monero daemon is manually specified, we will automatically choose one from a list of public daemons by connecting to each and checking their availability. + ## [0.12.2] - 2023-08-08 ### Changed From 782407897577b44c5b9fe3f3a46001efaa5e4449 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface Date: Wed, 20 Sep 2023 18:34:50 +0000 Subject: [PATCH 106/395] Prepare release 0.12.3 --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4b857c6..160c34a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.12.3] - 2023-09-20 + - Swap: If no Monero daemon is manually specified, we will automatically choose one from a list of public daemons by connecting to each and checking their availability. ## [0.12.2] - 2023-08-08 @@ -347,7 +349,8 @@ 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.12.2...HEAD +[Unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...HEAD +[0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 [0.12.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.1...0.12.2 [0.12.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.0...0.12.1 [0.12.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.11.0...0.12.0 diff --git a/Cargo.lock b/Cargo.lock index 6f37fab9..e3619fce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4269,7 +4269,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.12.2" +version = "0.12.3" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 074ad0df..b2872469 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.12.2" +version = "0.12.3" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From 5182b4f53a741eebc3b734e980904d2e5a8113d1 Mon Sep 17 00:00:00 2001 From: pokkst Date: Fri, 29 Sep 2023 08:08:25 -0500 Subject: [PATCH 107/395] Update lock timeout to 10 min --- swap/src/env.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swap/src/env.rs b/swap/src/env.rs index a80d402d..1ba8c432 100644 --- a/swap/src/env.rs +++ b/swap/src/env.rs @@ -46,7 +46,7 @@ pub struct Regtest; impl GetConfig for Mainnet { fn get_config() -> Config { Config { - bitcoin_lock_mempool_timeout: 3.std_minutes(), + bitcoin_lock_mempool_timeout: 10.std_minutes(), bitcoin_lock_confirmed_timeout: 2.std_hours(), bitcoin_finality_confirmations: 1, bitcoin_avg_block_time: 10.std_minutes(), @@ -63,7 +63,7 @@ impl GetConfig for Mainnet { impl GetConfig for Testnet { fn get_config() -> Config { Config { - bitcoin_lock_mempool_timeout: 3.std_minutes(), + bitcoin_lock_mempool_timeout: 10.std_minutes(), bitcoin_lock_confirmed_timeout: 1.std_hours(), bitcoin_finality_confirmations: 1, bitcoin_avg_block_time: 10.std_minutes(), From eac6a6be5cc6e5865dfebd5cf56c1060996163cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Oct 2023 11:13:47 +0000 Subject: [PATCH 108/395] build(deps): bump actions/checkout from 4.0.0 to 4.1.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.0.0 to 4.1.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.0.0...v4.1.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 3db89051..21ed973b 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index af335076..5ec81fcc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 - uses: dtolnay/rust-toolchain@master with: @@ -37,7 +37,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 - uses: Swatinem/rust-cache@v2.6.2 @@ -51,7 +51,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 - uses: Swatinem/rust-cache@v2.6.2 @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 - uses: Swatinem/rust-cache@v2.6.2 @@ -118,7 +118,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 - uses: Swatinem/rust-cache@v2.6.2 @@ -155,7 +155,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.0.0 + uses: actions/checkout@v4.1.1 - uses: Swatinem/rust-cache@v2.6.2 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index c95f8d22..ac24fe3f 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.1 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 2e89fd6c..06bb9052 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.1 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 6e557033..d27a645a 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.0.0 + - uses: actions/checkout@v4.1.1 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From dcf9f24b770a1c9b9898372c7e254d155ce7f7dd Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 23 Oct 2023 11:21:04 +0200 Subject: [PATCH 109/395] build(deps): bump pem to 3.0 replaces #1415 also fixes the `seed_from_pem_fails_for_long_seed` unit test, which was "passing" but not actually testing what it meant to. --- Cargo.lock | 7 ++++--- swap/Cargo.toml | 2 +- swap/src/seed.rs | 21 ++++++++++----------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e3619fce..d0e46b43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2823,11 +2823,12 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pem" -version = "1.1.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" dependencies = [ - "base64 0.13.1", + "base64 0.21.2", + "serde", ] [[package]] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index b2872469..102eff4f 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -34,7 +34,7 @@ itertools = "0.10" libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } -pem = "1.1" +pem = "3.0" proptest = "1" qrcode = "0.12" rand = "0.8" diff --git a/swap/src/seed.rs b/swap/src/seed.rs index f89215b9..5ffe9124 100644 --- a/swap/src/seed.rs +++ b/swap/src/seed.rs @@ -106,11 +106,12 @@ impl Seed { } fn from_pem(pem: pem::Pem) -> Result { - if pem.contents.len() != SEED_LENGTH { - Err(Error::IncorrectLength(pem.contents.len())) + let contents = pem.contents(); + if contents.len() != SEED_LENGTH { + Err(Error::IncorrectLength(contents.len())) } else { let mut array = [0; SEED_LENGTH]; - for (i, b) in pem.contents.iter().enumerate() { + for (i, b) in contents.iter().enumerate() { array[i] = *b; } @@ -122,10 +123,7 @@ impl Seed { ensure_directory_exists(&seed_file)?; let data = self.bytes(); - let pem = Pem { - tag: String::from("SEED"), - contents: data.to_vec(), - }; + let pem = Pem::new("SEED", data); let pem_string = encode(&pem); @@ -224,19 +222,20 @@ VnZUNFZ4dlY= } #[test] - #[should_panic] fn seed_from_pem_fails_for_long_seed() { let long = "-----BEGIN SEED----- -mbKANv2qKGmNVg1qtquj6Hx1pFPelpqOfE2JaJJAMEg1FlFhNRNlFlE= -mbKANv2qKGmNVg1qtquj6Hx1pFPelpqOfE2JaJJAMEg1FlFhNRNlFlE= +MIIBPQIBAAJBAOsfi5AGYhdRs/x6q5H7kScxA0Kzzqe6WI6gf6+tc6IvKQJo5rQc +dWWSQ0nRGt2hOPDO+35NKhQEjBQxPh/v7n0CAwEAAQJBAOGaBAyuw0ICyENy5NsO -----END SEED----- "; let pem = pem::parse(long).unwrap(); + assert_eq!(pem.contents().len(), 96); + match Seed::from_pem(pem) { Ok(_) => panic!("should fail for long payload"), Err(e) => { match e { - Error::IncorrectLength(_) => {} // pass + Error::IncorrectLength(len) => assert_eq!(len, 96), // pass _ => panic!("should fail with IncorrectLength error"), } } From 9819f74c125510c77ed66fb558d896cf6e43164c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:25:08 +0000 Subject: [PATCH 110/395] build(deps): bump Swatinem/rust-cache from 2.6.2 to 2.7.1 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.6.2 to 2.7.1. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.6.2...v2.7.1) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 21ed973b..62e25913 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ec81fcc..d54fc558 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: toolchain: 1.67 components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - name: Check formatting uses: dprint/check@v2.2 @@ -39,7 +39,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - name: Build swap run: cargo build --bin swap @@ -53,7 +53,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - name: Install sqlx-cli run: cargo install sqlx-cli --locked @@ -80,7 +80,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - uses: dtolnay/rust-toolchain@master with: @@ -120,7 +120,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - name: Build tests run: cargo build --tests --workspace --all-features @@ -157,7 +157,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.6.2 + - uses: Swatinem/rust-cache@v2.7.1 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From 53972cdeb3057e9275245c083f5ae8bf983096d7 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 5 Dec 2023 13:21:12 +0200 Subject: [PATCH 111/395] ci: update minimum rust version to 1.70 this is to fix the issue with installing sqlx-cli in ci --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 4 ++-- .github/workflows/draft-new-release.yml | 2 +- CHANGELOG.md | 2 ++ README.md | 2 +- rust-toolchain.toml | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 62e25913..45229bc4 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -54,7 +54,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.67 + toolchain: "1.70" targets: armv7-unknown-linux-gnueabihf - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d54fc558..2a7ed795 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.67 + toolchain: "1.70" components: clippy,rustfmt - uses: Swatinem/rust-cache@v2.7.1 @@ -84,7 +84,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: 1.67 + toolchain: "1.70" targets: armv7-unknown-linux-gnueabihf - name: Build binary diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 06bb9052..70a623a8 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -43,7 +43,7 @@ jobs: id: make-commit env: DPRINT_VERSION: 0.39.1 - RUST_TOOLCHAIN: 1.67 + RUST_TOOLCHAIN: 1.70 run: | rustup component add rustfmt --toolchain "$RUST_TOOLCHAIN-x86_64-unknown-linux-gnu" curl -fsSL https://dprint.dev/install.sh | sh -s $DPRINT_VERSION diff --git a/CHANGELOG.md b/CHANGELOG.md index 160c34a0..4d3ad105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Minimum Supported Rust Version (MSRV) bumped to 1.70 + ## [0.12.3] - 2023-09-20 - Swap: If no Monero daemon is manually specified, we will automatically choose one from a list of public daemons by connecting to each and checking their availability. diff --git a/README.md b/README.md index 7cbccc5a..71a37896 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ 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.67 _should_ work. +All stable toolchains since 1.70 _should_ work. ## Contact diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d6b509dd..d03c251b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.67" # also update this in the readme, changelog, and github actions +channel = "1.70" # also update this in the readme, changelog, and github actions components = ["clippy"] targets = ["armv7-unknown-linux-gnueabihf"] From dbb66fe6b743edc8dc769602f48cea4b1f6448a5 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 6 Dec 2023 13:19:50 +0200 Subject: [PATCH 112/395] ci: remove bors bors has been deprecated for some time and seems to be gone now. --- .github/workflows/ci.yml | 2 -- bors.toml | 25 ------------------------- 2 files changed, 27 deletions(-) delete mode 100644 bors.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a7ed795..64b53e83 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,6 @@ on: pull_request: # Need to run on pull-requests, otherwise PRs from forks don't run push: branches: - - "staging" # Bors uses this branch - - "trying" # Bors uses this branch - "master" # Always build head of master for the badge in the README jobs: diff --git a/bors.toml b/bors.toml deleted file mode 100644 index 92e8a84c..00000000 --- a/bors.toml +++ /dev/null @@ -1,25 +0,0 @@ -status = [ - "static_analysis", - "bdk_test", - "sqlx_test", - "build (x86_64-unknown-linux-gnu, ubuntu-latest)", - "build (armv7-unknown-linux-gnueabihf, ubuntu-latest)", - "build (x86_64-apple-darwin, macos-latest)", - "build (x86_64-pc-windows-msvc, windows-latest)", - "test (ubuntu-latest)", - "test (macos-latest)", - "docker_tests (happy_path)", - "docker_tests (happy_path_restart_bob_after_xmr_locked)", - "docker_tests (happy_path_restart_alice_after_xmr_locked)", - "docker_tests (happy_path_restart_bob_before_xmr_locked)", - "docker_tests (alice_and_bob_refund_using_cancel_and_refund_command)", - "docker_tests (alice_and_bob_refund_using_cancel_then_refund_command)", - "docker_tests (alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired)", - "docker_tests (punish)", - "docker_tests (alice_punishes_after_restart_bob_dead)", - "docker_tests (alice_manually_punishes_after_bob_dead)", - "docker_tests (alice_refunds_after_restart_bob_refunded)", - "docker_tests (ensure_same_swap_id)", - "docker_tests (concurrent_bobs_before_xmr_lock_proof_sent)", - "docker_tests (alice_manually_redeems_after_enc_sig_learned)" -] From c8802bad3de73c0183bd4debb573ef901675d305 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 11:13:34 +0000 Subject: [PATCH 113/395] build(deps): bump actions/setup-python from 4 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 45229bc4..3bf9aefd 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -69,7 +69,7 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help # Remove once python 3 is the default - - uses: actions/setup-python@v4 + - uses: actions/setup-python@v5 with: python-version: "3.x" From 7ccb9d61beaee054fca413351fa8e2608c8c8869 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:16:30 +0000 Subject: [PATCH 114/395] build(deps): bump url from 2.4.0 to 2.5.0 Bumps [url](https://github.com/servo/rust-url) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/servo/rust-url/releases) - [Commits](https://github.com/servo/rust-url/compare/v2.4.0...v2.5.0) --- updated-dependencies: - dependency-name: url dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0e46b43..33073558 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1305,9 +1305,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1767,9 +1767,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -2833,9 +2833,9 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" @@ -4991,12 +4991,12 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" [[package]] name = "url" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", - "idna 0.4.0", + "idna 0.5.0", "percent-encoding", "serde", ] From 564302b1848a1f2aeb94bdc71db54fadf4f99b43 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:16:48 +0000 Subject: [PATCH 115/395] build(deps): bump tokio-util from 0.7.3 to 0.7.10 Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.3 to 0.7.10. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/commits) --- updated-dependencies: - dependency-name: tokio-util dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0e46b43..4ff9b1ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4653,9 +4653,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", From 73162adcd78dda8a2a79662dee16998ab3b35482 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:17:18 +0000 Subject: [PATCH 116/395] build(deps): bump strum from 0.24.1 to 0.25.0 Bumps [strum](https://github.com/Peternator7/strum) from 0.24.1 to 0.25.0. - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 35 +++++++++++++++++++++++++++-------- swap/Cargo.toml | 2 +- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0e46b43..63bd45f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -693,8 +693,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" dependencies = [ "crossterm", - "strum", - "strum_macros", + "strum 0.24.1", + "strum_macros 0.24.0", "unicode-width", ] @@ -1598,9 +1598,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" dependencies = [ "unicode-segmentation", ] @@ -4151,7 +4151,7 @@ checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" dependencies = [ "dotenvy", "either", - "heck 0.4.0", + "heck 0.4.1", "hex", "once_cell", "proc-macro2", @@ -4239,8 +4239,14 @@ name = "strum" version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros", + "strum_macros 0.25.3", ] [[package]] @@ -4249,13 +4255,26 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" dependencies = [ - "heck 0.4.0", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", "syn 1.0.109", ] +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.15", +] + [[package]] name = "subtle" version = "2.4.0" @@ -4321,7 +4340,7 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum", + "strum 0.25.0", "tempfile", "testcontainers 0.12.0", "thiserror", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 102eff4f..eaf24114 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -50,7 +50,7 @@ sha2 = "0.10" sigma_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "ed25519", "serde", "secp256k1", "alloc" ] } sqlx = { version = "0.6", features = [ "sqlite", "runtime-tokio-rustls", "offline" ] } structopt = "0.3" -strum = { version = "0.24", features = [ "derive" ] } +strum = { version = "0.25", features = [ "derive" ] } thiserror = "1" time = "0.3" tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } From 46a73e2a6311e21905be4d0b0e4532973ff32772 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 11:17:40 +0000 Subject: [PATCH 117/395] build(deps): bump tracing from 0.1.38 to 0.1.40 Bumps [tracing](https://github.com/tokio-rs/tracing) from 0.1.38 to 0.1.40. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-0.1.38...tracing-0.1.40) --- updated-dependencies: - dependency-name: tracing dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0e46b43..e22788a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3009,9 +3009,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" dependencies = [ "unicode-ident", ] @@ -4700,9 +4700,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.38" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ "pin-project-lite 0.2.13", "tracing-attributes", @@ -4722,9 +4722,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.24" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", @@ -4733,9 +4733,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", From f602bec096fdab276efb04991def849a0c8f72bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:41:50 +0000 Subject: [PATCH 118/395] build(deps): bump uuid from 1.4.1 to 1.6.1 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.4.1 to 1.6.1. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.4.1...1.6.1) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..e3d0445a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5028,9 +5028,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.4.1" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "getrandom 0.2.6", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index eaf24114..488513b9 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -64,7 +64,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.4", features = [ "serde", "v4" ] } +uuid = { version = "1.6", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From c7bf84d9361685b201bd31bb822699d74f6fd1f7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:42:04 +0000 Subject: [PATCH 119/395] build(deps): bump data-encoding from 2.4.0 to 2.5.0 Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.4.0 to 2.5.0. - [Commits](https://github.com/ia0/data-encoding/commits) --- updated-dependencies: - dependency-name: data-encoding dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..c0e77b2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1010,9 +1010,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "deranged" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index eaf24114..c55f1a80 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -23,7 +23,7 @@ comfy-table = "6.1" config = { version = "0.13", default-features = false, features = [ "toml" ] } conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } -data-encoding = "2.4" +data-encoding = "2.5" dialoguer = "0.10" directories-next = "2" ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] } From 9c7d33acbe113d4146c632886c84cfe00c5ccb44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:42:14 +0000 Subject: [PATCH 120/395] build(deps): bump proptest from 1.2.0 to 1.4.0 Bumps [proptest](https://github.com/proptest-rs/proptest) from 1.2.0 to 1.4.0. - [Release notes](https://github.com/proptest-rs/proptest/releases) - [Changelog](https://github.com/proptest-rs/proptest/blob/master/CHANGELOG.md) - [Commits](https://github.com/proptest-rs/proptest/compare/v1.2.0...v1.4.0) --- updated-dependencies: - dependency-name: proptest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..2b629dcd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3018,19 +3018,19 @@ dependencies = [ [[package]] name = "proptest" -version = "1.2.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e35c06b98bf36aba164cc17cb25f7e232f5c4aeea73baa14b8a9f0d92dbfa65" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", - "bitflags 1.3.2", - "byteorder", + "bit-vec", + "bitflags 2.4.0", "lazy_static", "num-traits", "rand 0.8.3", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax", + "regex-syntax 0.8.2", "rusty-fork", "tempfile", "unarray", @@ -3308,7 +3308,7 @@ checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -3318,7 +3318,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" dependencies = [ "byteorder", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] @@ -3327,6 +3327,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "rend" version = "0.3.6" From 42e0cdcae964f3e81f211d811057728fa7268b2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:42:26 +0000 Subject: [PATCH 121/395] build(deps): bump thiserror from 1.0.40 to 1.0.50 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.40 to 1.0.50. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.40...1.0.50) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..bb6cb7bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,7 +151,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -1396,7 +1396,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -3138,9 +3138,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -3766,7 +3766,7 @@ checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -3836,7 +3836,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -4272,7 +4272,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -4376,9 +4376,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" dependencies = [ "proc-macro2", "quote", @@ -4464,22 +4464,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -4580,7 +4580,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] @@ -4747,7 +4747,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.40", ] [[package]] From 81ea313d4e36c0bfad288d4ba34b563cb8aab901 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:42:37 +0000 Subject: [PATCH 122/395] build(deps): bump hyper from 0.14.26 to 1.0.1 Bumps [hyper](https://github.com/hyperium/hyper) from 0.14.26 to 1.0.1. - [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.26...v1.0.1) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 64 ++++++++++++++++++++++++++++++++++++++----------- swap/Cargo.toml | 2 +- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..613d55c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1546,7 +1546,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http", + "http 0.2.3", "indexmap", "slab", "tokio", @@ -1689,6 +1689,17 @@ dependencies = [ "itoa 0.4.7", ] +[[package]] +name = "http" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +dependencies = [ + "bytes", + "fnv", + "itoa 1.0.1", +] + [[package]] name = "http-body" version = "0.4.0" @@ -1696,7 +1707,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" dependencies = [ "bytes", - "http", + "http 0.2.3", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.0.0", ] [[package]] @@ -1713,17 +1734,17 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http", - "http-body", + "http 0.2.3", + "http-body 0.4.0", "httparse", "httpdate", "itoa 1.0.1", @@ -1735,14 +1756,29 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f9214f3e703236b221f1a9cd88ec8b4adfa5296de01ab96216361f4692f56" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "pin-project-lite 0.2.13", + "tokio", +] + [[package]] name = "hyper-rustls" version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" dependencies = [ - "http", - "hyper", + "http 0.2.3", + "hyper 0.14.27", "rustls 0.21.1", "tokio", "tokio-rustls 0.24.0", @@ -2433,7 +2469,7 @@ dependencies = [ "assert-json-diff", "colored", "futures", - "hyper", + "hyper 0.14.27", "lazy_static", "log", "rand 0.8.3", @@ -3348,9 +3384,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http", - "http-body", - "hyper", + "http 0.2.3", + "http-body 0.4.0", + "hyper 0.14.27", "hyper-rustls", "ipnet", "js-sys", @@ -4314,7 +4350,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper", + "hyper 1.0.1", "itertools", "libp2p", "mockito", @@ -4892,7 +4928,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "bytes", - "http", + "http 0.2.3", "httparse", "log", "rand 0.8.3", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index eaf24114..26c10cf6 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -76,7 +76,7 @@ zip = "0.5" [dev-dependencies] bitcoin-harness = "0.2.2" get-port = "3" -hyper = "0.14" +hyper = "1.0" mockito = "1.1.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" From 8b8c69a9cc4e501fbd4415d6f539e49684ac4b50 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:42:48 +0000 Subject: [PATCH 123/395] build(deps): bump sha2 from 0.10.6 to 0.10.8 Bumps [sha2](https://github.com/RustCrypto/hashes) from 0.10.6 to 0.10.8. - [Commits](https://github.com/RustCrypto/hashes/compare/sha2-v0.10.6...sha2-v0.10.8) --- updated-dependencies: - dependency-name: sha2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..4c159c57 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1056,9 +1056,9 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.5" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.2", "crypto-common", @@ -1664,7 +1664,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "digest 0.10.5", + "digest 0.10.7", ] [[package]] @@ -2027,7 +2027,7 @@ dependencies = [ "rand 0.8.3", "ring", "rw-stream-sink", - "sha2 0.10.6", + "sha2 0.10.8", "smallvec", "thiserror", "unsigned-varint", @@ -2111,7 +2111,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.3", - "sha2 0.10.6", + "sha2 0.10.8", "snow", "static_assertions", "x25519-dalek", @@ -2151,7 +2151,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.3", - "sha2 0.10.6", + "sha2 0.10.8", "thiserror", "unsigned-varint", "void", @@ -3681,7 +3681,7 @@ name = "secp256kfun" version = "0.7.1" source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca" dependencies = [ - "digest 0.10.5", + "digest 0.10.7", "rand_core 0.6.2", "secp256k1", "serde", @@ -3867,13 +3867,13 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures 0.2.1", - "digest 0.10.5", + "digest 0.10.7", ] [[package]] @@ -3909,7 +3909,7 @@ version = "0.4.1" source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca" dependencies = [ "curve25519-dalek-ng", - "digest 0.10.5", + "digest 0.10.7", "generic-array", "rand_core 0.6.2", "secp256kfun", @@ -4132,7 +4132,7 @@ dependencies = [ "rustls 0.20.2", "rustls-pemfile", "serde", - "sha2 0.10.6", + "sha2 0.10.8", "smallvec", "sqlformat", "sqlx-rt", @@ -4158,7 +4158,7 @@ dependencies = [ "quote", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", "sqlx-core", "sqlx-rt", "syn 1.0.109", @@ -4335,7 +4335,7 @@ dependencies = [ "serde_json", "serde_with", "serial_test", - "sha2 0.10.6", + "sha2 0.10.8", "sigma_fun", "spectral", "sqlx", @@ -4450,7 +4450,7 @@ dependencies = [ "rand 0.8.3", "serde", "serde_json", - "sha2 0.10.6", + "sha2 0.10.8", ] [[package]] From 0ea8ce71b6c349316b46fcaa5b9c52c29ae82d53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Dec 2023 11:44:32 +0000 Subject: [PATCH 124/395] build(deps): bump comfy-table from 6.1.4 to 7.1.0 Bumps [comfy-table](https://github.com/nukesor/comfy-table) from 6.1.4 to 7.1.0. - [Release notes](https://github.com/nukesor/comfy-table/releases) - [Changelog](https://github.com/Nukesor/comfy-table/blob/main/CHANGELOG.md) - [Commits](https://github.com/nukesor/comfy-table/compare/v6.1.4...v7.1.0) --- updated-dependencies: - dependency-name: comfy-table dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 66 +++++++++---------------------------------------- swap/Cargo.toml | 2 +- 2 files changed, 12 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dae1e4dc..73cf7bd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -688,13 +688,13 @@ dependencies = [ [[package]] name = "comfy-table" -version = "6.1.4" +version = "7.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" +checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" dependencies = [ "crossterm", - "strum 0.24.1", - "strum_macros 0.24.0", + "strum", + "strum_macros", "unicode-width", ] @@ -857,25 +857,22 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.25.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "crossterm_winapi", "libc", - "mio", "parking_lot 0.12.0", - "signal-hook", - "signal-hook-mio", "winapi", ] [[package]] name = "crossterm_winapi" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ "winapi", ] @@ -2419,7 +2416,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -3916,27 +3912,6 @@ dependencies = [ "serde", ] -[[package]] -name = "signal-hook" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "647c97df271007dcea485bb74ffdb57f2e683f1306c854f468a0c244badabf2d" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - [[package]] name = "signal-hook-registry" version = "1.4.0" @@ -4234,32 +4209,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" - [[package]] name = "strum" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" dependencies = [ - "strum_macros 0.25.3", -] - -[[package]] -name = "strum_macros" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", + "strum_macros", ] [[package]] @@ -4340,7 +4296,7 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum 0.25.0", + "strum", "tempfile", "testcontainers 0.12.0", "thiserror", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index eaf24114..508eb8d5 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -19,7 +19,7 @@ bdk = "0.28" big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bmrng = "0.5" -comfy-table = "6.1" +comfy-table = "7.1" config = { version = "0.13", default-features = false, features = [ "toml" ] } conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } From 8ff683f8150284f451723b4596003a2eabfdbd30 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:44:49 +0000 Subject: [PATCH 125/395] build(deps): bump tempfile from 3.6.0 to 3.8.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.6.0 to 3.8.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.6.0...v3.8.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 49 +++++++------------------------------------------ 1 file changed, 7 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b46592e0..529ec5d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1232,12 +1232,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" -version = "1.7.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "filetime" @@ -1851,17 +1848,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "ipconfig" version = "0.2.2" @@ -1887,7 +1873,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi 0.3.1", - "rustix 0.38.11", + "rustix", "windows-sys 0.48.0", ] @@ -2312,12 +2298,6 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" -[[package]] -name = "linux-raw-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" - [[package]] name = "linux-raw-sys" version = "0.4.5" @@ -3521,20 +3501,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.37.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.1", - "windows-sys 0.48.0", -] - [[package]] name = "rustix" version = "0.38.11" @@ -3544,7 +3510,7 @@ dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.5", + "linux-raw-sys", "windows-sys 0.48.0", ] @@ -4397,15 +4363,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ - "autocfg", "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.11", + "rustix", "windows-sys 0.48.0", ] From ae67e6386be85249286698d43fc960d80a41aee4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:45:05 +0000 Subject: [PATCH 126/395] build(deps): bump base64 from 0.21.2 to 0.21.5 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.2 to 0.21.5. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.2...v0.21.5) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b46592e0..075ecccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,9 +260,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "bdk" @@ -2859,7 +2859,7 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "serde", ] @@ -3380,7 +3380,7 @@ version = "0.11.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" dependencies = [ - "base64 0.21.2", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -4294,7 +4294,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.21.2", + "base64 0.21.5", "bdk", "big-bytes", "bitcoin", From 69751d204d13dc2de20a3491e061eb358cd7447f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:45:21 +0000 Subject: [PATCH 127/395] build(deps): bump dialoguer from 0.10.4 to 0.11.0 Bumps [dialoguer](https://github.com/console-rs/dialoguer) from 0.10.4 to 0.11.0. - [Changelog](https://github.com/console-rs/dialoguer/blob/master/CHANGELOG.md) - [Commits](https://github.com/console-rs/dialoguer/compare/v0.10.4...v0.11.0) --- updated-dependencies: - dependency-name: dialoguer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 5 +++-- swap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b46592e0..3a536585 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1032,13 +1032,14 @@ dependencies = [ [[package]] name = "dialoguer" -version = "0.10.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87" +checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" dependencies = [ "console", "shell-words", "tempfile", + "thiserror", "zeroize", ] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index a0b9ee95..78ae00bd 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -24,7 +24,7 @@ config = { version = "0.13", default-features = false, features = [ "toml" ] } conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } data-encoding = "2.5" -dialoguer = "0.10" +dialoguer = "0.11" directories-next = "2" ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] } ed25519-dalek = "1" From 641c1070120927dbe66ceb13e1a086eaa8e40f77 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:45:38 +0000 Subject: [PATCH 128/395] build(deps): bump toml from 0.5.11 to 0.7.6 Bumps [toml](https://github.com/toml-rs/toml) from 0.5.11 to 0.7.6. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.5.11...toml-v0.7.6) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 92 ++++++++++++++++++++++++++++++++++++++++++++----- swap/Cargo.toml | 2 +- 2 files changed, 84 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b46592e0..10822f68 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -709,7 +709,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml", + "toml 0.5.11", ] [[package]] @@ -1203,6 +1203,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.1" @@ -1544,7 +1550,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.3", - "indexmap", + "indexmap 1.7.0", "slab", "tokio", "tokio-util", @@ -1575,6 +1581,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "hashlink" version = "0.8.1" @@ -1842,6 +1854,16 @@ dependencies = [ "hashbrown 0.11.2", ] +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + [[package]] name = "instant" version = "0.1.12" @@ -2392,9 +2414,9 @@ checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "memchr" -version = "2.4.1" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" @@ -2885,7 +2907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a13a2fa9d0b63e5f22328828741e523766fff0ee9e779316902290dff3f824f" dependencies = [ "fixedbitset", - "indexmap", + "indexmap 1.7.0", ] [[package]] @@ -3002,7 +3024,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" dependencies = [ - "toml", + "toml 0.5.11", ] [[package]] @@ -3012,7 +3034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" dependencies = [ "thiserror", - "toml", + "toml 0.5.11", ] [[package]] @@ -3818,6 +3840,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -4137,7 +4168,7 @@ dependencies = [ "futures-util", "hashlink", "hex", - "indexmap", + "indexmap 1.7.0", "itoa 1.0.1", "libc", "libsqlite3-sys", @@ -4348,7 +4379,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml", + "toml 0.7.6", "torut", "tracing", "tracing-appender", @@ -4691,6 +4722,40 @@ dependencies = [ "serde", ] +[[package]] +name = "toml" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.1.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "torut" version = "0.2.1" @@ -5391,6 +5456,15 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "winnow" +version = "0.5.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +dependencies = [ + "memchr", +] + [[package]] name = "winreg" version = "0.6.2" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index a0b9ee95..2769d384 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -57,7 +57,7 @@ tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync tokio-socks = "0.5" tokio-tungstenite = { version = "0.15", features = [ "rustls-tls" ] } tokio-util = { version = "0.7", features = [ "io", "codec" ] } -toml = "0.5" +toml = "0.7" torut = { version = "0.2", default-features = false, features = [ "v3", "control" ] } tracing = { version = "0.1", features = [ "attributes" ] } tracing-appender = "0.2" From b015397400830a409ec01ac0f84cb1283f592934 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:46:20 +0000 Subject: [PATCH 129/395] build(deps): bump anyhow from 1.0.71 to 1.0.75 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.71 to 1.0.75. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.71...1.0.75) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b46592e0..e79c9a70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.71" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arrayref" From 9481f54fe082537a928b2669a78810d1e732d0c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:46:38 +0000 Subject: [PATCH 130/395] build(deps): bump serde from 1.0.164 to 1.0.193 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.164 to 1.0.193. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.164...v1.0.193) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b46592e0..f5bfe44c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3769,9 +3769,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.164" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" dependencies = [ "serde_derive", ] @@ -3798,9 +3798,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.193" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", From ab2db98c79371f926f9ec8267f16663f7d10dcca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:38:45 +0000 Subject: [PATCH 131/395] build(deps): bump pem from 3.0.2 to 3.0.3 Bumps [pem](https://github.com/jcreekmore/pem-rs) from 3.0.2 to 3.0.3. - [Changelog](https://github.com/jcreekmore/pem-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/jcreekmore/pem-rs/compare/v3.0.2...v3.0.3) --- updated-dependencies: - dependency-name: pem dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13720807..48977da8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2857,9 +2857,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pem" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3163d2912b7c3b52d651a055f2c7eec9ba5cd22d26ef75b8dd3a59980b185923" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ "base64 0.21.5", "serde", From d39c9eb7386107ed47a6e30417b912f775f416c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:39:04 +0000 Subject: [PATCH 132/395] build(deps): bump serde_json from 1.0.96 to 1.0.108 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.96 to 1.0.108. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.96...v1.0.108) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13720807..9af75138 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3797,9 +3797,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ "itoa 1.0.1", "ryu", From e21043be4e214bae831111addf4cce06405db0d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:39:26 +0000 Subject: [PATCH 133/395] build(deps): bump tokio from 1.32.0 to 1.35.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.32.0 to 1.35.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.32.0...tokio-1.35.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13720807..e95118f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1986,9 +1986,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libgit2-sys" @@ -2449,9 +2449,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -4041,9 +4041,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", "windows-sys 0.48.0", @@ -4549,9 +4549,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.32.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", @@ -4561,16 +4561,16 @@ dependencies = [ "parking_lot 0.12.0", "pin-project-lite 0.2.13", "signal-hook-registry", - "socket2 0.5.3", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", From 9e4303c1963c638ef94b3e7459bcacaa891e2df3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:39:54 +0000 Subject: [PATCH 134/395] build(deps): bump reqwest from 0.11.18 to 0.11.22 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.18 to 0.11.22. - [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.18...v0.11.22) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 148 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13720807..f747f5dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,7 +64,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.11", "once_cell", "version_check", ] @@ -209,7 +209,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" dependencies = [ "futures-core", - "getrandom 0.2.6", + "getrandom 0.2.11", "instant", "pin-project-lite 0.2.13", "rand 0.8.3", @@ -274,7 +274,7 @@ dependencies = [ "bdk-macros", "bitcoin", "electrum-client", - "getrandom 0.2.6", + "getrandom 0.2.11", "js-sys", "log", "miniscript", @@ -581,11 +581,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.67" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "jobserver", + "libc", ] [[package]] @@ -1485,13 +1486,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -1785,7 +1786,7 @@ checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" dependencies = [ "http 0.2.3", "hyper 0.14.27", - "rustls 0.21.1", + "rustls 0.21.10", "tokio", "tokio-rustls 0.24.0", ] @@ -1986,9 +1987,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libgit2-sys" @@ -2018,7 +2019,7 @@ dependencies = [ "bytes", "futures", "futures-timer", - "getrandom 0.2.6", + "getrandom 0.2.11", "instant", "lazy_static", "libp2p-core", @@ -2066,7 +2067,7 @@ dependencies = [ "prost", "prost-build", "rand 0.8.3", - "ring", + "ring 0.16.20", "rw-stream-sink", "sha2 0.10.8", "smallvec", @@ -3267,7 +3268,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.11", ] [[package]] @@ -3330,7 +3331,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.11", "redox_syscall 0.2.10", ] @@ -3378,9 +3379,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.18" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ "base64 0.21.5", "bytes", @@ -3399,11 +3400,12 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.13", - "rustls 0.21.1", + "rustls 0.21.10", "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-rustls 0.24.0", "tokio-socks", @@ -3414,8 +3416,8 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.22.2", - "winreg 0.10.1", + "webpki-roots 0.25.3", + "winreg 0.50.0", ] [[package]] @@ -3438,11 +3440,25 @@ dependencies = [ "libc", "once_cell", "spin 0.5.2", - "untrusted", + "untrusted 0.7.1", "web-sys", "winapi", ] +[[package]] +name = "ring" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babe80d5c16becf6594aa32ad2be8fe08498e7ae60b77de8df700e67f191d7e" +dependencies = [ + "cc", + "getrandom 0.2.11", + "libc", + "spin 0.9.4", + "untrusted 0.9.0", + "windows-sys 0.48.0", +] + [[package]] name = "rkyv" version = "0.7.39" @@ -3544,7 +3560,7 @@ checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" dependencies = [ "base64 0.13.1", "log", - "ring", + "ring 0.16.20", "sct 0.6.0", "webpki 0.21.4", ] @@ -3556,19 +3572,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d37e5e2290f3e040b594b1a9e04377c2c671f1a1cfd9bfdef82106ac1c113f84" dependencies = [ "log", - "ring", + "ring 0.16.20", "sct 0.7.0", "webpki 0.22.0", ] [[package]] name = "rustls" -version = "0.21.1" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring", + "ring 0.17.3", "rustls-webpki", "sct 0.7.0", ] @@ -3596,12 +3612,12 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.100.1" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring", - "untrusted", + "ring 0.17.3", + "untrusted 0.9.0", ] [[package]] @@ -3661,8 +3677,8 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -3671,8 +3687,8 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -4011,7 +4027,7 @@ dependencies = [ "chacha20poly1305", "rand 0.8.3", "rand_core 0.6.2", - "ring", + "ring 0.16.20", "rustc_version", "sha2 0.9.8", "subtle", @@ -4392,6 +4408,27 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" version = "3.8.0" @@ -4605,7 +4642,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" dependencies = [ - "rustls 0.21.1", + "rustls 0.21.10", "tokio", ] @@ -5036,6 +5073,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.0" @@ -5060,7 +5103,7 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ - "getrandom 0.2.6", + "getrandom 0.2.11", "serde", ] @@ -5135,12 +5178,6 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -5215,9 +5252,9 @@ checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wasm-streams" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078" +checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" dependencies = [ "futures-util", "js-sys", @@ -5242,8 +5279,8 @@ version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -5252,8 +5289,8 @@ version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" dependencies = [ - "ring", - "untrusted", + "ring 0.16.20", + "untrusted 0.7.1", ] [[package]] @@ -5274,6 +5311,12 @@ dependencies = [ "webpki 0.22.0", ] +[[package]] +name = "webpki-roots" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" + [[package]] name = "which" version = "4.0.2" @@ -5441,11 +5484,12 @@ dependencies = [ [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if 1.0.0", + "windows-sys 0.48.0", ] [[package]] From b7b54e8c5d7d99277f860857ff2011c22e5471a1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:40:30 +0000 Subject: [PATCH 135/395] build(deps): bump tokio-tar from 0.3.0 to 0.3.1 Bumps [tokio-tar](https://github.com/vorot93/tokio-tar) from 0.3.0 to 0.3.1. - [Commits](https://github.com/vorot93/tokio-tar/compare/v0.3.0...v0.3.1) --- updated-dependencies: - dependency-name: tokio-tar dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 115 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13720807..f2e1db16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1211,23 +1211,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -1986,9 +1975,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.147" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libgit2-sys" @@ -2322,9 +2311,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "lock_api" @@ -3525,15 +3514,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.11" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.0", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -4634,14 +4623,14 @@ dependencies = [ [[package]] name = "tokio-tar" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50188549787c32c1c3d9c8c71ad7e003ccf2f102489c5a96e385c84760477f4" +checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75" dependencies = [ "filetime", "futures-core", "libc", - "redox_syscall 0.2.10", + "redox_syscall 0.3.5", "tokio", "tokio-stream", "xattr", @@ -5331,7 +5320,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -5340,21 +5338,42 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm", + "windows_aarch64_gnullvm 0.48.0", "windows_aarch64_msvc 0.48.0", "windows_i686_gnu 0.48.0", "windows_i686_msvc 0.48.0", "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm", + "windows_x86_64_gnullvm 0.48.0", "windows_x86_64_msvc 0.48.0", ] +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" @@ -5367,6 +5386,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.32.0" @@ -5379,6 +5404,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.32.0" @@ -5391,6 +5422,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.32.0" @@ -5403,12 +5440,24 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.32.0" @@ -5421,6 +5470,12 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" version = "0.5.28" @@ -5461,11 +5516,13 @@ dependencies = [ [[package]] name = "xattr" -version = "0.2.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "244c3741f4240ef46274860397c7c74e50eb23624996930e484c16679633a54c" +checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995" dependencies = [ "libc", + "linux-raw-sys", + "rustix", ] [[package]] From dc1ad6df7d5ef06b2a9cacf1a7ed967fe21f232e Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:23:47 +0100 Subject: [PATCH 136/395] Upgrade monero-wallet-rpc to `v0.18.3.1` --- swap/src/monero/wallet_rpc.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index e44d800e..cecdd620 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -44,20 +44,20 @@ const MONERO_DAEMONS: [MoneroDaemon; 17] = [ compile_error!("unsupported operating system"); #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.0.0.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "arm"))] const DOWNLOAD_URL: &str = - "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2"; + "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2"; #[cfg(target_os = "windows")] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.3.1.zip"; #[cfg(any(target_os = "macos", target_os = "linux"))] const PACKED_FILE: &str = "monero-wallet-rpc"; @@ -65,7 +65,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc"; #[cfg(target_os = "windows")] const PACKED_FILE: &str = "monero-wallet-rpc.exe"; -const WALLET_RPC_VERSION: &str = "v0.18.1.2"; +const WALLET_RPC_VERSION: &str = "v0.18.3.1"; #[derive(Debug, Clone, Copy, thiserror::Error)] #[error("monero wallet rpc executable not found in downloaded archive")] From 8d95643fa7889ece5e916acdde8ed81b4f9b98b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:14:29 +0000 Subject: [PATCH 137/395] build(deps): bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64b53e83..90824b4c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -98,13 +98,13 @@ jobs: run: cross build -p swap --target ${{ matrix.target }} - name: Upload swap binary - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: swap-${{ matrix.target }} path: target/${{ matrix.target }}/debug/swap - name: Upload asb binary - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: asb-${{ matrix.target }} path: target/${{ matrix.target }}/debug/asb From 999adf82156884c4f4198934d6a1d1ffe649f749 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:19:47 +0000 Subject: [PATCH 138/395] build(deps): bump time from 0.3.24 to 0.3.30 Bumps [time](https://github.com/time-rs/time) from 0.3.24 to 0.3.30. - [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.24...v0.3.30) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10e4049d..1db1bffe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1014,9 +1014,12 @@ checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "deranged" -version = "0.3.6" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8810e7e2cf385b1e9b50d68264908ec367ba642c96d02edfe61c39e88e2a3c01" +checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +dependencies = [ + "powerfmt", +] [[package]] name = "derive_more" @@ -2972,6 +2975,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6519412c9e0d4be579b9f0618364d19cb434b324fc6ddb1b27b1e682c7105ed" +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -4344,7 +4353,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.24", + "time 0.3.30", "tokio", "tokio-socks", "tokio-tar", @@ -4523,12 +4532,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.24" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b79eabcd964882a646b3584543ccabeae7869e9ac32a46f6f22b7a5bd405308b" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", "itoa 1.0.1", + "powerfmt", "serde", "time-core", "time-macros", @@ -4536,15 +4546,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -4789,7 +4799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" dependencies = [ "crossbeam-channel", - "time 0.3.24", + "time 0.3.30", "tracing-subscriber 0.3.15", ] @@ -4879,7 +4889,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.24", + "time 0.3.30", "tracing", "tracing-core", "tracing-log", @@ -5127,7 +5137,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.24", + "time 0.3.30", ] [[package]] From b4eb49e6ce131db67dc4f32795a1ac07aea2ad58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:20:24 +0000 Subject: [PATCH 139/395] build(deps): bump config from 0.13.3 to 0.13.4 Bumps [config](https://github.com/mehcode/config-rs) from 0.13.3 to 0.13.4. - [Changelog](https://github.com/mehcode/config-rs/blob/v0.13.4/CHANGELOG.md) - [Commits](https://github.com/mehcode/config-rs/compare/0.13.3...v0.13.4) --- updated-dependencies: - dependency-name: config dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10e4049d..233c7aab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -701,9 +701,9 @@ dependencies = [ [[package]] name = "config" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7" +checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" dependencies = [ "async-trait", "lazy_static", From e44134c96d0eca6e5c82197f5d21828a105a2537 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:21:20 +0000 Subject: [PATCH 140/395] build(deps): bump qrcode from 0.12.0 to 0.13.0 Bumps [qrcode](https://github.com/kennytm/qrcode-rust) from 0.12.0 to 0.13.0. - [Release notes](https://github.com/kennytm/qrcode-rust/releases) - [Commits](https://github.com/kennytm/qrcode-rust/commits) --- updated-dependencies: - dependency-name: qrcode dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 26 +++++++++----------------- swap/Cargo.toml | 2 +- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10e4049d..209587b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -542,9 +542,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.5.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" +checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" [[package]] name = "byteorder" @@ -626,12 +626,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "checked_int_cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" - [[package]] name = "chrono" version = "0.4.19" @@ -1819,15 +1813,14 @@ dependencies = [ [[package]] name = "image" -version = "0.23.14" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" dependencies = [ "bytemuck", "byteorder", "color_quant", - "num-iter", - "num-rational 0.3.2", + "num-rational 0.4.1", "num-traits", ] @@ -2697,9 +2690,9 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ "autocfg", "num-integer", @@ -3135,11 +3128,10 @@ dependencies = [ [[package]] name = "qrcode" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" +checksum = "166f136dfdb199f98186f3649cf7a0536534a61417a1a30221b492b4fb60ce3f" dependencies = [ - "checked_int_cast", "image", ] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 2769d384..4394dcdb 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -36,7 +36,7 @@ monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } pem = "3.0" proptest = "1" -qrcode = "0.12" +qrcode = "0.13" rand = "0.8" rand_chacha = "0.3" reqwest = { version = "0.11", features = [ "rustls-tls", "stream", "socks" ], default-features = false } From 4d200f0c7859ab07e40dd424b101535c330be830 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:21:58 +0000 Subject: [PATCH 141/395] build(deps): bump tempfile from 3.8.0 to 3.8.1 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.8.0 to 3.8.1. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/commits) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10e4049d..8abb50c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3314,6 +3314,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.0" @@ -4420,13 +4429,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "windows-sys 0.48.0", ] From 55f95c970ed3cb12c9245c2866b5eb97a4e71ee2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Dec 2023 11:22:38 +0000 Subject: [PATCH 142/395] build(deps): bump mockito from 1.1.0 to 1.2.0 Bumps [mockito](https://github.com/lipanski/mockito) from 1.1.0 to 1.2.0. - [Release notes](https://github.com/lipanski/mockito/releases) - [Commits](https://github.com/lipanski/mockito/compare/1.1.0...1.2.0) --- updated-dependencies: - dependency-name: mockito dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 5 ++--- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10e4049d..2594b4b5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2450,15 +2450,14 @@ dependencies = [ [[package]] name = "mockito" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09c762b6267c4593555bb38f1df19e9318985bc4de60b5e8462890856a9a5b4c" +checksum = "f8d3038e23466858569c2d30a537f691fa0d53b51626630ae08262943e3bbb8b" dependencies = [ "assert-json-diff", "colored", "futures", "hyper 0.14.27", - "lazy_static", "log", "rand 0.8.3", "regex", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 2769d384..f77391b2 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -77,7 +77,7 @@ zip = "0.5" bitcoin-harness = "0.2.2" get-port = "3" hyper = "1.0" -mockito = "1.1.0" +mockito = "1.2.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" From ab43a51fbfdcfe304e7debdb4800ac3f1d6c368c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:16:41 +0000 Subject: [PATCH 143/395] build(deps): bump thiserror from 1.0.50 to 1.0.51 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.50 to 1.0.51. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.50...1.0.51) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d1e6477..1c107d6b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4493,18 +4493,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" dependencies = [ "proc-macro2", "quote", From 07db057b34d5004f9aa4fe4f2c04a00eb130c031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:17:03 +0000 Subject: [PATCH 144/395] build(deps): bump futures from 0.3.28 to 0.3.29 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.28 to 0.3.29. - [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.28...0.3.29) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d1e6477..2e68731a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,9 +1317,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -1332,9 +1332,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -1342,15 +1342,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -1371,15 +1371,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -1399,15 +1399,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-timer" @@ -1417,9 +1417,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", From 839d74be053b03bd5497ff985f32ea38c01c9ca5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:17:25 +0000 Subject: [PATCH 145/395] build(deps): bump tracing-appender from 0.2.2 to 0.2.3 Bumps [tracing-appender](https://github.com/tokio-rs/tracing) from 0.2.2 to 0.2.3. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-appender-0.2.2...tracing-appender-0.2.3) --- updated-dependencies: - dependency-name: tracing-appender dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 66 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d1e6477..beceefe0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,9 +809,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.0" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -842,12 +842,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" dependencies = [ "cfg-if 1.0.0", - "lazy_static", ] [[package]] @@ -2323,12 +2322,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "lru" @@ -2621,6 +2617,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num" version = "0.1.42" @@ -2771,6 +2777,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "owning_ref" version = "0.4.1" @@ -3939,9 +3951,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.1" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c719719ee05df97490f80a45acfc99e5a30ce98a1e4fb67aee422745ae14e3" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] @@ -4364,7 +4376,7 @@ dependencies = [ "tracing", "tracing-appender", "tracing-futures", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.18", "url", "uuid", "vergen", @@ -4794,13 +4806,14 @@ dependencies = [ [[package]] name = "tracing-appender" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d48f71a791638519505cefafe162606f706c25592e4bde4d97600c0195312e" +checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", + "thiserror", "time 0.3.30", - "tracing-subscriber 0.3.15", + "tracing-subscriber 0.3.18", ] [[package]] @@ -4847,6 +4860,17 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-serde" version = "0.1.3" @@ -4872,17 +4896,17 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.2", ] [[package]] name = "tracing-subscriber" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "ansi_term 0.12.1", "matchers 0.1.0", + "nu-ansi-term", "once_cell", "regex", "serde", @@ -4892,7 +4916,7 @@ dependencies = [ "time 0.3.30", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-serde", ] From 46d93b67cb1c5a66e90a819c8131ff6ef2ca14c1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:17:44 +0000 Subject: [PATCH 146/395] build(deps): bump itertools from 0.10.5 to 0.12.0 Bumps [itertools](https://github.com/rust-itertools/itertools) from 0.10.5 to 0.12.0. - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-itertools/itertools/compare/v0.10.5...v0.12.0) --- updated-dependencies: - dependency-name: itertools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 17 +++++++++++++---- swap/Cargo.toml | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d1e6477..6aade65d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1894,6 +1894,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.7" @@ -3079,7 +3088,7 @@ checksum = "62941722fb675d463659e49c4f3fe1fe792ff24fe5bbaa9c08cd3b98a1c354f5" dependencies = [ "bytes", "heck 0.3.2", - "itertools", + "itertools 0.10.5", "lazy_static", "log", "multimap", @@ -3098,7 +3107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" dependencies = [ "anyhow", - "itertools", + "itertools 0.10.5", "proc-macro2", "quote", "syn 1.0.109", @@ -4109,7 +4118,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" dependencies = [ - "itertools", + "itertools 0.10.5", "nom", "unicode_categories", ] @@ -4324,7 +4333,7 @@ dependencies = [ "get-port", "hex", "hyper 1.0.1", - "itertools", + "itertools 0.12.0", "libp2p", "mockito", "monero", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 64a4fe2a..c20074b6 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -30,7 +30,7 @@ ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = ed25519-dalek = "1" futures = { version = "0.3", default-features = false } hex = "0.4" -itertools = "0.10" +itertools = "0.12" libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } From 85b5c40384c33f08a0b4854a9232c65a434a942a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Dec 2023 11:18:39 +0000 Subject: [PATCH 147/395] build(deps): bump rust_decimal_macros from 1.29.1 to 1.30.0 Bumps [rust_decimal_macros](https://github.com/paupino/rust-decimal) from 1.29.1 to 1.30.0. - [Release notes](https://github.com/paupino/rust-decimal/releases) - [Changelog](https://github.com/paupino/rust-decimal/blob/master/CHANGELOG.md) - [Commits](https://github.com/paupino/rust-decimal/compare/1.29.1...1.30.0) --- updated-dependencies: - dependency-name: rust_decimal_macros dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d1e6477..b59e7142 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3502,9 +3502,9 @@ dependencies = [ [[package]] name = "rust_decimal_macros" -version = "1.29.1" +version = "1.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e773fd3da1ed42472fdf3cfdb4972948a555bc3d73f5e0bdb99d17e7b54c687" +checksum = "7ca5c398d85f83b9a44de754a2048625a8c5eafcf070da7b8f116b685e2f6608" dependencies = [ "quote", "rust_decimal", From 38ba2fc38734201876ee552061182fbdeb8aa735 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:41:54 +0000 Subject: [PATCH 148/395] build(deps): bump hyper from 1.0.1 to 1.1.0 Bumps [hyper](https://github.com/hyperium/hyper) from 1.0.1 to 1.1.0. - [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/v1.0.1...v1.1.0) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 +++----- swap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68040b49..3738e6eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1751,13 +1751,11 @@ dependencies = [ [[package]] name = "hyper" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f9214f3e703236b221f1a9cd88ec8b4adfa5296de01ab96216361f4692f56" +checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" dependencies = [ "bytes", - "futures-channel", - "futures-util", "http 1.0.0", "http-body 1.0.0", "pin-project-lite 0.2.13", @@ -4345,7 +4343,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper 1.0.1", + "hyper 1.1.0", "itertools 0.12.0", "libp2p", "mockito", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index ad48c4e2..497a67d0 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -76,7 +76,7 @@ zip = "0.5" [dev-dependencies] bitcoin-harness = "0.2.2" get-port = "3" -hyper = "1.0" +hyper = "1.1" mockito = "1.2.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" From cf89da7e849fd63d8b3b2937238d6eddcb75cc9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:42:08 +0000 Subject: [PATCH 149/395] build(deps): bump toml from 0.7.6 to 0.8.8 Bumps [toml](https://github.com/toml-rs/toml) from 0.7.6 to 0.8.8. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.7.6...toml-v0.8.8) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 +++++----- swap/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68040b49..ab7d066f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4381,7 +4381,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.7.6", + "toml 0.8.8", "torut", "tracing", "tracing-appender", @@ -4747,9 +4747,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" dependencies = [ "serde", "serde_spanned", @@ -4768,9 +4768,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.15" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ "indexmap 2.1.0", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index ad48c4e2..dfc19b7f 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -57,7 +57,7 @@ tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync tokio-socks = "0.5" tokio-tungstenite = { version = "0.15", features = [ "rustls-tls" ] } tokio-util = { version = "0.7", features = [ "io", "codec" ] } -toml = "0.7" +toml = "0.8" torut = { version = "0.2", default-features = false, features = [ "v3", "control" ] } tracing = { version = "0.1", features = [ "attributes" ] } tracing-appender = "0.2" From c9757caf1e126edfb55f8e2aa70fc8d71d8d5bed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:42:25 +0000 Subject: [PATCH 150/395] build(deps): bump async-trait from 0.1.68 to 0.1.74 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.68 to 0.1.74. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.68...0.1.74) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68040b49..3bf739bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", From 3d88102cd98f2343244d3a28ceeb050d46c8ba08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:42:37 +0000 Subject: [PATCH 151/395] build(deps): bump time from 0.3.30 to 0.3.31 Bumps [time](https://github.com/time-rs/time) from 0.3.30 to 0.3.31. - [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.30...v0.3.31) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68040b49..cbdb434c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4375,7 +4375,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.30", + "time 0.3.31", "tokio", "tokio-socks", "tokio-tar", @@ -4554,9 +4554,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa 1.0.1", @@ -4574,9 +4574,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -4822,7 +4822,7 @@ checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror", - "time 0.3.30", + "time 0.3.31", "tracing-subscriber 0.3.18", ] @@ -4923,7 +4923,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.30", + "time 0.3.31", "tracing", "tracing-core", "tracing-log 0.2.0", @@ -5171,7 +5171,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.30", + "time 0.3.31", ] [[package]] From 3298313d5186b53ad645d5fd2a37fe63bd068a54 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Dec 2023 11:42:55 +0000 Subject: [PATCH 152/395] build(deps): bump reqwest from 0.11.22 to 0.11.23 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.22 to 0.11.23. - [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.22...v0.11.23) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 68040b49..deab5f85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3399,9 +3399,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ "base64 0.21.5", "bytes", From 3b9fbc866d06c6e122ed6b2a9a42228ae3933b6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Dec 2023 11:31:38 +0000 Subject: [PATCH 153/395] build(deps): bump tokio from 1.35.0 to 1.35.1 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.35.0 to 1.35.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.35.0...tokio-1.35.1) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0340082d..3685d143 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4605,9 +4605,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.35.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", From f29ff00febdac448f9f1cb7e9fb6df2e4eace673 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:22:43 +0000 Subject: [PATCH 154/395] build(deps): bump anyhow from 1.0.75 to 1.0.76 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.75 to 1.0.76. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.75...1.0.76) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ced57725..2954ad06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" [[package]] name = "arrayref" From 712327ed03c38283f566a9cccd1e0f42b01904fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:23:58 +0000 Subject: [PATCH 155/395] build(deps): bump async-trait from 0.1.74 to 0.1.75 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.74 to 0.1.75. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.74...0.1.75) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ced57725..1bae1c81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" dependencies = [ "proc-macro2", "quote", From 2026bb9fdf2f4ec9c534a403732d66a0bd69d650 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Dec 2023 11:55:47 +0000 Subject: [PATCH 156/395] build(deps): bump futures from 0.3.29 to 0.3.30 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.29 to 0.3.30. - [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.29...0.3.30) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ebe82e0..cd98d403 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1317,9 +1317,9 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1332,9 +1332,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1342,15 +1342,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1371,15 +1371,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -1399,15 +1399,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -1417,9 +1417,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", From 0f68415129996f64be1027441655c3ea6e7cca34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Dec 2023 11:20:49 +0000 Subject: [PATCH 157/395] build(deps): bump thiserror from 1.0.51 to 1.0.52 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.51 to 1.0.52. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.51...1.0.52) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd98d403..895a9629 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4513,18 +4513,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" dependencies = [ "proc-macro2", "quote", From 844bf23ed5e1cc41d4d0144cd76bf553c073935d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 Dec 2023 11:58:34 +0000 Subject: [PATCH 158/395] build(deps): bump anyhow from 1.0.76 to 1.0.77 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.76 to 1.0.77. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.76...1.0.77) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 895a9629..564dbc52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.76" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" +checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" [[package]] name = "arrayref" From 05b460a2c91a6f4d9113b1bfa9faa475ef332a68 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Dec 2023 11:25:47 +0000 Subject: [PATCH 159/395] build(deps): bump tempfile from 3.8.1 to 3.9.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.8.1 to 3.9.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.8.1...v3.9.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 564dbc52..b5e7f026 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4449,15 +4449,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if 1.0.0", "fastrand", "redox_syscall 0.4.1", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] From 9e33e8b1d193e59b07c549c90f622af8b6a2a502 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 14 Dec 2023 17:22:55 +0100 Subject: [PATCH 160/395] Give feedback to user about state of monero refresh and retry if fails This commit changes the following behaviour in the refresh functionality of the monero wallet - Allows for multiple retries because in some cases users have experienced an issue where the wallet rpc returns `no connection to daemon` even though the daemon is available. I'm not 100% sure why this happens but retrying often fixes the issue - Attempt to print the current sync height while the wallet is syncing. This only works to some degree because the `monero-wallet-rpc` stops responding (or takes a long time to respond) while it's refreshing - The `monero-wallet-rpc` is started with the `--no-initial-sync` flag which ensures that as soon as it's started, it's ready to respond to requests --- swap/src/monero/wallet.rs | 68 +++++++++++++++++++++++++++++++++-- swap/src/monero/wallet_rpc.rs | 1 + swap/src/protocol/bob/swap.rs | 2 +- swap/tests/harness/mod.rs | 2 +- 4 files changed, 68 insertions(+), 5 deletions(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 56fd8e60..3ba99aac 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -45,6 +45,7 @@ impl Wallet { pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result { let main_address = monero::Address::from_str(client.get_address(0).await?.address.as_str())?; + Ok(Self { inner: Mutex::new(client), network: env_config.monero_network, @@ -144,7 +145,7 @@ impl Wallet { .await?; // Try to send all the funds from the generated wallet to the default wallet - match wallet.refresh().await { + match self.refresh(3).await { Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await { Ok(sweep_all) => { for tx in sweep_all.tx_hash_list { @@ -261,8 +262,69 @@ impl Wallet { self.main_address } - pub async fn refresh(&self) -> Result { - Ok(self.inner.lock().await.refresh().await?) + pub async fn refresh(&self, max_attempts: usize) -> Result { + const GET_HEIGHT_INTERVAL: Duration = Duration::from_secs(5); + const RETRY_INTERVAL: Duration = Duration::from_secs(2); + + let inner = self.inner.lock().await; + + // Cloning this is relatively cheap because reqwest::Client is a wrapper around an Arc + let inner_clone = inner.clone(); + let wallet_name_clone = self.name.clone(); + + let refresh_task = tokio::task::spawn(async move { + loop { + let height = inner_clone.get_height().await; + + match height { + Err(error) => { + tracing::warn!(name = %wallet_name_clone, %error, "Failed to get current Monero wallet sync height"); + } + Ok(height) => { + tracing::debug!(name = %wallet_name_clone, current_sync_height = height.height, "Syncing Monero wallet"); + } + } + + tokio::time::sleep(GET_HEIGHT_INTERVAL).await; + } + }); + + let refresh_result = tokio::select! { + biased; + _ = refresh_task => { + unreachable!("Current sync height refresh task should never finish") + } + refresh_result = async { + for i in 1..=max_attempts { + tracing::info!(name = %self.name, attempt=i, "Syncing Monero wallet"); + + let result = inner.refresh().await; + + match result { + Ok(refreshed) => { + tracing::info!(name = %self.name, "Monero wallet synced"); + return Ok(refreshed); + } + Err(error) => { + let attempts_left = max_attempts - i; + tracing::warn!(attempt=i, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet"); + + if attempts_left == 0 { + return Err(error); + } + } + } + + tokio::time::sleep(RETRY_INTERVAL).await; + } + + unreachable!("Loop should always return before it breaks") + } => { + refresh_result + } + }; + + Ok(refresh_result?) } } diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index cecdd620..e2f019a3 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -309,6 +309,7 @@ impl WalletRpc { .arg("--disable-rpc-login") .arg("--wallet-dir") .arg(self.working_dir.join("monero-data")) + .arg("--no-initial-sync") .spawn()?; let stdout = child diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 66933a87..fa4cd8d3 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -247,7 +247,7 @@ async fn next_state( } // Ensure that the generated wallet is synced so we have a proper balance - monero_wallet.refresh().await?; + monero_wallet.refresh(3).await?; // Sweep (transfer all funds) to the given address let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?; diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 4f3f5fee..e81c78d3 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -865,7 +865,7 @@ impl Wallet for monero::Wallet { type Amount = monero::Amount; async fn refresh(&self) -> Result<()> { - self.refresh().await?; + self.refresh(1).await?; Ok(()) } From 07101deab1d4b802ce0d82e9d9020ef6985f3920 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 14 Dec 2023 18:34:30 +0100 Subject: [PATCH 161/395] Unify monero-wallet-rpc downloader logging --- swap/src/monero/wallet.rs | 2 +- swap/src/monero/wallet_rpc.rs | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 3ba99aac..8792994c 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -278,7 +278,7 @@ impl Wallet { match height { Err(error) => { - tracing::warn!(name = %wallet_name_clone, %error, "Failed to get current Monero wallet sync height"); + tracing::debug!(name = %wallet_name_clone, %error, "Failed to get current Monero wallet sync height"); } Ok(height) => { tracing::debug!(name = %wallet_name_clone, current_sync_height = height.height, "Syncing Monero wallet"); diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index e2f019a3..8973c021 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -221,9 +221,10 @@ impl WalletRpc { .parse::()?; tracing::info!( - "Downloading monero-wallet-rpc ({}) from {}", - content_length.big_byte(2), - DOWNLOAD_URL + progress="0%", + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", ); let byte_stream = response @@ -250,12 +251,24 @@ impl WalletRpc { let total = 3 * content_length; let percent = 100 * received as u64 / total; if percent != notified && percent % 10 == 0 { - tracing::debug!("{}%", percent); + tracing::info!( + progress=format!("{}%", percent), + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", + ); notified = percent; } file.write_all(&bytes).await?; } + tracing::info!( + progress="100%", + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", + ); + file.flush().await?; tracing::debug!("Extracting archive"); From 48abcd5b437597cae3e1c6684d821ab551701e28 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 14 Dec 2023 20:58:28 +0100 Subject: [PATCH 162/395] Add extra log message before opening redeem XMR wallet on Bob --- swap/src/protocol/bob/swap.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index fa4cd8d3..92d4f628 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -227,6 +227,9 @@ async fn next_state( let (spend_key, view_key) = state.xmr_keys(); let wallet_file_name = swap_id.to_string(); + + tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero"); + if let Err(e) = monero_wallet .create_from_and_load( wallet_file_name.clone(), From bd3e6136cecbb2bfd1ed5c940e1543d1f1970790 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:13:20 +0100 Subject: [PATCH 163/395] Update wallet.rs --- swap/src/monero/wallet.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 8792994c..61ed4ca4 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -310,6 +310,7 @@ impl Wallet { tracing::warn!(attempt=i, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet"); if attempts_left == 0 { + tracing::error!(name = %self.name, %error, "Failed to sync Monero wallet"); return Err(error); } } From 4f6f6b805478ecbf4f89dd84ddb1f9da5b09ef9b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:17:35 +0000 Subject: [PATCH 164/395] build(deps): bump async-trait from 0.1.75 to 0.1.76 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.75 to 0.1.76. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.75...0.1.76) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5e7f026..68bc4bc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.75" +version = "0.1.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" +checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" dependencies = [ "proc-macro2", "quote", From 1c8c9034c01bae3ca7e3445063a68fd3124b2be9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:18:24 +0000 Subject: [PATCH 165/395] build(deps): bump anyhow from 1.0.77 to 1.0.78 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.77 to 1.0.78. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.77...1.0.78) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5e7f026..ad67ecd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.77" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9" +checksum = "ca87830a3e3fb156dc96cfbd31cb620265dd053be734723f22b760d6cc3c3051" [[package]] name = "arrayref" From 5de4d1dfa7908f111cac7fc7ed74e5dd424da3e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:19:15 +0000 Subject: [PATCH 166/395] build(deps): bump thiserror from 1.0.52 to 1.0.53 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.52 to 1.0.53. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.52...1.0.53) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5e7f026..bfcc3c17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4513,18 +4513,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", From 81119af5231ce345642743f8106b9be7f64b4b0c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 11:20:15 +0000 Subject: [PATCH 167/395] build(deps): bump serde_json from 1.0.108 to 1.0.109 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.108 to 1.0.109. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.108...v1.0.109) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b5e7f026..e865bdf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3831,9 +3831,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" dependencies = [ "itoa 1.0.1", "ryu", From d675626477b9f61c5fe21cc1ddf2afb0d4ed32e7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:44:56 +0000 Subject: [PATCH 168/395] build(deps): bump serde from 1.0.193 to 1.0.194 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.193 to 1.0.194. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.193...v1.0.194) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a68c57..af734e72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,7 +151,7 @@ checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1383,7 +1383,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3054,9 +3054,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -3182,9 +3182,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3791,9 +3791,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" dependencies = [ "serde_derive", ] @@ -3820,13 +3820,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3905,7 +3905,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4301,7 +4301,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4405,9 +4405,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", @@ -4528,7 +4528,7 @@ checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4630,7 +4630,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4832,7 +4832,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] From ed2d0c9ddc8b90af37fe1f9c32959383b866e856 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:45:06 +0000 Subject: [PATCH 169/395] build(deps): bump async-trait from 0.1.76 to 0.1.77 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.76 to 0.1.77. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/commits) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a68c57..6fe24b11 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,13 +145,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.76" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1383,7 +1383,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3054,9 +3054,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -3182,9 +3182,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3826,7 +3826,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3905,7 +3905,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4301,7 +4301,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4405,9 +4405,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", @@ -4528,7 +4528,7 @@ checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4630,7 +4630,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4832,7 +4832,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] From 36c4e4fa6ec02f159523542a4d543ed25b90fef6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:45:19 +0000 Subject: [PATCH 170/395] build(deps): bump thiserror from 1.0.53 to 1.0.56 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.53 to 1.0.56. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.53...1.0.56) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a68c57..7a71774c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,7 +151,7 @@ checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1383,7 +1383,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3054,9 +3054,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -3182,9 +3182,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3826,7 +3826,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3905,7 +3905,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4301,7 +4301,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4405,9 +4405,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", @@ -4513,22 +4513,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4630,7 +4630,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4832,7 +4832,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] From 10ba9203fa8a2f7db4459dbbd4612ac34ea62ffb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:45:36 +0000 Subject: [PATCH 171/395] build(deps): bump serde_json from 1.0.109 to 1.0.110 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.109 to 1.0.110. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.109...v1.0.110) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a68c57..9bb509e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,7 +151,7 @@ checksum = "531b97fb4cd3dfdce92c35dedbfdc1f0b9d8091c8ca943d6dae340ef5012d514" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -1383,7 +1383,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -3054,9 +3054,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" dependencies = [ "unicode-ident", ] @@ -3182,9 +3182,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -3791,9 +3791,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" dependencies = [ "serde_derive", ] @@ -3820,20 +3820,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.194" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] name = "serde_json" -version = "1.0.109" +version = "1.0.110" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0652c533506ad7a2e353cce269330d6afd8bdfb6d75e0ace5b35aacbd7b9e9" +checksum = "6fbd975230bada99c8bb618e0c365c2eefa219158d5c6c29610fd09ff1833257" dependencies = [ "itoa 1.0.1", "ryu", @@ -3905,7 +3905,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4301,7 +4301,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4405,9 +4405,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.40" +version = "2.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13fa70a4ee923979ffb522cacce59d34421ebdea5625e1073c4326ef9d2dd42e" +checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" dependencies = [ "proc-macro2", "quote", @@ -4528,7 +4528,7 @@ checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4630,7 +4630,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] @@ -4832,7 +4832,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.40", + "syn 2.0.46", ] [[package]] From b31779dfe117b428c0998c23750339609a650424 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:46:23 +0000 Subject: [PATCH 172/395] build(deps): bump anyhow from 1.0.78 to 1.0.79 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.78 to 1.0.79. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.78...1.0.79) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a68c57..d23d4c86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca87830a3e3fb156dc96cfbd31cb620265dd053be734723f22b760d6cc3c3051" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "arrayref" From 57d19ad85281ed9da8c20a051d35bd4c6506b8ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:46:51 +0000 Subject: [PATCH 173/395] build(deps): bump serde_json from 1.0.110 to 1.0.111 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.110 to 1.0.111. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.110...v1.0.111) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2af4443..d755d99c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3831,9 +3831,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.110" +version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fbd975230bada99c8bb618e0c365c2eefa219158d5c6c29610fd09ff1833257" +checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "itoa 1.0.1", "ryu", From dd9d5246c3d1f1ef200610ed64f5e5876cc06d36 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:27:04 +0000 Subject: [PATCH 174/395] build(deps): bump serial_test from 2.0.0 to 3.0.0 Bumps [serial_test](https://github.com/palfrey/serial_test) from 2.0.0 to 3.0.0. - [Release notes](https://github.com/palfrey/serial_test/releases) - [Commits](https://github.com/palfrey/serial_test/compare/v2.0.0...v3.0.0) --- updated-dependencies: - dependency-name: serial_test dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- swap/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1019c937..9141f22c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3885,9 +3885,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" +checksum = "953ad9342b3aaca7cb43c45c097dd008d4907070394bd0751a0aa8817e5a018d" dependencies = [ "dashmap", "futures", @@ -3899,9 +3899,9 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" +checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" dependencies = [ "proc-macro2", "quote", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index cb9dfb2a..4caf2571 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -82,7 +82,7 @@ monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" serde_cbor = "0.11" -serial_test = "2.0" +serial_test = "3.0" spectral = "0.6" tempfile = "3" testcontainers = "0.12" From afe0060c4aa7d9079bb8cf77b604dc5e2974d1fd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:27:16 +0000 Subject: [PATCH 175/395] build(deps): bump serde from 1.0.194 to 1.0.195 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.194 to 1.0.195. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.194...v1.0.195) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1019c937..4783991a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,9 +3791,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] @@ -3820,9 +3820,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.194" +version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", From f50ee16bf1d698dd98d8935b6aeee5ae00fcf994 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:20:03 +0000 Subject: [PATCH 176/395] build(deps): bump base64 from 0.21.5 to 0.21.6 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.5 to 0.21.6. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.5...v0.21.6) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4783991a..10a389bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,9 +260,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" [[package]] name = "bdk" @@ -2866,7 +2866,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "serde", ] @@ -3401,7 +3401,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.6", "bytes", "encoding_rs", "futures-core", @@ -4325,7 +4325,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.21.5", + "base64 0.21.6", "bdk", "big-bytes", "bitcoin", From aedabcbcbb4abdf994a4b9e2780b52f091671674 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Jan 2024 11:43:10 +0000 Subject: [PATCH 177/395] build(deps): bump Swatinem/rust-cache from 2.7.1 to 2.7.2 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.1 to 2.7.2. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.7.1...v2.7.2) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 3bf9aefd..ad0ad629 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 90824b4c..4bbc7474 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: toolchain: "1.70" components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - name: Check formatting uses: dprint/check@v2.2 @@ -37,7 +37,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - name: Build swap run: cargo build --bin swap @@ -51,7 +51,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - name: Install sqlx-cli run: cargo install sqlx-cli --locked @@ -78,7 +78,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - uses: dtolnay/rust-toolchain@master with: @@ -118,7 +118,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - name: Build tests run: cargo build --tests --workspace --all-features @@ -155,7 +155,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.2 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From b945fa3ee6348f1c6a27da790f06044a0d2f97de Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jan 2024 11:13:36 +0000 Subject: [PATCH 178/395] build(deps): bump base64 from 0.21.6 to 0.21.7 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.6 to 0.21.7. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.6...v0.21.7) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a389bc..2c6becef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -260,9 +260,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.6" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c79fed4cdb43e993fcdadc7e58a09fd0e3e649c4436fa11da71c9f1f3ee7feb9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bdk" @@ -2866,7 +2866,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "serde", ] @@ -3401,7 +3401,7 @@ version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.6", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -4325,7 +4325,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.21.6", + "base64 0.21.7", "bdk", "big-bytes", "bitcoin", From 85712aa95fffc9f4b289c202af1e3e25332ccb6d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Jan 2024 11:38:18 +0000 Subject: [PATCH 179/395] build(deps): bump Swatinem/rust-cache from 2.7.2 to 2.7.3 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.2 to 2.7.3. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.7.2...v2.7.3) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index ad0ad629..48888845 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -50,7 +50,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4bbc7474..55ff513d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: toolchain: "1.70" components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - name: Check formatting uses: dprint/check@v2.2 @@ -37,7 +37,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - name: Build swap run: cargo build --bin swap @@ -51,7 +51,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - name: Install sqlx-cli run: cargo install sqlx-cli --locked @@ -78,7 +78,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - uses: dtolnay/rust-toolchain@master with: @@ -118,7 +118,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - name: Build tests run: cargo build --tests --workspace --all-features @@ -155,7 +155,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.2 + - uses: Swatinem/rust-cache@v2.7.3 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture From fada511c9ae6b768b05f1deacb54a256f0b0feb6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 11:58:59 +0000 Subject: [PATCH 180/395] build(deps): bump uuid from 1.6.1 to 1.7.0 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.6.1 to 1.7.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.6.1...1.7.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2c6becef..ee3f0ddc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5130,9 +5130,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ "getrandom 0.2.11", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index cb9dfb2a..0ff331bb 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -64,7 +64,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.6", features = [ "serde", "v4" ] } +uuid = { version = "1.7", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From 44875e22748ffe09da20bf71341b852126ae9e4f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:05:33 +0000 Subject: [PATCH 181/395] build(deps): bump serde_json from 1.0.111 to 1.0.113 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.111 to 1.0.113. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.111...v1.0.113) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee3f0ddc..521d30c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3831,9 +3831,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ "itoa 1.0.1", "ryu", From 1ad6af6d5cf1a69aa2ca47adc3093f75d1131a13 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:06:15 +0000 Subject: [PATCH 182/395] build(deps): bump strum from 0.25.0 to 0.26.1 Bumps [strum](https://github.com/Peternator7/strum) from 0.25.0 to 0.26.1. - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 27 +++++++++++++++++++++++---- swap/Cargo.toml | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee3f0ddc..44e839c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -688,8 +688,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" dependencies = [ "crossterm", - "strum", - "strum_macros", + "strum 0.25.0", + "strum_macros 0.25.3", "unicode-width", ] @@ -4287,8 +4287,14 @@ name = "strum" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" + +[[package]] +name = "strum" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" dependencies = [ - "strum_macros", + "strum_macros 0.26.1", ] [[package]] @@ -4304,6 +4310,19 @@ dependencies = [ "syn 2.0.46", ] +[[package]] +name = "strum_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.46", +] + [[package]] name = "subtle" version = "2.4.0" @@ -4369,7 +4388,7 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum", + "strum 0.26.1", "tempfile", "testcontainers 0.12.0", "thiserror", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 0ff331bb..9533666a 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -50,7 +50,7 @@ sha2 = "0.10" sigma_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "ed25519", "serde", "secp256k1", "alloc" ] } sqlx = { version = "0.6", features = [ "sqlite", "runtime-tokio-rustls", "offline" ] } structopt = "0.3" -strum = { version = "0.25", features = [ "derive" ] } +strum = { version = "0.26", features = [ "derive" ] } thiserror = "1" time = "0.3" tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } From 9d9e408ee05a5e3dceee999a9f51a0e37c35c53f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jan 2024 11:06:50 +0000 Subject: [PATCH 183/395] build(deps): bump serde from 1.0.195 to 1.0.196 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.195 to 1.0.196. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.195...v1.0.196) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee3f0ddc..810b57ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,9 +3791,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] @@ -3820,9 +3820,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", From db7fe0dc997bb068c3a067846657744762f76851 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 11:41:32 +0000 Subject: [PATCH 184/395] build(deps): bump itertools from 0.12.0 to 0.12.1 Bumps [itertools](https://github.com/rust-itertools/itertools) from 0.12.0 to 0.12.1. - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-itertools/itertools/compare/v0.12.0...v0.12.1) --- updated-dependencies: - dependency-name: itertools dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1689038..18312c63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1894,9 +1894,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] @@ -4363,7 +4363,7 @@ dependencies = [ "get-port", "hex", "hyper 1.1.0", - "itertools 0.12.0", + "itertools 0.12.1", "libp2p", "mockito", "monero", From 45d6326dc16aa0ec1e7f5f0da29d11e7c1cc8a4c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:32:36 +0000 Subject: [PATCH 185/395] build(deps): bump toml from 0.8.8 to 0.8.9 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.8 to 0.8.9. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.8...toml-v0.8.9) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18312c63..38e50b43 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3842,9 +3842,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" +checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" dependencies = [ "serde", ] @@ -4398,7 +4398,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.8", + "toml 0.8.9", "torut", "tracing", "tracing-appender", @@ -4764,9 +4764,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" dependencies = [ "serde", "serde_spanned", @@ -4785,9 +4785,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.1.0", "serde", From 83080abe30fe8e574b594dd6681cdf15e731664c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:32:59 +0000 Subject: [PATCH 186/395] build(deps): bump config from 0.13.4 to 0.14.0 Bumps [config](https://github.com/mehcode/config-rs) from 0.13.4 to 0.14.0. - [Changelog](https://github.com/mehcode/config-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/mehcode/config-rs/compare/v0.13.4...0.14.0) --- updated-dependencies: - dependency-name: config dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 7 +++---- swap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18312c63..36cd0241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -695,16 +695,15 @@ dependencies = [ [[package]] name = "config" -version = "0.13.4" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" +checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" dependencies = [ - "async-trait", "lazy_static", "nom", "pathdiff", "serde", - "toml 0.5.11", + "toml 0.8.8", ] [[package]] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index ebac362a..f850085b 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -20,7 +20,7 @@ big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } bmrng = "0.5" comfy-table = "7.1" -config = { version = "0.13", default-features = false, features = [ "toml" ] } +config = { version = "0.14", default-features = false, features = [ "toml" ] } conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } data-encoding = "2.5" From 9a024db955037bfee41c7047771f58b81f88090c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:33:32 +0000 Subject: [PATCH 187/395] build(deps): bump time from 0.3.31 to 0.3.32 Bumps [time](https://github.com/time-rs/time) from 0.3.31 to 0.3.32. - [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.31...v0.3.32) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18312c63..6186d732 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2671,6 +2671,12 @@ dependencies = [ "rustc-serialize", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" version = "0.1.44" @@ -4392,7 +4398,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.31", + "time 0.3.32", "tokio", "tokio-socks", "tokio-tar", @@ -4571,12 +4577,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd" dependencies = [ "deranged", "itoa 1.0.1", + "num-conv", "powerfmt", "serde", "time-core", @@ -4591,10 +4598,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -4839,7 +4847,7 @@ checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror", - "time 0.3.31", + "time 0.3.32", "tracing-subscriber 0.3.18", ] @@ -4940,7 +4948,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.31", + "time 0.3.32", "tracing", "tracing-core", "tracing-log 0.2.0", @@ -5188,7 +5196,7 @@ dependencies = [ "git2", "rustversion", "thiserror", - "time 0.3.31", + "time 0.3.32", ] [[package]] From e08770f405569bd97572a803c6d70477bfa76749 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 11:34:26 +0000 Subject: [PATCH 188/395] build(deps): bump reqwest from 0.11.23 to 0.11.24 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.23 to 0.11.24. - [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.23...v0.11.24) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 51 +++++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18312c63..24a7e53b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1924,9 +1924,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.48" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -3397,9 +3397,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ "base64 0.21.7", "bytes", @@ -3423,6 +3423,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls 0.24.0", @@ -4433,6 +4434,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.4" @@ -5236,9 +5243,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -5246,24 +5253,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.46", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.21" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e67a5806118af01f0d9045915676b22aaebecf4178ae7021bc171dab0b897ab" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -5273,9 +5280,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5283,28 +5290,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.46", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "wasm-streams" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" +checksum = "b65dc4c90b63b118468cf747d8bf3566c1913ef60be765b5730ead9e0a3ba129" dependencies = [ "futures-util", "js-sys", @@ -5315,9 +5322,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.48" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", From 140dc6dc04d4bbebd047d4f76571eec41ce8cd4d Mon Sep 17 00:00:00 2001 From: Ian McKenzie <13459320+ikmckenz@users.noreply.github.com> Date: Sat, 3 Feb 2024 22:43:59 -0800 Subject: [PATCH 189/395] Upgrade to vergen 8.3, move to git describe --dirty --tags for semver (#1543) * Upgrade to vergen 8.3, move to git describe --dirty --tags for semver * Add newline to build.rs --- Cargo.lock | 66 +++++++++++++---------------------------- swap/Cargo.toml | 2 +- swap/build.rs | 10 +++---- swap/src/asb/command.rs | 2 +- swap/src/cli/command.rs | 2 +- 5 files changed, 29 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4fd45c1..5724a107 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.8", + "toml 0.8.9", ] [[package]] @@ -1180,26 +1180,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "enum-iterator" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91a4ec26efacf4aeff80887a175a419493cb6f8b5480d26387eb0bd038976187" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1480,18 +1460,6 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] -[[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "ghash" version = "0.4.1" @@ -1510,11 +1478,11 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "git2" -version = "0.16.1" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf7f68c2995f392c49fffb4f95ae2c873297830eb25c6bc4c114ce8f4562acc" +checksum = "fbf97ba92db08df386e10c8ede66a2a0369bd277090afd8710e19e38de9ec0cd" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "libc", "libgit2-sys", "log", @@ -1984,9 +1952,9 @@ checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libgit2-sys" -version = "0.14.2+1.5.1" +version = "0.16.1+1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f3d95f6b51075fe9810a7ae22c7095f12b98005ab364d8544797a825ce946a4" +checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c" dependencies = [ "cc", "libc", @@ -2740,6 +2708,15 @@ dependencies = [ "libc", ] +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.32.1" @@ -3646,9 +3623,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rusty-fork" @@ -4589,7 +4566,9 @@ checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd" dependencies = [ "deranged", "itoa 1.0.1", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -5191,17 +5170,14 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "7.5.1" +version = "8.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21b881cd6636ece9735721cf03c1fe1e774fe258683d084bb2812ab67435749" +checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" dependencies = [ "anyhow", "cfg-if 1.0.0", - "enum-iterator", - "getset", "git2", "rustversion", - "thiserror", "time 0.3.32", ] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index f850085b..2be46da8 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -89,4 +89,4 @@ testcontainers = "0.12" [build-dependencies] anyhow = "1" -vergen = { version = "7.5", default-features = false, features = [ "git", "build" ] } +vergen = { version = "8.3", default-features = false, features = [ "build", "git", "git2" ] } diff --git a/swap/build.rs b/swap/build.rs index 10b11e3c..57bbce40 100644 --- a/swap/build.rs +++ b/swap/build.rs @@ -1,9 +1,9 @@ use anyhow::Result; -use vergen::{vergen, Config, SemverKind}; +use vergen::EmitBuilder; fn main() -> Result<()> { - let mut config = Config::default(); - *config.git_mut().semver_kind_mut() = SemverKind::Lightweight; - - vergen(config) + EmitBuilder::builder() + .git_describe(true, true, None) + .emit()?; + Ok(()) } diff --git a/swap/src/asb/command.rs b/swap/src/asb/command.rs index 6831e595..f22e1500 100644 --- a/swap/src/asb/command.rs +++ b/swap/src/asb/command.rs @@ -226,7 +226,7 @@ pub enum Command { name = "asb", about = "Automated Swap Backend for swapping XMR for BTC", author, - version = env!("VERGEN_GIT_SEMVER_LIGHTWEIGHT") + version = env!("VERGEN_GIT_DESCRIBE") )] pub struct RawArguments { #[structopt(long, help = "Swap on testnet")] diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index ee48428a..5c3b2827 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -298,7 +298,7 @@ pub enum Command { name = "swap", about = "CLI for swapping BTC for XMR", author, - version = env!("VERGEN_GIT_SEMVER_LIGHTWEIGHT") + version = env!("VERGEN_GIT_DESCRIBE") )] struct RawArguments { // global is necessary to ensure that clap can match against testnet in subcommands From ac2a13b1d02a4067328d60359d22312a0ca94a53 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:28:50 +0000 Subject: [PATCH 190/395] build(deps): bump time from 0.3.32 to 0.3.34 Bumps [time](https://github.com/time-rs/time) from 0.3.32 to 0.3.34. - [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.32...v0.3.34) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5724a107..465bce38 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4375,7 +4375,7 @@ dependencies = [ "tempfile", "testcontainers 0.12.0", "thiserror", - "time 0.3.32", + "time 0.3.34", "tokio", "tokio-socks", "tokio-tar", @@ -4560,9 +4560,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe80ced77cbfb4cb91a94bf72b378b4b6791a0d9b7f09d0be747d1bdff4e68bd" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa 1.0.1", @@ -4832,7 +4832,7 @@ checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror", - "time 0.3.32", + "time 0.3.34", "tracing-subscriber 0.3.18", ] @@ -4933,7 +4933,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.32", + "time 0.3.34", "tracing", "tracing-core", "tracing-log 0.2.0", @@ -5178,7 +5178,7 @@ dependencies = [ "cfg-if 1.0.0", "git2", "rustversion", - "time 0.3.32", + "time 0.3.34", ] [[package]] From 1b0a6d22fe0a41946ca5b5573a6fea1dad9d43c8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 11:29:31 +0000 Subject: [PATCH 191/395] build(deps): bump tokio from 1.35.1 to 1.36.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.35.1 to 1.36.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.35.1...tokio-1.36.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5724a107..f292ddba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4617,9 +4617,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", From b1a72940df22cd3985dcd931fb45099090270daf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:53:45 +0000 Subject: [PATCH 192/395] build(deps): bump tempfile from 3.9.0 to 3.10.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.9.0 to 3.10.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.9.0...v3.10.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d750ec3..df62fcb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1946,9 +1946,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libgit2-sys" @@ -3316,15 +3316,6 @@ dependencies = [ "bitflags 1.3.2", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_users" version = "0.4.0" @@ -3542,9 +3533,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.4.0", "errno", @@ -4457,13 +4448,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.9.0" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" +checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" dependencies = [ "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.4.1", "rustix", "windows-sys 0.52.0", ] From 039192aeb6c659c13b3c96ccbf1b4edfc0ab0333 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:54:55 +0000 Subject: [PATCH 193/395] build(deps): bump toml from 0.8.9 to 0.8.10 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.9 to 0.8.10. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.9...toml-v0.8.10) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d750ec3..789cf7b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.9", + "toml 0.8.10", ] [[package]] @@ -4381,7 +4381,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.9", + "toml 0.8.10", "torut", "tracing", "tracing-appender", @@ -4757,9 +4757,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" +checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" dependencies = [ "serde", "serde_spanned", @@ -4778,9 +4778,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" dependencies = [ "indexmap 2.1.0", "serde", From f12cf363647c1b8c6de893ddf6096fd7a5e75e93 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 14 Feb 2024 22:22:35 +0200 Subject: [PATCH 194/395] ci: free up space on ubuntu test job (#1555) * ci: free up space on ubuntu test job (cherry picked from commit d234d2335f49ba5c0284fe0efd696856be2e58bf) * fixup! ci: free up space on ubuntu test job * ci use commit hash instead of malleable tag for free space action --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55ff513d..5ff9a6d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,6 +115,19 @@ jobs: os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: + - name: (Free disk space on Ubuntu) + if: matrix.os == 'ubuntu-latest' + uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be + with: + # removing all of these takes ~10 mins, so just do as needed + android: true + dotnet: true + haskell: true + docker-images: false + large-packages: false + swap-storage: false + tool-cache: false + - name: Checkout sources uses: actions/checkout@v4.1.1 From 3d2b51998e661c3e6808b103045a736fcf06d5b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 04:29:12 +0000 Subject: [PATCH 195/395] build(deps): bump thomaseizinger/keep-a-changelog-new-release Bumps [thomaseizinger/keep-a-changelog-new-release](https://github.com/thomaseizinger/keep-a-changelog-new-release) from 1.3.0 to 2.0.0. - [Release notes](https://github.com/thomaseizinger/keep-a-changelog-new-release/releases) - [Changelog](https://github.com/thomaseizinger/keep-a-changelog-new-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/thomaseizinger/keep-a-changelog-new-release/compare/1.3.0...2.0.0) --- updated-dependencies: - dependency-name: thomaseizinger/keep-a-changelog-new-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/draft-new-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 70a623a8..d980d388 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -20,7 +20,7 @@ jobs: run: git checkout -b release/${{ github.event.inputs.version }} - name: Update changelog - uses: thomaseizinger/keep-a-changelog-new-release@1.3.0 + uses: thomaseizinger/keep-a-changelog-new-release@2.0.0 with: version: ${{ github.event.inputs.version }} changelogPath: CHANGELOG.md From 640290023ad00581e8bd917d4fc3d1804d04842d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Feb 2024 04:30:57 +0000 Subject: [PATCH 196/395] build(deps): bump thiserror from 1.0.56 to 1.0.57 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.56 to 1.0.57. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.56...1.0.57) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e4612376..591593b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4511,18 +4511,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ "proc-macro2", "quote", From 2c11f3865984c5cb8e240d5e9ee8698f418f3cd0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Feb 2024 11:59:24 +0000 Subject: [PATCH 197/395] build(deps): bump anyhow from 1.0.79 to 1.0.80 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.79 to 1.0.80. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.79...1.0.80) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 591593b2..9cda5977 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arrayref" From d8d1c4178eab7cbdcc9c5d5acb4122d72524eff9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:55:23 +0000 Subject: [PATCH 198/395] build(deps): bump serde_json from 1.0.113 to 1.0.114 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.113 to 1.0.114. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.113...v1.0.114) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9cda5977..bee36efd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3805,9 +3805,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.113" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa 1.0.1", "ryu", From 344440bb5476e95d309ed276d26f5fc22c1bb72a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:55:59 +0000 Subject: [PATCH 199/395] build(deps): bump serde from 1.0.196 to 1.0.197 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.196 to 1.0.197. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.196...v1.0.197) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9cda5977..82ae25e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3765,9 +3765,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -3794,9 +3794,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.196" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", From 005361c833b8fa8eefbe39b6913dbf2d76fb28b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:43:08 +0000 Subject: [PATCH 200/395] build(deps): bump hyper from 1.1.0 to 1.2.0 Bumps [hyper](https://github.com/hyperium/hyper) from 1.1.0 to 1.2.0. - [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/v1.1.0...v1.2.0) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 7 +++---- swap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52ad6987..4deb6706 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1718,14 +1718,13 @@ dependencies = [ [[package]] name = "hyper" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "http 1.0.0", "http-body 1.0.0", - "pin-project-lite 0.2.13", "tokio", ] @@ -4336,7 +4335,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper 1.1.0", + "hyper 1.2.0", "itertools 0.12.1", "libp2p", "mockito", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 2be46da8..c900f0b4 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -76,7 +76,7 @@ zip = "0.5" [dev-dependencies] bitcoin-harness = "0.2.2" get-port = "3" -hyper = "1.1" +hyper = "1.2" mockito = "1.2.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" From b2ca1b5f8c2249355cf933199d1888b6065a3d44 Mon Sep 17 00:00:00 2001 From: Ian McKenzie <13459320+ikmckenz@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:04:27 -0800 Subject: [PATCH 201/395] Upgrade testcontainers from 0.12 to 0.14 (#1552) * Upgrade testcontainers from 0.12 to 0.14 * minor cleanup --------- Co-authored-by: Byron Hambly --- Cargo.lock | 43 ++------------ monero-harness/Cargo.toml | 2 +- monero-harness/src/image.rs | 103 ++++++++++----------------------- monero-harness/src/lib.rs | 50 ++++++++-------- monero-wallet/Cargo.toml | 2 +- monero-wallet/src/lib.rs | 3 +- swap/Cargo.toml | 2 +- swap/tests/harness/bitcoind.rs | 65 ++++++--------------- swap/tests/harness/electrs.rs | 66 +++++++++------------ swap/tests/harness/mod.rs | 57 +++++++++--------- 10 files changed, 136 insertions(+), 257 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4deb6706..0708533b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -366,7 +366,7 @@ dependencies = [ "reqwest", "serde", "serde_json", - "testcontainers 0.14.0", + "testcontainers", "thiserror", "tokio", "tracing", @@ -896,16 +896,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "crypto-mac" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" -dependencies = [ - "generic-array", - "subtle", -] - [[package]] name = "crypto-mac" version = "0.11.1" @@ -1598,16 +1588,6 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" -[[package]] -name = "hmac" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" -dependencies = [ - "crypto-mac 0.10.0", - "digest 0.9.0", -] - [[package]] name = "hmac" version = "0.11.0" @@ -2468,7 +2448,7 @@ dependencies = [ "monero-rpc", "rand 0.7.3", "spectral", - "testcontainers 0.12.0", + "testcontainers", "tokio", "tracing", "tracing-subscriber 0.2.25", @@ -2504,7 +2484,7 @@ dependencies = [ "monero-harness", "monero-rpc", "rand 0.7.3", - "testcontainers 0.12.0", + "testcontainers", "tokio", "tracing-subscriber 0.2.25", ] @@ -4363,7 +4343,7 @@ dependencies = [ "structopt", "strum 0.26.1", "tempfile", - "testcontainers 0.12.0", + "testcontainers", "thiserror", "time 0.3.34", "tokio", @@ -4467,21 +4447,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "testcontainers" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e3ed6e3598dbf32cba8cb356b881c085e0adea57597f387723430dd94b4084" -dependencies = [ - "hex", - "hmac 0.10.1", - "log", - "rand 0.8.3", - "serde", - "serde_json", - "sha2 0.9.8", -] - [[package]] name = "testcontainers" version = "0.14.0" diff --git a/monero-harness/Cargo.toml b/monero-harness/Cargo.toml index b659220b..6780dbd8 100644 --- a/monero-harness/Cargo.toml +++ b/monero-harness/Cargo.toml @@ -11,7 +11,7 @@ futures = "0.3" monero-rpc = { path = "../monero-rpc" } rand = "0.7" spectral = "0.6" -testcontainers = "0.12" +testcontainers = "0.14" tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "macros" ] } tracing = "0.1" tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "tracing-log" ] } diff --git a/monero-harness/src/image.rs b/monero-harness/src/image.rs index 63cc4b20..d4dd3942 100644 --- a/monero-harness/src/image.rs +++ b/monero-harness/src/image.rs @@ -1,6 +1,4 @@ -use std::collections::HashMap; -use testcontainers::core::{Container, Docker, WaitForMessage}; -use testcontainers::Image; +use testcontainers::{core::WaitFor, Image, ImageArgs}; pub const MONEROD_DAEMON_CONTAINER_NAME: &str = "monerod"; pub const MONEROD_DEFAULT_NETWORK: &str = "monero_network"; @@ -13,43 +11,22 @@ pub const MONEROD_DEFAULT_NETWORK: &str = "monero_network"; /// this doesn't matter. pub const RPC_PORT: u16 = 18081; -#[derive(Debug, Default)] -pub struct Monerod { - args: MonerodArgs, -} +#[derive(Clone, Copy, Debug, Default)] +pub struct Monerod; impl Image for Monerod { type Args = MonerodArgs; - type EnvVars = HashMap; - type Volumes = HashMap; - type EntryPoint = str; - fn descriptor(&self) -> String { - "rinocommunity/monero:v0.18.1.2".to_owned() + fn name(&self) -> String { + "rinocommunity/monero".into() } - fn wait_until_ready(&self, container: &Container<'_, D, Self>) { - container - .logs() - .stdout - .wait_for_message("RPC server started ok") - .unwrap(); + fn tag(&self) -> String { + "v0.18.1.2".into() } - fn args(&self) -> ::Args { - self.args.clone() - } - - fn volumes(&self) -> Self::Volumes { - HashMap::new() - } - - fn env_vars(&self) -> Self::EnvVars { - HashMap::new() - } - - fn with_args(self, args: ::Args) -> Self { - Self { args } + fn ready_conditions(&self) -> Vec { + vec![WaitFor::message_on_stdout("RPC server started ok")] } fn entrypoint(&self) -> Option { @@ -58,43 +35,22 @@ impl Image for Monerod { } } -#[derive(Debug, Default)] -pub struct MoneroWalletRpc { - args: MoneroWalletRpcArgs, -} +#[derive(Clone, Copy, Debug)] +pub struct MoneroWalletRpc; impl Image for MoneroWalletRpc { type Args = MoneroWalletRpcArgs; - type EnvVars = HashMap; - type Volumes = HashMap; - type EntryPoint = str; - fn descriptor(&self) -> String { - "rinocommunity/monero:v0.18.1.2".to_owned() + fn name(&self) -> String { + "rinocommunity/monero".into() } - fn wait_until_ready(&self, container: &Container<'_, D, Self>) { - container - .logs() - .stdout - .wait_for_message("Run server thread name: RPC") - .unwrap(); + fn tag(&self) -> String { + "v0.18.1.2".into() } - fn args(&self) -> ::Args { - self.args.clone() - } - - fn volumes(&self) -> Self::Volumes { - HashMap::new() - } - - fn env_vars(&self) -> Self::EnvVars { - HashMap::new() - } - - fn with_args(self, args: ::Args) -> Self { - Self { args } + fn ready_conditions(&self) -> Vec { + vec![WaitFor::message_on_stdout("Run server thread name: RPC")] } fn entrypoint(&self) -> Option { @@ -104,10 +60,9 @@ impl Image for MoneroWalletRpc { } impl MoneroWalletRpc { - pub fn new(name: &str, daemon_address: String) -> Self { - Self { - args: MoneroWalletRpcArgs::new(name, daemon_address), - } + pub fn new(name: &str, daemon_address: String) -> (Self, MoneroWalletRpcArgs) { + let args = MoneroWalletRpcArgs::new(name, daemon_address); + (Self, args) } } @@ -191,6 +146,12 @@ impl IntoIterator for MonerodArgs { } } +impl ImageArgs for MonerodArgs { + fn into_iterator(self) -> Box> { + Box::new(self.into_iter()) + } +} + #[derive(Debug, Clone)] pub struct MoneroWalletRpcArgs { pub disable_rpc_login: bool, @@ -200,12 +161,6 @@ pub struct MoneroWalletRpcArgs { pub daemon_address: String, } -impl Default for MoneroWalletRpcArgs { - fn default() -> Self { - unimplemented!("A default instance for `MoneroWalletRpc` doesn't make sense because we always need to connect to a node.") - } -} - impl MoneroWalletRpcArgs { pub fn new(wallet_name: &str, daemon_address: String) -> Self { Self { @@ -247,3 +202,9 @@ impl IntoIterator for MoneroWalletRpcArgs { args.into_iter() } } + +impl ImageArgs for MoneroWalletRpcArgs { + fn into_iterator(self) -> Box> { + Box::new(self.into_iter()) + } +} diff --git a/monero-harness/src/lib.rs b/monero-harness/src/lib.rs index 46a03002..d5f8a513 100644 --- a/monero-harness/src/lib.rs +++ b/monero-harness/src/lib.rs @@ -20,17 +20,20 @@ //! every BLOCK_TIME_SECS seconds. //! //! Also provides standalone JSON RPC clients for monerod and monero-wallet-rpc. -pub mod image; +use std::time::Duration; -use crate::image::{MONEROD_DAEMON_CONTAINER_NAME, MONEROD_DEFAULT_NETWORK, RPC_PORT}; use anyhow::{anyhow, bail, Context, Result}; +use testcontainers::clients::Cli; +use testcontainers::{Container, RunnableImage}; +use tokio::time; + use monero_rpc::monerod; use monero_rpc::monerod::MonerodRpc as _; use monero_rpc::wallet::{self, GetAddress, MoneroWalletRpc as _, Refreshed, Transfer}; -use std::time::Duration; -use testcontainers::clients::Cli; -use testcontainers::{Container, Docker, RunArgs}; -use tokio::time; + +use crate::image::{MONEROD_DAEMON_CONTAINER_NAME, MONEROD_DEFAULT_NETWORK, RPC_PORT}; + +pub mod image; /// How often we mine a block. const BLOCK_TIME_SECS: u64 = 1; @@ -56,8 +59,8 @@ impl<'c> Monero { additional_wallets: Vec<&'static str>, ) -> Result<( Self, - Container<'c, Cli, image::Monerod>, - Vec>, + Container<'c, image::Monerod>, + Vec>, )> { let prefix = format!("{}_", random_prefix()); let monerod_name = format!("{}{}", prefix, MONEROD_DAEMON_CONTAINER_NAME); @@ -221,15 +224,14 @@ impl<'c> Monerod { cli: &'c Cli, name: String, network: String, - ) -> Result<(Self, Container<'c, Cli, image::Monerod>)> { + ) -> Result<(Self, Container<'c, image::Monerod>)> { let image = image::Monerod::default(); - let run_args = RunArgs::default() - .with_name(name.clone()) + let image: RunnableImage = RunnableImage::from(image) + .with_container_name(name.clone()) .with_network(network.clone()); - let container = cli.run_with_args(image, run_args); - let monerod_rpc_port = container - .get_host_port(RPC_PORT) - .context("port not exposed")?; + + let container = cli.run(image); + let monerod_rpc_port = container.get_host_port_ipv4(RPC_PORT); Ok(( Self { @@ -262,19 +264,15 @@ impl<'c> MoneroWalletRpc { name: &str, monerod: &Monerod, prefix: String, - ) -> Result<(Self, Container<'c, Cli, image::MoneroWalletRpc>)> { + ) -> Result<(Self, Container<'c, image::MoneroWalletRpc>)> { let daemon_address = format!("{}:{}", monerod.name, RPC_PORT); - let image = image::MoneroWalletRpc::new(name, daemon_address); + let (image, args) = image::MoneroWalletRpc::new(name, daemon_address); + let image = RunnableImage::from((image, args)) + .with_container_name(format!("{}{}", prefix, name)) + .with_network(monerod.network.clone()); - let network = monerod.network.clone(); - let run_args = RunArgs::default() - // prefix the container name so we can run multiple tests - .with_name(format!("{}{}", prefix, name)) - .with_network(network.clone()); - let container = cli.run_with_args(image, run_args); - let wallet_rpc_port = container - .get_host_port(RPC_PORT) - .context("port not exposed")?; + let container = cli.run(image); + let wallet_rpc_port = container.get_host_port_ipv4(RPC_PORT); let client = wallet::Client::localhost(wallet_rpc_port)?; diff --git a/monero-wallet/Cargo.toml b/monero-wallet/Cargo.toml index f767b08e..81982c83 100644 --- a/monero-wallet/Cargo.toml +++ b/monero-wallet/Cargo.toml @@ -14,6 +14,6 @@ rand = "0.7" curve25519-dalek = "3" monero-harness = { path = "../monero-harness" } rand = "0.7" -testcontainers = "0.12" +testcontainers = "0.14" tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs" ] } tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "chrono", "tracing-log" ] } diff --git a/monero-wallet/src/lib.rs b/monero-wallet/src/lib.rs index 2058f476..080c2599 100644 --- a/monero-wallet/src/lib.rs +++ b/monero-wallet/src/lib.rs @@ -61,13 +61,12 @@ mod tests { use monero_harness::image::Monerod; use monero_rpc::monerod::{Client, GetOutputsOut}; use testcontainers::clients::Cli; - use testcontainers::Docker; #[tokio::test] async fn get_outs_for_key_offsets() { let cli = Cli::default(); let container = cli.run(Monerod::default()); - let rpc_client = Client::localhost(container.get_host_port(18081).unwrap()).unwrap(); + let rpc_client = Client::localhost(container.get_host_port_ipv4(18081)).unwrap(); rpc_client.generateblocks(150, "498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj".to_owned()).await.unwrap(); let wallet = Wallet { client: rpc_client.clone(), diff --git a/swap/Cargo.toml b/swap/Cargo.toml index c900f0b4..3c1d2336 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -85,7 +85,7 @@ serde_cbor = "0.11" serial_test = "3.0" spectral = "0.6" tempfile = "3" -testcontainers = "0.12" +testcontainers = "0.14" [build-dependencies] anyhow = "1" diff --git a/swap/tests/harness/bitcoind.rs b/swap/tests/harness/bitcoind.rs index 13aa5658..fc70161b 100644 --- a/swap/tests/harness/bitcoind.rs +++ b/swap/tests/harness/bitcoind.rs @@ -1,6 +1,5 @@ -use std::collections::HashMap; -use testcontainers::core::{Container, Docker, WaitForMessage}; -use testcontainers::Image; +use std::collections::BTreeMap; +use testcontainers::{core::WaitFor, Image, ImageArgs}; pub const RPC_USER: &str = "admin"; pub const RPC_PASSWORD: &str = "123"; @@ -10,57 +9,27 @@ pub const DATADIR: &str = "/home/bdk"; #[derive(Debug)] pub struct Bitcoind { - args: BitcoindArgs, entrypoint: Option, - volume: Option, + volumes: BTreeMap, } impl Image for Bitcoind { type Args = BitcoindArgs; - type EnvVars = HashMap; - type Volumes = HashMap; - type EntryPoint = str; - fn descriptor(&self) -> String { - "coblox/bitcoin-core:0.21.0".to_string() + fn name(&self) -> String { + "coblox/bitcoin-core".into() } - fn wait_until_ready(&self, container: &Container<'_, D, Self>) { - container - .logs() - .stdout - .wait_for_message("init message: Done loading") - .unwrap(); + fn tag(&self) -> String { + "0.21.0".into() } - fn args(&self) -> ::Args { - self.args.clone() + fn ready_conditions(&self) -> Vec { + vec![WaitFor::message_on_stdout("init message: Done loading")] } - fn volumes(&self) -> Self::Volumes { - let mut volumes = HashMap::new(); - match self.volume.clone() { - None => {} - Some(volume) => { - volumes.insert(volume, DATADIR.to_string()); - } - } - volumes - } - - fn env_vars(&self) -> Self::EnvVars { - HashMap::new() - } - - fn with_args(self, args: ::Args) -> Self { - Bitcoind { args, ..self } - } - - fn with_entrypoint(self, entrypoint: &Self::EntryPoint) -> Self { - Self { - entrypoint: Some(entrypoint.to_string()), - ..self - } + fn volumes(&self) -> Box + '_> { + Box::new(self.volumes.iter()) } fn entrypoint(&self) -> Option { @@ -71,16 +40,15 @@ impl Image for Bitcoind { impl Default for Bitcoind { fn default() -> Self { Bitcoind { - args: BitcoindArgs::default(), entrypoint: Some("/usr/bin/bitcoind".into()), - volume: None, + volumes: BTreeMap::default(), } } } impl Bitcoind { pub fn with_volume(mut self, volume: String) -> Self { - self.volume = Some(volume); + self.volumes.insert(volume, DATADIR.to_string()); self } } @@ -109,7 +77,6 @@ impl IntoIterator for BitcoindArgs { format!("-rpcuser={}", RPC_USER), format!("-rpcpassword={}", RPC_PASSWORD), "-printtoconsole".to_string(), - "-rest".to_string(), "-fallbackfee=0.0002".to_string(), format!("-datadir={}", DATADIR), format!("-rpcport={}", RPC_PORT), @@ -120,3 +87,9 @@ impl IntoIterator for BitcoindArgs { args.into_iter() } } + +impl ImageArgs for BitcoindArgs { + fn into_iterator(self) -> Box> { + Box::new(self.into_iter()) + } +} diff --git a/swap/tests/harness/electrs.rs b/swap/tests/harness/electrs.rs index 538fbf27..773a4e3a 100644 --- a/swap/tests/harness/electrs.rs +++ b/swap/tests/harness/electrs.rs @@ -1,8 +1,8 @@ +use std::collections::BTreeMap; + use crate::harness::bitcoind; use bitcoin::Network; -use std::collections::HashMap; -use testcontainers::core::{Container, Docker, WaitForMessage}; -use testcontainers::Image; +use testcontainers::{core::WaitFor, Image, ImageArgs}; pub const HTTP_PORT: u16 = 60401; pub const RPC_PORT: u16 = 3002; @@ -13,50 +13,25 @@ pub struct Electrs { args: ElectrsArgs, entrypoint: Option, wait_for_message: String, - volume: String, + volumes: BTreeMap, } impl Image for Electrs { type Args = ElectrsArgs; - type EnvVars = HashMap; - type Volumes = HashMap; - type EntryPoint = str; - - fn descriptor(&self) -> String { - format!("vulpemventures/electrs:{}", self.tag) + fn name(&self) -> String { + "vulpemventures/electrs".into() } - fn wait_until_ready(&self, container: &Container<'_, D, Self>) { - container - .logs() - .stderr - .wait_for_message(&self.wait_for_message) - .unwrap(); + fn tag(&self) -> String { + self.tag.clone() } - fn args(&self) -> ::Args { - self.args.clone() + fn ready_conditions(&self) -> Vec { + vec![WaitFor::message_on_stderr(self.wait_for_message.clone())] } - fn volumes(&self) -> Self::Volumes { - let mut volumes = HashMap::new(); - volumes.insert(self.volume.clone(), bitcoind::DATADIR.to_string()); - volumes - } - - fn env_vars(&self) -> Self::EnvVars { - HashMap::new() - } - - fn with_args(self, args: ::Args) -> Self { - Electrs { args, ..self } - } - - fn with_entrypoint(self, entrypoint: &Self::EntryPoint) -> Self { - Self { - entrypoint: Some(entrypoint.to_string()), - ..self - } + fn volumes(&self) -> Box + '_> { + Box::new(self.volumes.iter()) } fn entrypoint(&self) -> Option { @@ -71,7 +46,7 @@ impl Default for Electrs { args: ElectrsArgs::default(), entrypoint: Some("/build/electrs".into()), wait_for_message: "Running accept thread".to_string(), - volume: uuid::Uuid::new_v4().to_string(), + volumes: BTreeMap::default(), } } } @@ -85,7 +60,7 @@ impl Electrs { } pub fn with_volume(mut self, volume: String) -> Self { - self.volume = volume; + self.volumes.insert(volume, bitcoind::DATADIR.to_string()); self } @@ -93,6 +68,11 @@ impl Electrs { self.args.daemon_rpc_addr = name; self } + + pub fn self_and_args(self) -> (Self, ElectrsArgs) { + let args = self.args.clone(); + (self, args) + } } #[derive(Debug, Clone)] @@ -137,7 +117,7 @@ impl IntoIterator for ElectrsArgs { } args.push("-vvvvv".to_string()); - args.push(format!("--daemon-dir=={}", self.daemon_dir.as_str())); + args.push(format!("--daemon-dir={}", self.daemon_dir.as_str())); args.push(format!("--daemon-rpc-addr={}", self.daemon_rpc_addr)); args.push(format!("--cookie={}", self.cookie)); args.push(format!("--http-addr={}", self.http_addr)); @@ -147,3 +127,9 @@ impl IntoIterator for ElectrsArgs { args.into_iter() } } + +impl ImageArgs for ElectrsArgs { + fn into_iterator(self) -> Box> { + Box::new(self.into_iter()) + } +} diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 4f3f5fee..bd039477 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -28,7 +28,7 @@ use swap::seed::Seed; use swap::{asb, bitcoin, cli, env, monero}; use tempfile::{tempdir, NamedTempFile}; use testcontainers::clients::Cli; -use testcontainers::{Container, Docker, RunArgs}; +use testcontainers::{Container, RunnableImage}; use tokio::sync::mpsc; use tokio::sync::mpsc::Receiver; use tokio::task::JoinHandle; @@ -61,10 +61,7 @@ where let alice_starting_balances = StartingBalances::new(bitcoin::Amount::ZERO, xmr_amount, Some(10)); - let electrs_rpc_port = containers - .electrs - .get_host_port(electrs::RPC_PORT) - .expect("Could not map electrs rpc port"); + let electrs_rpc_port = containers.electrs.get_host_port_ipv4(electrs::RPC_PORT); let alice_seed = Seed::random().unwrap(); let (alice_bitcoin_wallet, alice_monero_wallet) = init_test_wallets( @@ -146,14 +143,14 @@ where async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) { let prefix = random_prefix(); let bitcoind_name = format!("{}_{}", prefix, "bitcoind"); - let (bitcoind, bitcoind_url) = + let (_bitcoind, bitcoind_url, mapped_port) = 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, mapped_port) .await .expect("could not init electrs"); - let (monero, monerod_container, monero_wallet_rpc_containers) = + let (monero, _monerod_container, _monero_wallet_rpc_containers) = Monero::new(cli, vec![MONERO_WALLET_NAME_ALICE, MONERO_WALLET_NAME_BOB]) .await .unwrap(); @@ -162,9 +159,9 @@ async fn init_containers(cli: &Cli) -> (Monero, Containers<'_>) { monero, Containers { bitcoind_url, - bitcoind, - monerod_container, - monero_wallet_rpc_containers, + _bitcoind, + _monerod_container, + _monero_wallet_rpc_containers, electrs, }, ) @@ -175,29 +172,28 @@ async fn init_bitcoind_container( volume: String, name: String, network: String, -) -> Result<(Container<'_, Cli, bitcoind::Bitcoind>, Url)> { +) -> Result<(Container<'_, bitcoind::Bitcoind>, Url, u16)> { let image = bitcoind::Bitcoind::default().with_volume(volume); + let image = RunnableImage::from(image) + .with_container_name(name) + .with_network(network); - let run_args = RunArgs::default().with_name(name).with_network(network); - - let docker = cli.run_with_args(image, run_args); - let a = docker - .get_host_port(bitcoind::RPC_PORT) - .context("Could not map bitcoind rpc port")?; + let docker = cli.run(image); + let port = docker.get_host_port_ipv4(bitcoind::RPC_PORT); let bitcoind_url = { let input = format!( "http://{}:{}@localhost:{}", bitcoind::RPC_USER, bitcoind::RPC_PASSWORD, - a + port ); Url::parse(&input).unwrap() }; init_bitcoind(bitcoind_url.clone(), 5).await?; - Ok((docker, bitcoind_url.clone())) + Ok((docker, bitcoind_url.clone(), bitcoind::RPC_PORT)) } pub async fn init_electrs_container( @@ -205,16 +201,18 @@ pub async fn init_electrs_container( volume: String, bitcoind_container_name: String, network: String, -) -> Result> { - let bitcoind_rpc_addr = format!("{}:{}", bitcoind_container_name, bitcoind::RPC_PORT); + port: u16, +) -> Result> { + let bitcoind_rpc_addr = format!("{}:{}", bitcoind_container_name, port); let image = electrs::Electrs::default() .with_volume(volume) .with_daemon_rpc_addr(bitcoind_rpc_addr) .with_tag("latest"); + let image = RunnableImage::from(image.self_and_args()) + .with_network(network.clone()) + .with_container_name(format!("{}_electrs", network)); - let run_args = RunArgs::default().with_network(network); - - let docker = cli.run_with_args(image, run_args); + let docker = cli.run(image); Ok(docker) } @@ -952,13 +950,12 @@ pub async fn mint(node_url: Url, address: bitcoin::Address, amount: bitcoin::Amo } // This is just to keep the containers alive -#[allow(dead_code)] struct Containers<'a> { bitcoind_url: Url, - bitcoind: Container<'a, Cli, bitcoind::Bitcoind>, - monerod_container: Container<'a, Cli, image::Monerod>, - monero_wallet_rpc_containers: Vec>, - electrs: Container<'a, Cli, electrs::Electrs>, + _bitcoind: Container<'a, bitcoind::Bitcoind>, + _monerod_container: Container<'a, image::Monerod>, + _monero_wallet_rpc_containers: Vec>, + electrs: Container<'a, electrs::Electrs>, } pub mod alice_run_until { From 00abded1c596398effc21e73a3f87956b0688e88 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Feb 2024 22:25:06 +0200 Subject: [PATCH 202/395] build(deps): bump mockito from 1.2.0 to 1.3.0 (#1561) * build(deps): bump mockito from 1.2.0 to 1.3.0 Bumps [mockito](https://github.com/lipanski/mockito) from 1.2.0 to 1.3.0. - [Release notes](https://github.com/lipanski/mockito/releases) - [Commits](https://github.com/lipanski/mockito/compare/1.2.0...1.3.0) --- updated-dependencies: - dependency-name: mockito dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * build(deps): update http to 0.2.11 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Byron Hambly --- Cargo.lock | 54 ++++++++++++++++++++++--------------------------- swap/Cargo.toml | 2 +- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0708533b..1ab5e16f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1490,7 +1490,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.3", + "http 0.2.11", "indexmap 1.7.0", "slab", "tokio", @@ -1620,13 +1620,13 @@ dependencies = [ [[package]] name = "http" -version = "0.2.3" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7245cd7449cc792608c3c8a9eaf69bd4eabbabf802713748fd739c98b82f0747" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", - "itoa 0.4.7", + "itoa", ] [[package]] @@ -1637,7 +1637,7 @@ checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" dependencies = [ "bytes", "fnv", - "itoa 1.0.1", + "itoa", ] [[package]] @@ -1647,7 +1647,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2861bd27ee074e5ee891e8b539837a9430012e249d7f0ca2d795650f579c1994" dependencies = [ "bytes", - "http 0.2.3", + "http 0.2.11", ] [[package]] @@ -1674,22 +1674,22 @@ checksum = "05842d0d43232b23ccb7060ecb0f0626922c21f30012e97b767b30afd4a5d4b9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", "futures-core", "futures-util", "h2", - "http 0.2.3", + "http 0.2.11", "http-body 0.4.0", "httparse", "httpdate", - "itoa 1.0.1", + "itoa", "pin-project-lite 0.2.13", - "socket2 0.4.7", + "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -1714,8 +1714,8 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" dependencies = [ - "http 0.2.3", - "hyper 0.14.27", + "http 0.2.11", + "hyper 0.14.28", "rustls 0.21.10", "tokio", "tokio-rustls 0.24.0", @@ -1847,12 +1847,6 @@ dependencies = [ "either", ] -[[package]] -name = "itoa" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" - [[package]] name = "itoa" version = "1.0.1" @@ -2396,14 +2390,14 @@ dependencies = [ [[package]] name = "mockito" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8d3038e23466858569c2d30a537f691fa0d53b51626630ae08262943e3bbb8b" +checksum = "a8c84fe1f1d8c56dc157f79942056fad4b9efceebba374a01b222428b553facb" dependencies = [ "assert-json-diff", "colored", "futures", - "hyper 0.14.27", + "hyper 0.14.28", "log", "rand 0.8.3", "regex", @@ -2724,7 +2718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f85842b073145726190373213c63f852020fb884c841a3a1f390637267a2fb8c" dependencies = [ "dtoa", - "itoa 1.0.1", + "itoa", "open-metrics-client-derive-text-encode", "owning_ref", ] @@ -3359,9 +3353,9 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.3", + "http 0.2.11", "http-body 0.4.0", - "hyper 0.14.27", + "hyper 0.14.28", "hyper-rustls", "ipnet", "js-sys", @@ -3788,7 +3782,7 @@ version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -3809,7 +3803,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.1", + "itoa", "ryu", "serde", ] @@ -4122,7 +4116,7 @@ dependencies = [ "hashlink", "hex", "indexmap 1.7.0", - "itoa 1.0.1", + "itoa", "libc", "libsqlite3-sys", "log", @@ -4519,7 +4513,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", - "itoa 1.0.1", + "itoa", "libc", "num-conv", "num_threads", @@ -4954,7 +4948,7 @@ dependencies = [ "base64 0.13.1", "byteorder", "bytes", - "http 0.2.3", + "http 0.2.11", "httparse", "log", "rand 0.8.3", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 3c1d2336..d5e2b529 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -77,7 +77,7 @@ zip = "0.5" bitcoin-harness = "0.2.2" get-port = "3" hyper = "1.2" -mockito = "1.2.0" +mockito = "1.3.0" monero-harness = { path = "../monero-harness" } port_check = "0.1" proptest = "1" From 3037bbcbe4c7052a2b23fb0c2c120a41acb36c3d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Feb 2024 11:36:17 +0000 Subject: [PATCH 203/395] build(deps): bump tempfile from 3.10.0 to 3.10.1 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.10.0 to 3.10.1. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.10.0...v3.10.1) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ab5e16f..59995984 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4421,9 +4421,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if 1.0.0", "fastrand", From bb596fcc090fa438e9e5913c4b85d8b3ba9ac0dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:48:02 +0000 Subject: [PATCH 204/395] build(deps): bump base64 from 0.21.7 to 0.22.0 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.21.7 to 0.22.0. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.21.7...v0.22.0) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 +++++++- swap/Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59995984..41d70d60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -264,6 +264,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" + [[package]] name = "bdk" version = "0.28.0" @@ -4291,7 +4297,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.21.7", + "base64 0.22.0", "bdk", "big-bytes", "bitcoin", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index d5e2b529..4c6e5dd9 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -14,7 +14,7 @@ async-compression = { version = "0.3", features = [ "bzip2", "tokio" ] } async-trait = "0.1" atty = "0.2" backoff = { version = "0.4", features = [ "tokio" ] } -base64 = "0.21" +base64 = "0.22" bdk = "0.28" big-bytes = "1" bitcoin = { version = "0.29", features = [ "rand", "serde" ] } From 397aa972bb6ec08b3656919f3766eb33c70da580 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:54:07 +0000 Subject: [PATCH 205/395] build(deps): bump strum from 0.26.1 to 0.26.2 Bumps [strum](https://github.com/Peternator7/strum) from 0.26.1 to 0.26.2. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/commits) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41d70d60..9091c6dd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4243,9 +4243,9 @@ checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" [[package]] name = "strum" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723b93e8addf9aa965ebe2d11da6d7540fa2283fcea14b3371ff055f7ba13f5f" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ "strum_macros 0.26.1", ] @@ -4341,7 +4341,7 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum 0.26.1", + "strum 0.26.2", "tempfile", "testcontainers", "thiserror", From 6af198743ab1aae890ea9ddb5a763fe8f496f02c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:54:48 +0000 Subject: [PATCH 206/395] build(deps): bump reqwest from 0.11.24 to 0.11.25 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.24 to 0.11.25. - [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.24...v0.11.25) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41d70d60..c4c17895 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3349,9 +3349,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.24" +version = "0.11.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" dependencies = [ "base64 0.21.7", "bytes", @@ -4406,20 +4406,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" dependencies = [ "core-foundation-sys", "libc", From 82eac08bfeccfb8a62d11b1dea6f8ee05e891398 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 12 Mar 2024 14:55:52 +0200 Subject: [PATCH 207/395] ci: specify version of sqlx-cli --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ff9a6d7..ed083227 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: - uses: Swatinem/rust-cache@v2.7.3 - name: Install sqlx-cli - run: cargo install sqlx-cli --locked + run: cargo install --version 0.6.3 sqlx-cli - name: Run sqlite_dev_setup.sh script run: | From 28937b86932a35e312b61f09198f6989e0bc59b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 13:10:43 +0000 Subject: [PATCH 208/395] build(deps): bump actions/checkout from 4.1.1 to 4.1.2 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.1...v4.1.2) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 48888845..c18c3124 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ed083227..69c11c72 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - uses: Swatinem/rust-cache@v2.7.3 @@ -76,7 +76,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - uses: Swatinem/rust-cache@v2.7.3 @@ -129,7 +129,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - uses: Swatinem/rust-cache@v2.7.3 @@ -166,7 +166,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.2 - uses: Swatinem/rust-cache@v2.7.3 diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index ac24fe3f..c62d47eb 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index d980d388..5188be0a 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index d27a645a..f45ff1b4 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.1 + - uses: actions/checkout@v4.1.2 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From bf262acf0088c9b8a8f2e6dbe2c15d941f2c7a37 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 13:11:26 +0000 Subject: [PATCH 209/395] build(deps): bump thiserror from 1.0.57 to 1.0.58 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.57 to 1.0.58. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.57...1.0.58) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ddbf1ab..4a616727 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4475,18 +4475,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", From ccff348cddc84583be862c748cb6ac8e288dbbc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 13:11:35 +0000 Subject: [PATCH 210/395] build(deps): bump toml from 0.8.10 to 0.8.11 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.10 to 0.8.11. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.10...toml-v0.8.11) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ddbf1ab..f2eea16a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -709,7 +709,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.10", + "toml 0.8.11", ] [[package]] @@ -4351,7 +4351,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.10", + "toml 0.8.11", "torut", "tracing", "tracing-appender", @@ -4711,9 +4711,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290" +checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" dependencies = [ "serde", "serde_spanned", @@ -4732,9 +4732,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.4" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ffdf896f8daaabf9b66ba8e77ea1ed5ed0f72821b398aba62352e95062951" +checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ "indexmap 2.1.0", "serde", @@ -5526,9 +5526,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.28" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] From 46eee5ccfc867d62fffef2e9b4915c4b6f10c1e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Mar 2024 13:11:43 +0000 Subject: [PATCH 211/395] build(deps): bump anyhow from 1.0.80 to 1.0.81 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.80 to 1.0.81. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.80...1.0.81) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ddbf1ab..594d5c33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arrayref" From a61f7809d98eba06d27c39d494cdc2305e5f4b4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 13 Mar 2024 11:32:44 +0000 Subject: [PATCH 212/395] build(deps): bump reqwest from 0.11.25 to 0.11.26 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.25 to 0.11.26. - [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.25...v0.11.26) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 275b13fe..1f5a3ac7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3349,9 +3349,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.25" +version = "0.11.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eea5a9eb898d3783f17c6407670e3592fd174cb81a10e51d4c37f49450b9946" +checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" dependencies = [ "base64 0.21.7", "bytes", @@ -4406,20 +4406,20 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" dependencies = [ - "bitflags 2.4.0", + "bitflags 1.3.2", "core-foundation", "system-configuration-sys", ] [[package]] name = "system-configuration-sys" -version = "0.6.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" dependencies = [ "core-foundation-sys", "libc", From fea34cc35b5fe1121fb6816aff61791a70cbf328 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 14 Mar 2024 11:58:41 +0000 Subject: [PATCH 213/395] build(deps): bump qrcode from 0.13.0 to 0.14.0 Bumps [qrcode](https://github.com/kennytm/qrcode-rust) from 0.13.0 to 0.14.0. - [Release notes](https://github.com/kennytm/qrcode-rust/releases) - [Commits](https://github.com/kennytm/qrcode-rust/commits) --- updated-dependencies: - dependency-name: qrcode dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 29 +++++------------------------ swap/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f5a3ac7..61d24025 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -670,12 +670,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - [[package]] name = "colored" version = "2.0.4" @@ -1766,14 +1760,12 @@ dependencies = [ [[package]] name = "image" -version = "0.24.7" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" +checksum = "a9b4f005360d32e9325029b38ba47ebd7a56f3316df09249368939562d518645" dependencies = [ "bytemuck", "byteorder", - "color_quant", - "num-rational 0.4.1", "num-traits", ] @@ -2591,7 +2583,7 @@ dependencies = [ "num-complex", "num-integer", "num-iter", - "num-rational 0.1.42", + "num-rational", "num-traits", ] @@ -2656,17 +2648,6 @@ dependencies = [ "rustc-serialize", ] -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -3117,9 +3098,9 @@ dependencies = [ [[package]] name = "qrcode" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "166f136dfdb199f98186f3649cf7a0536534a61417a1a30221b492b4fb60ce3f" +checksum = "23e719ca51966ff9f5a8436edb00d6115b3c606a0bb27c8f8ca74a38ff2b036d" dependencies = [ "image", ] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 4c6e5dd9..1cbd5ed5 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -36,7 +36,7 @@ monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } pem = "3.0" proptest = "1" -qrcode = "0.13" +qrcode = "0.14" rand = "0.8" rand_chacha = "0.3" reqwest = { version = "0.11", features = [ "rustls-tls", "stream", "socks" ], default-features = false } From 3b83822a71ffbf8beadac433c761bf9e3aa57c58 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 11:35:06 +0000 Subject: [PATCH 214/395] build(deps): bump async-trait from 0.1.77 to 0.1.78 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.77 to 0.1.78. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.77...0.1.78) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61d24025..3a00c8fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" dependencies = [ "proc-macro2", "quote", From d77f208aae00d7e8103cc83143b7f9905a56f659 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:22:48 +0000 Subject: [PATCH 215/395] build(deps): bump uuid from 1.7.0 to 1.8.0 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.7.0 to 1.8.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.7.0...1.8.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a00c8fe..6c9dfec1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5077,9 +5077,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom 0.2.11", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 1cbd5ed5..3cb84995 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -64,7 +64,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.7", features = [ "serde", "v4" ] } +uuid = { version = "1.8", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From 5d1b9cf4c3cb2f259a7d2f2bf477278e967dea16 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Mar 2024 11:23:48 +0000 Subject: [PATCH 216/395] build(deps): bump toml from 0.8.11 to 0.8.12 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.11 to 0.8.12. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.11...toml-v0.8.12) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a00c8fe..2f69f7a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.11", + "toml 0.8.12", ] [[package]] @@ -4332,7 +4332,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.11", + "toml 0.8.12", "torut", "tracing", "tracing-appender", @@ -4692,9 +4692,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" dependencies = [ "serde", "serde_spanned", @@ -4713,9 +4713,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "c12219811e0c1ba077867254e5ad62ee2c9c190b0d957110750ac0cda1ae96cd" dependencies = [ "indexmap 2.1.0", "serde", From 1901594d288cedbf0b4dff06a340d865170dc12b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 11:09:02 +0000 Subject: [PATCH 217/395] build(deps): bump reqwest from 0.11.26 to 0.11.27 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.26 to 0.11.27. - [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.26...v0.11.27) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3795cae6..c7736aea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3330,9 +3330,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.26" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", From eb15f477fac1872af4028ded403c511993ea2bed Mon Sep 17 00:00:00 2001 From: Ian McKenzie <13459320+ikmckenz@users.noreply.github.com> Date: Fri, 22 Mar 2024 02:18:40 -0700 Subject: [PATCH 218/395] Verify hashes of monero cli on download (#1572) * Bump Monero CLI for macos aarch64 to match other platforms * Check hash on download of monero cli * change panic to bail --------- Co-authored-by: Byron Hambly --- Cargo.lock | 1 + swap/Cargo.toml | 1 + swap/src/monero/wallet_rpc.rs | 32 +++++++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c7736aea..8c58895b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4290,6 +4290,7 @@ dependencies = [ "curve25519-dalek-ng", "data-encoding", "dialoguer", + "digest 0.10.7", "directories-next", "ecdsa_fun", "ed25519-dalek", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 3cb84995..8b60517a 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -25,6 +25,7 @@ conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } data-encoding = "2.5" dialoguer = "0.11" +digest = "0.10.7" directories-next = "2" ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] } ed25519-dalek = "1" diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index e44d800e..e227c3f3 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -1,11 +1,13 @@ use ::monero::Network; use anyhow::{bail, Context, Error, Result}; use big_bytes::BigByte; +use data_encoding::HEXLOWER; use futures::{StreamExt, TryStreamExt}; use monero_rpc::wallet::{Client, MoneroWalletRpc as _}; use reqwest::header::CONTENT_LENGTH; use reqwest::Url; use serde::Deserialize; +use sha2::{Digest, Sha256}; use std::fmt; use std::fmt::{Debug, Display, Formatter}; use std::io::ErrorKind; @@ -45,19 +47,29 @@ compile_error!("unsupported operating system"); #[cfg(all(target_os = "macos", target_arch = "x86_64"))] const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2"; +#[cfg(all(target_os = "macos", target_arch = "x86_64"))] +const DOWNLOAD_HASH: &str = "ba1108c7a5e5efe15b6a628fb007c50f01c231f61137bba7427605286dbc6f01"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.0.0.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.1.2.tar.bz2"; +#[cfg(all(target_os = "macos", target_arch = "aarch64"))] +const DOWNLOAD_HASH: &str = "620b825c04f84845ed09de03b207a3230a34f74b30a8a07dde504a7d376ee4b9"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2"; +#[cfg(all(target_os = "linux", target_arch = "x86_64"))] +const DOWNLOAD_HASH: &str = "7d51e7072351f65d0c7909e745827cfd3b00abe5e7c4cc4c104a3c9b526da07e"; #[cfg(all(target_os = "linux", target_arch = "arm"))] const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2"; +#[cfg(all(target_os = "linux", target_arch = "arm"))] +const DOWNLOAD_HASH: &str = "94ece435ed60f85904114643482c2b6716f74bf97040a7af237450574a9cf06d"; #[cfg(target_os = "windows")] const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip"; +#[cfg(target_os = "windows")] +const DOWNLOAD_HASH: &str = "0a3d4d1af7e094c05352c31b2dafcc6ccbc80edc195ca9eaedc919c36accd05a"; #[cfg(any(target_os = "macos", target_os = "linux"))] const PACKED_FILE: &str = "monero-wallet-rpc"; @@ -226,8 +238,14 @@ impl WalletRpc { DOWNLOAD_URL ); + let mut hasher = Sha256::new(); + let byte_stream = response .bytes_stream() + .map_ok(|bytes| { + hasher.update(&bytes); + bytes + }) .map_err(|err| std::io::Error::new(ErrorKind::Other, err)); #[cfg(not(target_os = "windows"))] @@ -256,6 +274,18 @@ impl WalletRpc { file.write_all(&bytes).await?; } + let result = hasher.finalize(); + let result_hash = HEXLOWER.encode(result.as_ref()); + if result_hash != DOWNLOAD_HASH { + bail!( + "SHA256 of download ({}) does not match expected ({})!", + result_hash, + DOWNLOAD_HASH + ); + } else { + tracing::debug!("Hashes match"); + } + file.flush().await?; tracing::debug!("Extracting archive"); From 85cee51eeee41055570eb4cf73d43a6982562287 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:05:21 +0100 Subject: [PATCH 219/395] Run dprint fmt --- swap/src/monero/wallet_rpc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index d0d3d6ed..bb696ba0 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -61,7 +61,8 @@ const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64 const DOWNLOAD_HASH: &str = "23af572fdfe3459b9ab97e2e9aa7e3c11021c955d6064b801a27d7e8c21ae09d"; #[cfg(all(target_os = "linux", target_arch = "arm"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2"; +const DOWNLOAD_URL: &str = + "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "arm"))] const DOWNLOAD_HASH: &str = "2ea2c8898cbab88f49423f4f6c15f2a94046cb4bbe827493dd061edc0fd5f1ca"; From bfc1e829dc6f4eed81d362d34456183d04974edd Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:07:11 +0100 Subject: [PATCH 220/395] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3ad105..594cae30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Minimum Supported Rust Version (MSRV) bumped to 1.70 +- Update monero-wallet-rpc version to v0.18.3.1 +- Add retry logic to monero-wallet-rpc wallet refresh ## [0.12.3] - 2023-09-20 From d8dacbdee99a8d951977e62db1c888cc9ed56ea8 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Mon, 25 Mar 2024 15:08:54 +0100 Subject: [PATCH 221/395] Monero wallet refresh fix (#1487) * Upgrade monero-wallet-rpc to `v0.18.3.1` * Give feedback to user about state of monero refresh and retry if fails This commit changes the following behaviour in the refresh functionality of the monero wallet - Allows for multiple retries because in some cases users have experienced an issue where the wallet rpc returns `no connection to daemon` even though the daemon is available. I'm not 100% sure why this happens but retrying often fixes the issue - Attempt to print the current sync height while the wallet is syncing. This only works to some degree because the `monero-wallet-rpc` stops responding (or takes a long time to respond) while it's refreshing - The `monero-wallet-rpc` is started with the `--no-initial-sync` flag which ensures that as soon as it's started, it's ready to respond to requests --------- Co-authored-by: Byron Hambly Co-authored-by: Byron Hambly --- CHANGELOG.md | 2 + swap/src/monero/wallet.rs | 69 +++++++++++++++++++++++++++++++++-- swap/src/monero/wallet_rpc.rs | 44 ++++++++++++++-------- swap/src/protocol/bob/swap.rs | 5 ++- swap/tests/harness/mod.rs | 2 +- 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3ad105..594cae30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Minimum Supported Rust Version (MSRV) bumped to 1.70 +- Update monero-wallet-rpc version to v0.18.3.1 +- Add retry logic to monero-wallet-rpc wallet refresh ## [0.12.3] - 2023-09-20 diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 56fd8e60..61ed4ca4 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -45,6 +45,7 @@ impl Wallet { pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result { let main_address = monero::Address::from_str(client.get_address(0).await?.address.as_str())?; + Ok(Self { inner: Mutex::new(client), network: env_config.monero_network, @@ -144,7 +145,7 @@ impl Wallet { .await?; // Try to send all the funds from the generated wallet to the default wallet - match wallet.refresh().await { + match self.refresh(3).await { Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await { Ok(sweep_all) => { for tx in sweep_all.tx_hash_list { @@ -261,8 +262,70 @@ impl Wallet { self.main_address } - pub async fn refresh(&self) -> Result { - Ok(self.inner.lock().await.refresh().await?) + pub async fn refresh(&self, max_attempts: usize) -> Result { + const GET_HEIGHT_INTERVAL: Duration = Duration::from_secs(5); + const RETRY_INTERVAL: Duration = Duration::from_secs(2); + + let inner = self.inner.lock().await; + + // Cloning this is relatively cheap because reqwest::Client is a wrapper around an Arc + let inner_clone = inner.clone(); + let wallet_name_clone = self.name.clone(); + + let refresh_task = tokio::task::spawn(async move { + loop { + let height = inner_clone.get_height().await; + + match height { + Err(error) => { + tracing::debug!(name = %wallet_name_clone, %error, "Failed to get current Monero wallet sync height"); + } + Ok(height) => { + tracing::debug!(name = %wallet_name_clone, current_sync_height = height.height, "Syncing Monero wallet"); + } + } + + tokio::time::sleep(GET_HEIGHT_INTERVAL).await; + } + }); + + let refresh_result = tokio::select! { + biased; + _ = refresh_task => { + unreachable!("Current sync height refresh task should never finish") + } + refresh_result = async { + for i in 1..=max_attempts { + tracing::info!(name = %self.name, attempt=i, "Syncing Monero wallet"); + + let result = inner.refresh().await; + + match result { + Ok(refreshed) => { + tracing::info!(name = %self.name, "Monero wallet synced"); + return Ok(refreshed); + } + Err(error) => { + let attempts_left = max_attempts - i; + tracing::warn!(attempt=i, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet"); + + if attempts_left == 0 { + tracing::error!(name = %self.name, %error, "Failed to sync Monero wallet"); + return Err(error); + } + } + } + + tokio::time::sleep(RETRY_INTERVAL).await; + } + + unreachable!("Loop should always return before it breaks") + } => { + refresh_result + } + }; + + Ok(refresh_result?) } } diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index e227c3f3..bb696ba0 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -46,30 +46,30 @@ const MONERO_DAEMONS: [MoneroDaemon; 17] = [ compile_error!("unsupported operating system"); #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_HASH: &str = "ba1108c7a5e5efe15b6a628fb007c50f01c231f61137bba7427605286dbc6f01"; +const DOWNLOAD_HASH: &str = "7f8bd9364ef16482b418aa802a65be0e4cc660c794bb5d77b2d17bc84427883a"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_HASH: &str = "620b825c04f84845ed09de03b207a3230a34f74b30a8a07dde504a7d376ee4b9"; +const DOWNLOAD_HASH: &str = "915288b023cb5811e626e10052adc6ac5323dd283c5a25b91059b0fb86a21fb6"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_HASH: &str = "7d51e7072351f65d0c7909e745827cfd3b00abe5e7c4cc4c104a3c9b526da07e"; +const DOWNLOAD_HASH: &str = "23af572fdfe3459b9ab97e2e9aa7e3c11021c955d6064b801a27d7e8c21ae09d"; #[cfg(all(target_os = "linux", target_arch = "arm"))] const DOWNLOAD_URL: &str = - "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2"; + "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "arm"))] -const DOWNLOAD_HASH: &str = "94ece435ed60f85904114643482c2b6716f74bf97040a7af237450574a9cf06d"; +const DOWNLOAD_HASH: &str = "2ea2c8898cbab88f49423f4f6c15f2a94046cb4bbe827493dd061edc0fd5f1ca"; #[cfg(target_os = "windows")] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.3.1.zip"; #[cfg(target_os = "windows")] -const DOWNLOAD_HASH: &str = "0a3d4d1af7e094c05352c31b2dafcc6ccbc80edc195ca9eaedc919c36accd05a"; +const DOWNLOAD_HASH: &str = "35dcc4bee4caad3442659d37837e0119e4649a77f2e3b5e80dd6d9b8fc4fb6ad"; #[cfg(any(target_os = "macos", target_os = "linux"))] const PACKED_FILE: &str = "monero-wallet-rpc"; @@ -77,7 +77,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc"; #[cfg(target_os = "windows")] const PACKED_FILE: &str = "monero-wallet-rpc.exe"; -const WALLET_RPC_VERSION: &str = "v0.18.1.2"; +const WALLET_RPC_VERSION: &str = "v0.18.3.1"; #[derive(Debug, Clone, Copy, thiserror::Error)] #[error("monero wallet rpc executable not found in downloaded archive")] @@ -233,9 +233,10 @@ impl WalletRpc { .parse::()?; tracing::info!( - "Downloading monero-wallet-rpc ({}) from {}", - content_length.big_byte(2), - DOWNLOAD_URL + progress="0%", + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", ); let mut hasher = Sha256::new(); @@ -268,12 +269,24 @@ impl WalletRpc { let total = 3 * content_length; let percent = 100 * received as u64 / total; if percent != notified && percent % 10 == 0 { - tracing::debug!("{}%", percent); + tracing::info!( + progress=format!("{}%", percent), + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", + ); notified = percent; } file.write_all(&bytes).await?; } + tracing::info!( + progress="100%", + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", + ); + let result = hasher.finalize(); let result_hash = HEXLOWER.encode(result.as_ref()); if result_hash != DOWNLOAD_HASH { @@ -339,6 +352,7 @@ impl WalletRpc { .arg("--disable-rpc-login") .arg("--wallet-dir") .arg(self.working_dir.join("monero-data")) + .arg("--no-initial-sync") .spawn()?; let stdout = child diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 66933a87..92d4f628 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -227,6 +227,9 @@ async fn next_state( let (spend_key, view_key) = state.xmr_keys(); let wallet_file_name = swap_id.to_string(); + + tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero"); + if let Err(e) = monero_wallet .create_from_and_load( wallet_file_name.clone(), @@ -247,7 +250,7 @@ async fn next_state( } // Ensure that the generated wallet is synced so we have a proper balance - monero_wallet.refresh().await?; + monero_wallet.refresh(3).await?; // Sweep (transfer all funds) to the given address let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?; diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index bd039477..7331f96f 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -863,7 +863,7 @@ impl Wallet for monero::Wallet { type Amount = monero::Amount; async fn refresh(&self) -> Result<()> { - self.refresh().await?; + self.refresh(1).await?; Ok(()) } From a19501a0023fa8bbd7342cac736cd079a58361ce Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 26 Mar 2024 09:06:31 +0200 Subject: [PATCH 222/395] Revert "Monero wallet refresh fix (#1487)" This reverts commit d8dacbdee99a8d951977e62db1c888cc9ed56ea8. --- CHANGELOG.md | 2 - swap/src/monero/wallet.rs | 69 ++--------------------------------- swap/src/monero/wallet_rpc.rs | 44 ++++++++-------------- swap/src/protocol/bob/swap.rs | 5 +-- swap/tests/harness/mod.rs | 2 +- 5 files changed, 20 insertions(+), 102 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 594cae30..4d3ad105 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Minimum Supported Rust Version (MSRV) bumped to 1.70 -- Update monero-wallet-rpc version to v0.18.3.1 -- Add retry logic to monero-wallet-rpc wallet refresh ## [0.12.3] - 2023-09-20 diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 61ed4ca4..56fd8e60 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -45,7 +45,6 @@ impl Wallet { pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result { let main_address = monero::Address::from_str(client.get_address(0).await?.address.as_str())?; - Ok(Self { inner: Mutex::new(client), network: env_config.monero_network, @@ -145,7 +144,7 @@ impl Wallet { .await?; // Try to send all the funds from the generated wallet to the default wallet - match self.refresh(3).await { + match wallet.refresh().await { Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await { Ok(sweep_all) => { for tx in sweep_all.tx_hash_list { @@ -262,70 +261,8 @@ impl Wallet { self.main_address } - pub async fn refresh(&self, max_attempts: usize) -> Result { - const GET_HEIGHT_INTERVAL: Duration = Duration::from_secs(5); - const RETRY_INTERVAL: Duration = Duration::from_secs(2); - - let inner = self.inner.lock().await; - - // Cloning this is relatively cheap because reqwest::Client is a wrapper around an Arc - let inner_clone = inner.clone(); - let wallet_name_clone = self.name.clone(); - - let refresh_task = tokio::task::spawn(async move { - loop { - let height = inner_clone.get_height().await; - - match height { - Err(error) => { - tracing::debug!(name = %wallet_name_clone, %error, "Failed to get current Monero wallet sync height"); - } - Ok(height) => { - tracing::debug!(name = %wallet_name_clone, current_sync_height = height.height, "Syncing Monero wallet"); - } - } - - tokio::time::sleep(GET_HEIGHT_INTERVAL).await; - } - }); - - let refresh_result = tokio::select! { - biased; - _ = refresh_task => { - unreachable!("Current sync height refresh task should never finish") - } - refresh_result = async { - for i in 1..=max_attempts { - tracing::info!(name = %self.name, attempt=i, "Syncing Monero wallet"); - - let result = inner.refresh().await; - - match result { - Ok(refreshed) => { - tracing::info!(name = %self.name, "Monero wallet synced"); - return Ok(refreshed); - } - Err(error) => { - let attempts_left = max_attempts - i; - tracing::warn!(attempt=i, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet"); - - if attempts_left == 0 { - tracing::error!(name = %self.name, %error, "Failed to sync Monero wallet"); - return Err(error); - } - } - } - - tokio::time::sleep(RETRY_INTERVAL).await; - } - - unreachable!("Loop should always return before it breaks") - } => { - refresh_result - } - }; - - Ok(refresh_result?) + pub async fn refresh(&self) -> Result { + Ok(self.inner.lock().await.refresh().await?) } } diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index bb696ba0..e227c3f3 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -46,30 +46,30 @@ const MONERO_DAEMONS: [MoneroDaemon; 17] = [ compile_error!("unsupported operating system"); #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.3.1.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_HASH: &str = "7f8bd9364ef16482b418aa802a65be0e4cc660c794bb5d77b2d17bc84427883a"; +const DOWNLOAD_HASH: &str = "ba1108c7a5e5efe15b6a628fb007c50f01c231f61137bba7427605286dbc6f01"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.3.1.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.1.2.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_HASH: &str = "915288b023cb5811e626e10052adc6ac5323dd283c5a25b91059b0fb86a21fb6"; +const DOWNLOAD_HASH: &str = "620b825c04f84845ed09de03b207a3230a34f74b30a8a07dde504a7d376ee4b9"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.3.1.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_HASH: &str = "23af572fdfe3459b9ab97e2e9aa7e3c11021c955d6064b801a27d7e8c21ae09d"; +const DOWNLOAD_HASH: &str = "7d51e7072351f65d0c7909e745827cfd3b00abe5e7c4cc4c104a3c9b526da07e"; #[cfg(all(target_os = "linux", target_arch = "arm"))] const DOWNLOAD_URL: &str = - "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2"; + "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "arm"))] -const DOWNLOAD_HASH: &str = "2ea2c8898cbab88f49423f4f6c15f2a94046cb4bbe827493dd061edc0fd5f1ca"; +const DOWNLOAD_HASH: &str = "94ece435ed60f85904114643482c2b6716f74bf97040a7af237450574a9cf06d"; #[cfg(target_os = "windows")] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.3.1.zip"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip"; #[cfg(target_os = "windows")] -const DOWNLOAD_HASH: &str = "35dcc4bee4caad3442659d37837e0119e4649a77f2e3b5e80dd6d9b8fc4fb6ad"; +const DOWNLOAD_HASH: &str = "0a3d4d1af7e094c05352c31b2dafcc6ccbc80edc195ca9eaedc919c36accd05a"; #[cfg(any(target_os = "macos", target_os = "linux"))] const PACKED_FILE: &str = "monero-wallet-rpc"; @@ -77,7 +77,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc"; #[cfg(target_os = "windows")] const PACKED_FILE: &str = "monero-wallet-rpc.exe"; -const WALLET_RPC_VERSION: &str = "v0.18.3.1"; +const WALLET_RPC_VERSION: &str = "v0.18.1.2"; #[derive(Debug, Clone, Copy, thiserror::Error)] #[error("monero wallet rpc executable not found in downloaded archive")] @@ -233,10 +233,9 @@ impl WalletRpc { .parse::()?; tracing::info!( - progress="0%", - size=%content_length.big_byte(2), - download_url=DOWNLOAD_URL, - "Downloading monero-wallet-rpc", + "Downloading monero-wallet-rpc ({}) from {}", + content_length.big_byte(2), + DOWNLOAD_URL ); let mut hasher = Sha256::new(); @@ -269,24 +268,12 @@ impl WalletRpc { let total = 3 * content_length; let percent = 100 * received as u64 / total; if percent != notified && percent % 10 == 0 { - tracing::info!( - progress=format!("{}%", percent), - size=%content_length.big_byte(2), - download_url=DOWNLOAD_URL, - "Downloading monero-wallet-rpc", - ); + tracing::debug!("{}%", percent); notified = percent; } file.write_all(&bytes).await?; } - tracing::info!( - progress="100%", - size=%content_length.big_byte(2), - download_url=DOWNLOAD_URL, - "Downloading monero-wallet-rpc", - ); - let result = hasher.finalize(); let result_hash = HEXLOWER.encode(result.as_ref()); if result_hash != DOWNLOAD_HASH { @@ -352,7 +339,6 @@ impl WalletRpc { .arg("--disable-rpc-login") .arg("--wallet-dir") .arg(self.working_dir.join("monero-data")) - .arg("--no-initial-sync") .spawn()?; let stdout = child diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 92d4f628..66933a87 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -227,9 +227,6 @@ async fn next_state( let (spend_key, view_key) = state.xmr_keys(); let wallet_file_name = swap_id.to_string(); - - tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero"); - if let Err(e) = monero_wallet .create_from_and_load( wallet_file_name.clone(), @@ -250,7 +247,7 @@ async fn next_state( } // Ensure that the generated wallet is synced so we have a proper balance - monero_wallet.refresh(3).await?; + monero_wallet.refresh().await?; // Sweep (transfer all funds) to the given address let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?; diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 7331f96f..bd039477 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -863,7 +863,7 @@ impl Wallet for monero::Wallet { type Amount = monero::Amount; async fn refresh(&self) -> Result<()> { - self.refresh(1).await?; + self.refresh().await?; Ok(()) } From 9d426066a995272d4dfd36fbdb841b17f6206963 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 26 Mar 2024 09:08:38 +0200 Subject: [PATCH 223/395] ci: lock install version for sqlx-cli --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69c11c72..14c5a835 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: - uses: Swatinem/rust-cache@v2.7.3 - name: Install sqlx-cli - run: cargo install --version 0.6.3 sqlx-cli + run: cargo install --locked --version 0.6.3 sqlx-cli - name: Run sqlite_dev_setup.sh script run: | From 870911bd5837470f7ec518d1ad319815c5e70420 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 09:06:19 +0000 Subject: [PATCH 224/395] build(deps): bump async-trait from 0.1.78 to 0.1.79 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.78 to 0.1.79. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.78...0.1.79) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c58895b..48ca6b71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.78" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", From f575a93bbb191cc0b2aa7bf358328b0f799110b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:06:45 +0000 Subject: [PATCH 225/395] build(deps): bump serde_json from 1.0.114 to 1.0.115 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.114 to 1.0.115. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.114...v1.0.115) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c58895b..972b4fb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3765,9 +3765,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", From be8b3c1ddec88f3a27cd4ac8a2b6b1b0a785cc1a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 29 Mar 2024 11:37:49 +0000 Subject: [PATCH 226/395] build(deps): bump tokio from 1.36.0 to 1.37.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.36.0 to 1.37.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.36.0...tokio-1.37.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c58895b..e1f60e88 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4553,9 +4553,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", From c231a343995eb7747c3212f6618c32d54d70995d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 2 Apr 2024 11:28:21 +0000 Subject: [PATCH 227/395] build(deps): bump port_check from 0.1.5 to 0.2.1 Bumps [port_check](https://github.com/ufoscout/port-check-rs) from 0.1.5 to 0.2.1. - [Commits](https://github.com/ufoscout/port-check-rs/commits/v0.2.1) --- updated-dependencies: - dependency-name: port_check dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1f60e88..909bef52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2925,9 +2925,9 @@ dependencies = [ [[package]] name = "port_check" -version = "0.1.5" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6519412c9e0d4be579b9f0618364d19cb434b324fc6ddb1b27b1e682c7105ed" +checksum = "2110609fb863cdb367d4e69d6c43c81ba6a8c7d18e80082fe9f3ef16b23afeed" [[package]] name = "powerfmt" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 8b60517a..b0c31790 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -80,7 +80,7 @@ get-port = "3" hyper = "1.2" mockito = "1.3.0" monero-harness = { path = "../monero-harness" } -port_check = "0.1" +port_check = "0.2" proptest = "1" serde_cbor = "0.11" serial_test = "3.0" From 73370ce7d922f409bff1a177ef0e1148f5cbdfdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Apr 2024 11:42:05 +0000 Subject: [PATCH 228/395] build(deps): bump comfy-table from 7.1.0 to 7.1.1 Bumps [comfy-table](https://github.com/nukesor/comfy-table) from 7.1.0 to 7.1.1. - [Release notes](https://github.com/nukesor/comfy-table/releases) - [Changelog](https://github.com/Nukesor/comfy-table/blob/main/CHANGELOG.md) - [Commits](https://github.com/nukesor/comfy-table/compare/v7.1.0...v7.1.1) --- updated-dependencies: - dependency-name: comfy-table dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 909bef52..f37addc3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -683,13 +683,13 @@ dependencies = [ [[package]] name = "comfy-table" -version = "7.1.0" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c64043d6c7b7a4c58e39e7efccfdea7b93d885a795d0c054a69dbbf4dd52686" +checksum = "b34115915337defe99b2aff5c2ce6771e5fbc4079f4b506301f5cf394c8452f7" dependencies = [ "crossterm", - "strum 0.25.0", - "strum_macros 0.25.3", + "strum", + "strum_macros", "unicode-width", ] @@ -4216,32 +4216,13 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "strum" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" - [[package]] name = "strum" version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ - "strum_macros 0.26.1", -] - -[[package]] -name = "strum_macros" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" -dependencies = [ - "heck 0.4.1", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.46", + "strum_macros", ] [[package]] @@ -4323,7 +4304,7 @@ dependencies = [ "spectral", "sqlx", "structopt", - "strum 0.26.2", + "strum", "tempfile", "testcontainers", "thiserror", From a87ffaa63172befb5a174277f5d6380b87c658b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:25:28 +0000 Subject: [PATCH 229/395] build(deps): bump thomaseizinger/keep-a-changelog-new-release Bumps [thomaseizinger/keep-a-changelog-new-release](https://github.com/thomaseizinger/keep-a-changelog-new-release) from 2.0.0 to 3.0.0. - [Release notes](https://github.com/thomaseizinger/keep-a-changelog-new-release/releases) - [Changelog](https://github.com/thomaseizinger/keep-a-changelog-new-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/thomaseizinger/keep-a-changelog-new-release/compare/2.0.0...3.0.0) --- updated-dependencies: - dependency-name: thomaseizinger/keep-a-changelog-new-release dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/draft-new-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 5188be0a..fe857dc9 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -20,7 +20,7 @@ jobs: run: git checkout -b release/${{ github.event.inputs.version }} - name: Update changelog - uses: thomaseizinger/keep-a-changelog-new-release@2.0.0 + uses: thomaseizinger/keep-a-changelog-new-release@3.0.0 with: version: ${{ github.event.inputs.version }} changelogPath: CHANGELOG.md From cf0b9aa601ee64ad94dd05366b224cad1d014803 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Apr 2024 11:55:30 +0000 Subject: [PATCH 230/395] build(deps): bump pem from 3.0.3 to 3.0.4 Bumps [pem](https://github.com/jcreekmore/pem-rs) from 3.0.3 to 3.0.4. - [Changelog](https://github.com/jcreekmore/pem-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/jcreekmore/pem-rs/compare/v3.0.3...v3.0.4) --- updated-dependencies: - dependency-name: pem dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 41d94424..c51e72b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2804,11 +2804,11 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" [[package]] name = "pem" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.21.7", + "base64 0.22.0", "serde", ] From 0d63087ab905edda2f0830ef58d26bfb901714dc Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Wed, 10 Apr 2024 09:53:32 +0200 Subject: [PATCH 231/395] ci: add cargo check job on stable rust --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14c5a835..e2f869f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -172,3 +172,16 @@ jobs: - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture + + check_stable: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4.1.2 + + - uses: dtolnay/rust-toolchain@stable + + - uses: Swatinem/rust-cache@v2.7.3 + + - name: Run cargo check on stable rust + run: cargo check --all-targets From 4767c684674f6be01f7d21f2adc5109ed2db71f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:34:44 +0000 Subject: [PATCH 232/395] build(deps): bump anyhow from 1.0.81 to 1.0.82 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.81 to 1.0.82. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.81...1.0.82) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c51e72b2..26e3d2d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "arrayref" From a449d9b60061d602e377165d174ab3653a88c2bd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:48:20 +0000 Subject: [PATCH 233/395] build(deps): bump time from 0.3.34 to 0.3.36 Bumps [time](https://github.com/time-rs/time) from 0.3.34 to 0.3.36. - [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.34...v0.3.36) --- updated-dependencies: - dependency-name: time dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 26e3d2d5..8619a4d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4308,7 +4308,7 @@ dependencies = [ "tempfile", "testcontainers", "thiserror", - "time 0.3.34", + "time 0.3.36", "tokio", "tokio-socks", "tokio-tar", @@ -4477,9 +4477,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -4500,9 +4500,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -4749,7 +4749,7 @@ checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror", - "time 0.3.34", + "time 0.3.36", "tracing-subscriber 0.3.18", ] @@ -4850,7 +4850,7 @@ dependencies = [ "serde_json", "sharded-slab", "thread_local", - "time 0.3.34", + "time 0.3.36", "tracing", "tracing-core", "tracing-log 0.2.0", @@ -5095,7 +5095,7 @@ dependencies = [ "cfg-if 1.0.0", "git2", "rustversion", - "time 0.3.34", + "time 0.3.36", ] [[package]] From 23216dea07d09e9e3a26740a77d7291be790fa48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Apr 2024 12:00:31 +0000 Subject: [PATCH 234/395] build(deps): bump async-trait from 0.1.79 to 0.1.80 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.79 to 0.1.80. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.79...0.1.80) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8619a4d0..1b03e2ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", From f0f197de20347e4fd682b3a438db4b3799dead6a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:24:28 +0000 Subject: [PATCH 235/395] build(deps): bump hyper from 1.2.0 to 1.3.0 Bumps [hyper](https://github.com/hyperium/hyper) from 1.2.0 to 1.3.0. - [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/v1.2.0...v1.3.0) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- swap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b03e2ba..c25d2c1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1698,9 +1698,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "9f24ce812868d86d19daa79bf3bf9175bc44ea323391147a5e3abde2a283871b" dependencies = [ "bytes", "http 1.0.0", @@ -4278,7 +4278,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper 1.2.0", + "hyper 1.3.0", "itertools 0.12.1", "libp2p", "mockito", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index b0c31790..68c3dfdb 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -77,7 +77,7 @@ zip = "0.5" [dev-dependencies] bitcoin-harness = "0.2.2" get-port = "3" -hyper = "1.2" +hyper = "1.3" mockito = "1.3.0" monero-harness = { path = "../monero-harness" } port_check = "0.2" From 76c72cceb2c463be5abbea121fcf1b41b6726d2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 Apr 2024 12:27:29 +0000 Subject: [PATCH 236/395] build(deps): bump serde_json from 1.0.115 to 1.0.116 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.116. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.116) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b03e2ba..324ddcf8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3765,9 +3765,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", From 6ba11b1738e2b900f99e1c95da50277019acea57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:50:10 +0000 Subject: [PATCH 237/395] build(deps): bump hyper from 1.3.0 to 1.3.1 Bumps [hyper](https://github.com/hyperium/hyper) from 1.3.0 to 1.3.1. - [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/v1.3.0...v1.3.1) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f02a73b3..b8cc035c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1698,9 +1698,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f24ce812868d86d19daa79bf3bf9175bc44ea323391147a5e3abde2a283871b" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "http 1.0.0", @@ -4278,7 +4278,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper 1.3.0", + "hyper 1.3.1", "itertools 0.12.1", "libp2p", "mockito", From 1ff67ec94348b004ea9223a29a5a32f6c1f7c24c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Apr 2024 11:50:26 +0000 Subject: [PATCH 238/395] build(deps): bump serde from 1.0.197 to 1.0.198 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.197 to 1.0.198. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.197...v1.0.198) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f02a73b3..669fa369 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3725,9 +3725,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" dependencies = [ "serde_derive", ] @@ -3754,9 +3754,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.198" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" dependencies = [ "proc-macro2", "quote", From e389027439ce09f0f20779924a73830b73c4c821 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:17:01 +0000 Subject: [PATCH 239/395] build(deps): bump thiserror from 1.0.58 to 1.0.59 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.58 to 1.0.59. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.58...1.0.59) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52b0edd2..b1f3d9f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4438,18 +4438,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", From 59974535258c97949d5cf44f31f6eeafa2566f2a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Apr 2024 11:18:11 +0000 Subject: [PATCH 240/395] build(deps): bump actions/checkout from 4.1.2 to 4.1.3 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.2...v4.1.3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index c18c3124..44754dbb 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e2f869f3..e9f2ca70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: Swatinem/rust-cache@v2.7.3 @@ -76,7 +76,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: Swatinem/rust-cache@v2.7.3 @@ -129,7 +129,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: Swatinem/rust-cache@v2.7.3 @@ -166,7 +166,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: Swatinem/rust-cache@v2.7.3 @@ -177,7 +177,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.2 + uses: actions/checkout@v4.1.3 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index c62d47eb..a793b43e 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index fe857dc9..0d066fcf 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index f45ff1b4..1e03123a 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.2 + - uses: actions/checkout@v4.1.3 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From 8a88bde4f5f04bab8b199a835435fc51fdbcc036 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 25 Apr 2024 11:42:46 +0000 Subject: [PATCH 241/395] build(deps): bump actions/checkout from 4.1.3 to 4.1.4 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.3 to 4.1.4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.3...v4.1.4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 44754dbb..3ee02709 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -45,7 +45,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9f2ca70..1c740eb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: Swatinem/rust-cache@v2.7.3 @@ -76,7 +76,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: Swatinem/rust-cache@v2.7.3 @@ -129,7 +129,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: Swatinem/rust-cache@v2.7.3 @@ -166,7 +166,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: Swatinem/rust-cache@v2.7.3 @@ -177,7 +177,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.3 + uses: actions/checkout@v4.1.4 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index a793b43e..28640153 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 0d066fcf..8ff8b6e4 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 1e03123a..7d7be25c 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.3 + - uses: actions/checkout@v4.1.4 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From 24466c0234f02fef1e32a06018dbb3e3d97f66f3 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 30 Apr 2024 10:17:15 +0200 Subject: [PATCH 242/395] ci: fix macos-latest and add macos-12 macos-latest is now aarch64, add macos-12 for x64_64 --- .github/workflows/build-release-binaries.yml | 7 +++++++ .github/workflows/ci.yml | 2 ++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 3ee02709..91c2788f 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -20,6 +20,9 @@ jobs: archive_ext: tar - bin: swap target: x86_64-apple-darwin + os: macos-12 + - bin: swap + target: aarch64-apple-darwin os: macos-latest archive_ext: tar - bin: swap @@ -36,6 +39,10 @@ jobs: archive_ext: tar - bin: asb target: x86_64-apple-darwin + os: macos-12 + archive_ext: tar + - bin: asb + target: aarch64-apple-darwin os: macos-latest archive_ext: tar - bin: asb diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1c740eb1..8b4f9964 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -70,6 +70,8 @@ jobs: - target: armv7-unknown-linux-gnueabihf os: ubuntu-latest - target: x86_64-apple-darwin + os: macos-12 + - target: aarch64-apple-darwin os: macos-latest - target: x86_64-pc-windows-msvc os: windows-latest From 79b4d8efbcdbb160e6e609ec150c8b2f54d7f213 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:28:44 +0000 Subject: [PATCH 243/395] build(deps): bump data-encoding from 2.5.0 to 2.6.0 Bumps [data-encoding](https://github.com/ia0/data-encoding) from 2.5.0 to 2.6.0. - [Commits](https://github.com/ia0/data-encoding/commits) --- updated-dependencies: - dependency-name: data-encoding dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1f3d9f9..a205210a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -990,9 +990,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "deranged" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 68c3dfdb..4cf0e05f 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -23,7 +23,7 @@ comfy-table = "7.1" config = { version = "0.14", default-features = false, features = [ "toml" ] } conquer-once = "0.4" curve25519-dalek = { package = "curve25519-dalek-ng", version = "4" } -data-encoding = "2.5" +data-encoding = "2.6" dialoguer = "0.11" digest = "0.10.7" directories-next = "2" From 1aca4462e7347b2cc036c44a792ad2156a2221e2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Apr 2024 10:29:01 +0000 Subject: [PATCH 244/395] build(deps): bump serde from 1.0.198 to 1.0.199 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.198 to 1.0.199. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.198...v1.0.199) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1f3d9f9..019d8825 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3725,9 +3725,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.198" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" +checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" dependencies = [ "serde_derive", ] @@ -3754,9 +3754,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.198" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" +checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" dependencies = [ "proc-macro2", "quote", From ad6b00beecb1d22db8d81d1c7e047c2c0fab1709 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 11:36:56 +0000 Subject: [PATCH 245/395] build(deps): bump base64 from 0.22.0 to 0.22.1 Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.22.0 to 0.22.1. - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.22.0...v0.22.1) --- updated-dependencies: - dependency-name: base64 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7bc6c8aa..2f274631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -266,9 +266,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bdk" @@ -2808,7 +2808,7 @@ version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "serde", ] @@ -4259,7 +4259,7 @@ dependencies = [ "async-trait", "atty", "backoff", - "base64 0.22.0", + "base64 0.22.1", "bdk", "big-bytes", "bitcoin", From cc3abf647c9296a1a8bccfe6bbea64b36bfcb86e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 May 2024 11:31:44 +0000 Subject: [PATCH 246/395] build(deps): bump serde from 1.0.199 to 1.0.200 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.199 to 1.0.200. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.199...v1.0.200) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f274631..3a22e80e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3725,9 +3725,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" dependencies = [ "serde_derive", ] @@ -3754,9 +3754,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.199" +version = "1.0.200" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" dependencies = [ "proc-macro2", "quote", From ca5bfed3923aee4b0dc65d71b3a4f759b2a82a9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 11:05:47 +0000 Subject: [PATCH 247/395] build(deps): bump thomaseizinger/create-pull-request from 1.3.1 to 1.4.0 Bumps [thomaseizinger/create-pull-request](https://github.com/thomaseizinger/create-pull-request) from 1.3.1 to 1.4.0. - [Release notes](https://github.com/thomaseizinger/create-pull-request/releases) - [Changelog](https://github.com/thomaseizinger/create-pull-request/blob/master/CHANGELOG.md) - [Commits](https://github.com/thomaseizinger/create-pull-request/compare/1.3.1...1.4.0) --- updated-dependencies: - dependency-name: thomaseizinger/create-pull-request dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/draft-new-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 8ff8b6e4..1dd94d10 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -58,7 +58,7 @@ jobs: run: git push origin release/${{ github.event.inputs.version }} --force - name: Create pull request - uses: thomaseizinger/create-pull-request@1.3.1 + uses: thomaseizinger/create-pull-request@1.4.0 with: GITHUB_TOKEN: ${{ secrets.BOTTY_GITHUB_TOKEN }} head: release/${{ github.event.inputs.version }} From 7661b19300230d795621960ef951d4113752350e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 11:47:38 +0000 Subject: [PATCH 248/395] build(deps): bump tokio-util from 0.7.10 to 0.7.11 Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.10 to 0.7.11. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.10...tokio-util-0.7.11) --- updated-dependencies: - dependency-name: tokio-util dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a22e80e..c22abe2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4651,16 +4651,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite 0.2.13", "tokio", - "tracing", ] [[package]] From ed8deeff57828cbf0e9ae2f8df51e769d66f3754 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 11:26:23 +0000 Subject: [PATCH 249/395] build(deps): bump actions/checkout from 4.1.4 to 4.1.5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.4 to 4.1.5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.4...v4.1.5) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 91c2788f..a0812e98 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -52,7 +52,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b4f9964..5dd8fd3d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: Swatinem/rust-cache@v2.7.3 @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: Swatinem/rust-cache@v2.7.3 @@ -131,7 +131,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: Swatinem/rust-cache@v2.7.3 @@ -168,7 +168,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: Swatinem/rust-cache@v2.7.3 @@ -179,7 +179,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.4 + uses: actions/checkout@v4.1.5 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 28640153..fc79af38 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 1dd94d10..9982f130 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 7d7be25c..d654bfc6 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.4 + - uses: actions/checkout@v4.1.5 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From d40059192a2bc1c837f7cf1787041cd881210393 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 11:59:43 +0000 Subject: [PATCH 250/395] build(deps): bump anyhow from 1.0.82 to 1.0.83 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.83. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.83) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c22abe2b..e7473808 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "arrayref" From 252c394ef616305fd6b3480160fdd124d7bf4b1f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 May 2024 12:01:20 +0000 Subject: [PATCH 251/395] build(deps): bump thiserror from 1.0.59 to 1.0.60 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.59 to 1.0.60. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.59...1.0.60) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c22abe2b..7812407d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4438,18 +4438,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", From f1d78593342d70e8a975a6d36183747220a3369b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 11:58:50 +0000 Subject: [PATCH 252/395] build(deps): bump serde_json from 1.0.116 to 1.0.117 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.116 to 1.0.117. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.116...v1.0.117) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7644ba9c..2cd36698 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3765,9 +3765,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.116" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", From 081bb965eec98b062268ddd1a32e457f2c1fc81b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 8 May 2024 11:59:51 +0000 Subject: [PATCH 253/395] build(deps): bump serde from 1.0.200 to 1.0.201 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.200 to 1.0.201. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.200...v1.0.201) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7644ba9c..3161afd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3725,9 +3725,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] @@ -3754,9 +3754,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", From d9de1b6cf36fe449feddb44ab5420cde9f9b28fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 15 May 2024 11:33:15 +0000 Subject: [PATCH 254/395] build(deps): bump serde from 1.0.201 to 1.0.202 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.201 to 1.0.202. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.201...v1.0.202) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7e85e364..34fdc50b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3725,9 +3725,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -3754,9 +3754,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", From 6edcc28b8def128b952644a33f1ded66690fcea4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 May 2024 11:18:16 +0000 Subject: [PATCH 255/395] build(deps): bump toml from 0.8.12 to 0.8.13 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.12 to 0.8.13. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.12...toml-v0.8.13) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34fdc50b..12c5b916 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,7 +703,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.12", + "toml 0.8.13", ] [[package]] @@ -3776,9 +3776,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" dependencies = [ "serde", ] @@ -4314,7 +4314,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.12", + "toml 0.8.13", "torut", "tracing", "tracing-appender", @@ -4673,9 +4673,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.12" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" dependencies = [ "serde", "serde_spanned", @@ -4685,18 +4685,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.8" +version = "0.22.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12219811e0c1ba077867254e5ad62ee2c9c190b0d957110750ac0cda1ae96cd" +checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" dependencies = [ "indexmap 2.1.0", "serde", From c8e5768955645dfe275c70745b0854ac4caf103b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 11:12:37 +0000 Subject: [PATCH 256/395] build(deps): bump actions/checkout from 4.1.5 to 4.1.6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.5 to 4.1.6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.5...v4.1.6) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 14 +++++++------- .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index a0812e98..ecfde0c8 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -52,7 +52,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5dd8fd3d..2a41dd6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: Swatinem/rust-cache@v2.7.3 @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: Swatinem/rust-cache@v2.7.3 @@ -131,7 +131,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: Swatinem/rust-cache@v2.7.3 @@ -168,7 +168,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: Swatinem/rust-cache@v2.7.3 @@ -179,7 +179,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.5 + uses: actions/checkout@v4.1.6 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index fc79af38..2e52519a 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 9982f130..48fb2d3a 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index d654bfc6..63ecfe6f 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.5 + - uses: actions/checkout@v4.1.6 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From 0e5241787fbac75ac92bc3ab48617c6ab4109efa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 17 May 2024 11:58:52 +0000 Subject: [PATCH 257/395] build(deps): bump itertools from 0.12.1 to 0.13.0 Bumps [itertools](https://github.com/rust-itertools/itertools) from 0.12.1 to 0.13.0. - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-itertools/itertools/compare/v0.12.1...v0.13.0) --- updated-dependencies: - dependency-name: itertools dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- swap/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34fdc50b..ed8efa66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1838,9 +1838,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -4279,7 +4279,7 @@ dependencies = [ "get-port", "hex", "hyper 1.3.1", - "itertools 0.12.1", + "itertools 0.13.0", "libp2p", "mockito", "monero", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 4cf0e05f..22705715 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -31,7 +31,7 @@ ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = ed25519-dalek = "1" futures = { version = "0.3", default-features = false } hex = "0.4" -itertools = "0.12" +itertools = "0.13" libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } From 8d8c938a940df44daed83bef64a75ec5cca0cd65 Mon Sep 17 00:00:00 2001 From: icy-ux <63157298+icy-ux@users.noreply.github.com> Date: Mon, 20 May 2024 08:28:44 +0000 Subject: [PATCH 258/395] document use of asb export-bitcoin-wallet (#1280) * document use of asb export-bitcoin-wallet Add to the `asb` document @delta1's text on exporting the Bitcoin wallet descriptor and importing the descriptor into Sparrow Wallet. TODO: maybe it would make sense to add the images to Git, instead of linking to files on Github? * bring asb/README.md into compliance with dprint * update bullet point formatting in asb/README.md * run * add images to git --------- Co-authored-by: icyfestive <> Co-authored-by: Byron Hambly --- docs/asb/README.md | 35 ++++++++++++++++++++++++++ docs/asb/enter-master-private-key.png | Bin 0 -> 35936 bytes docs/asb/import-keystore.png | Bin 0 -> 186436 bytes docs/asb/transactions-tab.png | Bin 0 -> 111456 bytes 4 files changed, 35 insertions(+) create mode 100644 docs/asb/enter-master-private-key.png create mode 100644 docs/asb/import-keystore.png create mode 100644 docs/asb/transactions-tab.png diff --git a/docs/asb/README.md b/docs/asb/README.md index 16e0a602..b1acc877 100644 --- a/docs/asb/README.md +++ b/docs/asb/README.md @@ -164,3 +164,38 @@ May 01 01:32:05.018 INFO Tor found. Setting up hidden service. May 01 01:32:07.475 INFO /onion3/z4findrdwtfbpoq64ayjtmxvr52vvxnsynerlenlfkmm52dqxsl4deyd:9939 May 01 01:32:07.476 INFO /onion3/z4findrdwtfbpoq64ayjtmxvr52vvxnsynerlenlfkmm52dqxsl4deyd:9940 ``` + +### Exporting the Bitcoin wallet descriptor + +First use `swap` or `asb` with the `export-bitcoin-wallet` subcommand. + +Output example: + +```json +{"descriptor":"wpkh(tprv8Zgredacted.../84'/1'/0'/0/*)","blockheight":2415616,"label":"asb-testnet"} +``` + +The wallet can theoretically be directly imported into +[bdk-cli](https://bitcoindevkit.org/bdk-cli/installation/) but it is easier to +use Sparrow Wallet. + +Sparrow wallet import works as follows: + +- File -> New wallet -> Give it a name +- Select "New or Imported Software Wallet" +- Click "Enter Private Key" for "Master Private Key (BIP32)" +- Enter the `xprv...` or `tprv...` part of the descriptor (example above is `tprv8Zgredacted...`: + +![image](enter-master-private-key.png) + +- Click "Import" +- Leave the derivation path as `m/84'/0'/0'` and click "Import Keystore" button +- Click "Apply" and then supply password + +![image](import-keystore.png) + +- Click Transactions tab +- ??? +- Profit! + +![image](transactions-tab.png) diff --git a/docs/asb/enter-master-private-key.png b/docs/asb/enter-master-private-key.png new file mode 100644 index 0000000000000000000000000000000000000000..7b69b5502d87a47c220458e3f71cbe4c3d46519b GIT binary patch literal 35936 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

juV7!m>J$0I2f#*5zabva!qa3& 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

+YjgTPXg*kerFDhTDlE%r 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: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%0A;Zu{5ku- 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 literal 0 HcmV?d00001 diff --git a/docs/asb/transactions-tab.png b/docs/asb/transactions-tab.png new file mode 100644 index 0000000000000000000000000000000000000000..7b0532aff6b4580ca2b1952931f293e8f5019103 GIT binary patch literal 111456 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 literal 0 HcmV?d00001 From 3bb6f060a049520b8d7d6fad48f54a9f5eb0fc85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 11:30:15 +0000 Subject: [PATCH 259/395] build(deps): bump thiserror from 1.0.60 to 1.0.61 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.60 to 1.0.61. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.60...1.0.61) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed8efa66..e46ceb7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4438,18 +4438,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", From 928fe33532aa93b740e942663a827ca39871665c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 May 2024 11:31:28 +0000 Subject: [PATCH 260/395] build(deps): bump anyhow from 1.0.83 to 1.0.86 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.83 to 1.0.86. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.83...1.0.86) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed8efa66..85f1523c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,9 +98,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arrayref" From 5ff46be2793bc62278ded2a4c02a4502ea6e99ba Mon Sep 17 00:00:00 2001 From: yamabiiko Date: Wed, 22 May 2024 16:12:58 +0300 Subject: [PATCH 261/395] RPC server for API Interface (#1276) * saving: implementing internal api shared by cli and rpc server * writing async rpc methods and using arc for shared struct references * cleaning up, renamed Init to Context * saving: cleaning up and initial work for tests * Respond with bitcoin withdraw txid * Print RPC server address * Cleanup, formatting, add `get_seller`, `get_swap_start_date` RPC endpoints * fixing tests in cli module * uncommenting and fixing more tests * split api module and propagate errors with rpc server * moving methods to api and validating addresses for rpc * add broadcast channel to handle shutdowns gracefully and prepare for RPC server test * added files * Update rpc.rs * adding new unfinished RPC tests * updating rpc-server tests * fixing warnings * fixing formatting and cargo clippy warnings * fix missing import in test * fix: add data_dir to config to make config command work * set server listen address manually and return file locations in JSON on Config * Add called api method and swap_id to tracing for context, reduced boilerplate * Pass server_address properly to RpcServer * Update Cargo.lock * dprint fmt * Add cancel_refund RPC endpoint * Combine Cmd and Params * Disallow concurrent swaps * Use RwLock instead of Mutex to allow for parallel reads and add get_current_swap endpoint * Return wallet descriptor to RPC API caller * Append all cli logs to single log file After careful consideration, I've concluded that it's not practical/possible to ensure that the previous behaviour (one log file per swap) is preserved due to limitations of the tracing-subscriber crate and a big in the built in JSON formatter * Add get_swap_expired_timelock timelock, other small refactoring - Add get_swap_expired_timelock endpoint to return expired timelock if one exists. Fails if bitcoin lock tx has not yet published or if swap is already finished. - Rename current_epoch to expired_timelock to enforce consistent method names - Add blocks left until current expired timelock expires (next timelock expires) to ExpiredTimelock struct - Change .expect() to .unwrap() in rpc server method register because those will only fail if we register the same method twice which will never happen * initiating swaps in a separate task and handling shutdown signals with broadcast queues * Replace get_swap_start_date, get_seller, get_expired_timelock with one get_swap_info rpc method * WIP: Struct for concurrent swaps manager * Ensure correct tracing spans * Add note regarding Request, Method structs * Update request.rs * Add tracing span attribute log_reference_id to logs caused by rpc call * Sync bitcoin wallet before initial max_giveable call * use Span::current() to pass down to tracing span to spawned tasks * Remove unused shutdown channel * Add `get_monero_recovery_info` RPC endpoint - Add `get_monero_recovery_info` RPC endpoint - format PrivateViewKey using Display * Rename `Method::RawHistory` to `Method::GetRawStates` * Wait for swap to be suspended after sending signal * Remove notes * Add tracing span attribute log_reference_id to logs caused by rpc call * Sync bitcoin wallet before initial max_giveable call * use Span::current() to pass down to tracing span to spawned tasks * Remove unused shutdown channel * Add `get_monero_recovery_info` RPC endpoint - Add `get_monero_recovery_info` RPC endpoint - format PrivateViewKey using Display * Rename `Method::RawHistory` to `Method::GetRawStates` * Wait for swap to be suspended after sending signal * Return additonal info on GetSwapInfo * Update wallet.rs * fix compile issues for tests and use serial_test crate * fix rpc tests, only check for RPC errors and not returned values * Rename `get_raw_history` tp `get_raw_states` * Fix typo in rpc server stopped tracing log * Remove unnecessary success property on suspend_current_swap response * fixing test_cli_arguments and other tests * WIP: RPC server integration tests * WIP: Integration tests for RPC server * Update rpc tests * fix compile and warnings in tests/rpc.rs * test: fix assert * clippy --fix * remove otp file * cargo clippy fixes * move resume swap initialization code out of spawned task * Use `in_current_span` to pass down tracing span to spawned tasks * moving buy_xmr initialization code out of spawned tasks * cargo fmt * Moving swap initialization code inside tokio select block to handle swap lock release logic * Remove unnecessary swap suspension listener from determine_btc_to_swap call in BuyXmr * Spawn event loop before requesting quote * Release swap lock after receiving shutdown signal * Remove inner tokio::select in BuyXmr and Resume * Improve debug text for swap resume * Return error to API caller if bid quote request fails * Print error if one occurs during process invoked by API call * Return bid quote to API caller * Use type safe query! macro for database retrieval of states * Return tx_lock_fee to API caller on GetSwapInfo call Update request.rs * Allow API caller to retrieve last synced bitcoin balane and avoid costly sync * Return restore height on MoneroRecovery command to API Caller * Include entire error cause-chain in API response * Add span to bitcoin wallet logs * Log event loop connection properties as tracing fields * Wait for background tasks to complete before exiting CLI * clippy * specify sqlx patch version explicitly * remove mem::forget and replace with _guard * ci: add rpc test job * test: wrap rpc test in #[cfg(test)] * add missing tokio::test attribute * fix and merge rpc tests, parse uuuid and multiaddr from serde_json value * default Tor socks port to 9050, Cargo fmt * Update swap/sqlite_dev_setup.sh: add version Co-authored-by: Byron Hambly * ci: free up space on ubuntu test job * Update swap/src/bitcoin/wallet.rs Co-authored-by: Byron Hambly * Update swap/src/bitcoin/wallet.rs Co-authored-by: Byron Hambly * fmt --------- Co-authored-by: binarybaron <86064887+binarybaron@users.noreply.github.com> Co-authored-by: Byron Hambly --- .github/workflows/ci.yml | 11 + Cargo.lock | 230 ++++- swap/Cargo.toml | 8 +- swap/sqlite_dev_setup.sh | 3 +- swap/sqlx-data.json | 96 +- swap/src/api.rs | 460 ++++++++++ swap/src/api/request.rs | 930 ++++++++++++++++++++ swap/src/bin/swap.rs | 706 +-------------- swap/src/bitcoin.rs | 66 +- swap/src/bitcoin/cancel.rs | 12 + swap/src/bitcoin/lock.rs | 12 +- swap/src/bitcoin/timelocks.rs | 6 +- swap/src/bitcoin/wallet.rs | 64 +- swap/src/cli/cancel_and_refund.rs | 6 +- swap/src/cli/command.rs | 1347 ++++++++++++++--------------- swap/src/cli/event_loop.rs | 13 +- swap/src/cli/tracing.rs | 82 +- swap/src/database/sqlite.rs | 87 +- swap/src/lib.rs | 2 + swap/src/monero.rs | 53 ++ swap/src/protocol.rs | 4 + swap/src/protocol/alice/swap.rs | 6 +- swap/src/protocol/bob/state.rs | 19 +- swap/src/protocol/bob/swap.rs | 12 +- swap/src/rpc.rs | 31 + swap/src/rpc/methods.rs | 236 +++++ swap/src/seed.rs | 2 +- swap/tests/harness/mod.rs | 36 +- swap/tests/rpc.rs | 436 ++++++++++ 29 files changed, 3471 insertions(+), 1505 deletions(-) create mode 100644 swap/src/api.rs create mode 100644 swap/src/api/request.rs create mode 100644 swap/src/rpc.rs create mode 100644 swap/src/rpc/methods.rs create mode 100644 swap/tests/rpc.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a41dd6d..da82b266 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -175,6 +175,17 @@ jobs: - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture + rpc_tests: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4.1.1 + + - uses: Swatinem/rust-cache@v2.7.1 + + - name: Run RPC server tests + run: cargo test --package swap --all-features --test rpc -- --nocapture + check_stable: runs-on: ubuntu-latest steps: diff --git a/Cargo.lock b/Cargo.lock index 0767d24f..1c9b370c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,6 +143,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-lock" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +dependencies = [ + "event-listener", +] + [[package]] name = "async-trait" version = "0.1.80" @@ -308,6 +317,15 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" +[[package]] +name = "beef" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1" +dependencies = [ + "serde", +] + [[package]] name = "big-bytes" version = "1.0.0" @@ -519,6 +537,16 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" +[[package]] +name = "bstr" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.6.1" @@ -1479,6 +1507,19 @@ dependencies = [ "url", ] +[[package]] +name = "globset" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +dependencies = [ + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", +] + [[package]] name = "h2" version = "0.3.18" @@ -1566,9 +1607,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "379dada1584ad501b383485dd706b8afb7a70fcbc7f4da7d780638a5a6124a60" [[package]] name = "hex" @@ -1818,13 +1859,13 @@ checksum = "47be2f14c678be2fdcab04ab1171db51b2762ce6f0a8ee87c8dd4a04ed216135" [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ - "hermit-abi 0.3.1", - "rustix", - "windows-sys 0.48.0", + "hermit-abi 0.3.8", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -1893,6 +1934,115 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "jsonrpsee" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d291e3a5818a2384645fd9756362e6d89cf0541b0b916fa7702ea4a9833608e" +dependencies = [ + "jsonrpsee-core", + "jsonrpsee-server", + "jsonrpsee-types", + "jsonrpsee-ws-client", +] + +[[package]] +name = "jsonrpsee-client-transport" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "965de52763f2004bc91ac5bcec504192440f0b568a5d621c59d9dbd6f886c3fb" +dependencies = [ + "futures-util", + "http 0.2.11", + "jsonrpsee-core", + "jsonrpsee-types", + "pin-project 1.0.5", + "rustls-native-certs 0.6.3", + "soketto", + "thiserror", + "tokio", + "tokio-rustls 0.23.1", + "tokio-util", + "tracing", + "webpki-roots 0.22.2", +] + +[[package]] +name = "jsonrpsee-core" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e70b4439a751a5de7dd5ed55eacff78ebf4ffe0fc009cb1ebb11417f5b536b" +dependencies = [ + "anyhow", + "arrayvec", + "async-lock", + "async-trait", + "beef", + "futures-channel", + "futures-timer", + "futures-util", + "globset", + "hyper 0.14.28", + "jsonrpsee-types", + "parking_lot 0.12.0", + "rand 0.8.3", + "rustc-hash", + "serde", + "serde_json", + "soketto", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "jsonrpsee-server" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fb69dad85df79527c019659a992498d03f8495390496da2f07e6c24c2b356fc" +dependencies = [ + "futures-channel", + "futures-util", + "http 0.2.11", + "hyper 0.14.28", + "jsonrpsee-core", + "jsonrpsee-types", + "serde", + "serde_json", + "soketto", + "tokio", + "tokio-stream", + "tokio-util", + "tower", + "tracing", +] + +[[package]] +name = "jsonrpsee-types" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd522fe1ce3702fd94812965d7bb7a3364b1c9aba743944c5a00529aae80f8c" +dependencies = [ + "anyhow", + "beef", + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "jsonrpsee-ws-client" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b83daeecfc6517cfe210df24e570fb06213533dfb990318fae781f4c7119dd9" +dependencies = [ + "http 0.2.11", + "jsonrpsee-client-transport", + "jsonrpsee-core", + "jsonrpsee-types", +] + [[package]] name = "keccak" version = "0.1.0" @@ -3470,6 +3620,12 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hex" version = "2.1.0" @@ -3553,6 +3709,18 @@ dependencies = [ "security-framework", ] +[[package]] +name = "rustls-native-certs" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "1.0.0" @@ -3723,6 +3891,21 @@ dependencies = [ "pest", ] +[[package]] +name = "sequential-macro" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5facc5f409a55d25bf271c853402a00e1187097d326757043f5dd711944d07" + +[[package]] +name = "sequential-test" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d9c0d773bc7e7733264f460e5dfa00b2510421ddd6284db0749eef8dfb79e9" +dependencies = [ + "sequential-macro", +] + [[package]] name = "serde" version = "1.0.202" @@ -3936,9 +4119,9 @@ checksum = "0f0242b8e50dd9accdd56170e94ca1ebd223b098eb9c83539a6e367d0f36ae68" [[package]] name = "similar" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +checksum = "2aeaf503862c419d66959f5d7ca015337d864e9c49485d771b732e2a20453597" [[package]] name = "slab" @@ -4019,14 +4202,15 @@ dependencies = [ [[package]] name = "soketto" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "083624472e8817d44d02c0e55df043737ff11f279af924abdf93845717c2b75c" +checksum = "41d1c5305e39e09653383c2c7244f2f78b3bcae37cf50c64cb4789c9f5096ec2" dependencies = [ "base64 0.13.1", "bytes", "flate2", "futures", + "http 0.2.11", "httparse", "log", "rand 0.8.3", @@ -4280,6 +4464,8 @@ dependencies = [ "hex", "hyper 1.3.1", "itertools 0.13.0", + "jsonrpsee", + "jsonrpsee-core", "libp2p", "mockito", "monero", @@ -4294,6 +4480,7 @@ dependencies = [ "reqwest", "rust_decimal", "rust_decimal_macros", + "sequential-test", "serde", "serde_cbor", "serde_json", @@ -4657,6 +4844,7 @@ checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite 0.2.13", "tokio", @@ -4723,6 +4911,23 @@ dependencies = [ "tokio", ] +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + [[package]] name = "tower-service" version = "0.3.1" @@ -4735,6 +4940,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite 0.2.13", "tracing-attributes", "tracing-core", @@ -4921,7 +5127,7 @@ dependencies = [ "log", "rand 0.8.3", "rustls 0.19.0", - "rustls-native-certs", + "rustls-native-certs 0.5.0", "sha-1", "thiserror", "url", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 22705715..b73d61bb 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -32,6 +32,8 @@ ed25519-dalek = "1" futures = { version = "0.3", default-features = false } hex = "0.4" itertools = "0.13" +jsonrpsee = { version = "0.16.2", features = [ "server" ] } +jsonrpsee-core = "0.16.2" libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } @@ -49,12 +51,12 @@ serde_json = "1" serde_with = { version = "1", features = [ "macros" ] } sha2 = "0.10" sigma_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "ed25519", "serde", "secp256k1", "alloc" ] } -sqlx = { version = "0.6", features = [ "sqlite", "runtime-tokio-rustls", "offline" ] } +sqlx = { version = "0.6.3", features = [ "sqlite", "runtime-tokio-rustls", "offline" ] } structopt = "0.3" strum = { version = "0.26", features = [ "derive" ] } thiserror = "1" time = "0.3" -tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net" ] } +tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs", "net", "parking_lot" ] } tokio-socks = "0.5" tokio-tungstenite = { version = "0.15", features = [ "rustls-tls" ] } tokio-util = { version = "0.7", features = [ "io", "codec" ] } @@ -78,10 +80,12 @@ zip = "0.5" bitcoin-harness = "0.2.2" get-port = "3" hyper = "1.3" +jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } mockito = "1.3.0" monero-harness = { path = "../monero-harness" } port_check = "0.2" proptest = "1" +sequential-test = "0.2.4" serde_cbor = "0.11" serial_test = "3.0" spectral = "0.6" diff --git a/swap/sqlite_dev_setup.sh b/swap/sqlite_dev_setup.sh index 67d2c9da..a30adaff 100755 --- a/swap/sqlite_dev_setup.sh +++ b/swap/sqlite_dev_setup.sh @@ -1,7 +1,8 @@ #!/bin/bash # run this script from the swap dir -# make sure you have sqlx-cli installed: cargo install sqlx-cli +# make sure you have sqlx-cli installed: cargo install --version 0.6.3 sqlx-cli +# it's advised for the sqlx-cli to be the same version as specified in cargo.toml # this script creates a temporary sqlite database # then runs the migration scripts to create the tables (migrations folder) diff --git a/swap/sqlx-data.json b/swap/sqlx-data.json index fd50cd87..f24a50e6 100644 --- a/swap/sqlx-data.json +++ b/swap/sqlx-data.json @@ -28,6 +28,24 @@ }, "query": "\n insert into peer_addresses (\n peer_id,\n address\n ) values (?, ?);\n " }, + "0d465a17ebbb5761421def759c73cad023c30705d5b41a1399ef79d8d2571d7c": { + "describe": { + "columns": [ + { + "name": "start_date", + "ordinal": 0, + "type_info": "Text" + } + ], + "nullable": [ + true + ], + "parameters": { + "Right": 1 + } + }, + "query": "\n SELECT min(entered_at) as start_date\n FROM swap_states\n WHERE swap_id = ?\n " + }, "1ec38c85e7679b2eb42b3df75d9098772ce44fdb8db3012d3c2410d828b74157": { "describe": { "columns": [ @@ -62,6 +80,30 @@ }, "query": "\n insert into peers (\n swap_id,\n peer_id\n ) values (?, ?);\n " }, + "3f2bfdd2d134586ccad22171cd85a465800fc5c4fdaf191d206974e530240c87": { + "describe": { + "columns": [ + { + "name": "swap_id", + "ordinal": 0, + "type_info": "Text" + }, + { + "name": "state", + "ordinal": 1, + "type_info": "Text" + } + ], + "nullable": [ + false, + false + ], + "parameters": { + "Right": 0 + } + }, + "query": "\n SELECT swap_id, state\n FROM swap_states\n " + }, "50a5764546f69c118fa0b64120da50f51073d36257d49768de99ff863e3511e0": { "describe": { "columns": [], @@ -90,24 +132,6 @@ }, "query": "\n SELECT state\n FROM swap_states\n WHERE swap_id = ?\n ORDER BY id desc\n LIMIT 1;\n\n " }, - "a0eb85d04ee3842c52291dad4d225941d1141af735922fcbc665868997fce304": { - "describe": { - "columns": [ - { - "name": "address", - "ordinal": 0, - "type_info": "Text" - } - ], - "nullable": [ - false - ], - "parameters": { - "Right": 1 - } - }, - "query": "\n SELECT address\n FROM peer_addresses\n WHERE peer_id = ?\n " - }, "b703032b4ddc627a1124817477e7a8e5014bdc694c36a14053ef3bb2fc0c69b0": { "describe": { "columns": [], @@ -135,5 +159,41 @@ } }, "query": "\n SELECT address\n FROM monero_addresses\n WHERE swap_id = ?\n " + }, + "d78acba5eb8563826dd190e0886aa665aae3c6f1e312ee444e65df1c95afe8b2": { + "describe": { + "columns": [ + { + "name": "address", + "ordinal": 0, + "type_info": "Text" + } + ], + "nullable": [ + false + ], + "parameters": { + "Right": 1 + } + }, + "query": "\n SELECT DISTINCT address\n FROM peer_addresses\n WHERE peer_id = ?\n " + }, + "e05620f420f8c1022971eeb66a803323a8cf258cbebb2834e3f7cf8f812fa646": { + "describe": { + "columns": [ + { + "name": "state", + "ordinal": 0, + "type_info": "Text" + } + ], + "nullable": [ + false + ], + "parameters": { + "Right": 1 + } + }, + "query": "\n SELECT state\n FROM swap_states\n WHERE swap_id = ?\n " } } \ No newline at end of file diff --git a/swap/src/api.rs b/swap/src/api.rs new file mode 100644 index 00000000..ca3ae21d --- /dev/null +++ b/swap/src/api.rs @@ -0,0 +1,460 @@ +pub mod request; +use crate::cli::command::{Bitcoin, Monero, Tor}; +use crate::database::open_db; +use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet}; +use crate::fs::system_data_dir; +use crate::network::rendezvous::XmrBtcNamespace; +use crate::protocol::Database; +use crate::seed::Seed; +use crate::{bitcoin, cli, monero}; +use anyhow::{bail, Context as AnyContext, Error, Result}; +use futures::future::try_join_all; +use std::fmt; +use std::future::Future; +use std::net::SocketAddr; +use std::path::PathBuf; +use std::sync::{Arc, Once}; +use tokio::sync::{broadcast, broadcast::Sender, Mutex, RwLock}; +use tokio::task::JoinHandle; +use url::Url; + +static START: Once = Once::new(); + +#[derive(Clone, PartialEq, Debug)] +pub struct Config { + tor_socks5_port: u16, + namespace: XmrBtcNamespace, + server_address: Option, + pub env_config: EnvConfig, + seed: Option, + debug: bool, + json: bool, + data_dir: PathBuf, + is_testnet: bool, +} + +use uuid::Uuid; + +#[derive(Default)] +pub struct PendingTaskList(Mutex>>); + +impl PendingTaskList { + pub async fn spawn(&self, future: F) + where + F: Future + Send + 'static, + T: Send + 'static, + { + let handle = tokio::spawn(async move { + let _ = future.await; + }); + + self.0.lock().await.push(handle); + } + + pub async fn wait_for_tasks(&self) -> Result<()> { + let tasks = { + // Scope for the lock, to avoid holding it for the entire duration of the async block + let mut guard = self.0.lock().await; + guard.drain(..).collect::>() + }; + + try_join_all(tasks).await?; + + Ok(()) + } +} + +pub struct SwapLock { + current_swap: RwLock>, + suspension_trigger: Sender<()>, +} + +impl SwapLock { + pub fn new() -> Self { + let (suspension_trigger, _) = broadcast::channel(10); + SwapLock { + current_swap: RwLock::new(None), + suspension_trigger, + } + } + + pub async fn listen_for_swap_force_suspension(&self) -> Result<(), Error> { + let mut listener = self.suspension_trigger.subscribe(); + let event = listener.recv().await; + match event { + Ok(_) => Ok(()), + Err(e) => { + tracing::error!("Error receiving swap suspension signal: {}", e); + bail!(e) + } + } + } + + pub async fn acquire_swap_lock(&self, swap_id: Uuid) -> Result<(), Error> { + let mut current_swap = self.current_swap.write().await; + if current_swap.is_some() { + bail!("There already exists an active swap lock"); + } + + tracing::debug!(swap_id = %swap_id, "Acquiring swap lock"); + *current_swap = Some(swap_id); + Ok(()) + } + + pub async fn get_current_swap_id(&self) -> Option { + *self.current_swap.read().await + } + + /// Sends a signal to suspend all ongoing swap processes. + /// + /// This function performs the following steps: + /// 1. Triggers the suspension by sending a unit `()` signal to all listeners via `self.suspension_trigger`. + /// 2. Polls the `current_swap` state every 50 milliseconds to check if it has been set to `None`, indicating that the swap processes have been suspended and the lock released. + /// 3. If the lock is not released within 10 seconds, the function returns an error. + /// + /// If we send a suspend signal while no swap is in progress, the function will not fail, but will return immediately. + /// + /// # Returns + /// - `Ok(())` if the swap lock is successfully released. + /// - `Err(Error)` if the function times out waiting for the swap lock to be released. + /// + /// # Notes + /// The 50ms polling interval is considered negligible overhead compared to the typical time required to suspend ongoing swap processes. + pub async fn send_suspend_signal(&self) -> Result<(), Error> { + const TIMEOUT: u64 = 10_000; + const INTERVAL: u64 = 50; + + let _ = self.suspension_trigger.send(())?; + + for _ in 0..(TIMEOUT / INTERVAL) { + if self.get_current_swap_id().await.is_none() { + return Ok(()); + } + tokio::time::sleep(tokio::time::Duration::from_millis(INTERVAL)).await; + } + + bail!("Timed out waiting for swap lock to be released"); + } + + pub async fn release_swap_lock(&self) -> Result { + let mut current_swap = self.current_swap.write().await; + if let Some(swap_id) = current_swap.as_ref() { + tracing::debug!(swap_id = %swap_id, "Releasing swap lock"); + + let prev_swap_id = *swap_id; + *current_swap = None; + drop(current_swap); + Ok(prev_swap_id) + } else { + bail!("There is no current swap lock to release"); + } + } +} + +impl Default for SwapLock { + fn default() -> Self { + Self::new() + } +} + +// workaround for warning over monero_rpc_process which we must own but not read +#[allow(dead_code)] +pub struct Context { + pub db: Arc, + bitcoin_wallet: Option>, + monero_wallet: Option>, + monero_rpc_process: Option, + pub swap_lock: Arc, + pub config: Config, + pub tasks: Arc, +} + +#[allow(clippy::too_many_arguments)] +impl Context { + pub async fn build( + bitcoin: Option, + monero: Option, + tor: Option, + data: Option, + is_testnet: bool, + debug: bool, + json: bool, + server_address: Option, + ) -> Result { + let data_dir = data::data_dir_from(data, is_testnet)?; + let env_config = env_config_from(is_testnet); + + let seed = Seed::from_file_or_generate(data_dir.as_path()) + .context("Failed to read seed in file")?; + + let bitcoin_wallet = { + if let Some(bitcoin) = bitcoin { + let (bitcoin_electrum_rpc_url, bitcoin_target_block) = + bitcoin.apply_defaults(is_testnet)?; + Some(Arc::new( + init_bitcoin_wallet( + bitcoin_electrum_rpc_url, + &seed, + data_dir.clone(), + env_config, + bitcoin_target_block, + ) + .await?, + )) + } else { + None + } + }; + + let (monero_wallet, monero_rpc_process) = { + if let Some(monero) = monero { + let monero_daemon_address = monero.apply_defaults(is_testnet); + let (wlt, prc) = + init_monero_wallet(data_dir.clone(), monero_daemon_address, env_config).await?; + (Some(Arc::new(wlt)), Some(prc)) + } else { + (None, None) + } + }; + + let tor_socks5_port = tor.map_or(9050, |tor| tor.tor_socks5_port); + + START.call_once(|| { + let _ = cli::tracing::init(debug, json, data_dir.join("logs")); + }); + + let context = Context { + db: open_db(data_dir.join("sqlite")).await?, + bitcoin_wallet, + monero_wallet, + monero_rpc_process, + config: Config { + tor_socks5_port, + namespace: XmrBtcNamespace::from_is_testnet(is_testnet), + env_config, + seed: Some(seed), + server_address, + debug, + json, + is_testnet, + data_dir, + }, + swap_lock: Arc::new(SwapLock::new()), + tasks: Arc::new(PendingTaskList::default()), + }; + + Ok(context) + } + + pub async fn for_harness( + seed: Seed, + env_config: EnvConfig, + db_path: PathBuf, + bob_bitcoin_wallet: Arc, + bob_monero_wallet: Arc, + ) -> Self { + let config = Config::for_harness(seed, env_config); + + Self { + bitcoin_wallet: Some(bob_bitcoin_wallet), + monero_wallet: Some(bob_monero_wallet), + config, + db: open_db(db_path) + .await + .expect("Could not open sqlite database"), + monero_rpc_process: None, + swap_lock: Arc::new(SwapLock::new()), + tasks: Arc::new(PendingTaskList::default()), + } + } +} + +impl fmt::Debug for Context { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "") + } +} + +async fn init_bitcoin_wallet( + electrum_rpc_url: Url, + seed: &Seed, + data_dir: PathBuf, + env_config: EnvConfig, + bitcoin_target_block: usize, +) -> Result { + let wallet_dir = data_dir.join("wallet"); + + let wallet = bitcoin::Wallet::new( + electrum_rpc_url.clone(), + &wallet_dir, + seed.derive_extended_private_key(env_config.bitcoin_network)?, + env_config, + bitcoin_target_block, + ) + .await + .context("Failed to initialize Bitcoin wallet")?; + + wallet.sync().await?; + + Ok(wallet) +} + +async fn init_monero_wallet( + data_dir: PathBuf, + monero_daemon_address: String, + env_config: EnvConfig, +) -> Result<(monero::Wallet, monero::WalletRpcProcess)> { + let network = env_config.monero_network; + + const MONERO_BLOCKCHAIN_MONITORING_WALLET_NAME: &str = "swap-tool-blockchain-monitoring-wallet"; + + let monero_wallet_rpc = monero::WalletRpc::new(data_dir.join("monero")).await?; + + let monero_wallet_rpc_process = monero_wallet_rpc + .run(network, Some(monero_daemon_address)) + .await?; + + let monero_wallet = monero::Wallet::open_or_create( + monero_wallet_rpc_process.endpoint(), + MONERO_BLOCKCHAIN_MONITORING_WALLET_NAME.to_string(), + env_config, + ) + .await?; + + Ok((monero_wallet, monero_wallet_rpc_process)) +} + +mod data { + use super::*; + + pub fn data_dir_from(arg_dir: Option, testnet: bool) -> Result { + let base_dir = match arg_dir { + Some(custom_base_dir) => custom_base_dir, + None => os_default()?, + }; + + let sub_directory = if testnet { "testnet" } else { "mainnet" }; + + Ok(base_dir.join(sub_directory)) + } + + fn os_default() -> Result { + Ok(system_data_dir()?.join("cli")) + } +} + +fn env_config_from(testnet: bool) -> EnvConfig { + if testnet { + Testnet::get_config() + } else { + Mainnet::get_config() + } +} + +impl Config { + pub fn for_harness(seed: Seed, env_config: EnvConfig) -> Self { + let data_dir = data::data_dir_from(None, false).expect("Could not find data directory"); + + Self { + tor_socks5_port: 9050, + namespace: XmrBtcNamespace::from_is_testnet(false), + server_address: None, + env_config, + seed: Some(seed), + debug: false, + json: false, + is_testnet: false, + data_dir, + } + } +} + +#[cfg(test)] +pub mod api_test { + use super::*; + use crate::api::request::{Method, Request}; + + use libp2p::Multiaddr; + use std::str::FromStr; + use uuid::Uuid; + + pub const MULTI_ADDRESS: &str = + "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; + pub const MONERO_STAGENET_ADDRESS: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a"; + pub const BITCOIN_TESTNET_ADDRESS: &str = "tb1qr3em6k3gfnyl8r7q0v7t4tlnyxzgxma3lressv"; + pub const MONERO_MAINNET_ADDRESS: &str = "44Ato7HveWidJYUAVw5QffEcEtSH1DwzSP3FPPkHxNAS4LX9CqgucphTisH978FLHE34YNEx7FcbBfQLQUU8m3NUC4VqsRa"; + pub const BITCOIN_MAINNET_ADDRESS: &str = "bc1qe4epnfklcaa0mun26yz5g8k24em5u9f92hy325"; + pub const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b"; + + impl Config { + pub fn default( + is_testnet: bool, + data_dir: Option, + debug: bool, + json: bool, + ) -> Self { + let data_dir = data::data_dir_from(data_dir, is_testnet).unwrap(); + + let seed = Seed::from_file_or_generate(data_dir.as_path()).unwrap(); + + let env_config = env_config_from(is_testnet); + Self { + tor_socks5_port: 9050, + namespace: XmrBtcNamespace::from_is_testnet(is_testnet), + server_address: None, + env_config, + seed: Some(seed), + debug, + json, + is_testnet, + data_dir, + } + } + } + + impl Request { + pub fn buy_xmr(is_testnet: bool) -> Request { + let seller = Multiaddr::from_str(MULTI_ADDRESS).unwrap(); + let bitcoin_change_address = { + if is_testnet { + bitcoin::Address::from_str(BITCOIN_TESTNET_ADDRESS).unwrap() + } else { + bitcoin::Address::from_str(BITCOIN_MAINNET_ADDRESS).unwrap() + } + }; + + let monero_receive_address = { + if is_testnet { + monero::Address::from_str(MONERO_STAGENET_ADDRESS).unwrap() + } else { + monero::Address::from_str(MONERO_MAINNET_ADDRESS).unwrap() + } + }; + + Request::new(Method::BuyXmr { + seller, + bitcoin_change_address, + monero_receive_address, + swap_id: Uuid::new_v4(), + }) + } + + pub fn resume() -> Request { + Request::new(Method::Resume { + swap_id: Uuid::from_str(SWAP_ID).unwrap(), + }) + } + + pub fn cancel() -> Request { + Request::new(Method::CancelAndRefund { + swap_id: Uuid::from_str(SWAP_ID).unwrap(), + }) + } + + pub fn refund() -> Request { + Request::new(Method::CancelAndRefund { + swap_id: Uuid::from_str(SWAP_ID).unwrap(), + }) + } + } +} diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs new file mode 100644 index 00000000..02bf27e1 --- /dev/null +++ b/swap/src/api/request.rs @@ -0,0 +1,930 @@ +use crate::api::Context; +use crate::bitcoin::{Amount, ExpiredTimelocks, TxLock}; +use crate::cli::{list_sellers, EventLoop, SellerStatus}; +use crate::libp2p_ext::MultiAddrExt; +use crate::network::quote::{BidQuote, ZeroQuoteReceived}; +use crate::network::swarm; +use crate::protocol::bob::{BobState, Swap}; +use crate::protocol::{bob, State}; +use crate::{bitcoin, cli, monero, rpc}; +use anyhow::{bail, Context as AnyContext, Result}; +use libp2p::core::Multiaddr; +use qrcode::render::unicode; +use qrcode::QrCode; +use serde_json::json; +use std::cmp::min; +use std::convert::TryInto; +use std::future::Future; +use std::net::SocketAddr; +use std::sync::Arc; +use std::time::Duration; +use tracing::{debug_span, field, Instrument, Span}; +use uuid::Uuid; + +#[derive(PartialEq, Debug)] +pub struct Request { + pub cmd: Method, + pub log_reference: Option, +} + +#[derive(Debug, PartialEq)] +pub enum Method { + BuyXmr { + seller: Multiaddr, + bitcoin_change_address: bitcoin::Address, + monero_receive_address: monero::Address, + swap_id: Uuid, + }, + Resume { + swap_id: Uuid, + }, + CancelAndRefund { + swap_id: Uuid, + }, + MoneroRecovery { + swap_id: Uuid, + }, + History, + Config, + WithdrawBtc { + amount: Option, + address: bitcoin::Address, + }, + Balance { + force_refresh: bool, + }, + ListSellers { + rendezvous_point: Multiaddr, + }, + ExportBitcoinWallet, + SuspendCurrentSwap, + StartDaemon { + server_address: Option, + }, + GetCurrentSwap, + GetSwapInfo { + swap_id: Uuid, + }, + GetRawStates, +} + +impl Method { + fn get_tracing_span(&self, log_reference_id: Option) -> Span { + let span = match self { + Method::Balance { .. } => { + debug_span!( + "method", + method_name = "Balance", + log_reference_id = field::Empty + ) + } + Method::BuyXmr { swap_id, .. } => { + debug_span!("method", method_name="BuyXmr", swap_id=%swap_id, log_reference_id=field::Empty) + } + Method::CancelAndRefund { swap_id } => { + debug_span!("method", method_name="CancelAndRefund", swap_id=%swap_id, log_reference_id=field::Empty) + } + Method::Resume { swap_id } => { + debug_span!("method", method_name="Resume", swap_id=%swap_id, log_reference_id=field::Empty) + } + Method::Config => { + debug_span!( + "method", + method_name = "Config", + log_reference_id = field::Empty + ) + } + Method::ExportBitcoinWallet => { + debug_span!( + "method", + method_name = "ExportBitcoinWallet", + log_reference_id = field::Empty + ) + } + Method::GetCurrentSwap => { + debug_span!( + "method", + method_name = "GetCurrentSwap", + log_reference_id = field::Empty + ) + } + Method::GetSwapInfo { .. } => { + debug_span!( + "method", + method_name = "GetSwapInfo", + log_reference_id = field::Empty + ) + } + Method::History => { + debug_span!( + "method", + method_name = "History", + log_reference_id = field::Empty + ) + } + Method::ListSellers { .. } => { + debug_span!( + "method", + method_name = "ListSellers", + log_reference_id = field::Empty + ) + } + Method::MoneroRecovery { .. } => { + debug_span!( + "method", + method_name = "MoneroRecovery", + log_reference_id = field::Empty + ) + } + Method::GetRawStates => debug_span!( + "method", + method_name = "RawHistory", + log_reference_id = field::Empty + ), + Method::StartDaemon { .. } => { + debug_span!( + "method", + method_name = "StartDaemon", + log_reference_id = field::Empty + ) + } + Method::SuspendCurrentSwap => { + debug_span!( + "method", + method_name = "SuspendCurrentSwap", + log_reference_id = field::Empty + ) + } + Method::WithdrawBtc { .. } => { + debug_span!( + "method", + method_name = "WithdrawBtc", + log_reference_id = field::Empty + ) + } + }; + if let Some(log_reference_id) = log_reference_id { + span.record("log_reference_id", log_reference_id.as_str()); + } + span + } +} + +impl Request { + pub fn new(cmd: Method) -> Request { + Request { + cmd, + log_reference: None, + } + } + + pub fn with_id(cmd: Method, id: Option) -> Request { + Request { + cmd, + log_reference: id, + } + } + + async fn handle_cmd(self, context: Arc) -> Result { + match self.cmd { + Method::SuspendCurrentSwap => { + let swap_id = context.swap_lock.get_current_swap_id().await; + + if let Some(id_value) = swap_id { + context.swap_lock.send_suspend_signal().await?; + + Ok(json!({ "swapId": id_value })) + } else { + bail!("No swap is currently running") + } + } + Method::GetSwapInfo { swap_id } => { + let bitcoin_wallet = context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?; + + let state = context.db.get_state(swap_id).await?; + let is_completed = state.swap_finished(); + + let peerId = context + .db + .get_peer_id(swap_id) + .await + .with_context(|| "Could not get PeerID")?; + + let addresses = context + .db + .get_addresses(peerId) + .await + .with_context(|| "Could not get addressess")?; + + let start_date = context.db.get_swap_start_date(swap_id).await?; + + let swap_state: BobState = state.try_into()?; + let state_name = format!("{}", swap_state); + + let ( + xmr_amount, + btc_amount, + tx_lock_id, + tx_cancel_fee, + tx_refund_fee, + tx_lock_fee, + btc_refund_address, + cancel_timelock, + punish_timelock, + ) = context + .db + .get_states(swap_id) + .await? + .iter() + .find_map(|state| { + if let State::Bob(BobState::SwapSetupCompleted(state2)) = state { + let xmr_amount = state2.xmr; + let btc_amount = state2.tx_lock.lock_amount().to_sat(); + let tx_cancel_fee = state2.tx_cancel_fee.to_sat(); + let tx_refund_fee = state2.tx_refund_fee.to_sat(); + let tx_lock_id = state2.tx_lock.txid(); + let btc_refund_address = state2.refund_address.to_string(); + + if let Ok(tx_lock_fee) = state2.tx_lock.fee() { + let tx_lock_fee = tx_lock_fee.to_sat(); + + Some(( + xmr_amount, + btc_amount, + tx_lock_id, + tx_cancel_fee, + tx_refund_fee, + tx_lock_fee, + btc_refund_address, + state2.cancel_timelock, + state2.punish_timelock, + )) + } else { + None + } + } else { + None + } + }) + .with_context(|| "Did not find SwapSetupCompleted state for swap")?; + + let timelock = match swap_state { + BobState::Started { .. } + | BobState::SafelyAborted + | BobState::SwapSetupCompleted(_) => None, + BobState::BtcLocked { state3: state, .. } + | BobState::XmrLockProofReceived { state, .. } => { + Some(state.expired_timelock(bitcoin_wallet).await) + } + BobState::XmrLocked(state) | BobState::EncSigSent(state) => { + Some(state.expired_timelock(bitcoin_wallet).await) + } + BobState::CancelTimelockExpired(state) | BobState::BtcCancelled(state) => { + Some(state.expired_timelock(bitcoin_wallet).await) + } + BobState::BtcPunished { .. } => Some(Ok(ExpiredTimelocks::Punish)), + BobState::BtcRefunded(_) + | BobState::BtcRedeemed(_) + | BobState::XmrRedeemed { .. } => None, + }; + + Ok(json!({ + "swapId": swap_id, + "seller": { + "peerId": peerId.to_string(), + "addresses": addresses + }, + "completed": is_completed, + "startDate": start_date, + "stateName": state_name, + "xmrAmount": xmr_amount, + "btcAmount": btc_amount, + "txLockId": tx_lock_id, + "txCancelFee": tx_cancel_fee, + "txRefundFee": tx_refund_fee, + "txLockFee": tx_lock_fee, + "btcRefundAddress": btc_refund_address.to_string(), + "cancelTimelock": cancel_timelock, + "punishTimelock": punish_timelock, + // If the timelock is None, it means that the swap is in a state where the timelock is not accessible to us. + // If that is the case, we return null. Otherwise, we return the timelock. + "timelock": timelock.map(|tl| tl.map(|tl| json!(tl)).unwrap_or(json!(null))).unwrap_or(json!(null)), + })) + } + Method::BuyXmr { + seller, + bitcoin_change_address, + monero_receive_address, + swap_id, + } => { + let bitcoin_wallet = Arc::clone( + context + .bitcoin_wallet + .as_ref() + .expect("Could not find Bitcoin wallet"), + ); + let monero_wallet = Arc::clone( + context + .monero_wallet + .as_ref() + .context("Could not get Monero wallet")?, + ); + let env_config = context.config.env_config; + let seed = context.config.seed.clone().context("Could not get seed")?; + + let seller_peer_id = seller + .extract_peer_id() + .context("Seller address must contain peer ID")?; + context + .db + .insert_address(seller_peer_id, seller.clone()) + .await?; + + let behaviour = cli::Behaviour::new( + seller_peer_id, + env_config, + bitcoin_wallet.clone(), + (seed.derive_libp2p_identity(), context.config.namespace), + ); + let mut swarm = swarm::cli( + seed.derive_libp2p_identity(), + context.config.tor_socks5_port, + behaviour, + ) + .await?; + + swarm.behaviour_mut().add_address(seller_peer_id, seller); + + context + .db + .insert_monero_address(swap_id, monero_receive_address) + .await?; + + tracing::debug!(peer_id = %swarm.local_peer_id(), "Network layer initialized"); + + context.swap_lock.acquire_swap_lock(swap_id).await?; + + let initialize_swap = tokio::select! { + biased; + _ = context.swap_lock.listen_for_swap_force_suspension() => { + tracing::debug!("Shutdown signal received, exiting"); + context.swap_lock.release_swap_lock().await.expect("Shutdown signal received but failed to release swap lock. The swap process has been terminated but the swap lock is still active."); + bail!("Shutdown signal received"); + }, + result = async { + let (event_loop, mut event_loop_handle) = + EventLoop::new(swap_id, swarm, seller_peer_id)?; + let event_loop = tokio::spawn(event_loop.run().in_current_span()); + + let bid_quote = event_loop_handle.request_quote().await?; + + Ok::<_, anyhow::Error>((event_loop, event_loop_handle, bid_quote)) + } => { + result + }, + }; + + let (event_loop, event_loop_handle, bid_quote) = match initialize_swap { + Ok(result) => result, + Err(error) => { + tracing::error!(%swap_id, "Swap initialization failed: {:#}", error); + context + .swap_lock + .release_swap_lock() + .await + .expect("Could not release swap lock"); + bail!(error); + } + }; + + context.tasks.clone().spawn(async move { + tokio::select! { + biased; + _ = context.swap_lock.listen_for_swap_force_suspension() => { + tracing::debug!("Shutdown signal received, exiting"); + context.swap_lock.release_swap_lock().await.expect("Shutdown signal received but failed to release swap lock. The swap process has been terminated but the swap lock is still active."); + bail!("Shutdown signal received"); + }, + event_loop_result = event_loop => { + match event_loop_result { + Ok(_) => { + tracing::debug!(%swap_id, "EventLoop completed") + } + Err(error) => { + tracing::error!(%swap_id, "EventLoop failed: {:#}", error) + } + } + }, + swap_result = async { + let max_givable = || bitcoin_wallet.max_giveable(TxLock::script_size()); + let estimate_fee = |amount| bitcoin_wallet.estimate_fee(TxLock::weight(), amount); + + let determine_amount = determine_btc_to_swap( + context.config.json, + bid_quote, + bitcoin_wallet.new_address(), + || bitcoin_wallet.balance(), + max_givable, + || bitcoin_wallet.sync(), + estimate_fee, + ); + + let (amount, fees) = match determine_amount.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"); + + context.db.insert_peer_id(swap_id, seller_peer_id).await?; + + let swap = Swap::new( + Arc::clone(&context.db), + swap_id, + Arc::clone(&bitcoin_wallet), + monero_wallet, + env_config, + event_loop_handle, + monero_receive_address, + bitcoin_change_address, + amount, + ); + + bob::run(swap).await + } => { + match swap_result { + Ok(state) => { + tracing::debug!(%swap_id, state=%state, "Swap completed") + } + Err(error) => { + tracing::error!(%swap_id, "Failed to complete swap: {:#}", error) + } + } + }, + }; + tracing::debug!(%swap_id, "Swap completed"); + + context + .swap_lock + .release_swap_lock() + .await + .expect("Could not release swap lock"); + Ok::<_, anyhow::Error>(()) + }.in_current_span()).await; + + Ok(json!({ + "swapId": swap_id.to_string(), + "quote": bid_quote, + })) + } + Method::Resume { swap_id } => { + context.swap_lock.acquire_swap_lock(swap_id).await?; + + let seller_peer_id = context.db.get_peer_id(swap_id).await?; + let seller_addresses = context.db.get_addresses(seller_peer_id).await?; + + let seed = context + .config + .seed + .as_ref() + .context("Could not get seed")? + .derive_libp2p_identity(); + + let behaviour = cli::Behaviour::new( + seller_peer_id, + context.config.env_config, + Arc::clone( + context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?, + ), + (seed.clone(), context.config.namespace), + ); + let mut swarm = + swarm::cli(seed.clone(), context.config.tor_socks5_port, behaviour).await?; + let our_peer_id = swarm.local_peer_id(); + + tracing::debug!(peer_id = %our_peer_id, "Network layer initialized"); + + for seller_address in seller_addresses { + swarm + .behaviour_mut() + .add_address(seller_peer_id, seller_address); + } + + let (event_loop, event_loop_handle) = + EventLoop::new(swap_id, swarm, seller_peer_id)?; + let monero_receive_address = context.db.get_monero_address(swap_id).await?; + let swap = Swap::from_db( + Arc::clone(&context.db), + swap_id, + Arc::clone( + context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?, + ), + Arc::clone( + context + .monero_wallet + .as_ref() + .context("Could not get Monero wallet")?, + ), + context.config.env_config, + event_loop_handle, + monero_receive_address, + ) + .await?; + + context.tasks.clone().spawn( + async move { + let handle = tokio::spawn(event_loop.run().in_current_span()); + tokio::select! { + biased; + _ = context.swap_lock.listen_for_swap_force_suspension() => { + tracing::debug!("Shutdown signal received, exiting"); + context.swap_lock.release_swap_lock().await.expect("Shutdown signal received but failed to release swap lock. The swap process has been terminated but the swap lock is still active."); + bail!("Shutdown signal received"); + }, + + event_loop_result = handle => { + match event_loop_result { + Ok(_) => { + tracing::debug!(%swap_id, "EventLoop completed during swap resume") + } + Err(error) => { + tracing::error!(%swap_id, "EventLoop failed during swap resume: {:#}", error) + } + } + }, + swap_result = bob::run(swap) => { + match swap_result { + Ok(state) => { + tracing::debug!(%swap_id, state=%state, "Swap completed after resuming") + } + Err(error) => { + tracing::error!(%swap_id, "Failed to resume swap: {:#}", error) + } + } + + } + } + context + .swap_lock + .release_swap_lock() + .await + .expect("Could not release swap lock"); + Ok::<(), anyhow::Error>(()) + } + .in_current_span(), + ).await; + Ok(json!({ + "result": "ok", + })) + } + Method::CancelAndRefund { swap_id } => { + let bitcoin_wallet = context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?; + + context.swap_lock.acquire_swap_lock(swap_id).await?; + + let state = cli::cancel_and_refund( + swap_id, + Arc::clone(bitcoin_wallet), + Arc::clone(&context.db), + ) + .await; + + context + .swap_lock + .release_swap_lock() + .await + .expect("Could not release swap lock"); + + state.map(|state| { + json!({ + "result": state, + }) + }) + } + Method::History => { + let swaps = context.db.all().await?; + let mut vec: Vec<(Uuid, String)> = Vec::new(); + for (swap_id, state) in swaps { + let state: BobState = state.try_into()?; + vec.push((swap_id, state.to_string())); + } + + Ok(json!({ "swaps": vec })) + } + Method::GetRawStates => { + let raw_history = context.db.raw_all().await?; + + Ok(json!({ "raw_states": raw_history })) + } + Method::Config => { + let data_dir_display = context.config.data_dir.display(); + 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"); + tracing::info!(path=%format!("{}/seed.pem", data_dir_display), "Seed file location"); + tracing::info!(path=%format!("{}/monero", data_dir_display), "Monero-wallet-rpc directory"); + tracing::info!(path=%format!("{}/wallet", data_dir_display), "Internal bitcoin wallet directory"); + + Ok(json!({ + "log_files": format!("{}/logs", data_dir_display), + "sqlite": format!("{}/sqlite", data_dir_display), + "seed": format!("{}/seed.pem", data_dir_display), + "monero-wallet-rpc": format!("{}/monero", data_dir_display), + "bitcoin_wallet": format!("{}/wallet", data_dir_display), + })) + } + Method::WithdrawBtc { address, amount } => { + let bitcoin_wallet = context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?; + + let amount = match amount { + Some(amount) => amount, + None => { + bitcoin_wallet + .max_giveable(address.script_pubkey().len()) + .await? + } + }; + let psbt = bitcoin_wallet + .send_to_address(address, amount, None) + .await?; + let signed_tx = bitcoin_wallet.sign_and_finalize(psbt).await?; + + bitcoin_wallet + .broadcast(signed_tx.clone(), "withdraw") + .await?; + + Ok(json!({ + "signed_tx": signed_tx, + "amount": amount.to_sat(), + "txid": signed_tx.txid(), + })) + } + Method::StartDaemon { server_address } => { + // Default to 127.0.0.1:1234 + let server_address = server_address.unwrap_or("127.0.0.1:1234".parse()?); + + let (addr, server_handle) = + rpc::run_server(server_address, Arc::clone(&context)).await?; + + tracing::info!(%addr, "Started RPC server"); + + server_handle.stopped().await; + + tracing::info!("Stopped RPC server"); + + Ok(json!({})) + } + Method::Balance { force_refresh } => { + let bitcoin_wallet = context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?; + + if force_refresh { + bitcoin_wallet.sync().await?; + } + + let bitcoin_balance = bitcoin_wallet.balance().await?; + + if force_refresh { + tracing::info!( + balance = %bitcoin_balance, + "Checked Bitcoin balance", + ); + } else { + tracing::debug!( + balance = %bitcoin_balance, + "Current Bitcoin balance as of last sync", + ); + } + + Ok(json!({ + "balance": bitcoin_balance.to_sat() + })) + } + Method::ListSellers { rendezvous_point } => { + let rendezvous_node_peer_id = rendezvous_point + .extract_peer_id() + .context("Rendezvous node address must contain peer ID")?; + + let identity = context + .config + .seed + .as_ref() + .context("Cannot extract seed")? + .derive_libp2p_identity(); + + let sellers = list_sellers( + rendezvous_node_peer_id, + rendezvous_point, + context.config.namespace, + context.config.tor_socks5_port, + identity, + ) + .await?; + + for seller in &sellers { + match seller.status { + SellerStatus::Online(quote) => { + tracing::info!( + price = %quote.price.to_string(), + min_quantity = %quote.min_quantity.to_string(), + max_quantity = %quote.max_quantity.to_string(), + status = "Online", + address = %seller.multiaddr.to_string(), + "Fetched peer status" + ); + } + SellerStatus::Unreachable => { + tracing::info!( + status = "Unreachable", + address = %seller.multiaddr.to_string(), + "Fetched peer status" + ); + } + } + } + + Ok(json!({ "sellers": sellers })) + } + Method::ExportBitcoinWallet => { + let bitcoin_wallet = context + .bitcoin_wallet + .as_ref() + .context("Could not get Bitcoin wallet")?; + + let wallet_export = bitcoin_wallet.wallet_export("cli").await?; + tracing::info!(descriptor=%wallet_export.to_string(), "Exported bitcoin wallet"); + Ok(json!({ + "descriptor": wallet_export.to_string(), + })) + } + Method::MoneroRecovery { swap_id } => { + let swap_state: BobState = context.db.get_state(swap_id).await?.try_into()?; + + if let BobState::BtcRedeemed(state5) = swap_state { + let (spend_key, view_key) = state5.xmr_keys(); + let restore_height = state5.monero_wallet_restore_blockheight.height; + + let address = monero::Address::standard( + context.config.env_config.monero_network, + monero::PublicKey::from_private_key(&spend_key), + monero::PublicKey::from(view_key.public()), + ); + + tracing::info!(restore_height=%restore_height, address=%address, spend_key=%spend_key, view_key=%view_key, "Monero recovery information"); + + Ok(json!({ + "address": address, + "spend_key": spend_key.to_string(), + "view_key": view_key.to_string(), + "restore_height": state5.monero_wallet_restore_blockheight.height, + })) + } else { + bail!( + "Cannot print monero recovery information in state {}, only possible for BtcRedeemed", + swap_state + ) + } + } + Method::GetCurrentSwap => Ok(json!({ + "swap_id": context.swap_lock.get_current_swap_id().await + })), + } + } + + pub async fn call(self, context: Arc) -> Result { + let method_span = self.cmd.get_tracing_span(self.log_reference.clone()); + + self.handle_cmd(context) + .instrument(method_span.clone()) + .await + .map_err(|err| { + method_span.in_scope(|| { + tracing::debug!(err = format!("{:?}", err), "API call resulted in an error"); + }); + err + }) + } +} + +fn qr_code(value: &impl ToString) -> Result { + let code = QrCode::new(value.to_string())?; + let qr_code = code + .render::() + .dark_color(unicode::Dense1x2::Light) + .light_color(unicode::Dense1x2::Dark) + .build(); + Ok(qr_code) +} + +pub async fn determine_btc_to_swap( + json: bool, + bid_quote: BidQuote, + get_new_address: impl Future>, + balance: FB, + max_giveable_fn: FMG, + sync: FS, + estimate_fee: FFE, +) -> Result<(Amount, Amount)> +where + TB: Future>, + FB: Fn() -> TB, + TMG: Future>, + FMG: Fn() -> TMG, + TS: Future>, + FS: Fn() -> TS, + FFE: Fn(Amount) -> TFE, + TFE: Future>, +{ + if bid_quote.max_quantity == Amount::ZERO { + bail!(ZeroQuoteReceived) + } + + tracing::info!( + price = %bid_quote.price, + minimum_amount = %bid_quote.min_quantity, + maximum_amount = %bid_quote.max_quantity, + "Received quote", + ); + + sync().await?; + let mut max_giveable = max_giveable_fn().await?; + + if max_giveable == Amount::ZERO || max_giveable < bid_quote.min_quantity { + let deposit_address = get_new_address.await?; + let minimum_amount = bid_quote.min_quantity; + let maximum_amount = bid_quote.max_quantity; + + if !json { + eprintln!("{}", qr_code(&deposit_address)?); + } + + loop { + let min_outstanding = bid_quote.min_quantity - max_giveable; + let min_fee = estimate_fee(min_outstanding).await?; + let min_deposit = min_outstanding + min_fee; + + tracing::info!( + "Deposit at least {} to cover the min quantity with fee!", + min_deposit + ); + tracing::info!( + %deposit_address, + %min_deposit, + %max_giveable, + %minimum_amount, + %maximum_amount, + "Waiting for Bitcoin deposit", + ); + + max_giveable = loop { + sync().await?; + let new_max_givable = max_giveable_fn().await?; + + if new_max_givable > max_giveable { + break new_max_givable; + } + + tokio::time::sleep(Duration::from_secs(1)).await; + }; + + let new_balance = balance().await?; + tracing::info!(%new_balance, %max_giveable, "Received Bitcoin"); + + if max_giveable < bid_quote.min_quantity { + tracing::info!("Deposited amount is less than `min_quantity`"); + continue; + } + + break; + } + }; + + let balance = balance().await?; + let fees = balance - max_giveable; + let max_accepted = bid_quote.max_quantity; + let btc_swap_amount = min(max_giveable, max_accepted); + + Ok((btc_swap_amount, fees)) +} diff --git a/swap/src/bin/swap.rs b/swap/src/bin/swap.rs index 292a4586..06be7b40 100644 --- a/swap/src/bin/swap.rs +++ b/swap/src/bin/swap.rs @@ -12,43 +12,15 @@ #![forbid(unsafe_code)] #![allow(non_snake_case)] -use anyhow::{bail, Context, Result}; -use comfy_table::Table; -use qrcode::render::unicode; -use qrcode::QrCode; -use std::cmp::min; -use std::convert::TryInto; +use anyhow::Result; use std::env; -use std::future::Future; -use std::path::PathBuf; -use std::sync::Arc; -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::cli::command::{parse_args_and_apply_defaults, ParseResult}; use swap::common::check_latest_version; -use swap::database::open_db; -use swap::env::Config; -use swap::libp2p_ext::MultiAddrExt; -use swap::network::quote::{BidQuote, ZeroQuoteReceived}; -use swap::network::swarm; -use swap::protocol::bob; -use swap::protocol::bob::{BobState, Swap}; -use swap::seed::Seed; -use swap::{bitcoin, cli, monero}; -use url::Url; -use uuid::Uuid; #[tokio::main] async fn main() -> Result<()> { - let Arguments { - env_config, - data_dir, - debug, - json, - cmd, - } = match parse_args_and_apply_defaults(env::args_os())? { - ParseResult::Arguments(args) => *args, + let (context, request) = match parse_args_and_apply_defaults(env::args_os()).await? { + ParseResult::Context(context, request) => (context, request), ParseResult::PrintAndExitZero { message } => { println!("{}", message); std::process::exit(0); @@ -58,601 +30,19 @@ async fn main() -> Result<()> { if let Err(e) = check_latest_version(env!("CARGO_PKG_VERSION")).await { eprintln!("{}", e); } - - match cmd { - Command::BuyXmr { - seller, - bitcoin_electrum_rpc_url, - bitcoin_target_block, - bitcoin_change_address, - monero_receive_address, - monero_daemon_address, - tor_socks5_port, - namespace, - } => { - let swap_id = Uuid::new_v4(); - - cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - - 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")?; - - let bitcoin_wallet = init_bitcoin_wallet( - bitcoin_electrum_rpc_url, - &seed, - data_dir.clone(), - env_config, - bitcoin_target_block, - ) - .await?; - let (monero_wallet, _process) = - init_monero_wallet(data_dir, monero_daemon_address, env_config).await?; - let bitcoin_wallet = Arc::new(bitcoin_wallet); - let seller_peer_id = seller - .extract_peer_id() - .context("Seller address must contain peer ID")?; - db.insert_address(seller_peer_id, seller.clone()).await?; - - let behaviour = cli::Behaviour::new( - seller_peer_id, - env_config, - bitcoin_wallet.clone(), - (seed.derive_libp2p_identity(), namespace), - ); - let mut swarm = - swarm::cli(seed.derive_libp2p_identity(), tor_socks5_port, behaviour).await?; - swarm.behaviour_mut().add_address(seller_peer_id, seller); - - 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)?; - let event_loop = tokio::spawn(event_loop.run()); - - let max_givable = || bitcoin_wallet.max_giveable(TxLock::script_size()); - let estimate_fee = |amount| bitcoin_wallet.estimate_fee(TxLock::weight(), amount); - - let (amount, fees) = match determine_btc_to_swap( - json, - event_loop_handle.request_quote(), - bitcoin_wallet.new_address(), - || bitcoin_wallet.balance(), - max_givable, - || bitcoin_wallet.sync(), - estimate_fee, - ) - .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"); - - db.insert_peer_id(swap_id, seller_peer_id).await?; - db.insert_monero_address(swap_id, monero_receive_address) - .await?; - - let swap = Swap::new( - db, - swap_id, - bitcoin_wallet, - Arc::new(monero_wallet), - env_config, - event_loop_handle, - monero_receive_address, - bitcoin_change_address, - amount, - ); - - tokio::select! { - result = event_loop => { - result - .context("EventLoop panicked")?; - }, - result = bob::run(swap) => { - result.context("Failed to complete swap")?; - } - } - } - Command::History => { - cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - - let db = open_db(data_dir.join("sqlite")).await?; - let swaps = db.all().await?; - - if json { - for (swap_id, state) in swaps { - let state: BobState = state.try_into()?; - tracing::info!(swap_id=%swap_id.to_string(), state=%state.to_string(), "Read swap state from database"); - } - } else { - let mut table = Table::new(); - - table.set_header(vec!["SWAP ID", "STATE"]); - - for (swap_id, state) in swaps { - let state: BobState = state.try_into()?; - table.add_row(vec![swap_id.to_string(), state.to_string()]); - } - - println!("{}", table); - } - } - Command::Config => { - cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - - 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"); - tracing::info!(path=%format!("{}/seed.pem", data_dir.display()), "Seed file location"); - tracing::info!(path=%format!("{}/monero", data_dir.display()), "Monero-wallet-rpc directory"); - tracing::info!(path=%format!("{}/wallet", data_dir.display()), "Internal bitcoin wallet directory"); - } - Command::WithdrawBtc { - bitcoin_electrum_rpc_url, - bitcoin_target_block, - amount, - address, - } => { - cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - - let seed = Seed::from_file_or_generate(data_dir.as_path()) - .context("Failed to read in seed file")?; - let bitcoin_wallet = init_bitcoin_wallet( - bitcoin_electrum_rpc_url, - &seed, - data_dir.clone(), - env_config, - bitcoin_target_block, - ) - .await?; - - let amount = match amount { - Some(amount) => amount, - None => { - bitcoin_wallet - .max_giveable(address.script_pubkey().len()) - .await? - } - }; - - let psbt = bitcoin_wallet - .send_to_address(address, amount, None) - .await?; - let signed_tx = bitcoin_wallet.sign_and_finalize(psbt).await?; - - bitcoin_wallet.broadcast(signed_tx, "withdraw").await?; - } - - Command::Balance { - bitcoin_electrum_rpc_url, - bitcoin_target_block, - } => { - cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - - let seed = Seed::from_file_or_generate(data_dir.as_path()) - .context("Failed to read in seed file")?; - let bitcoin_wallet = init_bitcoin_wallet( - bitcoin_electrum_rpc_url, - &seed, - data_dir.clone(), - env_config, - bitcoin_target_block, - ) - .await?; - - let bitcoin_balance = bitcoin_wallet.balance().await?; - tracing::info!( - balance = %bitcoin_balance, - "Checked Bitcoin balance", - ); - } - Command::Resume { - swap_id, - bitcoin_electrum_rpc_url, - bitcoin_target_block, - monero_daemon_address, - tor_socks5_port, - namespace, - } => { - cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - - 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")?; - - let bitcoin_wallet = init_bitcoin_wallet( - bitcoin_electrum_rpc_url, - &seed, - data_dir.clone(), - env_config, - bitcoin_target_block, - ) - .await?; - let (monero_wallet, _process) = - init_monero_wallet(data_dir, monero_daemon_address, env_config).await?; - let bitcoin_wallet = Arc::new(bitcoin_wallet); - - let seller_peer_id = db.get_peer_id(swap_id).await?; - let seller_addresses = db.get_addresses(seller_peer_id).await?; - - let behaviour = cli::Behaviour::new( - seller_peer_id, - env_config, - bitcoin_wallet.clone(), - (seed.derive_libp2p_identity(), namespace), - ); - let mut swarm = - swarm::cli(seed.derive_libp2p_identity(), tor_socks5_port, behaviour).await?; - let our_peer_id = swarm.local_peer_id(); - tracing::debug!(peer_id = %our_peer_id, "Network layer initialized"); - - for seller_address in seller_addresses { - swarm - .behaviour_mut() - .add_address(seller_peer_id, seller_address); - } - - 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?; - let swap = Swap::from_db( - db, - swap_id, - bitcoin_wallet, - Arc::new(monero_wallet), - env_config, - event_loop_handle, - monero_receive_address, - ) - .await?; - - tokio::select! { - event_loop_result = handle => { - event_loop_result?; - }, - swap_result = bob::run(swap) => { - swap_result?; - } - } - } - Command::CancelAndRefund { - swap_id, - bitcoin_electrum_rpc_url, - bitcoin_target_block, - } => { - cli::tracing::init(debug, json, data_dir.join("logs"), Some(swap_id))?; - - 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")?; - - let bitcoin_wallet = init_bitcoin_wallet( - bitcoin_electrum_rpc_url, - &seed, - data_dir, - env_config, - bitcoin_target_block, - ) - .await?; - - cli::cancel_and_refund(swap_id, Arc::new(bitcoin_wallet), db).await?; - } - Command::ListSellers { - rendezvous_point, - namespace, - tor_socks5_port, - } => { - let rendezvous_node_peer_id = rendezvous_point - .extract_peer_id() - .context("Rendezvous node address must contain peer ID")?; - - cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - - let seed = Seed::from_file_or_generate(data_dir.as_path()) - .context("Failed to read in seed file")?; - let identity = seed.derive_libp2p_identity(); - - let sellers = list_sellers( - rendezvous_node_peer_id, - rendezvous_point, - namespace, - tor_socks5_port, - identity, - ) - .await?; - - if json { - for seller in sellers { - match seller.status { - SellerStatus::Online(quote) => { - tracing::info!( - price = %quote.price.to_string(), - min_quantity = %quote.min_quantity.to_string(), - max_quantity = %quote.max_quantity.to_string(), - status = "Online", - address = %seller.multiaddr.to_string(), - "Fetched peer status" - ); - } - SellerStatus::Unreachable => { - tracing::info!( - status = "Unreachable", - address = %seller.multiaddr.to_string(), - "Fetched peer status" - ); - } - } - } - } else { - let mut table = Table::new(); - - table.set_header(vec![ - "PRICE", - "MIN_QUANTITY", - "MAX_QUANTITY", - "STATUS", - "ADDRESS", - ]); - - for seller in sellers { - let row = match seller.status { - SellerStatus::Online(quote) => { - vec![ - quote.price.to_string(), - quote.min_quantity.to_string(), - quote.max_quantity.to_string(), - "Online".to_owned(), - seller.multiaddr.to_string(), - ] - } - SellerStatus::Unreachable => { - vec![ - "???".to_owned(), - "???".to_owned(), - "???".to_owned(), - "Unreachable".to_owned(), - seller.multiaddr.to_string(), - ] - } - }; - - table.add_row(row); - } - - println!("{}", table); - } - } - Command::ExportBitcoinWallet { - bitcoin_electrum_rpc_url, - bitcoin_target_block, - } => { - cli::tracing::init(debug, json, data_dir.join("logs"), None)?; - - let seed = Seed::from_file_or_generate(data_dir.as_path()) - .context("Failed to read in seed file")?; - let bitcoin_wallet = init_bitcoin_wallet( - bitcoin_electrum_rpc_url, - &seed, - data_dir.clone(), - env_config, - bitcoin_target_block, - ) - .await?; - let wallet_export = bitcoin_wallet.wallet_export("cli").await?; - 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))?; - - let db = open_db(data_dir.join("sqlite")).await?; - - let swap_state: BobState = db.get_state(swap_id).await?.try_into()?; - - match swap_state { - BobState::Started { .. } - | BobState::SwapSetupCompleted(_) - | BobState::BtcLocked { .. } - | BobState::XmrLockProofReceived { .. } - | BobState::XmrLocked(_) - | BobState::EncSigSent(_) - | BobState::CancelTimelockExpired(_) - | BobState::BtcCancelled(_) - | BobState::BtcRefunded(_) - | BobState::BtcPunished { .. } - | BobState::SafelyAborted - | BobState::XmrRedeemed { .. } => { - bail!("Cannot print monero recovery information in state {}, only possible for BtcRedeemed", swap_state) - } - BobState::BtcRedeemed(state5) => { - let (spend_key, view_key) = state5.xmr_keys(); - - let address = monero::Address::standard( - env_config.monero_network, - monero::PublicKey::from_private_key(&spend_key), - monero::PublicKey::from(view_key.public()), - ); - tracing::info!("Wallet address: {}", address.to_string()); - - let view_key = serde_json::to_string(&view_key)?; - println!("View key: {}", view_key); - - println!("Spend key: {}", spend_key); - } - } - } - }; + request.call(context.clone()).await?; + context.tasks.wait_for_tasks().await?; Ok(()) } -async fn init_bitcoin_wallet( - electrum_rpc_url: Url, - seed: &Seed, - data_dir: PathBuf, - env_config: Config, - bitcoin_target_block: usize, -) -> Result { - tracing::debug!("Initializing bitcoin wallet"); - let xprivkey = seed.derive_extended_private_key(env_config.bitcoin_network)?; - - let wallet = bitcoin::Wallet::new( - electrum_rpc_url.clone(), - data_dir, - xprivkey, - env_config, - bitcoin_target_block, - ) - .await - .context("Failed to initialize Bitcoin wallet")?; - - tracing::debug!("Syncing bitcoin wallet"); - wallet.sync().await?; - - Ok(wallet) -} - -async fn init_monero_wallet( - data_dir: PathBuf, - monero_daemon_address: Option, - env_config: Config, -) -> Result<(monero::Wallet, monero::WalletRpcProcess)> { - let network = env_config.monero_network; - - const MONERO_BLOCKCHAIN_MONITORING_WALLET_NAME: &str = "swap-tool-blockchain-monitoring-wallet"; - - let monero_wallet_rpc = monero::WalletRpc::new(data_dir.join("monero")).await?; - - let monero_wallet_rpc_process = monero_wallet_rpc - .run(network, monero_daemon_address) - .await?; - - let monero_wallet = monero::Wallet::open_or_create( - monero_wallet_rpc_process.endpoint(), - MONERO_BLOCKCHAIN_MONITORING_WALLET_NAME.to_string(), - env_config, - ) - .await?; - - Ok((monero_wallet, monero_wallet_rpc_process)) -} - -fn qr_code(value: &impl ToString) -> Result { - let code = QrCode::new(value.to_string())?; - let qr_code = code - .render::() - .dark_color(unicode::Dense1x2::Light) - .light_color(unicode::Dense1x2::Dark) - .build(); - Ok(qr_code) -} - -async fn determine_btc_to_swap( - json: bool, - bid_quote: impl Future>, - get_new_address: impl Future>, - balance: FB, - max_giveable_fn: FMG, - sync: FS, - estimate_fee: FFE, -) -> Result<(bitcoin::Amount, bitcoin::Amount)> -where - TB: Future>, - FB: Fn() -> TB, - TMG: Future>, - FMG: Fn() -> TMG, - TS: Future>, - FS: Fn() -> TS, - FFE: Fn(bitcoin::Amount) -> TFE, - TFE: Future>, -{ - 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, - maximum_amount = %bid_quote.max_quantity, - "Received quote", - ); - - let mut max_giveable = max_giveable_fn().await?; - - if max_giveable == bitcoin::Amount::ZERO || max_giveable < bid_quote.min_quantity { - let deposit_address = get_new_address.await?; - let minimum_amount = bid_quote.min_quantity; - let maximum_amount = bid_quote.max_quantity; - - if !json { - eprintln!("{}", qr_code(&deposit_address)?); - } - - loop { - let min_outstanding = bid_quote.min_quantity - max_giveable; - let min_fee = estimate_fee(min_outstanding).await?; - let min_deposit = min_outstanding + min_fee; - - tracing::info!( - "Deposit at least {} to cover the min quantity with fee!", - min_deposit - ); - tracing::info!( - %deposit_address, - %min_deposit, - %max_giveable, - %minimum_amount, - %maximum_amount, - "Waiting for Bitcoin deposit", - ); - - max_giveable = loop { - sync().await?; - let new_max_givable = max_giveable_fn().await?; - - if new_max_givable > max_giveable { - break new_max_givable; - } - - tokio::time::sleep(Duration::from_secs(1)).await; - }; - - let new_balance = balance().await?; - tracing::info!(%new_balance, %max_giveable, "Received Bitcoin"); - - if max_giveable < bid_quote.min_quantity { - tracing::info!("Deposited amount is less than `min_quantity`"); - continue; - } - - break; - } - }; - - let balance = balance().await?; - let fees = balance - max_giveable; - let max_accepted = bid_quote.max_quantity; - let btc_swap_amount = min(max_giveable, max_accepted); - - Ok((btc_swap_amount, fees)) -} - #[cfg(test)] mod tests { use super::*; - use crate::determine_btc_to_swap; use ::bitcoin::Amount; - use std::sync::Mutex; + use std::sync::{Arc, Mutex}; + use std::time::Duration; + use swap::api::request::determine_btc_to_swap; + use swap::network::quote::BidQuote; use swap::tracing_ext::capture_logs; use tracing::level_filters::LevelFilter; @@ -666,7 +56,7 @@ mod tests { let (amount, fees) = determine_btc_to_swap( true, - async { Ok(quote_with_max(0.01)) }, + quote_with_max(0.01), get_dummy_address(), || async { Ok(Amount::from_btc(0.001)?) }, || async { @@ -685,10 +75,10 @@ mod tests { assert_eq!((amount, fees), (expected_amount, expected_fees)); assert_eq!( writer.captured(), - r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC - INFO swap: Deposit at least 0.00001000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC - INFO swap: Received Bitcoin new_balance=0.00100000 BTC max_giveable=0.00090000 BTC + r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC + INFO swap::api::request: Deposit at least 0.00001 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001 BTC max_giveable=0 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC + INFO swap::api::request: Received Bitcoin new_balance=0.001 BTC max_giveable=0.0009 BTC " ); } @@ -703,7 +93,7 @@ mod tests { let (amount, fees) = determine_btc_to_swap( true, - async { Ok(quote_with_max(0.01)) }, + quote_with_max(0.01), get_dummy_address(), || async { Ok(Amount::from_btc(0.1001)?) }, || async { @@ -722,10 +112,10 @@ mod tests { assert_eq!((amount, fees), (expected_amount, expected_fees)); assert_eq!( writer.captured(), - r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC - INFO swap: Deposit at least 0.00001000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC - INFO swap: Received Bitcoin new_balance=0.10010000 BTC max_giveable=0.10000000 BTC + r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC + INFO swap::api::request: Deposit at least 0.00001 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00001 BTC max_giveable=0 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC + INFO swap::api::request: Received Bitcoin new_balance=0.1001 BTC max_giveable=0.1 BTC " ); } @@ -740,7 +130,7 @@ mod tests { let (amount, fees) = determine_btc_to_swap( true, - async { Ok(quote_with_max(0.01)) }, + quote_with_max(0.01), async { panic!("should not request new address when initial balance is > 0") }, || async { Ok(Amount::from_btc(0.005)?) }, || async { @@ -759,7 +149,7 @@ mod tests { assert_eq!((amount, fees), (expected_amount, expected_fees)); assert_eq!( writer.captured(), - " INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC\n" + " INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC\n" ); } @@ -773,7 +163,7 @@ mod tests { let (amount, fees) = determine_btc_to_swap( true, - async { Ok(quote_with_max(0.01)) }, + quote_with_max(0.01), async { panic!("should not request new address when initial balance is > 0") }, || async { Ok(Amount::from_btc(0.1001)?) }, || async { @@ -792,7 +182,7 @@ mod tests { assert_eq!((amount, fees), (expected_amount, expected_fees)); assert_eq!( writer.captured(), - " INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.00000000 BTC maximum_amount=0.01000000 BTC\n" + " INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0 BTC maximum_amount=0.01 BTC\n" ); } @@ -806,7 +196,7 @@ mod tests { let (amount, fees) = determine_btc_to_swap( true, - async { Ok(quote_with_min(0.01)) }, + quote_with_min(0.01), get_dummy_address(), || async { Ok(Amount::from_btc(0.0101)?) }, || async { @@ -825,10 +215,10 @@ mod tests { assert_eq!((amount, fees), (expected_amount, expected_fees)); assert_eq!( writer.captured(), - r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Deposit at least 0.01001000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.01001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC + r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Deposit at least 0.01001 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.01001 BTC max_giveable=0 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC " ); } @@ -843,7 +233,7 @@ mod tests { let (amount, fees) = determine_btc_to_swap( true, - async { Ok(quote_with_min(0.01)) }, + quote_with_min(0.01), get_dummy_address(), || async { Ok(Amount::from_btc(0.0101)?) }, || async { @@ -862,10 +252,10 @@ mod tests { assert_eq!((amount, fees), (expected_amount, expected_fees)); assert_eq!( writer.captured(), - r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Deposit at least 0.00991000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00991000 BTC max_giveable=0.00010000 BTC minimum_amount=0.01000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC + r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Deposit at least 0.00991 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.00991 BTC max_giveable=0.0001 BTC minimum_amount=0.01 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC " ); } @@ -885,7 +275,7 @@ mod tests { Duration::from_secs(1), determine_btc_to_swap( true, - async { Ok(quote_with_min(0.1)) }, + quote_with_min(0.1), get_dummy_address(), || async { Ok(Amount::from_btc(0.0101)?) }, || async { @@ -902,13 +292,13 @@ mod tests { assert!(matches!(error, tokio::time::error::Elapsed { .. })); assert_eq!( writer.captured(), - r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Deposit at least 0.10001000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Received Bitcoin new_balance=0.01010000 BTC max_giveable=0.01000000 BTC - INFO swap: Deposited amount is less than `min_quantity` - INFO swap: Deposit at least 0.09001000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.09001000 BTC max_giveable=0.01000000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC + r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Deposit at least 0.10001 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001 BTC max_giveable=0 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Received Bitcoin new_balance=0.0101 BTC max_giveable=0.01 BTC + INFO swap::api::request: Deposited amount is less than `min_quantity` + INFO swap::api::request: Deposit at least 0.09001 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.09001 BTC max_giveable=0.01 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC " ); } @@ -933,7 +323,7 @@ mod tests { Duration::from_secs(10), determine_btc_to_swap( true, - async { Ok(quote_with_min(0.1)) }, + quote_with_min(0.1), get_dummy_address(), || async { Ok(Amount::from_btc(0.21)?) }, || async { @@ -951,10 +341,10 @@ mod tests { assert_eq!( writer.captured(), - r" INFO swap: Received quote price=0.00100000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Deposit at least 0.10001000 BTC to cover the min quantity with fee! - INFO swap: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001000 BTC max_giveable=0.00000000 BTC minimum_amount=0.10000000 BTC maximum_amount=184467440737.09551615 BTC - INFO swap: Received Bitcoin new_balance=0.21000000 BTC max_giveable=0.20000000 BTC + r" INFO swap::api::request: Received quote price=0.001 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Deposit at least 0.10001 BTC to cover the min quantity with fee! + INFO swap::api::request: Waiting for Bitcoin deposit deposit_address=1PdfytjS7C8wwd9Lq5o4x9aXA2YRqaCpH6 min_deposit=0.10001 BTC max_giveable=0 BTC minimum_amount=0.1 BTC maximum_amount=184467440737.09551615 BTC + INFO swap::api::request: Received Bitcoin new_balance=0.21 BTC max_giveable=0.2 BTC " ); } @@ -968,7 +358,7 @@ mod tests { let determination_error = determine_btc_to_swap( true, - async { Ok(quote_with_max(0.00)) }, + quote_with_max(0.00), get_dummy_address(), || async { Ok(Amount::from_btc(0.0101)?) }, || async { diff --git a/swap/src/bitcoin.rs b/swap/src/bitcoin.rs index 925f48e6..556d8453 100644 --- a/swap/src/bitcoin.rs +++ b/swap/src/bitcoin.rs @@ -15,7 +15,7 @@ pub use crate::bitcoin::refund::TxRefund; pub use crate::bitcoin::timelocks::{BlockHeight, ExpiredTimelocks}; pub use ::bitcoin::util::amount::Amount; pub use ::bitcoin::util::psbt::PartiallySignedTransaction; -pub use ::bitcoin::{Address, Network, Transaction, Txid}; +pub use ::bitcoin::{Address, AddressType, Network, Transaction, Txid}; pub use ecdsa_fun::adaptor::EncryptedSignature; pub use ecdsa_fun::fun::Scalar; pub use ecdsa_fun::Signature; @@ -244,10 +244,65 @@ pub fn current_epoch( } if tx_lock_status.is_confirmed_with(cancel_timelock) { - return ExpiredTimelocks::Cancel; + return ExpiredTimelocks::Cancel { + blocks_left: tx_cancel_status.blocks_left_until(punish_timelock), + }; } - ExpiredTimelocks::None + ExpiredTimelocks::None { + blocks_left: tx_lock_status.blocks_left_until(cancel_timelock), + } +} + +pub mod bitcoin_address { + use anyhow::{bail, Result}; + use serde::Serialize; + use std::str::FromStr; + + #[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Serialize)] + #[error("Invalid Bitcoin address provided, expected address on network {expected:?} but address provided is on {actual:?}")] + pub struct BitcoinAddressNetworkMismatch { + #[serde(with = "crate::bitcoin::network")] + expected: bitcoin::Network, + #[serde(with = "crate::bitcoin::network")] + actual: bitcoin::Network, + } + + pub fn parse(addr_str: &str) -> Result { + let address = bitcoin::Address::from_str(addr_str)?; + + if address.address_type() != Some(bitcoin::AddressType::P2wpkh) { + anyhow::bail!("Invalid Bitcoin address provided, only bech32 format is supported!") + } + + Ok(address) + } + + pub fn validate( + address: bitcoin::Address, + expected_network: bitcoin::Network, + ) -> Result { + if address.network != expected_network { + bail!(BitcoinAddressNetworkMismatch { + expected: expected_network, + actual: address.network + }); + } + + Ok(address) + } + + pub fn validate_is_testnet( + address: bitcoin::Address, + is_testnet: bool, + ) -> Result { + let expected_network = if is_testnet { + bitcoin::Network::Testnet + } else { + bitcoin::Network::Bitcoin + }; + validate(address, expected_network) + } } /// Bitcoin error codes: https://github.com/bitcoin/bitcoin/blob/97d3500601c1d28642347d014a6de1e38f53ae4e/src/rpc/protocol.h#L23 @@ -324,6 +379,7 @@ mod tests { use crate::env::{GetConfig, Regtest}; use crate::protocol::{alice, bob}; use rand::rngs::OsRng; + use std::matches; use uuid::Uuid; #[test] @@ -338,7 +394,7 @@ mod tests { tx_cancel_status, ); - assert_eq!(expired_timelock, ExpiredTimelocks::None) + assert!(matches!(expired_timelock, ExpiredTimelocks::None { .. })); } #[test] @@ -353,7 +409,7 @@ mod tests { tx_cancel_status, ); - assert_eq!(expired_timelock, ExpiredTimelocks::Cancel) + assert!(matches!(expired_timelock, ExpiredTimelocks::Cancel { .. })); } #[test] diff --git a/swap/src/bitcoin/cancel.rs b/swap/src/bitcoin/cancel.rs index 35b6b197..aec3fe38 100644 --- a/swap/src/bitcoin/cancel.rs +++ b/swap/src/bitcoin/cancel.rs @@ -24,6 +24,12 @@ use std::ops::Add; #[serde(transparent)] pub struct CancelTimelock(u32); +impl From for u32 { + fn from(cancel_timelock: CancelTimelock) -> Self { + cancel_timelock.0 + } +} + impl CancelTimelock { pub const fn new(number_of_blocks: u32) -> Self { Self(number_of_blocks) @@ -64,6 +70,12 @@ impl fmt::Display for CancelTimelock { #[serde(transparent)] pub struct PunishTimelock(u32); +impl From for u32 { + fn from(punish_timelock: PunishTimelock) -> Self { + punish_timelock.0 + } +} + impl PunishTimelock { pub const fn new(number_of_blocks: u32) -> Self { Self(number_of_blocks) diff --git a/swap/src/bitcoin/lock.rs b/swap/src/bitcoin/lock.rs index 42819ad5..f8aa9a39 100644 --- a/swap/src/bitcoin/lock.rs +++ b/swap/src/bitcoin/lock.rs @@ -4,9 +4,10 @@ use crate::bitcoin::{ }; use ::bitcoin::util::psbt::PartiallySignedTransaction; use ::bitcoin::{OutPoint, TxIn, TxOut, Txid}; -use anyhow::{bail, Result}; +use anyhow::{bail, Context, Result}; use bdk::database::BatchDatabase; use bdk::miniscript::Descriptor; +use bdk::psbt::PsbtUtils; use bitcoin::{PackedLockTime, Script, Sequence}; use serde::{Deserialize, Serialize}; @@ -100,6 +101,15 @@ impl TxLock { Amount::from_sat(self.inner.clone().extract_tx().output[self.lock_output_vout()].value) } + pub fn fee(&self) -> Result { + Ok(Amount::from_sat( + self.inner + .clone() + .fee_amount() + .context("The PSBT is missing a TxOut for an input")?, + )) + } + pub fn txid(&self) -> Txid { self.inner.clone().extract_tx().txid() } diff --git a/swap/src/bitcoin/timelocks.rs b/swap/src/bitcoin/timelocks.rs index e8b72ea6..427bef80 100644 --- a/swap/src/bitcoin/timelocks.rs +++ b/swap/src/bitcoin/timelocks.rs @@ -37,9 +37,9 @@ impl Add for BlockHeight { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Serialize, Debug, Clone, Copy, PartialEq, Eq)] pub enum ExpiredTimelocks { - None, - Cancel, + None { blocks_left: u32 }, + Cancel { blocks_left: u32 }, Punish, } diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index 2e5732f8..5d8685f3 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -24,6 +24,7 @@ use std::path::Path; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::sync::{watch, Mutex}; +use tracing::{debug_span, Instrument}; const SLED_TREE_NAME: &str = "default_tree"; @@ -192,7 +193,7 @@ impl Wallet { tokio::time::sleep(Duration::from_secs(5)).await; } - }); + }.instrument(debug_span!("BitcoinWalletSubscription"))); Subscription { receiver, @@ -274,7 +275,7 @@ impl Subscription { pub async fn wait_until_confirmed_with(&self, target: T) -> Result<()> where - u32: PartialOrd, + T: Into, T: Copy, { self.wait_until(|status| status.is_confirmed_with(target)) @@ -933,9 +934,20 @@ impl Confirmed { pub fn meets_target(&self, target: T) -> bool where - u32: PartialOrd, + T: Into, { - self.confirmations() >= target + self.confirmations() >= target.into() + } + + pub fn blocks_left_until(&self, target: T) -> u32 + where + T: Into + Copy, + { + if self.meets_target(target) { + 0 + } else { + target.into() - self.confirmations() + } } } @@ -948,7 +960,7 @@ impl ScriptStatus { /// Check if the script has met the given confirmation target. pub fn is_confirmed_with(&self, target: T) -> bool where - u32: PartialOrd, + T: Into, { match self { ScriptStatus::Confirmed(inner) => inner.meets_target(target), @@ -956,6 +968,17 @@ impl ScriptStatus { } } + // Calculate the number of blocks left until the target is met. + pub fn blocks_left_until(&self, target: T) -> u32 + where + T: Into + Copy, + { + match self { + ScriptStatus::Confirmed(inner) => inner.blocks_left_until(target), + _ => target.into(), + } + } + pub fn has_been_seen(&self) -> bool { matches!(self, ScriptStatus::InMempool | ScriptStatus::Confirmed(_)) } @@ -987,7 +1010,7 @@ mod tests { fn given_depth_0_should_meet_confirmation_target_one() { let script = ScriptStatus::Confirmed(Confirmed { depth: 0 }); - let confirmed = script.is_confirmed_with(1); + let confirmed = script.is_confirmed_with(1_u32); assert!(confirmed) } @@ -996,7 +1019,7 @@ mod tests { fn given_confirmations_1_should_meet_confirmation_target_one() { let script = ScriptStatus::from_confirmations(1); - let confirmed = script.is_confirmed_with(1); + let confirmed = script.is_confirmed_with(1_u32); assert!(confirmed) } @@ -1011,6 +1034,33 @@ mod tests { assert_eq!(confirmed.depth, 0) } + #[test] + fn given_depth_0_should_return_0_blocks_left_until_1() { + let script = ScriptStatus::Confirmed(Confirmed { depth: 0 }); + + let blocks_left = script.blocks_left_until(1_u32); + + assert_eq!(blocks_left, 0) + } + + #[test] + fn given_depth_1_should_return_0_blocks_left_until_1() { + let script = ScriptStatus::Confirmed(Confirmed { depth: 1 }); + + let blocks_left = script.blocks_left_until(1_u32); + + assert_eq!(blocks_left, 0) + } + + #[test] + fn given_depth_0_should_return_1_blocks_left_until_2() { + let script = ScriptStatus::Confirmed(Confirmed { depth: 0 }); + + let blocks_left = script.blocks_left_until(2_u32); + + assert_eq!(blocks_left, 1) + } + #[test] fn given_one_BTC_and_100k_sats_per_vb_fees_should_not_hit_max() { // 400 weight = 100 vbyte diff --git a/swap/src/cli/cancel_and_refund.rs b/swap/src/cli/cancel_and_refund.rs index b42c124c..d542b7ed 100644 --- a/swap/src/cli/cancel_and_refund.rs +++ b/swap/src/cli/cancel_and_refund.rs @@ -10,7 +10,7 @@ use uuid::Uuid; pub async fn cancel_and_refund( swap_id: Uuid, bitcoin_wallet: Arc, - db: Arc, + db: Arc, ) -> Result { if let Err(err) = cancel(swap_id, bitcoin_wallet.clone(), db.clone()).await { tracing::info!(%err, "Could not submit cancel transaction"); @@ -28,7 +28,7 @@ pub async fn cancel_and_refund( pub async fn cancel( swap_id: Uuid, bitcoin_wallet: Arc, - db: Arc, + db: Arc, ) -> Result<(Txid, Subscription, BobState)> { let state = db.get_state(swap_id).await?.try_into()?; @@ -80,7 +80,7 @@ pub async fn cancel( pub async fn refund( swap_id: Uuid, bitcoin_wallet: Arc, - db: Arc, + db: Arc, ) -> Result { let state = db.get_state(swap_id).await?.try_into()?; diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 5c3b2827..affd6a19 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -1,43 +1,39 @@ -use crate::bitcoin::Amount; -use crate::env::GetConfig; -use crate::fs::system_data_dir; -use crate::network::rendezvous::XmrBtcNamespace; -use crate::{env, monero}; -use anyhow::{bail, Context, Result}; -use bitcoin::{Address, AddressType}; +use crate::api::request::{Method, Request}; +use crate::api::Context; +use crate::bitcoin::{bitcoin_address, Amount}; +use crate::monero; +use crate::monero::monero_address; +use anyhow::Result; use libp2p::core::Multiaddr; -use serde::Serialize; use std::ffi::OsString; +use std::net::SocketAddr; use std::path::PathBuf; use std::str::FromStr; +use std::sync::Arc; use structopt::{clap, StructOpt}; use url::Url; use uuid::Uuid; +// See: https://moneroworld.com/ +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"; // See: https://1209k.com/bitcoin-eye/ele.php?chain=tbtc pub const DEFAULT_ELECTRUM_RPC_URL_TESTNET: &str = "ssl://electrum.blockstream.info:60002"; const DEFAULT_BITCOIN_CONFIRMATION_TARGET: usize = 3; -const DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET: usize = 1; +pub const DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET: usize = 1; const DEFAULT_TOR_SOCKS5_PORT: &str = "9050"; -#[derive(Debug, PartialEq, Eq)] -pub struct Arguments { - pub env_config: env::Config, - pub debug: bool, - pub json: bool, - pub data_dir: PathBuf, - pub cmd: Command, -} - /// Represents the result of parsing the command-line parameters. -#[derive(Debug, PartialEq, Eq)] + +#[derive(Debug)] pub enum ParseResult { /// The arguments we were invoked in. - Arguments(Box), + Context(Arc, Box), /// A flag or command was given that does not need further processing other /// than printing the provided message. /// @@ -45,13 +41,13 @@ pub enum ParseResult { PrintAndExitZero { message: String }, } -pub fn parse_args_and_apply_defaults(raw_args: I) -> Result +pub async fn parse_args_and_apply_defaults(raw_args: I) -> Result where I: IntoIterator, T: Into + Clone, { - let args = match RawArguments::clap().get_matches_from_safe(raw_args) { - Ok(matches) => RawArguments::from_clap(&matches), + let args = match Arguments::clap().get_matches_from_safe(raw_args) { + Ok(matches) => Arguments::from_clap(&matches), Err(clap::Error { message, kind: clap::ErrorKind::HelpDisplayed | clap::ErrorKind::VersionDisplayed, @@ -64,233 +60,195 @@ where let json = args.json; let is_testnet = args.testnet; let data = args.data; - - let arguments = match args.cmd { - RawCommand::BuyXmr { + let (context, request) = match args.cmd { + CliCommand::BuyXmr { seller: Seller { seller }, bitcoin, bitcoin_change_address, monero, monero_receive_address, - tor: Tor { tor_socks5_port }, + tor, } => { - let (bitcoin_electrum_rpc_url, bitcoin_target_block) = - bitcoin.apply_defaults(is_testnet)?; let monero_receive_address = - validate_monero_address(monero_receive_address, is_testnet)?; + monero_address::validate_is_testnet(monero_receive_address, is_testnet)?; let bitcoin_change_address = - validate_bitcoin_address(bitcoin_change_address, is_testnet)?; - let monero_daemon_address = monero.monero_daemon_address; + bitcoin_address::validate_is_testnet(bitcoin_change_address, is_testnet)?; - Arguments { - env_config: env_config_from(is_testnet), + let request = Request::new(Method::BuyXmr { + seller, + bitcoin_change_address, + monero_receive_address, + swap_id: Uuid::new_v4(), + }); + + let context = Context::build( + Some(bitcoin), + Some(monero), + Some(tor), + data, + is_testnet, debug, json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::BuyXmr { - seller, - bitcoin_electrum_rpc_url, - bitcoin_target_block, - bitcoin_change_address, - monero_receive_address, - monero_daemon_address, - tor_socks5_port, - namespace: XmrBtcNamespace::from_is_testnet(is_testnet), - }, - } + None, + ) + .await?; + (context, request) } - RawCommand::History => Arguments { - env_config: env_config_from(is_testnet), - debug, - json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::History, - }, - RawCommand::Config => Arguments { - env_config: env_config_from(is_testnet), - debug, - json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::Config, - }, - RawCommand::Balance { - bitcoin_electrum_rpc_url, + CliCommand::History => { + let request = Request::new(Method::History); + + let context = + Context::build(None, None, None, data, is_testnet, debug, json, None).await?; + (context, request) + } + CliCommand::Config => { + let request = Request::new(Method::Config); + + let context = + Context::build(None, None, None, data, is_testnet, debug, json, None).await?; + (context, request) + } + CliCommand::Balance { bitcoin } => { + let request = Request::new(Method::Balance { + force_refresh: true, + }); + + let context = Context::build( + Some(bitcoin), + None, + None, + data, + is_testnet, + debug, + json, + None, + ) + .await?; + (context, request) + } + CliCommand::StartDaemon { + server_address, + bitcoin, + monero, + tor, } => { - let bitcoin = Bitcoin { - bitcoin_electrum_rpc_url, - bitcoin_target_block: None, - }; - let (bitcoin_electrum_rpc_url, bitcoin_target_block) = - bitcoin.apply_defaults(is_testnet)?; + let request = Request::new(Method::StartDaemon { server_address }); - Arguments { - env_config: env_config_from(is_testnet), + let context = Context::build( + Some(bitcoin), + Some(monero), + Some(tor), + data, + is_testnet, debug, json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::Balance { - bitcoin_electrum_rpc_url, - bitcoin_target_block, - }, - } + server_address, + ) + .await?; + (context, request) } - RawCommand::WithdrawBtc { + CliCommand::WithdrawBtc { bitcoin, amount, address, } => { - let (bitcoin_electrum_rpc_url, bitcoin_target_block) = - bitcoin.apply_defaults(is_testnet)?; + let address = bitcoin_address::validate_is_testnet(address, is_testnet)?; + let request = Request::new(Method::WithdrawBtc { amount, address }); - Arguments { - env_config: env_config_from(is_testnet), + let context = Context::build( + Some(bitcoin), + None, + None, + data, + is_testnet, debug, json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::WithdrawBtc { - bitcoin_electrum_rpc_url, - bitcoin_target_block, - amount, - address: bitcoin_address(address, is_testnet)?, - }, - } + None, + ) + .await?; + (context, request) } - RawCommand::Resume { + CliCommand::Resume { swap_id: SwapId { swap_id }, bitcoin, monero, - tor: Tor { tor_socks5_port }, + tor, } => { - let (bitcoin_electrum_rpc_url, bitcoin_target_block) = - bitcoin.apply_defaults(is_testnet)?; - let monero_daemon_address = monero.monero_daemon_address; + let request = Request::new(Method::Resume { swap_id }); - Arguments { - env_config: env_config_from(is_testnet), + let context = Context::build( + Some(bitcoin), + Some(monero), + Some(tor), + data, + is_testnet, debug, json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::Resume { - swap_id, - bitcoin_electrum_rpc_url, - bitcoin_target_block, - monero_daemon_address, - tor_socks5_port, - namespace: XmrBtcNamespace::from_is_testnet(is_testnet), - }, - } + None, + ) + .await?; + (context, request) } - RawCommand::CancelAndRefund { + CliCommand::CancelAndRefund { swap_id: SwapId { swap_id }, bitcoin, + tor, } => { - let (bitcoin_electrum_rpc_url, bitcoin_target_block) = - bitcoin.apply_defaults(is_testnet)?; + let request = Request::new(Method::CancelAndRefund { swap_id }); - Arguments { - env_config: env_config_from(is_testnet), + let context = Context::build( + Some(bitcoin), + None, + Some(tor), + data, + is_testnet, debug, json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::CancelAndRefund { - swap_id, - bitcoin_electrum_rpc_url, - bitcoin_target_block, - }, - } + None, + ) + .await?; + (context, request) } - RawCommand::ListSellers { + CliCommand::ListSellers { rendezvous_point, - tor: Tor { tor_socks5_port }, - } => Arguments { - env_config: env_config_from(is_testnet), - debug, - json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::ListSellers { - rendezvous_point, - tor_socks5_port, - namespace: XmrBtcNamespace::from_is_testnet(is_testnet), - }, - }, - RawCommand::ExportBitcoinWallet { bitcoin } => { - let (bitcoin_electrum_rpc_url, bitcoin_target_block) = - bitcoin.apply_defaults(is_testnet)?; + tor, + } => { + let request = Request::new(Method::ListSellers { rendezvous_point }); - Arguments { - env_config: env_config_from(is_testnet), + let context = + Context::build(None, None, Some(tor), data, is_testnet, debug, json, None).await?; + + (context, request) + } + CliCommand::ExportBitcoinWallet { bitcoin } => { + let request = Request::new(Method::ExportBitcoinWallet); + + let context = Context::build( + Some(bitcoin), + None, + None, + data, + is_testnet, debug, json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::ExportBitcoinWallet { - bitcoin_electrum_rpc_url, - bitcoin_target_block, - }, - } + None, + ) + .await?; + (context, request) + } + CliCommand::MoneroRecovery { + swap_id: SwapId { swap_id }, + } => { + let request = Request::new(Method::MoneroRecovery { swap_id }); + + let context = + Context::build(None, None, None, data, is_testnet, debug, json, None).await?; + + (context, request) } - RawCommand::MoneroRecovery { swap_id } => Arguments { - env_config: env_config_from(is_testnet), - debug, - json, - data_dir: data::data_dir_from(data, is_testnet)?, - cmd: Command::MoneroRecovery { - swap_id: swap_id.swap_id, - }, - }, }; - Ok(ParseResult::Arguments(Box::new(arguments))) -} - -#[derive(Debug, PartialEq, Eq)] -pub enum Command { - BuyXmr { - seller: Multiaddr, - bitcoin_electrum_rpc_url: Url, - bitcoin_target_block: usize, - bitcoin_change_address: bitcoin::Address, - monero_receive_address: monero::Address, - monero_daemon_address: Option, - tor_socks5_port: u16, - namespace: XmrBtcNamespace, - }, - History, - Config, - WithdrawBtc { - bitcoin_electrum_rpc_url: Url, - bitcoin_target_block: usize, - amount: Option, - address: Address, - }, - Balance { - bitcoin_electrum_rpc_url: Url, - bitcoin_target_block: usize, - }, - Resume { - swap_id: Uuid, - bitcoin_electrum_rpc_url: Url, - bitcoin_target_block: usize, - monero_daemon_address: Option, - tor_socks5_port: u16, - namespace: XmrBtcNamespace, - }, - CancelAndRefund { - swap_id: Uuid, - bitcoin_electrum_rpc_url: Url, - bitcoin_target_block: usize, - }, - ListSellers { - rendezvous_point: Multiaddr, - namespace: XmrBtcNamespace, - tor_socks5_port: u16, - }, - ExportBitcoinWallet { - bitcoin_electrum_rpc_url: Url, - bitcoin_target_block: usize, - }, - MoneroRecovery { - swap_id: Uuid, - }, + Ok(ParseResult::Context(Arc::new(context), Box::new(request))) } #[derive(structopt::StructOpt, Debug)] @@ -300,7 +258,7 @@ pub enum Command { author, version = env!("VERGEN_GIT_DESCRIBE") )] -struct RawArguments { +struct Arguments { // global is necessary to ensure that clap can match against testnet in subcommands #[structopt( long, @@ -327,11 +285,11 @@ struct RawArguments { json: bool, #[structopt(subcommand)] - cmd: RawCommand, + cmd: CliCommand, } #[derive(structopt::StructOpt, Debug)] -enum RawCommand { +enum CliCommand { /// Start a BTC for XMR swap BuyXmr { #[structopt(flatten)] @@ -342,7 +300,8 @@ enum RawCommand { #[structopt( long = "change-address", - help = "The bitcoin address where any form of change or excess funds should be sent to" + help = "The bitcoin address where any form of change or excess funds should be sent to", + parse(try_from_str = bitcoin_address::parse) )] bitcoin_change_address: bitcoin::Address, @@ -351,7 +310,7 @@ enum RawCommand { #[structopt(long = "receive-address", help = "The monero address where you would like to receive monero", - parse(try_from_str = parse_monero_address) + parse(try_from_str = monero_address::parse) )] monero_receive_address: monero::Address, @@ -372,13 +331,34 @@ enum RawCommand { help = "Optionally specify the amount of Bitcoin to be withdrawn. If not specified the wallet will be drained." )] amount: Option, - #[structopt(long = "address", help = "The address to receive the Bitcoin.")] - address: Address, + + #[structopt(long = "address", + help = "The address to receive the Bitcoin.", + parse(try_from_str = bitcoin_address::parse) + )] + address: bitcoin::Address, }, #[structopt(about = "Prints the Bitcoin balance.")] Balance { - #[structopt(long = "electrum-rpc", help = "Provide the Bitcoin Electrum RPC URL")] - bitcoin_electrum_rpc_url: Option, + #[structopt(flatten)] + bitcoin: Bitcoin, + }, + #[structopt(about = "Starts a JSON-RPC server")] + StartDaemon { + #[structopt(flatten)] + bitcoin: Bitcoin, + + #[structopt(flatten)] + monero: Monero, + + #[structopt( + long = "server-address", + help = "The socket address the server should use" + )] + server_address: Option, + + #[structopt(flatten)] + tor: Tor, }, /// Resume a swap Resume { @@ -402,6 +382,9 @@ enum RawCommand { #[structopt(flatten)] bitcoin: Bitcoin, + + #[structopt(flatten)] + tor: Tor, }, /// Discover and list sellers (i.e. ASB providers) ListSellers { @@ -429,28 +412,40 @@ enum RawCommand { } #[derive(structopt::StructOpt, Debug)] -struct Monero { +pub struct Monero { #[structopt( long = "monero-daemon-address", - help = "Specify to connect to a monero daemon of your choice: :. If none is specified, we will connect to a public node." + help = "Specify to connect to a monero daemon of your choice: :" )] - monero_daemon_address: Option, + pub monero_daemon_address: Option, +} + +impl Monero { + pub fn apply_defaults(self, testnet: bool) -> String { + if let Some(address) = self.monero_daemon_address { + address + } else if testnet { + DEFAULT_MONERO_DAEMON_ADDRESS_STAGENET.to_string() + } else { + DEFAULT_MONERO_DAEMON_ADDRESS.to_string() + } + } } #[derive(structopt::StructOpt, Debug)] -struct Bitcoin { +pub struct Bitcoin { #[structopt(long = "electrum-rpc", help = "Provide the Bitcoin Electrum RPC URL")] - bitcoin_electrum_rpc_url: Option, + pub bitcoin_electrum_rpc_url: Option, #[structopt( long = "bitcoin-target-block", help = "Estimate Bitcoin fees such that transactions are confirmed within the specified number of blocks" )] - bitcoin_target_block: Option, + pub bitcoin_target_block: Option, } impl Bitcoin { - fn apply_defaults(self, testnet: bool) -> Result<(Url, usize)> { + pub fn apply_defaults(self, testnet: bool) -> Result<(Url, usize)> { let bitcoin_electrum_rpc_url = if let Some(url) = self.bitcoin_electrum_rpc_url { url } else if testnet { @@ -472,13 +467,13 @@ impl Bitcoin { } #[derive(structopt::StructOpt, Debug)] -struct Tor { +pub struct Tor { #[structopt( long = "tor-socks5-port", help = "Your local Tor socks5 proxy port", default_value = DEFAULT_TOR_SOCKS5_PORT )] - tor_socks5_port: u16, + pub tor_socks5_port: u16, } #[derive(structopt::StructOpt, Debug)] @@ -499,137 +494,26 @@ struct Seller { seller: Multiaddr, } -mod data { - use super::*; - - pub fn data_dir_from(arg_dir: Option, testnet: bool) -> Result { - let base_dir = match arg_dir { - Some(custom_base_dir) => custom_base_dir, - None => os_default()?, - }; - - let sub_directory = if testnet { "testnet" } else { "mainnet" }; - - Ok(base_dir.join(sub_directory)) - } - - fn os_default() -> Result { - Ok(system_data_dir()?.join("cli")) - } -} - -fn env_config_from(testnet: bool) -> env::Config { - if testnet { - env::Testnet::get_config() - } else { - env::Mainnet::get_config() - } -} - -fn bitcoin_address(address: Address, is_testnet: bool) -> Result

{ - let network = if is_testnet { - bitcoin::Network::Testnet - } else { - bitcoin::Network::Bitcoin - }; - - if address.network != network { - bail!(BitcoinAddressNetworkMismatch { - expected: network, - actual: address.network - }); - } - - Ok(address) -} - -fn validate_monero_address( - address: monero::Address, - testnet: bool, -) -> Result { - let expected_network = if testnet { - monero::Network::Stagenet - } else { - monero::Network::Mainnet - }; - - if address.network != expected_network { - return Err(MoneroAddressNetworkMismatch { - expected: expected_network, - actual: address.network, - }); - } - - Ok(address) -} - -fn validate_bitcoin_address(address: bitcoin::Address, testnet: bool) -> Result { - let expected_network = if testnet { - bitcoin::Network::Testnet - } else { - bitcoin::Network::Bitcoin - }; - - if address.network != expected_network { - anyhow::bail!( - "Invalid Bitcoin address provided; expected network {} but provided address is for {}", - expected_network, - address.network - ); - } - - if address.address_type() != Some(AddressType::P2wpkh) { - anyhow::bail!("Invalid Bitcoin address provided, only bech32 format is supported!") - } - - Ok(address) -} - -fn parse_monero_address(s: &str) -> Result { - monero::Address::from_str(s).with_context(|| { - format!( - "Failed to parse {} as a monero address, please make sure it is a valid address", - s - ) - }) -} - -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq)] -#[error("Invalid monero address provided, expected address on network {expected:?} but address provided is on {actual:?}")] -pub struct MoneroAddressNetworkMismatch { - expected: monero::Network, - actual: monero::Network, -} - -#[derive(thiserror::Error, Debug, Clone, Copy, PartialEq, Eq, Serialize)] -#[error("Invalid Bitcoin address provided, expected address on network {expected:?} but address provided is on {actual:?}")] -pub struct BitcoinAddressNetworkMismatch { - #[serde(with = "crate::bitcoin::network")] - expected: bitcoin::Network, - #[serde(with = "crate::bitcoin::network")] - actual: bitcoin::Network, -} - #[cfg(test)] mod tests { use super::*; - use crate::tor::DEFAULT_SOCKS5_PORT; + + use crate::api::api_test::*; + use crate::api::Config; + use crate::monero::monero_address::MoneroAddressNetworkMismatch; const BINARY_NAME: &str = "swap"; + const ARGS_DATA_DIR: &str = "/tmp/dir/"; - const TESTNET: &str = "testnet"; - const MAINNET: &str = "mainnet"; + #[tokio::test] - const MONERO_STAGENET_ADDRESS: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a"; - const BITCOIN_TESTNET_ADDRESS: &str = "tb1qr3em6k3gfnyl8r7q0v7t4tlnyxzgxma3lressv"; - const MONERO_MAINNET_ADDRESS: &str = "44Ato7HveWidJYUAVw5QffEcEtSH1DwzSP3FPPkHxNAS4LX9CqgucphTisH978FLHE34YNEx7FcbBfQLQUU8m3NUC4VqsRa"; - const BITCOIN_MAINNET_ADDRESS: &str = "bc1qe4epnfklcaa0mun26yz5g8k24em5u9f92hy325"; - const MULTI_ADDRESS: &str = - "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; - const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b"; + // this test is very long, however it just checks that various CLI arguments sets the + // internal Context and Request properly. It is unlikely to fail and splitting it in various + // tests would require to run the tests sequantially which is very slow (due to the context + // need to access files like the Bitcoin wallet). + async fn test_cli_arguments() { + // given_buy_xmr_on_mainnet_then_defaults_to_mainnet - #[test] - fn given_buy_xmr_on_mainnet_then_defaults_to_mainnet() { let raw_ars = vec![ BINARY_NAME, "buy-xmr", @@ -641,15 +525,34 @@ mod tests { MULTI_ADDRESS, ]; - let expected_args = - ParseResult::Arguments(Arguments::buy_xmr_mainnet_defaults().into_boxed()); - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, false); - assert_eq!(expected_args, args); - } + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; - #[test] - fn given_buy_xmr_on_testnet_then_defaults_to_testnet() { + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::buy_xmr(is_testnet), + ); + + // since Uuid is random, copy before comparing requests + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_testnet_then_defaults_to_testnet let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -662,16 +565,33 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, false); - assert_eq!( - args, - ParseResult::Arguments(Arguments::buy_xmr_testnet_defaults().into_boxed()) + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::buy_xmr(is_testnet), ); - } - #[test] - fn given_buy_xmr_on_mainnet_with_testnet_address_then_fails() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_mainnet_with_testnet_address_then_fails let raw_ars = vec![ BINARY_NAME, "buy-xmr", @@ -683,7 +603,7 @@ mod tests { MULTI_ADDRESS, ]; - let err = parse_args_and_apply_defaults(raw_ars).unwrap_err(); + let err = parse_args_and_apply_defaults(raw_ars).await.unwrap_err(); assert_eq!( err.downcast_ref::().unwrap(), @@ -692,10 +612,8 @@ mod tests { actual: monero::Network::Stagenet } ); - } - #[test] - fn given_buy_xmr_on_testnet_with_mainnet_address_then_fails() { + // given_buy_xmr_on_testnet_with_mainnet_address_then_fails let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -708,7 +626,7 @@ mod tests { MULTI_ADDRESS, ]; - let err = parse_args_and_apply_defaults(raw_ars).unwrap_err(); + let err = parse_args_and_apply_defaults(raw_ars).await.unwrap_err(); assert_eq!( err.downcast_ref::().unwrap(), @@ -717,88 +635,126 @@ mod tests { actual: monero::Network::Mainnet } ); - } - #[test] - fn given_resume_on_mainnet_then_defaults_to_mainnet() { + // given_resume_on_mainnet_then_defaults_to_mainnet let raw_ars = vec![BINARY_NAME, "resume", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, false); - assert_eq!( - args, - ParseResult::Arguments(Arguments::resume_mainnet_defaults().into_boxed()) + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::resume(), ); - } - #[test] - fn given_resume_on_testnet_then_defaults_to_testnet() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_testnet_then_defaults_to_testnet let raw_ars = vec![BINARY_NAME, "--testnet", "resume", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, false); - assert_eq!( - args, - ParseResult::Arguments(Arguments::resume_testnet_defaults().into_boxed()) + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::resume(), ); - } - #[test] - fn given_cancel_on_mainnet_then_defaults_to_mainnet() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_cancel_on_mainnet_then_defaults_to_mainnet let raw_ars = vec![BINARY_NAME, "cancel", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); - assert_eq!( - args, - ParseResult::Arguments(Arguments::cancel_mainnet_defaults().into_boxed()) + let (is_testnet, debug, json) = (false, false, false); + + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::cancel(), ); - } - #[test] - fn given_cancel_on_testnet_then_defaults_to_testnet() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_cancel_on_testnet_then_defaults_to_testnet let raw_ars = vec![BINARY_NAME, "--testnet", "cancel", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, false); - assert_eq!( - args, - ParseResult::Arguments(Arguments::cancel_testnet_defaults().into_boxed()) + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::cancel(), ); - } - #[test] - fn given_refund_on_mainnet_then_defaults_to_mainnet() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + let raw_ars = vec![BINARY_NAME, "refund", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, false); - assert_eq!( - args, - ParseResult::Arguments(Arguments::refund_mainnet_defaults().into_boxed()) + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::refund(), ); - } - #[test] - fn given_refund_on_testnet_then_defaults_to_testnet() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_refund_on_testnet_then_defaults_to_testnet let raw_ars = vec![BINARY_NAME, "--testnet", "refund", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, false); - assert_eq!( - args, - ParseResult::Arguments(Arguments::refund_testnet_defaults().into_boxed()) + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::refund(), ); - } - #[test] - fn given_with_data_dir_then_data_dir_set() { - let data_dir = "/some/path/to/dir"; + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_mainnet_with_data_dir_then_data_dir_set let raw_ars = vec![ BINARY_NAME, "--data-base-dir", - data_dir, + ARGS_DATA_DIR, "buy-xmr", "--change-address", BITCOIN_MAINNET_ADDRESS, @@ -808,22 +764,39 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, false); + let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::buy_xmr_mainnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("mainnet")) - .into_boxed() - ) + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, Some(data_dir.clone()), debug, json), + Request::buy_xmr(is_testnet), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_testnet_with_data_dir_then_data_dir_set let raw_ars = vec![ BINARY_NAME, "--testnet", "--data-base-dir", - data_dir, + ARGS_DATA_DIR, "buy-xmr", "--change-address", BITCOIN_TESTNET_ADDRESS, @@ -833,61 +806,99 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, false); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::buy_xmr_testnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("testnet")) - .into_boxed() - ) + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, Some(data_dir.clone()), debug, json), + Request::buy_xmr(is_testnet), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_mainnet_with_data_dir_then_data_dir_set let raw_ars = vec![ BINARY_NAME, "--data-base-dir", - data_dir, + ARGS_DATA_DIR, "resume", "--swap-id", SWAP_ID, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, false); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::resume_mainnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("mainnet")) - .into_boxed() - ) + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, Some(data_dir.clone()), debug, json), + Request::resume(), ); + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_testnet_with_data_dir_then_data_dir_set let raw_ars = vec![ BINARY_NAME, "--testnet", "--data-base-dir", - data_dir, + ARGS_DATA_DIR, "resume", "--swap-id", SWAP_ID, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); + let data_dir = PathBuf::from_str(ARGS_DATA_DIR).unwrap(); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, false); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::resume_testnet_defaults() - .with_data_dir(PathBuf::from_str(data_dir).unwrap().join("testnet")) - .into_boxed() - ) + let (expected_config, expected_request) = ( + Config::default(is_testnet, Some(data_dir.clone()), debug, json), + Request::resume(), ); - } - #[test] - fn given_with_debug_then_debug_set() { + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_mainnet_with_debug_then_debug_set let raw_ars = vec![ BINARY_NAME, "--debug", @@ -900,16 +911,33 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::buy_xmr_mainnet_defaults() - .with_debug() - .into_boxed() - ) + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, true, false); + + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::buy_xmr(is_testnet), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_testnet_with_debug_then_debug_set let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -923,28 +951,62 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::buy_xmr_testnet_defaults() - .with_debug() - .into_boxed() - ) + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, true, false); + + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::buy_xmr(is_testnet), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_mainnet_with_debug_then_debug_set let raw_ars = vec![BINARY_NAME, "--debug", "resume", "--swap-id", SWAP_ID]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::resume_mainnet_defaults() - .with_debug() - .into_boxed() - ) + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, true, false); + + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::resume(), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_testnet_with_debug_then_debug_set let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -954,19 +1016,23 @@ mod tests { SWAP_ID, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::resume_testnet_defaults() - .with_debug() - .into_boxed() - ) - ); - } + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, true, false); - #[test] - fn given_with_json_then_json_set() { + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::resume(), + ); + + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_mainnet_with_json_then_json_set let raw_ars = vec![ BINARY_NAME, "--json", @@ -979,16 +1045,33 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::buy_xmr_mainnet_defaults() - .with_json() - .into_boxed() - ) + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, true); + + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::buy_xmr(is_testnet), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_buy_xmr_on_testnet_with_json_then_json_set let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -1002,28 +1085,51 @@ mod tests { MULTI_ADDRESS, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::buy_xmr_testnet_defaults() - .with_json() - .into_boxed() - ) - ); + let (is_testnet, debug, json) = (true, false, true); + let (expected_config, mut expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::buy_xmr(is_testnet), + ); + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + if let Method::BuyXmr { + ref mut swap_id, .. + } = expected_request.cmd + { + *swap_id = match actual_request.cmd { + Method::BuyXmr { swap_id, .. } => swap_id, + _ => panic!("Not the Method we expected"), + } + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_mainnet_with_json_then_json_set let raw_ars = vec![BINARY_NAME, "--json", "resume", "--swap-id", SWAP_ID]; + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (false, false, true); - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::resume_mainnet_defaults() - .with_json() - .into_boxed() - ) + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::resume(), ); + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // given_resume_on_testnet_with_json_then_json_set let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -1033,19 +1139,23 @@ mod tests { SWAP_ID, ]; - let args = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert_eq!( - args, - ParseResult::Arguments( - Arguments::resume_testnet_defaults() - .with_json() - .into_boxed() - ) - ); - } + let args = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + let (is_testnet, debug, json) = (true, false, true); - #[test] - fn only_bech32_addresses_mainnet_are_allowed() { + let (expected_config, expected_request) = ( + Config::default(is_testnet, None, debug, json), + Request::resume(), + ); + + let (actual_config, actual_request) = match args { + ParseResult::Context(context, request) => (context.config.clone(), request), + _ => panic!("Couldn't parse result"), + }; + + assert_eq!(actual_config, expected_config); + assert_eq!(actual_request, Box::new(expected_request)); + + // only_bech32_addresses_mainnet_are_allowed let raw_ars = vec![ BINARY_NAME, "buy-xmr", @@ -1056,11 +1166,7 @@ mod tests { "--seller", MULTI_ADDRESS, ]; - let result = parse_args_and_apply_defaults(raw_ars); - assert_eq!( - result.unwrap_err().to_string(), - "Invalid Bitcoin address provided, only bech32 format is supported!" - ); + parse_args_and_apply_defaults(raw_ars).await.unwrap_err(); let raw_ars = vec![ BINARY_NAME, @@ -1072,11 +1178,7 @@ mod tests { "--seller", MULTI_ADDRESS, ]; - let result = parse_args_and_apply_defaults(raw_ars); - assert_eq!( - result.unwrap_err().to_string(), - "Invalid Bitcoin address provided, only bech32 format is supported!" - ); + parse_args_and_apply_defaults(raw_ars).await.unwrap_err(); let raw_ars = vec![ BINARY_NAME, @@ -1088,12 +1190,10 @@ mod tests { "--seller", MULTI_ADDRESS, ]; - let result = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert!(matches!(result, ParseResult::Arguments(_))); - } + let result = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + assert!(matches!(result, ParseResult::Context(_, _))); - #[test] - fn only_bech32_addresses_testnet_are_allowed() { + // only_bech32_addresses_testnet_are_allowed let raw_ars = vec![ BINARY_NAME, "--testnet", @@ -1105,11 +1205,7 @@ mod tests { "--seller", MULTI_ADDRESS, ]; - let result = parse_args_and_apply_defaults(raw_ars); - assert_eq!( - result.unwrap_err().to_string(), - "Invalid Bitcoin address provided, only bech32 format is supported!" - ); + parse_args_and_apply_defaults(raw_ars).await.unwrap_err(); let raw_ars = vec![ BINARY_NAME, @@ -1122,11 +1218,7 @@ mod tests { "--seller", MULTI_ADDRESS, ]; - let result = parse_args_and_apply_defaults(raw_ars); - assert_eq!( - result.unwrap_err().to_string(), - "Invalid Bitcoin address provided, only bech32 format is supported!" - ); + parse_args_and_apply_defaults(raw_ars).await.unwrap_err(); let raw_ars = vec![ BINARY_NAME, @@ -1139,166 +1231,7 @@ mod tests { "--seller", MULTI_ADDRESS, ]; - let result = parse_args_and_apply_defaults(raw_ars).unwrap(); - assert!(matches!(result, ParseResult::Arguments(_))); - } - - impl Arguments { - pub fn buy_xmr_testnet_defaults() -> Self { - Self { - env_config: env::Testnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(TESTNET), - cmd: Command::BuyXmr { - seller: Multiaddr::from_str(MULTI_ADDRESS).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET) - .unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET, - bitcoin_change_address: BITCOIN_TESTNET_ADDRESS.parse().unwrap(), - monero_receive_address: monero::Address::from_str(MONERO_STAGENET_ADDRESS) - .unwrap(), - monero_daemon_address: None, - tor_socks5_port: DEFAULT_SOCKS5_PORT, - namespace: XmrBtcNamespace::Testnet, - }, - } - } - - pub fn buy_xmr_mainnet_defaults() -> Self { - Self { - env_config: env::Mainnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(MAINNET), - cmd: Command::BuyXmr { - seller: Multiaddr::from_str(MULTI_ADDRESS).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET, - bitcoin_change_address: BITCOIN_MAINNET_ADDRESS.parse().unwrap(), - monero_receive_address: monero::Address::from_str(MONERO_MAINNET_ADDRESS) - .unwrap(), - monero_daemon_address: None, - tor_socks5_port: DEFAULT_SOCKS5_PORT, - namespace: XmrBtcNamespace::Mainnet, - }, - } - } - - pub fn resume_testnet_defaults() -> Self { - Self { - env_config: env::Testnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(TESTNET), - cmd: Command::Resume { - swap_id: Uuid::from_str(SWAP_ID).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET) - .unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET, - monero_daemon_address: None, - tor_socks5_port: DEFAULT_SOCKS5_PORT, - namespace: XmrBtcNamespace::Testnet, - }, - } - } - - pub fn resume_mainnet_defaults() -> Self { - Self { - env_config: env::Mainnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(MAINNET), - cmd: Command::Resume { - swap_id: Uuid::from_str(SWAP_ID).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET, - monero_daemon_address: None, - tor_socks5_port: DEFAULT_SOCKS5_PORT, - namespace: XmrBtcNamespace::Mainnet, - }, - } - } - - pub fn cancel_testnet_defaults() -> Self { - Self { - env_config: env::Testnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(TESTNET), - cmd: Command::CancelAndRefund { - swap_id: Uuid::from_str(SWAP_ID).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET) - .unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET, - }, - } - } - - pub fn cancel_mainnet_defaults() -> Self { - Self { - env_config: env::Mainnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(MAINNET), - cmd: Command::CancelAndRefund { - swap_id: Uuid::from_str(SWAP_ID).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET, - }, - } - } - - pub fn refund_testnet_defaults() -> Self { - Self { - env_config: env::Testnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(TESTNET), - cmd: Command::CancelAndRefund { - swap_id: Uuid::from_str(SWAP_ID).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL_TESTNET) - .unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET, - }, - } - } - - pub fn refund_mainnet_defaults() -> Self { - Self { - env_config: env::Mainnet::get_config(), - debug: false, - json: false, - data_dir: data_dir_path_cli().join(MAINNET), - cmd: Command::CancelAndRefund { - swap_id: Uuid::from_str(SWAP_ID).unwrap(), - bitcoin_electrum_rpc_url: Url::from_str(DEFAULT_ELECTRUM_RPC_URL).unwrap(), - bitcoin_target_block: DEFAULT_BITCOIN_CONFIRMATION_TARGET, - }, - } - } - - pub fn with_data_dir(mut self, data_dir: PathBuf) -> Self { - self.data_dir = data_dir; - self - } - - pub fn with_debug(mut self) -> Self { - self.debug = true; - self - } - - pub fn with_json(mut self) -> Self { - self.json = true; - self - } - - pub fn into_boxed(self) -> Box { - Box::new(self) - } - } - - fn data_dir_path_cli() -> PathBuf { - system_data_dir().unwrap().join("cli") + let result = parse_args_and_apply_defaults(raw_ars).await.unwrap(); + assert!(matches!(result, ParseResult::Context(_, _))); } } diff --git a/swap/src/cli/event_loop.rs b/swap/src/cli/event_loop.rs index 1799d20b..23aa0f38 100644 --- a/swap/src/cli/event_loop.rs +++ b/swap/src/cli/event_loop.rs @@ -151,17 +151,17 @@ impl EventLoop { return; } SwarmEvent::Behaviour(OutEvent::Failure { peer, error }) => { - tracing::warn!(%peer, "Communication error: {:#}", error); + tracing::warn!(%peer, err = %error, "Communication error"); return; } SwarmEvent::ConnectionEstablished { peer_id, endpoint, .. } if peer_id == self.alice_peer_id => { - tracing::info!("Connected to Alice at {}", endpoint.get_remote_address()); + tracing::info!(peer_id = %endpoint.get_remote_address(), "Connected to Alice"); } SwarmEvent::Dialing(peer_id) if peer_id == self.alice_peer_id => { - tracing::debug!("Dialling Alice at {}", peer_id); + tracing::debug!(%peer_id, "Dialling Alice"); } SwarmEvent::ConnectionClosed { peer_id, endpoint, num_established, cause: Some(error) } if peer_id == self.alice_peer_id && num_established == 0 => { - tracing::warn!("Lost connection to Alice at {}, cause: {}", endpoint.get_remote_address(), error); + tracing::warn!(peer_id = %endpoint.get_remote_address(), cause = %error, "Lost connection to Alice"); } SwarmEvent::ConnectionClosed { peer_id, num_established, cause: None, .. } if peer_id == self.alice_peer_id && num_established == 0 => { // no error means the disconnection was requested @@ -169,10 +169,10 @@ impl EventLoop { return; } SwarmEvent::OutgoingConnectionError { peer_id, error } if matches!(peer_id, Some(alice_peer_id) if alice_peer_id == self.alice_peer_id) => { - tracing::warn!( "Failed to dial Alice: {}", error); + tracing::warn!(%error, "Failed to dial Alice"); if let Some(duration) = self.swarm.behaviour_mut().redial.until_next_redial() { - tracing::info!("Next redial attempt in {}s", duration.as_secs()); + tracing::info!(seconds_until_next_redial = %duration.as_secs(), "Waiting for next redial attempt"); } } @@ -241,6 +241,7 @@ impl EventLoopHandle { } pub async fn request_quote(&mut self) -> Result { + tracing::debug!("Requesting quote"); Ok(self.quote.send_receive(()).await?) } diff --git a/swap/src/cli/tracing.rs b/swap/src/cli/tracing.rs index a1cd77fb..7cb0721b 100644 --- a/swap/src/cli/tracing.rs +++ b/swap/src/cli/tracing.rs @@ -1,5 +1,4 @@ use anyhow::Result; -use std::option::Option::Some; use std::path::Path; use time::format_description::well_known::Rfc3339; use tracing::subscriber::set_global_default; @@ -7,55 +6,32 @@ use tracing::{Event, Level, Subscriber}; use tracing_subscriber::fmt::format::{DefaultFields, Format, JsonFields}; use tracing_subscriber::fmt::time::UtcTime; use tracing_subscriber::layer::{Context, SubscriberExt}; -use tracing_subscriber::{fmt, EnvFilter, FmtSubscriber, Layer, Registry}; -use uuid::Uuid; +use tracing_subscriber::{fmt, EnvFilter, Layer, Registry}; -pub fn init(debug: bool, json: bool, dir: impl AsRef, swap_id: Option) -> Result<()> { - if let Some(swap_id) = swap_id { - let level_filter = EnvFilter::try_new("swap=debug")?; +pub fn init(debug: bool, json: bool, dir: impl AsRef) -> Result<()> { + let level_filter = EnvFilter::try_new("swap=debug")?; + let registry = Registry::default().with(level_filter); - let registry = Registry::default().with(level_filter); + let appender = tracing_appender::rolling::never(dir.as_ref(), "swap-all.log"); + let (appender, _guard) = tracing_appender::non_blocking(appender); - let appender = - tracing_appender::rolling::never(dir.as_ref(), format!("swap-{}.log", swap_id)); - let (appender, guard) = tracing_appender::non_blocking(appender); + let file_logger = registry.with( + fmt::layer() + .with_ansi(false) + .with_target(false) + .json() + .with_writer(appender), + ); - std::mem::forget(guard); - - let file_logger = registry.with( - fmt::layer() - .with_ansi(false) - .with_target(false) - .json() - .with_writer(appender), - ); - - if json && debug { - set_global_default(file_logger.with(debug_json_terminal_printer()))?; - } else if json && !debug { - set_global_default(file_logger.with(info_json_terminal_printer()))?; - } else if !json && debug { - set_global_default(file_logger.with(debug_terminal_printer()))?; - } else { - set_global_default(file_logger.with(info_terminal_printer()))?; - } + if json && debug { + set_global_default(file_logger.with(debug_json_terminal_printer()))?; + } else if json && !debug { + set_global_default(file_logger.with(info_json_terminal_printer()))?; + } else if !json && debug { + set_global_default(file_logger.with(debug_terminal_printer()))?; } else { - let level = if debug { Level::DEBUG } else { Level::INFO }; - let is_terminal = atty::is(atty::Stream::Stderr); - - let builder = FmtSubscriber::builder() - .with_env_filter(format!("swap={}", level)) - .with_writer(std::io::stderr) - .with_ansi(is_terminal) - .with_timer(UtcTime::rfc_3339()) - .with_target(false); - - if json { - builder.json().init(); - } else { - builder.init(); - } - }; + set_global_default(file_logger.with(info_terminal_printer()))?; + } tracing::info!("Logging initialized to {}", dir.as_ref().display()); Ok(()) @@ -66,19 +42,11 @@ pub struct StdErrPrinter { level: Level, } -type StdErrLayer = tracing_subscriber::fmt::Layer< - S, - DefaultFields, - Format, - fn() -> std::io::Stderr, ->; +type StdErrLayer = + fmt::Layer, fn() -> std::io::Stderr>; -type StdErrJsonLayer = tracing_subscriber::fmt::Layer< - S, - JsonFields, - Format, - fn() -> std::io::Stderr, ->; +type StdErrJsonLayer = + fmt::Layer, fn() -> std::io::Stderr>; fn debug_terminal_printer() -> StdErrPrinter>> { let is_terminal = atty::is(atty::Stream::Stderr); diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index d39e3f87..751f76aa 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -1,11 +1,12 @@ use crate::database::Swap; use crate::monero::Address; use crate::protocol::{Database, State}; -use anyhow::{Context, Result}; +use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use libp2p::{Multiaddr, PeerId}; use sqlx::sqlite::Sqlite; use sqlx::{Pool, SqlitePool}; +use std::collections::HashMap; use std::path::Path; use std::str::FromStr; use time::OffsetDateTime; @@ -149,7 +150,7 @@ impl Database for SqliteDatabase { let rows = sqlx::query!( r#" - SELECT address + SELECT DISTINCT address FROM peer_addresses WHERE peer_id = ? "#, @@ -169,6 +170,25 @@ impl Database for SqliteDatabase { addresses } + async fn get_swap_start_date(&self, swap_id: Uuid) -> Result { + let mut conn = self.pool.acquire().await?; + let swap_id = swap_id.to_string(); + + let row = sqlx::query!( + r#" + SELECT min(entered_at) as start_date + FROM swap_states + WHERE swap_id = ? + "#, + swap_id + ) + .fetch_one(&mut conn) + .await?; + + row.start_date + .ok_or_else(|| anyhow!("Could not get swap start date")) + } + async fn insert_latest_state(&self, swap_id: Uuid, state: State) -> Result<()> { let mut conn = self.pool.acquire().await?; let entered_at = OffsetDateTime::now_utc(); @@ -249,6 +269,69 @@ impl Database for SqliteDatabase { result } + + async fn get_states(&self, swap_id: Uuid) -> Result> { + let mut conn = self.pool.acquire().await?; + let swap_id = swap_id.to_string(); + + // TODO: We should use query! instead of query here to allow for at-compile-time validation + // I didn't manage to generate the mappings for the query! macro because of problems with sqlx-cli + let rows = sqlx::query!( + r#" + SELECT state + FROM swap_states + WHERE swap_id = ? + "#, + swap_id + ) + .fetch_all(&mut conn) + .await?; + + let result = rows + .iter() + .map(|row| { + let state_str: &str = &row.state; + + let state = match serde_json::from_str::(state_str) { + Ok(a) => Ok(State::from(a)), + Err(e) => Err(e), + }?; + Ok(state) + }) + .collect::>>(); + + result + } + + async fn raw_all(&self) -> Result>> { + let mut conn = self.pool.acquire().await?; + let rows = sqlx::query!( + r#" + SELECT swap_id, state + FROM swap_states + "# + ) + .fetch_all(&mut conn) + .await?; + + let mut swaps: HashMap> = HashMap::new(); + + for row in &rows { + let swap_id = Uuid::from_str(&row.swap_id)?; + let state = serde_json::from_str(&row.state)?; + + if let std::collections::hash_map::Entry::Vacant(e) = swaps.entry(swap_id) { + e.insert(vec![state]); + } else { + swaps + .get_mut(&swap_id) + .ok_or_else(|| anyhow!("Error while retrieving the swap"))? + .push(state); + } + } + + Ok(swaps) + } } #[cfg(test)] diff --git a/swap/src/lib.rs b/swap/src/lib.rs index 4865187b..84a39dcc 100644 --- a/swap/src/lib.rs +++ b/swap/src/lib.rs @@ -16,6 +16,7 @@ missing_copy_implementations )] +pub mod api; pub mod asb; pub mod bitcoin; pub mod cli; @@ -28,6 +29,7 @@ pub mod libp2p_ext; pub mod monero; pub mod network; pub mod protocol; +pub mod rpc; pub mod seed; pub mod tor; pub mod tracing_ext; diff --git a/swap/src/monero.rs b/swap/src/monero.rs index d46fc157..8205e75f 100644 --- a/swap/src/monero.rs +++ b/swap/src/monero.rs @@ -42,6 +42,13 @@ pub fn private_key_from_secp256k1_scalar(scalar: bitcoin::Scalar) -> PrivateKey #[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct PrivateViewKey(#[serde(with = "monero_private_key")] PrivateKey); +impl fmt::Display for PrivateViewKey { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Delegate to the Display implementation of PrivateKey + write!(f, "{}", self.0) + } +} + impl PrivateViewKey { pub fn new_random(rng: &mut R) -> Self { let scalar = Scalar::random(rng); @@ -320,6 +327,52 @@ pub mod monero_amount { } } +pub mod monero_address { + use anyhow::{bail, Context, Result}; + use std::str::FromStr; + + #[derive(thiserror::Error, Debug, Clone, Copy, PartialEq)] + #[error("Invalid monero address provided, expected address on network {expected:?} but address provided is on {actual:?}")] + pub struct MoneroAddressNetworkMismatch { + pub expected: monero::Network, + pub actual: monero::Network, + } + + pub fn parse(s: &str) -> Result { + monero::Address::from_str(s).with_context(|| { + format!( + "Failed to parse {} as a monero address, please make sure it is a valid address", + s + ) + }) + } + + pub fn validate( + address: monero::Address, + expected_network: monero::Network, + ) -> Result { + if address.network != expected_network { + bail!(MoneroAddressNetworkMismatch { + expected: expected_network, + actual: address.network, + }); + } + Ok(address) + } + + pub fn validate_is_testnet( + address: monero::Address, + is_testnet: bool, + ) -> Result { + let expected_network = if is_testnet { + monero::Network::Stagenet + } else { + monero::Network::Mainnet + }; + validate(address, expected_network) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/swap/src/protocol.rs b/swap/src/protocol.rs index 9389e3ae..0e15f89a 100644 --- a/swap/src/protocol.rs +++ b/swap/src/protocol.rs @@ -11,6 +11,7 @@ use serde::{Deserialize, Serialize}; use sha2::Sha256; use sigma_fun::ext::dl_secp256k1_ed25519_eq::{CrossCurveDLEQ, CrossCurveDLEQProof}; use sigma_fun::HashTranscript; +use std::collections::HashMap; use std::convert::TryInto; use uuid::Uuid; @@ -139,7 +140,10 @@ pub trait Database { async fn get_monero_address(&self, swap_id: Uuid) -> Result; async fn insert_address(&self, peer_id: PeerId, address: Multiaddr) -> Result<()>; async fn get_addresses(&self, peer_id: PeerId) -> Result>; + async fn get_swap_start_date(&self, swap_id: Uuid) -> Result; async fn insert_latest_state(&self, swap_id: Uuid, state: State) -> Result<()>; async fn get_state(&self, swap_id: Uuid) -> Result; + async fn get_states(&self, swap_id: Uuid) -> Result>; async fn all(&self) -> Result>; + async fn raw_all(&self) -> Result>>; } diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 941e5a43..0eef7dcd 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -112,7 +112,7 @@ where } AliceState::BtcLocked { state3 } => { match state3.expired_timelocks(bitcoin_wallet).await? { - ExpiredTimelocks::None => { + ExpiredTimelocks::None { .. } => { // Record the current monero wallet block height so we don't have to scan from // block 0 for scenarios where we create a refund wallet. let monero_wallet_restore_blockheight = monero_wallet.block_height().await?; @@ -135,7 +135,7 @@ where transfer_proof, state3, } => match state3.expired_timelocks(bitcoin_wallet).await? { - ExpiredTimelocks::None => { + ExpiredTimelocks::None { .. } => { monero_wallet .watch_for_transfer(state3.lock_xmr_watch_request(transfer_proof.clone(), 1)) .await @@ -221,7 +221,7 @@ where encrypted_signature, state3, } => match state3.expired_timelocks(bitcoin_wallet).await? { - ExpiredTimelocks::None => { + ExpiredTimelocks::None { .. } => { let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await; match state3.signed_redeem_transaction(*encrypted_signature) { Ok(tx) => match bitcoin_wallet.broadcast(tx, "redeem").await { diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index 4d0e5a31..edf902b6 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -21,9 +21,10 @@ use sigma_fun::ext::dl_secp256k1_ed25519_eq::CrossCurveDLEQProof; use std::fmt; use uuid::Uuid; -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize)] pub enum BobState { Started { + #[serde(with = "::bitcoin::util::amount::serde::as_sat")] btc_amount: bitcoin::Amount, change_address: bitcoin::Address, }, @@ -287,13 +288,13 @@ pub struct State2 { S_a_monero: monero::PublicKey, S_a_bitcoin: bitcoin::PublicKey, v: monero::PrivateViewKey, - xmr: monero::Amount, - cancel_timelock: CancelTimelock, - punish_timelock: PunishTimelock, - refund_address: bitcoin::Address, + pub xmr: monero::Amount, + pub cancel_timelock: CancelTimelock, + pub punish_timelock: PunishTimelock, + pub refund_address: bitcoin::Address, redeem_address: bitcoin::Address, punish_address: bitcoin::Address, - tx_lock: bitcoin::TxLock, + pub tx_lock: bitcoin::TxLock, tx_cancel_sig_a: Signature, tx_refund_encsig: bitcoin::EncryptedSignature, min_monero_confirmations: u64, @@ -302,9 +303,9 @@ pub struct State2 { #[serde(with = "::bitcoin::util::amount::serde::as_sat")] tx_punish_fee: bitcoin::Amount, #[serde(with = "::bitcoin::util::amount::serde::as_sat")] - tx_refund_fee: bitcoin::Amount, + pub tx_refund_fee: bitcoin::Amount, #[serde(with = "::bitcoin::util::amount::serde::as_sat")] - tx_cancel_fee: bitcoin::Amount, + pub tx_cancel_fee: bitcoin::Amount, } impl State2 { @@ -439,7 +440,7 @@ impl State3 { self.tx_lock.txid() } - pub async fn current_epoch( + pub async fn expired_timelock( &self, bitcoin_wallet: &bitcoin::Wallet, ) -> Result { diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 66933a87..6f5de482 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -117,7 +117,7 @@ async fn next_state( } => { let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await; - if let ExpiredTimelocks::None = state3.current_epoch(bitcoin_wallet).await? { + if let ExpiredTimelocks::None { .. } = state3.expired_timelock(bitcoin_wallet).await? { let transfer_proof_watcher = event_loop_handle.recv_transfer_proof(); let cancel_timelock_expires = tx_lock_status.wait_until_confirmed_with(state3.cancel_timelock); @@ -156,7 +156,7 @@ async fn next_state( } => { let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await; - if let ExpiredTimelocks::None = state.current_epoch(bitcoin_wallet).await? { + if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? { let watch_request = state.lock_xmr_watch_request(lock_transfer_proof); select! { @@ -185,7 +185,7 @@ async fn next_state( BobState::XmrLocked(state) => { let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await; - if let ExpiredTimelocks::None = state.expired_timelock(bitcoin_wallet).await? { + if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? { // Alice has locked Xmr // Bob sends Alice his key @@ -209,7 +209,7 @@ async fn next_state( BobState::EncSigSent(state) => { let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await; - if let ExpiredTimelocks::None = state.expired_timelock(bitcoin_wallet).await? { + if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? { select! { state5 = state.watch_for_redeem_btc(bitcoin_wallet) => { BobState::BtcRedeemed(state5?) @@ -269,12 +269,12 @@ async fn next_state( BobState::BtcCancelled(state) => { // Bob has cancelled the swap match state.expired_timelock(bitcoin_wallet).await? { - ExpiredTimelocks::None => { + ExpiredTimelocks::None { .. } => { bail!( "Internal error: canceled state reached before cancel timelock was expired" ); } - ExpiredTimelocks::Cancel => { + ExpiredTimelocks::Cancel { .. } => { state.publish_refund_btc(bitcoin_wallet).await?; BobState::BtcRefunded(state) } diff --git a/swap/src/rpc.rs b/swap/src/rpc.rs new file mode 100644 index 00000000..6e759057 --- /dev/null +++ b/swap/src/rpc.rs @@ -0,0 +1,31 @@ +use crate::api::Context; +use jsonrpsee::server::{RpcModule, ServerBuilder, ServerHandle}; +use std::net::SocketAddr; +use std::sync::Arc; +use thiserror::Error; + +pub mod methods; + +#[derive(Debug, Error)] +pub enum Error { + #[error("Could not parse key value from params")] + ParseError, +} + +pub async fn run_server( + server_address: SocketAddr, + context: Arc, +) -> anyhow::Result<(SocketAddr, ServerHandle)> { + let server = ServerBuilder::default().build(server_address).await?; + let mut modules = RpcModule::new(()); + { + modules + .merge(methods::register_modules(Arc::clone(&context))?) + .expect("Could not register RPC modules") + } + + let addr = server.local_addr()?; + let server_handle = server.start(modules)?; + + Ok((addr, server_handle)) +} diff --git a/swap/src/rpc/methods.rs b/swap/src/rpc/methods.rs new file mode 100644 index 00000000..83100d4a --- /dev/null +++ b/swap/src/rpc/methods.rs @@ -0,0 +1,236 @@ +use crate::api::request::{Method, Request}; +use crate::api::Context; +use crate::bitcoin::bitcoin_address; +use crate::monero::monero_address; +use crate::{bitcoin, monero}; +use anyhow::Result; +use jsonrpsee::server::RpcModule; +use jsonrpsee::types::Params; +use libp2p::core::Multiaddr; +use std::collections::HashMap; +use std::str::FromStr; +use std::sync::Arc; +use uuid::Uuid; + +pub fn register_modules(context: Arc) -> Result>> { + let mut module = RpcModule::new(context); + + module.register_async_method("suspend_current_swap", |params, context| async move { + execute_request(params, Method::SuspendCurrentSwap, &context).await + })?; + + module.register_async_method("get_swap_info", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let swap_id = params + .get("swap_id") + .ok_or_else(|| jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()))?; + + let swap_id = as_uuid(swap_id) + .ok_or_else(|| jsonrpsee_core::Error::Custom("Could not parse swap_id".to_string()))?; + + execute_request(params_raw, Method::GetSwapInfo { swap_id }, &context).await + })?; + + module.register_async_method("get_bitcoin_balance", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let force_refresh = params + .get("force_refresh") + .ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain force_refresh".to_string()) + })? + .as_bool() + .ok_or_else(|| { + jsonrpsee_core::Error::Custom("force_refesh is not a boolean".to_string()) + })?; + + execute_request(params_raw, Method::Balance { force_refresh }, &context).await + })?; + + module.register_async_method("get_history", |params, context| async move { + execute_request(params, Method::History, &context).await + })?; + + module.register_async_method("get_raw_states", |params, context| async move { + execute_request(params, Method::GetRawStates, &context).await + })?; + + module.register_async_method("resume_swap", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let swap_id = params + .get("swap_id") + .ok_or_else(|| jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()))?; + + let swap_id = as_uuid(swap_id) + .ok_or_else(|| jsonrpsee_core::Error::Custom("Could not parse swap_id".to_string()))?; + + execute_request(params_raw, Method::Resume { swap_id }, &context).await + })?; + + module.register_async_method("cancel_refund_swap", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let swap_id = params + .get("swap_id") + .ok_or_else(|| jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()))?; + + let swap_id = as_uuid(swap_id) + .ok_or_else(|| jsonrpsee_core::Error::Custom("Could not parse swap_id".to_string()))?; + + execute_request(params_raw, Method::CancelAndRefund { swap_id }, &context).await + })?; + + module.register_async_method( + "get_monero_recovery_info", + |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let swap_id = params.get("swap_id").ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain swap_id".to_string()) + })?; + + let swap_id = as_uuid(swap_id).ok_or_else(|| { + jsonrpsee_core::Error::Custom("Could not parse swap_id".to_string()) + })?; + + execute_request(params_raw, Method::MoneroRecovery { swap_id }, &context).await + }, + )?; + + module.register_async_method("withdraw_btc", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let amount = if let Some(amount_str) = params.get("amount") { + Some( + ::bitcoin::Amount::from_str_in(amount_str, ::bitcoin::Denomination::Bitcoin) + .map_err(|_| { + jsonrpsee_core::Error::Custom("Unable to parse amount".to_string()) + })?, + ) + } else { + None + }; + + let withdraw_address = + bitcoin::Address::from_str(params.get("address").ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain address".to_string()) + })?) + .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + let withdraw_address = + bitcoin_address::validate(withdraw_address, context.config.env_config.bitcoin_network)?; + + execute_request( + params_raw, + Method::WithdrawBtc { + amount, + address: withdraw_address, + }, + &context, + ) + .await + })?; + + module.register_async_method("buy_xmr", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let bitcoin_change_address = + bitcoin::Address::from_str(params.get("bitcoin_change_address").ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain bitcoin_change_address".to_string()) + })?) + .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + + let bitcoin_change_address = bitcoin_address::validate( + bitcoin_change_address, + context.config.env_config.bitcoin_network, + )?; + + let monero_receive_address = + monero::Address::from_str(params.get("monero_receive_address").ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain monero_receiveaddress".to_string()) + })?) + .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + + let monero_receive_address = monero_address::validate( + monero_receive_address, + context.config.env_config.monero_network, + )?; + + let seller = + Multiaddr::from_str(params.get("seller").ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain seller".to_string()) + })?) + .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; + + execute_request( + params_raw, + Method::BuyXmr { + bitcoin_change_address, + monero_receive_address, + seller, + swap_id: Uuid::new_v4(), + }, + &context, + ) + .await + })?; + + module.register_async_method("list_sellers", |params_raw, context| async move { + let params: HashMap = params_raw.parse()?; + + let rendezvous_point = params.get("rendezvous_point").ok_or_else(|| { + jsonrpsee_core::Error::Custom("Does not contain rendezvous_point".to_string()) + })?; + + let rendezvous_point = rendezvous_point + .as_str() + .and_then(|addr_str| Multiaddr::from_str(addr_str).ok()) + .ok_or_else(|| { + jsonrpsee_core::Error::Custom("Could not parse valid multiaddr".to_string()) + })?; + + execute_request( + params_raw, + Method::ListSellers { + rendezvous_point: rendezvous_point.clone(), + }, + &context, + ) + .await + })?; + + module.register_async_method("get_current_swap", |params, context| async move { + execute_request(params, Method::GetCurrentSwap, &context).await + })?; + + Ok(module) +} + +fn as_uuid(json_value: &serde_json::Value) -> Option { + if let Some(uuid_str) = json_value.as_str() { + Uuid::parse_str(uuid_str).ok() + } else { + None + } +} + +async fn execute_request( + params: Params<'static>, + cmd: Method, + context: &Arc, +) -> Result { + // If we fail to parse the params as a String HashMap, it's most likely because its an empty object + // In that case, we want to make sure not to fail the request, so we set the log_reference_id to None + // and swallow the error + let reference_id = params + .parse::>() + .ok() + .and_then(|params_parsed| params_parsed.get("log_reference_id").cloned()); + + let request = Request::with_id(cmd, reference_id.map(|log_ref| log_ref.to_string())); + request + .call(Arc::clone(context)) + .await + .map_err(|err| jsonrpsee_core::Error::Custom(format!("{:#}", err))) +} diff --git a/swap/src/seed.rs b/swap/src/seed.rs index 5ffe9124..aa363905 100644 --- a/swap/src/seed.rs +++ b/swap/src/seed.rs @@ -16,7 +16,7 @@ use torut::onion::TorSecretKeyV3; pub const SEED_LENGTH: usize = 32; -#[derive(Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq)] pub struct Seed([u8; SEED_LENGTH]); impl Seed { diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index bd039477..c099376d 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -23,9 +23,9 @@ use swap::network::rendezvous::XmrBtcNamespace; use swap::network::swarm; use swap::protocol::alice::{AliceState, Swap}; use swap::protocol::bob::BobState; -use swap::protocol::{alice, bob}; +use swap::protocol::{alice, bob, Database}; use swap::seed::Seed; -use swap::{asb, bitcoin, cli, env, monero}; +use swap::{api, asb, bitcoin, cli, env, monero}; use tempfile::{tempdir, NamedTempFile}; use testcontainers::clients::Cli; use testcontainers::{Container, RunnableImage}; @@ -400,7 +400,7 @@ impl StartingBalances { } } -struct BobParams { +pub struct BobParams { seed: Seed, db_path: PathBuf, bitcoin_wallet: Arc, @@ -411,6 +411,21 @@ struct BobParams { } impl BobParams { + pub fn get_concentenated_alice_address(&self) -> String { + format!( + "{}/p2p/{}", + self.alice_address.clone(), + self.alice_peer_id.clone().to_base58() + ) + } + + pub async fn get_change_receive_addresses(&self) -> (bitcoin::Address, monero::Address) { + ( + self.bitcoin_wallet.new_address().await.unwrap(), + self.monero_wallet.get_main_address(), + ) + } + pub async fn new_swap_from_db(&self, swap_id: Uuid) -> Result<(bob::Swap, cli::EventLoop)> { let (event_loop, handle) = self.new_eventloop(swap_id).await?; @@ -452,6 +467,8 @@ impl BobParams { } let db = Arc::new(SqliteDatabase::open(&self.db_path).await?); + db.insert_peer_id(swap_id, self.alice_peer_id).await?; + let swap = bob::Swap::new( db, swap_id, @@ -525,13 +542,24 @@ pub struct TestContext { alice_swap_handle: mpsc::Receiver, alice_handle: AliceApplicationHandle, - bob_params: BobParams, + pub bob_params: BobParams, bob_starting_balances: StartingBalances, bob_bitcoin_wallet: Arc, bob_monero_wallet: Arc, } impl TestContext { + pub async fn get_bob_context(self) -> api::Context { + api::Context::for_harness( + self.bob_params.seed, + self.env_config, + self.bob_params.db_path, + self.bob_bitcoin_wallet, + self.bob_monero_wallet, + ) + .await + } + pub async fn restart_alice(&mut self) { self.alice_handle.abort(); diff --git a/swap/tests/rpc.rs b/swap/tests/rpc.rs new file mode 100644 index 00000000..5dc640d4 --- /dev/null +++ b/swap/tests/rpc.rs @@ -0,0 +1,436 @@ +pub mod harness; +#[cfg(test)] +mod test { + + use anyhow::Result; + + use jsonrpsee::ws_client::WsClientBuilder; + use jsonrpsee_core::client::{Client, ClientT}; + use jsonrpsee_core::params::ObjectParams; + + use serial_test::serial; + + use serde_json::Value; + use std::collections::HashMap; + use std::net::SocketAddr; + use std::sync::Arc; + use std::time::Duration; + use swap::api::request::{Method, Request}; + use swap::api::Context; + + use crate::harness::alice_run_until::is_xmr_lock_transaction_sent; + use crate::harness::bob_run_until::is_btc_locked; + use crate::harness::{setup_test, SlowCancelConfig, TestContext}; + use swap::asb::FixedRate; + use swap::protocol::{alice, bob}; + use swap::tracing_ext::{capture_logs, MakeCapturingWriter}; + use tracing_subscriber::filter::LevelFilter; + use uuid::Uuid; + + const SERVER_ADDRESS: &str = "127.0.0.1:1234"; + const SERVER_START_TIMEOUT_SECS: u64 = 50; + const BITCOIN_ADDR: &str = "bcrt1qahvhjfc7vx5857zf8knxs8yp5lkm26jgyt0k76"; + const MONERO_ADDR: &str = "53gEuGZUhP9JMEBZoGaFNzhwEgiG7hwQdMCqFxiyiTeFPmkbt1mAoNybEUvYBKHcnrSgxnVWgZsTvRBaHBNXPa8tHiCU51a"; + const SELLER: &str = + "/ip4/127.0.0.1/tcp/9939/p2p/12D3KooWCdMKjesXMJz1SiZ7HgotrxuqhQJbP5sgBm2BwP1cqThi"; + const SWAP_ID: &str = "ea030832-3be9-454f-bb98-5ea9a788406b"; + + pub async fn setup_daemon( + harness_ctx: TestContext, + ) -> (Client, MakeCapturingWriter, Arc) { + let writer = capture_logs(LevelFilter::DEBUG); + let server_address: SocketAddr = SERVER_ADDRESS.parse().unwrap(); + + let request = Request::new(Method::StartDaemon { + server_address: Some(server_address), + }); + + let context = Arc::new(harness_ctx.get_bob_context().await); + + let context_clone = context.clone(); + + tokio::spawn(async move { + if let Err(err) = request.call(context_clone).await { + println!("Failed to initialize daemon for testing: {}", err); + } + }); + + for _ in 0..SERVER_START_TIMEOUT_SECS { + if writer.captured().contains("Started RPC server") { + let url = format!("ws://{}", SERVER_ADDRESS); + let client = WsClientBuilder::default().build(&url).await.unwrap(); + + return (client, writer, context); + } + + tokio::time::sleep(Duration::from_secs(1)).await; + } + + panic!( + "Failed to start RPC server after {} seconds", + SERVER_START_TIMEOUT_SECS + ); + } + + fn assert_has_keys_serde(map: &serde_json::Map, keys: &[&str]) { + for &key in keys { + assert!(map.contains_key(key), "Key {} is missing", key); + } + } + + // Helper function for HashMap + fn assert_has_keys_hashmap(map: &HashMap, keys: &[&str]) { + for &key in keys { + assert!(map.contains_key(key), "Key {} is missing", key); + } + } + + #[tokio::test] + #[serial] + pub async fn get_swap_info() { + setup_test(SlowCancelConfig, |mut harness_ctx| async move { + // Start a swap and wait for xmr lock transaction to be published (XmrLockTransactionSent) + let (bob_swap, _) = harness_ctx.bob_swap().await; + let bob_swap_id = bob_swap.id; + tokio::spawn(bob::run_until(bob_swap, is_btc_locked)); + let alice_swap = harness_ctx.alice_next_swap().await; + alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + ) + .await?; + + let (client, _, _) = setup_daemon(harness_ctx).await; + + let response: HashMap> = client + .request("get_history", ObjectParams::new()) + .await + .unwrap(); + let swaps: Vec<(Uuid, String)> = vec![(bob_swap_id, "btc is locked".to_string())]; + + assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)])); + + let response: HashMap>> = client + .request("get_raw_states", ObjectParams::new()) + .await + .unwrap(); + + let response_raw_states = response.get("raw_states").unwrap(); + + assert!(response_raw_states.contains_key(&bob_swap_id)); + assert_eq!(response_raw_states.get(&bob_swap_id).unwrap().len(), 2); + + let mut params = ObjectParams::new(); + params.insert("swap_id", bob_swap_id).unwrap(); + let response: HashMap = + client.request("get_swap_info", params).await.unwrap(); + + // Check primary keys in response + assert_has_keys_hashmap( + &response, + &[ + "txRefundFee", + "swapId", + "cancelTimelock", + "timelock", + "punishTimelock", + "stateName", + "btcAmount", + "startDate", + "btcRefundAddress", + "txCancelFee", + "xmrAmount", + "completed", + "txLockId", + "seller", + ], + ); + + // Assert specific fields + assert_eq!(response.get("swapId").unwrap(), &bob_swap_id.to_string()); + assert_eq!( + response.get("stateName").unwrap(), + &"btc is locked".to_string() + ); + assert_eq!(response.get("completed").unwrap(), &Value::Bool(false)); + + // Check seller object and its keys + let seller = response + .get("seller") + .expect("Field 'seller' is missing from response") + .as_object() + .expect("'seller' is not an object"); + assert_has_keys_serde(seller, &["peerId"]); + + // Check timelock object, nested 'None' object, and blocks_left + let timelock = response + .get("timelock") + .expect("Field 'timelock' is missing from response") + .as_object() + .expect("'timelock' is not an object"); + let none_obj = timelock + .get("None") + .expect("Field 'None' is missing from 'timelock'") + .as_object() + .expect("'None' is not an object in 'timelock'"); + let blocks_left = none_obj + .get("blocks_left") + .expect("Field 'blocks_left' is missing from 'None'") + .as_i64() + .expect("'blocks_left' is not an integer"); + + // Validate blocks_left + assert!( + blocks_left > 0 && blocks_left <= 180, + "Field 'blocks_left' should be > 0 and <= 180 but got {}", + blocks_left + ); + + Ok(()) + }) + .await; + } + + #[tokio::test] + #[serial] + pub async fn test_rpc_calls() { + setup_test(SlowCancelConfig, |harness_ctx| async move { + let alice_addr = harness_ctx.bob_params.get_concentenated_alice_address(); + let (change_address, receive_address) = + harness_ctx.bob_params.get_change_receive_addresses().await; + + let (client, writer, _) = setup_daemon(harness_ctx).await; + assert!(client.is_connected()); + + let mut params = ObjectParams::new(); + + params.insert("force_refresh", false).unwrap(); + let response: HashMap = client + .request("get_bitcoin_balance", params) + .await + .unwrap(); + + assert_eq!(response, HashMap::from([("balance".to_string(), 10000000)])); + + + let mut params = ObjectParams::new(); + params.insert("log_reference_id", "test_ref_id").unwrap(); + params.insert("force_refresh", false).unwrap(); + + let _: HashMap = client.request("get_bitcoin_balance", params).await.unwrap(); + + assert!(writer.captured().contains( + r#"method{method_name="Balance" log_reference_id="\"test_ref_id\""}: swap::api::request: Current Bitcoin balance as of last sync balance=0.1 BTC"# + )); + + for method in ["get_swap_info", "resume_swap", "cancel_refund_swap"].iter() { + let mut params = ObjectParams::new(); + params.insert("swap_id", "invalid_swap").unwrap(); + + let response: Result, _> = + client.request(method, params).await; + response.expect_err(&format!( + "Expected an error when swap_id is invalid for method {}", + method + )); + + let params = ObjectParams::new(); + + let response: Result, _> = + client.request(method, params).await; + response.expect_err(&format!( + "Expected an error when swap_id is missing for method {}", + method + )); + } + + let params = ObjectParams::new(); + let result: Result, _> = + client.request("list_sellers", params).await; + + result.expect_err("Expected an error when rendezvous_point is missing"); + + let params = ObjectParams::new(); + let result: Result, _> = + client.request("list_sellers", params).await; + + result.expect_err("Expected an error when rendezvous_point is missing"); + + let params = ObjectParams::new(); + let response: Result, _> = + client.request("withdraw_btc", params).await; + response.expect_err("Expected an error when withdraw_address is missing"); + + let mut params = ObjectParams::new(); + params.insert("address", "invalid_address").unwrap(); + let response: Result, _> = + client.request("withdraw_btc", params).await; + response.expect_err("Expected an error when withdraw_address is malformed"); + + let mut params = ObjectParams::new(); + params.insert("address", BITCOIN_ADDR).unwrap(); + params.insert("amount", "0").unwrap(); + let response: Result, _> = + client.request("withdraw_btc", params).await; + response.expect_err("Expected an error when amount is 0"); + + let mut params = ObjectParams::new(); + params + .insert("address", BITCOIN_ADDR) + .unwrap(); + params.insert("amount", "0.01").unwrap(); + let response: HashMap = client + .request("withdraw_btc", params) + .await + .expect("Expected a valid response"); + + assert_has_keys_hashmap(&response, &["signed_tx", "amount", "txid"]); + assert_eq!( + response.get("amount").unwrap().as_u64().unwrap(), + 1_000_000 + ); + + let params = ObjectParams::new(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when no params are given"); + + let mut params = ObjectParams::new(); + params + .insert("bitcoin_change_address", BITCOIN_ADDR) + .unwrap(); + params + .insert("monero_receive_address", MONERO_ADDR) + .unwrap(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when seller is missing"); + + let mut params = ObjectParams::new(); + params + .insert("bitcoin_change_address", BITCOIN_ADDR) + .unwrap(); + params.insert("seller", SELLER).unwrap(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when monero_receive_address is missing"); + + let mut params = ObjectParams::new(); + params + .insert("monero_receive_address", MONERO_ADDR) + .unwrap(); + params.insert("seller", SELLER).unwrap(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when bitcoin_change_address is missing"); + + let mut params = ObjectParams::new(); + params + .insert("bitcoin_change_address", "invalid_address") + .unwrap(); + params + .insert("monero_receive_address", MONERO_ADDR) + .unwrap(); + params.insert("seller", SELLER).unwrap(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when bitcoin_change_address is malformed"); + + let mut params = ObjectParams::new(); + params + .insert("bitcoin_change_address", BITCOIN_ADDR) + .unwrap(); + params + .insert("monero_receive_address", "invalid_address") + .unwrap(); + params.insert("seller", SELLER).unwrap(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when monero_receive_address is malformed"); + + + let mut params = ObjectParams::new(); + params + .insert("bitcoin_change_address", BITCOIN_ADDR) + .unwrap(); + params + .insert("monero_receive_address", MONERO_ADDR) + .unwrap(); + params.insert("seller", "invalid_seller").unwrap(); + let response: Result, _> = + client.request("buy_xmr", params).await; + response.expect_err("Expected an error when seller is malformed"); + + let response: Result, _> = client + .request("suspend_current_swap", ObjectParams::new()) + .await; + response.expect_err("Expected an error when no swap is running"); + + let mut params = ObjectParams::new(); + params + .insert("bitcoin_change_address", change_address) + .unwrap(); + params + .insert("monero_receive_address", receive_address) + .unwrap(); + + params.insert("seller", alice_addr).unwrap(); + let response: HashMap = client + .request("buy_xmr", params) + .await + .expect("Expected a HashMap, got an error"); + + assert_has_keys_hashmap(&response, &["swapId"]); + + Ok(()) + }) + .await; + } + + #[tokio::test] + #[serial] + pub async fn suspend_current_swap_swap_running() { + setup_test(SlowCancelConfig, |harness_ctx| async move { + let (client, _, ctx) = setup_daemon(harness_ctx).await; + + ctx.swap_lock + .acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap()) + .await + .unwrap(); + let cloned_ctx = ctx.clone(); + + tokio::spawn(async move { + // Immediately release lock when suspend signal is received. Mocks a running swap that is then cancelled. + ctx.swap_lock + .listen_for_swap_force_suspension() + .await + .unwrap(); + ctx.swap_lock.release_swap_lock().await.unwrap(); + }); + + let response: HashMap = client + .request("suspend_current_swap", ObjectParams::new()) + .await + .unwrap(); + assert_eq!( + response, + HashMap::from([("swapId".to_string(), SWAP_ID.to_string())]) + ); + + cloned_ctx + .swap_lock + .acquire_swap_lock(Uuid::parse_str(SWAP_ID).unwrap()) + .await + .unwrap(); + + let response: Result, _> = client + .request("suspend_current_swap", ObjectParams::new()) + .await; + response.expect_err("Expected an error when suspend signal times out"); + + Ok(()) + }) + .await; + } +} From 97210739a177d27c12f1056ec8d2c89b77abf4f9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 11:10:26 +0000 Subject: [PATCH 262/395] build(deps): bump Swatinem/rust-cache from 2.7.1 to 2.7.3 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.1 to 2.7.3. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.7.1...v2.7.3) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da82b266..5711b8f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -181,7 +181,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.1 - - uses: Swatinem/rust-cache@v2.7.1 + - uses: Swatinem/rust-cache@v2.7.3 - name: Run RPC server tests run: cargo test --package swap --all-features --test rpc -- --nocapture From b443a964695bcc0cd707b6fdedbca6f3f1a5c476 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 11:10:29 +0000 Subject: [PATCH 263/395] build(deps): bump actions/checkout from 4.1.1 to 4.1.6 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.1...v4.1.6) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da82b266..23072bf5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -179,7 +179,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.1 + uses: actions/checkout@v4.1.6 - uses: Swatinem/rust-cache@v2.7.1 From 0c4b7d50c267ff0c94157a7ad225e19e5b5e724f Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 24 May 2024 18:02:29 +0200 Subject: [PATCH 264/395] Lower DEFAULT_BITCOIN_CONFIRMATION_TARGET to 1 to ensure timely confirmation of bitcoin transactions (#1640) --- swap/src/cli/command.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index affd6a19..af72df1b 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -23,7 +23,7 @@ const DEFAULT_ELECTRUM_RPC_URL: &str = "ssl://blockstream.info:700"; // See: https://1209k.com/bitcoin-eye/ele.php?chain=tbtc pub const DEFAULT_ELECTRUM_RPC_URL_TESTNET: &str = "ssl://electrum.blockstream.info:60002"; -const DEFAULT_BITCOIN_CONFIRMATION_TARGET: usize = 3; +const DEFAULT_BITCOIN_CONFIRMATION_TARGET: usize = 1; pub const DEFAULT_BITCOIN_CONFIRMATION_TARGET_TESTNET: usize = 1; const DEFAULT_TOR_SOCKS5_PORT: &str = "9050"; From 2f28ef940183d8272244c2a81ec4295873569a49 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 24 May 2024 18:06:21 +0200 Subject: [PATCH 265/395] Add missing changelog entries (#1641) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d3ad105..2eaf409c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Minimum Supported Rust Version (MSRV) bumped to 1.70 +- Lowered default Bitcoin confirmation target for Bob to 1 to make sure Bitcoin transactions get confirmed in time +- Added support for starting the CLI (using the `start-daemon` subcommand) as a Daemon that accepts JSON-RPC requests ## [0.12.3] - 2023-09-20 From 0ca98cd0b78aff95a38021e9574fe3c28c968963 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Sat, 25 May 2024 14:43:22 +0200 Subject: [PATCH 266/395] Make tracing file appender blocking (#1643) --- swap/src/cli/tracing.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/swap/src/cli/tracing.rs b/swap/src/cli/tracing.rs index 7cb0721b..6b6de60f 100644 --- a/swap/src/cli/tracing.rs +++ b/swap/src/cli/tracing.rs @@ -13,7 +13,6 @@ pub fn init(debug: bool, json: bool, dir: impl AsRef) -> Result<()> { let registry = Registry::default().with(level_filter); let appender = tracing_appender::rolling::never(dir.as_ref(), "swap-all.log"); - let (appender, _guard) = tracing_appender::non_blocking(appender); let file_logger = registry.with( fmt::layer() From c433bd2389300f05f167462a8fe45a66e1040915 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Sat, 25 May 2024 17:59:12 +0200 Subject: [PATCH 267/395] CLI: Initiate tracing earlier to avoid lost logs (#1646) --- swap/src/api.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/swap/src/api.rs b/swap/src/api.rs index ca3ae21d..6940b8b1 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -184,6 +184,10 @@ impl Context { let data_dir = data::data_dir_from(data, is_testnet)?; let env_config = env_config_from(is_testnet); + START.call_once(|| { + let _ = cli::tracing::init(debug, json, data_dir.join("logs")); + }); + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read seed in file")?; @@ -219,10 +223,6 @@ impl Context { let tor_socks5_port = tor.map_or(9050, |tor| tor.tor_socks5_port); - START.call_once(|| { - let _ = cli::tracing::init(debug, json, data_dir.join("logs")); - }); - let context = Context { db: open_db(data_dir.join("sqlite")).await?, bitcoin_wallet, From 32ca0b1a4ac868505f1a6522c16fd3690c73c649 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Sat, 25 May 2024 18:08:17 +0200 Subject: [PATCH 268/395] CLI: Upgrade monero-wallet-rpc to 0.18.3.1, clarify a few log. messages --- CHANGELOG.md | 1 + swap/src/api.rs | 2 +- swap/src/monero/wallet_rpc.rs | 43 +++++++++++++++++++++++------------ swap/src/protocol/bob/swap.rs | 3 +++ 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eaf409c..0a299af8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Minimum Supported Rust Version (MSRV) bumped to 1.70 - Lowered default Bitcoin confirmation target for Bob to 1 to make sure Bitcoin transactions get confirmed in time - Added support for starting the CLI (using the `start-daemon` subcommand) as a Daemon that accepts JSON-RPC requests +- Update monero-wallet-rpc version to v0.18.3.1 ## [0.12.3] - 2023-09-20 diff --git a/swap/src/api.rs b/swap/src/api.rs index 6940b8b1..340c2e39 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -187,7 +187,7 @@ impl Context { START.call_once(|| { let _ = cli::tracing::init(debug, json, data_dir.join("logs")); }); - + let seed = Seed::from_file_or_generate(data_dir.as_path()) .context("Failed to read seed in file")?; diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index e227c3f3..8af1167e 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -46,30 +46,30 @@ const MONERO_DAEMONS: [MoneroDaemon; 17] = [ compile_error!("unsupported operating system"); #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-x64-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "x86_64"))] -const DOWNLOAD_HASH: &str = "ba1108c7a5e5efe15b6a628fb007c50f01c231f61137bba7427605286dbc6f01"; +const DOWNLOAD_HASH: &str = "7f8bd9364ef16482b418aa802a65be0e4cc660c794bb5d77b2d17bc84427883a"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-mac-armv8-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "macos", target_arch = "aarch64"))] -const DOWNLOAD_HASH: &str = "620b825c04f84845ed09de03b207a3230a34f74b30a8a07dde504a7d376ee4b9"; +const DOWNLOAD_HASH: &str = "915288b023cb5811e626e10052adc6ac5323dd283c5a25b91059b0fb86a21fb6"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.1.2.tar.bz2"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-linux-x64-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "x86_64"))] -const DOWNLOAD_HASH: &str = "7d51e7072351f65d0c7909e745827cfd3b00abe5e7c4cc4c104a3c9b526da07e"; +const DOWNLOAD_HASH: &str = "23af572fdfe3459b9ab97e2e9aa7e3c11021c955d6064b801a27d7e8c21ae09d"; #[cfg(all(target_os = "linux", target_arch = "arm"))] const DOWNLOAD_URL: &str = - "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.1.2.tar.bz2"; + "https://downloads.getmonero.org/cli/monero-linux-armv7-v0.18.3.1.tar.bz2"; #[cfg(all(target_os = "linux", target_arch = "arm"))] -const DOWNLOAD_HASH: &str = "94ece435ed60f85904114643482c2b6716f74bf97040a7af237450574a9cf06d"; +const DOWNLOAD_HASH: &str = "2ea2c8898cbab88f49423f4f6c15f2a94046cb4bbe827493dd061edc0fd5f1ca"; #[cfg(target_os = "windows")] -const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.1.2.zip"; +const DOWNLOAD_URL: &str = "https://downloads.getmonero.org/cli/monero-win-x64-v0.18.3.1.zip"; #[cfg(target_os = "windows")] -const DOWNLOAD_HASH: &str = "0a3d4d1af7e094c05352c31b2dafcc6ccbc80edc195ca9eaedc919c36accd05a"; +const DOWNLOAD_HASH: &str = "35dcc4bee4caad3442659d37837e0119e4649a77f2e3b5e80dd6d9b8fc4fb6ad"; #[cfg(any(target_os = "macos", target_os = "linux"))] const PACKED_FILE: &str = "monero-wallet-rpc"; @@ -77,7 +77,7 @@ const PACKED_FILE: &str = "monero-wallet-rpc"; #[cfg(target_os = "windows")] const PACKED_FILE: &str = "monero-wallet-rpc.exe"; -const WALLET_RPC_VERSION: &str = "v0.18.1.2"; +const WALLET_RPC_VERSION: &str = "v0.18.3.1"; #[derive(Debug, Clone, Copy, thiserror::Error)] #[error("monero wallet rpc executable not found in downloaded archive")] @@ -233,9 +233,10 @@ impl WalletRpc { .parse::()?; tracing::info!( - "Downloading monero-wallet-rpc ({}) from {}", - content_length.big_byte(2), - DOWNLOAD_URL + progress="0%", + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", ); let mut hasher = Sha256::new(); @@ -268,12 +269,24 @@ impl WalletRpc { let total = 3 * content_length; let percent = 100 * received as u64 / total; if percent != notified && percent % 10 == 0 { - tracing::debug!("{}%", percent); + tracing::info!( + progress=format!("{}%", percent), + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", + ); notified = percent; } file.write_all(&bytes).await?; } + tracing::info!( + progress="100%", + size=%content_length.big_byte(2), + download_url=DOWNLOAD_URL, + "Downloading monero-wallet-rpc", + ); + let result = hasher.finalize(); let result_hash = HEXLOWER.encode(result.as_ref()); if result_hash != DOWNLOAD_HASH { diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 6f5de482..37a6b65a 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -227,6 +227,9 @@ async fn next_state( let (spend_key, view_key) = state.xmr_keys(); let wallet_file_name = swap_id.to_string(); + + tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero"); + if let Err(e) = monero_wallet .create_from_and_load( wallet_file_name.clone(), From 796863359f23190c55aaa4564a505b7c0cee37d5 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 27 May 2024 11:03:20 +0200 Subject: [PATCH 269/395] upgrade secp256kfun (#1466) * ci: add cargo check on rust stable * refactor: upgrade secp256kfun and fix resulting issues * build(deps): update sigma_fun and ecdsa_fun to a52142cf7f #1520 #1521 * chore: fix clippy issue * update to 91112f80b24 * bump to 294de1721add * chore(deps): remove spectral spectral fails to compile on rust stable 1.76 due to dep on deprecated rustc-serialize * secp256kfun: update to 7da9d277 and set rev in manifest * update to 6fdc5d8 * switch to crates.io versions of ecdsa_fun and sigma_fun * ci: update toolchain to 1.74 and fix draft action * clippy fixes --------- Co-authored-by: binarybaron <86064887+binarybaron@users.noreply.github.com> --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 20 +- .github/workflows/draft-new-release.yml | 4 +- CHANGELOG.md | 2 +- Cargo.lock | 220 ++++++++----------- Cargo.toml | 1 + README.md | 2 +- monero-harness/Cargo.toml | 1 - monero-harness/src/lib.rs | 2 +- monero-harness/tests/monerod.rs | 5 +- monero-harness/tests/wallet.rs | 7 +- monero-wallet/src/lib.rs | 2 +- rust-toolchain.toml | 2 +- swap/Cargo.toml | 5 +- swap/src/asb/event_loop.rs | 6 +- swap/src/asb/network.rs | 4 +- swap/src/bitcoin.rs | 40 +++- swap/src/bitcoin/cancel.rs | 21 +- swap/src/bitcoin/lock.rs | 6 +- swap/src/bitcoin/punish.rs | 8 +- swap/src/bitcoin/redeem.rs | 28 ++- swap/src/bitcoin/refund.rs | 26 ++- swap/src/bitcoin/wallet.rs | 4 +- swap/src/cli/event_loop.rs | 2 +- swap/src/network/cbor_request_response.rs | 2 +- swap/src/network/json_pull_codec.rs | 2 +- swap/src/network/test.rs | 2 +- swap/src/protocol/alice/state.rs | 6 +- swap/src/protocol/bob/state.rs | 17 +- 29 files changed, 229 insertions(+), 220 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index ecfde0c8..bcd2c806 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -61,7 +61,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: "1.70" + toolchain: "1.74" targets: armv7-unknown-linux-gnueabihf - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b92d60de..7619754b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: "1.70" + toolchain: "1.74" components: clippy,rustfmt - uses: Swatinem/rust-cache@v2.7.3 @@ -31,6 +31,22 @@ jobs: - name: Run clippy with all features enabled run: cargo clippy --workspace --all-targets --all-features -- -D warnings + check_stable: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4.1.1 + + - uses: dtolnay/rust-toolchain@stable + + - name: Override rust stable + run: | + rustup override set stable + + - name: Run cargo check on rust stable + run: cargo check --all-targets + + bdk_test: runs-on: ubuntu-latest steps: @@ -84,7 +100,7 @@ jobs: - uses: dtolnay/rust-toolchain@master with: - toolchain: "1.70" + toolchain: "1.74" targets: armv7-unknown-linux-gnueabihf - name: Build binary diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 48fb2d3a..09df0bd7 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -42,8 +42,8 @@ jobs: - name: Commit changelog and manifest files id: make-commit env: - DPRINT_VERSION: 0.39.1 - RUST_TOOLCHAIN: 1.70 + DPRINT_VERSION: "0.39.1" + RUST_TOOLCHAIN: "1.74" run: | rustup component add rustfmt --toolchain "$RUST_TOOLCHAIN-x86_64-unknown-linux-gnu" curl -fsSL https://dprint.dev/install.sh | sh -s $DPRINT_VERSION diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a299af8..e3e510a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -- Minimum Supported Rust Version (MSRV) bumped to 1.70 +- Minimum Supported Rust Version (MSRV) bumped to 1.74 - Lowered default Bitcoin confirmation target for Bob to 1 to make sure Bitcoin transactions get confirmed in time - Added support for starting the CLI (using the `start-daemon` subcommand) as a Daemon that accepts JSON-RPC requests - Update monero-wallet-rpc version to v0.18.3.1 diff --git a/Cargo.lock b/Cargo.lock index 34ced0d5..435a86bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -347,6 +347,25 @@ dependencies = [ "serde", ] +[[package]] +name = "bincode" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" +dependencies = [ + "bincode_derive", + "serde", +] + +[[package]] +name = "bincode_derive" +version = "2.0.0-rc.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" +dependencies = [ + "virtue", +] + [[package]] name = "bit-set" version = "0.5.2" @@ -371,7 +390,7 @@ dependencies = [ "base64 0.13.1", "bech32", "bitcoin_hashes", - "secp256k1", + "secp256k1 0.24.1", "serde", ] @@ -1112,10 +1131,11 @@ checksum = "5caaa75cbd2b960ff1e5392d2cfb1f44717fffe12fc1f32b7b5d1267f99732a6" [[package]] name = "ecdsa_fun" -version = "0.7.1" -source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fd850b7ece4e4ddaa1478d5de36b6d4d599f2d521f73456ca706b4e2b32a4ec" dependencies = [ - "bincode", + "bincode 1.3.3", "rand_chacha 0.3.1", "secp256kfun", "sigma_fun", @@ -1306,12 +1326,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures" version = "0.3.30" @@ -2589,7 +2603,6 @@ dependencies = [ "futures", "monero-rpc", "rand 0.7.3", - "spectral", "testcontainers", "tokio", "tracing", @@ -2723,42 +2736,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" -dependencies = [ - "num-integer", - "num-traits", - "rand 0.4.6", - "rustc-serialize", -] - -[[package]] -name = "num-complex" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b288631d7878aaf59442cffd36910ea604ecd7745c36054328595114001c9656" -dependencies = [ - "num-traits", - "rustc-serialize", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -2775,29 +2752,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", - "rustc-serialize", -] - [[package]] name = "num-traits" version = "0.2.15" @@ -3281,19 +3235,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" @@ -3339,21 +3280,6 @@ dependencies = [ "rand_core 0.6.2", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -3399,15 +3325,6 @@ dependencies = [ "rand_core 0.6.2", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" version = "0.2.10" @@ -3632,12 +3549,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" -[[package]] -name = "rustc-serialize" -version = "0.3.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" - [[package]] name = "rustc_version" version = "0.3.3" @@ -3825,7 +3736,27 @@ checksum = "ff55dc09d460954e9ef2fa8a7ced735a964be9981fd50e870b2b3b0705e14964" dependencies = [ "bitcoin_hashes", "rand 0.8.3", - "secp256k1-sys", + "secp256k1-sys 0.6.1", + "serde", +] + +[[package]] +name = "secp256k1" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +dependencies = [ + "secp256k1-sys 0.8.1", + "serde", +] + +[[package]] +name = "secp256k1" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" +dependencies = [ + "secp256k1-sys 0.9.2", "serde", ] @@ -3839,17 +3770,49 @@ dependencies = [ ] [[package]] -name = "secp256kfun" -version = "0.7.1" -source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca" +name = "secp256k1-sys" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" dependencies = [ + "cc", +] + +[[package]] +name = "secp256k1-sys" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb" +dependencies = [ + "cc", +] + +[[package]] +name = "secp256kfun" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecc2adce3ef929c5dc7dacdd612d65ab98002ee18119215ce25d8054ed53c1a" +dependencies = [ + "bincode 2.0.0-rc.3", "digest 0.10.7", "rand_core 0.6.2", - "secp256k1", + "secp256k1 0.27.0", + "secp256k1 0.28.2", + "secp256kfun_arithmetic_macros", "serde", "subtle-ng", ] +[[package]] +name = "secp256kfun_arithmetic_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91b7c385a72530ebfe6010ff476ad9e235743fb33408a360052bb706f1481e1e" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "security-framework" version = "2.3.1" @@ -4091,8 +4054,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "sigma_fun" -version = "0.4.1" -source = "git+https://github.com/LLFourn/secp256kfun#9657d8c12fd26df5e57254a0063eaf41082a38ca" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b8e9462de42c6f14c7e20154d18d8e9e8683750798885e76f06973317b1cb1d" dependencies = [ "curve25519-dalek-ng", "digest 0.10.7", @@ -4217,15 +4181,6 @@ dependencies = [ "sha-1", ] -[[package]] -name = "spectral" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3c15181f4b14e52eeaac3efaeec4d2764716ce9c86da0c934c3e318649c5ba" -dependencies = [ - "num", -] - [[package]] name = "spin" version = "0.5.2" @@ -4488,7 +4443,6 @@ dependencies = [ "serial_test", "sha2 0.10.8", "sigma_fun", - "spectral", "sqlx", "structopt", "strum", @@ -5309,6 +5263,12 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "virtue" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" + [[package]] name = "void" version = "1.0.2" diff --git a/Cargo.toml b/Cargo.toml index 0f654d91..ab29e919 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "monero-harness", "monero-rpc", "swap", "monero-wallet" ] [patch.crates-io] diff --git a/README.md b/README.md index 71a37896..35adc5f0 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ 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.70 _should_ work. +All stable toolchains since 1.74 _should_ work. ## Contact diff --git a/monero-harness/Cargo.toml b/monero-harness/Cargo.toml index 6780dbd8..a4c9ce72 100644 --- a/monero-harness/Cargo.toml +++ b/monero-harness/Cargo.toml @@ -10,7 +10,6 @@ anyhow = "1" futures = "0.3" monero-rpc = { path = "../monero-rpc" } rand = "0.7" -spectral = "0.6" testcontainers = "0.14" tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "macros" ] } tracing = "0.1" diff --git a/monero-harness/src/lib.rs b/monero-harness/src/lib.rs index d5f8a513..61c12a27 100644 --- a/monero-harness/src/lib.rs +++ b/monero-harness/src/lib.rs @@ -225,7 +225,7 @@ impl<'c> Monerod { name: String, network: String, ) -> Result<(Self, Container<'c, image::Monerod>)> { - let image = image::Monerod::default(); + let image = image::Monerod; let image: RunnableImage = RunnableImage::from(image) .with_container_name(name.clone()) .with_network(network.clone()); diff --git a/monero-harness/tests/monerod.rs b/monero-harness/tests/monerod.rs index d218167b..f454fb74 100644 --- a/monero-harness/tests/monerod.rs +++ b/monero-harness/tests/monerod.rs @@ -1,6 +1,5 @@ use monero_harness::Monero; use monero_rpc::monerod::MonerodRpc as _; -use spectral::prelude::*; use std::time::Duration; use testcontainers::clients::Cli; use tokio::time; @@ -21,12 +20,12 @@ async fn init_miner_and_mine_to_miner_address() { let miner_wallet = monero.wallet("miner").unwrap(); let got_miner_balance = miner_wallet.balance().await.unwrap(); - assert_that!(got_miner_balance).is_greater_than(0); + assert!(got_miner_balance > 0); time::sleep(Duration::from_millis(1010)).await; // after a bit more than 1 sec another block should have been mined let block_height = monerod.client().get_block_count().await.unwrap().count; - assert_that(&block_height).is_greater_than(70); + assert!(block_height > 70); } diff --git a/monero-harness/tests/wallet.rs b/monero-harness/tests/wallet.rs index b25683ad..67d11645 100644 --- a/monero-harness/tests/wallet.rs +++ b/monero-harness/tests/wallet.rs @@ -1,6 +1,5 @@ use monero_harness::{Monero, MoneroWalletRpc}; use monero_rpc::wallet::MoneroWalletRpc as _; -use spectral::prelude::*; use std::time::Duration; use testcontainers::clients::Cli; use tokio::time::sleep; @@ -29,7 +28,7 @@ async fn fund_transfer_and_check_tx_key() { // check alice balance let got_alice_balance = alice_wallet.balance().await.unwrap(); - assert_that(&got_alice_balance).is_equal_to(fund_alice); + assert_eq!(got_alice_balance, fund_alice); // transfer from alice to bob let bob_address = bob_wallet.address().await.unwrap().address; @@ -41,7 +40,7 @@ async fn fund_transfer_and_check_tx_key() { wait_for_wallet_to_catch_up(bob_wallet, send_to_bob).await; let got_bob_balance = bob_wallet.balance().await.unwrap(); - assert_that(&got_bob_balance).is_equal_to(send_to_bob); + assert_eq!(got_bob_balance, send_to_bob); // check if tx was actually seen let tx_id = transfer.tx_hash; @@ -52,7 +51,7 @@ async fn fund_transfer_and_check_tx_key() { .await .expect("failed to check tx by key"); - assert_that!(res.received).is_equal_to(send_to_bob); + assert_eq!(res.received, send_to_bob); } async fn wait_for_wallet_to_catch_up(wallet: &MoneroWalletRpc, expected_balance: u64) { diff --git a/monero-wallet/src/lib.rs b/monero-wallet/src/lib.rs index 080c2599..7f2928c3 100644 --- a/monero-wallet/src/lib.rs +++ b/monero-wallet/src/lib.rs @@ -65,7 +65,7 @@ mod tests { #[tokio::test] async fn get_outs_for_key_offsets() { let cli = Cli::default(); - let container = cli.run(Monerod::default()); + let container = cli.run(Monerod); let rpc_client = Client::localhost(container.get_host_port_ipv4(18081)).unwrap(); rpc_client.generateblocks(150, "498AVruCDWgP9Az9LjMm89VWjrBrSZ2W2K3HFBiyzzrRjUJWUcCVxvY1iitfuKoek2FdX6MKGAD9Qb1G1P8QgR5jPmmt3Vj".to_owned()).await.unwrap(); let wallet = Wallet { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d03c251b..cc47d97a 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "1.70" # also update this in the readme, changelog, and github actions +channel = "1.74" # also update this in the readme, changelog, and github actions components = ["clippy"] targets = ["armv7-unknown-linux-gnueabihf"] diff --git a/swap/Cargo.toml b/swap/Cargo.toml index b73d61bb..3f9349d6 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -27,7 +27,7 @@ data-encoding = "2.6" dialoguer = "0.11" digest = "0.10.7" directories-next = "2" -ecdsa_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] } +ecdsa_fun = { version = "0.10", default-features = false, features = [ "libsecp_compat", "serde", "adaptor" ] } ed25519-dalek = "1" futures = { version = "0.3", default-features = false } hex = "0.4" @@ -50,7 +50,7 @@ serde_cbor = "0.11" serde_json = "1" serde_with = { version = "1", features = [ "macros" ] } sha2 = "0.10" -sigma_fun = { git = "https://github.com/LLFourn/secp256kfun", default-features = false, features = [ "ed25519", "serde", "secp256k1", "alloc" ] } +sigma_fun = { version = "0.7", default-features = false, features = [ "ed25519", "serde", "secp256k1", "alloc" ] } sqlx = { version = "0.6.3", features = [ "sqlite", "runtime-tokio-rustls", "offline" ] } structopt = "0.3" strum = { version = "0.26", features = [ "derive" ] } @@ -88,7 +88,6 @@ proptest = "1" sequential-test = "0.2.4" serde_cbor = "0.11" serial_test = "3.0" -spectral = "0.6" tempfile = "3" testcontainers = "0.14" diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index 4083f130..0d6de9a7 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -279,10 +279,10 @@ where SwarmEvent::IncomingConnectionError { send_back_addr: address, error, .. } => { tracing::warn!(%address, "Failed to set up connection with peer: {:#}", error); } - SwarmEvent::ConnectionClosed { peer_id: peer, num_established, endpoint, cause: Some(error) } if num_established == 0 => { + SwarmEvent::ConnectionClosed { peer_id: peer, num_established: 0, endpoint, cause: Some(error) } => { tracing::debug!(%peer, address = %endpoint.get_remote_address(), "Lost connection to peer: {:#}", error); } - SwarmEvent::ConnectionClosed { peer_id: peer, num_established, endpoint, cause: None } if num_established == 0 => { + SwarmEvent::ConnectionClosed { peer_id: peer, num_established: 0, endpoint, cause: None } => { tracing::info!(%peer, address = %endpoint.get_remote_address(), "Successfully closed connection"); } SwarmEvent::NewListenAddr{address, ..} => { @@ -296,7 +296,7 @@ where Some(Ok((peer, transfer_proof, responder))) => { if !self.swarm.behaviour_mut().transfer_proof.is_connected(&peer) { tracing::warn!(%peer, "No active connection to peer, buffering transfer proof"); - self.buffered_transfer_proofs.entry(peer).or_insert_with(Vec::new).push((transfer_proof, responder)); + self.buffered_transfer_proofs.entry(peer).or_default().push((transfer_proof, responder)); continue; } diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index 181ec9bc..7b85f8fb 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -302,7 +302,7 @@ pub mod rendezvous { fn inject_disconnected(&mut self, peer_id: &PeerId) { for i in 0..self.rendezvous_nodes.len() { - let mut node = &mut self.rendezvous_nodes[i]; + let node = &mut self.rendezvous_nodes[i]; if peer_id == &node.peer_id { node.connection_status = ConnectionStatus::Disconnected; } @@ -325,7 +325,7 @@ pub mod rendezvous { _error: &DialError, ) { for i in 0..self.rendezvous_nodes.len() { - let mut node = &mut self.rendezvous_nodes[i]; + let node = &mut self.rendezvous_nodes[i]; if let Some(id) = peer_id { if id == node.peer_id { node.connection_status = ConnectionStatus::Disconnected; diff --git a/swap/src/bitcoin.rs b/swap/src/bitcoin.rs index 556d8453..2d86d303 100644 --- a/swap/src/bitcoin.rs +++ b/swap/src/bitcoin.rs @@ -16,6 +16,7 @@ pub use crate::bitcoin::timelocks::{BlockHeight, ExpiredTimelocks}; pub use ::bitcoin::util::amount::Amount; pub use ::bitcoin::util::psbt::PartiallySignedTransaction; pub use ::bitcoin::{Address, AddressType, Network, Transaction, Txid}; +use bitcoin::secp256k1::ecdsa; pub use ecdsa_fun::adaptor::EncryptedSignature; pub use ecdsa_fun::fun::Scalar; pub use ecdsa_fun::Signature; @@ -25,9 +26,8 @@ pub use wallet::Wallet; pub use wallet::WalletBuilder; use crate::bitcoin::wallet::ScriptStatus; -use ::bitcoin::hashes::hex::ToHex; use ::bitcoin::hashes::Hash; -use ::bitcoin::{secp256k1, Sighash}; +use ::bitcoin::Sighash; use anyhow::{bail, Context, Result}; use bdk::miniscript::descriptor::Wsh; use bdk::miniscript::{Descriptor, Segwitv0}; @@ -206,20 +206,21 @@ pub fn verify_encsig( #[error("encrypted signature is invalid")] pub struct InvalidEncryptedSignature; -pub fn build_shared_output_descriptor(A: Point, B: Point) -> Descriptor { +pub fn build_shared_output_descriptor( + A: Point, + B: Point, +) -> Result> { const MINISCRIPT_TEMPLATE: &str = "c:and_v(v:pk(A),pk_k(B))"; - // NOTE: This shouldn't be a source of error, but maybe it is - let A = ToHex::to_hex(&secp256k1::PublicKey::from(A)); - let B = ToHex::to_hex(&secp256k1::PublicKey::from(B)); - - let miniscript = MINISCRIPT_TEMPLATE.replace('A', &A).replace('B', &B); + let miniscript = MINISCRIPT_TEMPLATE + .replace('A', &A.to_string()) + .replace('B', &B.to_string()); let miniscript = bdk::miniscript::Miniscript::::from_str(&miniscript) .expect("a valid miniscript"); - Descriptor::Wsh(Wsh::new(miniscript).expect("a valid descriptor")) + Ok(Descriptor::Wsh(Wsh::new(miniscript)?)) } pub fn recover(S: PublicKey, sig: Signature, encsig: EncryptedSignature) -> Result { @@ -305,6 +306,13 @@ pub mod bitcoin_address { } } +// Transform the ecdsa der signature bytes into a secp256kfun ecdsa signature type. +pub fn extract_ecdsa_sig(sig: &[u8]) -> Result { + let data = &sig[..sig.len() - 1]; + let sig = ecdsa::Signature::from_der(data)?.serialize_compact(); + Signature::from_bytes(sig).ok_or(anyhow::anyhow!("invalid signature")) +} + /// Bitcoin error codes: https://github.com/bitcoin/bitcoin/blob/97d3500601c1d28642347d014a6de1e38f53ae4e/src/rpc/protocol.h#L23 pub enum RpcErrorCode { /// Transaction or block was rejected by network rules. Error code -26. @@ -378,6 +386,8 @@ mod tests { use super::*; use crate::env::{GetConfig, Regtest}; use crate::protocol::{alice, bob}; + use bitcoin::secp256k1; + use ecdsa_fun::fun::marker::{NonZero, Public}; use rand::rngs::OsRng; use std::matches; use uuid::Uuid; @@ -524,4 +534,16 @@ mod tests { transaction ) } + + #[test] + fn compare_point_hex() { + // secp256kfun Point and secp256k1 PublicKey should have the same bytes and hex representation + let secp = secp256k1::Secp256k1::default(); + let keypair = secp256k1::KeyPair::new(&secp, &mut OsRng); + + let pubkey = keypair.public_key(); + let point: Point<_, Public, NonZero> = Point::from_bytes(pubkey.serialize()).unwrap(); + + assert_eq!(pubkey.to_string(), point.to_string()); + } } diff --git a/swap/src/bitcoin/cancel.rs b/swap/src/bitcoin/cancel.rs index aec3fe38..34612148 100644 --- a/swap/src/bitcoin/cancel.rs +++ b/swap/src/bitcoin/cancel.rs @@ -5,7 +5,8 @@ use crate::bitcoin::{ }; use ::bitcoin::util::sighash::SighashCache; use ::bitcoin::{ - EcdsaSighashType, OutPoint, PackedLockTime, Script, Sequence, Sighash, TxIn, TxOut, Txid, + secp256k1, EcdsaSighashType, OutPoint, PackedLockTime, Script, Sequence, Sighash, TxIn, TxOut, + Txid, }; use anyhow::Result; use bdk::miniscript::Descriptor; @@ -117,8 +118,8 @@ impl TxCancel { A: PublicKey, B: PublicKey, spending_fee: Amount, - ) -> Self { - let cancel_output_descriptor = build_shared_output_descriptor(A.0, B.0); + ) -> Result { + let cancel_output_descriptor = build_shared_output_descriptor(A.0, B.0)?; let tx_in = TxIn { previous_output: tx_lock.as_outpoint(), @@ -148,12 +149,12 @@ impl TxCancel { ) .expect("sighash"); - Self { + Ok(Self { inner: transaction, digest, output_descriptor: cancel_output_descriptor, lock_output_descriptor: tx_lock.output_descriptor.clone(), - } + }) } pub fn txid(&self) -> Txid { @@ -214,25 +215,27 @@ impl TxCancel { let A = ::bitcoin::PublicKey { compressed: true, - inner: A.0.into(), + inner: secp256k1::PublicKey::from_slice(&A.0.to_bytes())?, }; let B = ::bitcoin::PublicKey { compressed: true, - inner: B.0.into(), + inner: secp256k1::PublicKey::from_slice(&B.0.to_bytes())?, }; // The order in which these are inserted doesn't matter + let sig_a = secp256k1::ecdsa::Signature::from_compact(&sig_a.to_bytes())?; + let sig_b = secp256k1::ecdsa::Signature::from_compact(&sig_b.to_bytes())?; satisfier.insert( A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), + sig: sig_a, hash_ty: EcdsaSighashType::All, }, ); satisfier.insert( B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), + sig: sig_b, hash_ty: EcdsaSighashType::All, }, ); diff --git a/swap/src/bitcoin/lock.rs b/swap/src/bitcoin/lock.rs index f8aa9a39..0a9bd8f8 100644 --- a/swap/src/bitcoin/lock.rs +++ b/swap/src/bitcoin/lock.rs @@ -32,7 +32,7 @@ impl TxLock { C: EstimateFeeRate, D: BatchDatabase, { - let lock_output_descriptor = build_shared_output_descriptor(A.0, B.0); + let lock_output_descriptor = build_shared_output_descriptor(A.0, B.0)?; let address = lock_output_descriptor .address(wallet.get_network()) .expect("can derive address from descriptor"); @@ -84,7 +84,7 @@ impl TxLock { } }; - let descriptor = build_shared_output_descriptor(A.0, B.0); + let descriptor = build_shared_output_descriptor(A.0, B.0)?; let legit_shared_output_script = descriptor.script_pubkey(); if shared_output_candidate.script_pubkey != legit_shared_output_script { @@ -263,7 +263,7 @@ mod tests { fn estimated_tx_lock_script_size_never_changes(a in crate::proptest::ecdsa_fun::point(), b in crate::proptest::ecdsa_fun::point()) { proptest::prop_assume!(a != b); - let computed_size = build_shared_output_descriptor(a, b).script_pubkey().len(); + let computed_size = build_shared_output_descriptor(a, b).unwrap().script_pubkey().len(); assert_eq!(computed_size, SCRIPT_SIZE); } diff --git a/swap/src/bitcoin/punish.rs b/swap/src/bitcoin/punish.rs index 247c904f..9d687544 100644 --- a/swap/src/bitcoin/punish.rs +++ b/swap/src/bitcoin/punish.rs @@ -1,7 +1,7 @@ use crate::bitcoin::wallet::Watchable; use crate::bitcoin::{self, Address, Amount, PunishTimelock, Transaction, TxCancel, Txid}; use ::bitcoin::util::sighash::SighashCache; -use ::bitcoin::{EcdsaSighashType, Sighash}; +use ::bitcoin::{secp256k1, EcdsaSighashType, Sighash}; use anyhow::{Context, Result}; use bdk::bitcoin::Script; use bdk::miniscript::Descriptor; @@ -64,18 +64,20 @@ impl TxPunish { let A = a.public().try_into()?; let B = B.try_into()?; + let sig_a = secp256k1::ecdsa::Signature::from_compact(&sig_a.to_bytes())?; + let sig_b = secp256k1::ecdsa::Signature::from_compact(&sig_b.to_bytes())?; // The order in which these are inserted doesn't matter satisfier.insert( A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), + sig: sig_a, hash_ty: EcdsaSighashType::All, }, ); satisfier.insert( B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), + sig: sig_b, hash_ty: EcdsaSighashType::All, }, ); diff --git a/swap/src/bitcoin/redeem.rs b/swap/src/bitcoin/redeem.rs index e91c25ee..a6a55e4b 100644 --- a/swap/src/bitcoin/redeem.rs +++ b/swap/src/bitcoin/redeem.rs @@ -6,7 +6,7 @@ use crate::bitcoin::{ use ::bitcoin::{Sighash, Txid}; use anyhow::{bail, Context, Result}; use bdk::miniscript::Descriptor; -use bitcoin::secp256k1::ecdsa; +use bitcoin::secp256k1; use bitcoin::util::sighash::SighashCache; use bitcoin::{EcdsaSighashType, Script}; use ecdsa_fun::adaptor::{Adaptor, HashTranscript}; @@ -16,6 +16,8 @@ use ecdsa_fun::Signature; use sha2::Sha256; use std::collections::HashMap; +use super::extract_ecdsa_sig; + #[derive(Clone, Debug)] pub struct TxRedeem { inner: Transaction, @@ -64,7 +66,7 @@ impl TxRedeem { ) -> Result { verify_encsig( B, - PublicKey::from(s_a.clone()), + PublicKey::from(s_a), &self.digest(), &encrypted_signature, ) @@ -79,25 +81,27 @@ impl TxRedeem { let A = ::bitcoin::PublicKey { compressed: true, - inner: a.public.into(), + inner: secp256k1::PublicKey::from_slice(&a.public.to_bytes())?, }; let B = ::bitcoin::PublicKey { compressed: true, - inner: B.0.into(), + inner: secp256k1::PublicKey::from_slice(&B.0.to_bytes())?, }; + let sig_a = secp256k1::ecdsa::Signature::from_compact(&sig_a.to_bytes())?; + let sig_b = secp256k1::ecdsa::Signature::from_compact(&sig_b.to_bytes())?; // The order in which these are inserted doesn't matter satisfier.insert( A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), + sig: sig_a, hash_ty: EcdsaSighashType::All, }, ); satisfier.insert( B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), + sig: sig_b, hash_ty: EcdsaSighashType::All, }, ); @@ -120,16 +124,16 @@ impl TxRedeem { let input = match candidate_transaction.input.as_slice() { [input] => input, [] => bail!(NoInputs), - [inputs @ ..] => bail!(TooManyInputs(inputs.len())), + inputs => bail!(TooManyInputs(inputs.len())), }; - let sigs = match input.witness.iter().collect::>().as_slice() { + let sigs = match input.witness.to_vec().as_slice() { [sig_1, sig_2, _script] => [sig_1, sig_2] - .iter() - .map(|sig| ecdsa::Signature::from_der(&sig[..sig.len() - 1]).map(Signature::from)) - .collect::, _>>(), + .into_iter() + .map(|sig| extract_ecdsa_sig(sig)) + .collect::, _>>(), [] => bail!(EmptyWitnessStack), - [witnesses @ ..] => bail!(NotThreeWitnesses(witnesses.len())), + witnesses => bail!(NotThreeWitnesses(witnesses.len())), }?; let sig = sigs diff --git a/swap/src/bitcoin/refund.rs b/swap/src/bitcoin/refund.rs index a73dd0e3..ec9fc802 100644 --- a/swap/src/bitcoin/refund.rs +++ b/swap/src/bitcoin/refund.rs @@ -4,7 +4,7 @@ use crate::bitcoin::{ TooManyInputs, Transaction, TxCancel, }; use crate::{bitcoin, monero}; -use ::bitcoin::secp256k1::ecdsa; +use ::bitcoin::secp256k1; use ::bitcoin::util::sighash::SighashCache; use ::bitcoin::{EcdsaSighashType, Script, Sighash, Txid}; use anyhow::{bail, Context, Result}; @@ -12,6 +12,8 @@ use bdk::miniscript::Descriptor; use ecdsa_fun::Signature; use std::collections::HashMap; +use super::extract_ecdsa_sig; + #[derive(Debug)] pub struct TxRefund { inner: Transaction, @@ -62,25 +64,27 @@ impl TxRefund { let A = ::bitcoin::PublicKey { compressed: true, - inner: A.0.into(), + inner: secp256k1::PublicKey::from_slice(&A.0.to_bytes())?, }; let B = ::bitcoin::PublicKey { compressed: true, - inner: B.0.into(), + inner: secp256k1::PublicKey::from_slice(&B.0.to_bytes())?, }; + let sig_a = secp256k1::ecdsa::Signature::from_compact(&sig_a.to_bytes())?; + let sig_b = secp256k1::ecdsa::Signature::from_compact(&sig_b.to_bytes())?; // The order in which these are inserted doesn't matter satisfier.insert( A, ::bitcoin::EcdsaSig { - sig: sig_a.into(), + sig: sig_a, hash_ty: EcdsaSighashType::All, }, ); satisfier.insert( B, ::bitcoin::EcdsaSig { - sig: sig_b.into(), + sig: sig_b, hash_ty: EcdsaSighashType::All, }, ); @@ -127,16 +131,16 @@ impl TxRefund { let input = match candidate_transaction.input.as_slice() { [input] => input, [] => bail!(NoInputs), - [inputs @ ..] => bail!(TooManyInputs(inputs.len())), + inputs => bail!(TooManyInputs(inputs.len())), }; - let sigs = match input.witness.iter().collect::>().as_slice() { + let sigs = match input.witness.to_vec().as_slice() { [sig_1, sig_2, _script] => [sig_1, sig_2] - .iter() - .map(|sig| ecdsa::Signature::from_der(&sig[..sig.len() - 1]).map(Signature::from)) - .collect::, _>>(), + .into_iter() + .map(|sig| extract_ecdsa_sig(sig)) + .collect::, _>>(), [] => bail!(EmptyWitnessStack), - [witnesses @ ..] => bail!(NotThreeWitnesses(witnesses.len())), + witnesses => bail!(NotThreeWitnesses(witnesses.len())), }?; let sig = sigs diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index 5d8685f3..9748d740 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -65,9 +65,7 @@ impl Wallet { database, ) { Ok(w) => w, - Err(e) if matches!(e, bdk::Error::ChecksumMismatch) => { - Self::migrate(data_dir, xprivkey, network)? - } + Err(bdk::Error::ChecksumMismatch) => Self::migrate(data_dir, xprivkey, network)?, err => err?, }; diff --git a/swap/src/cli/event_loop.rs b/swap/src/cli/event_loop.rs index 23aa0f38..befe1dc5 100644 --- a/swap/src/cli/event_loop.rs +++ b/swap/src/cli/event_loop.rs @@ -168,7 +168,7 @@ impl EventLoop { tracing::info!("Successfully closed connection to Alice"); return; } - SwarmEvent::OutgoingConnectionError { peer_id, error } if matches!(peer_id, Some(alice_peer_id) if alice_peer_id == self.alice_peer_id) => { + SwarmEvent::OutgoingConnectionError { peer_id: Some(alice_peer_id), error } if alice_peer_id == self.alice_peer_id => { tracing::warn!(%error, "Failed to dial Alice"); if let Some(duration) = self.swarm.behaviour_mut().redial.until_next_redial() { diff --git a/swap/src/network/cbor_request_response.rs b/swap/src/network/cbor_request_response.rs index 18e193ee..634dd729 100644 --- a/swap/src/network/cbor_request_response.rs +++ b/swap/src/network/cbor_request_response.rs @@ -19,7 +19,7 @@ pub struct CborCodec { impl Default for CborCodec { fn default() -> Self { Self { - phantom: PhantomData::default(), + phantom: PhantomData, } } } diff --git a/swap/src/network/json_pull_codec.rs b/swap/src/network/json_pull_codec.rs index bf473e84..01fcf494 100644 --- a/swap/src/network/json_pull_codec.rs +++ b/swap/src/network/json_pull_codec.rs @@ -25,7 +25,7 @@ pub struct JsonPullCodec { impl Default for JsonPullCodec { fn default() -> Self { Self { - phantom: PhantomData::default(), + phantom: PhantomData, } } } diff --git a/swap/src/network/test.rs b/swap/src/network/test.rs index a5c316b1..5a324385 100644 --- a/swap/src/network/test.rs +++ b/swap/src/network/test.rs @@ -40,7 +40,7 @@ where .expect("failed to create dh_keys"); let noise = NoiseConfig::xx(dh_keys).into_authenticated(); - let transport = MemoryTransport::default() + let transport = MemoryTransport .or_transport(TokioTcpConfig::new()) .upgrade(Version::V1) .authenticate(noise) diff --git a/swap/src/protocol/alice/state.rs b/swap/src/protocol/alice/state.rs index b34e0326..b4e155a6 100644 --- a/swap/src/protocol/alice/state.rs +++ b/swap/src/protocol/alice/state.rs @@ -310,7 +310,8 @@ impl State2 { self.a.public(), self.B, self.tx_cancel_fee, - ); + ) + .expect("valid cancel tx"); let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address, self.tx_refund_fee); @@ -335,7 +336,7 @@ impl State2 { self.a.public(), self.B, self.tx_cancel_fee, - ); + )?; bitcoin::verify_sig(&self.B, &tx_cancel.digest(), &msg.tx_cancel_sig) .context("Failed to verify cancel transaction")?; let tx_punish = bitcoin::TxPunish::new( @@ -458,6 +459,7 @@ impl State3 { self.B, self.tx_cancel_fee, ) + .expect("valid cancel tx") } pub fn tx_refund(&self) -> TxRefund { diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index edf902b6..aa0045ea 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -243,7 +243,7 @@ impl State1 { self.A, self.b.public(), self.tx_cancel_fee, - ); + )?; let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address, self.tx_refund_fee); @@ -316,7 +316,8 @@ impl State2 { self.A, self.b.public(), self.tx_cancel_fee, - ); + ) + .expect("valid cancel tx"); let tx_cancel_sig = self.b.sign(tx_cancel.digest()); let tx_punish = bitcoin::TxPunish::new( &tx_cancel, @@ -450,7 +451,7 @@ impl State3 { self.A, self.b.public(), self.tx_cancel_fee, - ); + )?; let tx_lock_status = bitcoin_wallet.status_of_script(&self.tx_lock).await?; let tx_cancel_status = bitcoin_wallet.status_of_script(&tx_cancel).await?; @@ -531,7 +532,7 @@ impl State4 { self.A, self.b.public(), self.tx_cancel_fee, - ); + )?; let tx_lock_status = bitcoin_wallet.status_of_script(&self.tx_lock).await?; let tx_cancel_status = bitcoin_wallet.status_of_script(&tx_cancel).await?; @@ -612,7 +613,7 @@ impl State6 { self.A, self.b.public(), self.tx_cancel_fee, - ); + )?; let tx_lock_status = bitcoin_wallet.status_of_script(&self.tx_lock).await?; let tx_cancel_status = bitcoin_wallet.status_of_script(&tx_cancel).await?; @@ -635,7 +636,7 @@ impl State6 { self.A, self.b.public(), self.tx_cancel_fee, - ); + )?; let tx = bitcoin_wallet.get_raw_transaction(tx_cancel.txid()).await?; @@ -652,7 +653,7 @@ impl State6 { self.A, self.b.public(), self.tx_cancel_fee, - ) + )? .complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone()) .context("Failed to complete Bitcoin cancel transaction")?; @@ -675,7 +676,7 @@ impl State6 { self.A, self.b.public(), self.tx_cancel_fee, - ); + )?; let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address, self.tx_refund_fee); From e6d37c01a6bcf30774bb7df40c7babbb15b861a1 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 27 May 2024 11:06:10 +0200 Subject: [PATCH 270/395] ci: fix duplicate definition of check_stable --- .github/workflows/ci.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7619754b..cb869ccf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,22 +31,6 @@ jobs: - name: Run clippy with all features enabled run: cargo clippy --workspace --all-targets --all-features -- -D warnings - check_stable: - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4.1.1 - - - uses: dtolnay/rust-toolchain@stable - - - name: Override rust stable - run: | - rustup override set stable - - - name: Run cargo check on rust stable - run: cargo check --all-targets - - bdk_test: runs-on: ubuntu-latest steps: From bbf8f8431261500c7cabe8070269a86ea8a9846f Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 27 May 2024 12:04:04 +0200 Subject: [PATCH 271/395] ci: fix build-release-binaries --- .github/workflows/build-release-binaries.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index bcd2c806..afa4d580 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -62,17 +62,16 @@ jobs: - uses: dtolnay/rust-toolchain@master with: toolchain: "1.74" - targets: armv7-unknown-linux-gnueabihf + + - name: install armv7 target + if: matrix.target != 'armv7-unknown-linux-gnueabihf' + run: rustup target add armv7-unknown-linux-gnueabihf - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary - uses: actions-rs/cargo@v1 - with: - command: build - args: --target=${{ matrix.target }} --release --package swap --bin ${{ matrix.bin }} - use-cross: true + run: cargo build --target=${{ matrix.target }} --release --package swap --bin ${{ matrix.bin }} - name: Smoke test the binary - if: matrix.target != 'armv7-unknown-linux-gnueabihf' # armv7-unknown-linux-gnueabihf is only cross-compiled, no smoke test + if: matrix.target != 'armv7-unknown-linux-gnueabihf' run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help # Remove once python 3 is the default From 52d56ae254bc537bcf8ac66c0153e6bd0e612953 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 27 May 2024 12:19:13 +0200 Subject: [PATCH 272/395] ci: fix build-release-binaries --- .github/workflows/build-release-binaries.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index afa4d580..252003be 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -6,8 +6,9 @@ on: jobs: build_binaries: - name: Build swap and asb binaries + name: Build strategy: + fail-fast: false matrix: include: - bin: swap @@ -63,11 +64,16 @@ jobs: with: toolchain: "1.74" - - name: install armv7 target - if: matrix.target != 'armv7-unknown-linux-gnueabihf' - run: rustup target add armv7-unknown-linux-gnueabihf + - name: Cross Build ${{ matrix.target }} ${{ matrix.bin }} binary + if: matrix.target == 'armv7-unknown-linux-gnueabihf' + run: | + curl -L "https://github.com/cross-rs/cross/releases/download/v0.2.5/cross-x86_64-unknown-linux-gnu.tar.gz" | tar xzv + sudo mv cross /usr/bin + sudo mv cross-util /usr/bin + cross build --target=${{ matrix.target }} --release --package swap --bin ${{ matrix.bin }} - name: Build ${{ matrix.target }} ${{ matrix.bin }} release binary + if: matrix.target != 'armv7-unknown-linux-gnueabihf' run: cargo build --target=${{ matrix.target }} --release --package swap --bin ${{ matrix.bin }} - name: Smoke test the binary From 268a24083f3cdd2b78734e7c58bb0ea1f1d00f9c Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 27 May 2024 12:57:32 +0200 Subject: [PATCH 273/395] deps: bump miniscript 9.0.0 to 9.0.2 to fix overflow issue --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 435a86bb..982de04c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2513,9 +2513,9 @@ checksum = "0c835948974f68e0bd58636fc6c5b1fbff7b297e3046f11b3b3c18bbac012c6d" [[package]] name = "miniscript" -version = "9.0.0" +version = "9.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123a10aae81d0712ecc09b780f6f0ae0b0f506a5c4c912974725760d59ba073e" +checksum = "e5b106477a0709e2da253e5559ba4ab20a272f8577f1eefff72f3a905b5d35f5" dependencies = [ "bitcoin", "serde", From 6399343de9b1a73d1aa06f8f5d8f42ed76f1afd4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 11:29:09 +0000 Subject: [PATCH 274/395] build(deps): bump serde from 1.0.202 to 1.0.203 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.202 to 1.0.203. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.202...v1.0.203) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 982de04c..f665b39e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3871,9 +3871,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] @@ -3900,9 +3900,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", From 66bc59892a50d906ca38dc93b435106bc66fa3a6 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 28 May 2024 12:21:19 +0200 Subject: [PATCH 275/395] ci: wip fixing build binaries actions --- .github/workflows/build-release-binaries.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 252003be..9299cea4 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -80,11 +80,6 @@ jobs: if: matrix.target != 'armv7-unknown-linux-gnueabihf' run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help - # Remove once python 3 is the default - - uses: actions/setup-python@v5 - with: - python-version: "3.x" - - id: create-archive-name shell: python # Use python to have a prettier name for the archive on Windows. run: | @@ -98,10 +93,13 @@ jobs: archive_name=f'${{ matrix.bin }}_${{ github.event.release.tag_name }}_{os_info.system}_{arch}.${{ matrix.archive_ext }}' - print(f'::set-output name=archive::{archive_name}') + print(f'archive={archive_name} >> $GITHUB_OUTPUT') + + - name: debug + run: tree ./target - name: Pack macos archive - if: matrix.os == 'macos-latest' + if: startsWith(matrix.os, 'macos') shell: bash run: gtar -C ./target/${{ matrix.target }}/release --create --file=${{ steps.create-archive-name.outputs.archive }} ${{ matrix.bin }} From e09401b9f78c856ffd3014f0b8410127b42a279e Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 28 May 2024 12:32:04 +0200 Subject: [PATCH 276/395] ci: wip fixing build binaries actions --- .github/workflows/build-release-binaries.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 9299cea4..8a35a88f 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -93,10 +93,7 @@ jobs: archive_name=f'${{ matrix.bin }}_${{ github.event.release.tag_name }}_{os_info.system}_{arch}.${{ matrix.archive_ext }}' - print(f'archive={archive_name} >> $GITHUB_OUTPUT') - - - name: debug - run: tree ./target + print(f'::set-output name=archive::{archive_name}') - name: Pack macos archive if: startsWith(matrix.os, 'macos') From 41687ffab96bc1aaa22526ed0a7c51ef9cdde1bf Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 29 May 2024 11:58:28 +0200 Subject: [PATCH 277/395] CI: Fix faulty x86-darwin release name (#1658) --- .github/workflows/build-release-binaries.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 8a35a88f..29bdde64 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -22,6 +22,7 @@ jobs: - bin: swap target: x86_64-apple-darwin os: macos-12 + archive_ext: tar - bin: swap target: aarch64-apple-darwin os: macos-latest From 2932abc9ec2475717944afa02aeaad73f3c98f16 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Thu, 30 May 2024 00:00:17 +1000 Subject: [PATCH 278/395] Prepare release 0.13.0 (#1659) --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3e510a9..1fa3bdeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.0] - 2024-05-29 + - Minimum Supported Rust Version (MSRV) bumped to 1.74 - Lowered default Bitcoin confirmation target for Bob to 1 to make sure Bitcoin transactions get confirmed in time - Added support for starting the CLI (using the `start-daemon` subcommand) as a Daemon that accepts JSON-RPC requests @@ -354,7 +356,8 @@ 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.12.3...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...HEAD +[0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 [0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 [0.12.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.1...0.12.2 [0.12.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.0...0.12.1 diff --git a/Cargo.lock b/Cargo.lock index f665b39e..522c7c75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4391,7 +4391,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.12.3" +version = "0.13.0" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 3f9349d6..b37570ba 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.12.3" +version = "0.13.0" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From 1930540c1f6b599d34786372bf3c0afb46d34f39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 10:27:48 +0200 Subject: [PATCH 279/395] build(deps): bump reqwest from 0.11.27 to 0.12.4 (#1588) * build(deps): bump reqwest from 0.11.27 to 0.12.0 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.11.27 to 0.12.0. - [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.27...v0.12.0) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * wip * wip * ci: lock sqlx-cli install * bump reqwest to 0.12.2 * deps: reqwest to 0.12.4 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Byron Hambly --- Cargo.lock | 262 +++++++++++++++++++++++--------------- Cargo.toml | 2 + monero-harness/Cargo.toml | 2 +- monero-rpc/Cargo.toml | 2 +- monero-wallet/Cargo.toml | 2 +- swap/Cargo.toml | 6 +- 6 files changed, 165 insertions(+), 111 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 522c7c75..298978fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,12 +267,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -396,19 +390,21 @@ dependencies = [ [[package]] name = "bitcoin-harness" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b6a18713ec8acbc96d1e843f6998f00e8c5d81173e38760023b84926b8db3b8" +version = "0.2.1" +source = "git+https://github.com/delta1/bitcoin-harness-rs.git?rev=80cc8d05db2610d8531011be505b7bee2b5cdf9f#80cc8d05db2610d8531011be505b7bee2b5cdf9f" dependencies = [ "base64 0.12.3", "bitcoin", "bitcoincore-rpc-json", "futures", "hex", + "hmac 0.12.1", "jsonrpc_client", + "rand 0.8.3", "reqwest", "serde", "serde_json", + "sha2 0.10.8", "testcontainers", "thiserror", "tokio", @@ -496,11 +492,10 @@ dependencies = [ [[package]] name = "bollard-stubs" -version = "1.41.0" +version = "1.42.0-rc.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed2f2e73fffe9455141e170fb9c1feb0ac521ec7e7dcd47a7cab72a658490fb8" +checksum = "ed59b5c00048f48d7af971b71f800fdf23e858844a6f9e4d32ca72e9399e7864" dependencies = [ - "chrono", "serde", "serde_with", ] @@ -656,21 +651,21 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chacha20" -version = "0.7.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f08493fa7707effc63254c66c6ea908675912493cd67952eda23c09fae2610b1" +checksum = "fee7ad89dc1128635074c268ee661f90c3f7e83d9fd12910608c36b47d6c3412" dependencies = [ "cfg-if 1.0.0", "cipher", - "cpufeatures 0.2.1", + "cpufeatures 0.1.4", "zeroize", ] [[package]] name = "chacha20poly1305" -version = "0.8.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6547abe025f4027edacd9edaa357aded014eecec42a5070d9b885c3c334aba2" +checksum = "1580317203210c517b6d44794abfbe600698276db18127e37ad3e69bf5e848e5" dependencies = [ "aead", "chacha20", @@ -688,8 +683,6 @@ dependencies = [ "libc", "num-integer", "num-traits", - "serde", - "time 0.1.43", "winapi", ] @@ -945,9 +938,9 @@ dependencies = [ [[package]] name = "crypto-mac" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d1a86f49236c215f271d40892d5fc950490551400b02ef360692c29815c714" +checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e" dependencies = [ "generic-array", "subtle", @@ -1197,15 +1190,6 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -[[package]] -name = "encoding_rs" -version = "0.8.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "enum-as-inner" version = "0.3.3" @@ -1553,6 +1537,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51ee2dd2e4f378392eeff5d51618cd9a63166a2513846bbc55f21cfacd9199d4" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.0.0", + "indexmap 2.1.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "1.7.1" @@ -1649,7 +1652,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b" dependencies = [ - "crypto-mac 0.11.1", + "crypto-mac 0.11.0", "digest 0.9.0", ] @@ -1715,6 +1718,19 @@ dependencies = [ "http 1.0.0", ] +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http 1.0.0", + "http-body 1.0.0", + "pin-project-lite 0.2.13", +] + [[package]] name = "httparse" version = "1.8.0" @@ -1737,14 +1753,13 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.18", "http 0.2.11", "http-body 0.4.0", "httparse", "httpdate", "itoa", "pin-project-lite 0.2.13", - "socket2 0.5.5", "tokio", "tower-service", "tracing", @@ -1758,22 +1773,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", + "futures-channel", + "futures-util", + "h2 0.4.3", "http 1.0.0", "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite 0.2.13", + "smallvec", "tokio", + "want", ] [[package]] name = "hyper-rustls" -version = "0.24.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" +checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" dependencies = [ - "http 0.2.11", - "hyper 0.14.28", - "rustls 0.21.10", + "futures-util", + "http 1.0.0", + "hyper 1.3.1", + "hyper-util", + "rustls 0.22.2", + "rustls-pki-types", "tokio", - "tokio-rustls 0.24.0", + "tokio-rustls 0.25.0", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite 0.2.13", + "socket2 0.5.5", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1927,8 +1974,7 @@ dependencies = [ [[package]] name = "jsonrpc_client" version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c1ec33c537dc1d5a8b597313db6d213fee54320f81ea0d19b0c3869b282e1a" +source = "git+https://github.com/delta1/rust-jsonrpc-client.git?rev=3b6081697cd616c952acb9c2f02d546357d35506#3b6081697cd616c952acb9c2f02d546357d35506" dependencies = [ "async-trait", "jsonrpc_client_macro", @@ -1941,8 +1987,7 @@ dependencies = [ [[package]] name = "jsonrpc_client_macro" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c11e429f0eaa41fe659013680b459d2368d8f0a3e69dccfb7a35800b0dc27b" +source = "git+https://github.com/delta1/rust-jsonrpc-client.git?rev=3b6081697cd616c952acb9c2f02d546357d35506#3b6081697cd616c952acb9c2f02d546357d35506" dependencies = [ "quote", "syn 1.0.109", @@ -3397,20 +3442,21 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.27" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "bytes", - "encoding_rs", "futures-core", "futures-util", - "h2", - "http 0.2.11", - "http-body 0.4.0", - "hyper 0.14.28", + "h2 0.4.3", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", "hyper-rustls", + "hyper-util", "ipnet", "js-sys", "log", @@ -3418,15 +3464,15 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.13", - "rustls 0.21.10", - "rustls-pemfile", + "rustls 0.22.2", + "rustls-pemfile 2.1.2", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-rustls 0.24.0", + "tokio-rustls 0.25.0", "tokio-socks", "tokio-util", "tower-service", @@ -3435,8 +3481,8 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.25.3", - "winreg 0.50.0", + "webpki-roots 0.26.1", + "winreg 0.52.0", ] [[package]] @@ -3598,14 +3644,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" dependencies = [ "log", "ring 0.17.3", + "rustls-pki-types", "rustls-webpki", - "sct 0.7.0", + "subtle", + "zeroize", ] [[package]] @@ -3627,7 +3675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile", + "rustls-pemfile 1.0.0", "schannel", "security-framework", ] @@ -3642,12 +3690,29 @@ dependencies = [ ] [[package]] -name = "rustls-webpki" -version = "0.101.7" +name = "rustls-pemfile" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" + +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" dependencies = [ "ring 0.17.3", + "rustls-pki-types", "untrusted 0.9.0", ] @@ -4111,9 +4176,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "snow" @@ -4251,7 +4316,7 @@ dependencies = [ "paste", "percent-encoding", "rustls 0.20.2", - "rustls-pemfile", + "rustls-pemfile 1.0.0", "serde", "sha2 0.10.8", "smallvec", @@ -4379,9 +4444,9 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "subtle-ng" @@ -4508,27 +4573,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "tempfile" version = "3.10.1" @@ -4553,9 +4597,9 @@ dependencies = [ [[package]] name = "testcontainers" -version = "0.14.0" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e2b1567ca8a2b819ea7b28c92be35d9f76fb9edb214321dcc86eb96023d1f87" +checksum = "f83d2931d7f521af5bae989f716c3fa43a6af9af7ec7a5e21b59ae40878cec00" dependencies = [ "bollard-stubs", "futures", @@ -4727,11 +4771,12 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.24.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" +checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.21.10", + "rustls 0.22.2", + "rustls-pki-types", "tokio", ] @@ -4871,6 +4916,11 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ + "futures-core", + "futures-util", + "pin-project 1.0.5", + "pin-project-lite 0.2.13", + "tokio", "tower-layer", "tower-service", "tracing", @@ -5435,9 +5485,12 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" +dependencies = [ + "rustls-pki-types", +] [[package]] name = "which" @@ -5672,9 +5725,9 @@ dependencies = [ [[package]] name = "winreg" -version = "0.50.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if 1.0.0", "windows-sys 0.48.0", @@ -5718,23 +5771,22 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.2.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a974bcdd357f0dca4d41677db03436324d45a4c9ed2d0b873a5a360ce41c36" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.0.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f369ddb18862aba61aa49bf31e74d29f0f162dec753063200e1dc084345d16" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", - "synstructure", + "syn 2.0.46", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ab29e919..c3d131a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,4 +3,6 @@ resolver = "2" members = [ "monero-harness", "monero-rpc", "swap", "monero-wallet" ] [patch.crates-io] +# patch until new release https://github.com/thomaseizinger/rust-jsonrpc-client/pull/51 +jsonrpc_client = { git = "https://github.com/delta1/rust-jsonrpc-client.git", rev = "3b6081697cd616c952acb9c2f02d546357d35506" } monero = { git = "https://github.com/comit-network/monero-rs", rev = "818f38b" } diff --git a/monero-harness/Cargo.toml b/monero-harness/Cargo.toml index a4c9ce72..1151f47a 100644 --- a/monero-harness/Cargo.toml +++ b/monero-harness/Cargo.toml @@ -10,7 +10,7 @@ anyhow = "1" futures = "0.3" monero-rpc = { path = "../monero-rpc" } rand = "0.7" -testcontainers = "0.14" +testcontainers = "0.15" tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "macros" ] } tracing = "0.1" tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "tracing-log" ] } diff --git a/monero-rpc/Cargo.toml b/monero-rpc/Cargo.toml index 6da1e88a..18843745 100644 --- a/monero-rpc/Cargo.toml +++ b/monero-rpc/Cargo.toml @@ -12,7 +12,7 @@ jsonrpc_client = { version = "0.7", features = [ "reqwest" ] } monero = "0.12" monero-epee-bin-serde = "1" rand = "0.7" -reqwest = { version = "0.11", default-features = false, features = [ "json" ] } +reqwest = { version = "0.12", default-features = false, features = [ "json" ] } rust_decimal = { version = "1", features = [ "serde-float" ] } serde = { version = "1.0", features = [ "derive" ] } serde_json = "1.0" diff --git a/monero-wallet/Cargo.toml b/monero-wallet/Cargo.toml index 81982c83..99bd3f4d 100644 --- a/monero-wallet/Cargo.toml +++ b/monero-wallet/Cargo.toml @@ -14,6 +14,6 @@ rand = "0.7" curve25519-dalek = "3" monero-harness = { path = "../monero-harness" } rand = "0.7" -testcontainers = "0.14" +testcontainers = "0.15" tokio = { version = "1", features = [ "rt-multi-thread", "time", "macros", "sync", "process", "fs" ] } tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "chrono", "tracing-log" ] } diff --git a/swap/Cargo.toml b/swap/Cargo.toml index b37570ba..efcc736e 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -42,7 +42,7 @@ proptest = "1" qrcode = "0.14" rand = "0.8" rand_chacha = "0.3" -reqwest = { version = "0.11", features = [ "rustls-tls", "stream", "socks" ], default-features = false } +reqwest = { version = "0.12", features = [ "http2", "rustls-tls", "stream", "socks" ], default-features = false } rust_decimal = { version = "1", features = [ "serde-float" ] } rust_decimal_macros = "1" serde = { version = "1", features = [ "derive" ] } @@ -77,7 +77,7 @@ tokio-tar = "0.3" zip = "0.5" [dev-dependencies] -bitcoin-harness = "0.2.2" +bitcoin-harness = { git = "https://github.com/delta1/bitcoin-harness-rs.git", rev = "80cc8d05db2610d8531011be505b7bee2b5cdf9f" } get-port = "3" hyper = "1.3" jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } @@ -89,7 +89,7 @@ sequential-test = "0.2.4" serde_cbor = "0.11" serial_test = "3.0" tempfile = "3" -testcontainers = "0.14" +testcontainers = "0.15" [build-dependencies] anyhow = "1" From 9635c0b5513c6fa08820e4e5bc40596874b52444 Mon Sep 17 00:00:00 2001 From: pokkst <47200567+pokkst@users.noreply.github.com> Date: Tue, 4 Jun 2024 05:49:15 -0500 Subject: [PATCH 280/395] fix (Bob): Check if Bitcoin redeem transaction was published before transitioning to CancelTimelockExpired (#1427) * fix (Bob): Check if Bitcoin redeem transaction was published before transitioning to CancelTimelockExpired --------- Co-authored-by: binarybaron <86064887+binarybaron@users.noreply.github.com> Co-authored-by: Byron Hambly --- .github/workflows/ci.yml | 1 + swap/src/protocol/bob/state.rs | 21 +++++++++ swap/src/protocol/bob/swap.rs | 14 ++++++ ...ath_bob_offline_while_alice_redeems_btc.rs | 44 +++++++++++++++++++ swap/tests/harness/mod.rs | 4 ++ 5 files changed, 84 insertions(+) create mode 100644 swap/tests/happy_path_bob_offline_while_alice_redeems_btc.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb869ccf..629e4e37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -164,6 +164,7 @@ jobs: ensure_same_swap_id, concurrent_bobs_before_xmr_lock_proof_sent, alice_manually_redeems_after_enc_sig_learned, + happy_path_bob_offline_while_alice_redeems_btc, ] runs-on: ubuntu-latest steps: diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index aa0045ea..58c1d723 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -489,6 +489,27 @@ pub struct State4 { } impl State4 { + pub async fn check_for_tx_redeem(&self, bitcoin_wallet: &bitcoin::Wallet) -> Result { + let tx_redeem = + bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address, self.tx_redeem_fee); + let tx_redeem_encsig = self.b.encsign(self.S_a_bitcoin, tx_redeem.digest()); + + let tx_redeem_candidate = bitcoin_wallet.get_raw_transaction(tx_redeem.txid()).await?; + + let tx_redeem_sig = + tx_redeem.extract_signature_by_key(tx_redeem_candidate, self.b.public())?; + let s_a = bitcoin::recover(self.S_a_bitcoin, tx_redeem_sig, tx_redeem_encsig)?; + let s_a = monero::private_key_from_secp256k1_scalar(s_a.into()); + + Ok(State5 { + s_a, + s_b: self.s_b, + v: self.v, + tx_lock: self.tx_lock.clone(), + monero_wallet_restore_blockheight: self.monero_wallet_restore_blockheight, + }) + } + pub fn tx_redeem_encsig(&self) -> bitcoin::EncryptedSignature { let tx_redeem = bitcoin::TxRedeem::new(&self.tx_lock, &self.redeem_address, self.tx_redeem_fee); diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 37a6b65a..8eaa1489 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -183,6 +183,13 @@ async fn next_state( } } BobState::XmrLocked(state) => { + // In case we send the encrypted signature to Alice, but she doesn't give us a confirmation + // We need to check if she still published the Bitcoin redeem transaction + // Otherwise we risk staying stuck in "XmrLocked" + if let Ok(state5) = state.check_for_tx_redeem(bitcoin_wallet).await { + return Ok(BobState::BtcRedeemed(state5)); + } + let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await; if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? { @@ -207,6 +214,13 @@ async fn next_state( } } BobState::EncSigSent(state) => { + // We need to make sure that Alice did not publish the redeem transaction while we were offline + // Even if the cancel timelock expired, if Alice published the redeem transaction while we were away we cannot miss it + // If we do we cannot refund and will never be able to leave the "CancelTimelockExpired" state + if let Ok(state5) = state.check_for_tx_redeem(bitcoin_wallet).await { + return Ok(BobState::BtcRedeemed(state5)); + } + let tx_lock_status = bitcoin_wallet.subscribe_to(state.tx_lock.clone()).await; if let ExpiredTimelocks::None { .. } = state.expired_timelock(bitcoin_wallet).await? { diff --git a/swap/tests/happy_path_bob_offline_while_alice_redeems_btc.rs b/swap/tests/happy_path_bob_offline_while_alice_redeems_btc.rs new file mode 100644 index 00000000..c958c4f0 --- /dev/null +++ b/swap/tests/happy_path_bob_offline_while_alice_redeems_btc.rs @@ -0,0 +1,44 @@ +pub mod harness; + +use crate::harness::bob_run_until::is_encsig_sent; +use swap::asb::FixedRate; +use swap::protocol::bob::BobState; +use swap::protocol::{alice, bob}; +use tokio::join; + +#[tokio::test] +async fn given_bob_restarts_while_alice_redeems_btc() { + harness::setup_test(harness::SlowCancelConfig, |mut ctx| async move { + let (bob_swap, bob_handle) = ctx.bob_swap().await; + let swap_id = bob_swap.id; + + let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_encsig_sent)); + + let alice_swap = ctx.alice_next_swap().await; + let alice_swap = tokio::spawn(alice::run(alice_swap, FixedRate::default())); + + let (bob_state, alice_state) = join!(bob_swap, alice_swap); + ctx.assert_alice_redeemed(alice_state??).await; + assert!(matches!(bob_state??, BobState::EncSigSent { .. })); + + let (bob_swap, _) = ctx.stop_and_resume_bob_from_db(bob_handle, swap_id).await; + + if let BobState::EncSigSent(state4) = bob_swap.state.clone() { + bob_swap + .bitcoin_wallet + .subscribe_to(state4.tx_lock) + .await + .wait_until_confirmed_with(state4.cancel_timelock) + .await?; + } else { + panic!("Bob in unexpected state {}", bob_swap.state); + } + + // Restart Bob + let bob_state = bob::run(bob_swap).await?; + ctx.assert_bob_redeemed(bob_state).await; + + Ok(()) + }) + .await; +} diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index c099376d..025b7e42 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -996,6 +996,10 @@ pub mod alice_run_until { pub fn is_encsig_learned(state: &AliceState) -> bool { matches!(state, AliceState::EncSigLearned { .. }) } + + pub fn is_btc_redeemed(state: &AliceState) -> bool { + matches!(state, AliceState::BtcRedeemed { .. }) + } } pub mod bob_run_until { From 16d5ffc07e92b68010f53e38617042dce87856e8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Jun 2024 11:31:51 +0000 Subject: [PATCH 281/395] build(deps): bump toml from 0.8.13 to 0.8.14 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.13 to 0.8.14. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.13...toml-v0.8.14) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 298978fc..5633899a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.13", + "toml 0.8.14", ] [[package]] @@ -4520,7 +4520,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.13", + "toml 0.8.14", "torut", "tracing", "tracing-appender", @@ -4860,9 +4860,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e43f8cc456c9704c851ae29c67e17ef65d2c30017c17a9765b89c382dc8bba" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", @@ -4881,9 +4881,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.13" +version = "0.22.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c" +checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" dependencies = [ "indexmap 2.1.0", "serde", From 49a7f7eed6fbfa0c4b5b09c431e13dd4dc30ecbd Mon Sep 17 00:00:00 2001 From: chengehe Date: Thu, 6 Jun 2024 19:10:19 +0900 Subject: [PATCH 282/395] chore: remove repeat word (#1671) Signed-off-by: chengehe --- docs/asb/README.md | 2 +- swap/src/asb/recovery/cancel.rs | 2 +- swap/src/monero/wallet_rpc.rs | 2 +- swap/src/protocol/bob/swap.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/asb/README.md b/docs/asb/README.md index b1acc877..88448b71 100644 --- a/docs/asb/README.md +++ b/docs/asb/README.md @@ -110,7 +110,7 @@ The minimum and maximum amount as well as a spread, that is added on top of the In order to be able to trade, the ASB must define a price to be able to agree on the amounts to be swapped with a CLI. The `XMR<>BTC` price is currently determined by the price from the central exchange Kraken. Upon startup the ASB connects to the Kraken price websocket and listens on the stream for price updates. -You can plug in a different price ticker websocket using the the `price_ticker_ws_url` configuration option. +You can plug in a different price ticker websocket using the `price_ticker_ws_url` configuration option. You will have to make sure that the format returned is the same as the format used by Kraken. Currently, we use a spot-price model, i.e. the ASB dictates the price to the CLI. diff --git a/swap/src/asb/recovery/cancel.rs b/swap/src/asb/recovery/cancel.rs index ec70a8df..8da1508f 100644 --- a/swap/src/asb/recovery/cancel.rs +++ b/swap/src/asb/recovery/cancel.rs @@ -39,7 +39,7 @@ pub async fn cancel( | AliceState::BtcRedeemed | AliceState::XmrRefunded | AliceState::BtcPunished - | AliceState::SafelyAborted => bail!("Swap is is in state {} which is not cancelable", state), + | AliceState::SafelyAborted => bail!("Swap is in state {} which is not cancelable", state), }; let txid = match state3.submit_tx_cancel(bitcoin_wallet.as_ref()).await { diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index 8af1167e..f99994df 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -369,7 +369,7 @@ impl WalletRpc { } // If we do not hear from the monero_wallet_rpc process for 3 seconds we assume - // it is is ready + // it is ready #[cfg(target_os = "windows")] while let Ok(line) = tokio::time::timeout(std::time::Duration::from_secs(3), reader.next_line()).await diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 8eaa1489..a1dec289 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -258,7 +258,7 @@ async fn next_state( // might not be able to ever transfer the Monero. tracing::warn!("Failed to generate monero wallet from keys: {:#}", e); tracing::info!(%wallet_file_name, - "Falling back to trying to open the the wallet if it already exists", + "Falling back to trying to open the wallet if it already exists", ); monero_wallet.open(wallet_file_name).await?; } From b99978879d51775f0572b3676e025561bff65153 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:25:09 +0000 Subject: [PATCH 283/395] build(deps): bump tokio from 1.37.0 to 1.38.0 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.37.0 to 1.38.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.37.0...tokio-1.38.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5633899a..3a826beb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4719,9 +4719,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -4738,9 +4738,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", From 55b67d31d41b7bff29aa515408fc22a8894e3183 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:19:54 +0200 Subject: [PATCH 284/395] feat (Bob): Log extensive information about deposit requirements --- swap/src/api/request.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index 02bf27e1..338432c3 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -882,19 +882,24 @@ where loop { let min_outstanding = bid_quote.min_quantity - max_giveable; - let min_fee = estimate_fee(min_outstanding).await?; - let min_deposit = min_outstanding + min_fee; + let min_bitcoin_lock_tx_fee = estimate_fee(min_outstanding).await?; + let min_deposit_until_swap_will_start = min_outstanding + min_bitcoin_lock_tx_fee; + let max_deposit_until_maximum_amount_is_reached = + maximum_amount - max_giveable + min_bitcoin_lock_tx_fee; tracing::info!( "Deposit at least {} to cover the min quantity with fee!", - min_deposit + min_deposit_until_swap_will_start ); tracing::info!( %deposit_address, - %min_deposit, + %min_deposit_until_swap_will_start, + %max_deposit_until_maximum_amount_is_reached, %max_giveable, %minimum_amount, %maximum_amount, + %min_bitcoin_lock_tx_fee, + price = %bid_quote.price, "Waiting for Bitcoin deposit", ); @@ -913,7 +918,7 @@ where tracing::info!(%new_balance, %max_giveable, "Received Bitcoin"); if max_giveable < bid_quote.min_quantity { - tracing::info!("Deposited amount is less than `min_quantity`"); + tracing::info!("Deposited amount is not enough to cover `min_quantity` when accounting for network fees"); continue; } From 90494ba4a51c982e7bd898f02fd155b0974d721a Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 10 Jun 2024 18:53:52 +0200 Subject: [PATCH 285/395] fix: monero wallet refresh (#1596) This PR changes the following behaviour in the refresh functionality of the monero wallet - Allows for multiple retries because in some cases users have experienced an issue where the wallet rpc returns `no connection to daemon` even though the daemon is available. I'm not 100% sure why this happens but retrying often fixes the issue - Print the current sync height after each failed attempt at syncing to see how far we've come - The `monero-wallet-rpc` is started with the `--no-initial-sync` flag which ensures that as soon as it's started, it's ready to respond to requests - The `monero-wallet-rpc` was upgraded to `v0.18.3.1` because this PR https://github.com/monero-project/monero/pull/8941 has improved some of the issues mentioned above This PR is part of a larger effort to fix this issue https://github.com/comit-network/xmr-btc-swap/issues/1432 --- CHANGELOG.md | 2 ++ monero-rpc/src/wallet.rs | 6 ++++ swap/src/monero/wallet.rs | 67 ++++++++++++++++++++++++++++++----- swap/src/monero/wallet_rpc.rs | 1 + swap/src/protocol/bob/swap.rs | 2 +- swap/tests/harness/mod.rs | 2 +- 6 files changed, 69 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fa3bdeb..4b0ab63e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Add retry logic to monero-wallet-rpc wallet refresh + ## [0.13.0] - 2024-05-29 - Minimum Supported Rust Version (MSRV) bumped to 1.74 diff --git a/monero-rpc/src/wallet.rs b/monero-rpc/src/wallet.rs index bc78e7a6..3e21ad1b 100644 --- a/monero-rpc/src/wallet.rs +++ b/monero-rpc/src/wallet.rs @@ -162,6 +162,12 @@ pub struct BlockHeight { pub height: u32, } +impl fmt::Display for BlockHeight { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.height) + } +} + #[derive(Clone, Copy, Debug, Deserialize)] #[serde(from = "CheckTxKeyResponse")] pub struct CheckTxKey { diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 56fd8e60..99fa206a 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -45,6 +45,7 @@ impl Wallet { pub async fn connect(client: wallet::Client, name: String, env_config: Config) -> Result { let main_address = monero::Address::from_str(client.get_address(0).await?.address.as_str())?; + Ok(Self { inner: Mutex::new(client), network: env_config.monero_network, @@ -125,13 +126,14 @@ impl Wallet { let temp_wallet_address = Address::standard(self.network, public_spend_key, public_view_key); - let wallet = self.inner.lock().await; - // Close the default wallet before generating the other wallet to ensure that // it saves its state correctly - let _ = wallet.close_wallet().await?; + let _ = self.inner.lock().await.close_wallet().await?; - let _ = wallet + let _ = self + .inner + .lock() + .await .generate_from_keys( file_name, temp_wallet_address.to_string(), @@ -144,8 +146,14 @@ impl Wallet { .await?; // Try to send all the funds from the generated wallet to the default wallet - match wallet.refresh().await { - Ok(_) => match wallet.sweep_all(self.main_address.to_string()).await { + match self.refresh(3).await { + Ok(_) => match self + .inner + .lock() + .await + .sweep_all(self.main_address.to_string()) + .await + { Ok(sweep_all) => { for tx in sweep_all.tx_hash_list { tracing::info!( @@ -166,7 +174,12 @@ impl Wallet { } } - let _ = wallet.open_wallet(self.name.clone()).await?; + let _ = self + .inner + .lock() + .await + .open_wallet(self.name.clone()) + .await?; Ok(()) } @@ -261,8 +274,44 @@ impl Wallet { self.main_address } - pub async fn refresh(&self) -> Result { - Ok(self.inner.lock().await.refresh().await?) + pub async fn refresh(&self, max_attempts: usize) -> Result { + const RETRY_INTERVAL: Duration = Duration::from_secs(1); + + for i in 1..=max_attempts { + tracing::info!(name = %self.name, attempt=i, "Syncing Monero wallet"); + + let result = self.inner.lock().await.refresh().await; + + match result { + Ok(refreshed) => { + tracing::info!(name = %self.name, "Monero wallet synced"); + return Ok(refreshed); + } + Err(error) => { + let attempts_left = max_attempts - i; + + // We would not want to fail here if the height is not available + // as it is not critical for the operation of the wallet. + // We can just log a warning and continue. + let height = match self.inner.lock().await.get_height().await { + Ok(height) => height.to_string(), + Err(_) => { + tracing::warn!(name = %self.name, "Failed to fetch Monero wallet height during sync"); + "unknown".to_string() + } + }; + + tracing::warn!(attempt=i, %height, %attempts_left, name = %self.name, %error, "Failed to sync Monero wallet"); + + if attempts_left == 0 { + return Err(error.into()); + } + } + } + + tokio::time::sleep(RETRY_INTERVAL).await; + } + unreachable!("Loop should have returned by now"); } } diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index f99994df..c7009993 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -352,6 +352,7 @@ impl WalletRpc { .arg("--disable-rpc-login") .arg("--wallet-dir") .arg(self.working_dir.join("monero-data")) + .arg("--no-initial-sync") .spawn()?; let stdout = child diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index a1dec289..3900a17b 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -264,7 +264,7 @@ async fn next_state( } // Ensure that the generated wallet is synced so we have a proper balance - monero_wallet.refresh().await?; + monero_wallet.refresh(20).await?; // Sweep (transfer all funds) to the given address let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?; diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 025b7e42..24083a71 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -891,7 +891,7 @@ impl Wallet for monero::Wallet { type Amount = monero::Amount; async fn refresh(&self) -> Result<()> { - self.refresh().await?; + self.refresh(1).await?; Ok(()) } From a3b1e772b2700ce0b4b8f2d932c84b9902fd9f11 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Tue, 11 Jun 2024 04:23:50 +1000 Subject: [PATCH 286/395] Prepare release 0.13.1 (#1675) --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b0ab63e..e2c930c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.1] - 2024-06-10 + - Add retry logic to monero-wallet-rpc wallet refresh ## [0.13.0] - 2024-05-29 @@ -358,7 +360,8 @@ 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.13.0...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...HEAD +[0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 [0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 [0.12.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.1...0.12.2 diff --git a/Cargo.lock b/Cargo.lock index 3a826beb..955142f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4456,7 +4456,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.13.0" +version = "0.13.1" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index efcc736e..0d2f70c9 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.13.0" +version = "0.13.1" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From 122aee022a8cd7e1db6d052a1b749d7bdc6f562e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Jun 2024 11:53:20 +0000 Subject: [PATCH 287/395] build(deps): bump actions/checkout from 4.1.6 to 4.1.7 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.6 to 4.1.7. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.6...v4.1.7) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 29bdde64..662e3a5e 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -54,7 +54,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 629e4e37..6b3fdbf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: Swatinem/rust-cache@v2.7.3 @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: Swatinem/rust-cache@v2.7.3 @@ -131,7 +131,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: Swatinem/rust-cache@v2.7.3 @@ -169,7 +169,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: Swatinem/rust-cache@v2.7.3 @@ -180,7 +180,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: Swatinem/rust-cache@v2.7.3 @@ -191,7 +191,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.6 + uses: actions/checkout@v4.1.7 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 2e52519a..443c4418 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 09df0bd7..74ff34ba 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index 63ecfe6f..ccd7e641 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.6 + - uses: actions/checkout@v4.1.7 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From f4792174da1c34022a06b0ceee6b543d951d2e4d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:45:28 +0000 Subject: [PATCH 288/395] build(deps): bump reqwest from 0.12.4 to 0.12.5 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.12.4 to 0.12.5. - [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.12.4...v0.12.5) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 93 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 955142f1..9a248e5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1788,19 +1788,20 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.0.0", "hyper 1.3.1", "hyper-util", - "rustls 0.22.2", + "rustls 0.23.10", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tower-service", + "webpki-roots 0.26.1", ] [[package]] @@ -2837,9 +2838,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -3271,6 +3272,53 @@ dependencies = [ "pin-project-lite 0.1.12", ] +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite 0.2.13", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.10", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand 0.8.3", + "ring 0.17.3", + "rustc-hash", + "rustls 0.23.10", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2 0.5.5", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.35" @@ -3442,9 +3490,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", @@ -3464,7 +3512,8 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite 0.2.13", - "rustls 0.22.2", + "quinn", + "rustls 0.23.10", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", @@ -3472,7 +3521,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tokio-socks", "tokio-util", "tower-service", @@ -3644,11 +3693,11 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.23.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" dependencies = [ - "log", + "once_cell", "ring 0.17.3", "rustls-pki-types", "rustls-webpki", @@ -3701,15 +3750,15 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" dependencies = [ "ring 0.17.3", "rustls-pki-types", @@ -4557,9 +4606,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "0.1.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" [[package]] name = "synstructure" @@ -4771,11 +4820,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.25.0" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.22.2", + "rustls 0.23.10", "rustls-pki-types", "tokio", ] From 7da996ab7be4136f5d53c8758557c7367ba4796c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:34:57 +0000 Subject: [PATCH 289/395] build(deps): bump url from 2.5.0 to 2.5.2 Bumps [url](https://github.com/servo/rust-url) from 2.5.0 to 2.5.2. - [Release notes](https://github.com/servo/rust-url/releases) - [Commits](https://github.com/servo/rust-url/compare/v2.5.0...v2.5.2) --- updated-dependencies: - dependency-name: url dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a248e5b..2c673099 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5299,9 +5299,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna 0.5.0", From 543f2748b5942cc7f83c3da7ec7cb5aa54074dd6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:35:30 +0000 Subject: [PATCH 290/395] build(deps): bump serial_test from 3.0.0 to 3.1.1 Bumps [serial_test](https://github.com/palfrey/serial_test) from 3.0.0 to 3.1.1. - [Release notes](https://github.com/palfrey/serial_test/releases) - [Commits](https://github.com/palfrey/serial_test/compare/v3.0.0...v3.1.1) --- updated-dependencies: - dependency-name: serial_test dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 38 +++++++++++++++++++++----------------- swap/Cargo.toml | 2 +- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a248e5b..a9ed4569 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1017,17 +1017,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "dashmap" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8858831f7781322e539ea39e72449c46b059638250c14344fec8d0aa6e539c" -dependencies = [ - "cfg-if 1.0.0", - "num_cpus", - "parking_lot 0.12.0", -] - [[package]] name = "data-encoding" version = "2.6.0" @@ -3800,6 +3789,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "scc" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ad2bbb0ae5100a07b7a6f2ed7ab5fd0045551a4c507989b7a620046ea3efdc" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.19" @@ -3836,6 +3834,12 @@ dependencies = [ "untrusted 0.7.1", ] +[[package]] +name = "sdd" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" + [[package]] name = "seahash" version = "4.1.0" @@ -4079,23 +4083,23 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "953ad9342b3aaca7cb43c45c097dd008d4907070394bd0751a0aa8817e5a018d" +checksum = "4b4b487fe2acf240a021cf57c6b2b4903b1e78ca0ecd862a71b71d2a51fed77d" dependencies = [ - "dashmap", "futures", - "lazy_static", "log", + "once_cell", "parking_lot 0.12.0", + "scc", "serial_test_derive", ] [[package]] name = "serial_test_derive" -version = "3.0.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b93fb4adc70021ac1b47f7d45e8cc4169baaa7ea58483bc5b721d19a26202212" +checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 0d2f70c9..2e70742b 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -87,7 +87,7 @@ port_check = "0.2" proptest = "1" sequential-test = "0.2.4" serde_cbor = "0.11" -serial_test = "3.0" +serial_test = "3.1" tempfile = "3" testcontainers = "0.15" From 4d557d1ef9c33bf6b3a92a7067acc0166b6a6330 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:35:05 +0200 Subject: [PATCH 291/395] build(deps): bump mockito from 1.3.0 to 1.4.0 (#1567) * build(deps): bump mockito from 1.3.0 to 1.3.1 Bumps [mockito](https://github.com/lipanski/mockito) from 1.3.0 to 1.3.1. - [Release notes](https://github.com/lipanski/mockito/releases) - [Commits](https://github.com/lipanski/mockito/compare/1.3.0...1.3.1) --- updated-dependencies: - dependency-name: mockito dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * fix: breaking change in mockito async * bump mockito to 1.4 --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Byron Hambly --- Cargo.lock | 6 +++--- swap/Cargo.toml | 2 +- swap/src/monero/wallet_rpc.rs | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51a7fa08..203c718d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2587,13 +2587,13 @@ dependencies = [ [[package]] name = "mockito" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c84fe1f1d8c56dc157f79942056fad4b9efceebba374a01b222428b553facb" +checksum = "d2f6e023aa5bdf392aa06c78e4a4e6d498baab5138d0c993503350ebbc37bf1e" dependencies = [ "assert-json-diff", "colored", - "futures", + "futures-core", "hyper 0.14.28", "log", "rand 0.8.3", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 2e70742b..fd2b0b39 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -81,7 +81,7 @@ bitcoin-harness = { git = "https://github.com/delta1/bitcoin-harness-rs.git", re get-port = "3" hyper = "1.3" jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } -mockito = "1.3.0" +mockito = "1.4" monero-harness = { path = "../monero-harness" } port_check = "0.2" proptest = "1" diff --git a/swap/src/monero/wallet_rpc.rs b/swap/src/monero/wallet_rpc.rs index c7009993..609c3eab 100644 --- a/swap/src/monero/wallet_rpc.rs +++ b/swap/src/monero/wallet_rpc.rs @@ -480,7 +480,7 @@ mod tests { #[tokio::test] async fn test_is_daemon_available_success() { - let mut server = mockito::Server::new(); + let mut server = mockito::Server::new_async().await; let _ = server .mock("GET", "/get_info") @@ -511,7 +511,7 @@ mod tests { #[tokio::test] async fn test_is_daemon_available_wrong_network_failure() { - let mut server = mockito::Server::new(); + let mut server = mockito::Server::new_async().await; let _ = server .mock("GET", "/get_info") @@ -542,7 +542,7 @@ mod tests { #[tokio::test] async fn test_is_daemon_available_not_synced_failure() { - let mut server = mockito::Server::new(); + let mut server = mockito::Server::new_async().await; let _ = server .mock("GET", "/get_info") From cca0d0027e982af00f64aee1835f07f8243a777b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:09:33 +0000 Subject: [PATCH 292/395] build(deps): bump proptest from 1.4.0 to 1.5.0 Bumps [proptest](https://github.com/proptest-rs/proptest) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/proptest-rs/proptest/releases) - [Changelog](https://github.com/proptest-rs/proptest/blob/master/CHANGELOG.md) - [Commits](https://github.com/proptest-rs/proptest/compare/v1.4.0...v1.5.0) --- updated-dependencies: - dependency-name: proptest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 203c718d..b96308c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3144,9 +3144,9 @@ dependencies = [ [[package]] name = "proptest" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +checksum = "b4c2511913b88df1637da85cc8d96ec8e43a3f8bb8ccb71ee1ac240d6f3df58d" dependencies = [ "bit-set", "bit-vec", From dabe1abb216378b1644457fa10d4e38c09734421 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:10:02 +0000 Subject: [PATCH 293/395] build(deps): bump uuid from 1.8.0 to 1.9.0 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.8.0 to 1.9.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.8.0...1.9.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 203c718d..18870f31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5321,9 +5321,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "3ea73390fe27785838dcbf75b91b1d84799e28f1ce71e6f372a5dc2200c80de5" dependencies = [ "getrandom 0.2.11", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index fd2b0b39..cbb7a802 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -67,7 +67,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.8", features = [ "serde", "v4" ] } +uuid = { version = "1.9", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From 2068a4cf787e6b2277d7469bad90804191779f4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 11:12:44 +0000 Subject: [PATCH 294/395] build(deps): bump strum from 0.26.2 to 0.26.3 Bumps [strum](https://github.com/Peternator7/strum) from 0.26.2 to 0.26.3. - [Release notes](https://github.com/Peternator7/strum/releases) - [Changelog](https://github.com/Peternator7/strum/blob/master/CHANGELOG.md) - [Commits](https://github.com/Peternator7/strum/compare/v0.26.2...v0.26.3) --- updated-dependencies: - dependency-name: strum dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 203c718d..1b9d0b5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1602,6 +1602,12 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.18" @@ -4475,20 +4481,20 @@ dependencies = [ [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.1" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", From 3fc934a189baa8a2dede7bf7f57a2bfc4ee7780a Mon Sep 17 00:00:00 2001 From: Ian McKenzie Date: Mon, 24 Jun 2024 21:27:13 -0700 Subject: [PATCH 295/395] Add concurrent_bobs_after_xmr_lock_proof_sent test to ci --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b3fdbf3..2b0a0ce6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -163,6 +163,7 @@ jobs: alice_refunds_after_restart_bob_refunded, ensure_same_swap_id, concurrent_bobs_before_xmr_lock_proof_sent, + concurrent_bobs_after_xmr_lock_proof_sent, alice_manually_redeems_after_enc_sig_learned, happy_path_bob_offline_while_alice_redeems_btc, ] From fbf1c3dabfb4105d33accdbff74da00708e9738d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:48:33 +0000 Subject: [PATCH 296/395] build(deps): bump serde_json from 1.0.117 to 1.0.118 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.117 to 1.0.118. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.117...v1.0.118) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2277173..ed0db29d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4035,9 +4035,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" dependencies = [ "itoa", "ryu", From 5551f513d562ae09431b05224a13b184e2738542 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 11:49:47 +0000 Subject: [PATCH 297/395] build(deps): bump uuid from 1.9.0 to 1.9.1 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.9.0 to 1.9.1. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.9.0...1.9.1) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2277173..677345d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5327,9 +5327,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea73390fe27785838dcbf75b91b1d84799e28f1ce71e6f372a5dc2200c80de5" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" dependencies = [ "getrandom 0.2.11", "serde", From 4c9d1e8d8d1ac6444ae0ab01b8a46cdceef08978 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 27 Jun 2024 14:24:27 +0200 Subject: [PATCH 298/395] Reduce check interval for Monero `watch_for_transfer` (#1670) Oftentimes we fail to check the status of the Monero transaction on the first try (because it hasn't been registered on our Monero daemon yet, it takes a few seconds). By decreasing the check interval from the default of 2 minutes to a 10th of that, we ensure that Bob get's his transfer proof faster. --- swap/src/monero/wallet.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swap/src/monero/wallet.rs b/swap/src/monero/wallet.rs index 99fa206a..e3db3416 100644 --- a/swap/src/monero/wallet.rs +++ b/swap/src/monero/wallet.rs @@ -6,6 +6,7 @@ use ::monero::{Address, Network, PrivateKey, PublicKey}; use anyhow::{Context, Result}; use monero_rpc::wallet::{BlockHeight, MoneroWalletRpc as _, Refreshed}; use monero_rpc::{jsonrpc, wallet}; +use std::ops::Div; use std::str::FromStr; use std::time::Duration; use tokio::sync::Mutex; @@ -233,7 +234,7 @@ impl Wallet { let address = Address::standard(self.network, public_spend_key, public_view_key.into()); - let check_interval = tokio::time::interval(self.sync_interval); + let check_interval = tokio::time::interval(self.sync_interval.div(10)); wait_for_confirmations( &self.inner, From 23a27680a48535ee9a92b613e322e7eff398bc29 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 28 Jun 2024 21:39:30 +0200 Subject: [PATCH 299/395] feat (Bob): Buffer transfer proof to database when we are running a different swap (#1669) --- CHANGELOG.md | 2 + .../20210903050345_create_swaps_table.sql | 6 ++ swap/sqlx-data.json | 28 ++++++ swap/src/api/request.rs | 4 +- swap/src/cli/event_loop.rs | 88 +++++++++++++------ swap/src/database/sqlite.rs | 52 ++++++++++- swap/src/network/test.rs | 6 +- swap/src/protocol.rs | 9 ++ swap/src/protocol/bob/swap.rs | 25 +++++- ...current_bobs_before_xmr_lock_proof_sent.rs | 11 +-- swap/tests/harness/mod.rs | 13 +-- 11 files changed, 193 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2c930c9..0c48cb79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- CLI: Buffer received transfer proofs for later processing if we're currently running a different swap + ## [0.13.1] - 2024-06-10 - Add retry logic to monero-wallet-rpc wallet refresh diff --git a/swap/migrations/20210903050345_create_swaps_table.sql b/swap/migrations/20210903050345_create_swaps_table.sql index 741a45e6..84a97d0f 100644 --- a/swap/migrations/20210903050345_create_swaps_table.sql +++ b/swap/migrations/20210903050345_create_swaps_table.sql @@ -22,4 +22,10 @@ CREATE TABLE if NOT EXISTS peer_addresses ( peer_id TEXT NOT NULL, address TEXT NOT NULL +); + +CREATE TABLE if NOT EXISTS buffered_transfer_proofs +( + swap_id TEXT PRIMARY KEY NOT NULL, + proof TEXT NOT NULL ); \ No newline at end of file diff --git a/swap/sqlx-data.json b/swap/sqlx-data.json index f24a50e6..6ab0f14a 100644 --- a/swap/sqlx-data.json +++ b/swap/sqlx-data.json @@ -195,5 +195,33 @@ } }, "query": "\n SELECT state\n FROM swap_states\n WHERE swap_id = ?\n " + }, + "e36c287aa98ae80ad4b6bb6f7e4b59cced041406a9db71da827b09f0d3bacfd6": { + "describe": { + "columns": [], + "nullable": [], + "parameters": { + "Right": 2 + } + }, + "query": "\n INSERT INTO buffered_transfer_proofs (\n swap_id,\n proof\n ) VALUES (?, ?);\n " + }, + "e9d422daf774d099fcbde6c4cda35821da948bd86cc57798b4d8375baf0b51ae": { + "describe": { + "columns": [ + { + "name": "proof", + "ordinal": 0, + "type_info": "Text" + } + ], + "nullable": [ + false + ], + "parameters": { + "Right": 1 + } + }, + "query": "\n SELECT proof\n FROM buffered_transfer_proofs\n WHERE swap_id = ?\n " } } \ No newline at end of file diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index 338432c3..800e1c06 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -376,7 +376,7 @@ impl Request { }, result = async { let (event_loop, mut event_loop_handle) = - EventLoop::new(swap_id, swarm, seller_peer_id)?; + EventLoop::new(swap_id, swarm, seller_peer_id, context.db.clone())?; let event_loop = tokio::spawn(event_loop.run().in_current_span()); let bid_quote = event_loop_handle.request_quote().await?; @@ -522,7 +522,7 @@ impl Request { } let (event_loop, event_loop_handle) = - EventLoop::new(swap_id, swarm, seller_peer_id)?; + EventLoop::new(swap_id, swarm, seller_peer_id, context.db.clone())?; let monero_receive_address = context.db.get_monero_address(swap_id).await?; let swap = Swap::from_db( Arc::clone(&context.db), diff --git a/swap/src/cli/event_loop.rs b/swap/src/cli/event_loop.rs index befe1dc5..fd7b4308 100644 --- a/swap/src/cli/event_loop.rs +++ b/swap/src/cli/event_loop.rs @@ -5,6 +5,7 @@ use crate::network::encrypted_signature; use crate::network::quote::BidQuote; use crate::network::swap_setup::bob::NewSwap; use crate::protocol::bob::State2; +use crate::protocol::Database; use anyhow::{Context, Result}; use futures::future::{BoxFuture, OptionFuture}; use futures::{FutureExt, StreamExt}; @@ -13,6 +14,7 @@ use libp2p::swarm::dial_opts::DialOpts; use libp2p::swarm::SwarmEvent; use libp2p::{PeerId, Swarm}; use std::collections::HashMap; +use std::sync::Arc; use std::time::Duration; use uuid::Uuid; @@ -21,6 +23,7 @@ pub struct EventLoop { swap_id: Uuid, swarm: libp2p::Swarm, alice_peer_id: PeerId, + db: Arc, // these streams represents outgoing requests that we have to make quote_requests: bmrng::RequestReceiverStream<(), BidQuote>, @@ -51,6 +54,7 @@ impl EventLoop { swap_id: Uuid, swarm: Swarm, alice_peer_id: PeerId, + db: Arc, ) -> 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)); @@ -69,6 +73,7 @@ impl EventLoop { inflight_swap_setup: None, inflight_encrypted_signature_requests: HashMap::default(), pending_transfer_proof: OptionFuture::from(None), + db, }; let handle = EventLoopHandle { @@ -108,38 +113,63 @@ impl EventLoop { SwarmEvent::Behaviour(OutEvent::TransferProofReceived { msg, channel, peer }) => { let swap_id = msg.swap_id; - if peer != self.alice_peer_id { - tracing::warn!( - %swap_id, - "Ignoring malicious transfer proof from {}, expected to receive it from {}", - peer, - self.alice_peer_id); - continue; - } - - if swap_id != self.swap_id { - - // TODO: Save unexpected transfer proofs in the database and check for messages in the database when handling swaps - tracing::warn!("Received unexpected transfer proof for swap {} while running swap {}. This transfer proof will be ignored", swap_id, self.swap_id); - - // When receiving a transfer proof that is unexpected we still have to acknowledge that it was received - let _ = self.swarm.behaviour_mut().transfer_proof.send_response(channel, ()); - continue; - } - - let mut responder = match self.transfer_proof.send(msg.tx_lock_proof).await { - Ok(responder) => responder, - Err(e) => { - tracing::warn!("Failed to pass on transfer proof: {:#}", e); - continue; + if swap_id == self.swap_id { + if peer != self.alice_peer_id { + tracing::warn!( + %swap_id, + "Ignoring malicious transfer proof from {}, expected to receive it from {}", + peer, + self.alice_peer_id); + continue; } - }; - self.pending_transfer_proof = OptionFuture::from(Some(async move { - let _ = responder.recv().await; + let mut responder = match self.transfer_proof.send(msg.tx_lock_proof).await { + Ok(responder) => responder, + Err(e) => { + tracing::warn!("Failed to pass on transfer proof: {:#}", e); + continue; + } + }; - channel - }.boxed())); + self.pending_transfer_proof = OptionFuture::from(Some(async move { + let _ = responder.recv().await; + + channel + }.boxed())); + }else { + // Check if the transfer proof is sent from the correct peer and if we have a record of the swap + match self.db.get_peer_id(swap_id).await { + // We have a record of the swap + Ok(buffer_swap_alice_peer_id) => { + if buffer_swap_alice_peer_id == self.alice_peer_id { + // Save transfer proof in the database such that we can process it later when we resume the swap + match self.db.insert_buffered_transfer_proof(swap_id, msg.tx_lock_proof).await { + Ok(_) => { + tracing::info!("Received transfer proof for swap {} while running swap {}. Buffering this transfer proof in the database for later retrieval", swap_id, self.swap_id); + let _ = self.swarm.behaviour_mut().transfer_proof.send_response(channel, ()); + } + Err(e) => { + tracing::error!("Failed to buffer transfer proof for swap {}: {:#}", swap_id, e); + } + }; + }else { + tracing::warn!( + %swap_id, + "Ignoring malicious transfer proof from {}, expected to receive it from {}", + self.swap_id, + buffer_swap_alice_peer_id); + } + }, + // We do not have a record of the swap or an error occurred while retrieving the peer id of Alice + Err(e) => { + if let Some(sqlx::Error::RowNotFound) = e.downcast_ref::() { + tracing::warn!("Ignoring transfer proof for swap {} while running swap {}. We do not have a record of this swap", swap_id, self.swap_id); + } else { + tracing::error!("Ignoring transfer proof for swap {} while running swap {}. Failed to retrieve the peer id of Alice for the corresponding swap: {:#}", swap_id, self.swap_id, e); + } + } + } + } } SwarmEvent::Behaviour(OutEvent::EncryptedSignatureAcknowledged { id }) => { if let Some(responder) = self.inflight_encrypted_signature_requests.remove(&id) { diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index 751f76aa..6cddd50e 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -1,5 +1,5 @@ use crate::database::Swap; -use crate::monero::Address; +use crate::monero::{Address, TransferProof}; use crate::protocol::{Database, State}; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; @@ -303,6 +303,56 @@ impl Database for SqliteDatabase { result } + async fn insert_buffered_transfer_proof( + &self, + swap_id: Uuid, + proof: TransferProof, + ) -> Result<()> { + let mut conn = self.pool.acquire().await?; + let swap_id = swap_id.to_string(); + let proof = serde_json::to_string(&proof)?; + + sqlx::query!( + r#" + INSERT INTO buffered_transfer_proofs ( + swap_id, + proof + ) VALUES (?, ?); + "#, + swap_id, + proof + ) + .execute(&mut conn) + .await?; + + Ok(()) + } + + async fn get_buffered_transfer_proof(&self, swap_id: Uuid) -> Result> { + let mut conn = self.pool.acquire().await?; + let swap_id = swap_id.to_string(); + + let row = sqlx::query!( + r#" + SELECT proof + FROM buffered_transfer_proofs + WHERE swap_id = ? + "#, + swap_id + ) + .fetch_all(&mut conn) + .await?; + + if row.is_empty() { + return Ok(None); + } + + let proof_str = &row[0].proof; + let proof = serde_json::from_str(proof_str)?; + + Ok(Some(proof)) + } + async fn raw_all(&self) -> Result>> { let mut conn = self.pool.acquire().await?; let rows = sqlx::query!( diff --git a/swap/src/network/test.rs b/swap/src/network/test.rs index 5a324385..f27c3824 100644 --- a/swap/src/network/test.rs +++ b/swap/src/network/test.rs @@ -1,6 +1,6 @@ use async_trait::async_trait; use futures::stream::FusedStream; -use futures::{future, Future, Stream, StreamExt}; +use futures::{future, Future, StreamExt}; use libp2p::core::muxing::StreamMuxerBox; use libp2p::core::transport::upgrade::Version; use libp2p::core::transport::MemoryTransport; @@ -75,8 +75,8 @@ async fn get_local_tcp_address() -> Multiaddr { } pub async fn await_events_or_timeout( - swarm_1: &mut (impl Stream> + FusedStream + Unpin), - swarm_2: &mut (impl Stream> + FusedStream + Unpin), + swarm_1: &mut (impl FusedStream> + FusedStream + Unpin), + swarm_2: &mut (impl FusedStream> + FusedStream + Unpin), ) -> (SwarmEvent, SwarmEvent) where SwarmEvent: Debug, diff --git a/swap/src/protocol.rs b/swap/src/protocol.rs index 0e15f89a..676a03f4 100644 --- a/swap/src/protocol.rs +++ b/swap/src/protocol.rs @@ -146,4 +146,13 @@ pub trait Database { async fn get_states(&self, swap_id: Uuid) -> Result>; async fn all(&self) -> Result>; async fn raw_all(&self) -> Result>>; + async fn insert_buffered_transfer_proof( + &self, + swap_id: Uuid, + proof: monero::TransferProof, + ) -> Result<()>; + async fn get_buffered_transfer_proof( + &self, + swap_id: Uuid, + ) -> Result>; } diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 3900a17b..7a702d77 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -1,10 +1,11 @@ use crate::bitcoin::{ExpiredTimelocks, TxCancel, TxRefund}; use crate::cli::EventLoopHandle; use crate::network::swap_setup::bob::NewSwap; -use crate::protocol::bob; use crate::protocol::bob::state::*; +use crate::protocol::{bob, Database}; use crate::{bitcoin, monero}; use anyhow::{bail, Context, Result}; +use std::sync::Arc; use tokio::select; use uuid::Uuid; @@ -34,6 +35,7 @@ pub async fn run_until( swap.id, current_state.clone(), &mut swap.event_loop_handle, + swap.db.clone(), swap.bitcoin_wallet.as_ref(), swap.monero_wallet.as_ref(), swap.monero_receive_address, @@ -52,6 +54,7 @@ async fn next_state( swap_id: Uuid, state: BobState, event_loop_handle: &mut EventLoopHandle, + db: Arc, bitcoin_wallet: &bitcoin::Wallet, monero_wallet: &monero::Wallet, monero_receive_address: monero::Address, @@ -118,12 +121,28 @@ async fn next_state( let tx_lock_status = bitcoin_wallet.subscribe_to(state3.tx_lock.clone()).await; if let ExpiredTimelocks::None { .. } = state3.expired_timelock(bitcoin_wallet).await? { + tracing::info!("Waiting for Alice to lock Monero"); + + let buffered_transfer_proof = db + .get_buffered_transfer_proof(swap_id) + .await + .context("Failed to get buffered transfer proof")?; + + if let Some(transfer_proof) = buffered_transfer_proof { + tracing::debug!(txid = %transfer_proof.tx_hash(), "Found buffered transfer proof"); + tracing::info!(txid = %transfer_proof.tx_hash(), "Alice locked Monero"); + + return Ok(BobState::XmrLockProofReceived { + state: state3, + lock_transfer_proof: transfer_proof, + monero_wallet_restore_blockheight, + }); + } + let transfer_proof_watcher = event_loop_handle.recv_transfer_proof(); let cancel_timelock_expires = tx_lock_status.wait_until_confirmed_with(state3.cancel_timelock); - tracing::info!("Waiting for Alice to lock Monero"); - select! { transfer_proof = transfer_proof_watcher => { let transfer_proof = transfer_proof?; diff --git a/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs b/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs index d76b3b5f..bf8adb06 100644 --- a/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs +++ b/swap/tests/concurrent_bobs_before_xmr_lock_proof_sent.rs @@ -32,8 +32,7 @@ async fn concurrent_bobs_before_xmr_lock_proof_sent() { let alice_swap_2 = tokio::spawn(alice::run(alice_swap_2, FixedRate::default())); // The 2nd swap ALWAYS finish successfully in this - // scenario, but will receive an "unwanted" transfer proof that is ignored in - // the event loop. + // scenario, but will receive an "unwanted" transfer proof that is buffered until the 1st swap is resumed let bob_state_2 = bob_swap_2.await??; assert!(matches!(bob_state_2, BobState::XmrRedeemed { .. })); @@ -46,15 +45,13 @@ async fn concurrent_bobs_before_xmr_lock_proof_sent() { .await; assert!(matches!(bob_state_1, BobState::BtcLocked { .. })); - // The 1st (paused) swap is expected to refund, because the transfer - // proof is delivered to the wrong swap, and we currently don't store it in the - // database for the other swap. + // The 1st (paused) swap is expected to finish successfully because the transfer proof is buffered when it is receives while another swap is running. let bob_state_1 = bob::run(bob_swap_1).await?; - assert!(matches!(bob_state_1, BobState::BtcRefunded { .. })); + assert!(matches!(bob_state_1, BobState::XmrRedeemed { .. })); let alice_state_1 = alice_swap_1.await??; - assert!(matches!(alice_state_1, AliceState::XmrRefunded { .. })); + assert!(matches!(alice_state_1, AliceState::BtcRedeemed { .. })); Ok(()) }) diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 24083a71..028b0935 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -427,8 +427,6 @@ impl BobParams { } pub async fn new_swap_from_db(&self, swap_id: Uuid) -> Result<(bob::Swap, cli::EventLoop)> { - let (event_loop, handle) = self.new_eventloop(swap_id).await?; - if let Some(parent_dir) = self.db_path.parent() { ensure_directory_exists(parent_dir)?; } @@ -437,8 +435,10 @@ impl BobParams { } let db = Arc::new(SqliteDatabase::open(&self.db_path).await?); + let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?; + let swap = bob::Swap::from_db( - db, + db.clone(), swap_id, self.bitcoin_wallet.clone(), self.monero_wallet.clone(), @@ -457,8 +457,6 @@ impl BobParams { ) -> Result<(bob::Swap, cli::EventLoop)> { let swap_id = Uuid::new_v4(); - let (event_loop, handle) = self.new_eventloop(swap_id).await?; - if let Some(parent_dir) = self.db_path.parent() { ensure_directory_exists(parent_dir)?; } @@ -467,6 +465,8 @@ impl BobParams { } let db = Arc::new(SqliteDatabase::open(&self.db_path).await?); + let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?; + db.insert_peer_id(swap_id, self.alice_peer_id).await?; let swap = bob::Swap::new( @@ -487,6 +487,7 @@ impl BobParams { pub async fn new_eventloop( &self, swap_id: Uuid, + db: Arc, ) -> Result<(cli::EventLoop, cli::EventLoopHandle)> { let tor_socks5_port = get_port() .expect("We don't care about Tor in the tests so we get a free port to disable it."); @@ -503,7 +504,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) + cli::EventLoop::new(swap_id, swarm, self.alice_peer_id, db.clone()) } } From 173d077751bce0522d5542f05c5ac04709f716e5 Mon Sep 17 00:00:00 2001 From: patrini32 Date: Mon, 1 Jul 2024 21:14:44 +0000 Subject: [PATCH 300/395] feat (Cli): Display reason for failed cancel-refund operation to the user (#1668) We now display the reason for a failed cancel-refund operation to the user. Fixes #683 --- .github/workflows/ci.yml | 1 + CHANGELOG.md | 1 + swap/src/api/request.rs | 1 + swap/src/cli/cancel_and_refund.rs | 130 ++++++++++++++---- swap/src/protocol/bob/state.rs | 37 ++--- ..._refund_using_cancel_and_refund_command.rs | 2 +- ...and_refund_command_timelock_not_expired.rs | 15 +- ...punishes_after_bob_dead_and_bob_cancels.rs | 98 +++++++++++++ 8 files changed, 224 insertions(+), 61 deletions(-) create mode 100644 swap/tests/alice_manually_punishes_after_bob_dead_and_bob_cancels.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2b0a0ce6..b3f742fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -157,6 +157,7 @@ jobs: alice_and_bob_refund_using_cancel_and_refund_command, alice_and_bob_refund_using_cancel_then_refund_command, alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired, + alice_manually_punishes_after_bob_dead_and_bob_cancels, punish, alice_punishes_after_restart_bob_dead, alice_manually_punishes_after_bob_dead, diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c48cb79..098db809 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap +- CLI: We now display the reason for a failed cancel-refund operation to the user (#683) ## [0.13.1] - 2024-06-10 diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index 800e1c06..50274ab1 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -821,6 +821,7 @@ impl Request { .await .map_err(|err| { method_span.in_scope(|| { + // The {:?} formatter is used to print the entire error chain tracing::debug!(err = format!("{:?}", err), "API call resulted in an error"); }); err diff --git a/swap/src/cli/cancel_and_refund.rs b/swap/src/cli/cancel_and_refund.rs index d542b7ed..e92283ea 100644 --- a/swap/src/cli/cancel_and_refund.rs +++ b/swap/src/cli/cancel_and_refund.rs @@ -1,5 +1,4 @@ -use crate::bitcoin::wallet::Subscription; -use crate::bitcoin::{parse_rpc_error_code, RpcErrorCode, Wallet}; +use crate::bitcoin::{ExpiredTimelocks, Wallet}; use crate::protocol::bob::BobState; use crate::protocol::Database; use anyhow::{bail, Result}; @@ -13,7 +12,7 @@ pub async fn cancel_and_refund( db: Arc, ) -> Result { if let Err(err) = cancel(swap_id, bitcoin_wallet.clone(), db.clone()).await { - tracing::info!(%err, "Could not submit cancel transaction"); + tracing::warn!(%err, "Could not cancel swap. Attempting to refund anyway"); }; let state = match refund(swap_id, bitcoin_wallet, db).await { @@ -21,7 +20,6 @@ pub async fn cancel_and_refund( Err(e) => bail!(e), }; - tracing::info!("Refund transaction submitted"); Ok(state) } @@ -29,7 +27,7 @@ pub async fn cancel( swap_id: Uuid, bitcoin_wallet: Arc, db: Arc, -) -> Result<(Txid, Subscription, BobState)> { +) -> Result<(Txid, BobState)> { let state = db.get_state(swap_id).await?.try_into()?; let state6 = match state { @@ -47,34 +45,69 @@ pub async fn cancel( | BobState::XmrRedeemed { .. } | BobState::BtcPunished { .. } | BobState::SafelyAborted => bail!( - "Cannot cancel swap {} because it is in state {} which is not refundable.", + "Cannot cancel swap {} because it is in state {} which is not cancellable.", swap_id, state ), }; - tracing::info!(%swap_id, "Manually cancelling swap"); + tracing::info!(%swap_id, "Attempting to manually cancel swap"); - let (txid, subscription) = match state6.submit_tx_cancel(bitcoin_wallet.as_ref()).await { - Ok(txid) => txid, + // Attempt to just publish the cancel transaction + match state6.submit_tx_cancel(bitcoin_wallet.as_ref()).await { + Ok((txid, _)) => { + let state = BobState::BtcCancelled(state6); + db.insert_latest_state(swap_id, state.clone().into()) + .await?; + Ok((txid, state)) + } + + // If we fail to submit the cancel transaction it can have one of two reasons: + // 1. The cancel timelock hasn't expired yet + // 2. The cancel transaction has already been published by Alice Err(err) => { - if let Ok(error_code) = parse_rpc_error_code(&err) { - tracing::debug!(%error_code, "parse rpc error"); - if error_code == i64::from(RpcErrorCode::RpcVerifyAlreadyInChain) { - tracing::info!("Cancel transaction has already been confirmed on chain"); - } else if error_code == i64::from(RpcErrorCode::RpcVerifyError) { - tracing::info!("General error trying to submit cancel transaction"); + // Check if Alice has already published the cancel transaction while we were absent + if let Ok(tx) = state6.check_for_tx_cancel(bitcoin_wallet.as_ref()).await { + let state = BobState::BtcCancelled(state6); + db.insert_latest_state(swap_id, state.clone().into()) + .await?; + tracing::info!("Alice has already cancelled the swap"); + return Ok((tx.txid(), state)); + } + + // The cancel transaction has not been published yet and we failed to publish it ourselves + // Here we try to figure out why + match state6.expired_timelock(bitcoin_wallet.as_ref()).await { + // We cannot cancel because Alice has already cancelled and punished afterwards + Ok(ExpiredTimelocks::Punish { .. }) => { + let state = BobState::BtcPunished { + tx_lock_id: state6.tx_lock_id(), + }; + db.insert_latest_state(swap_id, state.clone().into()) + .await?; + tracing::info!("You have been punished for not refunding in time"); + bail!(err.context("Cannot cancel swap because we have already been punished")); + } + // We cannot cancel because the cancel timelock has not expired yet + Ok(ExpiredTimelocks::None { blocks_left }) => { + bail!(err.context( + format!( + "Cannot cancel swap because the cancel timelock has not expired yet. Blocks left: {}", + blocks_left + ) + )); + } + Ok(ExpiredTimelocks::Cancel { .. }) => { + bail!(err.context("Failed to cancel swap even though cancel timelock has expired. This is unexpected.")); + } + Err(timelock_err) => { + bail!(err + .context(timelock_err) + .context("Failed to cancel swap and could not check timelock status")); } } - bail!(err); } - }; - - let state = BobState::BtcCancelled(state6); - db.insert_latest_state(swap_id, state.clone().into()) - .await?; - - Ok((txid, subscription, state)) + } } pub async fn refund( @@ -104,12 +137,51 @@ pub async fn refund( ), }; - tracing::info!(%swap_id, "Manually refunding swap"); - state6.publish_refund_btc(bitcoin_wallet.as_ref()).await?; + tracing::info!(%swap_id, "Attempting to manually refund swap"); - let state = BobState::BtcRefunded(state6); - db.insert_latest_state(swap_id, state.clone().into()) - .await?; + // Attempt to just publish the refund transaction + match state6.publish_refund_btc(bitcoin_wallet.as_ref()).await { + Ok(_) => { + let state = BobState::BtcRefunded(state6); + db.insert_latest_state(swap_id, state.clone().into()) + .await?; - Ok(state) + Ok(state) + } + + // If we fail to submit the refund transaction it can have one of two reasons: + // 1. The cancel transaction has not been published yet + // 2. The refund timelock has already expired and we have been punished + Err(bitcoin_publication_err) => { + match state6.expired_timelock(bitcoin_wallet.as_ref()).await { + // We have been punished + Ok(ExpiredTimelocks::Punish { .. }) => { + let state = BobState::BtcPunished { + tx_lock_id: state6.tx_lock_id(), + }; + db.insert_latest_state(swap_id, state.clone().into()) + .await?; + tracing::info!("You have been punished for not refunding in time"); + bail!(bitcoin_publication_err + .context("Cannot refund swap because we have already been punished")); + } + Ok(ExpiredTimelocks::None { blocks_left }) => { + bail!( + bitcoin_publication_err.context(format!( + "Cannot refund swap because the cancel timelock has not expired yet. Blocks left: {}", + blocks_left + )) + ); + } + Ok(ExpiredTimelocks::Cancel { .. }) => { + bail!(bitcoin_publication_err.context("Failed to refund swap even though cancel timelock has expired. This should is unexpected.")); + } + Err(e) => { + bail!(bitcoin_publication_err + .context(e) + .context("Failed to refund swap and could not check timelock status")); + } + } + } + } } diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index 58c1d723..03f56d28 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -646,18 +646,20 @@ impl State6 { tx_cancel_status, )) } - - pub async fn check_for_tx_cancel( - &self, - bitcoin_wallet: &bitcoin::Wallet, - ) -> Result { - let tx_cancel = bitcoin::TxCancel::new( + pub fn construct_tx_cancel(&self) -> Result { + bitcoin::TxCancel::new( &self.tx_lock, self.cancel_timelock, self.A, self.b.public(), self.tx_cancel_fee, - )?; + ) + } + pub async fn check_for_tx_cancel( + &self, + bitcoin_wallet: &bitcoin::Wallet, + ) -> Result { + let tx_cancel = self.construct_tx_cancel()?; let tx = bitcoin_wallet.get_raw_transaction(tx_cancel.txid()).await?; @@ -668,15 +670,10 @@ impl State6 { &self, bitcoin_wallet: &bitcoin::Wallet, ) -> Result<(Txid, Subscription)> { - let transaction = bitcoin::TxCancel::new( - &self.tx_lock, - self.cancel_timelock, - self.A, - self.b.public(), - self.tx_cancel_fee, - )? - .complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone()) - .context("Failed to complete Bitcoin cancel transaction")?; + let transaction = self + .construct_tx_cancel()? + .complete_as_bob(self.A, self.b.clone(), self.tx_cancel_sig_a.clone()) + .context("Failed to complete Bitcoin cancel transaction")?; let (tx_id, subscription) = bitcoin_wallet.broadcast(transaction, "cancel").await?; @@ -691,13 +688,7 @@ impl State6 { } pub fn signed_refund_transaction(&self) -> Result { - let tx_cancel = bitcoin::TxCancel::new( - &self.tx_lock, - self.cancel_timelock, - self.A, - self.b.public(), - self.tx_cancel_fee, - )?; + let tx_cancel = self.construct_tx_cancel()?; let tx_refund = bitcoin::TxRefund::new(&tx_cancel, &self.refund_address, self.tx_refund_fee); diff --git a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs index 1870bed4..04cabec4 100644 --- a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs +++ b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command.rs @@ -50,7 +50,7 @@ async fn given_alice_and_bob_manually_refund_after_funds_locked_both_refund() { // Bob manually cancels bob_join_handle.abort(); - let (_, _, state) = cli::cancel(bob_swap.id, bob_swap.bitcoin_wallet, bob_swap.db).await?; + let (_, state) = cli::cancel(bob_swap.id, bob_swap.bitcoin_wallet, bob_swap.db).await?; assert!(matches!(state, BobState::BtcCancelled { .. })); let (bob_swap, bob_join_handle) = ctx diff --git a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs index 16953866..6584a3d2 100644 --- a/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs +++ b/swap/tests/alice_and_bob_refund_using_cancel_and_refund_command_timelock_not_expired.rs @@ -42,10 +42,10 @@ async fn given_alice_and_bob_manually_cancel_when_timelock_not_expired_errors() let error = cli::cancel(bob_swap.id, bob_swap.bitcoin_wallet, bob_swap.db) .await .unwrap_err(); - assert_eq!( - parse_rpc_error_code(&error).unwrap(), - i64::from(RpcErrorCode::RpcVerifyRejected) - ); + + assert!(error + .to_string() + .contains("Cannot cancel swap because the cancel timelock has not expired yet")); ctx.restart_alice().await; let alice_swap = ctx.alice_next_swap().await; @@ -72,10 +72,9 @@ async fn given_alice_and_bob_manually_cancel_when_timelock_not_expired_errors() let error = cli::refund(bob_swap.id, bob_swap.bitcoin_wallet, bob_swap.db) .await .unwrap_err(); - assert_eq!( - parse_rpc_error_code(&error).unwrap(), - i64::from(RpcErrorCode::RpcVerifyError) - ); + assert!(error + .to_string() + .contains("Cannot refund swap because the cancel timelock has not expired yet")); let (bob_swap, _) = ctx .stop_and_resume_bob_from_db(bob_join_handle, swap_id) diff --git a/swap/tests/alice_manually_punishes_after_bob_dead_and_bob_cancels.rs b/swap/tests/alice_manually_punishes_after_bob_dead_and_bob_cancels.rs new file mode 100644 index 00000000..374d6160 --- /dev/null +++ b/swap/tests/alice_manually_punishes_after_bob_dead_and_bob_cancels.rs @@ -0,0 +1,98 @@ +pub mod harness; + +use harness::alice_run_until::is_xmr_lock_transaction_sent; +use harness::bob_run_until::is_btc_locked; +use harness::FastPunishConfig; +use swap::asb; +use swap::asb::FixedRate; +use swap::cli; +use swap::protocol::alice::AliceState; +use swap::protocol::bob::BobState; +use swap::protocol::{alice, bob}; +/// Bob locks Btc and Alice locks Xmr. Bob does not act; he fails to send Alice +/// the encsig and fail to refund or redeem. Alice punishes using the cancel and +/// punish command. Then Bob tries to refund. +#[tokio::test] +async fn alice_manually_punishes_after_bob_dead_and_bob_cancels() { + harness::setup_test(FastPunishConfig, |mut ctx| async move { + let (bob_swap, bob_join_handle) = ctx.bob_swap().await; + let bob_swap_id = bob_swap.id; + let bob_swap = tokio::spawn(bob::run_until(bob_swap, is_btc_locked)); + + let alice_swap = ctx.alice_next_swap().await; + let alice_bitcoin_wallet = alice_swap.bitcoin_wallet.clone(); + + let alice_swap = tokio::spawn(alice::run_until( + alice_swap, + is_xmr_lock_transaction_sent, + FixedRate::default(), + )); + + let bob_state = bob_swap.await??; + assert!(matches!(bob_state, BobState::BtcLocked { .. })); + + let alice_state = alice_swap.await??; + + // Ensure cancel timelock is expired + if let AliceState::XmrLockTransactionSent { state3, .. } = alice_state { + alice_bitcoin_wallet + .subscribe_to(state3.tx_lock) + .await + .wait_until_confirmed_with(state3.cancel_timelock) + .await?; + } else { + panic!("Alice in unexpected state {}", alice_state); + } + + // manual cancel (required to be able to punish) + + ctx.restart_alice().await; + let alice_swap = ctx.alice_next_swap().await; + let (_, alice_state) = + asb::cancel(alice_swap.swap_id, alice_swap.bitcoin_wallet, alice_swap.db).await?; + + // Ensure punish timelock is expired + if let AliceState::BtcCancelled { state3, .. } = alice_state { + alice_bitcoin_wallet + .subscribe_to(state3.tx_cancel()) + .await + .wait_until_confirmed_with(state3.punish_timelock) + .await?; + } else { + panic!("Alice in unexpected state {}", alice_state); + } + + // manual punish + + ctx.restart_alice().await; + let alice_swap = ctx.alice_next_swap().await; + let (_, alice_state) = + asb::punish(alice_swap.swap_id, alice_swap.bitcoin_wallet, alice_swap.db).await?; + ctx.assert_alice_punished(alice_state).await; + // Bob is in wrong state. + let (bob_swap, bob_join_handle) = ctx + .stop_and_resume_bob_from_db(bob_join_handle, bob_swap_id) + .await; + assert!(matches!(bob_swap.state, BobState::BtcLocked { .. })); + bob_join_handle.abort(); + + let (_, state) = cli::cancel(bob_swap_id, bob_swap.bitcoin_wallet, bob_swap.db).await?; + // Bob should be in BtcCancelled state now. + assert!(matches!(state, BobState::BtcCancelled { .. })); + + let (bob_swap, _) = ctx + .stop_and_resume_bob_from_db(bob_join_handle, bob_swap_id) + .await; + assert!(matches!(bob_swap.state, BobState::BtcCancelled { .. })); + // Alice punished Bob, so he should be in the BtcPunished state. + let error = cli::refund(bob_swap_id, bob_swap.bitcoin_wallet, bob_swap.db) + .await + .unwrap_err(); + assert_eq!( + error.to_string(), + "Cannot refund swap because we have already been punished" + ); + Ok(()) + }) + .await; +} From 415323e4fcebc81e7e6ad0fdc50c600914575a36 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Tue, 2 Jul 2024 07:27:00 +1000 Subject: [PATCH 301/395] Prepare release 0.13.2 (#1694) --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 098db809..6da810b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.2] - 2024-07-01 + - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap - CLI: We now display the reason for a failed cancel-refund operation to the user (#683) @@ -363,7 +365,8 @@ 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.13.1...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...HEAD +[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 [0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 diff --git a/Cargo.lock b/Cargo.lock index b18965fb..cb3ea136 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4515,7 +4515,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.13.1" +version = "0.13.2" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index cbb7a802..5c754a53 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.13.1" +version = "0.13.2" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From aa9b3c46871258ec8b4cf30adfe52c860ec40889 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:20:20 +0200 Subject: [PATCH 302/395] fix: Add a new migration script for creating the buffered_transfer_proofs table (#1695) --- swap/migrations/20210903050345_create_swaps_table.sql | 6 ------ ...20240701231624_create_buffered_transfer_proofs_table.sql | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 swap/migrations/20240701231624_create_buffered_transfer_proofs_table.sql diff --git a/swap/migrations/20210903050345_create_swaps_table.sql b/swap/migrations/20210903050345_create_swaps_table.sql index 84a97d0f..741a45e6 100644 --- a/swap/migrations/20210903050345_create_swaps_table.sql +++ b/swap/migrations/20210903050345_create_swaps_table.sql @@ -22,10 +22,4 @@ CREATE TABLE if NOT EXISTS peer_addresses ( peer_id TEXT NOT NULL, address TEXT NOT NULL -); - -CREATE TABLE if NOT EXISTS buffered_transfer_proofs -( - swap_id TEXT PRIMARY KEY NOT NULL, - proof TEXT NOT NULL ); \ No newline at end of file diff --git a/swap/migrations/20240701231624_create_buffered_transfer_proofs_table.sql b/swap/migrations/20240701231624_create_buffered_transfer_proofs_table.sql new file mode 100644 index 00000000..32d2c918 --- /dev/null +++ b/swap/migrations/20240701231624_create_buffered_transfer_proofs_table.sql @@ -0,0 +1,5 @@ +CREATE TABLE if NOT EXISTS buffered_transfer_proofs +( + swap_id TEXT PRIMARY KEY NOT NULL, + proof TEXT NOT NULL +); \ No newline at end of file From 5e735ef4f72cb95f9372cd6d69f39f5f9019283b Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:28:07 +1000 Subject: [PATCH 303/395] Prepare release 0.13.2 (#1697) --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6da810b4..0d60a04d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.13.2] - 2024-07-01 +## [0.13.2] - 2024-07-01 + - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap - CLI: We now display the reason for a failed cancel-refund operation to the user (#683) @@ -366,6 +368,7 @@ It is possible to migrate critical data from the old db to the sqlite but there 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.13.2...HEAD +[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.2 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 From 26109d6d8a5e90536ec92dd86a0546ffb5970ff7 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:51:58 +0200 Subject: [PATCH 304/395] Revert "Prepare release 0.13.2 (#1697)" (#1698) This reverts commit 5e735ef4f72cb95f9372cd6d69f39f5f9019283b. --- CHANGELOG.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d60a04d..6da810b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.13.2] - 2024-07-01 -## [0.13.2] - 2024-07-01 - - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap - CLI: We now display the reason for a failed cancel-refund operation to the user (#683) @@ -368,7 +366,6 @@ It is possible to migrate critical data from the old db to the sqlite but there 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.13.2...HEAD -[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.2 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 From 6c1b85e4084b5ca9acb1fe53b9804850220fe9ee Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 2 Jul 2024 01:53:57 +0200 Subject: [PATCH 305/395] Revert "Prepare release 0.13.2 (#1694)" (#1699) This reverts commit 415323e4fcebc81e7e6ad0fdc50c600914575a36. --- CHANGELOG.md | 5 +---- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6da810b4..098db809 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.13.2] - 2024-07-01 - - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap - CLI: We now display the reason for a failed cancel-refund operation to the user (#683) @@ -365,8 +363,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.13.2...HEAD -[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...HEAD [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 [0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 diff --git a/Cargo.lock b/Cargo.lock index cb3ea136..b18965fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4515,7 +4515,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.13.2" +version = "0.13.1" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 5c754a53..cbb7a802 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.13.2" +version = "0.13.1" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From 5c9185876da7fc01b610bc749be149163ea59c76 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:11:36 +1000 Subject: [PATCH 306/395] Prepare release 0.13.2 (#1700) --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 098db809..9a2baf45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.2] - 2024-07-02 + - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap - CLI: We now display the reason for a failed cancel-refund operation to the user (#683) @@ -363,7 +365,8 @@ 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.13.1...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...HEAD +[0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 [0.12.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.2...0.12.3 diff --git a/Cargo.lock b/Cargo.lock index b18965fb..cb3ea136 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4515,7 +4515,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.13.1" +version = "0.13.2" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index cbb7a802..5c754a53 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.13.1" +version = "0.13.2" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From c5aa7edb6b55c31014a3110dd23061d68941d022 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 2 Jul 2024 12:03:56 +0200 Subject: [PATCH 307/395] chore: Fix typo (#1701) --- swap/src/cli/cancel_and_refund.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swap/src/cli/cancel_and_refund.rs b/swap/src/cli/cancel_and_refund.rs index e92283ea..5484d7cb 100644 --- a/swap/src/cli/cancel_and_refund.rs +++ b/swap/src/cli/cancel_and_refund.rs @@ -174,7 +174,7 @@ pub async fn refund( ); } Ok(ExpiredTimelocks::Cancel { .. }) => { - bail!(bitcoin_publication_err.context("Failed to refund swap even though cancel timelock has expired. This should is unexpected.")); + bail!(bitcoin_publication_err.context("Failed to refund swap even though cancel timelock has expired. This is unexpected.")); } Err(e) => { bail!(bitcoin_publication_err From d7b649b7a682f83cd2b555cbea801dfec9c55847 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:47:45 +0200 Subject: [PATCH 308/395] feat: Allow for cooperative Monero redeem after Bitcoin punish has happened --- CHANGELOG.md | 2 + .../20240615140942_btcpunished_update.sql | 135 ++++++++++++++++++ swap/src/asb/event_loop.rs | 55 +++++++ swap/src/asb/network.rs | 11 +- swap/src/asb/recovery/cancel.rs | 2 +- swap/src/asb/recovery/punish.rs | 6 +- swap/src/asb/recovery/redeem.rs | 2 +- swap/src/asb/recovery/refund.rs | 2 +- swap/src/asb/recovery/safely_abort.rs | 2 +- swap/src/cli/behaviour.rs | 18 ++- swap/src/cli/cancel_and_refund.rs | 25 +++- swap/src/cli/event_loop.rs | 32 ++++- swap/src/database/alice.rs | 12 +- swap/src/database/bob.rs | 12 +- swap/src/database/sqlite.rs | 15 +- swap/src/network.rs | 1 + .../cooperative_xmr_redeem_after_punish.rs | 113 +++++++++++++++ swap/src/protocol/alice/state.rs | 8 +- swap/src/protocol/alice/swap.rs | 6 +- swap/src/protocol/bob/state.rs | 68 ++++++++- swap/src/protocol/bob/swap.rs | 98 +++++++------ .../alice_manually_punishes_after_bob_dead.rs | 6 +- .../alice_punishes_after_restart_bob_dead.rs | 6 +- swap/tests/harness/mod.rs | 6 +- swap/tests/punish.rs | 6 +- 25 files changed, 548 insertions(+), 101 deletions(-) create mode 100644 swap/migrations/20240615140942_btcpunished_update.sql create mode 100644 swap/src/network/cooperative_xmr_redeem_after_punish.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2baf45..070c4a51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed + ## [0.13.2] - 2024-07-02 - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap diff --git a/swap/migrations/20240615140942_btcpunished_update.sql b/swap/migrations/20240615140942_btcpunished_update.sql new file mode 100644 index 00000000..b4c9a8a5 --- /dev/null +++ b/swap/migrations/20240615140942_btcpunished_update.sql @@ -0,0 +1,135 @@ +-- This migration script modifies swap states to be compatible with the new state structure introduced in PR #1676. +-- The following changes are made: +-- 1. Bob: BtcPunished state now has a new attribute 'state' (type: State6), 'tx_lock_id' (type: string) remains the same +-- 2. Bob: State6 has two new attributes: 'v' (monero viewkey) and 'monero_wallet_restore_blockheight' (type: BlockHeight) +-- State6 is used in BtcPunished, CancelTimelockExpired, BtcCancelled, BtcRefunded states +-- 3. Alice: BtcPunished state now has a new attribute 'state3' (type: State3) + +-- Alice: Add new attribute 'state3' (type: State3) to the BtcPunished state by copying it from the BtcLocked state +UPDATE swap_states SET + state = json_replace( -- Replaces "{"Alice":{"Done":"BtcPunished"}}" with "{"Alice": {"Done": "BtcPunished": {"state": } }}" + state, + '$.Alice.Done', + json_object( + 'BtcPunished', + ( + SELECT json_extract(states.state, '$.Alice.BtcLocked') -- Read state3 object from BtcLocked + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id -- swap_states.swap_id is id of the BtcPunished row + AND json_extract(states.state, '$.Alice.BtcLocked') IS NOT NULL -- Filters out only the BtcLocked state + ) + ) + ) +WHERE json_extract(state, '$.Alice.Done') = 'BtcPunished'; -- Apply update only to BtcPunished state rows + +-- Bob: Add new attribute 'state6' (type: State6) to the BtcPunished state by copying it from the BtcCancelled state +-- and add new State6 attributes 'v' and 'monero_wallet_restore_blockheight' from the BtcLocked state +UPDATE swap_states SET + state = json_replace( + state, + '$.Bob', -- Replace '{"Bob":{"Done": {"BtcPunished": {"tx_lock_id":"..."} }}}' with {"Bob":{"BtcPunished":{"state":{}, "tx_lock_id": "..."}}} + json_object( + 'BtcPunished', -- {"Bob":{"BtcPunished":{}} + json_object( + 'state', -- {"Bob":{"BtcPunished":{"state": {}}} + json_insert( + ( -- object that we insert properties into (original state6 from BtcCancelled state) + SELECT json_extract(states.state, '$.Bob.BtcCancelled') -- Get state6 from BtcCancelled state + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id + AND json_extract(states.state, '$.Bob.BtcCancelled') IS NOT NULL -- Filters out only the BtcCancelled state + ), + '$.v', -- {"Bob":{"BtcPunished":{"state": {..., "v": "..."}, "tx_lock_id": "..."}}} + ( -- Get v property from BtcLocked state + SELECT json_extract(states.state, '$.Bob.BtcLocked.state3.v') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id -- swap_states.swap_id is id of the BtcPunished row + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL -- Filters out only the BtcLocked state + ), + '$.monero_wallet_restore_blockheight', -- { "Bob": { "BtcPunished":{"state": {..., "monero_wallet_restore_blockheight": {"height":...}} }, "tx_lock_id": "..."} } } + ( -- Get monero_wallet_restore_blockheight property from BtcLocked state + SELECT json_extract(states.state, '$.Bob.BtcLocked.monero_wallet_restore_blockheight') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id -- swap_states.swap_id is id of the BtcPunished row, states.swap_id is id of the row that we are looking for + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL -- Filters out only the BtcLocked state + ) + ), + 'tx_lock_id', -- Insert tx_lock_id BtcPunished -> {"Bob": {"Done": {"BtcPunished": {"state":{}, "tx_lock_id": "..."} } } + json_extract(state, '$.Bob.Done.BtcPunished.tx_lock_id') -- Gets tx_lock_id from original state row + ) + ) + ) +WHERE json_extract(state, '$.Bob.Done.BtcPunished') IS NOT NULL; -- Apply update only to BtcPunished state rows + +-- Bob: Add new State6 attributes 'v' and 'monero_wallet_restore_blockheight' to the BtcRefunded state +UPDATE swap_states SET + state = json_insert( + state, -- Object that we insert properties into (original state from the row) + '$.Bob.Done.BtcRefunded.v', -- {"Bob":{"BtcRefunded":{..., "v": "..."}}} + ( + SELECT json_extract(states.state, '$.Bob.BtcLocked.state3.v') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id -- swap_states.swap_id is id of the BtcRefunded row, states.swap_id is id of the row that we are looking for + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL + ), + '$.Bob.Done.BtcRefunded.monero_wallet_restore_blockheight', -- {"Bob":{"BtcRefunded":{..., "monero_wallet_restore_blockheight": {"height":...}} }} + ( + SELECT json_extract(states.state, '$.Bob.BtcLocked.monero_wallet_restore_blockheight') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL + ) + ) +WHERE json_extract(state, '$.Bob.Done.BtcRefunded') IS NOT NULL; -- Apply update only to BtcRefunded state rows + +-- Bob: Add new State6 attributes 'v' and 'monero_wallet_restore_blockheight' to the BtcCancelled state +UPDATE swap_states SET + state = json_insert( + state, + '$.Bob.BtcCancelled.v', + ( + SELECT json_extract(states.state, '$.Bob.BtcLocked.state3.v') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL + ), + '$.Bob.BtcCancelled.monero_wallet_restore_blockheight', + ( + SELECT json_extract(states.state, '$.Bob.BtcLocked.monero_wallet_restore_blockheight') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL + ) + ) +WHERE json_extract(state, '$.Bob.BtcCancelled') IS NOT NULL; -- Apply update only to BtcCancelled state rows + +-- Bob: Add new State6 attributes 'v' and 'monero_wallet_restore_blockheight' to the CancelTimelockExpired state +UPDATE swap_states SET + state = json_insert( + state, + '$.Bob.CancelTimelockExpired.v', + ( + SELECT json_extract(states.state, '$.Bob.BtcLocked.state3.v') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL + ), + '$.Bob.CancelTimelockExpired.monero_wallet_restore_blockheight', + ( + SELECT json_extract(states.state, '$.Bob.BtcLocked.monero_wallet_restore_blockheight') + FROM swap_states AS states + WHERE + states.swap_id = swap_states.swap_id + AND json_extract(states.state, '$.Bob.BtcLocked') IS NOT NULL + ) + ) +WHERE json_extract(state, '$.Bob.CancelTimelockExpired') IS NOT NULL; -- Apply update only to CancelTimelockExpired state rows \ No newline at end of file diff --git a/swap/src/asb/event_loop.rs b/swap/src/asb/event_loop.rs index 0d6de9a7..8e3ac4c3 100644 --- a/swap/src/asb/event_loop.rs +++ b/swap/src/asb/event_loop.rs @@ -1,5 +1,7 @@ use crate::asb::{Behaviour, OutEvent, Rate}; use crate::monero::Amount; +use crate::network::cooperative_xmr_redeem_after_punish::CooperativeXmrRedeemRejectReason; +use crate::network::cooperative_xmr_redeem_after_punish::Response::{Fullfilled, Rejected}; use crate::network::quote::BidQuote; use crate::network::swap_setup::alice::WalletSnapshot; use crate::network::transfer_proof; @@ -253,6 +255,59 @@ where channel }.boxed()); } + SwarmEvent::Behaviour(OutEvent::CooperativeXmrRedeemRequested { swap_id, channel, peer }) => { + let swap_peer = self.db.get_peer_id(swap_id).await; + let swap_state = self.db.get_state(swap_id).await; + + let (swap_peer, swap_state) = match (swap_peer, swap_state) { + (Ok(peer), Ok(state)) => (peer, state), + _ => { + tracing::warn!( + swap_id = %swap_id, + received_from = %peer, + reason = "swap not found", + "Rejecting cooperative XMR redeem request" + ); + if self.swarm.behaviour_mut().cooperative_xmr_redeem.send_response(channel, Rejected { swap_id, reason: CooperativeXmrRedeemRejectReason::UnknownSwap }).is_err() { + tracing::error!(swap_id = %swap_id, "Failed to reject cooperative XMR redeem request"); + } + continue; + } + }; + + if swap_peer != peer { + tracing::warn!( + swap_id = %swap_id, + received_from = %peer, + expected_from = %swap_peer, + reason = "unexpected peer", + "Rejecting cooperative XMR redeem request" + ); + if self.swarm.behaviour_mut().cooperative_xmr_redeem.send_response(channel, Rejected { swap_id, reason: CooperativeXmrRedeemRejectReason::MaliciousRequest }).is_err() { + tracing::error!(swap_id = %swap_id, "Failed to reject cooperative XMR redeem request"); + } + continue; + } + + let State::Alice (AliceState::BtcPunished { state3 }) = swap_state else { + tracing::warn!( + swap_id = %swap_id, + reason = "swap is in invalid state", + "Rejecting cooperative XMR redeem request" + ); + if self.swarm.behaviour_mut().cooperative_xmr_redeem.send_response(channel, Rejected { swap_id, reason: CooperativeXmrRedeemRejectReason::SwapInvalidState }).is_err() { + tracing::error!(swap_id = %swap_id, "Failed to reject cooperative XMR redeem request"); + } + continue; + }; + + if self.swarm.behaviour_mut().cooperative_xmr_redeem.send_response(channel, Fullfilled { swap_id, s_a: state3.s_a }).is_err() { + tracing::error!(peer = %peer, "Failed to respond to cooperative XMR redeem request"); + continue; + } + + tracing::info!(swap_id = %swap_id, peer = %peer, "Fullfilled cooperative XMR redeem request"); + } SwarmEvent::Behaviour(OutEvent::Rendezvous(libp2p::rendezvous::client::Event::Registered { rendezvous_node, ttl, namespace })) => { tracing::info!("Successfully registered with rendezvous node: {} with namespace: {} and TTL: {:?}", rendezvous_node, namespace, ttl); } diff --git a/swap/src/asb/network.rs b/swap/src/asb/network.rs index 7b85f8fb..268a3cba 100644 --- a/swap/src/asb/network.rs +++ b/swap/src/asb/network.rs @@ -5,7 +5,9 @@ use crate::network::rendezvous::XmrBtcNamespace; use crate::network::swap_setup::alice; use crate::network::swap_setup::alice::WalletSnapshot; use crate::network::transport::authenticate_and_multiplex; -use crate::network::{encrypted_signature, quote, transfer_proof}; +use crate::network::{ + cooperative_xmr_redeem_after_punish, encrypted_signature, quote, transfer_proof, +}; use crate::protocol::alice::State3; use anyhow::{anyhow, Error, Result}; use futures::FutureExt; @@ -76,6 +78,11 @@ pub mod behaviour { channel: ResponseChannel<()>, peer: PeerId, }, + CooperativeXmrRedeemRequested { + channel: ResponseChannel, + swap_id: Uuid, + peer: PeerId, + }, Rendezvous(libp2p::rendezvous::client::Event), Failure { peer: PeerId, @@ -114,6 +121,7 @@ pub mod behaviour { pub quote: quote::Behaviour, pub swap_setup: alice::Behaviour, pub transfer_proof: transfer_proof::Behaviour, + pub cooperative_xmr_redeem: cooperative_xmr_redeem_after_punish::Behaviour, pub encrypted_signature: encrypted_signature::Behaviour, pub identify: Identify, @@ -160,6 +168,7 @@ pub mod behaviour { ), transfer_proof: transfer_proof::alice(), encrypted_signature: encrypted_signature::alice(), + cooperative_xmr_redeem: cooperative_xmr_redeem_after_punish::alice(), ping: Ping::new(PingConfig::new().with_keep_alive(true)), identify: Identify::new(identifyConfig), } diff --git a/swap/src/asb/recovery/cancel.rs b/swap/src/asb/recovery/cancel.rs index 8da1508f..f71b3e38 100644 --- a/swap/src/asb/recovery/cancel.rs +++ b/swap/src/asb/recovery/cancel.rs @@ -38,7 +38,7 @@ pub async fn cancel( // Alice already in final state | AliceState::BtcRedeemed | AliceState::XmrRefunded - | AliceState::BtcPunished + | AliceState::BtcPunished { .. } | AliceState::SafelyAborted => bail!("Swap is in state {} which is not cancelable", state), }; diff --git a/swap/src/asb/recovery/punish.rs b/swap/src/asb/recovery/punish.rs index e94abac8..e1d1ad28 100644 --- a/swap/src/asb/recovery/punish.rs +++ b/swap/src/asb/recovery/punish.rs @@ -38,7 +38,7 @@ pub async fn punish( // Alice already in final state | AliceState::BtcRedeemed | AliceState::XmrRefunded - | AliceState::BtcPunished + | AliceState::BtcPunished { .. } | AliceState::SafelyAborted => bail!(Error::SwapNotPunishable(state)), }; @@ -46,7 +46,9 @@ pub async fn punish( let txid = state3.punish_btc(&bitcoin_wallet).await?; - let state = AliceState::BtcPunished; + let state = AliceState::BtcPunished { + state3: state3.clone(), + }; db.insert_latest_state(swap_id, state.clone().into()) .await?; diff --git a/swap/src/asb/recovery/redeem.rs b/swap/src/asb/recovery/redeem.rs index e4642feb..47f4a048 100644 --- a/swap/src/asb/recovery/redeem.rs +++ b/swap/src/asb/recovery/redeem.rs @@ -81,7 +81,7 @@ pub async fn redeem( | AliceState::BtcPunishable { .. } | AliceState::BtcRedeemed | AliceState::XmrRefunded - | AliceState::BtcPunished + | AliceState::BtcPunished { .. } | AliceState::SafelyAborted => bail!( "Cannot redeem swap {} because it is in state {} which cannot be manually redeemed", swap_id, diff --git a/swap/src/asb/recovery/refund.rs b/swap/src/asb/recovery/refund.rs index 64e5c3f3..3067a8f6 100644 --- a/swap/src/asb/recovery/refund.rs +++ b/swap/src/asb/recovery/refund.rs @@ -55,7 +55,7 @@ pub async fn refund( AliceState::BtcRedeemTransactionPublished { .. } | AliceState::BtcRedeemed | AliceState::XmrRefunded - | AliceState::BtcPunished + | AliceState::BtcPunished { .. } | AliceState::SafelyAborted => bail!(Error::SwapNotRefundable(state)), }; diff --git a/swap/src/asb/recovery/safely_abort.rs b/swap/src/asb/recovery/safely_abort.rs index ad162f8d..8a9e1d95 100644 --- a/swap/src/asb/recovery/safely_abort.rs +++ b/swap/src/asb/recovery/safely_abort.rs @@ -31,7 +31,7 @@ pub async fn safely_abort(swap_id: Uuid, db: Arc) -> Result bail!( "Cannot safely abort swap {} because it is in state {} which cannot be safely aborted", swap_id, diff --git a/swap/src/cli/behaviour.rs b/swap/src/cli/behaviour.rs index 2ca8448f..72dc5891 100644 --- a/swap/src/cli/behaviour.rs +++ b/swap/src/cli/behaviour.rs @@ -1,7 +1,11 @@ +use crate::monero::Scalar; +use crate::network::cooperative_xmr_redeem_after_punish::CooperativeXmrRedeemRejectReason; use crate::network::quote::BidQuote; use crate::network::rendezvous::XmrBtcNamespace; use crate::network::swap_setup::bob; -use crate::network::{encrypted_signature, quote, redial, transfer_proof}; +use crate::network::{ + cooperative_xmr_redeem_after_punish, encrypted_signature, quote, redial, transfer_proof, +}; use crate::protocol::bob::State2; use crate::{bitcoin, env}; use anyhow::{anyhow, Error, Result}; @@ -28,6 +32,16 @@ pub enum OutEvent { EncryptedSignatureAcknowledged { id: RequestId, }, + CooperativeXmrRedeemFulfilled { + id: RequestId, + s_a: Scalar, + swap_id: uuid::Uuid, + }, + CooperativeXmrRedeemRejected { + id: RequestId, + reason: CooperativeXmrRedeemRejectReason, + swap_id: uuid::Uuid, + }, AllRedialAttemptsExhausted { peer: PeerId, }, @@ -64,6 +78,7 @@ pub struct Behaviour { pub quote: quote::Behaviour, pub swap_setup: bob::Behaviour, pub transfer_proof: transfer_proof::Behaviour, + pub cooperative_xmr_redeem: cooperative_xmr_redeem_after_punish::Behaviour, pub encrypted_signature: encrypted_signature::Behaviour, pub redial: redial::Behaviour, pub identify: Identify, @@ -91,6 +106,7 @@ impl Behaviour { swap_setup: bob::Behaviour::new(env_config, bitcoin_wallet), transfer_proof: transfer_proof::bob(), encrypted_signature: encrypted_signature::bob(), + cooperative_xmr_redeem: cooperative_xmr_redeem_after_punish::bob(), redial: redial::Behaviour::new(alice, Duration::from_secs(2)), ping: Ping::new(PingConfig::new().with_keep_alive(true)), identify: Identify::new(identifyConfig), diff --git a/swap/src/cli/cancel_and_refund.rs b/swap/src/cli/cancel_and_refund.rs index 5484d7cb..7ab4e4b0 100644 --- a/swap/src/cli/cancel_and_refund.rs +++ b/swap/src/cli/cancel_and_refund.rs @@ -31,8 +31,16 @@ pub async fn cancel( let state = db.get_state(swap_id).await?.try_into()?; let state6 = match state { - BobState::BtcLocked { state3, .. } => state3.cancel(), - BobState::XmrLockProofReceived { state, .. } => state.cancel(), + BobState::BtcLocked { + state3, + monero_wallet_restore_blockheight, + .. + } => state3.cancel(monero_wallet_restore_blockheight), + BobState::XmrLockProofReceived { + state, + monero_wallet_restore_blockheight, + .. + } => state.cancel(monero_wallet_restore_blockheight), BobState::XmrLocked(state4) => state4.cancel(), BobState::EncSigSent(state4) => state4.cancel(), BobState::CancelTimelockExpired(state6) => state6, @@ -81,6 +89,7 @@ pub async fn cancel( // We cannot cancel because Alice has already cancelled and punished afterwards Ok(ExpiredTimelocks::Punish { .. }) => { let state = BobState::BtcPunished { + state: state6.clone(), tx_lock_id: state6.tx_lock_id(), }; db.insert_latest_state(swap_id, state.clone().into()) @@ -118,8 +127,15 @@ pub async fn refund( let state = db.get_state(swap_id).await?.try_into()?; let state6 = match state { - BobState::BtcLocked { state3, .. } => state3.cancel(), - BobState::XmrLockProofReceived { state, .. } => state.cancel(), + BobState::BtcLocked { + state3, + monero_wallet_restore_blockheight, + } => state3.cancel(monero_wallet_restore_blockheight), + BobState::XmrLockProofReceived { + state, + monero_wallet_restore_blockheight, + .. + } => state.cancel(monero_wallet_restore_blockheight), BobState::XmrLocked(state4) => state4.cancel(), BobState::EncSigSent(state4) => state4.cancel(), BobState::CancelTimelockExpired(state6) => state6, @@ -157,6 +173,7 @@ pub async fn refund( // We have been punished Ok(ExpiredTimelocks::Punish { .. }) => { let state = BobState::BtcPunished { + state: state6.clone(), tx_lock_id: state6.tx_lock_id(), }; db.insert_latest_state(swap_id, state.clone().into()) diff --git a/swap/src/cli/event_loop.rs b/swap/src/cli/event_loop.rs index fd7b4308..53ee65b8 100644 --- a/swap/src/cli/event_loop.rs +++ b/swap/src/cli/event_loop.rs @@ -1,6 +1,7 @@ use crate::bitcoin::EncryptedSignature; use crate::cli::behaviour::{Behaviour, OutEvent}; use crate::monero; +use crate::network::cooperative_xmr_redeem_after_punish::{Request, Response}; use crate::network::encrypted_signature; use crate::network::quote::BidQuote; use crate::network::swap_setup::bob::NewSwap; @@ -27,6 +28,7 @@ pub struct EventLoop { // these streams represents outgoing requests that we have to make quote_requests: bmrng::RequestReceiverStream<(), BidQuote>, + cooperative_xmr_redeem_requests: bmrng::RequestReceiverStream, encrypted_signatures: bmrng::RequestReceiverStream, swap_setup_requests: bmrng::RequestReceiverStream>, @@ -36,7 +38,7 @@ pub struct EventLoop { inflight_quote_requests: HashMap>, inflight_encrypted_signature_requests: HashMap>, inflight_swap_setup: Option>>, - + inflight_cooperative_xmr_redeem_requests: HashMap>, /// The sender we will use to relay incoming transfer proofs. transfer_proof: bmrng::RequestSender, /// The future representing the successful handling of an incoming transfer @@ -60,7 +62,7 @@ impl EventLoop { let transfer_proof = bmrng::channel_with_timeout(1, Duration::from_secs(60)); let encrypted_signature = bmrng::channel(1); let quote = bmrng::channel_with_timeout(1, Duration::from_secs(60)); - + let cooperative_xmr_redeem = bmrng::channel_with_timeout(1, Duration::from_secs(60)); let event_loop = EventLoop { swap_id, swarm, @@ -68,10 +70,12 @@ impl EventLoop { swap_setup_requests: execution_setup.1.into(), transfer_proof: transfer_proof.0, encrypted_signatures: encrypted_signature.1.into(), + cooperative_xmr_redeem_requests: cooperative_xmr_redeem.1.into(), quote_requests: quote.1.into(), inflight_quote_requests: HashMap::default(), inflight_swap_setup: None, inflight_encrypted_signature_requests: HashMap::default(), + inflight_cooperative_xmr_redeem_requests: HashMap::default(), pending_transfer_proof: OptionFuture::from(None), db, }; @@ -80,6 +84,7 @@ impl EventLoop { swap_setup: execution_setup.0, transfer_proof: transfer_proof.1, encrypted_signature: encrypted_signature.0, + cooperative_xmr_redeem: cooperative_xmr_redeem.0, quote: quote.0, }; @@ -176,6 +181,16 @@ impl EventLoop { let _ = responder.respond(()); } } + SwarmEvent::Behaviour(OutEvent::CooperativeXmrRedeemFulfilled { id, swap_id, s_a }) => { + if let Some(responder) = self.inflight_cooperative_xmr_redeem_requests.remove(&id) { + let _ = responder.respond(Response::Fullfilled { s_a, swap_id }); + } + } + SwarmEvent::Behaviour(OutEvent::CooperativeXmrRedeemRejected { id, swap_id, reason }) => { + if let Some(responder) = self.inflight_cooperative_xmr_redeem_requests.remove(&id) { + let _ = responder.respond(Response::Rejected { reason, swap_id }); + } + } SwarmEvent::Behaviour(OutEvent::AllRedialAttemptsExhausted { peer }) if peer == self.alice_peer_id => { tracing::error!("Exhausted all re-dial attempts to Alice"); return; @@ -234,7 +249,14 @@ impl EventLoop { let _ = self.swarm.behaviour_mut().transfer_proof.send_response(response_channel, ()); self.pending_transfer_proof = OptionFuture::from(None); - } + }, + + Some((swap_id, responder)) = self.cooperative_xmr_redeem_requests.next().fuse(), if self.is_connected_to_alice() => { + let id = self.swarm.behaviour_mut().cooperative_xmr_redeem.send_request(&self.alice_peer_id, Request { + swap_id + }); + self.inflight_cooperative_xmr_redeem_requests.insert(id, responder); + }, } } } @@ -250,6 +272,7 @@ pub struct EventLoopHandle { transfer_proof: bmrng::RequestReceiver, encrypted_signature: bmrng::RequestSender, quote: bmrng::RequestSender<(), BidQuote>, + cooperative_xmr_redeem: bmrng::RequestSender, } impl EventLoopHandle { @@ -274,6 +297,9 @@ impl EventLoopHandle { tracing::debug!("Requesting quote"); Ok(self.quote.send_receive(()).await?) } + pub async fn request_cooperative_xmr_redeem(&mut self, swap_id: Uuid) -> Result { + Ok(self.cooperative_xmr_redeem.send_receive(swap_id).await?) + } pub async fn send_encrypted_signature( &mut self, diff --git a/swap/src/database/alice.rs b/swap/src/database/alice.rs index 4ed61790..fcf3ead3 100644 --- a/swap/src/database/alice.rs +++ b/swap/src/database/alice.rs @@ -70,12 +70,12 @@ pub enum Alice { Done(AliceEndState), } -#[derive(Copy, Clone, strum::Display, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Clone, strum::Display, Debug, Deserialize, Serialize, PartialEq)] pub enum AliceEndState { SafelyAborted, BtcRedeemed, XmrRefunded, - BtcPunished, + BtcPunished { state3: alice::State3 }, } impl From for Alice { @@ -173,7 +173,9 @@ impl From for Alice { transfer_proof, state3: state3.as_ref().clone(), }, - AliceState::BtcPunished => Alice::Done(AliceEndState::BtcPunished), + AliceState::BtcPunished { state3 } => Alice::Done(AliceEndState::BtcPunished { + state3: state3.as_ref().clone(), + }), AliceState::SafelyAborted => Alice::Done(AliceEndState::SafelyAborted), } } @@ -277,7 +279,9 @@ impl From for AliceState { AliceEndState::SafelyAborted => AliceState::SafelyAborted, AliceEndState::BtcRedeemed => AliceState::BtcRedeemed, AliceEndState::XmrRefunded => AliceState::XmrRefunded, - AliceEndState::BtcPunished => AliceState::BtcPunished, + AliceEndState::BtcPunished { state3 } => AliceState::BtcPunished { + state3: Box::new(state3), + }, }, } } diff --git a/swap/src/database/bob.rs b/swap/src/database/bob.rs index 25117763..735f45a2 100644 --- a/swap/src/database/bob.rs +++ b/swap/src/database/bob.rs @@ -33,6 +33,10 @@ pub enum Bob { EncSigSent { state4: bob::State4, }, + BtcPunished { + state: bob::State6, + tx_lock_id: bitcoin::Txid, + }, BtcRedeemed(bob::State5), CancelTimelockExpired(bob::State6), BtcCancelled(bob::State6), @@ -44,7 +48,6 @@ pub enum BobEndState { SafelyAborted, XmrRedeemed { tx_lock_id: bitcoin::Txid }, BtcRefunded(Box), - BtcPunished { tx_lock_id: bitcoin::Txid }, } impl From for Bob { @@ -79,13 +82,11 @@ impl From for Bob { BobState::BtcRedeemed(state5) => Bob::BtcRedeemed(state5), BobState::CancelTimelockExpired(state6) => Bob::CancelTimelockExpired(state6), BobState::BtcCancelled(state6) => Bob::BtcCancelled(state6), + BobState::BtcPunished { state, tx_lock_id } => Bob::BtcPunished { state, tx_lock_id }, BobState::BtcRefunded(state6) => Bob::Done(BobEndState::BtcRefunded(Box::new(state6))), BobState::XmrRedeemed { tx_lock_id } => { Bob::Done(BobEndState::XmrRedeemed { tx_lock_id }) } - BobState::BtcPunished { tx_lock_id } => { - Bob::Done(BobEndState::BtcPunished { tx_lock_id }) - } BobState::SafelyAborted => Bob::Done(BobEndState::SafelyAborted), } } @@ -123,11 +124,11 @@ impl From for BobState { Bob::BtcRedeemed(state5) => BobState::BtcRedeemed(state5), Bob::CancelTimelockExpired(state6) => BobState::CancelTimelockExpired(state6), Bob::BtcCancelled(state6) => BobState::BtcCancelled(state6), + Bob::BtcPunished { state, tx_lock_id } => BobState::BtcPunished { state, tx_lock_id }, Bob::Done(end_state) => match end_state { BobEndState::SafelyAborted => BobState::SafelyAborted, BobEndState::XmrRedeemed { tx_lock_id } => BobState::XmrRedeemed { tx_lock_id }, BobEndState::BtcRefunded(state6) => BobState::BtcRefunded(*state6), - BobEndState::BtcPunished { tx_lock_id } => BobState::BtcPunished { tx_lock_id }, }, } } @@ -148,6 +149,7 @@ impl fmt::Display for Bob { Bob::BtcRedeemed(_) => f.write_str("Monero redeemable"), Bob::Done(end_state) => write!(f, "Done: {}", end_state), Bob::EncSigSent { .. } => f.write_str("Encrypted signature sent"), + Bob::BtcPunished { .. } => f.write_str("Bitcoin punished"), } } } diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index 6cddd50e..576dc362 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -417,9 +417,8 @@ mod tests { let db = setup_test_db().await.unwrap(); let state_1 = State::Alice(AliceState::BtcRedeemed); - let state_2 = State::Alice(AliceState::BtcPunished); - let state_3 = State::Alice(AliceState::SafelyAborted); - let state_4 = State::Bob(BobState::SafelyAborted); + let state_2 = State::Alice(AliceState::SafelyAborted); + let state_3 = State::Bob(BobState::SafelyAborted); let swap_id_1 = Uuid::new_v4(); let swap_id_2 = Uuid::new_v4(); @@ -429,10 +428,7 @@ mod tests { db.insert_latest_state(swap_id_1, state_2.clone()) .await .unwrap(); - db.insert_latest_state(swap_id_1, state_3.clone()) - .await - .unwrap(); - db.insert_latest_state(swap_id_2, state_4.clone()) + db.insert_latest_state(swap_id_2, state_3.clone()) .await .unwrap(); @@ -440,11 +436,10 @@ mod tests { assert_eq!(latest_loaded.len(), 2); - assert!(latest_loaded.contains(&(swap_id_1, state_3))); - assert!(latest_loaded.contains(&(swap_id_2, state_4))); + assert!(latest_loaded.contains(&(swap_id_1, state_2))); + assert!(latest_loaded.contains(&(swap_id_2, state_3))); assert!(!latest_loaded.contains(&(swap_id_1, state_1))); - assert!(!latest_loaded.contains(&(swap_id_1, state_2))); } #[tokio::test] diff --git a/swap/src/network.rs b/swap/src/network.rs index 22243783..527c04fc 100644 --- a/swap/src/network.rs +++ b/swap/src/network.rs @@ -1,6 +1,7 @@ mod impl_from_rr_event; pub mod cbor_request_response; +pub mod cooperative_xmr_redeem_after_punish; pub mod encrypted_signature; pub mod json_pull_codec; pub mod quote; diff --git a/swap/src/network/cooperative_xmr_redeem_after_punish.rs b/swap/src/network/cooperative_xmr_redeem_after_punish.rs new file mode 100644 index 00000000..fb9149e2 --- /dev/null +++ b/swap/src/network/cooperative_xmr_redeem_after_punish.rs @@ -0,0 +1,113 @@ +use crate::monero::Scalar; +use crate::network::cbor_request_response::CborCodec; +use crate::{asb, cli}; +use libp2p::core::ProtocolName; +use libp2p::request_response::{ + ProtocolSupport, RequestResponse, RequestResponseConfig, RequestResponseEvent, + RequestResponseMessage, +}; +use libp2p::PeerId; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +const PROTOCOL: &str = "/comit/xmr/btc/cooperative_xmr_redeem_after_punish/1.0.0"; +type OutEvent = RequestResponseEvent; +type Message = RequestResponseMessage; + +pub type Behaviour = RequestResponse>; + +#[derive(Debug, Clone, Copy, Default)] +pub struct CooperativeXmrRedeemProtocol; + +impl ProtocolName for CooperativeXmrRedeemProtocol { + fn protocol_name(&self) -> &[u8] { + PROTOCOL.as_bytes() + } +} + +#[derive(Debug, thiserror::Error, Clone, Serialize, Deserialize)] +pub enum CooperativeXmrRedeemRejectReason { + #[error("Alice does not have a record of the swap")] + UnknownSwap, + #[error("Alice rejected the request because it deemed it malicious")] + MaliciousRequest, + #[error("Alice is in a state where a cooperative redeem is not possible")] + SwapInvalidState, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct Request { + pub swap_id: Uuid, +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub enum Response { + Fullfilled { + swap_id: Uuid, + s_a: Scalar, + }, + Rejected { + swap_id: Uuid, + reason: CooperativeXmrRedeemRejectReason, + }, +} +pub fn alice() -> Behaviour { + Behaviour::new( + CborCodec::default(), + vec![(CooperativeXmrRedeemProtocol, ProtocolSupport::Inbound)], + RequestResponseConfig::default(), + ) +} + +pub fn bob() -> Behaviour { + Behaviour::new( + CborCodec::default(), + vec![(CooperativeXmrRedeemProtocol, ProtocolSupport::Outbound)], + RequestResponseConfig::default(), + ) +} + +impl From<(PeerId, Message)> for asb::OutEvent { + fn from((peer, message): (PeerId, Message)) -> Self { + match message { + Message::Request { + request, channel, .. + } => Self::CooperativeXmrRedeemRequested { + swap_id: request.swap_id, + channel, + peer, + }, + Message::Response { .. } => Self::unexpected_response(peer), + } + } +} + +crate::impl_from_rr_event!(OutEvent, asb::OutEvent, PROTOCOL); + +impl From<(PeerId, Message)> for cli::OutEvent { + fn from((peer, message): (PeerId, Message)) -> Self { + match message { + Message::Request { .. } => Self::unexpected_request(peer), + Message::Response { + response, + request_id, + } => match response { + Response::Fullfilled { swap_id, s_a } => Self::CooperativeXmrRedeemFulfilled { + id: request_id, + swap_id, + s_a, + }, + Response::Rejected { + swap_id, + reason: error, + } => Self::CooperativeXmrRedeemRejected { + id: request_id, + swap_id, + reason: error, + }, + }, + } + } +} + +crate::impl_from_rr_event!(OutEvent, cli::OutEvent, PROTOCOL); diff --git a/swap/src/protocol/alice/state.rs b/swap/src/protocol/alice/state.rs index b4e155a6..f0acab23 100644 --- a/swap/src/protocol/alice/state.rs +++ b/swap/src/protocol/alice/state.rs @@ -74,7 +74,9 @@ pub enum AliceState { transfer_proof: TransferProof, state3: Box, }, - BtcPunished, + BtcPunished { + state3: Box, + }, SafelyAborted, } @@ -98,7 +100,7 @@ impl fmt::Display for AliceState { AliceState::BtcRedeemed => write!(f, "btc is redeemed"), AliceState::BtcCancelled { .. } => write!(f, "btc is cancelled"), AliceState::BtcRefunded { .. } => write!(f, "btc is refunded"), - AliceState::BtcPunished => write!(f, "btc is punished"), + AliceState::BtcPunished { .. } => write!(f, "btc is punished"), AliceState::SafelyAborted => write!(f, "safely aborted"), AliceState::BtcPunishable { .. } => write!(f, "btc is punishable"), AliceState::XmrRefunded => write!(f, "xmr is refunded"), @@ -377,7 +379,7 @@ impl State2 { pub struct State3 { a: bitcoin::SecretKey, B: bitcoin::PublicKey, - s_a: monero::Scalar, + pub s_a: monero::Scalar, S_b_monero: monero::PublicKey, S_b_bitcoin: bitcoin::PublicKey, pub v: monero::PrivateViewKey, diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 0eef7dcd..79236563 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -362,7 +362,7 @@ where let punish = state3.punish_btc(bitcoin_wallet).await; match punish { - Ok(_) => AliceState::BtcPunished, + Ok(_) => AliceState::BtcPunished { state3 }, Err(error) => { tracing::warn!("Failed to publish punish transaction: {:#}", error); @@ -392,7 +392,7 @@ where } AliceState::XmrRefunded => AliceState::XmrRefunded, AliceState::BtcRedeemed => AliceState::BtcRedeemed, - AliceState::BtcPunished => AliceState::BtcPunished, + AliceState::BtcPunished { state3 } => AliceState::BtcPunished { state3 }, AliceState::SafelyAborted => AliceState::SafelyAborted, }) } @@ -402,7 +402,7 @@ pub(crate) fn is_complete(state: &AliceState) -> bool { state, AliceState::XmrRefunded | AliceState::BtcRedeemed - | AliceState::BtcPunished + | AliceState::BtcPunished { .. } | AliceState::SafelyAborted ) } diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index 03f56d28..8fe5ca32 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -48,6 +48,7 @@ pub enum BobState { tx_lock_id: bitcoin::Txid, }, BtcPunished { + state: State6, tx_lock_id: bitcoin::Txid, }, SafelyAborted, @@ -421,11 +422,13 @@ impl State3 { } } - pub fn cancel(&self) -> State6 { + pub fn cancel(&self, monero_wallet_restore_blockheight: BlockHeight) -> State6 { State6 { A: self.A, b: self.b.clone(), s_b: self.s_b, + v: self.v, + monero_wallet_restore_blockheight, cancel_timelock: self.cancel_timelock, punish_timelock: self.punish_timelock, refund_address: self.refund_address.clone(), @@ -463,6 +466,19 @@ impl State3 { tx_cancel_status, )) } + pub fn attempt_cooperative_redeem( + &self, + s_a: monero::PrivateKey, + monero_wallet_restore_blockheight: BlockHeight, + ) -> State5 { + State5 { + s_a, + s_b: self.s_b, + v: self.v, + tx_lock: self.tx_lock.clone(), + monero_wallet_restore_blockheight, + } + } } #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] @@ -571,6 +587,8 @@ impl State4 { A: self.A, b: self.b, s_b: self.s_b, + v: self.v, + monero_wallet_restore_blockheight: self.monero_wallet_restore_blockheight, cancel_timelock: self.cancel_timelock, punish_timelock: self.punish_timelock, refund_address: self.refund_address, @@ -604,6 +622,43 @@ impl State5 { pub fn tx_lock_id(&self) -> bitcoin::Txid { self.tx_lock.txid() } + pub async fn redeem_xmr( + &self, + monero_wallet: &monero::Wallet, + wallet_file_name: std::string::String, + monero_receive_address: monero::Address, + ) -> Result<()> { + let (spend_key, view_key) = self.xmr_keys(); + + tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero"); + if let Err(e) = monero_wallet + .create_from_and_load( + wallet_file_name.clone(), + spend_key, + view_key, + self.monero_wallet_restore_blockheight, + ) + .await + { + // In case we failed to refresh/sweep, when resuming the wallet might already + // exist! This is a very unlikely scenario, but if we don't take care of it we + // might not be able to ever transfer the Monero. + tracing::warn!("Failed to generate monero wallet from keys: {:#}", e); + tracing::info!(%wallet_file_name, + "Falling back to trying to open the wallet if it already exists", + ); + monero_wallet.open(wallet_file_name).await?; + } + + // Ensure that the generated wallet is synced so we have a proper balance + monero_wallet.refresh(20).await?; + // Sweep (transfer all funds) to the given address + let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?; + for tx_hash in tx_hashes { + tracing::info!(%monero_receive_address, txid=%tx_hash.0, "Successfully transferred XMR to wallet"); + } + Ok(()) + } } #[derive(Debug, Clone, Deserialize, Serialize, PartialEq)] @@ -611,6 +666,8 @@ pub struct State6 { A: bitcoin::PublicKey, b: bitcoin::SecretKey, s_b: monero::Scalar, + v: monero::PrivateViewKey, + pub monero_wallet_restore_blockheight: BlockHeight, cancel_timelock: CancelTimelock, punish_timelock: PunishTimelock, refund_address: bitcoin::Address, @@ -706,4 +763,13 @@ impl State6 { pub fn tx_lock_id(&self) -> bitcoin::Txid { self.tx_lock.txid() } + pub fn attempt_cooperative_redeem(&self, s_a: monero::PrivateKey) -> State5 { + State5 { + s_a, + s_b: self.s_b, + v: self.v, + tx_lock: self.tx_lock.clone(), + monero_wallet_restore_blockheight: self.monero_wallet_restore_blockheight, + } + } } diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 7a702d77..43c54e4b 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -1,5 +1,6 @@ use crate::bitcoin::{ExpiredTimelocks, TxCancel, TxRefund}; use crate::cli::EventLoopHandle; +use crate::network::cooperative_xmr_redeem_after_punish::Response::{Fullfilled, Rejected}; use crate::network::swap_setup::bob::NewSwap; use crate::protocol::bob::state::*; use crate::protocol::{bob, Database}; @@ -12,10 +13,7 @@ use uuid::Uuid; pub fn is_complete(state: &BobState) -> bool { matches!( state, - BobState::BtcRefunded(..) - | BobState::XmrRedeemed { .. } - | BobState::BtcPunished { .. } - | BobState::SafelyAborted + BobState::BtcRefunded(..) | BobState::XmrRedeemed { .. } | BobState::SafelyAborted ) } @@ -28,7 +26,7 @@ pub async fn run_until( mut swap: bob::Swap, is_target_state: fn(&BobState) -> bool, ) -> Result { - let mut current_state = swap.state; + let mut current_state = swap.state.clone(); while !is_target_state(¤t_state) { current_state = next_state( @@ -41,10 +39,14 @@ pub async fn run_until( swap.monero_receive_address, ) .await?; - swap.db .insert_latest_state(swap.id, current_state.clone().into()) .await?; + if matches!(current_state, BobState::BtcPunished { .. }) + && matches!(swap.state, BobState::BtcPunished { .. }) + { + break; // Stops swap when cooperative redeem fails without preventing resuming swap in BtcPunished state. + }; } Ok(current_state) @@ -159,12 +161,12 @@ async fn next_state( result?; tracing::info!("Alice took too long to lock Monero, cancelling the swap"); - let state4 = state3.cancel(); + let state4 = state3.cancel(monero_wallet_restore_blockheight); BobState::CancelTimelockExpired(state4) }, } } else { - let state4 = state3.cancel(); + let state4 = state3.cancel(monero_wallet_restore_blockheight); BobState::CancelTimelockExpired(state4) } } @@ -188,17 +190,17 @@ async fn next_state( tx_lock_status.wait_until_confirmed_with(state.cancel_timelock).await?; - BobState::CancelTimelockExpired(state.cancel()) + BobState::CancelTimelockExpired(state.cancel(monero_wallet_restore_blockheight)) }, } } result = tx_lock_status.wait_until_confirmed_with(state.cancel_timelock) => { result?; - BobState::CancelTimelockExpired(state.cancel()) + BobState::CancelTimelockExpired(state.cancel(monero_wallet_restore_blockheight)) } } } else { - BobState::CancelTimelockExpired(state.cancel()) + BobState::CancelTimelockExpired(state.cancel(monero_wallet_restore_blockheight)) } } BobState::XmrLocked(state) => { @@ -257,39 +259,9 @@ async fn next_state( } } BobState::BtcRedeemed(state) => { - let (spend_key, view_key) = state.xmr_keys(); - - let wallet_file_name = swap_id.to_string(); - - tracing::info!(%wallet_file_name, "Generating and opening Monero wallet from the extracted keys to redeem the Monero"); - - if let Err(e) = monero_wallet - .create_from_and_load( - wallet_file_name.clone(), - spend_key, - view_key, - state.monero_wallet_restore_blockheight, - ) - .await - { - // In case we failed to refresh/sweep, when resuming the wallet might already - // exist! This is a very unlikely scenario, but if we don't take care of it we - // might not be able to ever transfer the Monero. - tracing::warn!("Failed to generate monero wallet from keys: {:#}", e); - tracing::info!(%wallet_file_name, - "Falling back to trying to open the wallet if it already exists", - ); - monero_wallet.open(wallet_file_name).await?; - } - - // Ensure that the generated wallet is synced so we have a proper balance - monero_wallet.refresh(20).await?; - // Sweep (transfer all funds) to the given address - let tx_hashes = monero_wallet.sweep_all(monero_receive_address).await?; - - for tx_hash in tx_hashes { - tracing::info!(%monero_receive_address, txid=%tx_hash.0, "Successfully transferred XMR to wallet"); - } + state + .redeem_xmr(monero_wallet, swap_id.to_string(), monero_receive_address) + .await?; BobState::XmrRedeemed { tx_lock_id: state.tx_lock_id(), @@ -318,12 +290,48 @@ async fn next_state( tracing::info!("You have been punished for not refunding in time"); BobState::BtcPunished { tx_lock_id: state.tx_lock_id(), + state, } } } } BobState::BtcRefunded(state4) => BobState::BtcRefunded(state4), - BobState::BtcPunished { tx_lock_id } => BobState::BtcPunished { tx_lock_id }, + BobState::BtcPunished { state, tx_lock_id } => { + tracing::info!("Attempting cooperative XMR redeem"); + let response = event_loop_handle + .request_cooperative_xmr_redeem(swap_id) + .await; + + match response { + Ok(Fullfilled { s_a, .. }) => { + tracing::debug!("Alice revealed XMR key to us"); + + let s_a = monero::PrivateKey { scalar: s_a }; + let state5 = state.attempt_cooperative_redeem(s_a); + + match state5 + .redeem_xmr(monero_wallet, swap_id.to_string(), monero_receive_address) + .await + { + Ok(_) => { + return Ok(BobState::XmrRedeemed { tx_lock_id }); + } + Err(error) => { + return Err(error) + .context("Failed to redeem XMR with revealed XMR key"); + } + } + } + Ok(Rejected { reason: error, .. }) => { + return Err(error) + .context("Alice rejected our request for cooperative XMR redeem"); + } + Err(error) => { + return Err(error) + .context("Failed to request cooperative XMR redeem from Alice"); + } + }; + } BobState::SafelyAborted => BobState::SafelyAborted, BobState::XmrRedeemed { tx_lock_id } => BobState::XmrRedeemed { tx_lock_id }, }) diff --git a/swap/tests/alice_manually_punishes_after_bob_dead.rs b/swap/tests/alice_manually_punishes_after_bob_dead.rs index b27904ac..aa747ec9 100644 --- a/swap/tests/alice_manually_punishes_after_bob_dead.rs +++ b/swap/tests/alice_manually_punishes_after_bob_dead.rs @@ -11,7 +11,7 @@ use swap::protocol::{alice, bob}; /// Bob locks Btc and Alice locks Xmr. Bob does not act; he fails to send Alice /// the encsig and fail to refund or redeem. Alice punishes using the cancel and -/// punish command. +/// punish command. Bob then cooperates with Alice and redeems XMR with her key. #[tokio::test] async fn alice_manually_punishes_after_bob_dead() { harness::setup_test(FastPunishConfig, |mut ctx| async move { @@ -78,9 +78,7 @@ async fn alice_manually_punishes_after_bob_dead() { assert!(matches!(bob_swap.state, BobState::BtcLocked { .. })); let bob_state = bob::run(bob_swap).await?; - - ctx.assert_bob_punished(bob_state).await; - + ctx.assert_bob_redeemed(bob_state).await; Ok(()) }) .await; diff --git a/swap/tests/alice_punishes_after_restart_bob_dead.rs b/swap/tests/alice_punishes_after_restart_bob_dead.rs index b049d681..1bf140ee 100644 --- a/swap/tests/alice_punishes_after_restart_bob_dead.rs +++ b/swap/tests/alice_punishes_after_restart_bob_dead.rs @@ -9,7 +9,7 @@ use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; /// Bob locks Btc and Alice locks Xmr. Bob does not act; he fails to send Alice -/// the encsig and fail to refund or redeem. Alice cancels and punishes. +/// the encsig and fail to refund or redeem. Alice cancels and punishes. Bob then cooperates with Alice and redeems XMR with her key. #[tokio::test] async fn alice_punishes_after_restart_if_bob_dead() { harness::setup_test(FastPunishConfig, |mut ctx| async move { @@ -58,9 +58,7 @@ async fn alice_punishes_after_restart_if_bob_dead() { assert!(matches!(bob_swap.state, BobState::BtcLocked { .. })); let bob_state = bob::run(bob_swap).await?; - - ctx.assert_bob_punished(bob_state).await; - + ctx.assert_bob_redeemed(bob_state).await; Ok(()) }) .await; diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 028b0935..4a183084 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -652,7 +652,7 @@ impl TestContext { } pub async fn assert_alice_punished(&self, state: AliceState) { - assert!(matches!(state, AliceState::BtcPunished)); + assert!(matches!(state, AliceState::BtcPunished { .. })); assert_eventual_balance( self.alice_bitcoin_wallet.as_ref(), @@ -698,7 +698,7 @@ impl TestContext { let lock_tx_id = if let BobState::BtcRefunded(state4) = state { state4.tx_lock_id() } else { - panic!("Bob in not in btc refunded state: {:?}", state); + panic!("Bob is not in btc refunded state: {:?}", state); }; let lock_tx_bitcoin_fee = self .bob_bitcoin_wallet @@ -819,7 +819,7 @@ impl TestContext { async fn bob_punished_btc_balance(&self, state: BobState) -> Result { self.bob_bitcoin_wallet.sync().await?; - let lock_tx_id = if let BobState::BtcPunished { tx_lock_id } = state { + let lock_tx_id = if let BobState::BtcPunished { tx_lock_id, .. } = state { tx_lock_id } else { bail!("Bob in not in btc punished state: {:?}", state); diff --git a/swap/tests/punish.rs b/swap/tests/punish.rs index 60eadfe3..79d93d9d 100644 --- a/swap/tests/punish.rs +++ b/swap/tests/punish.rs @@ -7,7 +7,7 @@ use swap::protocol::bob::BobState; use swap::protocol::{alice, bob}; /// Bob locks Btc and Alice locks Xmr. Bob does not act; he fails to send Alice -/// the encsig and fail to refund or redeem. Alice punishes. +/// the encsig and fail to refund or redeem. Alice punishes. Bob then cooperates with Alice and redeems XMR with her key. #[tokio::test] async fn alice_punishes_if_bob_never_acts_after_fund() { harness::setup_test(FastPunishConfig, |mut ctx| async move { @@ -32,9 +32,7 @@ async fn alice_punishes_if_bob_never_acts_after_fund() { assert!(matches!(bob_swap.state, BobState::BtcLocked { .. })); let bob_state = bob::run(bob_swap).await?; - - ctx.assert_bob_punished(bob_state).await; - + ctx.assert_bob_redeemed(bob_state).await; Ok(()) }) .await; From 26e66ce9b95b6f84a9dce459e98cf1fbbac1c37d Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 3 Jul 2024 20:02:04 +0200 Subject: [PATCH 309/395] Update swap.rs --- swap/src/protocol/bob/swap.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 43c54e4b..b45962ec 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -17,6 +17,15 @@ pub fn is_complete(state: &BobState) -> bool { ) } +// Checks if this is a state where we should exit after +// but we don't want to prevent resuming the swap in this state +// This is currently only used for the BtcPunished state because we might be able to +// recover from this state by attempting a cooperative XMR redeem but it might also fail. +// We want to avoid an infinite retry loop but also allow the user to retry manually by resuming the swap. +pub fn is_exit_early(state: &BobState) -> bool { + matches!(state, BobState::BtcPunished { .. }) +} + #[allow(clippy::too_many_arguments)] pub async fn run(swap: bob::Swap) -> Result { run_until(swap, is_complete).await @@ -39,14 +48,14 @@ pub async fn run_until( swap.monero_receive_address, ) .await?; + swap.db .insert_latest_state(swap.id, current_state.clone().into()) .await?; - if matches!(current_state, BobState::BtcPunished { .. }) - && matches!(swap.state, BobState::BtcPunished { .. }) - { - break; // Stops swap when cooperative redeem fails without preventing resuming swap in BtcPunished state. - }; + + if is_exit_early(¤t_state) { + break; + } } Ok(current_state) From ef75019ac6446f7acd979b2b2241ce7ef8a5c37f Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 3 Jul 2024 20:12:22 +0200 Subject: [PATCH 310/395] Update swap.rs --- swap/src/protocol/bob/swap.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index b45962ec..341768e1 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -17,12 +17,12 @@ pub fn is_complete(state: &BobState) -> bool { ) } -// Checks if this is a state where we should exit after +// Checks if this is a state where we should exit after reaching it // but we don't want to prevent resuming the swap in this state // This is currently only used for the BtcPunished state because we might be able to // recover from this state by attempting a cooperative XMR redeem but it might also fail. // We want to avoid an infinite retry loop but also allow the user to retry manually by resuming the swap. -pub fn is_exit_early(state: &BobState) -> bool { +pub fn is_run_at_most_once(state: &BobState) -> bool { matches!(state, BobState::BtcPunished { .. }) } @@ -38,7 +38,7 @@ pub async fn run_until( let mut current_state = swap.state.clone(); while !is_target_state(¤t_state) { - current_state = next_state( + let next_state = next_state( swap.id, current_state.clone(), &mut swap.event_loop_handle, @@ -50,12 +50,14 @@ pub async fn run_until( .await?; swap.db - .insert_latest_state(swap.id, current_state.clone().into()) + .insert_latest_state(swap.id, next_state.clone().into()) .await?; - if is_exit_early(¤t_state) { + if is_run_at_most_once(¤t_state) && next_state == current_state { break; } + + current_state = next_state; } Ok(current_state) From 07f788eb81c1c32ac097f9ae2e4e313b8d751bac Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 3 Jul 2024 20:14:09 +0200 Subject: [PATCH 311/395] Update swap.rs --- swap/src/protocol/bob/swap.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 341768e1..f758ab03 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -17,11 +17,13 @@ pub fn is_complete(state: &BobState) -> bool { ) } -// Checks if this is a state where we should exit after reaching it -// but we don't want to prevent resuming the swap in this state -// This is currently only used for the BtcPunished state because we might be able to -// recover from this state by attempting a cooperative XMR redeem but it might also fail. -// We want to avoid an infinite retry loop but also allow the user to retry manually by resuming the swap. +// Identifies states that should be run at most once before exiting. +// This is used to prevent infinite retry loops while still allowing manual resumption. +// +// Currently, this applies to the BtcPunished state: +// - We want to attempt recovery via cooperative XMR redeem once. +// - If unsuccessful, we exit to avoid an infinite retry loop. +// - The swap can still be manually resumed later and retried if desired. pub fn is_run_at_most_once(state: &BobState) -> bool { matches!(state, BobState::BtcPunished { .. }) } From 2824ebc893958513539363da17bfa905d5ed1223 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 3 Jul 2024 20:39:49 +0200 Subject: [PATCH 312/395] Update swap.rs --- swap/src/protocol/bob/swap.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index f758ab03..55174d3a 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -310,14 +310,16 @@ async fn next_state( } BobState::BtcRefunded(state4) => BobState::BtcRefunded(state4), BobState::BtcPunished { state, tx_lock_id } => { - tracing::info!("Attempting cooperative XMR redeem"); + tracing::info!("Attempting to cooperatively redeem XMR after being punished"); let response = event_loop_handle .request_cooperative_xmr_redeem(swap_id) .await; match response { Ok(Fullfilled { s_a, .. }) => { - tracing::debug!("Alice revealed XMR key to us"); + tracing::info!( + "Alice has accepted our request to cooperatively redeem the XMR" + ); let s_a = monero::PrivateKey { scalar: s_a }; let state5 = state.attempt_cooperative_redeem(s_a); From 294b658f4327f4b8a2c68e72c347eba622f5d4d8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:04:18 +0000 Subject: [PATCH 313/395] build(deps): bump qrcode from 0.14.0 to 0.14.1 Bumps [qrcode](https://github.com/kennytm/qrcode-rust) from 0.14.0 to 0.14.1. - [Release notes](https://github.com/kennytm/qrcode-rust/releases) - [Commits](https://github.com/kennytm/qrcode-rust/commits/v0.14.1) --- updated-dependencies: - dependency-name: qrcode dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb3ea136..94cf9a78 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3243,9 +3243,9 @@ dependencies = [ [[package]] name = "qrcode" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e719ca51966ff9f5a8436edb00d6115b3c606a0bb27c8f8ca74a38ff2b036d" +checksum = "d68782463e408eb1e668cf6152704bd856c78c5b6417adaee3203d8f4c1fc9ec" dependencies = [ "image", ] From ab1001a18c190c83cdfc333b037b41b07d0c5609 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:04:38 +0000 Subject: [PATCH 314/395] build(deps): bump serde from 1.0.203 to 1.0.204 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.203 to 1.0.204. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.203...v1.0.204) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb3ea136..80f28d22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3995,9 +3995,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -4024,9 +4024,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", From cd29870e11ae06faf3b238c1ac3bb037af490682 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:04:55 +0000 Subject: [PATCH 315/395] build(deps): bump async-trait from 0.1.80 to 0.1.81 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.80 to 0.1.81. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.80...0.1.81) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb3ea136..9591db36 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", From 2af22c1aba19ec9daab9bf8e505b36cda1de04f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:08:29 +0000 Subject: [PATCH 316/395] build(deps): bump uuid from 1.9.1 to 1.10.0 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.9.1 to 1.10.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.9.1...1.10.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dfd9f239..b4ecc30e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5327,9 +5327,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom 0.2.11", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 5c754a53..a52f79a5 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -67,7 +67,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.9", features = [ "serde", "v4" ] } +uuid = { version = "1.10", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From 47f8a652090b0318fbcd7488e1d72e23c6e09a5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:19:16 +0000 Subject: [PATCH 317/395] build(deps): bump hyper from 1.3.1 to 1.4.1 Bumps [hyper](https://github.com/hyperium/hyper) from 1.3.1 to 1.4.1. - [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/v1.3.1...v1.4.1) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ swap/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4ecc30e..a5b9e009 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1763,9 +1763,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -1789,7 +1789,7 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.0.0", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "rustls 0.23.10", "rustls-pki-types", @@ -1810,7 +1810,7 @@ dependencies = [ "futures-util", "http 1.0.0", "http-body 1.0.0", - "hyper 1.3.1", + "hyper 1.4.1", "pin-project-lite 0.2.13", "socket2 0.5.5", "tokio", @@ -3497,7 +3497,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-rustls", "hyper-util", "ipnet", @@ -4541,7 +4541,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper 1.3.1", + "hyper 1.4.1", "itertools 0.13.0", "jsonrpsee", "jsonrpsee-core", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index a52f79a5..8c657d62 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -79,7 +79,7 @@ zip = "0.5" [dev-dependencies] bitcoin-harness = { git = "https://github.com/delta1/bitcoin-harness-rs.git", rev = "80cc8d05db2610d8531011be505b7bee2b5cdf9f" } get-port = "3" -hyper = "1.3" +hyper = "1.4" jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } mockito = "1.4" monero-harness = { path = "../monero-harness" } From dcb4edf58520c11c887de6da7b8ffcbde67cafb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:19:33 +0000 Subject: [PATCH 318/395] build(deps): bump vergen from 8.3.1 to 8.3.2 Bumps [vergen](https://github.com/rustyhorde/vergen) from 8.3.1 to 8.3.2. - [Release notes](https://github.com/rustyhorde/vergen/releases) - [Commits](https://github.com/rustyhorde/vergen/commits) --- updated-dependencies: - dependency-name: vergen dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b4ecc30e..997c31fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1483,9 +1483,9 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "git2" -version = "0.18.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf97ba92db08df386e10c8ede66a2a0369bd277090afd8710e19e38de9ec0cd" +checksum = "b903b73e45dc0c6c596f2d37eccece7c1c8bb6e4407b001096387c63d0d93724" dependencies = [ "bitflags 2.4.0", "libc", @@ -2128,9 +2128,9 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libgit2-sys" -version = "0.16.1+1.7.1" +version = "0.17.0+1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2a2bb3680b094add03bb3732ec520ece34da31a8cd2d633d1389d0f0fb60d0c" +checksum = "10472326a8a6477c3c20a64547b0059e4b0d086869eee31e6d7da728a8eb7224" dependencies = [ "cc", "libc", @@ -5355,9 +5355,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "vergen" -version = "8.3.1" +version = "8.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27d6bdd219887a9eadd19e1c34f32e47fa332301184935c6d9bca26f3cca525" +checksum = "2990d9ea5967266ea0ccf413a4aa5c42a93dbcfda9cb49a97de6931726b12566" dependencies = [ "anyhow", "cfg-if 1.0.0", From 4115a452e303a64c223c512b1a90c783d73ae7ca Mon Sep 17 00:00:00 2001 From: Einliterflasche <81313171+Einliterflasche@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:19:41 +0200 Subject: [PATCH 319/395] allow --change-address to be omitted and default to internal wallet address (#1709) allow --change-address to be omitted and default to internal wallet address (#1709) Co-authored-by: binarybaron <86064887+binarybaron@users.noreply.github.com> Co-authored-by: Byron Hambly --- CHANGELOG.md | 2 ++ docs/cli/README.md | 2 +- swap/src/api.rs | 4 ++++ swap/src/cli/command.rs | 46 +++++++++++++++++++++++++++++------------ 4 files changed, 40 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a2baf45..1b4776b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. + ## [0.13.2] - 2024-07-02 - CLI: Buffer received transfer proofs for later processing if we're currently running a different swap diff --git a/docs/cli/README.md b/docs/cli/README.md index d95d90ef..eff9d072 100644 --- a/docs/cli/README.md +++ b/docs/cli/README.md @@ -75,7 +75,7 @@ OPTIONS: This command has three core options: -- `--change-address`: A Bitcoin address you control. Will be used for refunds of any kind. +- `--change-address`: A Bitcoin address you control. Will be used for refunds of any kind. You can also omit this flag which will refund any change to the internal wallet. - `--receive-address`: A Monero address you control. This is where you will receive the Monero after the swap. - `--seller`: The multiaddress of the seller you want to swap with. diff --git a/swap/src/api.rs b/swap/src/api.rs index 340c2e39..fb071cd4 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -267,6 +267,10 @@ impl Context { tasks: Arc::new(PendingTaskList::default()), } } + + pub fn bitcoin_wallet(&self) -> Option> { + self.bitcoin_wallet.clone() + } } impl fmt::Debug for Context { diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index af72df1b..f3d61c92 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -69,6 +69,37 @@ where monero_receive_address, tor, } => { + let context = Context::build( + Some(bitcoin), + Some(monero), + Some(tor), + data, + is_testnet, + debug, + json, + None, + ) + .await?; + + // when no refund address was provided we default to the internal wallet + let bitcoin_change_address = match bitcoin_change_address { + Some(addr) => addr, + None => { + let internal_wallet_address = context + .bitcoin_wallet() + .expect("bitcoin wallet should exist") + .new_address() + .await?; + + tracing::info!( + internal_wallet_address=%internal_wallet_address, + "No --change-address supplied. Any change will be received to the internal wallet." + ); + + internal_wallet_address + } + }; + let monero_receive_address = monero_address::validate_is_testnet(monero_receive_address, is_testnet)?; let bitcoin_change_address = @@ -81,17 +112,6 @@ where swap_id: Uuid::new_v4(), }); - let context = Context::build( - Some(bitcoin), - Some(monero), - Some(tor), - data, - is_testnet, - debug, - json, - None, - ) - .await?; (context, request) } CliCommand::History => { @@ -300,10 +320,10 @@ enum CliCommand { #[structopt( long = "change-address", - help = "The bitcoin address where any form of change or excess funds should be sent to", + help = "The bitcoin address where any form of change or excess funds should be sent to. If omitted they will be sent to the internal wallet.", parse(try_from_str = bitcoin_address::parse) )] - bitcoin_change_address: bitcoin::Address, + bitcoin_change_address: Option, #[structopt(flatten)] monero: Monero, From 073baa97526bc82f0e681259ff7fb6d1a3b3bcb1 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 11 Jul 2024 09:30:48 +0200 Subject: [PATCH 320/395] Update swap.rs --- swap/src/protocol/bob/swap.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 55174d3a..42031007 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -337,11 +337,13 @@ async fn next_state( } } } - Ok(Rejected { reason: error, .. }) => { - return Err(error) + Ok(Rejected { reason, .. }) => { + tracing::error!(?reason, "Alice rejected our request for cooperative XMR redeem"); + return Err(reason) .context("Alice rejected our request for cooperative XMR redeem"); } Err(error) => { + tracing::error!(?error, "Failed to request cooperative XMR redeem from Alice"); return Err(error) .context("Failed to request cooperative XMR redeem from Alice"); } From ee04ff8a3b74c35d380f59f9808f42347b4ad6f8 Mon Sep 17 00:00:00 2001 From: patrini32 Date: Thu, 11 Jul 2024 10:58:07 +0300 Subject: [PATCH 321/395] fix formatting --- swap/src/protocol/bob/swap.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 42031007..dfba763d 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -338,12 +338,18 @@ async fn next_state( } } Ok(Rejected { reason, .. }) => { - tracing::error!(?reason, "Alice rejected our request for cooperative XMR redeem"); + tracing::error!( + ?reason, + "Alice rejected our request for cooperative XMR redeem" + ); return Err(reason) .context("Alice rejected our request for cooperative XMR redeem"); } Err(error) => { - tracing::error!(?error, "Failed to request cooperative XMR redeem from Alice"); + tracing::error!( + ?error, + "Failed to request cooperative XMR redeem from Alice" + ); return Err(error) .context("Failed to request cooperative XMR redeem from Alice"); } From 845b9428b7e56a0fdf1a286fc5ea99a063413545 Mon Sep 17 00:00:00 2001 From: patrini32 Date: Thu, 11 Jul 2024 11:02:23 +0300 Subject: [PATCH 322/395] remove whitespaces --- swap/src/protocol/bob/swap.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index dfba763d..5db98690 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -339,7 +339,7 @@ async fn next_state( } Ok(Rejected { reason, .. }) => { tracing::error!( - ?reason, + ?reason, "Alice rejected our request for cooperative XMR redeem" ); return Err(reason) @@ -347,7 +347,7 @@ async fn next_state( } Err(error) => { tracing::error!( - ?error, + ?error, "Failed to request cooperative XMR redeem from Alice" ); return Err(error) From 31d76cbdf4ac975614c6da2a7e69e30765bef91f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Jul 2024 11:25:56 +0000 Subject: [PATCH 323/395] build(deps): bump thiserror from 1.0.61 to 1.0.62 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.61 to 1.0.62. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.61...1.0.62) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e2ebd60..1e1a51f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4682,18 +4682,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", From 1f322b78c80fc7506223cf853a927a585b396459 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Tue, 16 Jul 2024 00:45:19 +1000 Subject: [PATCH 324/395] Prepare release 0.13.3 (#1714) --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0e31a9b..96a59b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.3] - 2024-07-15 + - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. @@ -368,7 +370,8 @@ 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.13.2...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...HEAD +[0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 [0.13.0]: https://github.com/comit-network/xmr-btc-swap/compare/0.12.3...0.13.0 diff --git a/Cargo.lock b/Cargo.lock index 1e1a51f0..75969f20 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4515,7 +4515,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.13.2" +version = "0.13.3" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 8c657d62..6af34a86 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.13.2" +version = "0.13.3" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From 60a31777100e72fdba408549a228a599eac483e8 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:43:47 +0200 Subject: [PATCH 325/395] feat: Dockerfile for asb --- Dockerfile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..7f7dddaf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM rust:1.74 AS builder + +WORKDIR /build + +RUN apt-get update +RUN apt-get install -y git clang cmake libsnappy-dev + +RUN git clone https://github.com/comit-network/xmr-btc-swap . + +RUN cargo build --release --bin=asb + +FROM debian:bullseye-slim + +WORKDIR /data + +COPY --from=builder /build/target/release/asb /bin/asb + +ENTRYPOINT ["asb"] From d55c6e8c1acf4a10329edcb531799e97743937bd Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:11:40 +0200 Subject: [PATCH 326/395] fix(Dockerfile): Use local repo --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 7f7dddaf..2dbf5397 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,11 @@ -FROM rust:1.74 AS builder +FROM rust:1.59-slim AS builder WORKDIR /build RUN apt-get update RUN apt-get install -y git clang cmake libsnappy-dev -RUN git clone https://github.com/comit-network/xmr-btc-swap . +COPY . . RUN cargo build --release --bin=asb From eab4b0047835a50712c139627e304dd4d457a9f3 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:19:56 +0200 Subject: [PATCH 327/395] feat: Release Docker image on build --- .github/workflows/build-release-binaries.yml | 34 +++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 662e3a5e..565d2dbd 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -4,6 +4,9 @@ on: release: types: [created] +env: + DOCKER_IMAGE_NAME: unstoppableswap/asb + jobs: build_binaries: name: Build @@ -82,7 +85,7 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help - id: create-archive-name - shell: python # Use python to have a prettier name for the archive on Windows. + shell: python run: | import platform os_info = platform.uname() @@ -122,3 +125,32 @@ jobs: asset_path: ./${{ steps.create-archive-name.outputs.archive }} asset_name: ${{ steps.create-archive-name.outputs.archive }} asset_content_type: application/gzip + + build_and_push_docker: + name: Build and Push Docker Image + runs-on: ubuntu-latest + needs: build_binaries + steps: + - name: Checkout code + uses: actions/checkout@v4.1.7 + with: + ref: ${{ github.event.release.target_commitish }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ${{ env.DOCKER_IMAGE_NAME }}:latest + ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} From c430e89502ae06e888d8482e21a0db11c437132d Mon Sep 17 00:00:00 2001 From: UnstoppableSwap Botty Date: Tue, 16 Jul 2024 09:25:28 +0000 Subject: [PATCH 328/395] Prepare release 0.13.3 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a59b5f..9ef7653e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.3] - 2024-07-16 + ## [0.13.3] - 2024-07-15 - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed @@ -370,7 +372,8 @@ 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.13.3...HEAD +[unreleased]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...HEAD +[0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 From f5bda640a0f40ba0db886df78a666a9291128cf7 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 16 Jul 2024 11:31:18 +0200 Subject: [PATCH 329/395] fix: Remove duplicate entry from CHANGELOG.md --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ef7653e..6804925c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.13.3] - 2024-07-16 - -## [0.13.3] - 2024-07-15 - - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. From 7c54fb2848d2f9f9c00ff3982b044f9bbe707343 Mon Sep 17 00:00:00 2001 From: UnstoppableSwap Botty Date: Tue, 16 Jul 2024 09:40:03 +0000 Subject: [PATCH 330/395] Prepare release 0.13.3 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6804925c..f66069f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.3] - 2024-07-16 + - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. @@ -370,6 +372,7 @@ It is possible to migrate critical data from the old db to the sqlite but there [unreleased]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...HEAD [0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 +[0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 From 85c4db1d7517715d643e31e02a875ce71c103409 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 16 Jul 2024 20:13:58 +0200 Subject: [PATCH 331/395] fix: Format cooperative redeem reject using thiserror (#1716) --- swap/src/protocol/bob/swap.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/swap/src/protocol/bob/swap.rs b/swap/src/protocol/bob/swap.rs index 5db98690..912181d4 100644 --- a/swap/src/protocol/bob/swap.rs +++ b/swap/src/protocol/bob/swap.rs @@ -339,7 +339,7 @@ async fn next_state( } Ok(Rejected { reason, .. }) => { tracing::error!( - ?reason, + %reason, "Alice rejected our request for cooperative XMR redeem" ); return Err(reason) @@ -347,7 +347,7 @@ async fn next_state( } Err(error) => { tracing::error!( - ?error, + %error, "Failed to request cooperative XMR redeem from Alice" ); return Err(error) From 7c9af191bc4c37e0e5efb6b785cfb3025486b187 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jul 2024 11:08:57 +0000 Subject: [PATCH 332/395] build(deps): bump tokio from 1.38.0 to 1.38.1 Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.38.0 to 1.38.1. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.38.0...tokio-1.38.1) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 75969f20..b32a5f47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4778,9 +4778,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.38.0" +version = "1.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" dependencies = [ "backtrace", "bytes", From 74af379f80fe682b3ad67d9059389b569b6c92c2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:24:12 +0000 Subject: [PATCH 333/395] build(deps): bump toml from 0.8.14 to 0.8.15 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.14 to 0.8.15. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.14...toml-v0.8.15) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b32a5f47..0297752a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.14", + "toml 0.8.15", ] [[package]] @@ -4579,7 +4579,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.14", + "toml 0.8.15", "torut", "tracing", "tracing-appender", @@ -4919,9 +4919,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" dependencies = [ "serde", "serde_spanned", @@ -4940,9 +4940,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" dependencies = [ "indexmap 2.1.0", "serde", From cb8543990591c9366fc32f12112f99c0e1a5d9b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 18 Jul 2024 11:24:34 +0000 Subject: [PATCH 334/395] build(deps): bump thiserror from 1.0.62 to 1.0.63 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.62 to 1.0.63. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.62...1.0.63) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b32a5f47..06d18dd8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4682,18 +4682,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", From eef78cddb21b64b96bed11ed7ea5edadc9b62c90 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:27:56 +0200 Subject: [PATCH 335/395] CI: Exclude preview releases from "latest" docker release tag --- .github/workflows/build-release-binaries.yml | 21 +++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 565d2dbd..4f466ada 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -145,6 +145,15 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set Docker tags + id: docker_tags + run: | + if [[ ${{ github.event.release.tag_name }} == "preview" ]]; then + echo "::set-output name=preview::true" + else + echo "::set-output name=preview::false" + fi + - name: Build and push Docker image uses: docker/build-push-action@v4 with: @@ -152,5 +161,15 @@ jobs: file: ./Dockerfile push: true tags: | - ${{ env.DOCKER_IMAGE_NAME }}:latest ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} + ${{ env.DOCKER_IMAGE_NAME }}:latest + if: steps.docker_tags.outputs.preview == 'false' + + - name: Build and push Docker image without latest tag (preview release) + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} + if: steps.docker_tags.outputs.preview == 'true' From 8ba8e3bd5c7a05468cb425fd4952d29f4495b99a Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Mon, 22 Jul 2024 16:32:04 +0200 Subject: [PATCH 336/395] fix: Revert 0.13.3 release --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f66069f8..5f565027 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.13.3] - 2024-07-16 - - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. From 410fcf211792dfcee9e97bb4f04fab4eaee39807 Mon Sep 17 00:00:00 2001 From: UnstoppableSwap Botty Date: Mon, 22 Jul 2024 14:40:59 +0000 Subject: [PATCH 337/395] Prepare release 0.13.3 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f565027..686c4ed5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.3] - 2024-07-22 + - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. @@ -371,6 +373,7 @@ It is possible to migrate critical data from the old db to the sqlite but there [unreleased]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...HEAD [0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 [0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 +[0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 From ef49b471d8d4d709af71dfa334beb4490a9a7585 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:12:44 +0200 Subject: [PATCH 338/395] docs: add binarybaron.asc --- utils/gpg_keys/binarybaron.asc | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 utils/gpg_keys/binarybaron.asc diff --git a/utils/gpg_keys/binarybaron.asc b/utils/gpg_keys/binarybaron.asc new file mode 100644 index 00000000..3ed5a155 --- /dev/null +++ b/utils/gpg_keys/binarybaron.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEZp+avRYJKwYBBAHaRw8BAQdAD99LhR+cHlXDsYPjRJr0Ag7BXsjGZKfdWCtx +CPA0fwG0LWJpbmFyeWJhcm9uIDxiaW5hcnliYXJvbkB1bnN0b3BwYWJsZXN3YXAu +bmV0PoiTBBMWCgA7FiEENahE1/S1W8ROGA/xmbddPhR2om4FAmafmr0CGwMFCwkI +BwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQmbddPhR2om5IQQD/d/EmD/yKMKRl +Hw9RSP4bhcALmrZPri8sYkPteus8OhIA+wWTaIxXZJgydpXv95yECTfUXZ0UhuJq +6UH0FQL8mosJuDgEZp+avRIKKwYBBAGXVQEFAQEHQOd1tQ46YVKxyUKluPAvGJLY +LQ+3UWFWQJavLblkrYE2AwEIB4h4BBgWCgAgFiEENahE1/S1W8ROGA/xmbddPhR2 +om4FAmafmr0CGwwACgkQmbddPhR2om6mmQEAn7vufrOp/HSYgn9l5tmJxMkyxJ3W +2WNo9u+JdnSik1IBAMsNcc4zm5ewfFr/qAnTHzHRId7dWR2+hs1oH7JOlf8L +=Rxij +-----END PGP PUBLIC KEY BLOCK----- From c80bdb2d8cbe6e0786158e53da63bdc5b6a46229 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Tue, 23 Jul 2024 14:52:01 +0200 Subject: [PATCH 339/395] fix(asb): Allow history command to be run while asb is running (#1724) Co-authored-by: einliterflasche --- CHANGELOG.md | 2 ++ swap/src/api.rs | 6 +++--- swap/src/bin/asb.rs | 18 +++++++++++++++--- swap/src/database.rs | 15 ++++++++++++--- swap/src/database/sqlite.rs | 20 +++++++++++++++----- swap/tests/harness/mod.rs | 12 ++++++++---- 6 files changed, 55 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96a59b5f..5152d646 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- ASB: The `history` command can now be used while the asb is running. + ## [0.13.3] - 2024-07-15 - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed diff --git a/swap/src/api.rs b/swap/src/api.rs index fb071cd4..36c6972f 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -1,6 +1,6 @@ pub mod request; use crate::cli::command::{Bitcoin, Monero, Tor}; -use crate::database::open_db; +use crate::database::{open_db, AccessMode}; use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet}; use crate::fs::system_data_dir; use crate::network::rendezvous::XmrBtcNamespace; @@ -224,7 +224,7 @@ impl Context { let tor_socks5_port = tor.map_or(9050, |tor| tor.tor_socks5_port); let context = Context { - db: open_db(data_dir.join("sqlite")).await?, + db: open_db(data_dir.join("sqlite"), AccessMode::ReadWrite).await?, bitcoin_wallet, monero_wallet, monero_rpc_process, @@ -259,7 +259,7 @@ impl Context { bitcoin_wallet: Some(bob_bitcoin_wallet), monero_wallet: Some(bob_monero_wallet), config, - db: open_db(db_path) + db: open_db(db_path, AccessMode::ReadWrite) .await .expect("Could not open sqlite database"), monero_rpc_process: None, diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index ff3b0e4c..0f2f13b5 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -30,7 +30,7 @@ use swap::asb::config::{ }; 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::database::{open_db, AccessMode}; use swap::network::rendezvous::XmrBtcNamespace; use swap::network::swarm; use swap::protocol::alice::{run, AliceState}; @@ -95,13 +95,13 @@ async fn main() -> Result<()> { )); } - let db = open_db(config.data.dir.join("sqlite")).await?; - let seed = Seed::from_file_or_generate(&config.data.dir).expect("Could not retrieve/initialize seed"); match cmd { Command::Start { resume_only } => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; + // check and warn for duplicate rendezvous points let mut rendezvous_addrs = config.network.rendezvous_point.clone(); let prev_len = rendezvous_addrs.len(); @@ -225,6 +225,8 @@ async fn main() -> Result<()> { event_loop.run().await; } Command::History => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?; + let mut table = Table::new(); table.set_header(vec!["SWAP ID", "STATE"]); @@ -270,6 +272,8 @@ async fn main() -> Result<()> { tracing::info!(%bitcoin_balance, %monero_balance, "Current balance"); } Command::Cancel { swap_id } => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; + let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let (txid, _) = cancel(swap_id, Arc::new(bitcoin_wallet), db).await?; @@ -277,6 +281,8 @@ async fn main() -> Result<()> { tracing::info!("Cancel transaction successfully published with id {}", txid); } Command::Refund { swap_id } => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; + let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let monero_wallet = init_monero_wallet(&config, env_config).await?; @@ -291,6 +297,8 @@ async fn main() -> Result<()> { tracing::info!("Monero successfully refunded"); } Command::Punish { swap_id } => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; + let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let (txid, _) = punish(swap_id, Arc::new(bitcoin_wallet), db).await?; @@ -298,6 +306,8 @@ async fn main() -> Result<()> { tracing::info!("Punish transaction successfully published with id {}", txid); } Command::SafelyAbort { swap_id } => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; + safely_abort(swap_id, db).await?; tracing::info!("Swap safely aborted"); @@ -306,6 +316,8 @@ async fn main() -> Result<()> { swap_id, do_not_await_finality, } => { + let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadWrite).await?; + let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let (txid, _) = redeem( diff --git a/swap/src/database.rs b/swap/src/database.rs index 7af16196..7c6185f7 100644 --- a/swap/src/database.rs +++ b/swap/src/database.rs @@ -83,16 +83,25 @@ impl Swap { } } -pub async fn open_db(sqlite_path: impl AsRef) -> Result> { +#[derive(Debug, Clone, Copy, Serialize, Deserialize, Hash, PartialEq)] +pub enum AccessMode { + ReadWrite, + ReadOnly, +} + +pub async fn open_db( + sqlite_path: impl AsRef, + access_mode: AccessMode, +) -> Result> { if sqlite_path.as_ref().exists() { tracing::debug!("Using existing sqlite database."); - let sqlite = SqliteDatabase::open(sqlite_path).await?; + let sqlite = SqliteDatabase::open(sqlite_path, access_mode).await?; Ok(Arc::new(sqlite)) } else { tracing::debug!("Creating and using new sqlite database."); ensure_directory_exists(sqlite_path.as_ref())?; tokio::fs::File::create(&sqlite_path).await?; - let sqlite = SqliteDatabase::open(sqlite_path).await?; + let sqlite = SqliteDatabase::open(sqlite_path, access_mode).await?; Ok(Arc::new(sqlite)) } } diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index 576dc362..eb013f66 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -4,7 +4,7 @@ use crate::protocol::{Database, State}; use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use libp2p::{Multiaddr, PeerId}; -use sqlx::sqlite::Sqlite; +use sqlx::sqlite::{Sqlite, SqliteConnectOptions}; use sqlx::{Pool, SqlitePool}; use std::collections::HashMap; use std::path::Path; @@ -12,19 +12,29 @@ use std::str::FromStr; use time::OffsetDateTime; use uuid::Uuid; +use super::AccessMode; + pub struct SqliteDatabase { pool: Pool, } impl SqliteDatabase { - pub async fn open(path: impl AsRef) -> Result + pub async fn open(path: impl AsRef, access_mode: AccessMode) -> Result where Self: std::marker::Sized, { + let read_only = matches!(access_mode, AccessMode::ReadOnly); + let path_str = format!("sqlite:{}", path.as_ref().display()); - let pool = SqlitePool::connect(&path_str).await?; + let options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only); + + let pool = SqlitePool::connect_with(options).await?; let mut sqlite = Self { pool }; - sqlite.run_migrations().await?; + + if !read_only { + sqlite.run_migrations().await?; + } + Ok(sqlite) } @@ -504,7 +514,7 @@ mod tests { // file has to exist in order to connect with sqlite File::create(temp_db.clone()).unwrap(); - let db = SqliteDatabase::open(temp_db).await?; + let db = SqliteDatabase::open(temp_db, AccessMode::ReadWrite).await?; Ok(db) } diff --git a/swap/tests/harness/mod.rs b/swap/tests/harness/mod.rs index 4a183084..989f0d8d 100644 --- a/swap/tests/harness/mod.rs +++ b/swap/tests/harness/mod.rs @@ -16,7 +16,7 @@ use std::sync::Arc; use std::time::Duration; use swap::asb::FixedRate; use swap::bitcoin::{CancelTimelock, PunishTimelock, TxCancel, TxPunish, TxRedeem, TxRefund}; -use swap::database::SqliteDatabase; +use swap::database::{AccessMode, SqliteDatabase}; use swap::env::{Config, GetConfig}; use swap::fs::ensure_directory_exists; use swap::network::rendezvous::XmrBtcNamespace; @@ -231,7 +231,11 @@ async fn start_alice( if !&db_path.exists() { tokio::fs::File::create(&db_path).await.unwrap(); } - let db = Arc::new(SqliteDatabase::open(db_path.as_path()).await.unwrap()); + let db = Arc::new( + SqliteDatabase::open(db_path.as_path(), AccessMode::ReadWrite) + .await + .unwrap(), + ); let min_buy = bitcoin::Amount::from_sat(u64::MIN); let max_buy = bitcoin::Amount::from_sat(u64::MAX); @@ -433,7 +437,7 @@ impl BobParams { if !self.db_path.exists() { tokio::fs::File::create(&self.db_path).await?; } - let db = Arc::new(SqliteDatabase::open(&self.db_path).await?); + let db = Arc::new(SqliteDatabase::open(&self.db_path, AccessMode::ReadWrite).await?); let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?; @@ -463,7 +467,7 @@ impl BobParams { if !self.db_path.exists() { tokio::fs::File::create(&self.db_path).await?; } - let db = Arc::new(SqliteDatabase::open(&self.db_path).await?); + let db = Arc::new(SqliteDatabase::open(&self.db_path, AccessMode::ReadWrite).await?); let (event_loop, handle) = self.new_eventloop(swap_id, db.clone()).await?; From 75cfc6b0d4169d72f136266af122381a05bb9efe Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 25 Jul 2024 00:13:15 +0200 Subject: [PATCH 340/395] fix(cli): allow bitcoin-change-address to be omitted when making request to rpc server (#1728) --- swap/src/api.rs | 2 +- swap/src/api/request.rs | 21 ++++++++++++++++++++- swap/src/cli/command.rs | 24 +++--------------------- swap/src/rpc/methods.rs | 29 +++++++++++++++++++---------- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/swap/src/api.rs b/swap/src/api.rs index 36c6972f..5640c833 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -437,7 +437,7 @@ pub mod api_test { Request::new(Method::BuyXmr { seller, - bitcoin_change_address, + bitcoin_change_address: Some(bitcoin_change_address), monero_receive_address, swap_id: Uuid::new_v4(), }) diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index 50274ab1..b1e9c68c 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -31,7 +31,7 @@ pub struct Request { pub enum Method { BuyXmr { seller: Multiaddr, - bitcoin_change_address: bitcoin::Address, + bitcoin_change_address: Option, monero_receive_address: monero::Address, swap_id: Uuid, }, @@ -335,6 +335,25 @@ impl Request { let env_config = context.config.env_config; let seed = context.config.seed.clone().context("Could not get seed")?; + // When no change address was provided we default to the internal wallet + let bitcoin_change_address = match bitcoin_change_address { + Some(addr) => addr, + None => { + let internal_wallet_address = context + .bitcoin_wallet() + .expect("bitcoin wallet should exist") + .new_address() + .await?; + + tracing::info!( + internal_wallet_address=%internal_wallet_address, + "No --change-address supplied. Any change will be received to the internal wallet." + ); + + internal_wallet_address + } + }; + let seller_peer_id = seller .extract_peer_id() .context("Seller address must contain peer ID")?; diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index f3d61c92..4881d94e 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -81,29 +81,11 @@ where ) .await?; - // when no refund address was provided we default to the internal wallet - let bitcoin_change_address = match bitcoin_change_address { - Some(addr) => addr, - None => { - let internal_wallet_address = context - .bitcoin_wallet() - .expect("bitcoin wallet should exist") - .new_address() - .await?; - - tracing::info!( - internal_wallet_address=%internal_wallet_address, - "No --change-address supplied. Any change will be received to the internal wallet." - ); - - internal_wallet_address - } - }; - let monero_receive_address = monero_address::validate_is_testnet(monero_receive_address, is_testnet)?; - let bitcoin_change_address = - bitcoin_address::validate_is_testnet(bitcoin_change_address, is_testnet)?; + let bitcoin_change_address = bitcoin_change_address + .map(|address| bitcoin_address::validate_is_testnet(address, is_testnet)) + .transpose()?; let request = Request::new(Method::BuyXmr { seller, diff --git a/swap/src/rpc/methods.rs b/swap/src/rpc/methods.rs index 83100d4a..f804e085 100644 --- a/swap/src/rpc/methods.rs +++ b/swap/src/rpc/methods.rs @@ -135,16 +135,25 @@ pub fn register_modules(context: Arc) -> Result> module.register_async_method("buy_xmr", |params_raw, context| async move { let params: HashMap = params_raw.parse()?; - let bitcoin_change_address = - bitcoin::Address::from_str(params.get("bitcoin_change_address").ok_or_else(|| { - jsonrpsee_core::Error::Custom("Does not contain bitcoin_change_address".to_string()) - })?) - .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string()))?; - - let bitcoin_change_address = bitcoin_address::validate( - bitcoin_change_address, - context.config.env_config.bitcoin_network, - )?; + let bitcoin_change_address = params + .get("bitcoin_change_address") + .map(|addr_str| { + bitcoin::Address::from_str(addr_str) + .map_err(|err| { + jsonrpsee_core::Error::Custom(format!( + "Could not parse bitcoin address: {}", + err + )) + }) + .and_then(|address| { + bitcoin_address::validate( + address, + context.config.env_config.bitcoin_network, + ) + .map_err(|err| jsonrpsee_core::Error::Custom(err.to_string())) + }) + }) + .transpose()?; let monero_receive_address = monero::Address::from_str(params.get("monero_receive_address").ok_or_else(|| { From 2eda2476ebd4953858f951cf2a401264319f868b Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:01:12 +0200 Subject: [PATCH 341/395] Revert "Merge branch 'master' into master" (#1730) This reverts commit ce8d3afe60f520523fe6ab6b8d1b3de3d07e2027, reversing changes made to 75cfc6b0d4169d72f136266af122381a05bb9efe. --- .github/workflows/build-release-binaries.yml | 53 +------------------- CHANGELOG.md | 7 +-- Dockerfile | 18 ------- 3 files changed, 3 insertions(+), 75 deletions(-) delete mode 100644 Dockerfile diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 4f466ada..662e3a5e 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -4,9 +4,6 @@ on: release: types: [created] -env: - DOCKER_IMAGE_NAME: unstoppableswap/asb - jobs: build_binaries: name: Build @@ -85,7 +82,7 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help - id: create-archive-name - shell: python + shell: python # Use python to have a prettier name for the archive on Windows. run: | import platform os_info = platform.uname() @@ -125,51 +122,3 @@ jobs: asset_path: ./${{ steps.create-archive-name.outputs.archive }} asset_name: ${{ steps.create-archive-name.outputs.archive }} asset_content_type: application/gzip - - build_and_push_docker: - name: Build and Push Docker Image - runs-on: ubuntu-latest - needs: build_binaries - steps: - - name: Checkout code - uses: actions/checkout@v4.1.7 - with: - ref: ${{ github.event.release.target_commitish }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set Docker tags - id: docker_tags - run: | - if [[ ${{ github.event.release.tag_name }} == "preview" ]]; then - echo "::set-output name=preview::true" - else - echo "::set-output name=preview::false" - fi - - - name: Build and push Docker image - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: | - ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} - ${{ env.DOCKER_IMAGE_NAME }}:latest - if: steps.docker_tags.outputs.preview == 'false' - - - name: Build and push Docker image without latest tag (preview release) - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} - if: steps.docker_tags.outputs.preview == 'true' diff --git a/CHANGELOG.md b/CHANGELOG.md index eaa3ad2a..5152d646 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ASB: The `history` command can now be used while the asb is running. -## [0.13.3] - 2024-07-22 +## [0.13.3] - 2024-07-15 - Introduced a cooperative Monero redeem feature for Bob to request from Alice if Bob is punished for not refunding in time. Alice can choose to cooperate but is not obligated to do so. This change is backwards compatible. To attempt recovery, resume a swap in the "Bitcoin punished" state. Success depends on Alice being active and still having a record of the swap. Note that Alice's cooperation is voluntary and recovery is not guaranteed - CLI: `--change-address` can now be omitted. In that case, any change is refunded to the internal bitcoin wallet. @@ -372,10 +372,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/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...HEAD -[0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 -[0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 -[0.13.3]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.3...0.13.3 +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...HEAD [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 2dbf5397..00000000 --- a/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM rust:1.59-slim AS builder - -WORKDIR /build - -RUN apt-get update -RUN apt-get install -y git clang cmake libsnappy-dev - -COPY . . - -RUN cargo build --release --bin=asb - -FROM debian:bullseye-slim - -WORKDIR /data - -COPY --from=builder /build/target/release/asb /bin/asb - -ENTRYPOINT ["asb"] From 2fe428779a27aecea220204f09c24e6ea702ca37 Mon Sep 17 00:00:00 2001 From: Einliterflasche <81313171+Einliterflasche@users.noreply.github.com> Date: Thu, 25 Jul 2024 23:06:50 +0200 Subject: [PATCH 342/395] feat(asb): Retry locking Monero (#1731) We retry to lock the Monero wallet until we succeed or until the cancel timelock expires. This is necessary because the monero-wallet-rpc can sometimes error out due to various reasons, such as - no connection to the daemon - "failed to get output distribution" See https://github.com/comit-network/xmr-btc-swap/issues/1726 --- CHANGELOG.md | 1 + swap/src/protocol/alice/swap.rs | 61 ++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5152d646..e496e3cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - ASB: The `history` command can now be used while the asb is running. +- ASB: Retry locking of Monero if it fails on first attempt ## [0.13.3] - 2024-07-15 diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 79236563..3848a2e1 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -1,11 +1,14 @@ //! Run an XMR/BTC swap in the role of Alice. //! Alice holds XMR and wishes receive BTC. +use std::time::Duration; + use crate::asb::{EventLoopHandle, LatestRate}; use crate::bitcoin::ExpiredTimelocks; use crate::env::Config; use crate::protocol::alice::{AliceState, Swap}; use crate::{bitcoin, monero}; use anyhow::{bail, Context, Result}; +use backoff::ExponentialBackoffBuilder; use tokio::select; use tokio::time::timeout; use uuid::Uuid; @@ -111,23 +114,63 @@ where } } AliceState::BtcLocked { state3 } => { - match state3.expired_timelocks(bitcoin_wallet).await? { - ExpiredTimelocks::None { .. } => { - // Record the current monero wallet block height so we don't have to scan from - // block 0 for scenarios where we create a refund wallet. - let monero_wallet_restore_blockheight = monero_wallet.block_height().await?; + // We retry to lock the Monero wallet until we succeed or until the cancel timelock expires. + // + // This is necessary because the monero-wallet-rpc can sometimes error out due to various reasons, such as + // - no connection to the daemon + // - "failed to get output distribution" + // See https://github.com/comit-network/xmr-btc-swap/issues/1726 + let backoff = ExponentialBackoffBuilder::new() + .with_initial_interval(Duration::from_secs(5)) + .with_max_interval(Duration::from_secs(60 * 3)) + .with_max_elapsed_time(None) + .build(); - let transfer_proof = monero_wallet - .transfer(state3.lock_xmr_transfer_request()) - .await?; + let result = backoff::future::retry_notify( + backoff, + || async { + match state3.expired_timelocks(bitcoin_wallet).await { + Ok(ExpiredTimelocks::None { .. }) => { + // Record the current monero wallet block height so we don't have to scan from + // block 0 for scenarios where we create a refund wallet. + let monero_wallet_restore_blockheight = monero_wallet + .block_height() + .await + .map_err(backoff::Error::transient)?; + let transfer_proof = monero_wallet + .transfer(state3.lock_xmr_transfer_request()) + .await + .map_err(backoff::Error::transient)?; + + Ok(Some((monero_wallet_restore_blockheight, transfer_proof))) + } + Ok(_) => Ok(None), + Err(e) => Err(backoff::Error::transient(e)), + } + }, + |err, delay: Duration| { + tracing::warn!( + %err, + delay_secs = delay.as_secs(), + "Failed to lock XMR. We will retry after a delay" + ); + }, + ) + .await; + + match result { + Ok(Some((monero_wallet_restore_blockheight, transfer_proof))) => { AliceState::XmrLockTransactionSent { monero_wallet_restore_blockheight, transfer_proof, state3, } } - _ => AliceState::SafelyAborted, + Ok(None) => AliceState::SafelyAborted, + Err(e) => { + unreachable!("We should retry forever until the cancel timelock expires. But we got an error: {:#}", e); + } } } AliceState::XmrLockTransactionSent { From 33ad3c374a6472210e878041435e2b6a145c4bc4 Mon Sep 17 00:00:00 2001 From: COMIT Botty McBotface <68941619+comit-botty-mc-botface@users.noreply.github.com> Date: Fri, 26 Jul 2024 07:14:31 +1000 Subject: [PATCH 343/395] Prepare release 0.13.4 (#1734) --- CHANGELOG.md | 5 ++++- Cargo.lock | 2 +- swap/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e496e3cc..bb8e53e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.4] - 2024-07-25 + - ASB: The `history` command can now be used while the asb is running. - ASB: Retry locking of Monero if it fails on first attempt @@ -373,7 +375,8 @@ 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.13.3...HEAD +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.4...HEAD +[0.13.4]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...0.13.4 [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 [0.13.1]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.0...0.13.1 diff --git a/Cargo.lock b/Cargo.lock index 4c2826b8..6ef8e322 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4515,7 +4515,7 @@ checksum = "8049cf85f0e715d6af38dde439cb0ccb91f67fb9f5f63c80f8b43e48356e1a3f" [[package]] name = "swap" -version = "0.13.3" +version = "0.13.4" dependencies = [ "anyhow", "async-compression", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 6af34a86..a75c29a7 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swap" -version = "0.13.3" +version = "0.13.4" authors = [ "The COMIT guys " ] edition = "2021" description = "XMR/BTC trustless atomic swaps." From 0ad78e4f30562b87942fc3357e1caf4669dcdd14 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Fri, 26 Jul 2024 00:20:17 +0200 Subject: [PATCH 344/395] revert: Update CHANGELOG.md --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb8e53e6..721f9fc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,8 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [0.13.4] - 2024-07-25 - - ASB: The `history` command can now be used while the asb is running. - ASB: Retry locking of Monero if it fails on first attempt From 8284bea778fb4003d339d6fc4ca93f6d8299e635 Mon Sep 17 00:00:00 2001 From: UnstoppableSwap Botty Date: Thu, 25 Jul 2024 22:31:14 +0000 Subject: [PATCH 345/395] Prepare release 0.13.4 --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 721f9fc2..7127c424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.13.4] - 2024-07-25 + - ASB: The `history` command can now be used while the asb is running. - ASB: Retry locking of Monero if it fails on first attempt @@ -373,7 +375,8 @@ 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.13.4...HEAD +[unreleased]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.4...HEAD +[0.13.4]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.4...0.13.4 [0.13.4]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...0.13.4 [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 From 49cae19059f09b5eadb72b4f73fef7c82c9913e0 Mon Sep 17 00:00:00 2001 From: binarybaron Date: Fri, 26 Jul 2024 11:40:16 +0200 Subject: [PATCH 346/395] fix: Reintroduce docker build action --- .github/workflows/build-release-binaries.yml | 53 +++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 662e3a5e..4f466ada 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -4,6 +4,9 @@ on: release: types: [created] +env: + DOCKER_IMAGE_NAME: unstoppableswap/asb + jobs: build_binaries: name: Build @@ -82,7 +85,7 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help - id: create-archive-name - shell: python # Use python to have a prettier name for the archive on Windows. + shell: python run: | import platform os_info = platform.uname() @@ -122,3 +125,51 @@ jobs: asset_path: ./${{ steps.create-archive-name.outputs.archive }} asset_name: ${{ steps.create-archive-name.outputs.archive }} asset_content_type: application/gzip + + build_and_push_docker: + name: Build and Push Docker Image + runs-on: ubuntu-latest + needs: build_binaries + steps: + - name: Checkout code + uses: actions/checkout@v4.1.7 + with: + ref: ${{ github.event.release.target_commitish }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set Docker tags + id: docker_tags + run: | + if [[ ${{ github.event.release.tag_name }} == "preview" ]]; then + echo "::set-output name=preview::true" + else + echo "::set-output name=preview::false" + fi + + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: | + ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} + ${{ env.DOCKER_IMAGE_NAME }}:latest + if: steps.docker_tags.outputs.preview == 'false' + + - name: Build and push Docker image without latest tag (preview release) + uses: docker/build-push-action@v4 + with: + context: . + file: ./Dockerfile + push: true + tags: ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} + if: steps.docker_tags.outputs.preview == 'true' From 77a43ba28cca49d269f22ba7dce13c19c5b435a7 Mon Sep 17 00:00:00 2001 From: binarybaron Date: Fri, 26 Jul 2024 11:45:48 +0200 Subject: [PATCH 347/395] fix: Reintroduce Dockerfile --- Dockerfile | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..2dbf5397 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM rust:1.59-slim AS builder + +WORKDIR /build + +RUN apt-get update +RUN apt-get install -y git clang cmake libsnappy-dev + +COPY . . + +RUN cargo build --release --bin=asb + +FROM debian:bullseye-slim + +WORKDIR /data + +COPY --from=builder /build/target/release/asb /bin/asb + +ENTRYPOINT ["asb"] From b52e07ace9e6d7853fbc20bc965141db7d7756fb Mon Sep 17 00:00:00 2001 From: binarybaron Date: Fri, 26 Jul 2024 11:46:19 +0200 Subject: [PATCH 348/395] Revert "fix: Reintroduce docker build action" This reverts commit 49cae19059f09b5eadb72b4f73fef7c82c9913e0. --- .github/workflows/build-release-binaries.yml | 53 +------------------- 1 file changed, 1 insertion(+), 52 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 4f466ada..662e3a5e 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -4,9 +4,6 @@ on: release: types: [created] -env: - DOCKER_IMAGE_NAME: unstoppableswap/asb - jobs: build_binaries: name: Build @@ -85,7 +82,7 @@ jobs: run: target/${{ matrix.target }}/release/${{ matrix.bin }} --help - id: create-archive-name - shell: python + shell: python # Use python to have a prettier name for the archive on Windows. run: | import platform os_info = platform.uname() @@ -125,51 +122,3 @@ jobs: asset_path: ./${{ steps.create-archive-name.outputs.archive }} asset_name: ${{ steps.create-archive-name.outputs.archive }} asset_content_type: application/gzip - - build_and_push_docker: - name: Build and Push Docker Image - runs-on: ubuntu-latest - needs: build_binaries - steps: - - name: Checkout code - uses: actions/checkout@v4.1.7 - with: - ref: ${{ github.event.release.target_commitish }} - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - - - name: Login to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - - name: Set Docker tags - id: docker_tags - run: | - if [[ ${{ github.event.release.tag_name }} == "preview" ]]; then - echo "::set-output name=preview::true" - else - echo "::set-output name=preview::false" - fi - - - name: Build and push Docker image - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: | - ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} - ${{ env.DOCKER_IMAGE_NAME }}:latest - if: steps.docker_tags.outputs.preview == 'false' - - - name: Build and push Docker image without latest tag (preview release) - uses: docker/build-push-action@v4 - with: - context: . - file: ./Dockerfile - push: true - tags: ${{ env.DOCKER_IMAGE_NAME }}:${{ github.event.release.tag_name }} - if: steps.docker_tags.outputs.preview == 'true' From f29bf20e8d694ae29a7202efe2cc0f014a6f7248 Mon Sep 17 00:00:00 2001 From: binarybaron Date: Fri, 26 Jul 2024 11:46:27 +0200 Subject: [PATCH 349/395] Revert "fix: Reintroduce Dockerfile" This reverts commit 77a43ba28cca49d269f22ba7dce13c19c5b435a7. --- Dockerfile | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 2dbf5397..00000000 --- a/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -FROM rust:1.59-slim AS builder - -WORKDIR /build - -RUN apt-get update -RUN apt-get install -y git clang cmake libsnappy-dev - -COPY . . - -RUN cargo build --release --bin=asb - -FROM debian:bullseye-slim - -WORKDIR /data - -COPY --from=builder /build/target/release/asb /bin/asb - -ENTRYPOINT ["asb"] From 45e14c5a1e1b13807db182abfbe2885e5f8cf9f7 Mon Sep 17 00:00:00 2001 From: binarybaron Date: Fri, 26 Jul 2024 11:51:33 +0200 Subject: [PATCH 350/395] Revert: 8284bea778fb4003d339d6fc4ca93f6d8299e635 --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7127c424..bb8e53e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -375,8 +375,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/UnstoppableSwap/xmr-btc-swap/compare/0.13.4...HEAD -[0.13.4]: https://github.com/UnstoppableSwap/xmr-btc-swap/compare/0.13.4...0.13.4 +[unreleased]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.4...HEAD [0.13.4]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.3...0.13.4 [0.13.3]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.2...0.13.3 [0.13.2]: https://github.com/comit-network/xmr-btc-swap/compare/0.13.1...0.13.2 From f3640aceb2d5e412e650a098957e366836f82351 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:23:43 +0000 Subject: [PATCH 351/395] build(deps): bump toml from 0.8.15 to 0.8.16 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.15 to 0.8.16. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.15...toml-v0.8.16) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ef8e322..73be37fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.15", + "toml 0.8.16", ] [[package]] @@ -4046,9 +4046,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -4579,7 +4579,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.15", + "toml 0.8.16", "torut", "tracing", "tracing-appender", @@ -4919,9 +4919,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" dependencies = [ "serde", "serde_spanned", @@ -4931,18 +4931,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" dependencies = [ "indexmap 2.1.0", "serde", From 011aa0cb9cd62a0c06ee80b5e7570a71924c969d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:25:26 +0000 Subject: [PATCH 352/395] build(deps): bump thomaseizinger/keep-a-changelog-new-release Bumps [thomaseizinger/keep-a-changelog-new-release](https://github.com/thomaseizinger/keep-a-changelog-new-release) from 3.0.0 to 3.1.0. - [Release notes](https://github.com/thomaseizinger/keep-a-changelog-new-release/releases) - [Changelog](https://github.com/thomaseizinger/keep-a-changelog-new-release/blob/master/CHANGELOG.md) - [Commits](https://github.com/thomaseizinger/keep-a-changelog-new-release/compare/3.0.0...3.1.0) --- updated-dependencies: - dependency-name: thomaseizinger/keep-a-changelog-new-release dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/draft-new-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 74ff34ba..9b9c849d 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -20,7 +20,7 @@ jobs: run: git checkout -b release/${{ github.event.inputs.version }} - name: Update changelog - uses: thomaseizinger/keep-a-changelog-new-release@3.0.0 + uses: thomaseizinger/keep-a-changelog-new-release@3.1.0 with: version: ${{ github.event.inputs.version }} changelogPath: CHANGELOG.md From 254874276c99bbb7ef6f2c7c5cf75c8fb1d63cc5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:00:29 +0000 Subject: [PATCH 353/395] build(deps): bump serde_json from 1.0.118 to 1.0.121 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.118 to 1.0.121. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.118...v1.0.121) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73be37fc..48d0552a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4035,11 +4035,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.118" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] From 9700d192b2623f35fbb5549d056ee76db5a5546a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:02:43 +0000 Subject: [PATCH 354/395] build(deps): bump tokio-socks from 0.5.1 to 0.5.2 Bumps [tokio-socks](https://github.com/sticnarf/tokio-socks) from 0.5.1 to 0.5.2. - [Release notes](https://github.com/sticnarf/tokio-socks/releases) - [Changelog](https://github.com/sticnarf/tokio-socks/blob/master/CHANGELOG.md) - [Commits](https://github.com/sticnarf/tokio-socks/compare/v0.5.1...v0.5.2) --- updated-dependencies: - dependency-name: tokio-socks dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73be37fc..b6804d26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4841,9 +4841,9 @@ dependencies = [ [[package]] name = "tokio-socks" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" dependencies = [ "either", "futures-util", From 6e09c73cf369c2a9ae5620e9c88fcb80e11ef031 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 11:39:26 +0000 Subject: [PATCH 355/395] build(deps): bump toml from 0.8.16 to 0.8.17 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.16 to 0.8.17. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.16...toml-v0.8.17) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb01de1b..78413bfc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.16", + "toml 0.8.17", ] [[package]] @@ -4580,7 +4580,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.16", + "toml 0.8.17", "torut", "tracing", "tracing-appender", @@ -4920,9 +4920,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" +checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631" dependencies = [ "serde", "serde_spanned", @@ -4932,18 +4932,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.17" +version = "0.22.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" +checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0" dependencies = [ "indexmap 2.1.0", "serde", @@ -5767,9 +5767,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" dependencies = [ "memchr", ] From 587212abc7e4c5d81bea31b9e236b3ef33f58e4b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:38:09 +0000 Subject: [PATCH 356/395] build(deps): bump mockito from 1.4.0 to 1.5.0 Bumps [mockito](https://github.com/lipanski/mockito) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/lipanski/mockito/releases) - [Commits](https://github.com/lipanski/mockito/compare/1.4.0...1.5.0) --- updated-dependencies: - dependency-name: mockito dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 14 ++++++++++---- swap/Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78413bfc..d75c78d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1774,6 +1774,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "httparse", + "httpdate", "itoa", "pin-project-lite 0.2.13", "smallvec", @@ -2593,14 +2594,19 @@ dependencies = [ [[package]] name = "mockito" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f6e023aa5bdf392aa06c78e4a4e6d498baab5138d0c993503350ebbc37bf1e" +checksum = "09b34bd91b9e5c5b06338d392463e1318d683cf82ec3d3af4014609be6e2108d" dependencies = [ "assert-json-diff", + "bytes", "colored", - "futures-core", - "hyper 0.14.28", + "futures-util", + "http 1.0.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.4.1", + "hyper-util", "log", "rand 0.8.3", "regex", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index a75c29a7..f7837c6a 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -81,7 +81,7 @@ bitcoin-harness = { git = "https://github.com/delta1/bitcoin-harness-rs.git", re get-port = "3" hyper = "1.4" jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } -mockito = "1.4" +mockito = "1.5" monero-harness = { path = "../monero-harness" } port_check = "0.2" proptest = "1" From af6bc47ed344055cc9e5e6a6a9ab15d8eb20528b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:39:35 +0000 Subject: [PATCH 357/395] build(deps): bump toml from 0.8.17 to 0.8.19 Bumps [toml](https://github.com/toml-rs/toml) from 0.8.17 to 0.8.19. - [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.17...toml-v0.8.19) --- updated-dependencies: - dependency-name: toml dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78413bfc..fcb20f9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -743,7 +743,7 @@ dependencies = [ "nom", "pathdiff", "serde", - "toml 0.8.17", + "toml 0.8.19", ] [[package]] @@ -4580,7 +4580,7 @@ dependencies = [ "tokio-tar", "tokio-tungstenite", "tokio-util", - "toml 0.8.17", + "toml 0.8.19", "torut", "tracing", "tracing-appender", @@ -4920,9 +4920,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a44eede9b727419af8095cb2d72fab15487a541f54647ad4414b34096ee4631" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", @@ -4941,9 +4941,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.18" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1490595c74d930da779e944f5ba2ecdf538af67df1a9848cbd156af43c1b7cf0" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap 2.1.0", "serde", @@ -5767,9 +5767,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.6.16" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] From cc854be8f4f2568905703b12a728320987ee9f5f Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:35:03 +0200 Subject: [PATCH 358/395] feat: Enhance history command with more swap details (#1725) --- swap/src/api.rs | 4 ++ swap/src/api/request.rs | 98 ++++++++++++++++++++++++++++++-- swap/src/asb/command.rs | 24 ++++++-- swap/src/bin/asb.rs | 86 +++++++++++++++++++++++++--- swap/src/cli/command.rs | 30 ++++++++-- swap/src/monero.rs | 15 +++-- swap/src/protocol/alice/state.rs | 4 +- swap/src/protocol/alice/swap.rs | 2 +- swap/src/protocol/bob/state.rs | 2 +- swap/tests/rpc.rs | 19 ++++++- 10 files changed, 248 insertions(+), 36 deletions(-) diff --git a/swap/src/api.rs b/swap/src/api.rs index 5640c833..a87db7c5 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -167,6 +167,7 @@ pub struct Context { pub swap_lock: Arc, pub config: Config, pub tasks: Arc, + pub is_daemon: bool, } #[allow(clippy::too_many_arguments)] @@ -180,6 +181,7 @@ impl Context { debug: bool, json: bool, server_address: Option, + is_daemon: bool, ) -> Result { let data_dir = data::data_dir_from(data, is_testnet)?; let env_config = env_config_from(is_testnet); @@ -241,6 +243,7 @@ impl Context { }, swap_lock: Arc::new(SwapLock::new()), tasks: Arc::new(PendingTaskList::default()), + is_daemon, }; Ok(context) @@ -265,6 +268,7 @@ impl Context { monero_rpc_process: None, swap_lock: Arc::new(SwapLock::new()), tasks: Arc::new(PendingTaskList::default()), + is_daemon: true, } } diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index b1e9c68c..d47e9a0d 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -8,9 +8,12 @@ use crate::protocol::bob::{BobState, Swap}; use crate::protocol::{bob, State}; use crate::{bitcoin, cli, monero, rpc}; use anyhow::{bail, Context as AnyContext, Result}; +use comfy_table::Table; use libp2p::core::Multiaddr; use qrcode::render::unicode; use qrcode::QrCode; +use rust_decimal::prelude::FromPrimitive; +use rust_decimal::Decimal; use serde_json::json; use std::cmp::min; use std::convert::TryInto; @@ -638,14 +641,97 @@ impl Request { }) } Method::History => { - let swaps = context.db.all().await?; - let mut vec: Vec<(Uuid, String)> = Vec::new(); - for (swap_id, state) in swaps { - let state: BobState = state.try_into()?; - vec.push((swap_id, state.to_string())); + let mut table = Table::new(); + table.set_header(vec![ + "Swap ID", + "Start Date", + "State", + "BTC Amount", + "XMR Amount", + "Exchange Rate", + "Trading Partner Peer ID", + ]); + + let all_swaps = context.db.all().await?; + let mut json_results = Vec::new(); + + for (swap_id, state) in all_swaps { + let result: Result<_> = async { + let latest_state: BobState = state.try_into()?; + let all_states = context.db.get_states(swap_id).await?; + let state3 = all_states + .iter() + .find_map(|s| { + if let State::Bob(BobState::BtcLocked { state3, .. }) = s { + Some(state3) + } else { + None + } + }) + .context("Failed to get \"BtcLocked\" state")?; + + let swap_start_date = context.db.get_swap_start_date(swap_id).await?; + let peer_id = context.db.get_peer_id(swap_id).await?; + let btc_amount = state3.tx_lock.lock_amount(); + let xmr_amount = state3.xmr; + let exchange_rate = Decimal::from_f64(btc_amount.to_btc()) + .ok_or_else(|| { + anyhow::anyhow!("Failed to convert BTC amount to Decimal") + })? + .checked_div(xmr_amount.as_xmr()) + .ok_or_else(|| anyhow::anyhow!("Division by zero or overflow"))?; + let exchange_rate = format!("{} XMR/BTC", exchange_rate.round_dp(8)); + + let swap_data = json!({ + "swapId": swap_id.to_string(), + "startDate": swap_start_date.to_string(), + "state": latest_state.to_string(), + "btcAmount": btc_amount.to_string(), + "xmrAmount": xmr_amount.to_string(), + "exchangeRate": exchange_rate, + "tradingPartnerPeerId": peer_id.to_string() + }); + + if context.config.json { + tracing::info!( + swap_id = %swap_id, + swap_start_date = %swap_start_date, + latest_state = %latest_state, + btc_amount = %btc_amount, + xmr_amount = %xmr_amount, + exchange_rate = %exchange_rate, + trading_partner_peer_id = %peer_id, + "Found swap in database" + ); + } else { + table.add_row(vec![ + swap_id.to_string(), + swap_start_date.to_string(), + latest_state.to_string(), + btc_amount.to_string(), + xmr_amount.to_string(), + exchange_rate, + peer_id.to_string(), + ]); + } + + Ok(swap_data) + } + .await; + + match result { + Ok(swap_data) => json_results.push(swap_data), + Err(e) => { + tracing::error!(swap_id = %swap_id, error = %e, "Failed to get swap details") + } + } } - Ok(json!({ "swaps": vec })) + if !context.config.json && !context.is_daemon { + println!("{}", table); + } + + Ok(json!({"swaps": json_results})) } Method::GetRawStates => { let raw_history = context.db.raw_all().await?; diff --git a/swap/src/asb/command.rs b/swap/src/asb/command.rs index f22e1500..260b5e9d 100644 --- a/swap/src/asb/command.rs +++ b/swap/src/asb/command.rs @@ -33,13 +33,13 @@ where env_config: env_config(testnet), cmd: Command::Start { resume_only }, }, - RawCommand::History => Arguments { + RawCommand::History { only_unfinished } => Arguments { testnet, json, disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), - cmd: Command::History, + cmd: Command::History { only_unfinished }, }, RawCommand::WithdrawBtc { amount, address } => Arguments { testnet, @@ -195,7 +195,9 @@ pub enum Command { Start { resume_only: bool, }, - History, + History { + only_unfinished: bool, + }, Config, WithdrawBtc { amount: Option, @@ -269,7 +271,13 @@ pub enum RawCommand { resume_only: bool, }, #[structopt(about = "Prints swap-id and the state of each swap ever made.")] - History, + History { + #[structopt( + long = "only-unfinished", + help = "If set, only unfinished swaps will be printed." + )] + only_unfinished: bool, + }, #[structopt(about = "Prints the current config")] Config, #[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")] @@ -387,7 +395,9 @@ mod tests { disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, - cmd: Command::History, + cmd: Command::History { + only_unfinished: false, + }, }; let args = parse_args(raw_ars).unwrap(); assert_eq!(expected_args, args); @@ -570,7 +580,9 @@ mod tests { disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, - cmd: Command::History, + cmd: Command::History { + only_unfinished: false, + }, }; let args = parse_args(raw_ars).unwrap(); assert_eq!(expected_args, args); diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 0f2f13b5..66630b88 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -18,6 +18,8 @@ use libp2p::core::multiaddr::Protocol; use libp2p::core::Multiaddr; use libp2p::swarm::AddressScore; use libp2p::Swarm; +use rust_decimal::prelude::FromPrimitive; +use rust_decimal::Decimal; use std::convert::TryInto; use std::env; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; @@ -33,7 +35,9 @@ use swap::common::check_latest_version; use swap::database::{open_db, AccessMode}; use swap::network::rendezvous::XmrBtcNamespace; use swap::network::swarm; +use swap::protocol::alice::swap::is_complete; use swap::protocol::alice::{run, AliceState}; +use swap::protocol::State; use swap::seed::Seed; use swap::tor::AuthenticatedClient; use swap::{asb, bitcoin, kraken, monero, tor}; @@ -224,19 +228,87 @@ async fn main() -> Result<()> { event_loop.run().await; } - Command::History => { + Command::History { only_unfinished } => { let db = open_db(config.data.dir.join("sqlite"), AccessMode::ReadOnly).await?; + let mut table: Table = Table::new(); - let mut table = Table::new(); + table.set_header(vec![ + "Swap ID", + "Start Date", + "State", + "BTC Amount", + "XMR Amount", + "Exchange Rate", + "Trading Partner Peer ID", + "Completed", + ]); - table.set_header(vec!["SWAP ID", "STATE"]); + let all_swaps = db.all().await?; + for (swap_id, state) in all_swaps { + if let Err(e) = async { + let latest_state: AliceState = state.try_into()?; + let is_completed = is_complete(&latest_state); - for (swap_id, state) in db.all().await? { - let state: AliceState = state.try_into()?; - table.add_row(vec![swap_id.to_string(), state.to_string()]); + if only_unfinished && is_completed { + return Ok::<_, anyhow::Error>(()); + } + + let all_states = db.get_states(swap_id).await?; + let state3 = all_states + .iter() + .find_map(|s| match s { + State::Alice(AliceState::BtcLockTransactionSeen { state3 }) => { + Some(state3) + } + _ => None, + }) + .context("Failed to get \"BtcLockTransactionSeen\" state")?; + + let swap_start_date = db.get_swap_start_date(swap_id).await?; + let peer_id = db.get_peer_id(swap_id).await?; + + let exchange_rate = Decimal::from_f64(state3.btc.to_btc()) + .ok_or_else(|| anyhow::anyhow!("Failed to convert BTC amount to Decimal"))? + .checked_div(state3.xmr.as_xmr()) + .ok_or_else(|| anyhow::anyhow!("Division by zero or overflow"))?; + let exchange_rate = format!("{} XMR/BTC", exchange_rate.round_dp(8)); + + if json { + tracing::info!( + swap_id = %swap_id, + swap_start_date = %swap_start_date, + latest_state = %latest_state, + btc_amount = %state3.btc, + xmr_amount = %state3.xmr, + exchange_rate = %exchange_rate, + trading_partner_peer_id = %peer_id, + completed = is_completed, + "Found swap in database" + ); + } else { + table.add_row(vec![ + swap_id.to_string(), + swap_start_date.to_string(), + latest_state.to_string(), + state3.btc.to_string(), + state3.xmr.to_string(), + exchange_rate, + peer_id.to_string(), + is_completed.to_string(), + ]); + } + + Ok::<_, anyhow::Error>(()) + } + .await + { + tracing::error!(swap_id = %swap_id, error = %e, "Failed to get swap details"); + } } - println!("{}", table); + if !json { + println!("{}", table); + } } Command::Config => { let config_json = serde_json::to_string_pretty(&config)?; diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 4881d94e..6c460f82 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -78,6 +78,7 @@ where debug, json, None, + false, ) .await?; @@ -100,14 +101,16 @@ where let request = Request::new(Method::History); let context = - Context::build(None, None, None, data, is_testnet, debug, json, None).await?; + Context::build(None, None, None, data, is_testnet, debug, json, None, false) + .await?; (context, request) } CliCommand::Config => { let request = Request::new(Method::Config); let context = - Context::build(None, None, None, data, is_testnet, debug, json, None).await?; + Context::build(None, None, None, data, is_testnet, debug, json, None, false) + .await?; (context, request) } CliCommand::Balance { bitcoin } => { @@ -124,6 +127,7 @@ where debug, json, None, + false, ) .await?; (context, request) @@ -145,6 +149,7 @@ where debug, json, server_address, + true, ) .await?; (context, request) @@ -166,6 +171,7 @@ where debug, json, None, + false, ) .await?; (context, request) @@ -187,6 +193,7 @@ where debug, json, None, + false, ) .await?; (context, request) @@ -207,6 +214,7 @@ where debug, json, None, + false, ) .await?; (context, request) @@ -217,8 +225,18 @@ where } => { let request = Request::new(Method::ListSellers { rendezvous_point }); - let context = - Context::build(None, None, Some(tor), data, is_testnet, debug, json, None).await?; + let context = Context::build( + None, + None, + Some(tor), + data, + is_testnet, + debug, + json, + None, + false, + ) + .await?; (context, request) } @@ -234,6 +252,7 @@ where debug, json, None, + false, ) .await?; (context, request) @@ -244,7 +263,8 @@ where let request = Request::new(Method::MoneroRecovery { swap_id }); let context = - Context::build(None, None, None, data, is_testnet, debug, json, None).await?; + Context::build(None, None, None, data, is_testnet, debug, json, None, false) + .await?; (context, request) } diff --git a/swap/src/monero.rs b/swap/src/monero.rs index 8205e75f..e5dd9e80 100644 --- a/swap/src/monero.rs +++ b/swap/src/monero.rs @@ -142,6 +142,14 @@ impl Amount { Decimal::from(self.as_piconero()) } + pub fn as_xmr(&self) -> Decimal { + let mut decimal = Decimal::from(self.0); + decimal + .set_scale(12) + .expect("12 is smaller than max precision of 28"); + decimal + } + fn from_decimal(amount: Decimal) -> Result { let piconeros_dec = amount.mul(Decimal::from_u64(PICONERO_OFFSET).expect("constant to fit into u64")); @@ -184,11 +192,8 @@ impl From for u64 { impl fmt::Display for Amount { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut decimal = Decimal::from(self.0); - decimal - .set_scale(12) - .expect("12 is smaller than max precision of 28"); - write!(f, "{} XMR", decimal) + let xmr_value = self.as_xmr(); + write!(f, "{} XMR", xmr_value) } } diff --git a/swap/src/protocol/alice/state.rs b/swap/src/protocol/alice/state.rs index f0acab23..7627a529 100644 --- a/swap/src/protocol/alice/state.rs +++ b/swap/src/protocol/alice/state.rs @@ -384,8 +384,8 @@ pub struct State3 { S_b_bitcoin: bitcoin::PublicKey, pub v: monero::PrivateViewKey, #[serde(with = "::bitcoin::util::amount::serde::as_sat")] - btc: bitcoin::Amount, - xmr: monero::Amount, + pub btc: bitcoin::Amount, + pub xmr: monero::Amount, pub cancel_timelock: CancelTimelock, pub punish_timelock: PunishTimelock, refund_address: bitcoin::Address, diff --git a/swap/src/protocol/alice/swap.rs b/swap/src/protocol/alice/swap.rs index 3848a2e1..14f718d3 100644 --- a/swap/src/protocol/alice/swap.rs +++ b/swap/src/protocol/alice/swap.rs @@ -440,7 +440,7 @@ where }) } -pub(crate) fn is_complete(state: &AliceState) -> bool { +pub fn is_complete(state: &AliceState) -> bool { matches!( state, AliceState::XmrRefunded diff --git a/swap/src/protocol/bob/state.rs b/swap/src/protocol/bob/state.rs index 8fe5ca32..04e7778e 100644 --- a/swap/src/protocol/bob/state.rs +++ b/swap/src/protocol/bob/state.rs @@ -369,7 +369,7 @@ pub struct State3 { S_a_monero: monero::PublicKey, S_a_bitcoin: bitcoin::PublicKey, v: monero::PrivateViewKey, - xmr: monero::Amount, + pub xmr: monero::Amount, pub cancel_timelock: CancelTimelock, punish_timelock: PunishTimelock, refund_address: bitcoin::Address, diff --git a/swap/tests/rpc.rs b/swap/tests/rpc.rs index 5dc640d4..553ccf46 100644 --- a/swap/tests/rpc.rs +++ b/swap/tests/rpc.rs @@ -103,13 +103,26 @@ mod test { let (client, _, _) = setup_daemon(harness_ctx).await; - let response: HashMap> = client + let response: HashMap> = client .request("get_history", ObjectParams::new()) .await .unwrap(); - let swaps: Vec<(Uuid, String)> = vec![(bob_swap_id, "btc is locked".to_string())]; - assert_eq!(response, HashMap::from([("swaps".to_string(), swaps)])); + let swaps = response.get("swaps").unwrap(); + assert_eq!(swaps.len(), 1); + + assert_has_keys_serde( + swaps[0].as_object().unwrap(), + &[ + "swapId", + "startDate", + "state", + "btcAmount", + "xmrAmount", + "exchangeRate", + "tradingPartnerPeerId", + ], + ); let response: HashMap>> = client .request("get_raw_states", ObjectParams::new()) From 9aaa7d358f565384eda5592914ecea9122a79d46 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 2 Aug 2024 11:39:10 +0000 Subject: [PATCH 359/395] build(deps): bump serde_json from 1.0.121 to 1.0.122 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.121 to 1.0.122. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.121...v1.0.122) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f374293..c95f4443 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4041,9 +4041,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.121" +version = "1.0.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" +checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" dependencies = [ "itoa", "memchr", From 6a76e9efbe2c06febd2da3263b6e789308b46cd8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:18:44 +0000 Subject: [PATCH 360/395] build(deps): bump tempfile from 3.10.1 to 3.11.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.10.1 to 3.11.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.10.1...v3.11.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c95f4443..233be0d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4641,12 +4641,13 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" dependencies = [ "cfg-if 1.0.0", "fastrand", + "once_cell", "rustix", "windows-sys 0.52.0", ] From 952fb71a6a22598c5f00ca3fe02bfb1ccb0ac65f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:15:11 +0000 Subject: [PATCH 361/395] build(deps): bump tempfile from 3.11.0 to 3.12.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.11.0 to 3.12.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/commits) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 70 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 233be0d3..2addb45b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4641,15 +4641,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.11.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if 1.0.0", "fastrand", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -5625,7 +5625,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -5645,17 +5654,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -5666,9 +5676,9 @@ checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -5684,9 +5694,9 @@ checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -5702,9 +5712,15 @@ checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -5720,9 +5736,9 @@ checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -5738,9 +5754,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -5750,9 +5766,9 @@ checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -5768,9 +5784,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" From f799da5203e9c27a91581aa444d02a42e62cbd87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Aug 2024 11:50:16 +0000 Subject: [PATCH 362/395] build(deps): bump serde from 1.0.204 to 1.0.205 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.204 to 1.0.205. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.204...v1.0.205) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 233be0d3..9d4b3d1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4001,9 +4001,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.204" +version = "1.0.205" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" dependencies = [ "serde_derive", ] @@ -4030,9 +4030,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.205" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" dependencies = [ "proc-macro2", "quote", From c8cbd27b795947c4950d75f71ebd5f264de2d05a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:07:36 +0000 Subject: [PATCH 363/395] build(deps): bump serde_json from 1.0.122 to 1.0.124 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.122 to 1.0.124. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.122...v1.0.124) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35962604..a4c51e62 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4041,9 +4041,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.122" +version = "1.0.124" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da" +checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" dependencies = [ "itoa", "memchr", From 33901a2ea9c3067b54025731eb7cbae6285fec69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Aug 2024 11:07:58 +0000 Subject: [PATCH 364/395] build(deps): bump serde from 1.0.205 to 1.0.206 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.205 to 1.0.206. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.205...v1.0.206) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35962604..f5f1b250 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4001,9 +4001,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.205" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33aedb1a7135da52b7c21791455563facbbcc43d0f0f66165b42c21b3dfb150" +checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" dependencies = [ "serde_derive", ] @@ -4030,9 +4030,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.205" +version = "1.0.206" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692d6f5ac90220161d6774db30c662202721e64aed9058d2c394f451261420c1" +checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", From 4eff6fe503e6a39fdee543703e974d1ffc5109ad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 16 Aug 2024 11:04:29 +0000 Subject: [PATCH 365/395] build(deps): bump serde from 1.0.206 to 1.0.208 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.206 to 1.0.208. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.206...v1.0.208) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99040c5c..44e21ae8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4001,9 +4001,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.206" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3e4cd94123dd520a128bcd11e34d9e9e423e7e3e50425cb1b4b1e3549d0284" +checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" dependencies = [ "serde_derive", ] @@ -4030,9 +4030,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.206" +version = "1.0.208" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" +checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" dependencies = [ "proc-macro2", "quote", From 3cebddf5936426680257bf88ad5834cb4e95e1fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:31:40 +0000 Subject: [PATCH 366/395] build(deps): bump reqwest from 0.12.5 to 0.12.7 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.12.5 to 0.12.7. - [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.12.5...v0.12.7) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 51 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44e21ae8..f6ef4952 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1906,7 +1906,7 @@ dependencies = [ "socket2 0.3.19", "widestring", "winapi", - "winreg 0.6.2", + "winreg", ] [[package]] @@ -3491,9 +3491,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.5" +version = "0.12.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" dependencies = [ "base64 0.22.1", "bytes", @@ -3532,7 +3532,7 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots 0.26.1", - "winreg 0.52.0", + "windows-registry", ] [[package]] @@ -4626,6 +4626,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -5597,6 +5600,36 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-registry" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" +dependencies = [ + "windows-result", + "windows-strings", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result", + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.32.0" @@ -5806,16 +5839,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "winreg" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" -dependencies = [ - "cfg-if 1.0.0", - "windows-sys 0.48.0", -] - [[package]] name = "x25519-dalek" version = "1.1.0" From 7871cf256b62d7d6fcb056c6b12d3470934f02fa Mon Sep 17 00:00:00 2001 From: Einliterflasche <81313171+Einliterflasche@users.noreply.github.com> Date: Wed, 21 Aug 2024 16:33:04 +0200 Subject: [PATCH 367/395] feat(asb + cli): Redact logs + unify tracing infrastructure (#1733) --- .cargo/config.toml | 4 + CHANGELOG.md | 3 + Cargo.lock | 39 ++++-- monero-harness/Cargo.toml | 2 +- swap/Cargo.toml | 2 + swap/src/api.rs | 14 +- swap/src/api/request.rs | 28 ++++ swap/src/asb.rs | 1 - swap/src/asb/command.rs | 69 +++++----- swap/src/asb/tracing.rs | 30 ----- swap/src/bin/asb.rs | 47 +++++-- swap/src/cli.rs | 1 - swap/src/cli/command.rs | 35 +++++ swap/src/cli/tracing.rs | 112 ---------------- swap/src/common.rs | 56 -------- swap/src/common/mod.rs | 221 ++++++++++++++++++++++++++++++++ swap/src/common/tracing_util.rs | 64 +++++++++ swap/src/database/sqlite.rs | 5 +- swap/src/rpc/methods.rs | 28 +++- swap/src/seed.rs | 4 +- 20 files changed, 505 insertions(+), 260 deletions(-) delete mode 100644 swap/src/asb/tracing.rs delete mode 100644 swap/src/cli/tracing.rs delete mode 100644 swap/src/common.rs create mode 100644 swap/src/common/mod.rs create mode 100644 swap/src/common/tracing_util.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index 0c1c209f..b707df9d 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,6 @@ [target.armv7-unknown-linux-gnueabihf] linker = "arm-linux-gnueabihf-gcc" + +# windows defaults to smaller stack sizes which isn't enough +[target.'cfg(windows)'] +rustflags = ["-C", "link-args=/STACK:8388608"] diff --git a/CHANGELOG.md b/CHANGELOG.md index bb8e53e6..c22e533e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- ASB + CLI: You can now use the `logs` command to retrieve logs stored in the past, redacting addresses and id's using `logs --redact`. +- ASB: The `--disable-timestamp` flag has been removed + ## [0.13.4] - 2024-07-25 - ASB: The `history` command can now be used while the asb is running. diff --git a/Cargo.lock b/Cargo.lock index f6ef4952..f0997737 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,6 +78,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -1500,7 +1509,7 @@ version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.18", "bstr", "fnv", "log", @@ -2508,7 +2517,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f099785f7595cc4b4553a174ce30dd7589ef93391ff414dbb67f62392b9e0ce1" dependencies = [ - "regex-automata", + "regex-automata 0.1.9", ] [[package]] @@ -2517,7 +2526,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.9", ] [[package]] @@ -2653,7 +2662,7 @@ dependencies = [ "testcontainers", "tokio", "tracing", - "tracing-subscriber 0.2.25", + "tracing-subscriber 0.3.18", ] [[package]] @@ -3449,13 +3458,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.3" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ - "aho-corasick", + "aho-corasick 1.1.3", "memchr", - "regex-syntax 0.6.29", + "regex-automata 0.4.7", + "regex-syntax 0.8.2", ] [[package]] @@ -3468,6 +3478,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick 1.1.3", + "memchr", + "regex-syntax 0.8.2", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -4557,12 +4578,14 @@ dependencies = [ "monero", "monero-harness", "monero-rpc", + "once_cell", "pem", "port_check", "proptest", "qrcode", "rand 0.8.3", "rand_chacha 0.3.1", + "regex", "reqwest", "rust_decimal", "rust_decimal_macros", diff --git a/monero-harness/Cargo.toml b/monero-harness/Cargo.toml index 1151f47a..e15c751d 100644 --- a/monero-harness/Cargo.toml +++ b/monero-harness/Cargo.toml @@ -13,4 +13,4 @@ rand = "0.7" testcontainers = "0.15" tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "macros" ] } tracing = "0.1" -tracing-subscriber = { version = "0.2", default-features = false, features = [ "fmt", "ansi", "env-filter", "tracing-log" ] } +tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "tracing-log" ] } diff --git a/swap/Cargo.toml b/swap/Cargo.toml index f7837c6a..8354ec0a 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -37,11 +37,13 @@ jsonrpsee-core = "0.16.2" libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } +once_cell = "1.19" pem = "3.0" proptest = "1" qrcode = "0.14" rand = "0.8" rand_chacha = "0.3" +regex = "1.10" reqwest = { version = "0.12", features = [ "http2", "rustls-tls", "stream", "socks" ], default-features = false } rust_decimal = { version = "1", features = [ "serde-float" ] } rust_decimal_macros = "1" diff --git a/swap/src/api.rs b/swap/src/api.rs index a87db7c5..ea87aae3 100644 --- a/swap/src/api.rs +++ b/swap/src/api.rs @@ -1,12 +1,13 @@ pub mod request; use crate::cli::command::{Bitcoin, Monero, Tor}; +use crate::common::tracing_util::Format; use crate::database::{open_db, AccessMode}; use crate::env::{Config as EnvConfig, GetConfig, Mainnet, Testnet}; use crate::fs::system_data_dir; use crate::network::rendezvous::XmrBtcNamespace; use crate::protocol::Database; use crate::seed::Seed; -use crate::{bitcoin, cli, monero}; +use crate::{bitcoin, common, monero}; use anyhow::{bail, Context as AnyContext, Error, Result}; use futures::future::try_join_all; use std::fmt; @@ -16,6 +17,8 @@ use std::path::PathBuf; use std::sync::{Arc, Once}; use tokio::sync::{broadcast, broadcast::Sender, Mutex, RwLock}; use tokio::task::JoinHandle; +use tracing::level_filters::LevelFilter; +use tracing::Level; use url::Url; static START: Once = Once::new(); @@ -186,8 +189,15 @@ impl Context { let data_dir = data::data_dir_from(data, is_testnet)?; let env_config = env_config_from(is_testnet); + let format = if json { Format::Json } else { Format::Raw }; + let level_filter = if debug { + LevelFilter::from_level(Level::DEBUG) + } else { + LevelFilter::from_level(Level::INFO) + }; + START.call_once(|| { - let _ = cli::tracing::init(debug, json, data_dir.join("logs")); + let _ = common::tracing_util::init(level_filter, format, data_dir.join("logs")); }); let seed = Seed::from_file_or_generate(data_dir.as_path()) diff --git a/swap/src/api/request.rs b/swap/src/api/request.rs index d47e9a0d..33e261d3 100644 --- a/swap/src/api/request.rs +++ b/swap/src/api/request.rs @@ -1,6 +1,7 @@ use crate::api::Context; use crate::bitcoin::{Amount, ExpiredTimelocks, TxLock}; use crate::cli::{list_sellers, EventLoop, SellerStatus}; +use crate::common::get_logs; use crate::libp2p_ext::MultiAddrExt; use crate::network::quote::{BidQuote, ZeroQuoteReceived}; use crate::network::swarm; @@ -19,6 +20,7 @@ use std::cmp::min; use std::convert::TryInto; use std::future::Future; use std::net::SocketAddr; +use std::path::PathBuf; use std::sync::Arc; use std::time::Duration; use tracing::{debug_span, field, Instrument, Span}; @@ -48,6 +50,11 @@ pub enum Method { swap_id: Uuid, }, History, + Logs { + logs_dir: Option, + redact: bool, + swap_id: Option, + }, Config, WithdrawBtc { amount: Option, @@ -125,6 +132,13 @@ impl Method { log_reference_id = field::Empty ) } + Method::Logs { .. } => { + debug_span!( + "method", + method_name = "Logs", + log_reference_id = field::Empty + ) + } Method::ListSellers { .. } => { debug_span!( "method", @@ -733,6 +747,20 @@ impl Request { Ok(json!({"swaps": json_results})) } + Method::Logs { + logs_dir, + redact, + swap_id, + } => { + let dir = logs_dir.unwrap_or(context.config.data_dir.join("logs")); + let logs = get_logs(dir, swap_id, redact).await?; + + for msg in &logs { + println!("{msg}"); + } + + Ok(json!({ "logs": logs })) + } Method::GetRawStates => { let raw_history = context.db.raw_all().await?; diff --git a/swap/src/asb.rs b/swap/src/asb.rs index b5ed8ac1..404a3b61 100644 --- a/swap/src/asb.rs +++ b/swap/src/asb.rs @@ -4,7 +4,6 @@ mod event_loop; mod network; mod rate; mod recovery; -pub mod tracing; pub use event_loop::{EventLoop, EventLoopHandle, FixedRate, KrakenRate, LatestRate}; pub use network::behaviour::{Behaviour, OutEvent}; diff --git a/swap/src/asb/command.rs b/swap/src/asb/command.rs index 260b5e9d..67565065 100644 --- a/swap/src/asb/command.rs +++ b/swap/src/asb/command.rs @@ -19,7 +19,6 @@ where let args = RawArguments::from_clap(&matches); let json = args.json; - let disable_timestamp = args.disable_timestamp; let testnet = args.testnet; let config = args.config; let command: RawCommand = args.cmd; @@ -28,7 +27,6 @@ where RawCommand::Start { resume_only } => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Start { resume_only }, @@ -36,15 +34,28 @@ where RawCommand::History { only_unfinished } => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::History { only_unfinished }, }, + RawCommand::Logs { + logs_dir: dir_path, + swap_id, + redact, + } => Arguments { + testnet, + json, + config_path: config_path(config, testnet)?, + env_config: env_config(testnet), + cmd: Command::Logs { + logs_dir: dir_path, + swap_id, + redact, + }, + }, RawCommand::WithdrawBtc { amount, address } => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::WithdrawBtc { @@ -55,7 +66,6 @@ where RawCommand::Balance => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Balance, @@ -63,7 +73,6 @@ where RawCommand::Config => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Config, @@ -71,7 +80,6 @@ where RawCommand::ExportBitcoinWallet => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::ExportBitcoinWallet, @@ -82,7 +90,6 @@ where }) => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Redeem { @@ -96,7 +103,6 @@ where }) => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Cancel { swap_id }, @@ -106,7 +112,6 @@ where }) => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Refund { swap_id }, @@ -116,7 +121,6 @@ where }) => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::Punish { swap_id }, @@ -124,7 +128,6 @@ where RawCommand::ManualRecovery(ManualRecovery::SafelyAbort { swap_id }) => Arguments { testnet, json, - disable_timestamp, config_path: config_path(config, testnet)?, env_config: env_config(testnet), cmd: Command::SafelyAbort { swap_id }, @@ -184,7 +187,6 @@ pub struct BitcoinAddressNetworkMismatch { pub struct Arguments { pub testnet: bool, pub json: bool, - pub disable_timestamp: bool, pub config_path: PathBuf, pub env_config: env::Config, pub cmd: Command, @@ -199,6 +201,11 @@ pub enum Command { only_unfinished: bool, }, Config, + Logs { + logs_dir: Option, + swap_id: Option, + redact: bool, + }, WithdrawBtc { amount: Option, address: Address, @@ -270,6 +277,25 @@ pub enum RawCommand { )] resume_only: bool, }, + #[structopt(about = "Prints all logging messages issued in the past.")] + Logs { + #[structopt( + short = "d", + help = "Print the logs from this directory instead of the default one." + )] + logs_dir: Option, + #[structopt( + help = "Redact swap-ids, Bitcoin and Monero addresses.", + long = "redact" + )] + redact: bool, + #[structopt( + long = "swap-id", + help = "Filter for logs concerning this swap.", + long_help = "This checks whether each logging message contains the swap id. Some messages might be skipped when they don't contain the swap id even though they're relevant." + )] + swap_id: Option, + }, #[structopt(about = "Prints swap-id and the state of each swap ever made.")] History { #[structopt( @@ -374,7 +400,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::Start { resume_only: false }, @@ -392,7 +417,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::History { @@ -412,7 +436,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::Balance, @@ -434,7 +457,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::WithdrawBtc { @@ -461,7 +483,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::Cancel { @@ -487,7 +508,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::Refund { @@ -513,7 +533,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::Punish { @@ -539,7 +558,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: false, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::SafelyAbort { @@ -559,7 +577,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::Start { resume_only: false }, @@ -577,7 +594,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::History { @@ -597,7 +613,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::Balance, @@ -621,7 +636,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::WithdrawBtc { @@ -648,7 +662,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::Cancel { @@ -675,7 +688,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::Refund { @@ -702,7 +714,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::Punish { @@ -729,7 +740,6 @@ mod tests { let expected_args = Arguments { testnet: true, json: false, - disable_timestamp: false, config_path: default_testnet_conf_path, env_config: testnet_env_config, cmd: Command::SafelyAbort { @@ -749,7 +759,6 @@ mod tests { let expected_args = Arguments { testnet: false, json: false, - disable_timestamp: true, config_path: default_mainnet_conf_path, env_config: mainnet_env_config, cmd: Command::Start { resume_only: false }, diff --git a/swap/src/asb/tracing.rs b/swap/src/asb/tracing.rs deleted file mode 100644 index c21c1e70..00000000 --- a/swap/src/asb/tracing.rs +++ /dev/null @@ -1,30 +0,0 @@ -use anyhow::Result; -use tracing_subscriber::filter::LevelFilter; -use tracing_subscriber::fmt::time::UtcTime; -use tracing_subscriber::FmtSubscriber; - -pub fn init(level: LevelFilter, json_format: bool, timestamp: bool) -> Result<()> { - if level == LevelFilter::OFF { - return Ok(()); - } - - let is_terminal = atty::is(atty::Stream::Stderr); - - let builder = FmtSubscriber::builder() - .with_env_filter(format!("asb={},swap={}", level, level)) - .with_writer(std::io::stderr) - .with_ansi(is_terminal) - .with_timer(UtcTime::rfc_3339()) - .with_target(false); - - match (json_format, timestamp) { - (true, true) => builder.json().init(), - (true, false) => builder.json().without_time().init(), - (false, true) => builder.init(), - (false, false) => builder.without_time().init(), - } - - tracing::info!(%level, "Initialized tracing"); - - Ok(()) -} diff --git a/swap/src/bin/asb.rs b/swap/src/bin/asb.rs index 66630b88..3a0d2dd4 100644 --- a/swap/src/bin/asb.rs +++ b/swap/src/bin/asb.rs @@ -31,7 +31,8 @@ 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::common::tracing_util::Format; +use swap::common::{self, check_latest_version, get_logs}; use swap::database::{open_db, AccessMode}; use swap::network::rendezvous::XmrBtcNamespace; use swap::network::swarm; @@ -40,44 +41,40 @@ use swap::protocol::alice::{run, AliceState}; use swap::protocol::State; use swap::seed::Seed; use swap::tor::AuthenticatedClient; -use swap::{asb, bitcoin, kraken, monero, tor}; +use swap::{bitcoin, kraken, monero, tor}; use tracing_subscriber::filter::LevelFilter; const DEFAULT_WALLET_NAME: &str = "asb-wallet"; #[tokio::main] async fn main() -> Result<()> { + // parse cli arguments let Arguments { testnet, json, - disable_timestamp, config_path, env_config, cmd, } = match parse_args(env::args_os()) { Ok(args) => args, Err(e) => { + // make sure to display the clap error message it exists if let Some(clap_err) = e.downcast_ref::() { - match clap_err.kind { - ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed => { - println!("{}", clap_err.message); - std::process::exit(0); - } - _ => { - bail!(e); - } + if let ErrorKind::HelpDisplayed | ErrorKind::VersionDisplayed = clap_err.kind { + println!("{}", clap_err.message); + std::process::exit(0); } } bail!(e); } }; + // warn if we're not on the latest version 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"); - + // read config from the specified path let config = match read_config(config_path.clone())? { Ok(config) => config, Err(ConfigNotInitialized {}) => { @@ -86,6 +83,12 @@ async fn main() -> Result<()> { } }; + // initialize tracing + let format = if json { Format::Json } else { Format::Raw }; + let log_dir = config.data.dir.join("logs"); + common::tracing_util::init(LevelFilter::DEBUG, format, log_dir).expect("initialize tracing"); + + // check for conflicting env / config values if config.monero.network != env_config.monero_network { bail!(format!( "Expected monero network in config file to be {:?} but was {:?}", @@ -112,6 +115,7 @@ async fn main() -> Result<()> { rendezvous_addrs.sort(); rendezvous_addrs.dedup(); let new_len = rendezvous_addrs.len(); + if new_len < prev_len { tracing::warn!( "`rendezvous_point` config has {} duplicate entries, they are being ignored.", @@ -119,9 +123,12 @@ async fn main() -> Result<()> { ); } + // initialize monero wallet let monero_wallet = init_monero_wallet(&config, env_config).await?; let monero_address = monero_wallet.get_main_address(); tracing::info!(%monero_address, "Monero wallet address"); + + // check monero balance let monero = monero_wallet.get_balance().await?; match (monero.balance, monero.unlocked_balance) { (0, _) => { @@ -144,6 +151,7 @@ async fn main() -> Result<()> { } } + // init bitcoin wallet let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; let bitcoin_balance = bitcoin_wallet.balance().await?; tracing::info!(%bitcoin_balance, "Bitcoin wallet balance"); @@ -314,6 +322,19 @@ async fn main() -> Result<()> { let config_json = serde_json::to_string_pretty(&config)?; println!("{}", config_json); } + Command::Logs { + logs_dir, + swap_id, + redact, + } => { + let dir = logs_dir.unwrap_or(config.data.dir.join("logs")); + + let log_messages = get_logs(dir, swap_id, redact).await?; + + for msg in log_messages { + println!("{msg}"); + } + } Command::WithdrawBtc { amount, address } => { let bitcoin_wallet = init_bitcoin_wallet(&config, &seed, env_config).await?; diff --git a/swap/src/cli.rs b/swap/src/cli.rs index f0faf146..6085eca0 100644 --- a/swap/src/cli.rs +++ b/swap/src/cli.rs @@ -3,7 +3,6 @@ pub mod cancel_and_refund; pub mod command; mod event_loop; mod list_sellers; -pub mod tracing; pub mod transport; pub use behaviour::{Behaviour, OutEvent}; diff --git a/swap/src/cli/command.rs b/swap/src/cli/command.rs index 6c460f82..acce7a50 100644 --- a/swap/src/cli/command.rs +++ b/swap/src/cli/command.rs @@ -105,6 +105,22 @@ where .await?; (context, request) } + CliCommand::Logs { + logs_dir, + redact, + swap_id, + } => { + let request = Request::new(Method::Logs { + logs_dir, + redact, + swap_id, + }); + let context = + Context::build(None, None, None, data, is_testnet, debug, json, None, false) + .await?; + + (context, request) + } CliCommand::Config => { let request = Request::new(Method::Config); @@ -341,6 +357,25 @@ enum CliCommand { }, /// Show a list of past, ongoing and completed swaps History, + /// Output all logging messages that have been issued. + Logs { + #[structopt( + short = "d", + help = "Print the logs from this directory instead of the default one." + )] + logs_dir: Option, + #[structopt( + help = "Redact swap-ids, Bitcoin and Monero addresses.", + long = "redact" + )] + redact: bool, + #[structopt( + long = "swap-id", + help = "Filter for logs concerning this swap.", + long_help = "This checks whether each logging message contains the swap id. Some messages might be skipped when they don't contain the swap id even though they're relevant." + )] + swap_id: Option, + }, #[structopt(about = "Prints the current config")] Config, #[structopt(about = "Allows withdrawing BTC from the internal Bitcoin wallet.")] diff --git a/swap/src/cli/tracing.rs b/swap/src/cli/tracing.rs deleted file mode 100644 index 6b6de60f..00000000 --- a/swap/src/cli/tracing.rs +++ /dev/null @@ -1,112 +0,0 @@ -use anyhow::Result; -use std::path::Path; -use time::format_description::well_known::Rfc3339; -use tracing::subscriber::set_global_default; -use tracing::{Event, Level, Subscriber}; -use tracing_subscriber::fmt::format::{DefaultFields, Format, JsonFields}; -use tracing_subscriber::fmt::time::UtcTime; -use tracing_subscriber::layer::{Context, SubscriberExt}; -use tracing_subscriber::{fmt, EnvFilter, Layer, Registry}; - -pub fn init(debug: bool, json: bool, dir: impl AsRef) -> Result<()> { - let level_filter = EnvFilter::try_new("swap=debug")?; - let registry = Registry::default().with(level_filter); - - let appender = tracing_appender::rolling::never(dir.as_ref(), "swap-all.log"); - - let file_logger = registry.with( - fmt::layer() - .with_ansi(false) - .with_target(false) - .json() - .with_writer(appender), - ); - - if json && debug { - set_global_default(file_logger.with(debug_json_terminal_printer()))?; - } else if json && !debug { - set_global_default(file_logger.with(info_json_terminal_printer()))?; - } else if !json && debug { - set_global_default(file_logger.with(debug_terminal_printer()))?; - } else { - set_global_default(file_logger.with(info_terminal_printer()))?; - } - - tracing::info!("Logging initialized to {}", dir.as_ref().display()); - Ok(()) -} - -pub struct StdErrPrinter { - inner: L, - level: Level, -} - -type StdErrLayer = - fmt::Layer, fn() -> std::io::Stderr>; - -type StdErrJsonLayer = - fmt::Layer, fn() -> std::io::Stderr>; - -fn debug_terminal_printer() -> StdErrPrinter>> { - let is_terminal = atty::is(atty::Stream::Stderr); - StdErrPrinter { - inner: fmt::layer() - .with_ansi(is_terminal) - .with_target(false) - .with_timer(UtcTime::rfc_3339()) - .with_writer(std::io::stderr), - level: Level::DEBUG, - } -} - -fn debug_json_terminal_printer() -> StdErrPrinter>> { - let is_terminal = atty::is(atty::Stream::Stderr); - StdErrPrinter { - inner: fmt::layer() - .with_ansi(is_terminal) - .with_target(false) - .with_timer(UtcTime::rfc_3339()) - .json() - .with_writer(std::io::stderr), - level: Level::DEBUG, - } -} - -fn info_terminal_printer() -> StdErrPrinter> { - let is_terminal = atty::is(atty::Stream::Stderr); - StdErrPrinter { - inner: fmt::layer() - .with_ansi(is_terminal) - .with_target(false) - .with_level(false) - .without_time() - .with_writer(std::io::stderr), - level: Level::INFO, - } -} - -fn info_json_terminal_printer() -> StdErrPrinter> { - let is_terminal = atty::is(atty::Stream::Stderr); - StdErrPrinter { - inner: fmt::layer() - .with_ansi(is_terminal) - .with_target(false) - .with_level(false) - .without_time() - .json() - .with_writer(std::io::stderr), - level: Level::INFO, - } -} - -impl Layer for StdErrPrinter -where - L: 'static + Layer, - S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>, -{ - fn on_event(&self, event: &Event<'_>, ctx: Context<'_, S>) { - if self.level.ge(event.metadata().level()) { - self.inner.on_event(event, ctx); - } - } -} diff --git a/swap/src/common.rs b/swap/src/common.rs deleted file mode 100644 index 98b9b99d..00000000 --- a/swap/src/common.rs +++ /dev/null @@ -1,56 +0,0 @@ -use anyhow::anyhow; - -const LATEST_RELEASE_URL: &str = "https://github.com/comit-network/xmr-btc-swap/releases/latest"; - -#[derive(Clone, Debug, PartialEq, Eq)] -pub enum Version { - Current, - Available, -} - -/// Check the latest release from GitHub API. -pub async fn check_latest_version(current_version: &str) -> anyhow::Result { - let response = reqwest::get(LATEST_RELEASE_URL).await?; - let e = "Failed to get latest release."; - let download_url = response.url(); - let segments = download_url.path_segments().ok_or_else(|| anyhow!(e))?; - let latest_version = segments.last().ok_or_else(|| anyhow!(e))?; - - let result = if is_latest_version(current_version, latest_version) { - Version::Current - } else { - tracing::warn!(%current_version, %latest_version, %download_url, - "You are not on the latest version", - ); - 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.11.0").await.unwrap(); - assert_eq!(result, Version::Available); - - let result = check_latest_version("0.11.1").await.unwrap(); - assert_eq!(result, Version::Current); - } -} diff --git a/swap/src/common/mod.rs b/swap/src/common/mod.rs new file mode 100644 index 00000000..bae1c0f4 --- /dev/null +++ b/swap/src/common/mod.rs @@ -0,0 +1,221 @@ +pub mod tracing_util; + +use std::{collections::HashMap, path::PathBuf}; + +use anyhow::anyhow; +use tokio::{ + fs::{read_dir, File}, + io::{AsyncBufReadExt, BufReader}, +}; +use uuid::Uuid; + +const LATEST_RELEASE_URL: &str = "https://github.com/comit-network/xmr-btc-swap/releases/latest"; + +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Version { + Current, + Available, +} + +/// Check the latest release from GitHub API. +pub async fn check_latest_version(current_version: &str) -> anyhow::Result { + let response = reqwest::get(LATEST_RELEASE_URL).await?; + let e = "Failed to get latest release."; + let download_url = response.url(); + let segments = download_url.path_segments().ok_or_else(|| anyhow!(e))?; + let latest_version = segments.last().ok_or_else(|| anyhow!(e))?; + + let result = if is_latest_version(current_version, latest_version) { + Version::Current + } else { + tracing::warn!(%current_version, %latest_version, %download_url, + "You are not on the latest version", + ); + Version::Available + }; + + Ok(result) +} + +// todo: naive implementation can be improved using semver +fn is_latest_version(current: &str, latest: &str) -> bool { + current == latest +} + +/// helper macro for [`redact`]... eldrich sorcery +/// the macro does in essence the following: +/// 1. create a static regex automaton for the pattern +/// 2. find all matching patterns using regex +/// 3. create a placeholder for each distinct matching pattern +/// 4. add the placeholder to the hashmap +macro_rules! regex_find_placeholders { + ($pattern:expr, $create_placeholder:expr, $replacements:expr, $input:expr) => {{ + // compile the regex pattern + static REGEX: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| { + tracing::debug!("initializing regex"); + regex::Regex::new($pattern).expect("invalid regex pattern") + }); + + // keep count of count patterns to generate distinct placeholders + let mut counter: usize = 0; + + // for every matched address check whether we already found it + // and if we didn't, generate a placeholder for it + for address in REGEX.find_iter($input) { + if !$replacements.contains_key(address.as_str()) { + #[allow(clippy::redundant_closure_call)] + $replacements.insert(address.as_str().to_owned(), $create_placeholder(counter)); + counter += 1; + } + } + }}; +} + +/// Print the logs from the specified logs or from the default location +/// to the specified path or the terminal. +/// +/// If specified, filter by swap id or redact addresses. +pub async fn get_logs( + logs_dir: PathBuf, + swap_id: Option, + redact_addresses: bool, +) -> anyhow::Result> { + tracing::debug!("reading logfiles from {}", logs_dir.display()); + + // get all files in the directory + let mut log_files = read_dir(&logs_dir).await?; + + let mut log_messages = Vec::new(); + // when we redact we need to store the placeholder + let mut placeholders = HashMap::new(); + + // print all lines from every log file. TODO: sort files by date? + while let Some(entry) = log_files.next_entry().await? { + // get the file path + let file_path = entry.path(); + + // filter for .log files + let file_name = file_path + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or(""); + + if !file_name.ends_with(".log") { + continue; + } + + // use BufReader to stay easy on memory and then read line by line + let buf_reader = BufReader::new(File::open(&file_path).await?); + let mut lines = buf_reader.lines(); + + // print each line, redacted if the flag is set + while let Some(line) = lines.next_line().await? { + // if we should filter by swap id, check if the line contains it + if let Some(swap_id) = swap_id { + // we only want lines which contain the swap id + if !line.contains(&swap_id.to_string()) { + continue; + } + } + + // redact if necessary + let line = if redact_addresses { + redact_with(&line, &mut placeholders) + } else { + line + }; + // save redacted message + log_messages.push(line); + } + } + + Ok(log_messages) +} + +/// Redact logs, etc. by replacing Bitcoin and Monero addresses +/// with generic placeholders. +/// +/// # Example +/// ```rust +/// use swap::common::redact; +/// +/// let redacted = redact("a9165a1e-d26d-4b56-bf6d-ca9658825c44"); +/// assert_eq!(redacted, ""); +/// ``` +pub fn redact(input: &str) -> String { + let mut replacements = HashMap::new(); + redact_with(input, &mut replacements) +} + +/// Same as [`redact`] but retrieves palceholders from and stores them +/// in a specified hashmap. +pub fn redact_with(input: &str, replacements: &mut HashMap) -> String { + // TODO: verify regex patterns + const MONERO_ADDR_REGEX: &str = r#"[48][1-9A-HJ-NP-Za-km-z]{94}"#; + const BITCOIN_ADDR_REGEX: &str = r#"\b[13][a-km-zA-HJ-NP-Z1-9]{25,34}\b"#; + // Both XMR and BTC transactions have + // a 64 bit hex id so they aren't distinguishible + const TX_ID_REGEX: &str = r#"\b[a-fA-F0-9]{64}\b"#; + const SWAP_ID_REGEX: &str = + r#"\b[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}\b"#; + + // use the macro to find all addresses and generate placeholders + // has to be a macro in order to create the regex automata only once. + regex_find_placeholders!( + MONERO_ADDR_REGEX, + |count| format!(""), + replacements, + input + ); + regex_find_placeholders!( + BITCOIN_ADDR_REGEX, + |count| format!(""), + replacements, + input + ); + regex_find_placeholders!( + TX_ID_REGEX, + |count| format!(""), + replacements, + input + ); + regex_find_placeholders!( + SWAP_ID_REGEX, + |count| format!(""), + replacements, + input + ); + + // allocate string variable to operate on + let mut redacted = input.to_owned(); + + // Finally we go through the input string and replace each occurance of an + // address we want to redact with the corresponding placeholder + for (address, placeholder) in replacements.iter() { + redacted = redacted.replace(address, placeholder); + } + + redacted +} + +#[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.11.0").await.unwrap(); + assert_eq!(result, Version::Available); + + let result = check_latest_version("0.11.1").await.unwrap(); + assert_eq!(result, Version::Current); + } +} diff --git a/swap/src/common/tracing_util.rs b/swap/src/common/tracing_util.rs new file mode 100644 index 00000000..191c43bf --- /dev/null +++ b/swap/src/common/tracing_util.rs @@ -0,0 +1,64 @@ +use std::path::Path; +use std::str::FromStr; + +use anyhow::Result; +use tracing_subscriber::filter::{Directive, LevelFilter}; +use tracing_subscriber::fmt::time::UtcTime; +use tracing_subscriber::layer::SubscriberExt; +use tracing_subscriber::util::SubscriberInitExt; +use tracing_subscriber::{fmt, EnvFilter, Layer}; + +/// Output formats for logging messages. +pub enum Format { + /// Standard, human readable format. + Raw, + /// JSON, machine readable format. + Json, +} + +/// Initialize tracing and enable logging messages according to these options. +/// Besides printing to `stdout`, this will append to a log file. +/// Said file will contain JSON-formatted logs of all levels, +/// disregarding the arguments to this function. +pub fn init(level_filter: LevelFilter, format: Format, dir: impl AsRef) -> Result<()> { + let env_filter = EnvFilter::from_default_env() + .add_directive(Directive::from_str(&format!("asb={}", &level_filter))?) + .add_directive(Directive::from_str(&format!("swap={}", &level_filter))?); + + // file logger will always write in JSON format and with timestamps + let file_appender = tracing_appender::rolling::never(&dir, "swap-all.log"); + + let file_layer = fmt::layer() + .with_writer(file_appender) + .with_ansi(false) + .with_timer(UtcTime::rfc_3339()) + .with_target(false) + .json() + .with_filter(env_filter); + + // terminal logger + let is_terminal = atty::is(atty::Stream::Stderr); + let terminal_layer = fmt::layer() + .with_writer(std::io::stdout) + .with_ansi(is_terminal) + .with_timer(UtcTime::rfc_3339()) + .with_target(false); + + // combine the layers and start logging, format with json if specified + if let Format::Json = format { + tracing_subscriber::registry() + .with(file_layer) + .with(terminal_layer.json().with_filter(level_filter)) + .init(); + } else { + tracing_subscriber::registry() + .with(file_layer) + .with(terminal_layer.with_filter(level_filter)) + .init(); + } + + // now we can use the tracing macros to log messages + tracing::info!(%level_filter, logs_dir=%dir.as_ref().display(), "Initialized tracing"); + + Ok(()) +} diff --git a/swap/src/database/sqlite.rs b/swap/src/database/sqlite.rs index eb013f66..ce455b6c 100644 --- a/swap/src/database/sqlite.rs +++ b/swap/src/database/sqlite.rs @@ -5,7 +5,7 @@ use anyhow::{anyhow, Context, Result}; use async_trait::async_trait; use libp2p::{Multiaddr, PeerId}; use sqlx::sqlite::{Sqlite, SqliteConnectOptions}; -use sqlx::{Pool, SqlitePool}; +use sqlx::{ConnectOptions, Pool, SqlitePool}; use std::collections::HashMap; use std::path::Path; use std::str::FromStr; @@ -26,7 +26,8 @@ impl SqliteDatabase { let read_only = matches!(access_mode, AccessMode::ReadOnly); let path_str = format!("sqlite:{}", path.as_ref().display()); - let options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only); + let mut options = SqliteConnectOptions::from_str(&path_str)?.read_only(read_only); + options.disable_statement_logging(); let pool = SqlitePool::connect_with(options).await?; let mut sqlite = Self { pool }; diff --git a/swap/src/rpc/methods.rs b/swap/src/rpc/methods.rs index f804e085..dd3d9a62 100644 --- a/swap/src/rpc/methods.rs +++ b/swap/src/rpc/methods.rs @@ -7,7 +7,9 @@ use anyhow::Result; use jsonrpsee::server::RpcModule; use jsonrpsee::types::Params; use libp2p::core::Multiaddr; +use serde::Deserialize; use std::collections::HashMap; +use std::path::PathBuf; use std::str::FromStr; use std::sync::Arc; use uuid::Uuid; @@ -48,8 +50,30 @@ pub fn register_modules(context: Arc) -> Result> execute_request(params_raw, Method::Balance { force_refresh }, &context).await })?; - module.register_async_method("get_history", |params, context| async move { - execute_request(params, Method::History, &context).await + module.register_async_method("get_history", |params_raw, context| async move { + execute_request(params_raw, Method::History, &context).await + })?; + + module.register_async_method("get_logs", |params_raw, context| async move { + #[derive(Debug, Clone, Deserialize)] + struct Params { + swap_id: Option, + logs_dir: Option, + redact: bool, + } + + let params: Params = params_raw.parse()?; + + execute_request( + params_raw, + Method::Logs { + swap_id: params.swap_id, + logs_dir: params.logs_dir, + redact: params.redact, + }, + &context, + ) + .await })?; module.register_async_method("get_raw_states", |params, context| async move { diff --git a/swap/src/seed.rs b/swap/src/seed.rs index aa363905..a17a7964 100644 --- a/swap/src/seed.rs +++ b/swap/src/seed.rs @@ -1,9 +1,9 @@ use crate::fs::ensure_directory_exists; -use ::bitcoin::secp256k1::constants::SECRET_KEY_SIZE; -use ::bitcoin::secp256k1::{self, SecretKey}; use anyhow::{Context, Result}; use bdk::bitcoin::util::bip32::ExtendedPrivKey; use bitcoin::hashes::{sha256, Hash, HashEngine}; +use bitcoin::secp256k1::constants::SECRET_KEY_SIZE; +use bitcoin::secp256k1::{self, SecretKey}; use libp2p::identity; use pem::{encode, Pem}; use rand::prelude::*; From 2faf7561bd279fc152de5ff4df776c308ebc1c4a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Aug 2024 11:57:24 +0000 Subject: [PATCH 368/395] build(deps): bump regex from 1.10.5 to 1.10.6 Bumps [regex](https://github.com/rust-lang/regex) from 1.10.5 to 1.10.6. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.10.5...1.10.6) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0997737..44dfaae1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3458,9 +3458,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick 1.1.3", "memchr", From 29ee6acb95408f140b96e4e103a4dc186c89af5f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Sep 2024 11:31:16 +0000 Subject: [PATCH 369/395] build(deps): bump async-trait from 0.1.81 to 0.1.82 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.81 to 0.1.82. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.81...0.1.82) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44dfaae1..6095ec0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.81" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", From a8a99db73868631ecfa51adfc44a335da1b1e805 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:47:01 +0000 Subject: [PATCH 370/395] build(deps): bump serde_json from 1.0.124 to 1.0.128 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.124 to 1.0.128. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.124...1.0.128) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44dfaae1..9df5e994 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4062,9 +4062,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.124" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66ad62847a56b3dba58cc891acd13884b9c61138d330c0d7b6181713d4fce38d" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", From ff9f3498892964c3f375697e467e94dbe6f99f2f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 11:47:31 +0000 Subject: [PATCH 371/395] build(deps): bump tokio-util from 0.7.11 to 0.7.12 Bumps [tokio-util](https://github.com/tokio-rs/tokio) from 0.7.11 to 0.7.12. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-util-0.7.11...tokio-util-0.7.12) --- updated-dependencies: - dependency-name: tokio-util dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44dfaae1..8801db02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4930,9 +4930,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", From 4114772bb78b14a7dedde9a7931a44d874c91b67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 Sep 2024 12:02:58 +0000 Subject: [PATCH 372/395] build(deps): bump serde from 1.0.208 to 1.0.210 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.208 to 1.0.210. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.210) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44dfaae1..a046bc24 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4022,9 +4022,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -4051,9 +4051,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", From 8022d8b423ad15e1def0b20a154bfff143410128 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:08:00 +0000 Subject: [PATCH 373/395] build(deps): bump anyhow from 1.0.86 to 1.0.88 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.86 to 1.0.88. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.86...1.0.88) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44dfaae1..d5052cb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.86" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" [[package]] name = "arrayref" From fe77b5af95567ed4ef9663a5e37206a48f968198 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:14:20 +0000 Subject: [PATCH 374/395] build(deps): bump anyhow from 1.0.88 to 1.0.89 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.88 to 1.0.89. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.88...1.0.89) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69053647..6bc9e794 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arrayref" From e3f31af88a48b6448739f1a003c4755abbf0e12f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 11:15:38 +0000 Subject: [PATCH 375/395] build(deps): bump once_cell from 1.19.0 to 1.20.0 Bumps [once_cell](https://github.com/matklad/once_cell) from 1.19.0 to 1.20.0. - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.19.0...v1.20.0) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69053647..efc263cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2848,9 +2848,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" [[package]] name = "opaque-debug" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index 8354ec0a..ec496e45 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -37,7 +37,7 @@ jsonrpsee-core = "0.16.2" libp2p = { version = "0.42.2", default-features = false, features = [ "tcp-tokio", "yamux", "mplex", "dns-tokio", "noise", "request-response", "websocket", "ping", "rendezvous", "identify" ] } monero = { version = "0.12", features = [ "serde_support" ] } monero-rpc = { path = "../monero-rpc" } -once_cell = "1.19" +once_cell = "1.20" pem = "3.0" proptest = "1" qrcode = "0.14" From e01986bb5018e39944753d764d41fa7a2e6dfcb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:42:15 +0000 Subject: [PATCH 376/395] build(deps): bump thiserror from 1.0.63 to 1.0.64 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.63 to 1.0.64. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.63...1.0.64) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bc9e794..4c3a59e8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4716,18 +4716,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", From 523adc6d26dad1529d2e0c8c46732ceb9eecf112 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:18:25 +0000 Subject: [PATCH 377/395] build(deps): bump async-trait from 0.1.82 to 0.1.83 Bumps [async-trait](https://github.com/dtolnay/async-trait) from 0.1.82 to 0.1.83. - [Release notes](https://github.com/dtolnay/async-trait/releases) - [Commits](https://github.com/dtolnay/async-trait/compare/0.1.82...0.1.83) --- updated-dependencies: - dependency-name: async-trait dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6bc9e794..169ad3f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -163,9 +163,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", From 6abd951b4631f9bd1a42415a4084af2763f29989 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:36:32 +0000 Subject: [PATCH 378/395] build(deps): bump regex from 1.10.6 to 1.11.0 Bumps [regex](https://github.com/rust-lang/regex) from 1.10.6 to 1.11.0. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.10.6...1.11.0) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 ++++++++++---------- swap/Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10d3cb5a..f4c5efde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3177,7 +3177,7 @@ dependencies = [ "rand 0.8.3", "rand_chacha 0.3.1", "rand_xorshift", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", "rusty-fork", "tempfile", "unarray", @@ -3458,14 +3458,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick 1.1.3", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.2", + "regex-automata 0.4.8", + "regex-syntax 0.8.5", ] [[package]] @@ -3480,13 +3480,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick 1.1.3", "memchr", - "regex-syntax 0.8.2", + "regex-syntax 0.8.5", ] [[package]] @@ -3497,9 +3497,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rend" diff --git a/swap/Cargo.toml b/swap/Cargo.toml index ec496e45..d7d06387 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -43,7 +43,7 @@ proptest = "1" qrcode = "0.14" rand = "0.8" rand_chacha = "0.3" -regex = "1.10" +regex = "1.11" reqwest = { version = "0.12", features = [ "http2", "rustls-tls", "stream", "socks" ], default-features = false } rust_decimal = { version = "1", features = [ "serde-float" ] } rust_decimal_macros = "1" From 12c6974458a0013caa1fd21b2f85ca3a999be34f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 11:37:04 +0000 Subject: [PATCH 379/395] build(deps): bump tempfile from 3.12.0 to 3.13.0 Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.12.0 to 3.13.0. - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.12.0...v3.13.0) --- updated-dependencies: - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10d3cb5a..b673ddce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1224,9 +1224,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "filetime" @@ -2132,9 +2132,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libgit2-sys" @@ -2468,9 +2468,9 @@ checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" @@ -3677,9 +3677,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.4.0", "errno", @@ -4667,9 +4667,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if 1.0.0", "fastrand", From a3ffd35fc0ba0bc0416fb8f29af23e64df90cbf2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:09:42 +0000 Subject: [PATCH 380/395] build(deps): bump reqwest from 0.12.7 to 0.12.8 Bumps [reqwest](https://github.com/seanmonstar/reqwest) from 0.12.7 to 0.12.8. - [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.12.7...v0.12.8) --- updated-dependencies: - dependency-name: reqwest dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10d3cb5a..24dc7bac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3512,9 +3512,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63" +checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "base64 0.22.1", "bytes", From 88e61127363d71e267263020fe7f4dfa994e707f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 11:39:41 +0000 Subject: [PATCH 381/395] build(deps): bump once_cell from 1.20.0 to 1.20.2 Bumps [once_cell](https://github.com/matklad/once_cell) from 1.20.0 to 1.20.2. - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.20.0...v1.20.2) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10d3cb5a..52d43f60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2848,9 +2848,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "opaque-debug" From 851086c5a24eea17147af09737bff88a3559584f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 11:47:11 +0000 Subject: [PATCH 382/395] build(deps): bump actions/checkout from 4.1.7 to 4.2.1 Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.7 to 4.2.1. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4.1.7...v4.2.1) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/create-release.yml | 2 +- .github/workflows/draft-new-release.yml | 2 +- .github/workflows/preview-release.yml | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 662e3a5e..b0fefb92 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -54,7 +54,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout tagged commit - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 with: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3f742fc..732c2491 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: dtolnay/rust-toolchain@master with: @@ -35,7 +35,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: Swatinem/rust-cache@v2.7.3 @@ -49,7 +49,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: Swatinem/rust-cache@v2.7.3 @@ -78,7 +78,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: Swatinem/rust-cache@v2.7.3 @@ -131,7 +131,7 @@ jobs: tool-cache: false - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: Swatinem/rust-cache@v2.7.3 @@ -171,7 +171,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: Swatinem/rust-cache@v2.7.3 @@ -182,7 +182,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: Swatinem/rust-cache@v2.7.3 @@ -193,7 +193,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout sources - uses: actions/checkout@v4.1.7 + uses: actions/checkout@v4.2.1 - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 443c4418..3dcd492d 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -11,7 +11,7 @@ jobs: if: github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.1 - name: Extract version from branch name id: extract-version diff --git a/.github/workflows/draft-new-release.yml b/.github/workflows/draft-new-release.yml index 9b9c849d..bd926d53 100644 --- a/.github/workflows/draft-new-release.yml +++ b/.github/workflows/draft-new-release.yml @@ -12,7 +12,7 @@ jobs: name: "Draft a new release" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.1 with: token: ${{ secrets.BOTTY_GITHUB_TOKEN }} diff --git a/.github/workflows/preview-release.yml b/.github/workflows/preview-release.yml index ccd7e641..b216d283 100644 --- a/.github/workflows/preview-release.yml +++ b/.github/workflows/preview-release.yml @@ -10,7 +10,7 @@ jobs: name: Create preview release runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4.1.7 + - uses: actions/checkout@v4.2.1 - name: Delete 'preview' release uses: larryjoelane/delete-release-action@v1.0.24 From 19710e296d7680d7a3b4f3ef0c7affd84e9d5e7b Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 9 Oct 2024 18:58:27 +0600 Subject: [PATCH 383/395] docs: Add notice to ReadMe about status of maintenance (#1790) docs: Add notice to ReadMe about status of maintenance and reference community fork at UnstoppableSwap/core --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 35adc5f0..1c0226b2 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,10 @@ Currently, swaps are only offered in one direction with the `swap` CLI on the bu We are working on implementing a protocol where XMR moves first, but are currently blocked by advances on Monero itself. You can read [this blogpost](https://comit.network/blog/2021/07/02/transaction-presigning) for more information. +## Maintenance + +This repository is currently maintained by community volunteers. While it remains safe to use, the original developers (@comit-network) have stopped contributing. For a more actively maintained version that includes a GUI, please check out this community fork: https://github.com/UnstoppableSwap/core + ## Quick Start 1. Download the [latest `swap` binary release](https://github.com/comit-network/xmr-btc-swap/releases/latest) for your operating system. From 3d4bc971a2874ac1676aaa7ede4abeb0a4dbbac9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:07:29 +0000 Subject: [PATCH 384/395] build(deps): bump Swatinem/rust-cache from 2.7.3 to 2.7.5 Bumps [Swatinem/rust-cache](https://github.com/swatinem/rust-cache) from 2.7.3 to 2.7.5. - [Release notes](https://github.com/swatinem/rust-cache/releases) - [Changelog](https://github.com/Swatinem/rust-cache/blob/master/CHANGELOG.md) - [Commits](https://github.com/swatinem/rust-cache/compare/v2.7.3...v2.7.5) --- updated-dependencies: - dependency-name: Swatinem/rust-cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- .github/workflows/build-release-binaries.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/build-release-binaries.yml b/.github/workflows/build-release-binaries.yml index 662e3a5e..6b8cae14 100644 --- a/.github/workflows/build-release-binaries.yml +++ b/.github/workflows/build-release-binaries.yml @@ -59,7 +59,7 @@ jobs: ref: ${{ github.event.release.target_commitish }} token: ${{ secrets.BOTTY_GITHUB_TOKEN }} - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - uses: dtolnay/rust-toolchain@master with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b3f742fc..3cc27914 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: toolchain: "1.74" components: clippy,rustfmt - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Check formatting uses: dprint/check@v2.2 @@ -37,7 +37,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.7 - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Build swap run: cargo build --bin swap @@ -51,7 +51,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.7 - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Install sqlx-cli run: cargo install --locked --version 0.6.3 sqlx-cli @@ -80,7 +80,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.7 - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - uses: dtolnay/rust-toolchain@master with: @@ -133,7 +133,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.7 - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Build tests run: cargo build --tests --workspace --all-features @@ -173,7 +173,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.7 - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Run test ${{ matrix.test_name }} run: cargo test --package swap --all-features --test ${{ matrix.test_name }} -- --nocapture @@ -184,7 +184,7 @@ jobs: - name: Checkout sources uses: actions/checkout@v4.1.7 - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Run RPC server tests run: cargo test --package swap --all-features --test rpc -- --nocapture @@ -197,7 +197,7 @@ jobs: - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2.7.3 + - uses: Swatinem/rust-cache@v2.7.5 - name: Run cargo check on stable rust run: cargo check --all-targets From 61c7afb35886dba5a9ce46f1aa6defcf367e4a7a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Oct 2024 11:32:11 +0000 Subject: [PATCH 385/395] build(deps): bump futures from 0.3.30 to 0.3.31 Bumps [futures](https://github.com/rust-lang/futures-rs) from 0.3.30 to 0.3.31. - [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.30...0.3.31) --- updated-dependencies: - dependency-name: futures dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0821b73f..17eb7fc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -169,7 +169,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -1310,9 +1310,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1325,9 +1325,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1335,15 +1335,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1364,19 +1364,19 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -1392,15 +1392,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-timer" @@ -1410,9 +1410,9 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -3156,9 +3156,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.74" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -4057,7 +4057,7 @@ checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -4137,7 +4137,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -4526,7 +4526,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -4635,9 +4635,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.46" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -4731,7 +4731,7 @@ checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -4837,7 +4837,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -5063,7 +5063,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] @@ -5470,7 +5470,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", "wasm-bindgen-shared", ] @@ -5504,7 +5504,7 @@ checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5915,7 +5915,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.46", + "syn 2.0.79", ] [[package]] From ec567ccba1eb295ca11aa43aa8debfc51dcfbbec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:55:59 +0000 Subject: [PATCH 386/395] build(deps): bump uuid from 1.10.0 to 1.11.0 Bumps [uuid](https://github.com/uuid-rs/uuid) from 1.10.0 to 1.11.0. - [Release notes](https://github.com/uuid-rs/uuid/releases) - [Commits](https://github.com/uuid-rs/uuid/compare/1.10.0...1.11.0) --- updated-dependencies: - dependency-name: uuid dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- swap/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0821b73f..608c302d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5361,9 +5361,9 @@ checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7" [[package]] name = "uuid" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" dependencies = [ "getrandom 0.2.11", "serde", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index d7d06387..d38d2c81 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -69,7 +69,7 @@ tracing-appender = "0.2" tracing-futures = { version = "0.2", features = [ "std-future", "futures-03" ] } tracing-subscriber = { version = "0.3", default-features = false, features = [ "fmt", "ansi", "env-filter", "time", "tracing-log", "json" ] } url = { version = "2", features = [ "serde" ] } -uuid = { version = "1.10", features = [ "serde", "v4" ] } +uuid = { version = "1.11", features = [ "serde", "v4" ] } void = "1" [target.'cfg(not(windows))'.dependencies] From d521815e913c3c50775009b5b93d260452d3c647 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:58:25 +0000 Subject: [PATCH 387/395] build(deps): bump hyper from 1.4.1 to 1.5.0 Bumps [hyper](https://github.com/hyperium/hyper) from 1.4.1 to 1.5.0. - [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/v1.4.1...v1.5.0) --- updated-dependencies: - dependency-name: hyper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 14 +++++++------- swap/Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0821b73f..37acc516 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1772,9 +1772,9 @@ dependencies = [ [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ "bytes", "futures-channel", @@ -1799,7 +1799,7 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.0.0", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "rustls 0.23.10", "rustls-pki-types", @@ -1820,7 +1820,7 @@ dependencies = [ "futures-util", "http 1.0.0", "http-body 1.0.0", - "hyper 1.4.1", + "hyper 1.5.0", "pin-project-lite 0.2.13", "socket2 0.5.5", "tokio", @@ -2614,7 +2614,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-util", "log", "rand 0.8.3", @@ -3524,7 +3524,7 @@ dependencies = [ "http 1.0.0", "http-body 1.0.0", "http-body-util", - "hyper 1.4.1", + "hyper 1.5.0", "hyper-rustls", "hyper-util", "ipnet", @@ -4569,7 +4569,7 @@ dependencies = [ "futures", "get-port", "hex", - "hyper 1.4.1", + "hyper 1.5.0", "itertools 0.13.0", "jsonrpsee", "jsonrpsee-core", diff --git a/swap/Cargo.toml b/swap/Cargo.toml index d7d06387..6bbdf8ea 100644 --- a/swap/Cargo.toml +++ b/swap/Cargo.toml @@ -81,7 +81,7 @@ zip = "0.5" [dev-dependencies] bitcoin-harness = { git = "https://github.com/delta1/bitcoin-harness-rs.git", rev = "80cc8d05db2610d8531011be505b7bee2b5cdf9f" } get-port = "3" -hyper = "1.4" +hyper = "1.5" jsonrpsee = { version = "0.16.2", features = [ "ws-client" ] } mockito = "1.5" monero-harness = { path = "../monero-harness" } From de7c8aec0a79a21280d53ebf41c271cdb2d50fec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:44:43 +0000 Subject: [PATCH 388/395] build(deps): bump anyhow from 1.0.89 to 1.0.90 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.89 to 1.0.90. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.89...1.0.90) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0821b73f..109f8dfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" [[package]] name = "arrayref" From 7b1b5ec3a5323049d1165683d6bf98d647b215f3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:45:16 +0000 Subject: [PATCH 389/395] build(deps): bump serde_json from 1.0.128 to 1.0.132 Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.128 to 1.0.132. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/1.0.128...1.0.132) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0821b73f..c020f4e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4062,9 +4062,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", From 02a3711cc939462f75b6f1246a048ddf75d70c85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:45:51 +0000 Subject: [PATCH 390/395] build(deps): bump anyhow from 1.0.90 to 1.0.91 Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.90 to 1.0.91. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.90...1.0.91) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7e33323..5749a8e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "arrayref" From fac5df93faf0a1ed3c255b570a06941a46f80677 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 11:46:56 +0000 Subject: [PATCH 391/395] build(deps): bump thiserror from 1.0.64 to 1.0.65 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.64 to 1.0.65. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.64...1.0.65) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7e33323..b5d26f34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4716,18 +4716,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", From 44fafc792e7427e8ad3f7cb8061ee0095171e811 Mon Sep 17 00:00:00 2001 From: Binarybaron Date: Mon, 11 Nov 2024 16:02:55 +0100 Subject: [PATCH 392/395] feat(asb): Add Dockerfile --- Dockerfile | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..05e5d64c --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +# This Dockerfile builds the asb binary + +FROM rust:1.79-slim AS builder + +WORKDIR /build + +RUN apt-get update +RUN apt-get install -y git clang cmake libsnappy-dev + +COPY . . + +WORKDIR /build/swap + +RUN cargo build --release --bin=asb + +FROM debian:bookworm-slim + +WORKDIR /data + +COPY --from=builder /build/target/release/asb /bin/asb + +ENTRYPOINT ["asb"] From a2cc3591b158e6695f318f4b816068cd5a9ad7be Mon Sep 17 00:00:00 2001 From: Binarybaron Date: Mon, 11 Nov 2024 16:03:15 +0100 Subject: [PATCH 393/395] fix: do not panic if electrum server does not support fee estimation --- swap/src/bitcoin/wallet.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/swap/src/bitcoin/wallet.rs b/swap/src/bitcoin/wallet.rs index 9748d740..55a05b73 100644 --- a/swap/src/bitcoin/wallet.rs +++ b/swap/src/bitcoin/wallet.rs @@ -468,6 +468,7 @@ where ) -> Result { let client = self.client.lock().await; let fee_rate = client.estimate_feerate(self.target_block)?; + let min_relay_fee = client.min_relay_fee()?; estimate_fee(weight, transfer_amount, fee_rate, min_relay_fee) @@ -871,6 +872,11 @@ impl EstimateFeeRate for Client { // https://github.com/romanz/electrs/blob/f9cf5386d1b5de6769ee271df5eef324aa9491bc/src/rpc.rs#L213 // Returned estimated fees are per BTC/kb. let fee_per_byte = self.electrum.estimate_fee(target_block)?; + + if fee_per_byte < 0.0 { + bail!("Fee per byte returned by electrum server is negative: {}. This may indicate that fee estimation is not supported by this server", fee_per_byte); + } + // we do not expect fees being that high. #[allow(clippy::cast_possible_truncation)] Ok(FeeRate::from_btc_per_kvb(fee_per_byte as f32)) From 81b89d63c28562476d05c5a39c952bfbe2d7c995 Mon Sep 17 00:00:00 2001 From: binarybaron <86064887+binarybaron@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:24:06 +0100 Subject: [PATCH 394/395] docs: Add notice about breaking backwards compatability --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1c0226b2..80612c4f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ You can read [this blogpost](https://comit.network/blog/2021/07/02/transaction-p ## Maintenance -This repository is currently maintained by community volunteers. While it remains safe to use, the original developers (@comit-network) have stopped contributing. For a more actively maintained version that includes a GUI, please check out this community fork: https://github.com/UnstoppableSwap/core +**This repository is unmaintained**. The original developers (@comit-network) have moved on to other projects. Community volunteers are continuing development at [UnstoppableSwap/core](https://github.com/UnstoppableSwap/core), which includes a graphical user interface. Please note that the fork has introduced network-level breaking changes, making it incompatible with peers running this repository - you will not be able to initiate swaps with them. ## Quick Start From 4db069b02c79a108ffa1d752f40cfea47deddb45 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Mon, 26 May 2025 11:14:21 +0200 Subject: [PATCH 395/395] Update README.md --- README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 80612c4f..72130de7 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,8 @@ +> [!CAUTION] +> # THIS REPO IS UNMAINTAINED
PLEASE USE [UNSTOPPABLESWAP]([url](https://github.com/UnstoppableSwap/core)) INSTEAD + +**This repository is unmaintained**. The original developers (@comit-network) have moved on to other projects. Community volunteers are continuing development at [UnstoppableSwap/core](https://github.com/UnstoppableSwap/core), which includes a graphical user interface. Please note that the fork has introduced network-level breaking changes, making it incompatible with peers running this repository - you will not be able to initiate swaps with them. + # XMR to BTC Atomic Swap This repository hosts an MVP for atomically swapping BTC to XMR. @@ -9,10 +14,6 @@ Currently, swaps are only offered in one direction with the `swap` CLI on the bu We are working on implementing a protocol where XMR moves first, but are currently blocked by advances on Monero itself. You can read [this blogpost](https://comit.network/blog/2021/07/02/transaction-presigning) for more information. -## Maintenance - -**This repository is unmaintained**. The original developers (@comit-network) have moved on to other projects. Community volunteers are continuing development at [UnstoppableSwap/core](https://github.com/UnstoppableSwap/core), which includes a graphical user interface. Please note that the fork has introduced network-level breaking changes, making it incompatible with peers running this repository - you will not be able to initiate swaps with them. - ## Quick Start 1. Download the [latest `swap` binary release](https://github.com/comit-network/xmr-btc-swap/releases/latest) for your operating system.