#[cfg(feature = "miniscript")]
mod miniscript_tests {
use blvm_node::miniscript::miniscript_support::*;
use blvm_protocol::ByteString;
use miniscript::bitcoin;
use miniscript::policy::concrete::Policy;
use std::str::FromStr;
#[test]
fn test_compile_simple_policy() {
let policy_str = "pk(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914)";
let policy: Policy<bitcoin::PublicKey> =
Policy::from_str(policy_str).expect("Failed to parse policy");
let result = compile_policy(&policy);
assert!(result.is_ok(), "Policy compilation should succeed");
let script = result.unwrap();
assert!(!script.is_empty(), "Compiled script should not be empty");
}
#[test]
fn test_compile_multisig_policy() {
let policy_str = "thresh(2,pk(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914),pk(03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0),pk(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9))";
let policy: Policy<bitcoin::PublicKey> =
Policy::from_str(policy_str).expect("Failed to parse multisig policy");
let result = compile_policy(&policy);
assert!(result.is_ok(), "Multisig policy compilation should succeed");
}
#[test]
fn test_compile_timelock_policy() {
let policy_str = "and(pk(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914),after(1000000))";
let policy: Policy<bitcoin::PublicKey> =
Policy::from_str(policy_str).expect("Failed to parse timelock policy");
let result = compile_policy(&policy);
assert!(result.is_ok(), "Timelock policy compilation should succeed");
}
#[test]
fn test_determine_script_type_p2pkh() {
let p2pkh_script = vec![
0x76, 0xa9, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x88, 0xac, ];
let script = ByteString::from(p2pkh_script);
let analysis = analyze_script(&script).expect("Analysis should succeed");
assert_eq!(analysis.script_type, "P2PKH", "Should detect P2PKH script");
}
#[test]
fn test_determine_script_type_p2sh() {
let p2sh_script = vec![
0xa9, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x87, ];
let script = ByteString::from(p2sh_script);
let analysis = analyze_script(&script).expect("Analysis should succeed");
assert_eq!(analysis.script_type, "P2SH", "Should detect P2SH script");
}
#[test]
fn test_determine_script_type_p2wpkh() {
let p2wpkh_script = vec![
0x00, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13,
];
let script = ByteString::from(p2wpkh_script);
let analysis = analyze_script(&script).expect("Analysis should succeed");
assert_eq!(
analysis.script_type, "P2WPKH",
"Should detect P2WPKH script"
);
}
#[test]
fn test_determine_script_type_p2wsh() {
let p2wsh_script = vec![
0x00, 0x20, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f,
];
let script = ByteString::from(p2wsh_script);
let analysis = analyze_script(&script).expect("Analysis should succeed");
assert_eq!(analysis.script_type, "P2WSH", "Should detect P2WSH script");
}
#[test]
fn test_determine_script_type_p2tr() {
let p2tr_script = vec![
0x51, 0x20, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f,
];
let script = ByteString::from(p2tr_script);
let analysis = analyze_script(&script).expect("Analysis should succeed");
assert_eq!(analysis.script_type, "P2TR", "Should detect P2TR script");
}
#[test]
fn test_parse_descriptor_pkh() {
let descriptor_str =
"pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914)";
let result = parse_descriptor(descriptor_str);
assert!(result.is_ok(), "P2PKH descriptor parsing should succeed");
}
#[test]
fn test_parse_descriptor_wpkh() {
let descriptor_str =
"wpkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914)";
let result = parse_descriptor(descriptor_str);
assert!(result.is_ok(), "P2WPKH descriptor parsing should succeed");
}
#[test]
fn test_parse_descriptor_sh() {
let descriptor_str =
"sh(wpkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914))";
let result = parse_descriptor(descriptor_str);
assert!(result.is_ok(), "P2SH descriptor parsing should succeed");
}
#[test]
fn test_parse_descriptor_multisig() {
let descriptor_str = "sh(multi(2,02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914,03e60fce93b59e9ec53011aabc21c23e97b2a31369b87a5ae9c44ee89e2a6dec0))";
let result = parse_descriptor(descriptor_str);
assert!(result.is_ok(), "Multisig descriptor parsing should succeed");
}
#[test]
fn test_parse_descriptor_invalid() {
let descriptor_str = "invalid_descriptor";
let result = parse_descriptor(descriptor_str);
assert!(result.is_err(), "Invalid descriptor should fail to parse");
}
#[test]
fn test_analyze_script_miniscript() {
let policy_str = "pk(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914)";
let policy: Policy<bitcoin::PublicKey> =
Policy::from_str(policy_str).expect("Failed to parse policy");
let script = compile_policy(&policy).expect("Policy compilation should succeed");
let analysis = analyze_script(&script).expect("Script analysis should succeed");
assert!(
!analysis.script_type.is_empty(),
"Script type should be determined"
);
}
#[test]
fn test_analyze_script_non_miniscript() {
let random_script = vec![0x51, 0x52, 0x53, 0x54]; let script = ByteString::from(random_script);
let analysis =
analyze_script(&script).expect("Analysis should succeed even for non-miniscript");
assert!(!analysis.is_miniscript, "Non-miniscript should be detected");
assert_eq!(
analysis.satisfaction_weight, None,
"Non-miniscript should have no satisfaction weight"
);
assert_eq!(
analysis.script_type, "Unknown",
"Unknown script type should be detected"
);
}
#[test]
fn test_compile_invalid_policy() {
let policy_str = "pk(00)"; let policy_result = Policy::from_str(policy_str);
if let Ok(policy) = policy_result {
let compile_result = compile_policy(&policy);
assert!(
compile_result.is_ok() || compile_result.is_err(),
"Compilation should handle errors gracefully"
);
}
}
#[test]
fn test_parse_invalid_script() {
let invalid_script = vec![0x00]; let script = ByteString::from(invalid_script);
let result = parse_script(&script);
assert!(
result.is_ok() || result.is_err(),
"Parsing should handle invalid scripts gracefully"
);
}
#[test]
fn test_satisfaction_weight() {
let policy_str = "pk(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914)";
let policy: Policy<bitcoin::PublicKey> =
Policy::from_str(policy_str).expect("Failed to parse policy");
let script = compile_policy(&policy).expect("Policy compilation should succeed");
let analysis = analyze_script(&script).expect("Script analysis should succeed");
if analysis.is_miniscript {
assert!(
analysis.satisfaction_weight.is_some(),
"Miniscript should have satisfaction weight"
);
}
}
}
#[cfg(feature = "miniscript")]
mod rpc_tests {
use blvm_node::rpc::miniscript::miniscript_rpc;
use serde_json::json;
#[tokio::test]
async fn test_getdescriptorinfo_valid() {
let descriptor = "pkh(02c6047f9441ed7d6d3045406e95c07cd85c778e4b8a8f3af4eb0c8666e7c1914)";
let params = json!([descriptor]);
let result = miniscript_rpc::get_descriptor_info(¶ms).await;
assert!(result.is_ok(), "getdescriptorinfo should succeed");
let response = result.unwrap();
assert!(
response.get("descriptor").is_some(),
"Response should contain descriptor"
);
assert!(
response.get("issolvable").is_some(),
"Response should contain issolvable"
);
}
#[tokio::test]
async fn test_getdescriptorinfo_invalid() {
let descriptor = "invalid_descriptor";
let params = json!([descriptor]);
let result = miniscript_rpc::get_descriptor_info(¶ms).await;
assert!(
result.is_ok(),
"getdescriptorinfo should handle invalid descriptors"
);
let response = result.unwrap();
assert_eq!(
response.get("issolvable").and_then(|v| v.as_bool()),
Some(false),
"Invalid descriptor should have issolvable=false"
);
}
#[tokio::test]
async fn test_getdescriptorinfo_missing_param() {
let params = json!([]);
let result = miniscript_rpc::get_descriptor_info(¶ms).await;
assert!(
result.is_err(),
"getdescriptorinfo should fail with missing parameter"
);
}
#[tokio::test]
async fn test_analyzepsbt() {
let psbt =
"cHNidP8BAH0CAAAAASuBBAO7r9HADl0R9l5z0z8BAAAAAAD/////AQAAAAAAAAAAAACAAQAAAAAB6wQAAAAA";
let params = json!([psbt]);
let result = miniscript_rpc::analyze_psbt(¶ms).await;
assert!(result.is_ok(), "analyzepsbt should succeed (placeholder)");
let response = result.unwrap();
assert!(
response.get("inputs").is_some(),
"Response should contain inputs"
);
}
}