bdk_wallet/descriptor/
checksum.rs1use crate::descriptor::DescriptorError;
18use alloc::string::String;
19
20use miniscript::descriptor::checksum::desc_checksum;
21
22pub fn calc_checksum(desc: &str) -> Result<String, DescriptorError> {
25 if let Some(split) = desc.split_once('#') {
26 let og_checksum = split.1;
27 let checksum = desc_checksum(split.0)?;
28 if og_checksum != checksum {
29 return Err(DescriptorError::InvalidDescriptorChecksum);
30 }
31 Ok(checksum)
32 } else {
33 Ok(desc_checksum(desc)?)
34 }
35}
36
37#[cfg(test)]
38mod test {
39 use super::*;
40 use crate::descriptor::calc_checksum;
41 use assert_matches::assert_matches;
42
43 #[test]
45 fn test_calc_checksum() {
46 let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
47 assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
48
49 let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
50 assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
51 }
52
53 #[test]
56 fn test_calc_checksum_with_checksum_hash() {
57 let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62";
58 assert_eq!(calc_checksum(desc).unwrap(), "tqz0nc62");
59
60 let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmfs";
61 assert_eq!(calc_checksum(desc).unwrap(), "lasegmfs");
62
63 let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc26";
64 assert_matches!(
65 calc_checksum(desc),
66 Err(DescriptorError::InvalidDescriptorChecksum)
67 );
68
69 let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)#lasegmsf";
70 assert_matches!(
71 calc_checksum(desc),
72 Err(DescriptorError::InvalidDescriptorChecksum)
73 );
74 }
75
76 #[test]
77 fn test_calc_checksum_invalid_character() {
78 let sparkle_heart = unsafe { core::str::from_utf8_unchecked(&[240, 159, 146, 150]) };
79 let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{sparkle_heart}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)");
80
81 assert_matches!(
82 calc_checksum(&invalid_desc),
83 Err(DescriptorError::Miniscript(miniscript::Error::BadDescriptor(e))) if e == format!("Invalid character in checksum: '{sparkle_heart}'")
84 );
85 }
86}