115 lines
5.5 KiB
Rust
115 lines
5.5 KiB
Rust
//! Tests for trusted preallocation during deserialization.
|
|
|
|
use proptest::prelude::*;
|
|
|
|
use crate::{
|
|
block::MAX_BLOCK_BYTES,
|
|
serialization::{arbitrary::max_allocation_is_big_enough, TrustedPreallocate, ZcashSerialize},
|
|
transaction::{
|
|
serialize::{
|
|
MIN_TRANSPARENT_INPUT_SIZE, MIN_TRANSPARENT_OUTPUT_SIZE, MIN_TRANSPARENT_TX_SIZE,
|
|
},
|
|
transparent::Input,
|
|
transparent::Output,
|
|
Transaction,
|
|
},
|
|
};
|
|
|
|
proptest! {
|
|
/// Confirm that each spend takes at least MIN_TRANSPARENT_TX_SIZE bytes when serialized.
|
|
/// This verifies that our calculated [`TrustedPreallocate::max_allocation`] is indeed an upper bound.
|
|
#[test]
|
|
fn tx_size_is_small_enough(tx in Transaction::arbitrary()) {
|
|
let serialized = tx.zcash_serialize_to_vec().expect("Serialization to vec must succeed");
|
|
prop_assert!(serialized.len() as u64 >= MIN_TRANSPARENT_TX_SIZE)
|
|
}
|
|
|
|
/// Confirm that each spend takes at least MIN_TRANSPARENT_TX_SIZE bytes when serialized.
|
|
/// This verifies that our calculated [`TrustedPreallocate::max_allocation`] is indeed an upper bound.
|
|
#[test]
|
|
fn transparent_input_size_is_small_enough(input in Input::arbitrary()) {
|
|
let serialized = input.zcash_serialize_to_vec().expect("Serialization to vec must succeed");
|
|
prop_assert!(serialized.len() as u64 >= MIN_TRANSPARENT_INPUT_SIZE)
|
|
}
|
|
|
|
/// Confirm that each spend takes at least MIN_TRANSPARENT_TX_SIZE bytes when serialized.
|
|
/// This verifies that our calculated [`TrustedPreallocate::max_allocation`] is indeed an upper bound.
|
|
#[test]
|
|
fn transparent_output_size_is_small_enough(output in Output::arbitrary()) {
|
|
let serialized = output.zcash_serialize_to_vec().expect("Serialization to vec must succeed");
|
|
prop_assert!(serialized.len() as u64 >= MIN_TRANSPARENT_OUTPUT_SIZE)
|
|
}
|
|
|
|
}
|
|
|
|
proptest! {
|
|
// This test is pretty slow, so only run a few cases
|
|
#![proptest_config(ProptestConfig::with_cases(8))]
|
|
|
|
/// Verify the smallest disallowed vector of `Transaction`s is too large to fit in a Zcash block
|
|
#[test]
|
|
fn tx_max_allocation_is_big_enough(tx in Transaction::arbitrary()) {
|
|
let (
|
|
smallest_disallowed_vec_len,
|
|
smallest_disallowed_serialized_len,
|
|
largest_allowed_vec_len,
|
|
_largest_allowed_serialized_len,
|
|
) = max_allocation_is_big_enough(tx);
|
|
|
|
// Check that our smallest_disallowed_vec is only one item larger than the limit
|
|
prop_assert!(((smallest_disallowed_vec_len - 1) as u64) == Transaction::max_allocation());
|
|
// Check that our smallest_disallowed_vec is too big to send in a valid Zcash Block
|
|
prop_assert!(smallest_disallowed_serialized_len as u64 > MAX_BLOCK_BYTES);
|
|
|
|
// Check that our largest_allowed_vec contains the maximum number of Transactions
|
|
prop_assert!((largest_allowed_vec_len as u64) == Transaction::max_allocation());
|
|
// This is a variable-sized type, so largest_allowed_serialized_len can exceed the length limit
|
|
}
|
|
|
|
/// Verify the smallest disallowed vector of `Input`s is too large to fit in a Zcash block
|
|
#[test]
|
|
fn input_max_allocation_is_big_enough(input in Input::arbitrary()) {
|
|
|
|
let (
|
|
smallest_disallowed_vec_len,
|
|
smallest_disallowed_serialized_len,
|
|
largest_allowed_vec_len,
|
|
_largest_allowed_serialized_len,
|
|
) = max_allocation_is_big_enough(input);
|
|
|
|
// Check that our smallest_disallowed_vec is only one item larger than the limit
|
|
prop_assert!(((smallest_disallowed_vec_len - 1) as u64) == Input::max_allocation());
|
|
// Check that our smallest_disallowed_vec is too big to be included in a valid block
|
|
// Note that a serialized block always includes at least one byte for the number of transactions,
|
|
// so any serialized Vec<Input> at least MAX_BLOCK_BYTES long is too large to fit in a block.
|
|
prop_assert!(smallest_disallowed_serialized_len as u64 >= MAX_BLOCK_BYTES);
|
|
|
|
// Check that our largest_allowed_vec contains the maximum number of Inputs
|
|
prop_assert!((largest_allowed_vec_len as u64) == Input::max_allocation());
|
|
// This is a variable-sized type, so largest_allowed_serialized_len can exceed the length limit
|
|
}
|
|
|
|
/// Verify the smallest disallowed vector of `Output`s is too large to fit in a Zcash block
|
|
#[test]
|
|
fn output_max_allocation_is_big_enough(output in Output::arbitrary()) {
|
|
|
|
let (
|
|
smallest_disallowed_vec_len,
|
|
smallest_disallowed_serialized_len,
|
|
largest_allowed_vec_len,
|
|
_largest_allowed_serialized_len,
|
|
) = max_allocation_is_big_enough(output);
|
|
|
|
// Check that our smallest_disallowed_vec is only one item larger than the limit
|
|
prop_assert!(((smallest_disallowed_vec_len - 1) as u64) == Output::max_allocation());
|
|
// Check that our smallest_disallowed_vec is too big to be included in a valid block
|
|
// Note that a serialized block always includes at least one byte for the number of transactions,
|
|
// so any serialized Vec<Output> at least MAX_BLOCK_BYTES long is too large to fit in a block.
|
|
prop_assert!(smallest_disallowed_serialized_len as u64 >= MAX_BLOCK_BYTES);
|
|
|
|
// Check that our largest_allowed_vec contains the maximum number of Outputs
|
|
prop_assert!((largest_allowed_vec_len as u64) == Output::max_allocation());
|
|
// This is a variable-sized type, so largest_allowed_serialized_len can exceed the length limit
|
|
}
|
|
}
|