From aeb070ae8dc7df5f5e1589befd2c017bb6405ccc Mon Sep 17 00:00:00 2001 From: hinto-janai Date: Tue, 20 Aug 2024 17:53:32 -0400 Subject: [PATCH] Replace `OnceLock` + `fn` with `LazyLock` (#256) * `consensus/` * `helper/` * `test-utils/` * `storage/` * fix docs + tests + lints * decomposed_amount: remove `LazyLock` * clippy --- consensus/rules/src/decomposed_amount.rs | 59 ++++----- consensus/rules/src/transactions/tests.rs | 4 +- helper/src/fs.rs | 133 +++++++++----------- storage/blockchain/src/config/config.rs | 20 +-- storage/blockchain/src/ops/block.rs | 12 +- storage/blockchain/src/ops/blockchain.rs | 8 +- storage/blockchain/src/ops/mod.rs | 4 +- storage/blockchain/src/ops/tx.rs | 4 +- storage/blockchain/src/service/mod.rs | 4 +- storage/blockchain/src/service/tests.rs | 20 +-- storage/database/src/backend/tests.rs | 2 +- storage/database/src/resize.rs | 33 ++--- test-utils/src/data/mod.rs | 14 +-- test-utils/src/data/{free.rs => statics.rs} | 96 +++++++------- 14 files changed, 186 insertions(+), 227 deletions(-) rename test-utils/src/data/{free.rs => statics.rs} (82%) diff --git a/consensus/rules/src/decomposed_amount.rs b/consensus/rules/src/decomposed_amount.rs index 5934814..a8821f3 100644 --- a/consensus/rules/src/decomposed_amount.rs +++ b/consensus/rules/src/decomposed_amount.rs @@ -1,36 +1,27 @@ -use std::sync::OnceLock; - -/// Decomposed amount table. -/// -static DECOMPOSED_AMOUNTS: OnceLock<[u64; 172]> = OnceLock::new(); - #[rustfmt::skip] -pub fn decomposed_amounts() -> &'static [u64; 172] { - DECOMPOSED_AMOUNTS.get_or_init(|| { - [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 20, 30, 40, 50, 60, 70, 80, 90, - 100, 200, 300, 400, 500, 600, 700, 800, 900, - 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, - 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, - 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, - 1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000, - 10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000, - 100000000, 200000000, 300000000, 400000000, 500000000, 600000000, 700000000, 800000000, 900000000, - 1000000000, 2000000000, 3000000000, 4000000000, 5000000000, 6000000000, 7000000000, 8000000000, 9000000000, - 10000000000, 20000000000, 30000000000, 40000000000, 50000000000, 60000000000, 70000000000, 80000000000, 90000000000, - 100000000000, 200000000000, 300000000000, 400000000000, 500000000000, 600000000000, 700000000000, 800000000000, 900000000000, - 1000000000000, 2000000000000, 3000000000000, 4000000000000, 5000000000000, 6000000000000, 7000000000000, 8000000000000, 9000000000000, - 10000000000000, 20000000000000, 30000000000000, 40000000000000, 50000000000000, 60000000000000, 70000000000000, 80000000000000, 90000000000000, - 100000000000000, 200000000000000, 300000000000000, 400000000000000, 500000000000000, 600000000000000, 700000000000000, 800000000000000, 900000000000000, - 1000000000000000, 2000000000000000, 3000000000000000, 4000000000000000, 5000000000000000, 6000000000000000, 7000000000000000, 8000000000000000, 9000000000000000, - 10000000000000000, 20000000000000000, 30000000000000000, 40000000000000000, 50000000000000000, 60000000000000000, 70000000000000000, 80000000000000000, 90000000000000000, - 100000000000000000, 200000000000000000, 300000000000000000, 400000000000000000, 500000000000000000, 600000000000000000, 700000000000000000, 800000000000000000, 900000000000000000, - 1000000000000000000, 2000000000000000000, 3000000000000000000, 4000000000000000000, 5000000000000000000, 6000000000000000000, 7000000000000000000, 8000000000000000000, 9000000000000000000, - 10000000000000000000 - ] - }) -} +/// Decomposed amount table. +pub static DECOMPOSED_AMOUNTS: [u64; 172] = [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 20, 30, 40, 50, 60, 70, 80, 90, + 100, 200, 300, 400, 500, 600, 700, 800, 900, + 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, + 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, + 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, + 1000000, 2000000, 3000000, 4000000, 5000000, 6000000, 7000000, 8000000, 9000000, + 10000000, 20000000, 30000000, 40000000, 50000000, 60000000, 70000000, 80000000, 90000000, + 100000000, 200000000, 300000000, 400000000, 500000000, 600000000, 700000000, 800000000, 900000000, + 1000000000, 2000000000, 3000000000, 4000000000, 5000000000, 6000000000, 7000000000, 8000000000, 9000000000, + 10000000000, 20000000000, 30000000000, 40000000000, 50000000000, 60000000000, 70000000000, 80000000000, 90000000000, + 100000000000, 200000000000, 300000000000, 400000000000, 500000000000, 600000000000, 700000000000, 800000000000, 900000000000, + 1000000000000, 2000000000000, 3000000000000, 4000000000000, 5000000000000, 6000000000000, 7000000000000, 8000000000000, 9000000000000, + 10000000000000, 20000000000000, 30000000000000, 40000000000000, 50000000000000, 60000000000000, 70000000000000, 80000000000000, 90000000000000, + 100000000000000, 200000000000000, 300000000000000, 400000000000000, 500000000000000, 600000000000000, 700000000000000, 800000000000000, 900000000000000, + 1000000000000000, 2000000000000000, 3000000000000000, 4000000000000000, 5000000000000000, 6000000000000000, 7000000000000000, 8000000000000000, 9000000000000000, + 10000000000000000, 20000000000000000, 30000000000000000, 40000000000000000, 50000000000000000, 60000000000000000, 70000000000000000, 80000000000000000, 90000000000000000, + 100000000000000000, 200000000000000000, 300000000000000000, 400000000000000000, 500000000000000000, 600000000000000000, 700000000000000000, 800000000000000000, 900000000000000000, + 1000000000000000000, 2000000000000000000, 3000000000000000000, 4000000000000000000, 5000000000000000000, 6000000000000000000, 7000000000000000000, 8000000000000000000, 9000000000000000000, + 10000000000000000000 +]; /// Checks that an output amount is decomposed. /// @@ -40,7 +31,7 @@ pub fn decomposed_amounts() -> &'static [u64; 172] { /// ref: #[inline] pub fn is_decomposed_amount(amount: &u64) -> bool { - decomposed_amounts().binary_search(amount).is_ok() + DECOMPOSED_AMOUNTS.binary_search(amount).is_ok() } #[cfg(test)] @@ -49,7 +40,7 @@ mod tests { #[test] fn decomposed_amounts_return_decomposed() { - for amount in decomposed_amounts() { + for amount in DECOMPOSED_AMOUNTS.iter() { assert!(is_decomposed_amount(amount)) } } diff --git a/consensus/rules/src/transactions/tests.rs b/consensus/rules/src/transactions/tests.rs index 0bea08c..cd0e8c3 100644 --- a/consensus/rules/src/transactions/tests.rs +++ b/consensus/rules/src/transactions/tests.rs @@ -10,11 +10,11 @@ use proptest::{collection::vec, prelude::*}; use monero_serai::transaction::Output; use super::*; -use crate::decomposed_amount::decomposed_amounts; +use crate::decomposed_amount::DECOMPOSED_AMOUNTS; #[test] fn test_check_output_amount_v1() { - for amount in decomposed_amounts() { + for amount in DECOMPOSED_AMOUNTS.iter() { assert!(check_output_amount_v1(*amount, &HardFork::V2).is_ok()) } diff --git a/helper/src/fs.rs b/helper/src/fs.rs index 1efb20c..d38ee33 100644 --- a/helper/src/fs.rs +++ b/helper/src/fs.rs @@ -4,7 +4,7 @@ //! Note that this module's functions uses [`dirs`], //! which adheres to the XDG standard on Linux. //! -//! This means that the values returned by these functions +//! This means that the values returned by these statics //! may change at runtime depending on environment variables, //! for example: //! @@ -17,7 +17,7 @@ //! # if cfg!(target_os = "linux") { //! std::env::set_var("XDG_CONFIG_HOME", "/custom/path"); //! assert_eq!( -//! cuprate_config_dir().to_string_lossy(), +//! CUPRATE_CONFIG_DIR.to_string_lossy(), //! "/custom/path/cuprate" //! ); //! # } @@ -28,10 +28,7 @@ //! - //---------------------------------------------------------------------------------------------------- Use -use std::{ - path::{Path, PathBuf}, - sync::OnceLock, -}; +use std::{path::PathBuf, sync::LazyLock}; //---------------------------------------------------------------------------------------------------- Const /// Cuprate's main directory. @@ -62,71 +59,59 @@ pub const CUPRATE_DIR: &str = { }; //---------------------------------------------------------------------------------------------------- Directories -/// Create a (private) `OnceLock` and accessor function for common PATHs used by Cuprate. +/// Create a `LazyLock` for common PATHs used by Cuprate. /// /// This currently creates these directories: -/// - [`cuprate_cache_dir()`] -/// - [`cuprate_config_dir()`] -/// - [`cuprate_data_dir()`] -/// - [`cuprate_blockchain_dir()`] -/// -/// FIXME: Use `LazyLock` when stabilized. -/// . -/// . -macro_rules! impl_path_oncelock_and_fn { +/// - [`CUPRATE_CACHE_DIR`] +/// - [`CUPRATE_CONFIG_DIR`] +/// - [`CUPRATE_DATA_DIR`] +/// - [`CUPRATE_BLOCKCHAIN_DIR`] +macro_rules! impl_path_lazylock { ($( $(#[$attr:meta])* // Documentation and any `derive`'s. - $fn:ident, // Name of the corresponding access function. + $name:ident, // Name of the corresponding `LazyLock`. $dirs_fn:ident, // Name of the `dirs` function to use, the PATH prefix. $sub_dirs:literal // Any sub-directories to add onto the PATH. ),* $(,)?) => {$( - // Create the `OnceLock` if needed, append + // Create the `LazyLock` if needed, append // the Cuprate directory string and return. $(#[$attr])* - pub fn $fn() -> &'static Path { - /// Local `OnceLock` containing the Path. - static ONCE_LOCK: OnceLock = OnceLock::new(); + pub static $name: LazyLock = LazyLock::new(|| { + // There's nothing we can do but panic if + // we cannot acquire critical system directories. + // + // Although, this realistically won't panic on + // normal systems for all OS's supported by `dirs`. + let mut path = dirs::$dirs_fn().unwrap(); - ONCE_LOCK.get_or_init(|| { - // There's nothing we can do but panic if - // we cannot acquire critical system directories. - // - // Although, this realistically won't panic on - // normal systems for all OS's supported by `dirs`. - let mut path = dirs::$dirs_fn().unwrap(); + // FIXME: + // Consider a user who does `HOME=/ ./cuprated` + // + // Should we say "that's stupid" and panic here? + // Or should it be respected? + // We really don't want a `rm -rf /` type of situation... + assert!( + path.parent().is_some(), + "SAFETY: returned OS PATH was either root or empty, aborting" + ); - // FIXME: - // Consider a user who does `HOME=/ ./cuprated` - // - // Should we say "that's stupid" and panic here? - // Or should it be respected? - // We really don't want a `rm -rf /` type of situation... - assert!( - path.parent().is_some(), - "SAFETY: returned OS PATH was either root or empty, aborting" - ); + // Returned OS PATH should be absolute, not relative. + assert!(path.is_absolute(), "SAFETY: returned OS PATH was not absolute"); - // Returned OS PATH should be absolute, not relative. - assert!(path.is_absolute(), "SAFETY: returned OS PATH was not absolute"); + // Unconditionally prefix with the top-level Cuprate directory. + path.push(CUPRATE_DIR); - // Unconditionally prefix with the top-level Cuprate directory. - path.push(CUPRATE_DIR); + // Add any sub directories if specified in the macro. + if !$sub_dirs.is_empty() { + path.push($sub_dirs); + } - // Add any sub directories if specified in the macro. - if !$sub_dirs.is_empty() { - path.push($sub_dirs); - } - - path - }) - } + path + }); )*}; } -// Note that the `OnceLock`'s are prefixed with `__` to indicate: -// 1. They're not really to be used directly -// 2. To avoid name conflicts -impl_path_oncelock_and_fn! { +impl_path_lazylock! { /// Cuprate's cache directory. /// /// This is the PATH used for any Cuprate cache files. @@ -136,7 +121,7 @@ impl_path_oncelock_and_fn! { /// | Windows | `C:\Users\Alice\AppData\Local\Cuprate\` | /// | macOS | `/Users/Alice/Library/Caches/Cuprate/` | /// | Linux | `/home/alice/.cache/cuprate/` | - cuprate_cache_dir, + CUPRATE_CACHE_DIR, cache_dir, "", @@ -149,7 +134,7 @@ impl_path_oncelock_and_fn! { /// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` | /// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` | /// | Linux | `/home/alice/.config/cuprate/` | - cuprate_config_dir, + CUPRATE_CONFIG_DIR, config_dir, "", @@ -162,7 +147,7 @@ impl_path_oncelock_and_fn! { /// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\` | /// | macOS | `/Users/Alice/Library/Application Support/Cuprate/` | /// | Linux | `/home/alice/.local/share/cuprate/` | - cuprate_data_dir, + CUPRATE_DATA_DIR, data_dir, "", @@ -175,7 +160,7 @@ impl_path_oncelock_and_fn! { /// | Windows | `C:\Users\Alice\AppData\Roaming\Cuprate\blockchain\` | /// | macOS | `/Users/Alice/Library/Application Support/Cuprate/blockchain/` | /// | Linux | `/home/alice/.local/share/cuprate/blockchain/` | - cuprate_blockchain_dir, + CUPRATE_BLOCKCHAIN_DIR, data_dir, "blockchain", } @@ -192,58 +177,58 @@ mod test { // - It must `ends_with()` the expected end PATH for the OS #[test] fn path_sanity_check() { - assert!(cuprate_cache_dir().is_absolute()); - assert!(cuprate_config_dir().is_absolute()); - assert!(cuprate_data_dir().is_absolute()); - assert!(cuprate_blockchain_dir().is_absolute()); + assert!(CUPRATE_CACHE_DIR.is_absolute()); + assert!(CUPRATE_CONFIG_DIR.is_absolute()); + assert!(CUPRATE_DATA_DIR.is_absolute()); + assert!(CUPRATE_BLOCKCHAIN_DIR.is_absolute()); if cfg!(target_os = "windows") { - let dir = cuprate_cache_dir(); + let dir = &*CUPRATE_CACHE_DIR; println!("cuprate_cache_dir: {dir:?}"); assert!(dir.ends_with(r"AppData\Local\Cuprate")); - let dir = cuprate_config_dir(); + let dir = &*CUPRATE_CONFIG_DIR; println!("cuprate_config_dir: {dir:?}"); assert!(dir.ends_with(r"AppData\Roaming\Cuprate")); - let dir = cuprate_data_dir(); + let dir = &*CUPRATE_DATA_DIR; println!("cuprate_data_dir: {dir:?}"); assert!(dir.ends_with(r"AppData\Roaming\Cuprate")); - let dir = cuprate_blockchain_dir(); + let dir = &*CUPRATE_BLOCKCHAIN_DIR; println!("cuprate_blockchain_dir: {dir:?}"); assert!(dir.ends_with(r"AppData\Roaming\Cuprate\blockchain")); } else if cfg!(target_os = "macos") { - let dir = cuprate_cache_dir(); + let dir = &*CUPRATE_CACHE_DIR; println!("cuprate_cache_dir: {dir:?}"); assert!(dir.ends_with("Library/Caches/Cuprate")); - let dir = cuprate_config_dir(); + let dir = &*CUPRATE_CONFIG_DIR; println!("cuprate_config_dir: {dir:?}"); assert!(dir.ends_with("Library/Application Support/Cuprate")); - let dir = cuprate_data_dir(); + let dir = &*CUPRATE_DATA_DIR; println!("cuprate_data_dir: {dir:?}"); assert!(dir.ends_with("Library/Application Support/Cuprate")); - let dir = cuprate_blockchain_dir(); + let dir = &*CUPRATE_BLOCKCHAIN_DIR; println!("cuprate_blockchain_dir: {dir:?}"); assert!(dir.ends_with("Library/Application Support/Cuprate/blockchain")); } else { // Assumes Linux. - let dir = cuprate_cache_dir(); + let dir = &*CUPRATE_CACHE_DIR; println!("cuprate_cache_dir: {dir:?}"); assert!(dir.ends_with(".cache/cuprate")); - let dir = cuprate_config_dir(); + let dir = &*CUPRATE_CONFIG_DIR; println!("cuprate_config_dir: {dir:?}"); assert!(dir.ends_with(".config/cuprate")); - let dir = cuprate_data_dir(); + let dir = &*CUPRATE_DATA_DIR; println!("cuprate_data_dir: {dir:?}"); assert!(dir.ends_with(".local/share/cuprate")); - let dir = cuprate_blockchain_dir(); + let dir = &*CUPRATE_BLOCKCHAIN_DIR; println!("cuprate_blockchain_dir: {dir:?}"); assert!(dir.ends_with(".local/share/cuprate/blockchain")); } diff --git a/storage/blockchain/src/config/config.rs b/storage/blockchain/src/config/config.rs index 5bfbf74..957c67c 100644 --- a/storage/blockchain/src/config/config.rs +++ b/storage/blockchain/src/config/config.rs @@ -7,7 +7,7 @@ use std::{borrow::Cow, path::Path}; use serde::{Deserialize, Serialize}; use cuprate_database::{config::SyncMode, resize::ResizeAlgorithm}; -use cuprate_helper::fs::cuprate_blockchain_dir; +use cuprate_helper::fs::CUPRATE_BLOCKCHAIN_DIR; // re-exports pub use cuprate_database_service::ReaderThreads; @@ -38,7 +38,7 @@ impl ConfigBuilder { Self { db_directory: None, db_config: cuprate_database::config::ConfigBuilder::new(Cow::Borrowed( - cuprate_blockchain_dir(), + &*CUPRATE_BLOCKCHAIN_DIR, )), reader_threads: None, } @@ -48,7 +48,7 @@ impl ConfigBuilder { /// /// # Default values /// If [`ConfigBuilder::db_directory`] was not called, - /// the default [`cuprate_blockchain_dir`] will be used. + /// the default [`CUPRATE_BLOCKCHAIN_DIR`] will be used. /// /// For all other values, [`Default::default`] is used. pub fn build(self) -> Config { @@ -56,7 +56,7 @@ impl ConfigBuilder { // in `helper::fs`. No need to do them here. let db_directory = self .db_directory - .unwrap_or_else(|| Cow::Borrowed(cuprate_blockchain_dir())); + .unwrap_or_else(|| Cow::Borrowed(&*CUPRATE_BLOCKCHAIN_DIR)); let reader_threads = self.reader_threads.unwrap_or_default(); let db_config = self @@ -106,7 +106,7 @@ impl ConfigBuilder { #[must_use] pub fn fast(mut self) -> Self { self.db_config = - cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(cuprate_blockchain_dir())) + cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(&*CUPRATE_BLOCKCHAIN_DIR)) .fast(); self.reader_threads = Some(ReaderThreads::OnePerThread); @@ -120,7 +120,7 @@ impl ConfigBuilder { #[must_use] pub fn low_power(mut self) -> Self { self.db_config = - cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(cuprate_blockchain_dir())) + cuprate_database::config::ConfigBuilder::new(Cow::Borrowed(&*CUPRATE_BLOCKCHAIN_DIR)) .low_power(); self.reader_threads = Some(ReaderThreads::One); @@ -130,7 +130,7 @@ impl ConfigBuilder { impl Default for ConfigBuilder { fn default() -> Self { - let db_directory = Cow::Borrowed(cuprate_blockchain_dir()); + let db_directory = Cow::Borrowed(&**CUPRATE_BLOCKCHAIN_DIR); Self { db_directory: Some(db_directory.clone()), db_config: cuprate_database::config::ConfigBuilder::new(db_directory), @@ -161,7 +161,7 @@ impl Config { /// Create a new [`Config`] with sane default settings. /// /// The [`cuprate_database::config::Config::db_directory`] - /// will be set to [`cuprate_blockchain_dir`]. + /// will be set to [`CUPRATE_BLOCKCHAIN_DIR`]. /// /// All other values will be [`Default::default`]. /// @@ -179,8 +179,8 @@ impl Config { /// /// let config = Config::new(); /// - /// assert_eq!(config.db_config.db_directory(), cuprate_blockchain_dir()); - /// assert!(config.db_config.db_file().starts_with(cuprate_blockchain_dir())); + /// assert_eq!(config.db_config.db_directory(), &*CUPRATE_BLOCKCHAIN_DIR); + /// assert!(config.db_config.db_file().starts_with(&*CUPRATE_BLOCKCHAIN_DIR)); /// assert!(config.db_config.db_file().ends_with(DATABASE_DATA_FILENAME)); /// assert_eq!(config.db_config.sync_mode, SyncMode::default()); /// assert_eq!(config.db_config.resize_algorithm, ResizeAlgorithm::default()); diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index de955c8..4f77d73 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -268,7 +268,7 @@ mod test { use pretty_assertions::assert_eq; use cuprate_database::{Env, EnvInner, TxRw}; - use cuprate_test_utils::data::{block_v16_tx0, block_v1_tx2, block_v9_tx3}; + use cuprate_test_utils::data::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3}; use super::*; @@ -292,9 +292,9 @@ mod test { assert_all_tables_are_empty(&env); let mut blocks = [ - block_v1_tx2().clone(), - block_v9_tx3().clone(), - block_v16_tx0().clone(), + BLOCK_V1_TX2.clone(), + BLOCK_V9_TX3.clone(), + BLOCK_V16_TX0.clone(), ]; // HACK: `add_block()` asserts blocks with non-sequential heights // cannot be added, to get around this, manually edit the block height. @@ -440,7 +440,7 @@ mod test { let tx_rw = env_inner.tx_rw().unwrap(); let mut tables = env_inner.open_tables_mut(&tx_rw).unwrap(); - let mut block = block_v9_tx3().clone(); + let mut block = BLOCK_V9_TX3.clone(); block.height = usize::try_from(u32::MAX).unwrap() + 1; add_block(&block, &mut tables).unwrap(); @@ -459,7 +459,7 @@ mod test { let tx_rw = env_inner.tx_rw().unwrap(); let mut tables = env_inner.open_tables_mut(&tx_rw).unwrap(); - let mut block = block_v9_tx3().clone(); + let mut block = BLOCK_V9_TX3.clone(); // HACK: `add_block()` asserts blocks with non-sequential heights // cannot be added, to get around this, manually edit the block height. block.height = 0; diff --git a/storage/blockchain/src/ops/blockchain.rs b/storage/blockchain/src/ops/blockchain.rs index 65d9ca2..ed368ad 100644 --- a/storage/blockchain/src/ops/blockchain.rs +++ b/storage/blockchain/src/ops/blockchain.rs @@ -84,7 +84,7 @@ mod test { use pretty_assertions::assert_eq; use cuprate_database::{Env, EnvInner, TxRw}; - use cuprate_test_utils::data::{block_v16_tx0, block_v1_tx2, block_v9_tx3}; + use cuprate_test_utils::data::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3}; use super::*; @@ -108,9 +108,9 @@ mod test { assert_all_tables_are_empty(&env); let mut blocks = [ - block_v1_tx2().clone(), - block_v9_tx3().clone(), - block_v16_tx0().clone(), + BLOCK_V1_TX2.clone(), + BLOCK_V9_TX3.clone(), + BLOCK_V16_TX0.clone(), ]; let blocks_len = blocks.len(); diff --git a/storage/blockchain/src/ops/mod.rs b/storage/blockchain/src/ops/mod.rs index 2699fc8..4ff7dff 100644 --- a/storage/blockchain/src/ops/mod.rs +++ b/storage/blockchain/src/ops/mod.rs @@ -54,7 +54,7 @@ //! ```rust //! use hex_literal::hex; //! -//! use cuprate_test_utils::data::block_v16_tx0; +//! use cuprate_test_utils::data::BLOCK_V16_TX0; //! use cuprate_blockchain::{ //! cuprate_database::{ //! ConcreteEnv, @@ -83,7 +83,7 @@ //! let mut tables = env_inner.open_tables_mut(&tx_rw)?; //! //! // Write a block to the database. -//! let mut block = block_v16_tx0().clone(); +//! let mut block = BLOCK_V16_TX0.clone(); //! # block.height = 0; //! add_block(&block, &mut tables)?; //! diff --git a/storage/blockchain/src/ops/tx.rs b/storage/blockchain/src/ops/tx.rs index 7d608ca..e7dbdcf 100644 --- a/storage/blockchain/src/ops/tx.rs +++ b/storage/blockchain/src/ops/tx.rs @@ -322,7 +322,7 @@ mod test { use pretty_assertions::assert_eq; use cuprate_database::{Env, EnvInner, TxRw}; - use cuprate_test_utils::data::{tx_v1_sig0, tx_v1_sig2, tx_v2_rct3}; + use cuprate_test_utils::data::{TX_V1_SIG0, TX_V1_SIG2, TX_V2_RCT3}; use crate::{ tables::{OpenTables, Tables}, @@ -337,7 +337,7 @@ mod test { assert_all_tables_are_empty(&env); // Monero `Transaction`, not database tx. - let txs = [tx_v1_sig0(), tx_v1_sig2(), tx_v2_rct3()]; + let txs = [&*TX_V1_SIG0, &*TX_V1_SIG2, &*TX_V2_RCT3]; // Add transactions. let tx_ids = { diff --git a/storage/blockchain/src/service/mod.rs b/storage/blockchain/src/service/mod.rs index 3331a55..c774ee4 100644 --- a/storage/blockchain/src/service/mod.rs +++ b/storage/blockchain/src/service/mod.rs @@ -66,7 +66,7 @@ //! use tower::{Service, ServiceExt}; //! //! use cuprate_types::{blockchain::{BlockchainReadRequest, BlockchainWriteRequest, BlockchainResponse}, Chain}; -//! use cuprate_test_utils::data::block_v16_tx0; +//! use cuprate_test_utils::data::BLOCK_V16_TX0; //! //! use cuprate_blockchain::{ //! cuprate_database::Env, @@ -86,7 +86,7 @@ //! let (mut read_handle, mut write_handle, _) = cuprate_blockchain::service::init(config)?; //! //! // Prepare a request to write block. -//! let mut block = block_v16_tx0().clone(); +//! let mut block = BLOCK_V16_TX0.clone(); //! # block.height = 0_usize; // must be 0th height or panic in `add_block()` //! let request = BlockchainWriteRequest::WriteBlock(block); //! diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index 8d817bb..ed13f7b 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -16,7 +16,7 @@ use pretty_assertions::assert_eq; use tower::{Service, ServiceExt}; use cuprate_database::{ConcreteEnv, DatabaseIter, DatabaseRo, Env, EnvInner, RuntimeError}; -use cuprate_test_utils::data::{block_v16_tx0, block_v1_tx2, block_v9_tx3}; +use cuprate_test_utils::data::{BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse, BlockchainWriteRequest}, Chain, OutputOnChain, VerifiedBlockInformation, @@ -61,7 +61,7 @@ fn init_service() -> ( #[allow(clippy::future_not_send)] // INVARIANT: tests are using a single threaded runtime async fn test_template( // Which block(s) to add? - block_fns: &[fn() -> &'static VerifiedBlockInformation], + blocks: &[&VerifiedBlockInformation], // Total amount of generated coins after the block(s) have been added. cumulative_generated_coins: u64, // What are the table lengths be after the block(s) have been added? @@ -76,8 +76,8 @@ async fn test_template( // HACK: `add_block()` asserts blocks with non-sequential heights // cannot be added, to get around this, manually edit the block height. - for (i, block_fn) in block_fns.iter().enumerate() { - let mut block = block_fn().clone(); + for (i, block) in blocks.iter().enumerate() { + let mut block = (*block).clone(); block.height = i; // Request a block to be written, assert it was written. @@ -104,7 +104,7 @@ async fn test_template( get_block_extended_header_from_height(&0, &tables).unwrap(), )); - let extended_block_header_1 = if block_fns.len() > 1 { + let extended_block_header_1 = if blocks.len() > 1 { Ok(BlockchainResponse::BlockExtendedHeader( get_block_extended_header_from_height(&1, &tables).unwrap(), )) @@ -116,7 +116,7 @@ async fn test_template( get_block_info(&0, tables.block_infos()).unwrap().block_hash, )); - let block_hash_1 = if block_fns.len() > 1 { + let block_hash_1 = if blocks.len() > 1 { Ok(BlockchainResponse::BlockHash( get_block_info(&1, tables.block_infos()).unwrap().block_hash, )) @@ -128,7 +128,7 @@ async fn test_template( get_block_extended_header_from_height(&0, &tables).unwrap(), ])); - let range_0_2 = if block_fns.len() >= 2 { + let range_0_2 = if blocks.len() >= 2 { Ok(BlockchainResponse::BlockExtendedHeaderInRange(vec![ get_block_extended_header_from_height(&0, &tables).unwrap(), get_block_extended_header_from_height(&1, &tables).unwrap(), @@ -333,7 +333,7 @@ fn init_drop() { #[tokio::test] async fn v1_tx2() { test_template( - &[block_v1_tx2], + &[&*BLOCK_V1_TX2], 14_535_350_982_449, AssertTableLen { block_infos: 1, @@ -359,7 +359,7 @@ async fn v1_tx2() { #[tokio::test] async fn v9_tx3() { test_template( - &[block_v9_tx3], + &[&*BLOCK_V9_TX3], 3_403_774_022_163, AssertTableLen { block_infos: 1, @@ -385,7 +385,7 @@ async fn v9_tx3() { #[tokio::test] async fn v16_tx0() { test_template( - &[block_v16_tx0], + &[&*BLOCK_V16_TX0], 600_000_000_000, AssertTableLen { block_infos: 1, diff --git a/storage/database/src/backend/tests.rs b/storage/database/src/backend/tests.rs index ac6b592..e219c42 100644 --- a/storage/database/src/backend/tests.rs +++ b/storage/database/src/backend/tests.rs @@ -126,7 +126,7 @@ fn resize() { let (env, _tempdir) = tmp_concrete_env(); // Resize by the OS page size. - let page_size = crate::resize::page_size(); + let page_size = *crate::resize::PAGE_SIZE; let old_size = env.current_map_size(); env.resize_map(Some(ResizeAlgorithm::FixedBytes(page_size))); diff --git a/storage/database/src/resize.rs b/storage/database/src/resize.rs index 99d6d7e..6ef9974 100644 --- a/storage/database/src/resize.rs +++ b/storage/database/src/resize.rs @@ -10,7 +10,7 @@ //! //! # Page size //! All free functions in this module will -//! return a multiple of the OS page size ([`page_size()`]), +//! return a multiple of the OS page size ([`PAGE_SIZE`]), //! [LMDB will error](http://www.lmdb.tech/doc/group__mdb.html#gaa2506ec8dab3d969b0e609cd82e619e5) //! if this is not the case. //! @@ -18,10 +18,10 @@ //! All returned [`NonZeroUsize`] values of the free functions in this module //! (including [`ResizeAlgorithm::resize`]) uphold the following invariants: //! 1. It will always be `>=` the input `current_size_bytes` -//! 2. It will always be a multiple of [`page_size()`] +//! 2. It will always be a multiple of [`PAGE_SIZE`] //---------------------------------------------------------------------------------------------------- Import -use std::{num::NonZeroUsize, sync::OnceLock}; +use std::{num::NonZeroUsize, sync::LazyLock}; //---------------------------------------------------------------------------------------------------- ResizeAlgorithm /// The function/algorithm used by the @@ -85,21 +85,14 @@ impl Default for ResizeAlgorithm { } //---------------------------------------------------------------------------------------------------- Free functions -/// This function retrieves the system’s memory page size. +/// This retrieves the system’s memory page size. /// /// It is just [`page_size::get`](https://docs.rs/page_size) internally. /// -/// This caches the result, so this function is cheap after the 1st call. -/// /// # Panics -/// This function will panic if the OS returns of page size of `0` (impossible?). -#[inline] -pub fn page_size() -> NonZeroUsize { - /// Cached result of [`page_size()`]. - static PAGE_SIZE: OnceLock = OnceLock::new(); - *PAGE_SIZE - .get_or_init(|| NonZeroUsize::new(page_size::get()).expect("page_size::get() returned 0")) -} +/// Accessing this [`LazyLock`] will panic if the OS returns of page size of `0` (impossible?). +pub static PAGE_SIZE: LazyLock = + LazyLock::new(|| NonZeroUsize::new(page_size::get()).expect("page_size::get() returned 0")); /// Memory map resize closely matching `monerod`. /// @@ -122,7 +115,7 @@ pub fn page_size() -> NonZeroUsize { /// assert_eq!(monero(0).get(), N); /// /// // Rounds up to nearest OS page size. -/// assert_eq!(monero(1).get(), N + page_size().get()); +/// assert_eq!(monero(1).get(), N + PAGE_SIZE.get()); /// ``` /// /// # Panics @@ -143,7 +136,7 @@ pub fn monero(current_size_bytes: usize) -> NonZeroUsize { /// const ADD_SIZE: usize = 1_usize << 30; - let page_size = page_size().get(); + let page_size = PAGE_SIZE.get(); let new_size_bytes = current_size_bytes + ADD_SIZE; // Round up the new size to the @@ -167,7 +160,7 @@ pub fn monero(current_size_bytes: usize) -> NonZeroUsize { /// /// ```rust /// # use cuprate_database::resize::*; -/// let page_size: usize = page_size().get(); +/// let page_size: usize = PAGE_SIZE.get(); /// /// // Anything below the page size will round up to the page size. /// for i in 0..=page_size { @@ -190,7 +183,7 @@ pub fn monero(current_size_bytes: usize) -> NonZeroUsize { /// fixed_bytes(1, usize::MAX); /// ``` pub fn fixed_bytes(current_size_bytes: usize, add_bytes: usize) -> NonZeroUsize { - let page_size = page_size(); + let page_size = *PAGE_SIZE; let new_size_bytes = current_size_bytes + add_bytes; // Guard against < page_size. @@ -222,7 +215,7 @@ pub fn fixed_bytes(current_size_bytes: usize, add_bytes: usize) -> NonZeroUsize /// /// ```rust /// # use cuprate_database::resize::*; -/// let page_size: usize = page_size().get(); +/// let page_size: usize = PAGE_SIZE.get(); /// /// // Anything below the page size will round up to the page size. /// for i in 0..=page_size { @@ -265,7 +258,7 @@ pub fn percent(current_size_bytes: usize, percent: f32) -> NonZeroUsize { _ => 1.0, }; - let page_size = page_size(); + let page_size = *PAGE_SIZE; // INVARIANT: Allow `f32` <-> `usize` casting, we handle all cases. #[allow( diff --git a/test-utils/src/data/mod.rs b/test-utils/src/data/mod.rs index 696c686..b9d42fb 100644 --- a/test-utils/src/data/mod.rs +++ b/test-utils/src/data/mod.rs @@ -15,14 +15,14 @@ //! let tx: Transaction = Transaction::read(&mut TX_E57440).unwrap(); //! ``` //! -//! ## Functions -//! The free functions provide access to typed data found in `cuprate_types`: +//! ## Statics +//! The statics provide access to typed data found in `cuprate_types`: //! ```rust //! # use cuprate_test_utils::data::*; //! use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; //! -//! let block: VerifiedBlockInformation = block_v16_tx0().clone(); -//! let tx: VerifiedTransactionInformation = tx_v1_sig0().clone(); +//! let block: VerifiedBlockInformation = BLOCK_V16_TX0.clone(); +//! let tx: VerifiedTransactionInformation = TX_V1_SIG0.clone(); //! ``` mod constants; @@ -31,7 +31,7 @@ pub use constants::{ TX_9E3F73, TX_B6B439, TX_D7FEBD, TX_E2D393, TX_E57440, }; -mod free; -pub use free::{ - block_v16_tx0, block_v1_tx2, block_v9_tx3, tx_fee, tx_v1_sig0, tx_v1_sig2, tx_v2_rct3, +mod statics; +pub use statics::{ + tx_fee, BLOCK_V16_TX0, BLOCK_V1_TX2, BLOCK_V9_TX3, TX_V1_SIG0, TX_V1_SIG2, TX_V2_RCT3, }; diff --git a/test-utils/src/data/free.rs b/test-utils/src/data/statics.rs similarity index 82% rename from test-utils/src/data/free.rs rename to test-utils/src/data/statics.rs index d7f61ae..8b98171 100644 --- a/test-utils/src/data/free.rs +++ b/test-utils/src/data/statics.rs @@ -1,4 +1,4 @@ -//! Free functions to access data. +//! `static LazyLock`s to access data. #![allow( const_item_mutation, // `R: Read` needs `&mut self` @@ -6,7 +6,7 @@ )] //---------------------------------------------------------------------------------------------------- Import -use std::sync::OnceLock; +use std::sync::LazyLock; use cuprate_helper::map::combine_low_high_bits_to_u128; use cuprate_types::{VerifiedBlockInformation, VerifiedTransactionInformation}; @@ -141,8 +141,7 @@ pub fn tx_fee(tx: &Transaction) -> u64 { } //---------------------------------------------------------------------------------------------------- Blocks -/// Generate a block accessor function with this signature: -/// `fn() -> &'static VerifiedBlockInformation` +/// Generate a `static LazyLock`. /// /// This will use `VerifiedBlockMap` type above to do various /// checks on the input data and makes sure it seems correct. @@ -153,9 +152,9 @@ pub fn tx_fee(tx: &Transaction) -> u64 { /// - Monero RPC (see cuprate_test_utils::rpc for this) /// /// See below for actual usage. -macro_rules! verified_block_information_fn { +macro_rules! verified_block_information { ( - fn_name: $fn_name:ident, // Name of the function created + name: $name:ident, // Name of the `LazyLock` created block_blob: $block_blob:ident, // Block blob ([u8], found in `constants.rs`) tx_blobs: [$($tx_blob:ident),*], // Array of contained transaction blobs pow_hash: $pow_hash:literal, // PoW hash as a string literal @@ -183,7 +182,7 @@ macro_rules! verified_block_information_fn { #[doc = "# use hex_literal::hex;"] #[doc = "use cuprate_helper::map::combine_low_high_bits_to_u128;"] #[doc = ""] - #[doc = concat!("let block = ", stringify!($fn_name), "();")] + #[doc = concat!("let block = &*", stringify!($name), ";")] #[doc = concat!("assert_eq!(&block.block.serialize(), ", stringify!($block_blob), ");")] #[doc = concat!("assert_eq!(block.pow_hash, hex!(\"", $pow_hash, "\"));")] #[doc = concat!("assert_eq!(block.height, ", $height, ");")] @@ -201,28 +200,25 @@ macro_rules! verified_block_information_fn { "));" )] /// ``` - pub fn $fn_name() -> &'static VerifiedBlockInformation { - static BLOCK: OnceLock = OnceLock::new(); - BLOCK.get_or_init(|| { - VerifiedBlockMap { - block_blob: $block_blob, - pow_hash: hex!($pow_hash), - height: $height, - generated_coins: $generated_coins, - weight: $weight, - long_term_weight: $long_term_weight, - cumulative_difficulty_low: $cumulative_difficulty_low, - cumulative_difficulty_high: $cumulative_difficulty_high, - txs: &[$($tx_blob),*], - } - .into_verified() - }) - } + pub static $name: LazyLock = LazyLock::new(|| { + VerifiedBlockMap { + block_blob: $block_blob, + pow_hash: hex!($pow_hash), + height: $height, + generated_coins: $generated_coins, + weight: $weight, + long_term_weight: $long_term_weight, + cumulative_difficulty_low: $cumulative_difficulty_low, + cumulative_difficulty_high: $cumulative_difficulty_high, + txs: &[$($tx_blob),*], + } + .into_verified() + }); }; } -verified_block_information_fn! { - fn_name: block_v1_tx2, +verified_block_information! { + name: BLOCK_V1_TX2, block_blob: BLOCK_5ECB7E, tx_blobs: [TX_2180A8, TX_D7FEBD], pow_hash: "c960d540000459480560b7816de968c7470083e5874e10040bdd4cc501000000", @@ -235,8 +231,8 @@ verified_block_information_fn! { tx_len: 2, } -verified_block_information_fn! { - fn_name: block_v9_tx3, +verified_block_information! { + name: BLOCK_V9_TX3, block_blob: BLOCK_F91043, tx_blobs: [TX_E2D393, TX_E57440, TX_B6B439], pow_hash: "7c78b5b67a112a66ea69ea51477492057dba9cfeaa2942ee7372c61800000000", @@ -249,8 +245,8 @@ verified_block_information_fn! { tx_len: 3, } -verified_block_information_fn! { - fn_name: block_v16_tx0, +verified_block_information! { + name: BLOCK_V16_TX0, block_blob: BLOCK_43BD1F, tx_blobs: [], pow_hash: "10b473b5d097d6bfa0656616951840724dfe38c6fb9c4adf8158800300000000", @@ -264,13 +260,12 @@ verified_block_information_fn! { } //---------------------------------------------------------------------------------------------------- Transactions -/// Generate a transaction accessor function with this signature: -/// `fn() -> &'static VerifiedTransactionInformation` +/// Generate a `const LazyLock`. /// -/// Same as [`verified_block_information_fn`] but for transactions. -macro_rules! transaction_verification_data_fn { +/// Same as [`verified_block_information`] but for transactions. +macro_rules! transaction_verification_data { ( - fn_name: $fn_name:ident, // Name of the function created + name: $name:ident, // Name of the `LazyLock` created tx_blobs: $tx_blob:ident, // Transaction blob ([u8], found in `constants.rs`) weight: $weight:literal, // Transaction weight hash: $hash:literal, // Transaction hash as a string literal @@ -280,35 +275,34 @@ macro_rules! transaction_verification_data_fn { /// ```rust #[doc = "# use cuprate_test_utils::data::*;"] #[doc = "# use hex_literal::hex;"] - #[doc = concat!("let tx = ", stringify!($fn_name), "();")] + #[doc = concat!("let tx = &*", stringify!($name), ";")] #[doc = concat!("assert_eq!(&tx.tx.serialize(), ", stringify!($tx_blob), ");")] #[doc = concat!("assert_eq!(tx.tx_blob, ", stringify!($tx_blob), ");")] #[doc = concat!("assert_eq!(tx.tx_weight, ", $weight, ");")] #[doc = concat!("assert_eq!(tx.tx_hash, hex!(\"", $hash, "\"));")] /// ``` - pub fn $fn_name() -> &'static VerifiedTransactionInformation { - static TX: OnceLock = OnceLock::new(); - TX.get_or_init(|| to_tx_verification_data($tx_blob)) - } + pub static $name: LazyLock = LazyLock::new(|| { + to_tx_verification_data($tx_blob) + }); }; } -transaction_verification_data_fn! { - fn_name: tx_v1_sig0, +transaction_verification_data! { + name: TX_V1_SIG0, tx_blobs: TX_3BC7FF, weight: 248, hash: "3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1", } -transaction_verification_data_fn! { - fn_name: tx_v1_sig2, +transaction_verification_data! { + name: TX_V1_SIG2, tx_blobs: TX_9E3F73, weight: 448, hash: "9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34", } -transaction_verification_data_fn! { - fn_name: tx_v2_rct3, +transaction_verification_data! { + name: TX_V2_RCT3, tx_blobs: TX_84D48D, weight: 2743, hash: "84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66", @@ -328,7 +322,7 @@ mod tests { #[tokio::test] async fn block_same_as_rpc() { let rpc = HttpRpcClient::new(None).await; - for block in [block_v1_tx2(), block_v9_tx3(), block_v16_tx0()] { + for block in [&*BLOCK_V1_TX2, &*BLOCK_V9_TX3, &*BLOCK_V16_TX0] { println!("block_height: {}", block.height); let block_rpc = rpc.get_verified_block_information(block.height).await; assert_eq!(block, &block_rpc); @@ -342,16 +336,12 @@ mod tests { async fn tx_same_as_rpc() { let rpc = HttpRpcClient::new(None).await; - let mut txs = [block_v1_tx2(), block_v9_tx3(), block_v16_tx0()] + let mut txs = [&*BLOCK_V1_TX2, &*BLOCK_V9_TX3, &*BLOCK_V16_TX0] .into_iter() .flat_map(|block| block.txs.iter().cloned()) .collect::>(); - txs.extend([ - tx_v1_sig0().clone(), - tx_v1_sig2().clone(), - tx_v2_rct3().clone(), - ]); + txs.extend([TX_V1_SIG0.clone(), TX_V1_SIG2.clone(), TX_V2_RCT3.clone()]); for tx in txs { println!("tx_hash: {:?}", tx.tx_hash);