sapio_miniscript/descriptor/
pretaproot.rs1use std::{
2 fmt,
3 str::{self, FromStr},
4};
5
6use bitcoin::{self, Script};
7
8use super::{checksum::verify_checksum, Bare, Pkh, Sh, Wpkh, Wsh};
9use {expression, DescriptorTrait, Error, MiniscriptKey, Satisfier, ToPublicKey};
10
11#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum PreTaprootDescriptor<Pk: MiniscriptKey> {
14 Bare(Bare<Pk>),
16 Pkh(Pkh<Pk>),
18 Wpkh(Wpkh<Pk>),
20 Sh(Sh<Pk>),
22 Wsh(Wsh<Pk>),
24}
25
26impl<Pk: MiniscriptKey> DescriptorTrait<Pk> for PreTaprootDescriptor<Pk> {
27 fn sanity_check(&self) -> Result<(), Error> {
36 match *self {
37 PreTaprootDescriptor::Bare(ref bare) => bare.sanity_check(),
38 PreTaprootDescriptor::Pkh(ref pkh) => pkh.sanity_check(),
39 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.sanity_check(),
40 PreTaprootDescriptor::Wsh(ref wsh) => wsh.sanity_check(),
41 PreTaprootDescriptor::Sh(ref sh) => sh.sanity_check(),
42 }
43 }
44 fn address(&self, network: bitcoin::Network) -> Result<bitcoin::Address, Error>
46 where
47 Pk: ToPublicKey,
48 {
49 match *self {
50 PreTaprootDescriptor::Bare(ref bare) => bare.address(network),
51 PreTaprootDescriptor::Pkh(ref pkh) => pkh.address(network),
52 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.address(network),
53 PreTaprootDescriptor::Wsh(ref wsh) => wsh.address(network),
54 PreTaprootDescriptor::Sh(ref sh) => sh.address(network),
55 }
56 }
57
58 fn script_pubkey(&self) -> Script
60 where
61 Pk: ToPublicKey,
62 {
63 match *self {
64 PreTaprootDescriptor::Bare(ref bare) => bare.script_pubkey(),
65 PreTaprootDescriptor::Pkh(ref pkh) => pkh.script_pubkey(),
66 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.script_pubkey(),
67 PreTaprootDescriptor::Wsh(ref wsh) => wsh.script_pubkey(),
68 PreTaprootDescriptor::Sh(ref sh) => sh.script_pubkey(),
69 }
70 }
71
72 fn unsigned_script_sig(&self) -> Script
81 where
82 Pk: ToPublicKey,
83 {
84 match *self {
85 PreTaprootDescriptor::Bare(ref bare) => bare.unsigned_script_sig(),
86 PreTaprootDescriptor::Pkh(ref pkh) => pkh.unsigned_script_sig(),
87 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.unsigned_script_sig(),
88 PreTaprootDescriptor::Wsh(ref wsh) => wsh.unsigned_script_sig(),
89 PreTaprootDescriptor::Sh(ref sh) => sh.unsigned_script_sig(),
90 }
91 }
92
93 fn explicit_script(&self) -> Result<Script, Error>
100 where
101 Pk: ToPublicKey,
102 {
103 match *self {
104 PreTaprootDescriptor::Bare(ref bare) => bare.explicit_script(),
105 PreTaprootDescriptor::Pkh(ref pkh) => pkh.explicit_script(),
106 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.explicit_script(),
107 PreTaprootDescriptor::Wsh(ref wsh) => wsh.explicit_script(),
108 PreTaprootDescriptor::Sh(ref sh) => sh.explicit_script(),
109 }
110 }
111
112 fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
116 where
117 Pk: ToPublicKey,
118 S: Satisfier<Pk>,
119 {
120 match *self {
121 PreTaprootDescriptor::Bare(ref bare) => bare.get_satisfaction(satisfier),
122 PreTaprootDescriptor::Pkh(ref pkh) => pkh.get_satisfaction(satisfier),
123 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction(satisfier),
124 PreTaprootDescriptor::Wsh(ref wsh) => wsh.get_satisfaction(satisfier),
125 PreTaprootDescriptor::Sh(ref sh) => sh.get_satisfaction(satisfier),
126 }
127 }
128
129 fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
133 where
134 Pk: ToPublicKey,
135 S: Satisfier<Pk>,
136 {
137 match *self {
138 PreTaprootDescriptor::Bare(ref bare) => bare.get_satisfaction_mall(satisfier),
139 PreTaprootDescriptor::Pkh(ref pkh) => pkh.get_satisfaction_mall(satisfier),
140 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.get_satisfaction_mall(satisfier),
141 PreTaprootDescriptor::Wsh(ref wsh) => wsh.get_satisfaction_mall(satisfier),
142 PreTaprootDescriptor::Sh(ref sh) => sh.get_satisfaction_mall(satisfier),
143 }
144 }
145
146 fn max_satisfaction_weight(&self) -> Result<usize, Error> {
151 match *self {
152 PreTaprootDescriptor::Bare(ref bare) => bare.max_satisfaction_weight(),
153 PreTaprootDescriptor::Pkh(ref pkh) => pkh.max_satisfaction_weight(),
154 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.max_satisfaction_weight(),
155 PreTaprootDescriptor::Wsh(ref wsh) => wsh.max_satisfaction_weight(),
156 PreTaprootDescriptor::Sh(ref sh) => sh.max_satisfaction_weight(),
157 }
158 }
159
160 fn script_code(&self) -> Result<Script, Error>
166 where
167 Pk: ToPublicKey,
168 {
169 match *self {
170 PreTaprootDescriptor::Bare(ref bare) => bare.script_code(),
171 PreTaprootDescriptor::Pkh(ref pkh) => pkh.script_code(),
172 PreTaprootDescriptor::Wpkh(ref wpkh) => wpkh.script_code(),
173 PreTaprootDescriptor::Wsh(ref wsh) => wsh.script_code(),
174 PreTaprootDescriptor::Sh(ref sh) => sh.script_code(),
175 }
176 }
177}
178
179impl<Pk> expression::FromTree for PreTaprootDescriptor<Pk>
180where
181 Pk: MiniscriptKey + str::FromStr,
182 Pk::Hash: str::FromStr,
183 <Pk as FromStr>::Err: ToString,
184 <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
185{
186 fn from_tree(top: &expression::Tree) -> Result<PreTaprootDescriptor<Pk>, Error> {
188 Ok(match (top.name, top.args.len() as u32) {
189 ("pkh", 1) => PreTaprootDescriptor::Pkh(Pkh::from_tree(top)?),
190 ("wpkh", 1) => PreTaprootDescriptor::Wpkh(Wpkh::from_tree(top)?),
191 ("sh", 1) => PreTaprootDescriptor::Sh(Sh::from_tree(top)?),
192 ("wsh", 1) => PreTaprootDescriptor::Wsh(Wsh::from_tree(top)?),
193 _ => PreTaprootDescriptor::Bare(Bare::from_tree(top)?),
194 })
195 }
196}
197
198impl<Pk> FromStr for PreTaprootDescriptor<Pk>
199where
200 Pk: MiniscriptKey + str::FromStr,
201 Pk::Hash: str::FromStr,
202 <Pk as FromStr>::Err: ToString,
203 <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString,
204{
205 type Err = Error;
206
207 fn from_str(s: &str) -> Result<PreTaprootDescriptor<Pk>, Error> {
208 let desc_str = verify_checksum(s)?;
209 let top = expression::Tree::from_str(desc_str)?;
210 expression::FromTree::from_tree(&top)
211 }
212}
213
214impl<Pk: MiniscriptKey> fmt::Debug for PreTaprootDescriptor<Pk> {
215 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
216 match *self {
217 PreTaprootDescriptor::Bare(ref sub) => write!(f, "{:?}", sub),
218 PreTaprootDescriptor::Pkh(ref pkh) => write!(f, "{:?}", pkh),
219 PreTaprootDescriptor::Wpkh(ref wpkh) => write!(f, "{:?}", wpkh),
220 PreTaprootDescriptor::Sh(ref sub) => write!(f, "{:?}", sub),
221 PreTaprootDescriptor::Wsh(ref sub) => write!(f, "{:?}", sub),
222 }
223 }
224}
225
226impl<Pk: MiniscriptKey> fmt::Display for PreTaprootDescriptor<Pk> {
227 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
228 match *self {
229 PreTaprootDescriptor::Bare(ref sub) => write!(f, "{}", sub),
230 PreTaprootDescriptor::Pkh(ref pkh) => write!(f, "{}", pkh),
231 PreTaprootDescriptor::Wpkh(ref wpkh) => write!(f, "{}", wpkh),
232 PreTaprootDescriptor::Sh(ref sub) => write!(f, "{}", sub),
233 PreTaprootDescriptor::Wsh(ref sub) => write!(f, "{}", sub),
234 }
235 }
236}
237
238serde_string_impl_pk!(PreTaprootDescriptor, "a pre-taproot script descriptor");
239
240pub(crate) mod traits {
242 use bitcoin::Script;
243
244 use {
245 descriptor::{Pkh, Sh, Wpkh, Wsh},
246 DescriptorTrait, MiniscriptKey, ToPublicKey,
247 };
248
249 use super::PreTaprootDescriptor;
250
251 pub trait PreTaprootDescriptorTrait<Pk: MiniscriptKey>: DescriptorTrait<Pk> {
254 fn explicit_script(&self) -> Script
257 where
258 Pk: ToPublicKey,
259 {
260 <Self as DescriptorTrait<Pk>>::explicit_script(&self)
263 .expect("Pre taproot descriptor have explicit script")
264 }
265
266 fn script_code(&self) -> Script
269 where
270 Pk: ToPublicKey,
271 {
272 <Self as DescriptorTrait<Pk>>::script_code(&self)
273 .expect("Pre taproot descriptor have non-failing script code")
274 }
275 }
276
277 impl<Pk: MiniscriptKey> PreTaprootDescriptorTrait<Pk> for Pkh<Pk> {}
278
279 impl<Pk: MiniscriptKey> PreTaprootDescriptorTrait<Pk> for Sh<Pk> {}
280
281 impl<Pk: MiniscriptKey> PreTaprootDescriptorTrait<Pk> for Wpkh<Pk> {}
282
283 impl<Pk: MiniscriptKey> PreTaprootDescriptorTrait<Pk> for Wsh<Pk> {}
284
285 impl<Pk: MiniscriptKey> PreTaprootDescriptorTrait<Pk> for PreTaprootDescriptor<Pk> {}
286}