From d54882fb366c330f436fcf4abb37ca7297805826 Mon Sep 17 00:00:00 2001 From: Mykhailo Kremniov Date: Mon, 27 Apr 2026 14:15:04 +0300 Subject: [PATCH 1/3] Update rust edition to 2024 --- Cargo.lock | 50 ++++++++++- Cargo.toml | 6 +- api-server/scanner-daemon/Cargo.toml | 1 + api-server/scanner-daemon/src/main.rs | 8 +- api-server/storage-test-suite/Cargo.toml | 1 + .../storage-test-suite/tests/in_memory.rs | 5 +- .../storage-test-suite/tests/postgres.rs | 5 +- api-server/web-server/Cargo.toml | 1 + api-server/web-server/src/main.rs | 6 +- chainstate/db-dumper/Cargo.toml | 2 +- chainstate/db-dumper/src/dumper/main.rs | 8 +- chainstate/launcher/src/lib.rs | 12 +-- chainstate/src/detail/ban_score.rs | 2 +- .../src/transaction_verifier/mod.rs | 6 +- common/src/chain/block/consensus_data.rs | 2 +- .../transaction/signature/tests/utils.rs | 6 +- crypto/src/key/extended.rs | 2 +- crypto/src/key/mod.rs | 8 +- crypto/src/vrf/mod.rs | 2 +- crypto/src/vrf/transcript/mod.rs | 4 +- crypto/src/vrf/transcript/no_rng.rs | 2 +- crypto/src/vrf/transcript/with_rng.rs | 2 +- dns-server/Cargo.toml | 1 + dns-server/src/main.rs | 4 +- logging/Cargo.toml | 5 ++ logging/src/lib.rs | 87 ++++++++++++++----- logging/src/log_style.rs | 71 --------------- logging/src/utils.rs | 7 +- logging/tests/env_tests.rs | 81 +++++++++++++++++ mempool/src/pool/tx_pool/mod.rs | 2 +- mempool/src/pool/tx_pool/reorg.rs | 2 +- node-daemon/Cargo.toml | 1 + node-daemon/src/main.rs | 8 +- node-gui/Cargo.toml | 1 + node-gui/backend/src/lib.rs | 23 ++--- node-gui/src/main.rs | 4 +- node-lib/src/node_daemon_runner.rs | 6 +- node-lib/src/runner.rs | 9 +- rustfmt.toml | 1 + storage/backend-test-suite/src/property.rs | 34 ++++---- storage/lmdb/src/lib.rs | 2 +- supply-chain/config.toml | 18 +++- supply-chain/imports.lock | 9 -- test-utils/src/env.rs | 45 ++++++++++ test-utils/src/lib.rs | 6 +- test/Cargo.toml | 1 + test/src/bin/test_rpc_wallet.rs | 8 +- test/src/bin/test_wallet.rs | 8 +- test/src/bin/test_wallet_address_generator.rs | 8 +- utils/Cargo.toml | 3 + utils/src/env_utils.rs | 41 --------- utils/src/rust_backtrace.rs | 34 ++++++-- utils/tests/env_tests.rs | 56 ++++++++++++ utils/tests/log_error.rs | 5 +- wallet/wallet-address-generator/Cargo.toml | 1 + wallet/wallet-address-generator/src/main.rs | 8 +- wallet/wallet-cli/Cargo.toml | 1 + wallet/wallet-cli/src/main.rs | 8 +- wallet/wallet-rpc-daemon/Cargo.toml | 1 + wallet/wallet-rpc-daemon/src/main.rs | 8 +- 60 files changed, 463 insertions(+), 296 deletions(-) create mode 100644 logging/tests/env_tests.rs create mode 100644 test-utils/src/env.rs create mode 100644 utils/tests/env_tests.rs diff --git a/Cargo.lock b/Cargo.lock index d2225122cd..665532a12c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,6 +234,7 @@ dependencies = [ "build_utils", "clap", "common", + "ctor", "logging", "node-comm", "node-lib", @@ -284,6 +285,7 @@ dependencies = [ "chrono", "common", "crypto", + "ctor", "futures", "libtest-mimic", "logging", @@ -364,6 +366,7 @@ dependencies = [ "clap", "common", "crypto", + "ctor", "hex", "logging", "mempool", @@ -2195,12 +2198,13 @@ dependencies = [ [[package]] name = "ctor" -version = "0.2.9" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" +checksum = "83cf0d42651b16c6dfe68685716d18480d18a9c39c62d76e8cf3eb6ed5d8bcbf" dependencies = [ - "quote", - "syn 2.0.114", + "ctor-proc-macro", + "dtor", + "link-section", ] [[package]] @@ -2209,6 +2213,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b29fccfdaeb0f9bd90da5759b1d0eaa2f6cfcfe90960124cfc83141ed4e111fd" +[[package]] +name = "ctor-proc-macro" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a949c44fcacbbbb7ada007dc7acb34603dd97cd47de5d054f2b6493ecebb483" + [[package]] name = "ctr" version = "0.9.2" @@ -2612,6 +2622,7 @@ dependencies = [ "clap", "common", "crypto", + "ctor", "directories", "futures", "hickory-client", @@ -2693,6 +2704,21 @@ dependencies = [ "linux-raw-sys 0.6.5", ] +[[package]] +name = "dtor" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf234dd1594d6dd434a8fb8cada51ddbbc593e40e4a01556a0b31c62da2775b" +dependencies = [ + "dtor-proc-macro", +] + +[[package]] +name = "dtor-proc-macro" +version = "0.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2647271c92754afcb174e758003cfd1cbf1e43e5a7853d7b1813e63e19e39a73" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -4745,6 +4771,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "link-section" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b685d66585d646efe09fec763d796c291049c8b6bf84e04954bffc8748341f0d" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -4826,6 +4858,8 @@ version = "1.3.0" dependencies = [ "console-subscriber", "log", + "serial_test", + "test-utils", "thiserror 1.0.69", "tracing", "tracing-subscriber", @@ -5133,6 +5167,7 @@ name = "mintlayer-test" version = "1.3.0" dependencies = [ "clap", + "ctor", "libtest-mimic", "logging", "node-lib", @@ -5388,6 +5423,7 @@ version = "1.3.0" dependencies = [ "anyhow", "assert_cmd", + "ctor", "expect-test", "logging", "node-lib", @@ -5404,6 +5440,7 @@ dependencies = [ "chainstate", "chrono", "common", + "ctor", "futures", "heck 0.5.0", "iced", @@ -9681,6 +9718,7 @@ dependencies = [ "clap", "criterion", "crypto", + "ctor", "directories", "fix-hidden-lifetime-bug", "fixed-hash", @@ -9695,6 +9733,7 @@ dependencies = [ "randomness", "regex", "rstest", + "serial_test", "serialization", "slave-pool", "static_assertions", @@ -9855,6 +9894,7 @@ dependencies = [ "clap", "common", "crypto", + "ctor", "thiserror 1.0.69", "utils", "wallet", @@ -9883,6 +9923,7 @@ name = "wallet-cli" version = "1.3.0" dependencies = [ "clap", + "ctor", "tokio", "utils", "wallet-cli-lib", @@ -10074,6 +10115,7 @@ version = "1.3.0" dependencies = [ "clap", "common", + "ctor", "expect-test", "logging", "rpc", diff --git a/Cargo.toml b/Cargo.toml index 06c0356c75..3c96aa3660 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/mintlayer/mintlayer-core" readme = "README.md" license = "MIT" version = "1.3.0" -edition = "2021" +edition = "2024" [workspace] members = [ @@ -126,7 +126,7 @@ storage = { path = "storage" } utxo = { path = "utxo" } [workspace.package] -edition = "2021" +edition = "2024" rust-version = "1.88" version = "1.3.0" license = "MIT" @@ -156,7 +156,7 @@ console-subscriber = "0.5" criterion = "0.5" crossterm = "0.28" csv = "1.3" -ctor = "0.2" +ctor = "0.10" derive_more = { version = "1.0", features = ["full"] } directories = "5.0" humantime = "2.1" diff --git a/api-server/scanner-daemon/Cargo.toml b/api-server/scanner-daemon/Cargo.toml index 091bd349f9..f0de772cad 100644 --- a/api-server/scanner-daemon/Cargo.toml +++ b/api-server/scanner-daemon/Cargo.toml @@ -17,6 +17,7 @@ utils = { path = "../../utils" } utils-networking = { path = "../../utils/networking" } clap = { workspace = true, features = ["derive"] } +ctor.workspace = true thiserror.workspace = true tokio = { workspace = true, features = ["full"] } diff --git a/api-server/scanner-daemon/src/main.rs b/api-server/scanner-daemon/src/main.rs index 70f598e8f8..4107d9b4b8 100644 --- a/api-server/scanner-daemon/src/main.rs +++ b/api-server/scanner-daemon/src/main.rs @@ -140,14 +140,10 @@ pub enum ApiServerScannerError { PostgresConnectionError(ApiServerStorageError), } +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() -> Result<(), ApiServerScannerError> { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - let args = ApiServerScannerArgs::parse(); logging::init_logging(); diff --git a/api-server/storage-test-suite/Cargo.toml b/api-server/storage-test-suite/Cargo.toml index 33935a6442..54a267aa04 100644 --- a/api-server/storage-test-suite/Cargo.toml +++ b/api-server/storage-test-suite/Cargo.toml @@ -19,6 +19,7 @@ serialization = { path = "../../serialization" } async-trait.workspace = true chrono.workspace = true +ctor.workspace = true futures = { workspace = true, default-features = false } libtest-mimic.workspace = true proptest.workspace = true diff --git a/api-server/storage-test-suite/tests/in_memory.rs b/api-server/storage-test-suite/tests/in_memory.rs index dbf8f4bc70..203b40ff96 100644 --- a/api-server/storage-test-suite/tests/in_memory.rs +++ b/api-server/storage-test-suite/tests/in_memory.rs @@ -20,7 +20,6 @@ use api_server_common::storage::{ storage_api::ApiServerStorage, }; use common::chain::{config::create_unit_test_config, ChainConfig}; -use utils::rust_backtrace; #[must_use] #[allow(clippy::unused_async)] @@ -28,9 +27,9 @@ async fn make_in_memory_storage(chain_config: Arc) -> impl ApiServe TransactionalApiServerInMemoryStorage::new(&chain_config) } -fn main() { - rust_backtrace::enable(); +utils::enable_rust_backtrace!(); +fn main() { let storage_maker = || make_in_memory_storage(Arc::new(create_unit_test_config())); let result = api_server_backend_test_suite::run(storage_maker); diff --git a/api-server/storage-test-suite/tests/postgres.rs b/api-server/storage-test-suite/tests/postgres.rs index f23aeed599..917eaad6f5 100644 --- a/api-server/storage-test-suite/tests/postgres.rs +++ b/api-server/storage-test-suite/tests/postgres.rs @@ -23,7 +23,6 @@ use api_server_common::storage::{ }; use common::chain::{config::create_unit_test_config, ChainConfig}; use containers::with_container::ApiServerStorageWithContainer; -use utils::rust_backtrace; #[must_use] async fn make_postgres_storage(chain_config: Arc) -> impl ApiServerStorage { @@ -56,9 +55,9 @@ async fn make_postgres_storage(chain_config: Arc) -> impl ApiServer ApiServerStorageWithContainer::new(storage, podman) } -fn main() { - rust_backtrace::enable(); +utils::enable_rust_backtrace!(); +fn main() { // Only run the test if the env var is defined if std::env::var("ML_CONTAINERIZED_TESTS").is_err() { eprintln!("Warning: Skipping Postgres containerized tests"); diff --git a/api-server/web-server/Cargo.toml b/api-server/web-server/Cargo.toml index d67a614ccd..f46c6cecef 100644 --- a/api-server/web-server/Cargo.toml +++ b/api-server/web-server/Cargo.toml @@ -20,6 +20,7 @@ mempool = { path = "../../mempool" } axum.workspace = true async-trait.workspace = true +ctor.workspace = true clap = { workspace = true, features = ["derive"] } hex.workspace = true serde = { workspace = true, features = ["derive"] } diff --git a/api-server/web-server/src/main.rs b/api-server/web-server/src/main.rs index 89bca9ec83..4a8d848121 100644 --- a/api-server/web-server/src/main.rs +++ b/api-server/web-server/src/main.rs @@ -36,12 +36,10 @@ use utils::{cookie::COOKIE_FILENAME, default_data_dir::default_data_dir_for_chai use crate::error::ApiServerWebServerInitError; +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() -> Result<(), ApiServerWebServerInitError> { - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - logging::init_logging(); let args = ApiServerWebServerConfig::parse(); diff --git a/chainstate/db-dumper/Cargo.toml b/chainstate/db-dumper/Cargo.toml index 9c0d305df2..b77fa4ff7e 100644 --- a/chainstate/db-dumper/Cargo.toml +++ b/chainstate/db-dumper/Cargo.toml @@ -21,6 +21,7 @@ utils = { path = "../../utils" } anyhow.workspace = true clap.workspace = true +ctor.workspace = true itertools.workspace = true strum.workspace = true thiserror.workspace = true @@ -30,7 +31,6 @@ crypto = { path = "../../crypto" } mocks = { path = "../../mocks" } test-utils = { path = "../../test-utils" } -ctor.workspace = true hex.workspace = true rstest.workspace = true diff --git a/chainstate/db-dumper/src/dumper/main.rs b/chainstate/db-dumper/src/dumper/main.rs index 2a6b547f92..2d1e8a9c53 100644 --- a/chainstate/db-dumper/src/dumper/main.rs +++ b/chainstate/db-dumper/src/dumper/main.rs @@ -45,13 +45,9 @@ fn run() -> anyhow::Result<()> { Ok(()) } -fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } +utils::enable_rust_backtrace!(); +fn main() { init_logging(); run().unwrap_or_else(|err| { diff --git a/chainstate/launcher/src/lib.rs b/chainstate/launcher/src/lib.rs index f7f291a17e..0cf05224c7 100644 --- a/chainstate/launcher/src/lib.rs +++ b/chainstate/launcher/src/lib.rs @@ -111,7 +111,7 @@ fn make_chainstate_impl( fn create_lmdb_storage( datadir: &std::path::Path, chain_config: &ChainConfig, -) -> Result { +) -> Result, Error> { let lmdb_resize_callback = MapResizeCallback::new(Box::new(|resize_info| { logging::log::info!("Lmdb resize happened: {:?}", resize_info) })); @@ -126,14 +126,16 @@ fn create_lmdb_storage( create_storage(backend, chain_config) } -fn create_inmemory_storage(chain_config: &ChainConfig) -> Result { +fn create_inmemory_storage( + chain_config: &ChainConfig, +) -> Result, Error> { create_storage(storage_inmemory::InMemory::new(), chain_config) } -fn create_storage( - storage_backend: impl BlockchainStorageBackend + 'static, +fn create_storage( + storage_backend: B, chain_config: &ChainConfig, -) -> Result { +) -> Result, Error> { let storage = chainstate_storage::Store::new(storage_backend, chain_config) .map_err(|e| Error::FailedToInitializeChainstate(e.into()))?; diff --git a/chainstate/src/detail/ban_score.rs b/chainstate/src/detail/ban_score.rs index 2506b664e5..56af0be08a 100644 --- a/chainstate/src/detail/ban_score.rs +++ b/chainstate/src/detail/ban_score.rs @@ -403,7 +403,7 @@ impl BanScore for ConsensusVerificationError { ConsensusVerificationError::ConsensusTypeMismatch(_) => 100, ConsensusVerificationError::PoWError(err) => err.ban_score(), ConsensusVerificationError::UnsupportedConsensusType => 100, - ConsensusVerificationError::PoSError(ref err) => err.ban_score(), + ConsensusVerificationError::PoSError(err) => err.ban_score(), } } } diff --git a/chainstate/tx-verifier/src/transaction_verifier/mod.rs b/chainstate/tx-verifier/src/transaction_verifier/mod.rs index 60f8ad2f68..8cf1f08a9a 100644 --- a/chainstate/tx-verifier/src/transaction_verifier/mod.rs +++ b/chainstate/tx-verifier/src/transaction_verifier/mod.rs @@ -355,7 +355,7 @@ where .inputs() .iter() .filter_map(|input| match input { - TxInput::Utxo(ref outpoint) => { + TxInput::Utxo(outpoint) => { self.spend_input_from_utxo(tx_source.into(), outpoint).transpose() } TxInput::Account(outpoint) => { @@ -553,7 +553,7 @@ where }); Some(res) } - AccountCommand::UnmintTokens(ref token_id) => { + AccountCommand::UnmintTokens(token_id) => { let res = self .spend_input_from_account(*nonce, account_op.into()) .and_then(|_| { @@ -704,7 +704,7 @@ where | TxOutput::LockThenTransfer(output_value, _, _) | TxOutput::Htlc(output_value, _) => match output_value { OutputValue::Coin(_) | OutputValue::TokenV0(_) => Ok(()), - OutputValue::TokenV1(ref token_id, _) => check_not_frozen(*token_id), + OutputValue::TokenV1(token_id, _) => check_not_frozen(*token_id), }, TxOutput::CreateOrder(data) => { [data.ask(), data.give()].iter().try_for_each(|v| match v { diff --git a/common/src/chain/block/consensus_data.rs b/common/src/chain/block/consensus_data.rs index b184587e5b..0e56637ff0 100644 --- a/common/src/chain/block/consensus_data.rs +++ b/common/src/chain/block/consensus_data.rs @@ -45,7 +45,7 @@ impl ConsensusData { ) -> Option { match self { ConsensusData::None => Some(1u64.into()), - ConsensusData::PoW(ref pow_data) => pow_data.get_block_proof(), + ConsensusData::PoW(pow_data) => pow_data.get_block_proof(), ConsensusData::PoS(_) => { let timestamp_diff = this_block_timestamp .as_int_seconds() diff --git a/common/src/chain/transaction/signature/tests/utils.rs b/common/src/chain/transaction/signature/tests/utils.rs index f5e755d673..2c64a319f4 100644 --- a/common/src/chain/transaction/signature/tests/utils.rs +++ b/common/src/chain/transaction/signature/tests/utils.rs @@ -442,10 +442,10 @@ pub fn sig_hash_types() -> impl Iterator + Clone { } /// Returns an iterator over all possible destinations. -pub fn destinations( - rng: &mut impl Rng, +pub fn destinations( + rng: &mut R, public_key: PublicKey, -) -> impl Iterator { +) -> impl Iterator + use { // TODO: find a way to write this such that it loops over all possible arms instead of doing this manually [ Destination::PublicKeyHash(PublicKeyHash::from(&public_key)), diff --git a/crypto/src/key/extended.rs b/crypto/src/key/extended.rs index 3ca4e6e9da..d9e5f0baf2 100644 --- a/crypto/src/key/extended.rs +++ b/crypto/src/key/extended.rs @@ -114,7 +114,7 @@ impl ExtendedPublicKey { pub fn from_private_key(private_key: &ExtendedPrivateKey) -> ExtendedPublicKey { match private_key.get_internal_key() { - ExtendedPrivateKeyHolder::Secp256k1Schnorr(ref k) => { + ExtendedPrivateKeyHolder::Secp256k1Schnorr(k) => { let secp_key = Secp256k1ExtendedPublicKey::from_private_key(k); ExtendedPublicKey { pub_key: ExtendedPublicKeyHolder::Secp256k1Schnorr(secp_key), diff --git a/crypto/src/key/mod.rs b/crypto/src/key/mod.rs index 75090f223f..c0ef4fc508 100644 --- a/crypto/src/key/mod.rs +++ b/crypto/src/key/mod.rs @@ -108,7 +108,7 @@ impl PrivateKey { aux_data_provider: &mut AuxP, ) -> Result { let signature = match &self.key { - PrivateKeyHolder::Secp256k1Schnorr(ref k) => { + PrivateKeyHolder::Secp256k1Schnorr(k) => { Secp256k1Schnorr(k.sign_message(msg, aux_data_provider)) } }; @@ -127,9 +127,7 @@ impl From for PrivateKey { impl PublicKey { pub fn from_private_key(private_key: &PrivateKey) -> Self { match private_key.get_internal_key() { - PrivateKeyHolder::Secp256k1Schnorr(ref k) => { - Secp256k1PublicKey::from_private_key(k).into() - } + PrivateKeyHolder::Secp256k1Schnorr(k) => Secp256k1PublicKey::from_private_key(k).into(), } } @@ -142,7 +140,7 @@ impl PublicKey { #[must_use] pub fn verify_message(&self, signature: &Signature, msg: &[u8]) -> bool { match &self.pub_key { - PublicKeyHolder::Secp256k1Schnorr(ref k) => match signature { + PublicKeyHolder::Secp256k1Schnorr(k) => match signature { Secp256k1Schnorr(s) => k.verify_message(s, msg), }, } diff --git a/crypto/src/vrf/mod.rs b/crypto/src/vrf/mod.rs index 3ab0219230..fd4ee98f2f 100644 --- a/crypto/src/vrf/mod.rs +++ b/crypto/src/vrf/mod.rs @@ -174,7 +174,7 @@ impl VRFPrivateKey { impl VRFPublicKey { pub fn from_private_key(private_key: &VRFPrivateKey) -> Self { match private_key.internal_key() { - VRFPrivateKeyHolder::Schnorrkel(ref k) => VRFPublicKey { + VRFPrivateKeyHolder::Schnorrkel(k) => VRFPublicKey { pub_key: VRFPublicKeyHolder::Schnorrkel(SchnorrkelPublicKey::from_private_key(k)), }, } diff --git a/crypto/src/vrf/transcript/mod.rs b/crypto/src/vrf/transcript/mod.rs index b961122c7a..230d500259 100644 --- a/crypto/src/vrf/transcript/mod.rs +++ b/crypto/src/vrf/transcript/mod.rs @@ -44,7 +44,7 @@ mod tests { let mut generator = assembled_transcript.take().build_rng().finalize(&mut Rng08Adapter(&mut rng)); - (0..100).map(|_| generator.gen::()).collect::>() + (0..100).map(|_| generator.r#gen::()).collect::>() }; let with_rng_value = { @@ -58,7 +58,7 @@ mod tests { let mut generator = assembled_transcript.take().build_rng().finalize(&mut Rng08Adapter(&mut rng2)); - (0..100).map(|_| generator.gen::()).collect::>() + (0..100).map(|_| generator.r#gen::()).collect::>() }; assert_eq!(with_rng_value, no_rng_value); diff --git a/crypto/src/vrf/transcript/no_rng.rs b/crypto/src/vrf/transcript/no_rng.rs index ffe941c8ad..fc6dacf828 100644 --- a/crypto/src/vrf/transcript/no_rng.rs +++ b/crypto/src/vrf/transcript/no_rng.rs @@ -117,7 +117,7 @@ mod tests { .finalize(&mut Rng08Adapter(&mut ChaChaRng::from_seed([0u8; 32]))); for _ in 0..100 { - assert_eq!(g1.gen::(), g2.gen::()); + assert_eq!(g1.r#gen::(), g2.r#gen::()); } } } diff --git a/crypto/src/vrf/transcript/with_rng.rs b/crypto/src/vrf/transcript/with_rng.rs index e53e0e3c03..823108fc26 100644 --- a/crypto/src/vrf/transcript/with_rng.rs +++ b/crypto/src/vrf/transcript/with_rng.rs @@ -120,7 +120,7 @@ mod tests { .finalize(&mut Rng08Adapter(&mut ChaChaRng::from_seed([0u8; 32]))); for _ in 0..100 { - assert_eq!(g1.gen::(), g2.gen::()); + assert_eq!(g1.r#gen::(), g2.r#gen::()); } } diff --git a/dns-server/Cargo.toml b/dns-server/Cargo.toml index 44e135a0fa..1fd38803bb 100644 --- a/dns-server/Cargo.toml +++ b/dns-server/Cargo.toml @@ -21,6 +21,7 @@ utils-networking = { path = "../utils/networking" } anyhow.workspace = true async-trait.workspace = true clap = { workspace = true, features = ["derive"] } +ctor.workspace = true directories.workspace = true futures = { workspace = true } itertools.workspace = true diff --git a/dns-server/src/main.rs b/dns-server/src/main.rs index 215a576ea2..b87af0e3ba 100644 --- a/dns-server/src/main.rs +++ b/dns-server/src/main.rs @@ -186,10 +186,10 @@ async fn run(options: DnsServerRunOptions) -> anyhow::Result { } } +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() { - utils::rust_backtrace::enable(); - logging::init_logging(); let run_options = DnsServerRunOptions::parse(); diff --git a/logging/Cargo.toml b/logging/Cargo.toml index 6c378baacf..136b517ce8 100644 --- a/logging/Cargo.toml +++ b/logging/Cargo.toml @@ -12,5 +12,10 @@ thiserror.workspace = true tracing.workspace = true tracing-subscriber.workspace = true +[dev-dependencies] +serial_test.workspace = true + +test-utils = { path = "../test-utils" } + [features] tokio-console = ["dep:console-subscriber"] diff --git a/logging/src/lib.rs b/logging/src/lib.rs index 8cda313c02..52122e7bb2 100644 --- a/logging/src/lib.rs +++ b/logging/src/lib.rs @@ -17,6 +17,7 @@ mod log_style; mod utils; use std::{ + borrow::Cow, io::{IsTerminal, Write}, sync::Mutex, }; @@ -26,18 +27,44 @@ use tracing_subscriber::{ fmt::MakeWriter, layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer, Registry, }; -use log_style::{get_log_style_from_env, LogStyleParseError}; - pub use log; +pub use log_style::{get_log_style_from_env, LogStyleParseError}; pub use log_style::{LogStyle, TextColoring}; -pub use utils::{get_from_env, GetFromEnvError, ValueOrEnvVar}; +pub use utils::{get_from_env, GetFromEnvError}; + +/// Default value for `RUST_LOG` used by the "simple" log initialization functions. +/// +/// I.e. `init_logging_generic` doesn't use this. +pub const SIMPLE_INIT_DEFAULT_FILTER: &str = "info"; -/// Send log output to the terminal. +/// This defines the default filter directive to use when the specified one turned out to be +/// empty or invalid. +/// +/// Note that `EnvFilter::from_env` would use ERROR as the default, but we want to be consistent +/// with `SIMPLE_INIT_DEFAULT_FILTER`. +fn default_filter_directive() -> tracing_subscriber::filter::Directive { + LevelFilter::INFO.into() +} + +/// Send log output to the terminal, taking the log filter from the "RUST_LOG" env var and using +/// `SIMPLE_INIT_DEFAULT_FILTER` if it's not set. pub fn init_logging() { - init_logging_generic(default_writer_settings(), no_writer_settings()); + init_logging_with_default_filter(SIMPLE_INIT_DEFAULT_FILTER.to_owned()); +} + +/// A more generic version of `init_logging` that allows to specify a custom default value for +/// `RUST_LOG`. +pub fn init_logging_with_default_filter(default_filter: String) { + init_logging_generic( + default_writer_settings(default_filter), + no_writer_settings(), + ); } -/// Send log output to the specified [Write] instance, log lines are separated by '\n' +/// Send log output to the specified [Write] instance, log lines are separated by '\n'. +/// +/// The log filter is taken from the "RUST_LOG" env var, using `SIMPLE_INIT_DEFAULT_FILTER` as +/// the default value. /// /// `is_terminal` will determine text coloring in the `TextColoring::Auto` case. pub fn init_logging_to(file: impl Write + Send + 'static, is_terminal: bool) { @@ -45,14 +72,17 @@ pub fn init_logging_to(file: impl Write + Send + 'static, is_terminal: bool) { WriterSettings { make_writer: write_to_make_writer(file), is_terminal, - filter: ValueOrEnvVar::EnvVar("RUST_LOG".into()), + filter: ValueOrEnvVarWithDefault::EnvVar { + var_name: "RUST_LOG".into(), + default_value: SIMPLE_INIT_DEFAULT_FILTER.to_owned(), + }, log_style: ValueOrEnvVar::EnvVar(LOG_STYLE_ENV_VAR_NAME.into()), }, no_writer_settings(), ); } -pub fn default_writer_settings() -> WriterSettings std::io::Stderr> { +pub fn default_writer_settings(default_filter: String) -> WriterSettings std::io::Stderr> { WriterSettings { // Write to stderr to mimic the behavior of env_logger. make_writer: std::io::stderr, @@ -60,7 +90,10 @@ pub fn default_writer_settings() -> WriterSettings std::io::Stderr> { // to a file etc). is_terminal: std::io::stderr().is_terminal(), // Use the default env var for filtering. - filter: ValueOrEnvVar::EnvVar("RUST_LOG".into()), + filter: ValueOrEnvVarWithDefault::EnvVar { + var_name: "RUST_LOG".into(), + default_value: default_filter, + }, // Use the default env var for style. log_style: ValueOrEnvVar::EnvVar(LOG_STYLE_ENV_VAR_NAME.into()), } @@ -78,10 +111,23 @@ static DEFAULT_LOG_STYLE: LogStyle = LogStyle::Text(TextColoring::Auto); static INITIALIZE_LOGGER_ONCE_FLAG: std::sync::Once = std::sync::Once::new(); +pub enum ValueOrEnvVar { + Value(T), + EnvVar(Cow<'static, str>), +} + +pub enum ValueOrEnvVarWithDefault { + Value(T1), + EnvVar { + var_name: Cow<'static, str>, + default_value: T2, + }, +} + pub struct WriterSettings { pub make_writer: MW, pub is_terminal: bool, - pub filter: ValueOrEnvVar, + pub filter: ValueOrEnvVarWithDefault, pub log_style: ValueOrEnvVar, } @@ -208,10 +254,10 @@ fn get_log_style_impl( } fn make_env_filter( - filter_str: ValueOrEnvVar, + filter: ValueOrEnvVarWithDefault, errors: &mut Vec, ) -> EnvFilter { - let result_opt = match make_env_filter_impl(filter_str) { + let result_opt = match make_env_filter_impl(filter) { Ok(filter) => Some(filter), Err(err) => { errors.push(err); @@ -226,12 +272,16 @@ fn make_env_filter( }) } -fn make_env_filter_impl(filter: ValueOrEnvVar) -> Result { +fn make_env_filter_impl( + filter: ValueOrEnvVarWithDefault, +) -> Result { let filter_directives = match filter { - ValueOrEnvVar::Value(val) => Some(val), - ValueOrEnvVar::EnvVar(var_name) => get_from_env(var_name.as_ref())?, + ValueOrEnvVarWithDefault::Value(val) => val, + ValueOrEnvVarWithDefault::EnvVar { + var_name, + default_value, + } => get_from_env(var_name.as_ref())?.unwrap_or(default_value), }; - let filter_directives = filter_directives.unwrap_or_default(); // Note: here we try to catch errors to later print them to the log with the "error" severity, so that // typos in the filter string can be noticed. But not all errors will be caught. E.g. if you set the filter @@ -250,11 +300,6 @@ fn make_env_filter_impl(filter: ValueOrEnvVar) -> Result tracing_subscriber::filter::Directive { - LevelFilter::ERROR.into() -} - #[allow(clippy::enum_variant_names)] #[derive(Debug, thiserror::Error)] enum InternalLogInitError { diff --git a/logging/src/log_style.rs b/logging/src/log_style.rs index 25d32f393d..1867fbde42 100644 --- a/logging/src/log_style.rs +++ b/logging/src/log_style.rs @@ -54,74 +54,3 @@ pub enum LogStyleParseError { #[error("Env var error: {0:?}")] GetFromEnvError(#[from] GetFromEnvError), } - -#[cfg(test)] -mod tests { - use super::*; - - // Make the name verbose so that it doesn't conflict with env variables used by other - // tests, if any. - static TEST_ENV_VAR: &str = "LOG_STYLE_TEST_ENV_VAR"; - - // Note: all checks are inside one test; if there were multiple tests, they would have - // to use different names for the test env var, so that they wouldn't conflict if the tests - // were run in parallel. - #[test] - fn parse_env_var() { - // Basic tests - { - std::env::set_var(TEST_ENV_VAR, "text"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Auto)))); - - std::env::set_var(TEST_ENV_VAR, "text-colored"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::On)))); - - std::env::set_var(TEST_ENV_VAR, "text-uncolored"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Off)))); - - std::env::set_var(TEST_ENV_VAR, "json"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Json))); - } - - // Case-insensitivity tests - { - std::env::set_var(TEST_ENV_VAR, "tEXt"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Auto)))); - - std::env::set_var(TEST_ENV_VAR, "tEXt-coLoRed"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::On)))); - - std::env::set_var(TEST_ENV_VAR, "tEXt-uncoLoRed"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Off)))); - - std::env::set_var(TEST_ENV_VAR, "jSoN"); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(Some(LogStyle::Json))); - } - - // Bad value test - { - let str = "foo"; - std::env::set_var(TEST_ENV_VAR, str); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!( - result, - Err(LogStyleParseError::UnrecognizedFormat(str.to_owned())) - ); - } - - // Missing value test - { - std::env::remove_var(TEST_ENV_VAR); - let result = get_log_style_from_env(TEST_ENV_VAR); - assert_eq!(result, Ok(None)); - } - } -} diff --git a/logging/src/utils.rs b/logging/src/utils.rs index ab6b3ec892..a630c59d10 100644 --- a/logging/src/utils.rs +++ b/logging/src/utils.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{borrow::Cow, ffi::OsString}; +use std::ffi::OsString; #[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)] pub enum GetFromEnvError { @@ -31,8 +31,3 @@ pub fn get_from_env(var_name: &str) -> Result, GetFromEnvError> { }), } } - -pub enum ValueOrEnvVar { - Value(T), - EnvVar(Cow<'static, str>), -} diff --git a/logging/tests/env_tests.rs b/logging/tests/env_tests.rs new file mode 100644 index 0000000000..47bab399a9 --- /dev/null +++ b/logging/tests/env_tests.rs @@ -0,0 +1,81 @@ +// Copyright (c) 2021-2026 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use logging::{get_log_style_from_env, LogStyle, LogStyleParseError, TextColoring}; +use test_utils::{remove_env_var, set_env_var}; + +static TEST_ENV_VAR: &str = "LOG_STYLE_TEST_ENV_VAR"; + +// Note: `serial_test::serial` is redundant while there is only one test here, but it'll be +// required if more tests are added in the future, so we have it "just in case". +#[test] +#[serial_test::serial] +fn parse_log_style_env_var() { + // Basic tests + { + set_env_var(TEST_ENV_VAR, "text"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Auto)))); + + set_env_var(TEST_ENV_VAR, "text-colored"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::On)))); + + set_env_var(TEST_ENV_VAR, "text-uncolored"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Off)))); + + set_env_var(TEST_ENV_VAR, "json"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Json))); + } + + // Case-insensitivity tests + { + set_env_var(TEST_ENV_VAR, "tEXt"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Auto)))); + + set_env_var(TEST_ENV_VAR, "tEXt-coLoRed"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::On)))); + + set_env_var(TEST_ENV_VAR, "tEXt-uncoLoRed"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Text(TextColoring::Off)))); + + set_env_var(TEST_ENV_VAR, "jSoN"); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(Some(LogStyle::Json))); + } + + // Bad value test + { + let str = "foo"; + set_env_var(TEST_ENV_VAR, str); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!( + result, + Err(LogStyleParseError::UnrecognizedFormat(str.to_owned())) + ); + } + + // Missing value test + { + remove_env_var(TEST_ENV_VAR); + let result = get_log_style_from_env(TEST_ENV_VAR); + assert_eq!(result, Ok(None)); + } +} diff --git a/mempool/src/pool/tx_pool/mod.rs b/mempool/src/pool/tx_pool/mod.rs index 6e3c830640..15bb652e8e 100644 --- a/mempool/src/pool/tx_pool/mod.rs +++ b/mempool/src/pool/tx_pool/mod.rs @@ -144,7 +144,7 @@ impl TxPool { } // Reset the mempool state, returning the list of transactions previously stored in mempool - pub fn reset(&mut self) -> impl Iterator { + pub fn reset(&mut self) -> impl Iterator + use { // Discard the old tx verifier and replace it with a fresh one self.tx_verifier = tx_verifier::create( self.chain_config.shallow_clone(), diff --git a/mempool/src/pool/tx_pool/reorg.rs b/mempool/src/pool/tx_pool/reorg.rs index d026b695c8..9aa93f4345 100644 --- a/mempool/src/pool/tx_pool/reorg.rs +++ b/mempool/src/pool/tx_pool/reorg.rs @@ -111,7 +111,7 @@ impl ReorgData { fn fetch_disconnected_txs( tx_pool: &TxPool, new_tip: Id, -) -> Result, ReorgError> { +) -> Result + use, ReorgError> { let old_tip = tx_pool .tx_verifier .get_best_block_for_utxos() diff --git a/node-daemon/Cargo.toml b/node-daemon/Cargo.toml index 18ea3f98ce..a2263ce3cb 100644 --- a/node-daemon/Cargo.toml +++ b/node-daemon/Cargo.toml @@ -11,6 +11,7 @@ node-lib = { path = "../node-lib/" } utils = { path = "../utils" } anyhow.workspace = true +ctor.workspace = true tokio = { workspace = true, default-features = false } [dev-dependencies] diff --git a/node-daemon/src/main.rs b/node-daemon/src/main.rs index 4c3b739c7c..0023b3b00a 100644 --- a/node-daemon/src/main.rs +++ b/node-daemon/src/main.rs @@ -15,14 +15,10 @@ use node_lib::run_node_daemon; +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - let exit_code = run_node_daemon().await.unwrap_or_else(|err| { eprintln!("Mintlayer node launch failed: {err:?}"); std::process::exit(1) diff --git a/node-gui/Cargo.toml b/node-gui/Cargo.toml index 4a38932d7f..dfbe0fab38 100644 --- a/node-gui/Cargo.toml +++ b/node-gui/Cargo.toml @@ -25,6 +25,7 @@ wallet-storage = { path = "../wallet/storage", default-features = false } anyhow.workspace = true chrono.workspace = true +ctor.workspace = true futures.workspace = true heck.workspace = true iced = { workspace = true, features = ["canvas", "debug", "tokio", "lazy"] } diff --git a/node-gui/backend/src/lib.rs b/node-gui/backend/src/lib.rs index 4b9ca1a377..ea3a0f8f48 100644 --- a/node-gui/backend/src/lib.rs +++ b/node-gui/backend/src/lib.rs @@ -106,22 +106,17 @@ pub enum NodeInitializationOutcome { DataDirCleanedUp, } +// Note: wgpu_hal=error is included to prevent it from spamming warnings "Unrecognized present +// mode 1000361000" on Windows (which are emitted e.g. when resizing the window). +// Note that this seems to have been fixed in https://github.com/gfx-rs/wgpu/pull/7850 and the fix +// has already been released, however our dependencies still use a pretty old version of wgpu. +const DEFAULT_LOG_FILTER: &str = + "info,wgpu_core=error,wgpu_hal=error,hyper=error,jsonrpsee-server=error"; + pub async fn node_initialize( opts: node_lib::OptionsWithResolvedCommand, mode: WalletMode, ) -> anyhow::Result { - if std::env::var("RUST_LOG").is_err() { - // Note: wgpu_hal=error is included to prevent it from spamming warnings - // "Unrecognized present mode 1000361000" on Windows. Note that this seems - // to have been fixed in https://github.com/gfx-rs/wgpu/pull/7850 and - // the fix has already been released, however our dependencies still use - // a pretty old version of wgpu. - std::env::set_var( - "RUST_LOG", - "info,wgpu_core=error,wgpu_hal=error,hyper=error,jsonrpsee-server=error", - ); - } - let opts = { let mut opts = opts; let run_opts = opts.command.run_options_mut(); @@ -141,7 +136,7 @@ pub async fn node_initialize( let (chain_config, chain_info) = match mode { WalletMode::Hot => { - let setup_result = node_lib::setup(opts).await?; + let setup_result = node_lib::setup(opts, DEFAULT_LOG_FILTER).await?; let node = match setup_result { node_lib::NodeSetupResult::RunNode(node) => node, node_lib::NodeSetupResult::Bootstrap(_, _) => { @@ -227,7 +222,7 @@ fn spawn_cold_backend( wallet_updated_tx: UnboundedSender, wallet_updated_rx: UnboundedReceiver, ) -> anyhow::Result<(Arc, ChainInfo)> { - logging::init_logging(); + logging::init_logging_with_default_filter(DEFAULT_LOG_FILTER.to_owned()); let chain_config = Arc::new(handle_options_in_cold_wallet_mode(options)?); let chain_info = ChainInfo { diff --git a/node-gui/src/main.rs b/node-gui/src/main.rs index 2eba0ce2a2..4fbd2310c9 100644 --- a/node-gui/src/main.rs +++ b/node-gui/src/main.rs @@ -50,9 +50,9 @@ const TEST_NETWORK_TOOLTIP: &str = "The 'Testnet' is the network with coins that const INITIAL_MAIN_WINDOW_WIDTH: f32 = 1024.0; const INITIAL_MAIN_WINDOW_HEIGHT: f32 = 768.0; -pub fn main() -> iced::Result { - utils::rust_backtrace::enable(); +utils::enable_rust_backtrace!(); +pub fn main() -> iced::Result { let initial_opts = node_lib::Options::from_args(std::env::args_os(), NodeType::NodeGui); iced::application(title, update, view) diff --git a/node-lib/src/node_daemon_runner.rs b/node-lib/src/node_daemon_runner.rs index f07ad36979..d8c651ff5a 100644 --- a/node-lib/src/node_daemon_runner.rs +++ b/node-lib/src/node_daemon_runner.rs @@ -27,7 +27,11 @@ pub struct ExitCode(pub i32); pub async fn run_node_daemon() -> anyhow::Result { let opts = Options::from_args(std::env::args_os(), NodeType::NodeDaemon); - let setup_result = setup(opts.with_resolved_command()).await?; + let setup_result = setup( + opts.with_resolved_command(), + logging::SIMPLE_INIT_DEFAULT_FILTER, + ) + .await?; match setup_result { NodeSetupResult::RunNode(node) => { node.main().await; diff --git a/node-lib/src/runner.rs b/node-lib/src/runner.rs index 13e93189ee..039ba3880e 100644 --- a/node-lib/src/runner.rs +++ b/node-lib/src/runner.rs @@ -240,7 +240,10 @@ async fn initialize( } /// Processes options and potentially runs the node. -pub async fn setup(options: OptionsWithResolvedCommand) -> Result { +pub async fn setup( + options: OptionsWithResolvedCommand, + default_log_filter: &str, +) -> Result { let chain_config = options.command.create_chain_config()?; // Prepare data dir @@ -255,7 +258,7 @@ pub async fn setup(options: OptionsWithResolvedCommand) -> Result Result>(backend_factory: Arc using_proptest( file!(), backend_factory, - (gen::key(100), gen::any::(), gen::any::()) + (gens::key(100), gens::any::(), gens::any::()) .prop_filter("not equal", |(_, a, b)| a != b), |backend, (key, val0, val1)| { let mut store = backend.open(desc(1)).expect("db open to succeed"); @@ -122,7 +122,7 @@ fn add_and_delete>(backend_factory: Arc) { using_proptest( file!(), backend_factory, - gen::entries(NUM_DBS, 0usize..20), + gens::entries(NUM_DBS, 0usize..20), |backend, entries| { let mut store = backend.open(desc(NUM_DBS)).expect("db open to succeed"); @@ -165,8 +165,8 @@ fn last_write_wins>(backend_factory: Arc) { file!(), backend_factory, ( - gen::key(1000), - gen::prop::collection::vec(gen::any::(), 0..100), + gens::key(1000), + gens::prop::collection::vec(gens::any::(), 0..100), ), |backend, (key, vals)| { let mut store = backend.open(desc(1)).expect("db open to succeed"); @@ -194,9 +194,9 @@ fn add_and_delete_some>(backend_factory: Arc file!(), backend_factory, ( - gen::entries(NUM_DBS, 0usize..20), - gen::entries(NUM_DBS, 0usize..20), - proptest::collection::vec((gen::map_id(NUM_DBS), gen::big_key()), 0usize..10), + gens::entries(NUM_DBS, 0usize..20), + gens::entries(NUM_DBS, 0usize..20), + proptest::collection::vec((gens::map_id(NUM_DBS), gens::big_key()), 0usize..10), ), |backend, (entries1, entries2, extra_keys)| { let mut store = backend.open(desc(NUM_DBS)).expect("db open to succeed"); @@ -249,9 +249,9 @@ fn add_modify_abort_modify_commit>(backend_fact file!(), backend_factory, ( - gen::actions(100, 0..20), - gen::actions(100, 0..20), - gen::actions(100, 0..20), + gens::actions(100, 0..20), + gens::actions(100, 0..20), + gens::actions(100, 0..20), ), |backend, (to_prepopulate, to_abort, to_commit)| { let model = Model::from_actions(to_prepopulate.clone()); @@ -293,7 +293,7 @@ fn add_modify_abort_replay_commit>(backend_fact using_proptest( file!(), backend_factory, - (gen::actions(100, 0..20), gen::actions(100, 0..20)), + (gens::actions(100, 0..20), gens::actions(100, 0..20)), |backend, (initial, actions)| { let mut store = backend.open(desc(1)).expect("db open to succeed"); @@ -324,7 +324,7 @@ fn db_writes_do_not_interfere>(backend_factory: using_proptest( file!(), backend_factory, - (gen::actions(100, 0..20), gen::actions(100, 0..20)), + (gens::actions(100, 0..20), gens::actions(100, 0..20)), |backend, (actions0, actions1)| { let mut store = backend.open(desc(2)).expect("db open to succeed"); @@ -350,8 +350,8 @@ fn empty_after_abort>(backend_factory: Arc) file!(), backend_factory, ( - gen::actions(100, 0..20), - gen::prop::collection::vec(gen::key(100), 0..20), + gens::actions(100, 0..20), + gens::prop::collection::vec(gens::key(100), 0..20), ), |backend, (actions, keys)| { let mut store = backend.open(desc(5)).expect("db open to succeed"); @@ -380,7 +380,7 @@ fn prefix_iteration>(backend_factory: Arc) { using_proptest( file!(), backend_factory, - (gen::actions(100, 0..20), gen::actions(100, 0..20)), + (gens::actions(100, 0..20), gens::actions(100, 0..20)), |backend, (actions_a, actions_b)| { // Add prefixes to action keys fn add_prefix(pfx: u8, mut key: Data) -> Data { @@ -440,7 +440,7 @@ fn post_commit_consistency>(backend_factory: Ar using_proptest( file!(), backend_factory, - gen::actions(100, 0..50), + gens::actions(100, 0..50), |backend, actions| { // Open storage let mut store = backend.open(desc(1)).expect("db open to succeed"); diff --git a/storage/lmdb/src/lib.rs b/storage/lmdb/src/lib.rs index 56b08a5497..9156f82f5f 100644 --- a/storage/lmdb/src/lib.rs +++ b/storage/lmdb/src/lib.rs @@ -74,7 +74,7 @@ impl DbTx<'_, Tx> { &self, map_id: DbMapId, key: &[u8], - ) -> storage_core::Result>> { + ) -> storage_core::Result + use<'_, Tx>>> { let cursor = self .tx .open_ro_cursor(self.backend.dbs[map_id]) diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 6cb1496f13..22b84c3937 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -269,13 +269,17 @@ version = "0.5.0" criteria = "safe-to-run" [[exemptions.ctor]] -version = "0.2.9" +version = "0.10.1" criteria = "safe-to-deploy" [[exemptions.ctor-lite]] version = "0.1.1" criteria = "safe-to-deploy" +[[exemptions.ctor-proc-macro]] +version = "0.0.13" +criteria = "safe-to-deploy" + [[exemptions.cursor-icon]] version = "1.2.0" criteria = "safe-to-deploy" @@ -416,6 +420,14 @@ criteria = "safe-to-deploy" version = "0.8.0" criteria = "safe-to-deploy" +[[exemptions.dtor]] +version = "0.8.1" +criteria = "safe-to-deploy" + +[[exemptions.dtor-proc-macro]] +version = "0.0.13" +criteria = "safe-to-deploy" + [[exemptions.encdec]] version = "0.10.0" criteria = "safe-to-deploy" @@ -740,6 +752,10 @@ criteria = "safe-to-deploy" version = "0.7.0" criteria = "safe-to-deploy" +[[exemptions.link-section]] +version = "0.2.1" +criteria = "safe-to-deploy" + [[exemptions.lru]] version = "0.12.5" criteria = "safe-to-deploy" diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index cdd5b3c6fb..6b7d20c899 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -3168,15 +3168,6 @@ Crate is sound, albeit leaky, and not actively malicious. Probably not the best crate to use in practice but it's suitable for testing dependencies. """ -[[audits.bytecode-alliance.audits.unarray]] -who = "Alex Crichton " -criteria = "safe-to-deploy" -version = "0.1.4" -notes = """ -Crate is sound, albeit leaky, and not actively malicious. Probably not the best -crate to use in practice but it's suitable for testing dependencies. -""" - [[audits.bytecode-alliance.audits.vcpkg]] who = "Pat Hickey " criteria = "safe-to-deploy" diff --git a/test-utils/src/env.rs b/test-utils/src/env.rs new file mode 100644 index 0000000000..3cb2abee2b --- /dev/null +++ b/test-utils/src/env.rs @@ -0,0 +1,45 @@ +// Copyright (c) 2026 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Wrappers for `std::env::set_var` and `remove_var` to avoid writing `unsafe` every time. +//! +//! Note: `std::env::set_var` and `remove_var` are unsafe since Rust 2024, but they've never been +//! actually safe to use on *nix systems in a multithreaded context because reading/writing +//! env vars (even different ones) is not thread-safe (the `std::env` functions do use a lock +//! internally, but an env var can potentially be read by any function from `libc`, which may +//! potentially be called by any function from the std lib). In production code we avoid this problem +//! by only modifying env vars before `main` is entered (at which point there is only one thread), +//! but in tests we sometimes need to do this in a test's body directly (e.g. to check that the +//! tested code reads the environment properly) and tests are run in parallel by default. +//! So, careless use of these functions may lead to flaky tests. To avoid it: +//! 1) Serialize the tests, by putting e.g. `#[serial_test::serial(env)]` on all environment-modifying +//! tests. But note that you'll also have to put `#[serial_test::parallel(env)]` on all other tests +//! belonging to the same test executable, to ensure that they can only run in parallel with +//! themselves, but not with those marked as "serial(env)". +//! 2) Consider putting environment-modifying tests into a separate integration test. + +use std::ffi::OsStr; + +pub fn set_env_var, V: AsRef>(key: K, value: V) { + unsafe { + std::env::set_var(key, value); + } +} + +pub fn remove_env_var>(key: K) { + unsafe { + std::env::remove_var(key); + } +} diff --git a/test-utils/src/lib.rs b/test-utils/src/lib.rs index 2eba055919..21282b1277 100644 --- a/test-utils/src/lib.rs +++ b/test-utils/src/lib.rs @@ -14,6 +14,7 @@ // limitations under the License. mod basic_test_time_getter; +mod env; pub mod mock_time_getter; pub mod random; pub mod test_dir; @@ -28,6 +29,7 @@ use itertools::Itertools; use randomness::{distributions::uniform::SampleRange, Rng, RngExt as _}; pub use basic_test_time_getter::BasicTestTimeGetter; +pub use env::{remove_env_var, set_env_var}; pub trait UnwrapInfallible { type Output; @@ -119,13 +121,13 @@ pub fn gen_text_with_non_ascii(c: u8, rng: &mut impl Rng, max_len: usize) -> Vec token_ticker } -pub fn gen_different_value(orig_val: &T, mut gen: G) -> T +pub fn gen_different_value(orig_val: &T, mut generator: G) -> T where T: Eq, G: FnMut() -> T, { for _ in 0..1000 { - let val = gen(); + let val = generator(); if val != *orig_val { return val; diff --git a/test/Cargo.toml b/test/Cargo.toml index a0ca34f8f2..8abd2d16b6 100644 --- a/test/Cargo.toml +++ b/test/Cargo.toml @@ -18,6 +18,7 @@ wallet-cli-lib = { path = "../wallet/wallet-cli-lib", default-features = false } wallet-rpc-lib = { path = "../wallet/wallet-rpc-lib", default-features = false } clap = { workspace = true, features = ["derive"] } +ctor.workspace = true tokio = { workspace = true, features = ['full'] } [dev-dependencies] diff --git a/test/src/bin/test_rpc_wallet.rs b/test/src/bin/test_rpc_wallet.rs index ef061f69c0..fe15addb6e 100644 --- a/test/src/bin/test_rpc_wallet.rs +++ b/test/src/bin/test_rpc_wallet.rs @@ -25,14 +25,10 @@ async fn run() -> Result<(), Box> { Ok(()) } +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - logging::init_logging(); let run_result = run().await; diff --git a/test/src/bin/test_wallet.rs b/test/src/bin/test_wallet.rs index 721e97e06b..55e00c5ebe 100644 --- a/test/src/bin/test_wallet.rs +++ b/test/src/bin/test_wallet.rs @@ -19,14 +19,10 @@ use wallet_cli_lib::{ console::{StdioInputConsole, StdioOutputConsole}, }; +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - let args = WalletCliArgs::parse(); wallet_cli_lib::run(StdioInputConsole, StdioOutputConsole, args, None) .await diff --git a/test/src/bin/test_wallet_address_generator.rs b/test/src/bin/test_wallet_address_generator.rs index 782f2286e8..3a6a882bc5 100644 --- a/test/src/bin/test_wallet_address_generator.rs +++ b/test/src/bin/test_wallet_address_generator.rs @@ -16,13 +16,9 @@ use clap::Parser; use wallet_address_generator_lib::CliArgs; -fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } +utils::enable_rust_backtrace!(); +fn main() { let args = CliArgs::parse(); wallet_address_generator_lib::run(args).unwrap_or_else(|err| { eprintln!("{}", err); diff --git a/utils/Cargo.toml b/utils/Cargo.toml index 2173f3ab73..07bf8959a6 100644 --- a/utils/Cargo.toml +++ b/utils/Cargo.toml @@ -14,6 +14,7 @@ serialization = { path = "../serialization" } anyhow.workspace = true clap = { workspace = true, features = ["env", "string", "derive"] } +ctor.workspace = true directories.workspace = true fix-hidden-lifetime-bug.workspace = true fixed-hash.workspace = true @@ -29,6 +30,8 @@ tracing.workspace = true zeroize.workspace = true [dev-dependencies] +serial_test.workspace = true + test-utils = { path = "../test-utils" } criterion.workspace = true diff --git a/utils/src/env_utils.rs b/utils/src/env_utils.rs index c40ba3ec04..25c957cab4 100644 --- a/utils/src/env_utils.rs +++ b/utils/src/env_utils.rs @@ -45,44 +45,3 @@ pub enum Error { #[error("Error obtaining env var value: {0}")] GetFromEnvError(#[from] logging::GetFromEnvError), } - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_bool_from_env() { - let var_name = "TEST_BOOL_FROM_ENV_TEST_VAR_NAME"; - - let result = bool_from_env(var_name); - assert_eq!(result, Ok(None)); - - let true_vals = ["1", "yes", "yEs", "true", "TruE"]; - let false_vals = ["0", "no", "nO", "false", "fALSE"]; - let bad_vals = ["2", "noo", "yess"]; - - for val in true_vals { - std::env::set_var(var_name, val); - let result = bool_from_env(var_name); - assert_eq!(result, Ok(Some(true))); - } - - for val in false_vals { - std::env::set_var(var_name, val); - let result = bool_from_env(var_name); - assert_eq!(result, Ok(Some(false))); - } - - for val in bad_vals { - std::env::set_var(var_name, val); - let result = bool_from_env(var_name); - assert_eq!( - result, - Err(Error::NonBoolValue { - var_name: var_name.to_owned(), - value: val.to_owned() - }) - ); - } - } -} diff --git a/utils/src/rust_backtrace.rs b/utils/src/rust_backtrace.rs index a037abaf99..23867a6a83 100644 --- a/utils/src/rust_backtrace.rs +++ b/utils/src/rust_backtrace.rs @@ -13,9 +13,33 @@ // See the License for the specific language governing permissions and // limitations under the License. -/// Set the `RUST_BACKTRACE` environment variable to `full` if it's not already set -pub fn enable() { - if std::env::var("RUST_BACKTRACE").is_err() { - std::env::set_var("RUST_BACKTRACE", "full"); - } +/// Set the `RUST_BACKTRACE` environment variable to `full` if it's not already set. +/// +/// The macro must be called at the module scope, and the env var will be set before `main` +/// is entered. +/// +/// Note: setting env vars is not safe in a multithreaded environment on *nix systems, so: +/// 1) It's not safe to set them in a `#[tokio::main]` function if a multithreaded runtime is used, +/// which is why we wrapped the call to `std::env::set_var` in a module-level macro. +/// 2) The macro itself is not safe if called in a dynamic library that can be loaded later +/// via `dlopen`. Though we always use static linking at the moment, it's better to avoid +/// calling this macro at a library level; call it inside "bin" crates only, preferably +/// near the `main` function. +/// +/// Also note that the macro uses the `ctor` crate under the hood, so packages that use the macro +/// have to explicitly depend on `ctor`. +#[macro_export] +macro_rules! enable_rust_backtrace { + () => { + ctor::declarative::ctor! { + #[ctor] + fn rust_backtrace_enabler() { + if std::env::var("RUST_BACKTRACE").is_err() { + unsafe { + std::env::set_var("RUST_BACKTRACE", "full"); + } + } + } + } + }; } diff --git a/utils/tests/env_tests.rs b/utils/tests/env_tests.rs new file mode 100644 index 0000000000..849226cee1 --- /dev/null +++ b/utils/tests/env_tests.rs @@ -0,0 +1,56 @@ +// Copyright (c) 2021-2026 RBB S.r.l +// opensource@mintlayer.org +// SPDX-License-Identifier: MIT +// Licensed under the MIT License; +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://github.com/mintlayer/mintlayer-core/blob/master/LICENSE +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use test_utils::set_env_var; +use utils::env_utils::{self, bool_from_env}; + +// Note: `serial_test::serial` is redundant while there is only one test here, but it'll be +// required if more tests are added in the future, so we have it "just in case". +#[test] +#[serial_test::serial] +fn test_bool_from_env() { + let var_name = "TEST_BOOL_FROM_ENV_TEST_VAR_NAME"; + + let result = bool_from_env(var_name); + assert_eq!(result, Ok(None)); + + let true_vals = ["1", "yes", "yEs", "true", "TruE"]; + let false_vals = ["0", "no", "nO", "false", "fALSE"]; + let bad_vals = ["2", "noo", "yess"]; + + for val in true_vals { + set_env_var(var_name, val); + let result = bool_from_env(var_name); + assert_eq!(result, Ok(Some(true))); + } + + for val in false_vals { + set_env_var(var_name, val); + let result = bool_from_env(var_name); + assert_eq!(result, Ok(Some(false))); + } + + for val in bad_vals { + set_env_var(var_name, val); + let result = bool_from_env(var_name); + assert_eq!( + result, + Err(env_utils::Error::NonBoolValue { + var_name: var_name.to_owned(), + value: val.to_owned() + }) + ); + } +} diff --git a/utils/tests/log_error.rs b/utils/tests/log_error.rs index 8c9bca1cf6..f4da6d2110 100644 --- a/utils/tests/log_error.rs +++ b/utils/tests/log_error.rs @@ -853,7 +853,8 @@ mod log_output { }; use logging::{ - init_logging_generic, write_to_make_writer, LogStyle, ValueOrEnvVar, WriterSettings, + init_logging_generic, write_to_make_writer, LogStyle, ValueOrEnvVar, + ValueOrEnvVarWithDefault, WriterSettings, }; #[derive(Clone)] @@ -869,7 +870,7 @@ mod log_output { WriterSettings { make_writer: write_to_make_writer(self.clone()), is_terminal: false, - filter: ValueOrEnvVar::Value("trace".to_owned()), + filter: ValueOrEnvVarWithDefault::Value("trace".to_owned()), log_style: ValueOrEnvVar::Value(LogStyle::Text(logging::TextColoring::Off)), }, logging::no_writer_settings(), diff --git a/wallet/wallet-address-generator/Cargo.toml b/wallet/wallet-address-generator/Cargo.toml index daab04034b..2ec4ff159c 100644 --- a/wallet/wallet-address-generator/Cargo.toml +++ b/wallet/wallet-address-generator/Cargo.toml @@ -15,4 +15,5 @@ wallet-controller = { path = "../wallet-controller", default-features = false } wallet-types = { path = "../types", default-features = false } clap = { workspace = true, features = ["derive"] } +ctor.workspace = true thiserror.workspace = true diff --git a/wallet/wallet-address-generator/src/main.rs b/wallet/wallet-address-generator/src/main.rs index 782f2286e8..3a6a882bc5 100644 --- a/wallet/wallet-address-generator/src/main.rs +++ b/wallet/wallet-address-generator/src/main.rs @@ -16,13 +16,9 @@ use clap::Parser; use wallet_address_generator_lib::CliArgs; -fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } +utils::enable_rust_backtrace!(); +fn main() { let args = CliArgs::parse(); wallet_address_generator_lib::run(args).unwrap_or_else(|err| { eprintln!("{}", err); diff --git a/wallet/wallet-cli/Cargo.toml b/wallet/wallet-cli/Cargo.toml index 897d20fb19..338b78297c 100644 --- a/wallet/wallet-cli/Cargo.toml +++ b/wallet/wallet-cli/Cargo.toml @@ -10,6 +10,7 @@ utils = { path = "../../utils" } wallet-cli-lib = { path = "../wallet-cli-lib", default-features = false } clap = { workspace = true, features = ["derive"] } +ctor.workspace = true tokio = { workspace = true, default-features = false, features = [ "io-util", "macros", diff --git a/wallet/wallet-cli/src/main.rs b/wallet/wallet-cli/src/main.rs index 8280d3c91a..ce8bd4da41 100644 --- a/wallet/wallet-cli/src/main.rs +++ b/wallet/wallet-cli/src/main.rs @@ -19,14 +19,10 @@ use wallet_cli_lib::{ console::{StdioInputConsole, StdioOutputConsole}, }; +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - let args = WalletCliArgs::parse(); wallet_cli_lib::run(StdioInputConsole, StdioOutputConsole, args, None) .await diff --git a/wallet/wallet-rpc-daemon/Cargo.toml b/wallet/wallet-rpc-daemon/Cargo.toml index b80cabf1f5..9ef41d3ff6 100644 --- a/wallet/wallet-rpc-daemon/Cargo.toml +++ b/wallet/wallet-rpc-daemon/Cargo.toml @@ -14,6 +14,7 @@ utils = { path = "../../utils" } wallet-rpc-lib = { path = "../wallet-rpc-lib", default-features = false } clap.workspace = true +ctor.workspace = true thiserror.workspace = true tokio.workspace = true diff --git a/wallet/wallet-rpc-daemon/src/main.rs b/wallet/wallet-rpc-daemon/src/main.rs index ef061f69c0..fe15addb6e 100644 --- a/wallet/wallet-rpc-daemon/src/main.rs +++ b/wallet/wallet-rpc-daemon/src/main.rs @@ -25,14 +25,10 @@ async fn run() -> Result<(), Box> { Ok(()) } +utils::enable_rust_backtrace!(); + #[tokio::main] async fn main() { - utils::rust_backtrace::enable(); - - if std::env::var("RUST_LOG").is_err() { - std::env::set_var("RUST_LOG", "info"); - } - logging::init_logging(); let run_result = run().await; From 93ed5e1c798250e71e0b4465cacf1f6d32bfcf9d Mon Sep 17 00:00:00 2001 From: Mykhailo Kremniov Date: Mon, 27 Apr 2026 15:00:32 +0300 Subject: [PATCH 2/3] Pacify clippy --- .../src/storage/impls/in_memory/mod.rs | 8 +- chainstate/src/detail/query.rs | 10 +- chainstate/test-framework/src/framework.rs | 8 +- .../test-framework/src/random_tx_maker.rs | 144 ++++++++---------- .../get_stake_pool_balances_at_heights.rs | 73 +++++---- .../src/crawler_p2p/crawler_manager/mod.rs | 8 +- networking/src/transport/message_codec.rs | 14 +- p2p/src/net/default_backend/peer/mod.rs | 18 +-- p2p/src/peer_manager/mod.rs | 20 +-- p2p/src/peer_manager/peerdb/mod.rs | 12 +- p2p/src/peer_manager/tests/addresses.rs | 12 +- p2p/src/sync/peer/block_manager.rs | 29 ++-- p2p/src/sync/tests/network_sync.rs | 20 +-- .../src/pool/tests/simulation_tests.rs | 13 +- script/src/interpreter.rs | 8 +- storage/failing/src/backend.rs | 18 +-- wallet/src/account/currency_grouper/mod.rs | 10 +- wallet/src/account/output_cache/mod.rs | 86 +++++------ wallet/wallet-cli-commands/src/lib.rs | 14 +- 19 files changed, 251 insertions(+), 274 deletions(-) diff --git a/api-server/api-server-common/src/storage/impls/in_memory/mod.rs b/api-server/api-server-common/src/storage/impls/in_memory/mod.rs index 6c2c9f6cdf..859e0bfaff 100644 --- a/api-server/api-server-common/src/storage/impls/in_memory/mod.rs +++ b/api-server/api-server-common/src/storage/impls/in_memory/mod.rs @@ -1038,10 +1038,10 @@ impl ApiServerInMemoryStorage { // Handle a degenerate case when the block is stored several times using different heights // (to be consistent with the postgres implementation). - if let Some(previously_stored_height) = previously_stored_height { - if previously_stored_height != block_height { - self.main_chain_blocks_table.remove(&previously_stored_height); - } + if let Some(previously_stored_height) = previously_stored_height + && previously_stored_height != block_height + { + self.main_chain_blocks_table.remove(&previously_stored_height); } Ok(()) diff --git a/chainstate/src/detail/query.rs b/chainstate/src/detail/query.rs index 262f724118..cdba8207be 100644 --- a/chainstate/src/detail/query.rs +++ b/chainstate/src/detail/query.rs @@ -314,11 +314,11 @@ impl<'a, S: BlockchainStorageRead, V: TransactionVerificationStrategy> Chainstat let mut best_height = BlockHeight::new(0); for block_id in locator.iter() { - if let Some(block_index) = self.chainstate_ref.get_gen_block_index(block_id)? { - if self.chainstate_ref.is_block_in_main_chain(block_id)? { - best_height = block_index.block_height(); - break; - } + if let Some(block_index) = self.chainstate_ref.get_gen_block_index(block_id)? + && self.chainstate_ref.is_block_in_main_chain(block_id)? + { + best_height = block_index.block_height(); + break; } } diff --git a/chainstate/test-framework/src/framework.rs b/chainstate/test-framework/src/framework.rs index 23345dd333..ff85a6726e 100644 --- a/chainstate/test-framework/src/framework.rs +++ b/chainstate/test-framework/src/framework.rs @@ -198,10 +198,10 @@ impl TestFramework { // persistence flag set. assert_eq!(was_persisted, is_persisted); - if let Some(new_block_index) = &new_block_index_opt { - if orig_block_index_opt.is_none() { - assert!(!new_block_index.status().is_ok()); - } + if let Some(new_block_index) = &new_block_index_opt + && orig_block_index_opt.is_none() + { + assert!(!new_block_index.status().is_ok()); } assert_gen_block_index_identical_to(&new_best_block_index, &orig_best_block_index); diff --git a/chainstate/test-framework/src/random_tx_maker.rs b/chainstate/test-framework/src/random_tx_maker.rs index 0e666559a4..e5cd3f725d 100644 --- a/chainstate/test-framework/src/random_tx_maker.rs +++ b/chainstate/test-framework/src/random_tx_maker.rs @@ -980,34 +980,31 @@ impl<'a> RandomTxMaker<'a> { // create order to exchange part of available coins for tokens if let Some((token_id, token_supply)) = get_random_token(rng, self.tokens_store, tokens_cache) + && token_supply > Amount::ZERO { - if token_supply > Amount::ZERO { - let ask_amount = - Amount::from_atoms(rng.random_range(1u128..=token_supply.into_atoms())); - let give_amount = - Amount::from_atoms(rng.random_range(1u128..=atoms_to_spend)); - let order_data = OrderData::new( - Destination::AnyoneCanSpend, - OutputValue::TokenV1(token_id, ask_amount), - OutputValue::Coin(give_amount), - ); - let change = (amount_to_spend - give_amount).unwrap(); + let ask_amount = + Amount::from_atoms(rng.random_range(1u128..=token_supply.into_atoms())); + let give_amount = Amount::from_atoms(rng.random_range(1u128..=atoms_to_spend)); + let order_data = OrderData::new( + Destination::AnyoneCanSpend, + OutputValue::TokenV1(token_id, ask_amount), + OutputValue::Coin(give_amount), + ); + let change = (amount_to_spend - give_amount).unwrap(); - // Transfer output is created intentionally besides order output to not waste utxo - // (e.g. single genesis output on issuance) - let outputs = vec![ - TxOutput::CreateOrder(Box::new(order_data)), - TxOutput::Transfer( - OutputValue::Coin(change), - key_manager - .new_destination(self.chainstate.get_chain_config(), rng), - ), - ]; + // Transfer output is created intentionally besides order output to not waste utxo + // (e.g. single genesis output on issuance) + let outputs = vec![ + TxOutput::CreateOrder(Box::new(order_data)), + TxOutput::Transfer( + OutputValue::Coin(change), + key_manager.new_destination(self.chainstate.get_chain_config(), rng), + ), + ]; - self.order_can_be_created = false; + self.order_can_be_created = false; - result_outputs.extend_from_slice(&outputs); - } + result_outputs.extend_from_slice(&outputs); } } else if switch == 3 && !self.account_command_used { // try fill order @@ -1019,28 +1016,27 @@ impl<'a> RandomTxMaker<'a> { calculate_filled_order_value(&orders_cache, order_id, amount_to_spend) .unwrap(); - if let Some(filled_value) = filled_value { - if !is_frozen_token(&filled_value, tokens_cache) - && !is_frozen_order(&orders_cache, order_id) - { - let input = TxInput::OrderAccountCommand( - OrderAccountCommand::FillOrder(order_id, amount_to_spend), - ); + if let Some(filled_value) = filled_value + && !is_frozen_token(&filled_value, tokens_cache) + && !is_frozen_order(&orders_cache, order_id) + { + let input = TxInput::OrderAccountCommand(OrderAccountCommand::FillOrder( + order_id, + amount_to_spend, + )); - let output = TxOutput::Transfer( - filled_value, - key_manager - .new_destination(self.chainstate.get_chain_config(), rng), - ); + let output = TxOutput::Transfer( + filled_value, + key_manager.new_destination(self.chainstate.get_chain_config(), rng), + ); - let _ = orders_cache - .fill_order(order_id, amount_to_spend, OrdersVersion::V1) - .unwrap(); - self.account_command_used = true; + let _ = orders_cache + .fill_order(order_id, amount_to_spend, OrdersVersion::V1) + .unwrap(); + self.account_command_used = true; - result_inputs.push(input); - result_outputs.push(output); - } + result_inputs.push(input); + result_outputs.push(output); } } } else if switch == 6 { @@ -1136,17 +1132,17 @@ impl<'a> RandomTxMaker<'a> { result_outputs.push(output); // Occasionally create new delegation id - if rng.random::() && self.delegation_can_be_created { - if let Some((pool_id, _)) = + if rng.random::() + && self.delegation_can_be_created + && let Some((pool_id, _)) = get_random_pool_data(rng, self.pos_accounting_store, &pos_accounting_cache) - { - self.delegation_can_be_created = false; + { + self.delegation_can_be_created = false; - result_outputs.push(TxOutput::CreateDelegationId( - key_manager.new_destination(self.chainstate.get_chain_config(), rng), - *pool_id, - )); - } + result_outputs.push(TxOutput::CreateDelegationId( + key_manager.new_destination(self.chainstate.get_chain_config(), rng), + *pool_id, + )); } } } @@ -1244,32 +1240,24 @@ impl<'a> RandomTxMaker<'a> { ) .unwrap(); - if let Some(filled_value) = filled_value { - if !is_frozen_token(&filled_value, tokens_cache) - && !is_frozen_order(orders_cache, order_id) - { - result_outputs.push(TxOutput::Transfer( - filled_value, - key_manager - .new_destination(self.chainstate.get_chain_config(), rng), - )); - - result_inputs.push(TxInput::OrderAccountCommand( - OrderAccountCommand::FillOrder( - order_id, - Amount::from_atoms(atoms), - ), - )); - - let _ = orders_cache - .fill_order( - order_id, - Amount::from_atoms(atoms), - OrdersVersion::V1, - ) - .unwrap(); - self.account_command_used = true; - } + if let Some(filled_value) = filled_value + && !is_frozen_token(&filled_value, tokens_cache) + && !is_frozen_order(orders_cache, order_id) + { + result_outputs.push(TxOutput::Transfer( + filled_value, + key_manager + .new_destination(self.chainstate.get_chain_config(), rng), + )); + + result_inputs.push(TxInput::OrderAccountCommand( + OrderAccountCommand::FillOrder(order_id, Amount::from_atoms(atoms)), + )); + + let _ = orders_cache + .fill_order(order_id, Amount::from_atoms(atoms), OrdersVersion::V1) + .unwrap(); + self.account_command_used = true; } } } diff --git a/chainstate/test-suite/src/tests/get_stake_pool_balances_at_heights.rs b/chainstate/test-suite/src/tests/get_stake_pool_balances_at_heights.rs index 491106b357..56ded7b951 100644 --- a/chainstate/test-suite/src/tests/get_stake_pool_balances_at_heights.rs +++ b/chainstate/test-suite/src/tests/get_stake_pool_balances_at_heights.rs @@ -169,58 +169,57 @@ fn randomized_test(#[case] seed: Seed) { did_something = true; } 1 => { - if rng.random_bool(0.5) { - if let Some(pool_id) = test_data.random_pool_id(&mut rng) { - test_data.decommission_pool(&mut tf, &mut rng, &pool_id); - did_something = true; - } + if rng.random_bool(0.5) + && let Some(pool_id) = test_data.random_pool_id(&mut rng) + { + test_data.decommission_pool(&mut tf, &mut rng, &pool_id); + did_something = true; } } 2 => { - if rng.random_bool(0.5) { - if let Some(pool_id) = test_data.random_pool_id(&mut rng) { - let _ = test_data.create_delegation(&mut tf, &mut rng, &pool_id); - did_something = true; - } + if rng.random_bool(0.5) + && let Some(pool_id) = test_data.random_pool_id(&mut rng) + { + let _ = test_data.create_delegation(&mut tf, &mut rng, &pool_id); + did_something = true; } } 3 => { - if rng.random_bool(0.5) { - if let Some((pool_id, delegation_id)) = + if rng.random_bool(0.5) + && let Some((pool_id, delegation_id)) = test_data.random_pool_and_delegation_id(&mut rng) - { - let _ = test_data.withdraw_from_delegation( - &mut tf, - &mut rng, - &pool_id, - &delegation_id, - ); - did_something = true; - } + { + let _ = test_data.withdraw_from_delegation( + &mut tf, + &mut rng, + &pool_id, + &delegation_id, + ); + did_something = true; } } _ => { - if rng.random_bool(0.5) { - if let Some((pool_id, delegation_id)) = + if rng.random_bool(0.5) + && let Some((pool_id, delegation_id)) = test_data.random_pool_and_delegation_id(&mut rng) - { - let _ = test_data.add_to_delegation( - &mut tf, - &mut rng, - &pool_id, - &delegation_id, - ); - did_something = true; - } + { + let _ = test_data.add_to_delegation( + &mut tf, + &mut rng, + &pool_id, + &delegation_id, + ); + did_something = true; } } } - if !did_something && rng.random_bool(0.5) { - if let Some(pool_id) = test_data.random_pool_id(&mut rng) { - test_data.produce_trivial_block_with_pool(&mut tf, &mut rng, &pool_id); - did_something = true; - } + if !did_something + && rng.random_bool(0.5) + && let Some(pool_id) = test_data.random_pool_id(&mut rng) + { + test_data.produce_trivial_block_with_pool(&mut tf, &mut rng, &pool_id); + did_something = true; } if !did_something { diff --git a/dns-server/src/crawler_p2p/crawler_manager/mod.rs b/dns-server/src/crawler_p2p/crawler_manager/mod.rs index 8d88c9d521..485c1b771a 100644 --- a/dns-server/src/crawler_p2p/crawler_manager/mod.rs +++ b/dns-server/src/crawler_p2p/crawler_manager/mod.rs @@ -290,10 +290,10 @@ where ConnectivityEvent::Message { peer_id, message } => { let result = self.handle_conn_message(peer_id, message); - if let Err(error) = result { - if error.ban_score() > 0 { - self.send_crawler_event(CrawlerEvent::Misbehaved { peer_id, error }); - } + if let Err(error) = result + && error.ban_score() > 0 + { + self.send_crawler_event(CrawlerEvent::Misbehaved { peer_id, error }); } } ConnectivityEvent::OutboundAccepted { diff --git a/networking/src/transport/message_codec.rs b/networking/src/transport/message_codec.rs index a3d48473a8..4f51f7fd05 100644 --- a/networking/src/transport/message_codec.rs +++ b/networking/src/transport/message_codec.rs @@ -42,14 +42,14 @@ impl MessageCodec { } fn check_encoded_message_size(&self, size: usize) -> Result<()> { - if let Some(max_message_size) = self.max_encoded_message_size { - if size > max_message_size { - return Err(MessageCodecError::MessageTooLarge { - actual_size: size, - max_size: max_message_size, - } - .into()); + if let Some(max_message_size) = self.max_encoded_message_size + && size > max_message_size + { + return Err(MessageCodecError::MessageTooLarge { + actual_size: size, + max_size: max_message_size, } + .into()); } Ok(()) diff --git a/p2p/src/net/default_backend/peer/mod.rs b/p2p/src/net/default_backend/peer/mod.rs index dad851919b..3f54fd49fb 100644 --- a/p2p/src/net/default_backend/peer/mod.rs +++ b/p2p/src/net/default_backend/peer/mod.rs @@ -398,15 +398,15 @@ async fn maybe_send_will_disconnect( peer_protocol_version: ProtocolVersion, socket_writer: &mut MessageWriter, ) -> crate::Result<()> { - if can_send_will_disconnect(peer_protocol_version) { - if let Some(reason) = reason { - log::debug!("Sending WillDisconnect, reason: {:?}", reason); - socket_writer - .send(Message::WillDisconnect(WillDisconnectMessage { - reason: reason.to_string(), - })) - .await?; - } + if can_send_will_disconnect(peer_protocol_version) + && let Some(reason) = reason + { + log::debug!("Sending WillDisconnect, reason: {:?}", reason); + socket_writer + .send(Message::WillDisconnect(WillDisconnectMessage { + reason: reason.to_string(), + })) + .await?; } Ok(()) diff --git a/p2p/src/peer_manager/mod.rs b/p2p/src/peer_manager/mod.rs index f0b831c0ea..a820023036 100644 --- a/p2p/src/peer_manager/mod.rs +++ b/p2p/src/peer_manager/mod.rs @@ -863,16 +863,16 @@ where P2pError::ConnectionValidationFailed(ConnectionValidationError::NoCommonServices), ); - if let Some(min_version) = self.p2p_config.peer_manager_config.min_peer_software_version { - if info.user_agent == self.p2p_config.user_agent && info.software_version < min_version - { - return Err(P2pError::ConnectionValidationFailed( - ConnectionValidationError::MinPeerSoftwareVersionNotSatisfied { - min_version, - actual_version: info.software_version, - }, - )); - } + if let Some(min_version) = self.p2p_config.peer_manager_config.min_peer_software_version + && info.user_agent == self.p2p_config.user_agent + && info.software_version < min_version + { + return Err(P2pError::ConnectionValidationFailed( + ConnectionValidationError::MinPeerSoftwareVersionNotSatisfied { + min_version, + actual_version: info.software_version, + }, + )); } match peer_role { diff --git a/p2p/src/peer_manager/peerdb/mod.rs b/p2p/src/peer_manager/peerdb/mod.rs index 4698426605..4463b8b77e 100644 --- a/p2p/src/peer_manager/peerdb/mod.rs +++ b/p2p/src/peer_manager/peerdb/mod.rs @@ -509,13 +509,13 @@ impl PeerDb { // Note: this function assumes that the address has already been removed from `address_tables`. fn remove_from_addresses_if_some_non_reserved(&mut self, address: Option) { - if let Some(address) = address { - if !self.reserved_nodes.contains(&address) { - self.addresses.remove(&address); + if let Some(address) = address + && !self.reserved_nodes.contains(&address) + { + self.addresses.remove(&address); - update_db(&self.storage, |tx| tx.del_known_address(&address)) - .expect("DB failure when deleting known address {address}"); - } + update_db(&self.storage, |tx| tx.del_known_address(&address)) + .expect("DB failure when deleting known address {address}"); } } diff --git a/p2p/src/peer_manager/tests/addresses.rs b/p2p/src/peer_manager/tests/addresses.rs index 3e1e6d7026..fc1b7ee134 100644 --- a/p2p/src/peer_manager/tests/addresses.rs +++ b/p2p/src/peer_manager/tests/addresses.rs @@ -463,14 +463,12 @@ async fn resend_own_addresses(#[case] seed: Seed) { peer_id: _, message, } = cmd + && let CategorizedMessage::PeerManagerMessage(PeerManagerMessage::AnnounceAddrRequest( + AnnounceAddrRequest { address }, + )) = message.categorize() { - if let CategorizedMessage::PeerManagerMessage( - PeerManagerMessage::AnnounceAddrRequest(AnnounceAddrRequest { address }), - ) = message.categorize() - { - let announced_addr = address.as_discoverable_socket_address(false).unwrap(); - listening_addresses.remove(&announced_addr); - } + let announced_addr = address.as_discoverable_socket_address(false).unwrap(); + listening_addresses.remove(&announced_addr); } } } diff --git a/p2p/src/sync/peer/block_manager.rs b/p2p/src/sync/peer/block_manager.rs index f96fe57cde..3ceb1900c3 100644 --- a/p2p/src/sync/peer/block_manager.rs +++ b/p2p/src/sync/peer/block_manager.rs @@ -549,21 +549,20 @@ where P2pError::ProtocolError(ProtocolError::UnknownBlockRequested(id)), )?; - if let Some(ref best_sent_block) = best_sent_block { - if index.block_height() <= best_sent_block.block_height() { - // This can be normal in case of reorg; ensure that the mainchain block - // at best_sent_block's height has a different id. - // Note that mainchain could have become shorter due to blocks - // invalidation, so no block at that height may be present at all. - if let Some(mainchain_block_id_at_height) = - c.get_block_id_from_height(best_sent_block.block_height())? - { - if &mainchain_block_id_at_height == best_sent_block.block_id() { - return Err(P2pError::ProtocolError( - ProtocolError::DuplicatedBlockRequest(id), - )); - } - } + if let Some(ref best_sent_block) = best_sent_block + && index.block_height() <= best_sent_block.block_height() + { + // This can be normal in case of reorg; ensure that the mainchain block + // at best_sent_block's height has a different id. + // Note that mainchain could have become shorter due to blocks + // invalidation, so no block at that height may be present at all. + if let Some(mainchain_block_id_at_height) = + c.get_block_id_from_height(best_sent_block.block_height())? + && &mainchain_block_id_at_height == best_sent_block.block_id() + { + return Err(P2pError::ProtocolError( + ProtocolError::DuplicatedBlockRequest(id), + )); } } } diff --git a/p2p/src/sync/tests/network_sync.rs b/p2p/src/sync/tests/network_sync.rs index 939b8b7374..5b32977302 100644 --- a/p2p/src/sync/tests/network_sync.rs +++ b/p2p/src/sync/tests/network_sync.rs @@ -368,16 +368,16 @@ async fn block_announcement_disconnected_headers(#[case] seed: Seed) { nodes .exchange_block_sync_messages_while(&mut delayed_msgs, async |_, delayed_msgs, msg| { - if msg.sender_node_idx == 1 { - if let BlockSyncMessage::BlockListRequest(req) = &msg.message { - assert_eq!(req.block_ids().len(), initial_block_count); - log::debug!( - "Got block list request from node idx {}, delaying it", - msg.sender_node_idx - ); - delayed_msgs.push(msg.clone()); - return MsgAction::Break; - } + if msg.sender_node_idx == 1 + && let BlockSyncMessage::BlockListRequest(req) = &msg.message + { + assert_eq!(req.block_ids().len(), initial_block_count); + log::debug!( + "Got block list request from node idx {}, delaying it", + msg.sender_node_idx + ); + delayed_msgs.push(msg.clone()); + return MsgAction::Break; } MsgAction::SendAndContinue diff --git a/pos-accounting/src/pool/tests/simulation_tests.rs b/pos-accounting/src/pool/tests/simulation_tests.rs index 0b89d5e03d..04fb94bf53 100644 --- a/pos-accounting/src/pool/tests/simulation_tests.rs +++ b/pos-accounting/src/pool/tests/simulation_tests.rs @@ -172,13 +172,12 @@ fn perform_random_operation( } // delete delegation 10 => { - if let Some((delegation_id, delegation_data)) = random_delegation { - if !op.pool_exists(*delegation_data.source_pool()).unwrap() - && op.get_delegation_balance(delegation_id).unwrap() == Amount::ZERO - { - let undo = op.delete_delegation_id(delegation_id).unwrap(); - undos.push(undo); - } + if let Some((delegation_id, delegation_data)) = random_delegation + && !op.pool_exists(*delegation_data.source_pool()).unwrap() + && op.get_delegation_balance(delegation_id).unwrap() == Amount::ZERO + { + let undo = op.delete_delegation_id(delegation_id).unwrap(); + undos.push(undo); } } // undo diff --git a/script/src/interpreter.rs b/script/src/interpreter.rs index 1f7e86a1a9..045fbc83cd 100644 --- a/script/src/interpreter.rs +++ b/script/src/interpreter.rs @@ -380,10 +380,10 @@ fn check_multisig<'a, Ctx: Context>( ParseResult::Reserved => break, // parsed a pubkey -> check signature ParseResult::Ok(pubkey) => { - if let Some(sigdata) = ctx.parse_signature(pubkey, sig) { - if ctx.verify_signature(&sigdata, subscript, codesep_idx) { - break; - } + if let Some(sigdata) = ctx.parse_signature(pubkey, sig) + && ctx.verify_signature(&sigdata, subscript, codesep_idx) + { + break; } } } diff --git a/storage/failing/src/backend.rs b/storage/failing/src/backend.rs index aa67579452..c717e33c78 100644 --- a/storage/failing/src/backend.rs +++ b/storage/failing/src/backend.rs @@ -161,15 +161,15 @@ struct RwTxState<'a> { impl RwTxState<'_> { fn emit_error(&mut self, eg: &ErrorGeneration) -> storage_core::Result<()> { - if self.transaction_failures < self.config.max_failures_per_transaction() { - if let Some(err) = eg.generate(&mut self.rng) { - if self.total_failures.fetch_add(1) < self.config.max_failures_total() { - self.transaction_failures += 1; - return Err(err.into()); - } else { - // Correct the previous fetch_add if we reached the max. - self.total_failures.fetch_sub(1); - } + if self.transaction_failures < self.config.max_failures_per_transaction() + && let Some(err) = eg.generate(&mut self.rng) + { + if self.total_failures.fetch_add(1) < self.config.max_failures_total() { + self.transaction_failures += 1; + return Err(err.into()); + } else { + // Correct the previous fetch_add if we reached the max. + self.total_failures.fetch_sub(1); } } Ok(()) diff --git a/wallet/src/account/currency_grouper/mod.rs b/wallet/src/account/currency_grouper/mod.rs index acf9827f4a..b4bb14e0ac 100644 --- a/wallet/src/account/currency_grouper/mod.rs +++ b/wallet/src/account/currency_grouper/mod.rs @@ -208,11 +208,11 @@ pub fn group_coin_utxos_for_input_by_destination { - if let Some(frozen_token_id) = conflict_check.frozen_token_id { - if self.violates_frozen_token(unconfirmed_tx, &frozen_token_id) { - conflicting_txs.insert(tx.get_transaction().get_id()); - continue; - } + if let Some(frozen_token_id) = conflict_check.frozen_token_id + && self.violates_frozen_token(unconfirmed_tx, &frozen_token_id) + { + conflicting_txs.insert(tx.get_transaction().get_id()); + continue; } if let Some((confirmed_account, confirmed_account_nonce)) = conflict_check.confirmed_account_nonce + && confirmed_tx.get_id() != tx.get_transaction().get_id() + && uses_conflicting_nonce( + unconfirmed_tx, + confirmed_account, + confirmed_account_nonce, + ) { - if confirmed_tx.get_id() != tx.get_transaction().get_id() - && uses_conflicting_nonce( - unconfirmed_tx, - confirmed_account, - confirmed_account_nonce, - ) - { - conflicting_txs.insert(tx.get_transaction().get_id()); - continue; - } + conflicting_txs.insert(tx.get_transaction().get_id()); + continue; } if let Some((confirmed_cmd_tag, confirmed_order_id)) = conflict_check.conflicting_order_command + && confirmed_tx.get_id() != tx.get_transaction().get_id() + && uses_conflicting_order_command( + unconfirmed_tx, + confirmed_cmd_tag, + confirmed_order_id, + ) { - if confirmed_tx.get_id() != tx.get_transaction().get_id() - && uses_conflicting_order_command( - unconfirmed_tx, - confirmed_cmd_tag, - confirmed_order_id, - ) - { - conflicting_txs.insert(tx.get_transaction().get_id()); - continue; - } + conflicting_txs.insert(tx.get_transaction().get_id()); + continue; } } WalletTx::Block(_) => { @@ -1190,16 +1186,16 @@ impl OutputCache { } TxInput::Account(outpoint) => match outpoint.account() { AccountSpending::DelegationBalance(delegation_id, _) => { - if !already_present { - if let Some(data) = self.delegations.get_mut(delegation_id) { - Self::update_delegation_state( - &mut self.unconfirmed_descendants, - data, - delegation_id, - outpoint.nonce(), - tx_id, - )?; - } + if !already_present + && let Some(data) = self.delegations.get_mut(delegation_id) + { + Self::update_delegation_state( + &mut self.unconfirmed_descendants, + data, + delegation_id, + outpoint.nonce(), + tx_id, + )?; } } }, @@ -1276,17 +1272,15 @@ impl OutputCache { OrderAccountCommand::FillOrder(order_id, _) | OrderAccountCommand::FreezeOrder(order_id) | OrderAccountCommand::ConcludeOrder(order_id) => { - if !already_present { - if let Some(data) = self.orders.get_mut(order_id) { - Self::update_order_state( - &mut self.unconfirmed_descendants, - data, - order_id, - cmd.into(), - None, - tx_id, - )?; - } + if !already_present && let Some(data) = self.orders.get_mut(order_id) { + Self::update_order_state( + &mut self.unconfirmed_descendants, + data, + order_id, + cmd.into(), + None, + tx_id, + )?; } } }, diff --git a/wallet/wallet-cli-commands/src/lib.rs b/wallet/wallet-cli-commands/src/lib.rs index dde3f893d0..c625b4db6c 100644 --- a/wallet/wallet-cli-commands/src/lib.rs +++ b/wallet/wallet-cli-commands/src/lib.rs @@ -1507,15 +1507,15 @@ pub fn get_repl_command(cold_wallet: bool, mutable_wallet: bool) -> Command { let mut new_subcommand = subcommand.clone().help_template(COMMAND_HELP_TEMPLATE).display_order(0); - if new_subcommand.get_about().is_none() { - if let Some(rpc_method) = method_desc_from_rpc.get(subcommand.get_name()) { - let (about, long_about) = clapify_and_split_rpc_description(rpc_method.description); + if new_subcommand.get_about().is_none() + && let Some(rpc_method) = method_desc_from_rpc.get(subcommand.get_name()) + { + let (about, long_about) = clapify_and_split_rpc_description(rpc_method.description); - new_subcommand = new_subcommand.about(about); + new_subcommand = new_subcommand.about(about); - if let Some(long_about) = long_about { - new_subcommand = new_subcommand.long_about(long_about); - } + if let Some(long_about) = long_about { + new_subcommand = new_subcommand.long_about(long_about); } } From 95f759a9c6e02565e90adf9d219d3c6ca5aaa0eb Mon Sep 17 00:00:00 2001 From: Mykhailo Kremniov Date: Mon, 27 Apr 2026 15:40:23 +0300 Subject: [PATCH 3/3] Update openssl to pacify dependabot --- Cargo.lock | 8 ++++---- supply-chain/imports.lock | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 665532a12c..9475b5206a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6035,9 +6035,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.75" +version = "0.10.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" +checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" dependencies = [ "bitflags 2.10.0", "cfg-if", @@ -6073,9 +6073,9 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.111" +version = "0.9.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" +checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" dependencies = [ "cc", "libc", diff --git a/supply-chain/imports.lock b/supply-chain/imports.lock index 6b7d20c899..15ce11b093 100644 --- a/supply-chain/imports.lock +++ b/supply-chain/imports.lock @@ -1081,8 +1081,8 @@ user-login = "epage" user-name = "Ed Page" [[publisher.openssl]] -version = "0.10.75" -when = "2025-11-07" +version = "0.10.78" +when = "2026-04-19" user-id = 163 user-login = "alex" user-name = "Alex Gaynor" @@ -1102,8 +1102,8 @@ user-login = "djc" user-name = "Dirkjan Ochtman" [[publisher.openssl-sys]] -version = "0.9.111" -when = "2025-11-07" +version = "0.9.114" +when = "2026-04-19" user-id = 163 user-login = "alex" user-name = "Alex Gaynor"