Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 25 additions & 34 deletions consensus/rules/src/decomposed_amount.rs
Original file line number Diff line number Diff line change
@@ -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.
///
Expand All @@ -40,7 +31,7 @@ pub fn decomposed_amounts() -> &'static [u64; 172] {
/// ref: <https://monero-book.cuprate.org/consensus_rules/blocks/miner_tx.html#output-amounts>
#[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)]
Expand All @@ -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))
}
}
Expand Down
4 changes: 2 additions & 2 deletions consensus/rules/src/transactions/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}

Expand Down
143 changes: 64 additions & 79 deletions helper/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
//!
Expand All @@ -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"
//! );
//! # }
Expand All @@ -28,10 +28,7 @@
//! - <https://docs.rs/dirs>

//---------------------------------------------------------------------------------------------------- Use
use std::{
path::{Path, PathBuf},
sync::OnceLock,
};
use std::{path::PathBuf, sync::LazyLock};

//---------------------------------------------------------------------------------------------------- Const
/// Cuprate's main directory.
Expand Down Expand Up @@ -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.
/// <https://github.com/rust-lang/rust/issues/109736>.
/// <https://doc.rust-lang.org/std/sync/struct.LazyLock.html>.
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<PathBuf> = OnceLock::new();

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"
);

// 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);

// Add any sub directories if specified in the macro.
if !$sub_dirs.is_empty() {
path.push($sub_dirs);
}

path
})
}
pub static $name: LazyLock<PathBuf> = 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();

// 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");

// 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);
}

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.
Expand All @@ -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,
"",

Expand All @@ -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,
"",

Expand All @@ -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,
"",

Expand All @@ -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",
}
Expand All @@ -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"));
}
Expand Down
Loading
Loading