1#![deny(unsafe_code)]
43#![deny(non_upper_case_globals)]
44#![deny(non_camel_case_types)]
45#![deny(non_snake_case)]
46#![deny(unused_mut)]
47#![deny(dead_code)]
48#![deny(unused_imports)]
49#![deny(missing_docs)]
50
51#[cfg(not(any(feature = "std")))]
52compile_error!("`std` must be enabled");
53
54pub mod decoder;
55mod dummy;
56pub mod encoder;
57mod tag;
58mod test_helpers;
59mod varint;
60
61pub use decoder::Error;
62
63use bitcoin::{
64 hashes::{hash160, ripemd160, sha256},
65 secp256k1,
66};
67use miniscript::{
68 Descriptor, TranslatePk, Translator,
69 descriptor::{DescriptorPublicKey, DescriptorSecretKey, KeyMap},
70 hash256,
71};
72use std::collections::BTreeMap;
73use std::str::FromStr;
74
75pub fn encode(s: &str) -> Result<Vec<u8>, miniscript::Error> {
77 let secp = secp256k1::Secp256k1::new();
78 let (descriptor, key_map) = parse_descriptor(&secp, s)?;
79 let (mut template, mut payload) = encoder::encode(descriptor, &key_map);
80 template.append(&mut payload);
81 Ok(template)
82}
83
84pub fn decode(bytes: &[u8]) -> Result<String, Error> {
86 let (_, _, size) = decoder::decode_template(bytes)?;
87 let (descriptor, key_map) = decoder::decode_with_payload(&bytes[..size], &bytes[size..])?;
88 Ok(descriptor.to_string_with_secret(&key_map))
89}
90
91fn parse_descriptor<C: secp256k1::Signing>(
99 secp: &secp256k1::Secp256k1<C>,
100 s: &str,
101) -> Result<(Descriptor<DescriptorPublicKey>, KeyMap), miniscript::Error> {
102 fn parse_key<C: secp256k1::Signing>(
103 s: &str,
104 key_map: &mut KeyMap,
105 secp: &secp256k1::Secp256k1<C>,
106 ) -> Result<DescriptorPublicKey, miniscript::Error> {
107 let (public_key, secret_key) = match DescriptorSecretKey::from_str(s) {
108 Ok(sk) => (
109 sk.to_public(secp)
110 .unwrap_or(test_helpers::create_dpk_single_compressed_no_origin(
111 1 + key_map.len() as u32,
112 )),
113 Some(sk),
114 ),
115 Err(_) => (
116 DescriptorPublicKey::from_str(s)
117 .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?,
118 None,
119 ),
120 };
121
122 if let Some(secret_key) = secret_key {
123 key_map.insert(public_key.clone(), secret_key);
124 }
125
126 Ok(public_key)
127 }
128
129 let mut keymap_pk = KeyMapWrapper(BTreeMap::new(), secp);
130
131 struct KeyMapWrapper<'a, C: secp256k1::Signing>(KeyMap, &'a secp256k1::Secp256k1<C>);
132
133 impl<C: secp256k1::Signing> Translator<String, DescriptorPublicKey, miniscript::Error>
134 for KeyMapWrapper<'_, C>
135 {
136 fn pk(&mut self, pk: &String) -> Result<DescriptorPublicKey, miniscript::Error> {
137 parse_key(pk, &mut self.0, self.1)
138 }
139
140 fn sha256(&mut self, sha256: &String) -> Result<sha256::Hash, miniscript::Error> {
141 let hash = sha256::Hash::from_str(sha256)
142 .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?;
143 Ok(hash)
144 }
145
146 fn hash256(&mut self, hash256: &String) -> Result<hash256::Hash, miniscript::Error> {
147 let hash = hash256::Hash::from_str(hash256)
148 .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?;
149 Ok(hash)
150 }
151
152 fn ripemd160(&mut self, ripemd160: &String) -> Result<ripemd160::Hash, miniscript::Error> {
153 let hash = ripemd160::Hash::from_str(ripemd160)
154 .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?;
155 Ok(hash)
156 }
157
158 fn hash160(&mut self, hash160: &String) -> Result<hash160::Hash, miniscript::Error> {
159 let hash = hash160::Hash::from_str(hash160)
160 .map_err(|e| miniscript::Error::Unexpected(e.to_string()))?;
161 Ok(hash)
162 }
163 }
164
165 let descriptor = Descriptor::<String>::from_str(s)?;
166 let descriptor = descriptor
167 .translate_pk(&mut keymap_pk)
168 .map_err(miniscript::TranslateErr::flatten)?;
169
170 Ok((descriptor, keymap_pk.0))
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_integration() {
179 let descriptors = vec![
180 "sh(sortedmulti(2,[2c49202a/45'/0'/0'/0]xpub6EigxozzGaNVWUwEFnbyX6oHPdpWTKgJgbfpRbAcdiGpGMrdpPinCoHBXehu35sqJHpgLDTxigAnFQG3opKjXQoSmGMrMNHz81ALZSBRCWw/0/*,[55b43a50/45'/0'/0'/0]xpub6EAtA5XJ6pwFQ7L32iAJMgiWQEcrwU75NNWQ6H6eavwznDFeGFzTbSFdDKNdbG2HQdZvzrXuCyEYSSJ4cGsmfoPkKUKQ6haNKMRqG4pD4xi/0/*,[35931b5e/0/0/0/0]xpub6EDykLBC5EfaDNC7Mpg2H8veCaJHDgxH2JQvRtxJrbyeAhXWV2jJzB9XL4jMiFN5TzQefYi4V4nDiH4bxhkrweQ3Smxc8uP4ux9HrMGV81P/0/*))#2esvpcaf",
181 "wsh(sortedmulti(2,[3abf21c8/48'/0'/0'/2']xpub6DYotmPf2kXFYhJMFDpfydjiXG1RzmH1V7Fnn2Z38DgN2oSYruczMyTFZZPz6yXq47Re8anhXWGj4yMzPTA3bjPDdpA96TLUbMehrH3sBna/<0;1>/*,[a1a4bd46/48'/0'/0'/2']xpub6DvXYo8BwnRACos42ME7tNL48JQhLMQ33ENfniLM9KZmeZGbBhyh1Jkfo3hUKmmjW92o3r7BprTPPdrTr4QLQR7aRnSBfz1UFMceW5ibhTc/<0;1>/*,[ed91913d/48'/0'/0'/2']xpub6EQUho4Z4pwh2UQGdPjoPrbtjd6qqseKZCEBLcZbJ7y6c9XBWHRkhERiADJfwRcUs14nQsxF3hvx7aFkbk3tfp4dnKfkcns217kBTVVN5gY/<0;1>/*))#e7m305nf",
182 "sh(wsh(sortedmulti(2,[2c49202a/45'/0'/0'/0]xpub6EigxozzGaNVWUwEFnbyX6oHPdpWTKgJgbfpRbAcdiGpGMrdpPinCoHBXehu35sqJHpgLDTxigAnFQG3opKjXQoSmGMrMNHz81ALZSBRCWw/0/*,[55b43a50/45'/0'/0'/0]xpub6EAtA5XJ6pwFQ7L32iAJMgiWQEcrwU75NNWQ6H6eavwznDFeGFzTbSFdDKNdbG2HQdZvzrXuCyEYSSJ4cGsmfoPkKUKQ6haNKMRqG4pD4xi/0/*,[35931b5e/0/0/0/0]xpub6EDykLBC5EfaDNC7Mpg2H8veCaJHDgxH2JQvRtxJrbyeAhXWV2jJzB9XL4jMiFN5TzQefYi4V4nDiH4bxhkrweQ3Smxc8uP4ux9HrMGV81P/0/*)))#c0t8r3nk",
183 "wsh(multi(2,02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e,03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556,023e9be8b82c7469c88b1912a61611dffb9f65bbf5a176952727e0046513eca0de))#qdgya3w5",
184 "wpkh(02f9308a019258c31049344f85f89d5229b531c845836f99b08601f113bce036f9)#8zl0zxma",
185 "sh(wsh(or_d(pk(03fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),and_v(v:pk(02d7924d4f7d43ea965a465ae3095ff41131e5946f3c85f79e44adbcf8e27e080e),older(1000)))))#ky8du3e6",
186 "wsh(thresh(4,pk([7258e4f9/44'/1'/0']tpubDCZrkQoEU3845aFKUu9VQBYWZtrTwxMzcxnBwKFCYXHD6gEXvtFcxddCCLFsEwmxQaG15izcHxj48SXg1QS5FQGMBx5Ak6deXKPAL7wauBU/0/*),s:pk([c80b1469/44'/1'/0']tpubDD3UwwHoNUF4F3Vi5PiUVTc3ji1uThuRfFyBexTSHoAcHuWW2z8qEE2YujegcLtgthr3wMp3ZauvNG9eT9xfJyxXCfNty8h6rDBYU8UU1qq/0/*),s:pk([4e5024fe/44'/1'/0']tpubDDLrpPymPLSCJyCMLQdmcWxrAWwsqqssm5NdxT2WSdEBPSXNXxwbeKtsHAyXPpLkhUyKovtZgCi47QxVpw9iVkg95UUgeevyAqtJ9dqBqa1/0/*),s:pk([3b1d1ee9/44'/1'/0']tpubDCmDTANBWPzf6d8Ap1J5Ku7J1Ay92MpHMrEV7M5muWxCrTBN1g5f1NPcjMEL6dJHxbvEKNZtYCdowaSTN81DAyLsmv6w6xjJHCQNkxrsrfu/0/*),sln:after(840000),sln:after(1050000),sln:after(1260000)))#fk029528",
187 "tr(c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5,{pk(fff97bd5755eeea420453a14355235d382f6472f8568a18b2f057a1460297556),pk(e493dbf1c10d80f3581e4904930b1404cc6c13900ee0758474fa94abe8c4cd13)})#2rqrdjrh",
188 "pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/0)#m6s0eyht",
189 "pkh(xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U/<2147483647';0>/0)#s0hk8xf9",
190 ];
191
192 for desc_str in descriptors {
193 assert_eq!(desc_str, decode(&encode(desc_str).unwrap()).unwrap());
194 }
195 }
196}