From 9346cb7baf17f56eb8dd8ace5edd98d0c9583159 Mon Sep 17 00:00:00 2001 From: Byron Hambly Date: Tue, 10 Jan 2023 13:38:19 +0200 Subject: [PATCH 1/2] 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 2/2] 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,