use blvm_consensus::opcodes::{OP_1, OP_2};
use blvm_consensus::taproot::{
TAPROOT_LEAF_VERSION_TAPSCRIPT, compute_script_merkle_root, compute_taproot_tweak,
validate_taproot_key_aggregation, validate_taproot_script_path,
};
use blvm_consensus::types::Hash;
use blvm_consensus::witness::validate_taproot_witness_structure;
#[test]
fn test_taproot_script_path_merkle_proof() {
let script = vec![OP_1];
let merkle_proof: Vec<Hash> = vec![];
let merkle_root =
compute_script_merkle_root(&script, &merkle_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
assert!(validate_taproot_script_path(&script, &merkle_proof, &merkle_root).unwrap());
assert!(!validate_taproot_script_path(&script, &merkle_proof, &[0x42; 32]).unwrap());
}
#[test]
fn test_taproot_script_path_invalid_proof() {
let script = vec![OP_1];
let invalid_proof: Vec<Hash> = vec![[0xff; 32]];
let merkle_root: Hash = [0x42; 32];
assert!(!validate_taproot_script_path(&script, &invalid_proof, &merkle_root).unwrap());
}
#[test]
fn test_taproot_script_path_empty_script() {
let empty_script = vec![];
let merkle_proof: Vec<Hash> = vec![];
let merkle_root =
compute_script_merkle_root(&empty_script, &merkle_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT)
.unwrap();
assert!(validate_taproot_script_path(&empty_script, &merkle_proof, &merkle_root).unwrap());
assert!(!validate_taproot_script_path(&empty_script, &merkle_proof, &[0x42; 32]).unwrap());
}
#[test]
fn test_taproot_script_path_depth_limits() {
let script = vec![OP_1];
let shallow_proof: Vec<Hash> = vec![[0x01; 32], [0x02; 32]];
let mut deep_proof = Vec::new();
for i in 0..10 {
deep_proof.push([i as u8; 32]);
}
let shallow_root =
compute_script_merkle_root(&script, &shallow_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT)
.unwrap();
let deep_root =
compute_script_merkle_root(&script, &deep_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
assert!(validate_taproot_script_path(&script, &shallow_proof, &shallow_root).unwrap());
assert!(validate_taproot_script_path(&script, &deep_proof, &deep_root).unwrap());
assert!(!validate_taproot_script_path(&script, &shallow_proof, &deep_root).unwrap());
}
#[test]
fn test_taproot_key_aggregation() {
let internal_pubkey: [u8; 32] = [0x01; 32];
let merkle_root: Hash = [0x02; 32];
let output_key = compute_taproot_tweak(&internal_pubkey, &merkle_root);
assert!(output_key.is_ok());
let output_key_value = output_key.unwrap();
assert_eq!(output_key_value.len(), 32);
let (expected_key, parity) = blvm_consensus::secp256k1_backend::taproot_output_key_with_parity(
&internal_pubkey,
&merkle_root,
)
.unwrap();
let result =
validate_taproot_key_aggregation(&internal_pubkey, &merkle_root, &expected_key, parity);
assert!(result.is_ok());
assert!(result.unwrap()); }
#[test]
fn test_taproot_key_aggregation_wrong_key() {
let internal_pubkey: [u8; 32] = [0x01; 32];
let merkle_root: Hash = [0x02; 32];
let wrong_output_key: [u8; 32] = [0xff; 32];
let result =
validate_taproot_key_aggregation(&internal_pubkey, &merkle_root, &wrong_output_key, 0);
assert!(result.is_ok());
assert!(!result.unwrap()); }
#[test]
fn test_taproot_witness_size_limits() {
let script = vec![0x51];
let control = vec![0xc0; 33];
assert!(validate_taproot_witness_structure(&vec![script.clone(), control], true).unwrap());
assert!(!validate_taproot_witness_structure(&vec![script, vec![0x42; 520]], true).unwrap());
}
#[test]
fn test_taproot_script_path_multiple_scripts() {
let script1 = vec![OP_1];
let script2 = vec![OP_2];
let proof1: Vec<Hash> = vec![[0x01; 32]];
let proof2: Vec<Hash> = vec![[0x02; 32]];
let root1 =
compute_script_merkle_root(&script1, &proof1, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
let root2 =
compute_script_merkle_root(&script2, &proof2, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
assert!(validate_taproot_script_path(&script1, &proof1, &root1).unwrap());
assert!(validate_taproot_script_path(&script2, &proof2, &root2).unwrap());
assert!(!validate_taproot_script_path(&script1, &proof1, &root2).unwrap());
}
#[test]
fn test_taproot_key_aggregation_empty_merkle() {
let internal_pubkey: [u8; 32] = [0x01; 32];
let empty_merkle_root: Hash = [0x00; 32];
let output_key = compute_taproot_tweak(&internal_pubkey, &empty_merkle_root);
assert!(output_key.is_ok());
let (expected_key, parity) = blvm_consensus::secp256k1_backend::taproot_output_key_with_parity(
&internal_pubkey,
&empty_merkle_root,
)
.unwrap();
let result = validate_taproot_key_aggregation(
&internal_pubkey,
&empty_merkle_root,
&expected_key,
parity,
);
assert!(result.unwrap());
}
#[test]
fn test_taproot_script_path_boundaries() {
let script = vec![OP_1];
let single_proof: Vec<Hash> = vec![[0x01; 32]];
let merkle_root: Hash = [0x42; 32];
let single_root =
compute_script_merkle_root(&script, &single_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
assert!(validate_taproot_script_path(&script, &single_proof, &single_root).unwrap());
assert!(!validate_taproot_script_path(&script, &single_proof, &merkle_root).unwrap());
let empty_proof: Vec<Hash> = vec![];
let empty_root =
compute_script_merkle_root(&script, &empty_proof, TAPROOT_LEAF_VERSION_TAPSCRIPT).unwrap();
assert!(validate_taproot_script_path(&script, &empty_proof, &empty_root).unwrap());
}
#[test]
fn test_taproot_control_block() {
let script = vec![0x51];
assert!(
validate_taproot_witness_structure(&vec![script.clone(), vec![0xc0; 33]], true).unwrap()
);
assert!(
validate_taproot_witness_structure(&vec![script.clone(), vec![0xc0; 33 + 32]], true)
.unwrap()
);
let wide = 33 + 5 * 32;
let within = wide <= blvm_consensus::taproot::TAPROOT_CONTROL_MAX_SIZE;
assert_eq!(
validate_taproot_witness_structure(&vec![script, vec![0xc0; wide]], true).unwrap(),
within
);
}