Skip to content

Commit ac92463

Browse files
committed
test(compile): add tests for randomized taproot internal key
Add `claims` dev-dependency for ergonomic `assert_ok!`/`assert_err!` macros. Adapt compile tests to verify randomized key behavior: - descriptor structure instead of exact match (key is now random) - presence of `r` field for taproot, absence for other types - uniqueness of `r` across compilations
1 parent 5e90452 commit ac92463

2 files changed

Lines changed: 81 additions & 33 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,6 @@ verify = []
6565
# Extra utility tools
6666
# Compile policies
6767
compiler = []
68+
69+
[dev-dependencies]
70+
claims = "0.8.0"

src/handlers.rs

Lines changed: 78 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,88 +1790,133 @@ mod test {
17901790
#[cfg(feature = "compiler")]
17911791
#[test]
17921792
fn test_compile_taproot() {
1793-
use super::{NUMS_UNSPENDABLE_KEY_HEX, handle_compile_subcommand};
1793+
use super::handle_compile_subcommand;
17941794
use bdk_wallet::bitcoin::Network;
1795-
1796-
// Expected taproot descriptors with checksums (using NUMS key from constant)
1797-
let expected_pk_a = format!("tr({},pk(A))#a2mlskt0", NUMS_UNSPENDABLE_KEY_HEX);
1798-
let expected_and_ab = format!(
1799-
"tr({},and_v(v:pk(A),pk(B)))#sfplm6kv",
1800-
NUMS_UNSPENDABLE_KEY_HEX
1801-
);
1795+
use claims::assert_ok;
18021796

18031797
// Test simple pk policy compilation to taproot
1804-
let result = handle_compile_subcommand(
1798+
let json_string = assert_ok!(handle_compile_subcommand(
18051799
Network::Testnet,
18061800
"pk(A)".to_string(),
18071801
"tr".to_string(),
18081802
false,
1809-
);
1810-
assert!(result.is_ok());
1811-
let json_string = result.unwrap();
1803+
));
18121804
let json_result: serde_json::Value = serde_json::from_str(&json_string).unwrap();
1805+
18131806
let descriptor = json_result.get("descriptor").unwrap().as_str().unwrap();
1814-
assert_eq!(descriptor, expected_pk_a);
1807+
assert!(descriptor.starts_with("tr("));
1808+
assert!(descriptor.contains(",pk(A))#"));
1809+
assert!(json_result.get("r").is_some());
18151810

18161811
// Test more complex policy
1817-
let result = handle_compile_subcommand(
1812+
let json_string = assert_ok!(handle_compile_subcommand(
18181813
Network::Testnet,
18191814
"and(pk(A),pk(B))".to_string(),
18201815
"tr".to_string(),
18211816
false,
1822-
);
1823-
assert!(result.is_ok());
1824-
let json_string = result.unwrap();
1817+
));
18251818
let json_result: serde_json::Value = serde_json::from_str(&json_string).unwrap();
1819+
18261820
let descriptor = json_result.get("descriptor").unwrap().as_str().unwrap();
1827-
assert_eq!(descriptor, expected_and_ab);
1821+
assert!(descriptor.starts_with("tr("));
1822+
assert!(descriptor.contains(",and_v(v:pk(A),pk(B)))#"));
1823+
assert!(json_result.get("r").is_some());
1824+
}
1825+
1826+
#[cfg(feature = "compiler")]
1827+
#[test]
1828+
fn test_compile_non_taproot_has_no_r() {
1829+
use super::handle_compile_subcommand;
1830+
use bdk_wallet::bitcoin::Network;
1831+
use claims::assert_ok;
1832+
1833+
let json_string = assert_ok!(handle_compile_subcommand(
1834+
Network::Testnet,
1835+
"pk(A)".to_string(),
1836+
"wsh".to_string(),
1837+
false,
1838+
));
1839+
let json_result: serde_json::Value = serde_json::from_str(&json_string).unwrap();
1840+
1841+
let descriptor = json_result.get("descriptor").unwrap().as_str().unwrap();
1842+
assert!(descriptor.starts_with("wsh(pk(A))#"));
1843+
assert!(json_result.get("r").is_none());
1844+
}
1845+
1846+
#[cfg(feature = "compiler")]
1847+
#[test]
1848+
fn test_compile_taproot_randomness() {
1849+
use super::handle_compile_subcommand;
1850+
use bdk_wallet::bitcoin::Network;
1851+
use claims::assert_ok;
1852+
1853+
// Two compilations of the same policy should produce different internal keys
1854+
let result1 = assert_ok!(handle_compile_subcommand(
1855+
Network::Testnet,
1856+
"pk(A)".to_string(),
1857+
"tr".to_string(),
1858+
false,
1859+
));
1860+
let result2 = assert_ok!(handle_compile_subcommand(
1861+
Network::Testnet,
1862+
"pk(A)".to_string(),
1863+
"tr".to_string(),
1864+
false,
1865+
));
1866+
1867+
let json1: serde_json::Value = serde_json::from_str(&result1).unwrap();
1868+
let json2: serde_json::Value = serde_json::from_str(&result2).unwrap();
1869+
1870+
let r1 = json1.get("r").unwrap().as_str().unwrap();
1871+
let r2 = json2.get("r").unwrap().as_str().unwrap();
1872+
assert_ne!(r1, r2, "Each compilation should produce a unique r value");
18281873
}
18291874

18301875
#[cfg(feature = "compiler")]
18311876
#[test]
18321877
fn test_compile_invalid_cases() {
18331878
use super::handle_compile_subcommand;
18341879
use bdk_wallet::bitcoin::Network;
1880+
use claims::assert_err;
18351881

18361882
// Test invalid policy syntax
1837-
let result = handle_compile_subcommand(
1883+
assert_err!(handle_compile_subcommand(
18381884
Network::Testnet,
18391885
"invalid_policy".to_string(),
18401886
"tr".to_string(),
18411887
false,
1842-
);
1843-
assert!(result.is_err());
1888+
));
18441889

18451890
// Test invalid script type
1846-
let result = handle_compile_subcommand(
1891+
assert_err!(handle_compile_subcommand(
18471892
Network::Testnet,
18481893
"pk(A)".to_string(),
18491894
"invalid_type".to_string(),
18501895
false,
1851-
);
1852-
assert!(result.is_err());
1896+
));
18531897

18541898
// Test empty policy
1855-
let result =
1856-
handle_compile_subcommand(Network::Testnet, "".to_string(), "tr".to_string(), false);
1857-
assert!(result.is_err());
1899+
assert_err!(handle_compile_subcommand(
1900+
Network::Testnet,
1901+
"".to_string(),
1902+
"tr".to_string(),
1903+
false,
1904+
));
18581905

18591906
// Test malformed policy with unmatched parentheses
1860-
let result = handle_compile_subcommand(
1907+
assert_err!(handle_compile_subcommand(
18611908
Network::Testnet,
18621909
"pk(A".to_string(),
18631910
"tr".to_string(),
18641911
false,
1865-
);
1866-
assert!(result.is_err());
1912+
));
18671913

18681914
// Test policy with unknown function
1869-
let result = handle_compile_subcommand(
1915+
assert_err!(handle_compile_subcommand(
18701916
Network::Testnet,
18711917
"unknown_func(A)".to_string(),
18721918
"tr".to_string(),
18731919
false,
1874-
);
1875-
assert!(result.is_err());
1920+
));
18761921
}
18771922
}

0 commit comments

Comments
 (0)