#[cfg(feature = "bolero")]
use blvm_consensus::block::connect_block;
#[cfg(feature = "bolero")]
use blvm_consensus::block::BlockValidationContext;
#[cfg(feature = "bolero")]
use blvm_consensus::pow::check_proof_of_work;
#[cfg(feature = "bolero")]
use blvm_consensus::types::Network;
#[cfg(feature = "bolero")]
use blvm_consensus::{Block, BlockHeader, UtxoSet};
#[cfg(feature = "bolero")]
use bolero::check;
#[cfg(feature = "bolero")]
#[test]
fn fuzz_check_proof_of_work_robustness() {
check!().for_each(|data: &[u8]| {
if data.len() < 80 {
return;
}
let header_bytes: [u8; 80] = data[..80].try_into().unwrap_or_else(|_| [0; 80]);
let header = BlockHeader {
version: i64::from(i32::from_le_bytes([
header_bytes[0],
header_bytes[1],
header_bytes[2],
header_bytes[3],
])),
prev_block_hash: header_bytes[4..36].try_into().unwrap_or([0; 32]),
merkle_root: header_bytes[36..68].try_into().unwrap_or([0; 32]),
timestamp: u64::from_le_bytes([
header_bytes[68],
header_bytes[69],
header_bytes[70],
header_bytes[71],
header_bytes[72],
header_bytes[73],
header_bytes[74],
header_bytes[75],
]),
bits: u32::from_le_bytes([
header_bytes[72],
header_bytes[73],
header_bytes[74],
header_bytes[75],
]) as u64,
nonce: u32::from_le_bytes([
header_bytes[76],
header_bytes[77],
header_bytes[78],
header_bytes[79],
]) as u64,
};
let result = check_proof_of_work(&header);
assert!(result.is_ok(), "check_proof_of_work should never panic");
});
}
#[cfg(feature = "bolero")]
#[test]
fn fuzz_check_proof_of_work_deterministic() {
check!().for_each(|data: &[u8]| {
if data.len() < 80 {
return;
}
let header_bytes: [u8; 80] = data[..80].try_into().unwrap_or_else(|_| [0; 80]);
let header = BlockHeader {
version: i64::from(i32::from_le_bytes([
header_bytes[0],
header_bytes[1],
header_bytes[2],
header_bytes[3],
])),
prev_block_hash: header_bytes[4..36].try_into().unwrap_or([0; 32]),
merkle_root: header_bytes[36..68].try_into().unwrap_or([0; 32]),
timestamp: u64::from_le_bytes([
header_bytes[68],
header_bytes[69],
header_bytes[70],
header_bytes[71],
header_bytes[72],
header_bytes[73],
header_bytes[74],
header_bytes[75],
]),
bits: u32::from_le_bytes([
header_bytes[72],
header_bytes[73],
header_bytes[74],
header_bytes[75],
]) as u64,
nonce: u32::from_le_bytes([
header_bytes[76],
header_bytes[77],
header_bytes[78],
header_bytes[79],
]) as u64,
};
let result1 = check_proof_of_work(&header);
let result2 = check_proof_of_work(&header);
assert_eq!(
result1, result2,
"check_proof_of_work must be deterministic"
);
});
}
#[cfg(feature = "bolero")]
#[test]
fn fuzz_connect_block_structure() {
check!().for_each(|data: &[u8]| {
if data.len() >= 80 {
let minimal_block = Block {
header: BlockHeader {
version: 1,
prev_block_hash: [0; 32],
merkle_root: [0; 32],
timestamp: 0,
bits: 0x1d00ffff,
nonce: 0,
},
transactions: vec![].into(),
};
let initial_utxo_set = UtxoSet::default();
let witnesses: Vec<Vec<blvm_consensus::Witness>> = vec![];
let ctx = BlockValidationContext::for_network(Network::Mainnet);
let result = connect_block(&minimal_block, &witnesses, initial_utxo_set, 0, &ctx);
assert!(
result.is_ok(),
"connect_block should handle blocks without panicking"
);
}
});
}