mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 19:49:28 +00:00
test-utils: return &'static
verified superset types (#108)
* data: return `&'static` verified superset types * docs * fix VerifiedBlockMap, use manual input, add block 5da0a3d * free: use macros to generate accessor functions * constants: use macro * docs * `tx_data` -> `tx_blob`
This commit is contained in:
parent
ad7b750d76
commit
fe2366c5df
14 changed files with 480 additions and 220 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -633,8 +633,10 @@ dependencies = [
|
|||
"borsh",
|
||||
"bytes",
|
||||
"bzip2",
|
||||
"cuprate-types",
|
||||
"futures",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"monero-p2p",
|
||||
"monero-serai",
|
||||
"monero-wire",
|
||||
|
|
|
@ -8,6 +8,7 @@ authors = ["Boog900"]
|
|||
[dependencies]
|
||||
monero-wire = { path = "../net/monero-wire"}
|
||||
monero-p2p = { path = "../p2p/monero-p2p", features = ["borsh"] }
|
||||
cuprate-types = { path = "../types" }
|
||||
|
||||
monero-serai = { workspace = true }
|
||||
futures = { workspace = true, features = ["std"] }
|
||||
|
@ -17,6 +18,7 @@ tokio-util = { workspace = true }
|
|||
reqwest = { workspace = true }
|
||||
bytes = { workspace = true, features = ["std"] }
|
||||
tempfile = { workspace = true }
|
||||
hex-literal = { workspace = true }
|
||||
|
||||
borsh = { workspace = true, features = ["derive"]}
|
||||
|
||||
|
|
|
@ -6,3 +6,4 @@ Cuprate crate, only in tests.
|
|||
It currently contains:
|
||||
- Code to spawn monerod instances and a testing network zone
|
||||
- Real raw and typed Monero data, e.g. `Block, Transaction`
|
||||
- An RPC client to generate types from `cuprate_types`
|
Binary file not shown.
Binary file not shown.
|
@ -3,147 +3,223 @@
|
|||
//---------------------------------------------------------------------------------------------------- Import
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Block
|
||||
/// Block with height `202612` and hash `bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698`.
|
||||
/// Generate a `const _: &[u8]` pointing to a block blob.
|
||||
///
|
||||
/// This will deserialize with `Block` to assume the blob is at least deserializable.
|
||||
///
|
||||
/// This requires some static block input for testing.
|
||||
///
|
||||
/// The actual block blob data on disk is found in `data/block`.
|
||||
///
|
||||
/// See below for actual usage.
|
||||
macro_rules! const_block_blob {
|
||||
(
|
||||
name: $name:ident, // Name of the `const` created
|
||||
height: $height:literal, // Block height
|
||||
hash: $hash:literal, // Block hash
|
||||
data_path: $data_path:literal, // Path to the block blob
|
||||
major_version: $major_version:literal, // Block's major version
|
||||
minor_version: $minor_version:literal, // Block's minor version
|
||||
timestamp: $timestamp:literal, // Block's timestamp
|
||||
nonce: $nonce:literal, // Block's nonce
|
||||
miner_tx_generated: $miner_tx_generated:literal, // Generated Monero in block's miner transaction
|
||||
tx_len: $tx_len:literal, // How many transactions there are in the block
|
||||
) => {
|
||||
#[doc = concat!("Block with hash `", $hash, "`.")]
|
||||
///
|
||||
#[doc = concat!("Height: `", $height, "`.")]
|
||||
///
|
||||
/// ```rust
|
||||
/// use monero_serai::{block::Block, transaction::Input};
|
||||
///
|
||||
/// let block = Block::read(&mut
|
||||
/// cuprate_test_utils::data::BLOCK_BBD604
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// assert_eq!(block.header.major_version, 1);
|
||||
/// assert_eq!(block.header.minor_version, 0);
|
||||
/// assert_eq!(block.header.timestamp, 1409804570);
|
||||
/// assert_eq!(block.header.nonce, 1073744198);
|
||||
/// assert!(matches!(block.miner_tx.prefix.inputs[0], Input::Gen(202612)));
|
||||
/// assert_eq!(block.txs.len(), 513);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// hex::encode(block.hash()),
|
||||
/// "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698",
|
||||
/// );
|
||||
#[doc = "# use cuprate_test_utils::data::*;"]
|
||||
#[doc = "use monero_serai::{block::Block, transaction::Input};"]
|
||||
#[doc = ""]
|
||||
#[doc = concat!("let block = Block::read(&mut ", stringify!($name), ").unwrap();")]
|
||||
#[doc = ""]
|
||||
#[doc = concat!("assert_eq!(block.header.major_version, ", $major_version, ");")]
|
||||
#[doc = concat!("assert_eq!(block.header.minor_version, ", $minor_version, ");")]
|
||||
#[doc = concat!("assert_eq!(block.header.timestamp, ", $timestamp, ");")]
|
||||
#[doc = concat!("assert_eq!(block.header.nonce, ", $nonce, ");")]
|
||||
#[doc = concat!("assert!(matches!(block.miner_tx.prefix.inputs[0], Input::Gen(", $miner_tx_generated, ")));")]
|
||||
#[doc = concat!("assert_eq!(block.txs.len(), ", $tx_len, ");")]
|
||||
#[doc = concat!("assert_eq!(hex::encode(block.hash()), \"", $hash, "\")")]
|
||||
/// ```
|
||||
pub const BLOCK_BBD604: &[u8] =
|
||||
include_bytes!("block/bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698.bin");
|
||||
pub const $name: &[u8] = include_bytes!($data_path);
|
||||
};
|
||||
}
|
||||
|
||||
/// Block with height `2751506` and hash `f910435a5477ca27be1986c080d5476aeab52d0c07cf3d9c72513213350d25d4`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use monero_serai::{block::Block, transaction::Input};
|
||||
///
|
||||
/// let block = Block::read(&mut
|
||||
/// cuprate_test_utils::data::BLOCK_F91043
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// assert_eq!(block.header.major_version, 9);
|
||||
/// assert_eq!(block.header.minor_version, 9);
|
||||
/// assert_eq!(block.header.timestamp, 1545423190);
|
||||
/// assert_eq!(block.header.nonce, 4123173351);
|
||||
/// assert!(matches!(block.miner_tx.prefix.inputs[0], Input::Gen(1731606)));
|
||||
/// assert_eq!(block.txs.len(), 3);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// hex::encode(block.hash()),
|
||||
/// "f910435a5477ca27be1986c080d5476aeab52d0c07cf3d9c72513213350d25d4",
|
||||
/// );
|
||||
/// ```
|
||||
pub const BLOCK_F91043: &[u8] =
|
||||
include_bytes!("block/f910435a5477ca27be1986c080d5476aeab52d0c07cf3d9c72513213350d25d4.bin");
|
||||
const_block_blob! {
|
||||
name: BLOCK_BBD604,
|
||||
height: 202_612,
|
||||
hash: "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698",
|
||||
data_path: "block/bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698.bin",
|
||||
major_version: 1,
|
||||
minor_version: 0,
|
||||
timestamp: 1409804570,
|
||||
nonce: 1073744198,
|
||||
miner_tx_generated: 202612,
|
||||
tx_len: 513,
|
||||
}
|
||||
|
||||
/// Block with height `2751506` and hash `43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use monero_serai::{block::Block, transaction::Input};
|
||||
///
|
||||
/// let block = Block::read(&mut
|
||||
/// cuprate_test_utils::data::BLOCK_43BD1F
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// assert_eq!(block.header.major_version, 16);
|
||||
/// assert_eq!(block.header.minor_version, 16);
|
||||
/// assert_eq!(block.header.timestamp, 1667941829);
|
||||
/// assert_eq!(block.header.nonce, 4110909056);
|
||||
/// assert!(matches!(block.miner_tx.prefix.inputs[0], Input::Gen(2751506)));
|
||||
/// assert_eq!(block.txs.len(), 0);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// hex::encode(block.hash()),
|
||||
/// "43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428",
|
||||
/// );
|
||||
/// ```
|
||||
pub const BLOCK_43BD1F: &[u8] =
|
||||
include_bytes!("block/43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428.bin");
|
||||
const_block_blob! {
|
||||
name: BLOCK_5ECB7E,
|
||||
height: 202_609,
|
||||
hash: "5ecb7e663bbe947c734c8059e7d7d52dc7d6644bb82d81a6ad4057d127ee8eda",
|
||||
data_path: "block/5ecb7e663bbe947c734c8059e7d7d52dc7d6644bb82d81a6ad4057d127ee8eda.bin",
|
||||
major_version: 1,
|
||||
minor_version: 0,
|
||||
timestamp: 1409804315,
|
||||
nonce: 48426,
|
||||
miner_tx_generated: 202609,
|
||||
tx_len: 2,
|
||||
}
|
||||
|
||||
const_block_blob! {
|
||||
name: BLOCK_F91043,
|
||||
height: 2_751_506,
|
||||
hash: "f910435a5477ca27be1986c080d5476aeab52d0c07cf3d9c72513213350d25d4",
|
||||
data_path: "block/f910435a5477ca27be1986c080d5476aeab52d0c07cf3d9c72513213350d25d4.bin",
|
||||
major_version: 9,
|
||||
minor_version: 9,
|
||||
timestamp: 1545423190,
|
||||
nonce: 4123173351,
|
||||
miner_tx_generated: 1731606,
|
||||
tx_len: 3,
|
||||
}
|
||||
|
||||
const_block_blob! {
|
||||
name: BLOCK_43BD1F,
|
||||
height: 2_751_506,
|
||||
hash: "43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428",
|
||||
data_path: "block/43bd1f2b6556dcafa413d8372974af59e4e8f37dbf74dc6b2a9b7212d0577428.bin",
|
||||
major_version: 16,
|
||||
minor_version: 16,
|
||||
timestamp: 1667941829,
|
||||
nonce: 4110909056,
|
||||
miner_tx_generated: 2751506,
|
||||
tx_len: 0,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Transaction
|
||||
/// Transaction with hash `3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1`.
|
||||
/// Generate a `const _: &[u8]` pointing to a transaction blob.
|
||||
///
|
||||
/// Same as [`const_block_blob`] but for transactions.
|
||||
macro_rules! const_tx_blob {
|
||||
(
|
||||
name: $name:ident, // Name of the `const` created
|
||||
hash: $hash:literal, // Transaction hash
|
||||
data_path: $data_path:literal, // Path to the transaction blob
|
||||
version: $version:literal, // Transaction version
|
||||
timelock: $timelock:expr, // Transaction's timelock (use the real type `Timelock`)
|
||||
input_len: $input_len:literal, // Amount of inputs
|
||||
output_len: $output_len:literal, // Amount of outputs
|
||||
signatures_len: $signatures_len:literal, // Amount of signatures
|
||||
) => {
|
||||
#[doc = concat!("Transaction with hash `", $hash, "`.")]
|
||||
///
|
||||
/// ```rust
|
||||
/// use monero_serai::transaction::{Transaction, Timelock};
|
||||
///
|
||||
/// let tx = Transaction::read(&mut
|
||||
/// cuprate_test_utils::data::TX_3BC7FF
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// assert_eq!(tx.prefix.version, 1);
|
||||
/// assert_eq!(tx.prefix.timelock, Timelock::Block(100_081));
|
||||
/// assert_eq!(tx.prefix.inputs.len(), 1);
|
||||
/// assert_eq!(tx.prefix.outputs.len(), 5);
|
||||
/// assert_eq!(tx.signatures.len(), 0);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// hex::encode(tx.hash()),
|
||||
/// "3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1",
|
||||
/// );
|
||||
#[doc = "# use cuprate_test_utils::data::*;"]
|
||||
#[doc = "use monero_serai::transaction::{Transaction, Timelock};"]
|
||||
#[doc = ""]
|
||||
#[doc = concat!("let tx = Transaction::read(&mut ", stringify!($name), ").unwrap();")]
|
||||
#[doc = ""]
|
||||
#[doc = concat!("assert_eq!(tx.prefix.version, ", $version, ");")]
|
||||
#[doc = concat!("assert_eq!(tx.prefix.timelock, ", stringify!($timelock), ");")]
|
||||
#[doc = concat!("assert_eq!(tx.prefix.inputs.len(), ", $input_len, ");")]
|
||||
#[doc = concat!("assert_eq!(tx.prefix.outputs.len(), ", $output_len, ");")]
|
||||
#[doc = concat!("assert_eq!(tx.signatures.len(), ", $signatures_len, ");")]
|
||||
#[doc = concat!("assert_eq!(hex::encode(tx.hash()), \"", $hash, "\")")]
|
||||
/// ```
|
||||
pub const TX_3BC7FF: &[u8] =
|
||||
include_bytes!("tx/3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1.bin");
|
||||
pub const $name: &[u8] = include_bytes!($data_path);
|
||||
};
|
||||
}
|
||||
|
||||
/// Transaction with hash `9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use monero_serai::transaction::{Transaction, Timelock};
|
||||
///
|
||||
/// let tx = Transaction::read(&mut
|
||||
/// cuprate_test_utils::data::TX_9E3F73
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// assert_eq!(tx.prefix.version, 1);
|
||||
/// assert_eq!(tx.prefix.timelock, Timelock::None);
|
||||
/// assert_eq!(tx.prefix.inputs.len(), 2);
|
||||
/// assert_eq!(tx.prefix.outputs.len(), 5);
|
||||
/// assert_eq!(tx.signatures.len(), 2);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// hex::encode(tx.hash()),
|
||||
/// "9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34",
|
||||
/// );
|
||||
/// ```
|
||||
pub const TX_9E3F73: &[u8] =
|
||||
include_bytes!("tx/9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34.bin");
|
||||
const_tx_blob! {
|
||||
name: TX_3BC7FF,
|
||||
hash: "3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1",
|
||||
data_path: "tx/3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1.bin",
|
||||
version: 1,
|
||||
timelock: Timelock::Block(100_081),
|
||||
input_len: 1,
|
||||
output_len: 5,
|
||||
signatures_len: 0,
|
||||
}
|
||||
|
||||
/// Transaction with hash `84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use monero_serai::transaction::{Transaction, Timelock};
|
||||
///
|
||||
/// let tx = Transaction::read(&mut
|
||||
/// cuprate_test_utils::data::TX_84D48D
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// assert_eq!(tx.prefix.version, 2);
|
||||
/// assert_eq!(tx.prefix.timelock, Timelock::None);
|
||||
/// assert_eq!(tx.prefix.inputs.len(), 2);
|
||||
/// assert_eq!(tx.prefix.outputs.len(), 2);
|
||||
/// assert_eq!(tx.signatures.len(), 0);
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// hex::encode(tx.hash()),
|
||||
/// "84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66",
|
||||
/// );
|
||||
/// ```
|
||||
pub const TX_84D48D: &[u8] =
|
||||
include_bytes!("tx/84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66.bin");
|
||||
const_tx_blob! {
|
||||
name: TX_2180A8,
|
||||
hash: "2180a87f724702d37af087e22476297e818a73579ef7b7da947da963245202a3",
|
||||
data_path: "tx/2180a87f724702d37af087e22476297e818a73579ef7b7da947da963245202a3.bin",
|
||||
version: 1,
|
||||
timelock: Timelock::None,
|
||||
input_len: 19,
|
||||
output_len: 61,
|
||||
signatures_len: 19,
|
||||
}
|
||||
|
||||
const_tx_blob! {
|
||||
name: TX_D7FEBD,
|
||||
hash: "d7febd16293799d9c6a8e0fe9199b8a0a3e0da5a8a165098937b60f0bbd582df",
|
||||
data_path: "tx/d7febd16293799d9c6a8e0fe9199b8a0a3e0da5a8a165098937b60f0bbd582df.bin",
|
||||
version: 1,
|
||||
timelock: Timelock::None,
|
||||
input_len: 46,
|
||||
output_len: 46,
|
||||
signatures_len: 46,
|
||||
}
|
||||
|
||||
const_tx_blob! {
|
||||
name: TX_E2D393,
|
||||
hash: "e2d39395dd1625b2d707b98af789e7eab9d24c2bd2978ec38ef910961a8cdcee",
|
||||
data_path: "tx/e2d39395dd1625b2d707b98af789e7eab9d24c2bd2978ec38ef910961a8cdcee.bin",
|
||||
version: 2,
|
||||
timelock: Timelock::None,
|
||||
input_len: 1,
|
||||
output_len: 2,
|
||||
signatures_len: 0,
|
||||
}
|
||||
|
||||
const_tx_blob! {
|
||||
name: TX_E57440,
|
||||
hash: "e57440ec66d2f3b2a5fa2081af40128868973e7c021bb3877290db3066317474",
|
||||
data_path: "tx/e57440ec66d2f3b2a5fa2081af40128868973e7c021bb3877290db3066317474.bin",
|
||||
version: 2,
|
||||
timelock: Timelock::None,
|
||||
input_len: 1,
|
||||
output_len: 2,
|
||||
signatures_len: 0,
|
||||
}
|
||||
|
||||
const_tx_blob! {
|
||||
name: TX_B6B439,
|
||||
hash: "b6b4394d4ec5f08ad63267c07962550064caa8d225dd9ad6d739ebf60291c169",
|
||||
data_path: "tx/b6b4394d4ec5f08ad63267c07962550064caa8d225dd9ad6d739ebf60291c169.bin",
|
||||
version: 2,
|
||||
timelock: Timelock::None,
|
||||
input_len: 2,
|
||||
output_len: 2,
|
||||
signatures_len: 0,
|
||||
}
|
||||
|
||||
const_tx_blob! {
|
||||
name: TX_9E3F73,
|
||||
hash: "9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34",
|
||||
data_path: "tx/9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34.bin",
|
||||
version: 1,
|
||||
timelock: Timelock::None,
|
||||
input_len: 2,
|
||||
output_len: 5,
|
||||
signatures_len: 2,
|
||||
}
|
||||
|
||||
const_tx_blob! {
|
||||
name: TX_84D48D,
|
||||
hash: "84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66",
|
||||
data_path: "tx/84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66.bin",
|
||||
version: 2,
|
||||
timelock: Timelock::None,
|
||||
input_len: 2,
|
||||
output_len: 2,
|
||||
signatures_len: 0,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -6,105 +6,260 @@
|
|||
)]
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
use std::sync::OnceLock;
|
||||
use std::sync::{Arc, OnceLock};
|
||||
|
||||
use hex_literal::hex;
|
||||
use monero_serai::{block::Block, transaction::Transaction};
|
||||
|
||||
use cuprate_types::{TransactionVerificationData, VerifiedBlockInformation};
|
||||
|
||||
use crate::data::constants::{
|
||||
BLOCK_43BD1F, BLOCK_BBD604, BLOCK_F91043, TX_3BC7FF, TX_84D48D, TX_9E3F73,
|
||||
BLOCK_43BD1F, BLOCK_5ECB7E, BLOCK_F91043, TX_2180A8, TX_3BC7FF, TX_84D48D, TX_9E3F73,
|
||||
TX_B6B439, TX_D7FEBD, TX_E2D393, TX_E57440,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Conversion
|
||||
/// Converts `monero_serai`'s `Block` into a
|
||||
/// `cuprate_types::VerifiedBlockInformation` (superset).
|
||||
///
|
||||
/// To prevent pulling other code in order to actually calculate things
|
||||
/// (e.g. `pow_hash`), some information must be provided statically,
|
||||
/// this struct represents that data that must be provided.
|
||||
///
|
||||
/// Consider using `cuprate_test_utils::rpc` to get this data easily.
|
||||
struct VerifiedBlockMap<'a> {
|
||||
block: Block,
|
||||
pow_hash: [u8; 32],
|
||||
height: u64,
|
||||
generated_coins: u64,
|
||||
weight: usize,
|
||||
long_term_weight: usize,
|
||||
cumulative_difficulty: u128,
|
||||
// Vec of `tx_blob`'s, i.e. the data in `/test-utils/src/data/tx/`.
|
||||
// This should the actual `tx_blob`'s of the transactions within this block.
|
||||
txs: Vec<&'a [u8]>,
|
||||
}
|
||||
|
||||
impl VerifiedBlockMap<'_> {
|
||||
/// Turn the various static data bits in `self` into a `VerifiedBlockInformation`.
|
||||
///
|
||||
/// Transactions are verified that they at least match the block's,
|
||||
/// although the correctness of data (whether this block actually existed or not)
|
||||
/// is not checked.
|
||||
fn into_verified(self) -> VerifiedBlockInformation {
|
||||
let Self {
|
||||
block,
|
||||
pow_hash,
|
||||
height,
|
||||
generated_coins,
|
||||
weight,
|
||||
long_term_weight,
|
||||
cumulative_difficulty,
|
||||
txs,
|
||||
} = self;
|
||||
|
||||
let txs: Vec<Arc<TransactionVerificationData>> = txs
|
||||
.into_iter()
|
||||
.map(to_tx_verification_data)
|
||||
.map(Arc::new)
|
||||
.collect();
|
||||
|
||||
assert_eq!(
|
||||
txs.len(),
|
||||
block.txs.len(),
|
||||
"(deserialized txs).len() != (txs hashes in block).len()"
|
||||
);
|
||||
|
||||
for (tx, tx_hash_in_block) in txs.iter().zip(&block.txs) {
|
||||
assert_eq!(
|
||||
&tx.tx_hash, tx_hash_in_block,
|
||||
"deserialized tx hash is not the same as the one in the parent block"
|
||||
);
|
||||
}
|
||||
|
||||
VerifiedBlockInformation {
|
||||
block_hash: block.hash(),
|
||||
block,
|
||||
txs,
|
||||
pow_hash,
|
||||
height,
|
||||
generated_coins,
|
||||
weight,
|
||||
long_term_weight,
|
||||
cumulative_difficulty,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same as [`VerifiedBlockMap`] but for [`TransactionVerificationData`].
|
||||
fn to_tx_verification_data(tx_blob: &[u8]) -> TransactionVerificationData {
|
||||
let tx_blob = tx_blob.to_vec();
|
||||
let tx = Transaction::read(&mut tx_blob.as_slice()).unwrap();
|
||||
TransactionVerificationData {
|
||||
tx_weight: tx.weight(),
|
||||
fee: tx.rct_signatures.base.fee,
|
||||
tx_hash: tx.hash(),
|
||||
tx_blob,
|
||||
tx,
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Blocks
|
||||
/// Return [`BLOCK_BBD604`] as a [`Block`].
|
||||
/// Generate a block accessor function with this signature:
|
||||
/// `fn() -> &'static VerifiedBlockInformation`
|
||||
///
|
||||
/// This will use `VerifiedBlockMap` type above to do various
|
||||
/// checks on the input data and makes sure it seems correct.
|
||||
///
|
||||
/// This requires some static block/tx input (from data) and some fields.
|
||||
/// This data can be accessed more easily via:
|
||||
/// - A block explorer (https://xmrchain.net)
|
||||
/// - Monero RPC (see cuprate_test_utils::rpc for this)
|
||||
///
|
||||
/// See below for actual usage.
|
||||
macro_rules! verified_block_information_fn {
|
||||
(
|
||||
fn_name: $fn_name:ident, // Name of the function 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
|
||||
height: $height:literal, // Block height
|
||||
generated_coins: $generated_coins:literal, // Generated coins in block (`reward`)
|
||||
weight: $weight:literal, // Block weight
|
||||
long_term_weight: $long_term_weight:literal, // Block long term weight
|
||||
cumulative_difficulty: $cumulative_difficulty:literal, // Block cumulative difficulty
|
||||
tx_len: $tx_len:literal, // Amount of transactions in this block
|
||||
) => {
|
||||
#[doc = concat!(
|
||||
"Return [`",
|
||||
stringify!($block_blob),
|
||||
"`] as a [`VerifiedBlockInformation`].",
|
||||
)]
|
||||
///
|
||||
/// Contained transactions:
|
||||
$(
|
||||
#[doc = concat!("- [`", stringify!($tx_blob), "`]")]
|
||||
)*
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// &cuprate_test_utils::data::block_v1_tx513().serialize(),
|
||||
/// cuprate_test_utils::data::BLOCK_BBD604
|
||||
/// );
|
||||
#[doc = "# use cuprate_test_utils::data::*;"]
|
||||
#[doc = "# use hex_literal::hex;"]
|
||||
#[doc = concat!("let block = ", stringify!($fn_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, ");")]
|
||||
#[doc = concat!("assert_eq!(block.generated_coins, ", $generated_coins, ");")]
|
||||
#[doc = concat!("assert_eq!(block.weight, ", $weight, ");")]
|
||||
#[doc = concat!("assert_eq!(block.long_term_weight, ", $long_term_weight, ");")]
|
||||
#[doc = concat!("assert_eq!(block.cumulative_difficulty, ", $cumulative_difficulty, ");")]
|
||||
#[doc = concat!("assert_eq!(block.txs.len(), ", $tx_len, ");")]
|
||||
/// ```
|
||||
pub fn block_v1_tx513() -> Block {
|
||||
/// `OnceLock` holding the data.
|
||||
static BLOCK: OnceLock<Block> = OnceLock::new();
|
||||
BLOCK
|
||||
.get_or_init(|| Block::read(&mut BLOCK_BBD604).unwrap())
|
||||
.clone()
|
||||
pub fn $fn_name() -> &'static VerifiedBlockInformation {
|
||||
static BLOCK: OnceLock<VerifiedBlockInformation> = OnceLock::new();
|
||||
BLOCK.get_or_init(|| {
|
||||
VerifiedBlockMap {
|
||||
block: Block::read(&mut $block_blob).unwrap(),
|
||||
pow_hash: hex!($pow_hash),
|
||||
height: $height,
|
||||
generated_coins: $generated_coins,
|
||||
weight: $weight,
|
||||
long_term_weight: $long_term_weight,
|
||||
cumulative_difficulty: $cumulative_difficulty,
|
||||
txs: vec![$($tx_blob),*],
|
||||
}
|
||||
.into_verified()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Return [`BLOCK_F91043`] as a [`Block`].
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// &cuprate_test_utils::data::block_v9_tx3().serialize(),
|
||||
/// cuprate_test_utils::data::BLOCK_F91043
|
||||
/// );
|
||||
/// ```
|
||||
pub fn block_v9_tx3() -> Block {
|
||||
/// `OnceLock` holding the data.
|
||||
static BLOCK: OnceLock<Block> = OnceLock::new();
|
||||
BLOCK
|
||||
.get_or_init(|| Block::read(&mut BLOCK_F91043).unwrap())
|
||||
.clone()
|
||||
verified_block_information_fn! {
|
||||
fn_name: block_v1_tx2,
|
||||
block_blob: BLOCK_5ECB7E,
|
||||
tx_blobs: [TX_2180A8, TX_D7FEBD],
|
||||
pow_hash: "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000",
|
||||
height: 202_612,
|
||||
generated_coins: 13_138_270_468_431,
|
||||
weight: 55_503,
|
||||
long_term_weight: 55_503,
|
||||
cumulative_difficulty: 126_654_460_829_362,
|
||||
tx_len: 2,
|
||||
}
|
||||
|
||||
/// Return [`BLOCK_43BD1F`] as a [`Block`].
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// &cuprate_test_utils::data::block_v16_tx0().serialize(),
|
||||
/// cuprate_test_utils::data::BLOCK_43BD1F
|
||||
/// );
|
||||
/// ```
|
||||
pub fn block_v16_tx0() -> Block {
|
||||
/// `OnceLock` holding the data.
|
||||
static BLOCK: OnceLock<Block> = OnceLock::new();
|
||||
BLOCK
|
||||
.get_or_init(|| Block::read(&mut BLOCK_43BD1F).unwrap())
|
||||
.clone()
|
||||
verified_block_information_fn! {
|
||||
fn_name: block_v9_tx3,
|
||||
block_blob: BLOCK_F91043,
|
||||
tx_blobs: [TX_E2D393, TX_E57440, TX_B6B439],
|
||||
pow_hash: "7c78b5b67a112a66ea69ea51477492057dba9cfeaa2942ee7372c61800000000",
|
||||
height: 1_731_606,
|
||||
generated_coins: 3_403_921_682_163,
|
||||
weight: 6_597,
|
||||
long_term_weight: 6_597,
|
||||
cumulative_difficulty: 23_558_910_234_058_343,
|
||||
tx_len: 3,
|
||||
}
|
||||
|
||||
verified_block_information_fn! {
|
||||
fn_name: block_v16_tx0,
|
||||
block_blob: BLOCK_43BD1F,
|
||||
tx_blobs: [],
|
||||
pow_hash: "10b473b5d097d6bfa0656616951840724dfe38c6fb9c4adf8158800300000000",
|
||||
height: 2_751_506,
|
||||
generated_coins: 600_000_000_000,
|
||||
weight: 106,
|
||||
long_term_weight: 176_470,
|
||||
cumulative_difficulty: 236_046_001_376_524_168,
|
||||
tx_len: 0,
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Transactions
|
||||
/// Return [`TX_3BC7FF`] as a [`Transaction`].
|
||||
/// Generate a transaction accessor function with this signature:
|
||||
/// `fn() -> &'static TransactionVerificationData`
|
||||
///
|
||||
/// Same as [`verified_block_information_fn`] but for transactions.
|
||||
macro_rules! transaction_verification_data_fn {
|
||||
(
|
||||
fn_name: $fn_name:ident, // Name of the function 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
|
||||
) => {
|
||||
#[doc = concat!("Return [`", stringify!($tx_blob), "`] as a [`TransactionVerificationData`].")]
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// &cuprate_test_utils::data::tx_v1_sig0().serialize(),
|
||||
/// cuprate_test_utils::data::TX_3BC7FF
|
||||
/// );
|
||||
#[doc = "# use cuprate_test_utils::data::*;"]
|
||||
#[doc = "# use hex_literal::hex;"]
|
||||
#[doc = concat!("let tx = ", stringify!($fn_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, "\"));")]
|
||||
#[doc = "assert_eq!(tx.fee, tx.tx.rct_signatures.base.fee);"]
|
||||
/// ```
|
||||
pub fn tx_v1_sig0() -> Transaction {
|
||||
/// `OnceLock` holding the data.
|
||||
static TX: OnceLock<Transaction> = OnceLock::new();
|
||||
TX.get_or_init(|| Transaction::read(&mut TX_3BC7FF).unwrap())
|
||||
.clone()
|
||||
pub fn $fn_name() -> &'static TransactionVerificationData {
|
||||
static TX: OnceLock<TransactionVerificationData> = OnceLock::new();
|
||||
TX.get_or_init(|| to_tx_verification_data($tx_blob))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Return [`TX_9E3F73`] as a [`Transaction`].
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// &cuprate_test_utils::data::tx_v1_sig2().serialize(),
|
||||
/// cuprate_test_utils::data::TX_9E3F73
|
||||
/// );
|
||||
/// ```
|
||||
pub fn tx_v1_sig2() -> Transaction {
|
||||
/// `OnceLock` holding the data.
|
||||
static TX: OnceLock<Transaction> = OnceLock::new();
|
||||
TX.get_or_init(|| Transaction::read(&mut TX_9E3F73).unwrap())
|
||||
.clone()
|
||||
transaction_verification_data_fn! {
|
||||
fn_name: tx_v1_sig0,
|
||||
tx_blobs: TX_3BC7FF,
|
||||
weight: 248,
|
||||
hash: "3bc7ff015b227e7313cc2e8668bfbb3f3acbee274a9c201d6211cf681b5f6bb1",
|
||||
}
|
||||
|
||||
/// Return [`TX_84D48D`] as a [`Transaction`].
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// &cuprate_test_utils::data::tx_v2_rct3().serialize(),
|
||||
/// cuprate_test_utils::data::TX_84D48D
|
||||
/// );
|
||||
/// ```
|
||||
pub fn tx_v2_rct3() -> Transaction {
|
||||
/// `OnceLock` holding the data.
|
||||
static TX: OnceLock<Transaction> = OnceLock::new();
|
||||
TX.get_or_init(|| Transaction::read(&mut TX_84D48D).unwrap())
|
||||
.clone()
|
||||
transaction_verification_data_fn! {
|
||||
fn_name: tx_v1_sig2,
|
||||
tx_blobs: TX_9E3F73,
|
||||
weight: 448,
|
||||
hash: "9e3f73e66d7c7293af59c59c1ff5d6aae047289f49e5884c66caaf4aea49fb34",
|
||||
}
|
||||
|
||||
transaction_verification_data_fn! {
|
||||
fn_name: tx_v2_rct3,
|
||||
tx_blobs: TX_84D48D,
|
||||
weight: 2743,
|
||||
hash: "84d48dc11ec91950f8b70a85af9db91fe0c8abef71ef5db08304f7344b99ea66",
|
||||
}
|
||||
|
|
|
@ -1,9 +1,35 @@
|
|||
//! Testing data and utilities.
|
||||
//! Real Monero data.
|
||||
//!
|
||||
//! Raw data is found in `data/`.
|
||||
//! This module provides access to _real_ Monero data,
|
||||
//! either in raw bytes or typed.
|
||||
//!
|
||||
//! ## Constants
|
||||
//! The `const`ants provide byte slices representing block
|
||||
//! and transaction blobs that can be directly deserialized:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use cuprate_test_utils::data::*;
|
||||
//! use monero_serai::{block::Block, transaction::Transaction};
|
||||
//!
|
||||
//! let block: Block = Block::read(&mut BLOCK_43BD1F).unwrap();
|
||||
//! let tx: Transaction = Transaction::read(&mut TX_E57440).unwrap();
|
||||
//! ```
|
||||
//!
|
||||
//! ## Functions
|
||||
//! The free functions provide access to typed data found in `cuprate_types`:
|
||||
//! ```rust
|
||||
//! # use cuprate_test_utils::data::*;
|
||||
//! use cuprate_types::{VerifiedBlockInformation, TransactionVerificationData};
|
||||
//!
|
||||
//! let block: VerifiedBlockInformation = block_v16_tx0().clone();
|
||||
//! let tx: TransactionVerificationData = tx_v1_sig0().clone();
|
||||
//! ```
|
||||
|
||||
mod constants;
|
||||
pub use constants::{BLOCK_43BD1F, BLOCK_BBD604, BLOCK_F91043, TX_3BC7FF, TX_84D48D, TX_9E3F73};
|
||||
pub use constants::{
|
||||
BLOCK_43BD1F, BLOCK_5ECB7E, BLOCK_BBD604, BLOCK_F91043, TX_2180A8, TX_3BC7FF, TX_84D48D,
|
||||
TX_9E3F73, TX_B6B439, TX_D7FEBD, TX_E2D393, TX_E57440,
|
||||
};
|
||||
|
||||
mod free;
|
||||
pub use free::{block_v16_tx0, block_v1_tx513, block_v9_tx3, tx_v1_sig0, tx_v1_sig2, tx_v2_rct3};
|
||||
pub use free::{block_v16_tx0, block_v1_tx2, block_v9_tx3, tx_v1_sig0, tx_v1_sig2, tx_v2_rct3};
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,4 @@
|
|||
//! Cuprate testing utilities.
|
||||
//!
|
||||
//! See the `README.md` for more info.
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
pub mod data;
|
||||
pub mod monerod;
|
||||
|
|
Loading…
Reference in a new issue