Skip to content

Commit 741e672

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 75b217c commit 741e672

File tree

3 files changed

+88
-33
lines changed

3 files changed

+88
-33
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,6 @@ verify = []
6363
# Extra utility tools
6464
# Compile policies
6565
compiler = []
66+
67+
[dev-dependencies]
68+
claims = "0.8.0"

src/handlers.rs

Lines changed: 78 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,88 +1744,133 @@ mod test {
17441744
#[cfg(feature = "compiler")]
17451745
#[test]
17461746
fn test_compile_taproot() {
1747-
use super::{NUMS_UNSPENDABLE_KEY_HEX, handle_compile_subcommand};
1747+
use super::handle_compile_subcommand;
17481748
use bdk_wallet::bitcoin::Network;
1749-
1750-
// Expected taproot descriptors with checksums (using NUMS key from constant)
1751-
let expected_pk_a = format!("tr({},pk(A))#a2mlskt0", NUMS_UNSPENDABLE_KEY_HEX);
1752-
let expected_and_ab = format!(
1753-
"tr({},and_v(v:pk(A),pk(B)))#sfplm6kv",
1754-
NUMS_UNSPENDABLE_KEY_HEX
1755-
);
1749+
use claims::assert_ok;
17561750

17571751
// Test simple pk policy compilation to taproot
1758-
let result = handle_compile_subcommand(
1752+
let json_string = assert_ok!(handle_compile_subcommand(
17591753
Network::Testnet,
17601754
"pk(A)".to_string(),
17611755
"tr".to_string(),
17621756
false,
1763-
);
1764-
assert!(result.is_ok());
1765-
let json_string = result.unwrap();
1757+
));
17661758
let json_result: serde_json::Value = serde_json::from_str(&json_string).unwrap();
1759+
17671760
let descriptor = json_result.get("descriptor").unwrap().as_str().unwrap();
1768-
assert_eq!(descriptor, expected_pk_a);
1761+
assert!(descriptor.starts_with("tr("));
1762+
assert!(descriptor.contains(",pk(A))#"));
1763+
assert!(json_result.get("r").is_some());
17691764

17701765
// Test more complex policy
1771-
let result = handle_compile_subcommand(
1766+
let json_string = assert_ok!(handle_compile_subcommand(
17721767
Network::Testnet,
17731768
"and(pk(A),pk(B))".to_string(),
17741769
"tr".to_string(),
17751770
false,
1776-
);
1777-
assert!(result.is_ok());
1778-
let json_string = result.unwrap();
1771+
));
17791772
let json_result: serde_json::Value = serde_json::from_str(&json_string).unwrap();
1773+
17801774
let descriptor = json_result.get("descriptor").unwrap().as_str().unwrap();
1781-
assert_eq!(descriptor, expected_and_ab);
1775+
assert!(descriptor.starts_with("tr("));
1776+
assert!(descriptor.contains(",and_v(v:pk(A),pk(B)))#"));
1777+
assert!(json_result.get("r").is_some());
1778+
}
1779+
1780+
#[cfg(feature = "compiler")]
1781+
#[test]
1782+
fn test_compile_non_taproot_has_no_r() {
1783+
use super::handle_compile_subcommand;
1784+
use bdk_wallet::bitcoin::Network;
1785+
use claims::assert_ok;
1786+
1787+
let json_string = assert_ok!(handle_compile_subcommand(
1788+
Network::Testnet,
1789+
"pk(A)".to_string(),
1790+
"wsh".to_string(),
1791+
false,
1792+
));
1793+
let json_result: serde_json::Value = serde_json::from_str(&json_string).unwrap();
1794+
1795+
let descriptor = json_result.get("descriptor").unwrap().as_str().unwrap();
1796+
assert!(descriptor.starts_with("wsh(pk(A))#"));
1797+
assert!(json_result.get("r").is_none());
1798+
}
1799+
1800+
#[cfg(feature = "compiler")]
1801+
#[test]
1802+
fn test_compile_taproot_randomness() {
1803+
use super::handle_compile_subcommand;
1804+
use bdk_wallet::bitcoin::Network;
1805+
use claims::assert_ok;
1806+
1807+
// Two compilations of the same policy should produce different internal keys
1808+
let result1 = assert_ok!(handle_compile_subcommand(
1809+
Network::Testnet,
1810+
"pk(A)".to_string(),
1811+
"tr".to_string(),
1812+
false,
1813+
));
1814+
let result2 = assert_ok!(handle_compile_subcommand(
1815+
Network::Testnet,
1816+
"pk(A)".to_string(),
1817+
"tr".to_string(),
1818+
false,
1819+
));
1820+
1821+
let json1: serde_json::Value = serde_json::from_str(&result1).unwrap();
1822+
let json2: serde_json::Value = serde_json::from_str(&result2).unwrap();
1823+
1824+
let r1 = json1.get("r").unwrap().as_str().unwrap();
1825+
let r2 = json2.get("r").unwrap().as_str().unwrap();
1826+
assert_ne!(r1, r2, "Each compilation should produce a unique r value");
17821827
}
17831828

17841829
#[cfg(feature = "compiler")]
17851830
#[test]
17861831
fn test_compile_invalid_cases() {
17871832
use super::handle_compile_subcommand;
17881833
use bdk_wallet::bitcoin::Network;
1834+
use claims::assert_err;
17891835

17901836
// Test invalid policy syntax
1791-
let result = handle_compile_subcommand(
1837+
assert_err!(handle_compile_subcommand(
17921838
Network::Testnet,
17931839
"invalid_policy".to_string(),
17941840
"tr".to_string(),
17951841
false,
1796-
);
1797-
assert!(result.is_err());
1842+
));
17981843

17991844
// Test invalid script type
1800-
let result = handle_compile_subcommand(
1845+
assert_err!(handle_compile_subcommand(
18011846
Network::Testnet,
18021847
"pk(A)".to_string(),
18031848
"invalid_type".to_string(),
18041849
false,
1805-
);
1806-
assert!(result.is_err());
1850+
));
18071851

18081852
// Test empty policy
1809-
let result =
1810-
handle_compile_subcommand(Network::Testnet, "".to_string(), "tr".to_string(), false);
1811-
assert!(result.is_err());
1853+
assert_err!(handle_compile_subcommand(
1854+
Network::Testnet,
1855+
"".to_string(),
1856+
"tr".to_string(),
1857+
false,
1858+
));
18121859

18131860
// Test malformed policy with unmatched parentheses
1814-
let result = handle_compile_subcommand(
1861+
assert_err!(handle_compile_subcommand(
18151862
Network::Testnet,
18161863
"pk(A".to_string(),
18171864
"tr".to_string(),
18181865
false,
1819-
);
1820-
assert!(result.is_err());
1866+
));
18211867

18221868
// Test policy with unknown function
1823-
let result = handle_compile_subcommand(
1869+
assert_err!(handle_compile_subcommand(
18241870
Network::Testnet,
18251871
"unknown_func(A)".to_string(),
18261872
"tr".to_string(),
18271873
false,
1828-
);
1829-
assert!(result.is_err());
1874+
));
18301875
}
18311876
}

0 commit comments

Comments
 (0)