diff --git a/Cargo.lock b/Cargo.lock index 31aed82..e640e27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -604,7 +604,9 @@ name = "cuprate-constants" version = "0.1.0" dependencies = [ "hex", + "hex-literal", "monero-serai", + "paste", "pretty_assertions", ] diff --git a/constants/Cargo.toml b/constants/Cargo.toml index abc43e9..d11f8c9 100644 --- a/constants/Cargo.toml +++ b/constants/Cargo.toml @@ -14,6 +14,8 @@ monero-serai = ["dep:monero-serai"] [dependencies] monero-serai = { workspace = true, optional = true } +hex-literal = { workspace = true } +paste = { workspace = true } [dev-dependencies] monero-serai = { workspace = true } diff --git a/constants/README.md b/constants/README.md index de31e07..8550ba7 100644 --- a/constants/README.md +++ b/constants/README.md @@ -1,6 +1,6 @@ # cuprate-constants This crate contains general constants that are not specific to any particular -part of the codebase yet are used in multiple places such as the [`MAXIMUM_BLOCK_HEIGHT`]. +part of the codebase yet are used in multiple places such as the [`crate::block::MAX_BLOCK_HEIGHT`]. ## Static data -This crate also contains `static` data used in multiple places such as the [`GENESIS_BLOCK`]. +This crate also contains `static` data used in multiple places such as the [`crate::genesis::mainnet::GENESIS_BLOCK`]. diff --git a/constants/src/genesis.rs b/constants/src/genesis.rs index 420cc04..5f7a945 100644 --- a/constants/src/genesis.rs +++ b/constants/src/genesis.rs @@ -2,106 +2,180 @@ #![expect(const_item_mutation, reason = "&mut is needed for `Read`")] -#[cfg(feature = "monero-serai")] -use monero_serai::{block::Block, transaction::Transaction}; -#[cfg(feature = "monero-serai")] -use std::sync::LazyLock; +/// Generate genesis block/transaction data and tests for multiple networks. +/// +/// Input string literals are in hexadecimal form. +macro_rules! generate_genesis_consts { + ($( + $network:ident { + nonce: $nonce:literal, + block: $block:literal, + block_hash: $block_hash:literal, + tx: $tx:literal, + tx_hash: $tx_hash:literal, + } + )*) => { paste::paste! { + $( + #[doc = concat!(stringify!([<$network:camel>]), " data.")] + pub mod [<$network:lower>] { + #[cfg(feature = "monero-serai")] + use monero_serai::{block::Block, transaction::Transaction}; + #[cfg(feature = "monero-serai")] + use std::sync::LazyLock; -/// The genesis block in [`Block`] form. -#[cfg(feature = "monero-serai")] -pub static GENESIS_BLOCK: LazyLock = - LazyLock::new(|| Block::read(&mut GENESIS_BLOCK_BYTES).unwrap()); + #[doc = concat!("The ", stringify!([<$network:lower>]), " genesis block in [`Block`] form.")] + #[cfg(feature = "monero-serai")] + pub static GENESIS_BLOCK: LazyLock = + LazyLock::new(|| Block::read(&mut GENESIS_BLOCK_BYTES).unwrap()); -/// The genesis block in hexadecimal form. -pub const GENESIS_BLOCK_HEX: &str = "010000000000000000000000000000000000000000000000000000000000000000000010270000013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d100"; + #[doc = concat!("The ", stringify!([<$network:lower>]), " genesis block in hexadecimal form.")] + pub const GENESIS_BLOCK_HEX: &str = $block; -/// The genesis block in byte form. -pub const GENESIS_BLOCK_BYTES: &[u8] = &[ - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 16, 39, 0, 0, 1, 60, 1, 255, 0, 1, 255, 255, 255, 255, 255, 255, 3, 2, 155, 46, 76, 2, - 129, 192, 176, 46, 124, 83, 41, 26, 148, 209, 208, 203, 255, 136, 131, 248, 2, 79, 81, 66, 238, - 73, 79, 251, 189, 8, 128, 113, 33, 1, 119, 103, 170, 252, 222, 155, 224, 13, 207, 208, 152, - 113, 94, 188, 247, 244, 16, 218, 235, 197, 130, 253, 166, 157, 36, 162, 142, 157, 11, 200, 144, - 209, 0, -]; + #[doc = concat!("The ", stringify!([<$network:lower>]), " genesis block in byte form.")] + pub const GENESIS_BLOCK_BYTES: &[u8] = &hex_literal::hex!($block); -/// The hash of the genesis block in hexadecimal form. -pub const GENESIS_BLOCK_HASH_HEX: &str = - "418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3"; + #[doc = concat!("The hash of the ", stringify!([<$network:lower>]), " genesis block in hexadecimal form.")] + pub const GENESIS_BLOCK_HASH_HEX: &str = $block_hash; -/// The hash of the genesis block in byte form. -pub const GENESIS_BLOCK_HASH_BYTES: [u8; 32] = [ - 65, 128, 21, 187, 154, 233, 130, 161, 151, 93, 167, 215, 146, 119, 194, 112, 87, 39, 165, 104, - 148, 186, 15, 178, 70, 173, 170, 187, 31, 70, 50, 227, -]; + #[doc = concat!("The hash of the ", stringify!([<$network:lower>]), " genesis block in byte form.")] + pub const GENESIS_BLOCK_HASH_BYTES: [u8; 32] = hex_literal::hex!($block_hash); -/// The genesis block in [`Transaction`] form. -#[cfg(feature = "monero-serai")] -pub static GENESIS_TX: LazyLock = - LazyLock::new(|| Transaction::read(&mut GENESIS_TX_BYTES).unwrap()); + #[doc = concat!("The ", stringify!([<$network:lower>]), " genesis block in [`Transaction`] form.")] + #[cfg(feature = "monero-serai")] + pub static GENESIS_TX: LazyLock = + LazyLock::new(|| Transaction::read(&mut GENESIS_TX_BYTES).unwrap()); -/// The genesis transaction in hexadecimal form. -pub const GENESIS_TX_HEX: &str = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"; + #[doc = concat!("The ", stringify!([<$network:lower>]), " genesis transaction in hexadecimal form.")] + pub const GENESIS_TX_HEX: &str = $tx; -/// The genesis transaction in byte form. -pub const GENESIS_TX_BYTES: &[u8] = &[ - 1, 60, 1, 255, 0, 1, 255, 255, 255, 255, 255, 255, 3, 2, 155, 46, 76, 2, 129, 192, 176, 46, - 124, 83, 41, 26, 148, 209, 208, 203, 255, 136, 131, 248, 2, 79, 81, 66, 238, 73, 79, 251, 189, - 8, 128, 113, 33, 1, 119, 103, 170, 252, 222, 155, 224, 13, 207, 208, 152, 113, 94, 188, 247, - 244, 16, 218, 235, 197, 130, 253, 166, 157, 36, 162, 142, 157, 11, 200, 144, 209, -]; + #[doc = concat!("The ", stringify!([<$network:lower>]), " genesis transaction in byte form.")] + pub const GENESIS_TX_BYTES: &[u8] = &hex_literal::hex!($tx); -/// The hash of the genesis transaction in hexadecimal form. -pub const GENESIS_TX_HASH_HEX: &str = - "c88ce9783b4f11190d7b9c17a69c1c52200f9faaee8e98dd07e6811175177139"; + #[doc = concat!("The hash of the ", stringify!([<$network:lower>]), " genesis transaction in hexadecimal form.")] + pub const GENESIS_TX_HASH_HEX: &str = $tx_hash; -/// The hash of the genesis transaction in byte form. -pub const GENESIS_TX_HASH_BYTES: [u8; 32] = [ - 200, 140, 233, 120, 59, 79, 17, 25, 13, 123, 156, 23, 166, 156, 28, 82, 32, 15, 159, 170, 238, - 142, 152, 221, 7, 230, 129, 17, 117, 23, 113, 57, -]; + #[doc = concat!("The hash of the ", stringify!([<$network:lower>]), " genesis transaction in byte form.")] + pub const GENESIS_TX_HASH_BYTES: [u8; 32] = hex_literal::hex!($tx_hash); -#[cfg(test)] -mod test { - use monero_serai::{block::Block, transaction::Transaction}; - use pretty_assertions::assert_eq; + #[doc = concat!("The nonce of the ", stringify!([<$network:lower>]), " genesis block.")] + pub const GENESIS_NONCE: u32 = $nonce; - use super::*; + // Generate tests for all input networks. + #[cfg(test)] + mod test { + use monero_serai::{block::Block, transaction::Transaction}; + use pretty_assertions::assert_eq; - #[test] - fn genesis_block() { - assert_eq!(hex::decode(GENESIS_BLOCK_HEX).unwrap(), GENESIS_BLOCK_BYTES); - assert_eq!(GENESIS_BLOCK_HEX, hex::encode(GENESIS_BLOCK_BYTES)); + use super::*; - assert_eq!( - hex::decode(GENESIS_BLOCK_HASH_HEX).unwrap(), - GENESIS_BLOCK_HASH_BYTES - ); - assert_eq!( - GENESIS_BLOCK_HASH_HEX, - hex::encode(GENESIS_BLOCK_HASH_BYTES) - ); + #[test] + /// Assert the block bytes/hash are correct. + fn genesis_block() { + let block = Block::read(&mut GENESIS_BLOCK_BYTES).unwrap(); + assert_eq!(block.serialize(), &*GENESIS_BLOCK_BYTES); + assert_eq!(block.hash(), GENESIS_BLOCK_HASH_BYTES); + assert_eq!(block.hash(), GENESIS_BLOCK.hash()); + assert_eq!(&block, &*GENESIS_BLOCK); + } - let block = Block::read(&mut GENESIS_BLOCK_BYTES).unwrap(); - assert_eq!(block.hash(), GENESIS_BLOCK_HASH_BYTES); - assert_eq!(block.hash(), GENESIS_BLOCK.hash()); - assert_eq!(&block, &*GENESIS_BLOCK); + #[test] + /// Assert the genesis transaction in the block is correct. + fn genesis_block_tx() { + let block = Block::read(&mut GENESIS_BLOCK_BYTES).unwrap(); + assert_eq!(block.miner_transaction.serialize(), &*GENESIS_TX_BYTES); + assert_eq!(block.miner_transaction.hash(), GENESIS_TX_HASH_BYTES); + assert_eq!(block.miner_transaction.hash(), GENESIS_BLOCK.miner_transaction.hash()); + assert_eq!(&block.miner_transaction, &GENESIS_BLOCK.miner_transaction); + } + + #[test] + /// Assert the hex is the same as the bytes. + fn genesis_block_hex_same_as_bytes() { + assert_eq!( + hex::decode(GENESIS_BLOCK_HEX).unwrap(), + GENESIS_BLOCK_BYTES + ); + assert_eq!( + GENESIS_BLOCK_HEX, + hex::encode(GENESIS_BLOCK_BYTES) + ); + } + + #[test] + /// Assert the hash hex is the same as the bytes. + fn genesis_block_hash_hex_same_as_bytes() { + assert_eq!( + hex::decode(GENESIS_BLOCK_HASH_HEX).unwrap(), + GENESIS_BLOCK_HASH_BYTES + ); + assert_eq!( + GENESIS_BLOCK_HASH_HEX, + hex::encode(GENESIS_BLOCK_HASH_BYTES) + ); + } + + #[test] + /// Assert the transaction bytes/hash are correct. + fn genesis_tx() { + let tx = Transaction::read(&mut GENESIS_TX_BYTES).unwrap(); + assert_eq!(tx.hash(), GENESIS_TX_HASH_BYTES); + assert_eq!(tx.hash(), GENESIS_TX.hash()); + assert_eq!(&tx, &*GENESIS_TX); + } + + #[test] + /// Assert the hex is the same as the bytes. + fn genesis_tx_hex_same_as_bytes() { + assert_eq!( + hex::decode(GENESIS_TX_HEX).unwrap(), + GENESIS_TX_BYTES + ); + assert_eq!( + GENESIS_TX_HEX, + hex::encode(GENESIS_TX_BYTES) + ); + } + + #[test] + /// Assert the hash hex is the same as the bytes. + fn genesis_tx_hash_hex_same_as_bytes() { + assert_eq!( + hex::decode(GENESIS_TX_HASH_HEX).unwrap(), + GENESIS_TX_HASH_BYTES + ); + assert_eq!( + GENESIS_TX_HASH_HEX, + hex::encode(GENESIS_TX_HASH_BYTES) + ); + } + } + } + )* + }}; +} + +generate_genesis_consts! { + Mainnet { + nonce: 10000, + block: "010000000000000000000000000000000000000000000000000000000000000000000010270000013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d100", + block_hash: "418015bb9ae982a1975da7d79277c2705727a56894ba0fb246adaabb1f4632e3", + tx: "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1", + tx_hash: "c88ce9783b4f11190d7b9c17a69c1c52200f9faaee8e98dd07e6811175177139", } - #[test] - fn genesis_tx() { - assert_eq!(hex::decode(GENESIS_TX_HEX).unwrap(), GENESIS_TX_BYTES); - assert_eq!(GENESIS_TX_HEX, hex::encode(GENESIS_TX_BYTES)); + Testnet { + nonce: 10001, + block: "010000000000000000000000000000000000000000000000000000000000000000000011270000013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d100", + block_hash: "48ca7cd3c8de5b6a4d53d2861fbdaedca141553559f9be9520068053cda8430b", + tx: "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1", + tx_hash: "c88ce9783b4f11190d7b9c17a69c1c52200f9faaee8e98dd07e6811175177139", + } - assert_eq!( - hex::decode(GENESIS_TX_HASH_HEX).unwrap(), - GENESIS_TX_HASH_BYTES - ); - assert_eq!(GENESIS_TX_HASH_HEX, hex::encode(GENESIS_TX_HASH_BYTES)); - - let tx = Transaction::read(&mut GENESIS_TX_BYTES).unwrap(); - assert_eq!(tx.hash(), GENESIS_TX_HASH_BYTES); - assert_eq!(tx.hash(), GENESIS_TX.hash()); - assert_eq!(&tx, &*GENESIS_TX); + Stagenet { + nonce: 10002, + block: "010000000000000000000000000000000000000000000000000000000000000000000012270000013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b00", + block_hash: "76ee3cc98646292206cd3e86f74d88b4dcc1d937088645e9b0cbca84b7ce74eb", + tx: "013c01ff0001ffffffffffff0302df5d56da0c7d643ddd1ce61901c7bdc5fb1738bfe39fbe69c28a3a7032729c0f2101168d0c4ca86fb55a4cf6a36d31431be1c53a3bd7411bb24e8832410289fa6f3b", + tx_hash: "c099809301da6ad2fde11969b0e9cb291fc698f8dc678cef00506e7baf561de4", } } diff --git a/types/src/block_complete_entry.rs b/types/src/block_complete_entry.rs index ba5fc2b..316ad65 100644 --- a/types/src/block_complete_entry.rs +++ b/types/src/block_complete_entry.rs @@ -1,7 +1,7 @@ //! Contains [`BlockCompleteEntry`] and the related types. //---------------------------------------------------------------------------------------------------- Import -#[cfg(feature = "epee")] +// #[cfg(feature = "epee")] use bytes::Bytes; #[cfg(feature = "serde")]