1use core::convert::TryFrom;
11use core::fmt;
12
13use bitcoin::script::PushBytes;
14use bitcoin::{script, Address, Network, ScriptBuf, Weight};
15
16use super::checksum::verify_checksum;
17use super::{SortedMultiVec, Wpkh, Wsh};
18use crate::descriptor::{write_descriptor, DefiniteDescriptorKey};
19use crate::expression::{self, FromTree};
20use crate::miniscript::context::ScriptContext;
21use crate::miniscript::satisfy::{Placeholder, Satisfaction};
22use crate::plan::AssetProvider;
23use crate::policy::{semantic, Liftable};
24use crate::prelude::*;
25use crate::util::{varint_len, witness_to_scriptsig};
26use crate::{
27 push_opcode_size, Error, ForEachKey, FromStrKey, Legacy, Miniscript, MiniscriptKey, Satisfier,
28 Segwitv0, ToPublicKey, TranslateErr, TranslatePk, Translator,
29};
30
31#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
33pub struct Sh<Pk: MiniscriptKey> {
34 inner: ShInner<Pk>,
36}
37
38#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
40pub enum ShInner<Pk: MiniscriptKey> {
41 Wsh(Wsh<Pk>),
43 Wpkh(Wpkh<Pk>),
45 SortedMulti(SortedMultiVec<Pk, Legacy>),
47 Ms(Miniscript<Pk, Legacy>),
49}
50
51impl<Pk: MiniscriptKey> Liftable<Pk> for Sh<Pk> {
52 fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
53 match self.inner {
54 ShInner::Wsh(ref wsh) => wsh.lift(),
55 ShInner::Wpkh(ref pk) => Ok(semantic::Policy::Key(pk.as_inner().clone())),
56 ShInner::SortedMulti(ref smv) => smv.lift(),
57 ShInner::Ms(ref ms) => ms.lift(),
58 }
59 }
60}
61
62impl<Pk: MiniscriptKey> fmt::Debug for Sh<Pk> {
63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 match self.inner {
65 ShInner::Wsh(ref wsh_inner) => write!(f, "sh({:?})", wsh_inner),
66 ShInner::Wpkh(ref pk) => write!(f, "sh({:?})", pk),
67 ShInner::SortedMulti(ref smv) => write!(f, "sh({:?})", smv),
68 ShInner::Ms(ref ms) => write!(f, "sh({:?})", ms),
69 }
70 }
71}
72
73impl<Pk: MiniscriptKey> fmt::Display for Sh<Pk> {
74 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
75 match self.inner {
76 ShInner::Wsh(ref wsh) => write_descriptor!(f, "sh({:#})", wsh),
77 ShInner::Wpkh(ref pk) => write_descriptor!(f, "sh({:#})", pk),
78 ShInner::SortedMulti(ref smv) => write_descriptor!(f, "sh({})", smv),
79 ShInner::Ms(ref ms) => write_descriptor!(f, "sh({})", ms),
80 }
81 }
82}
83
84impl<Pk: FromStrKey> crate::expression::FromTree for Sh<Pk> {
85 fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
86 if top.name == "sh" && top.args.len() == 1 {
87 let top = &top.args[0];
88 let inner = match top.name {
89 "wsh" => ShInner::Wsh(Wsh::from_tree(top)?),
90 "wpkh" => ShInner::Wpkh(Wpkh::from_tree(top)?),
91 "sortedmulti" => ShInner::SortedMulti(SortedMultiVec::from_tree(top)?),
92 _ => {
93 let sub = Miniscript::from_tree(top)?;
94 Legacy::top_level_checks(&sub)?;
95 ShInner::Ms(sub)
96 }
97 };
98 Ok(Sh { inner })
99 } else {
100 Err(Error::Unexpected(format!(
101 "{}({} args) while parsing sh descriptor",
102 top.name,
103 top.args.len(),
104 )))
105 }
106 }
107}
108
109impl<Pk: FromStrKey> core::str::FromStr for Sh<Pk> {
110 type Err = Error;
111 fn from_str(s: &str) -> Result<Self, Self::Err> {
112 let desc_str = verify_checksum(s)?;
113 let top = expression::Tree::from_str(desc_str)?;
114 Self::from_tree(&top)
115 }
116}
117
118impl<Pk: MiniscriptKey> Sh<Pk> {
119 pub fn into_inner(self) -> ShInner<Pk> { self.inner }
121
122 pub fn as_inner(&self) -> &ShInner<Pk> { &self.inner }
124
125 pub fn new(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
127 Legacy::top_level_checks(&ms)?;
129 Ok(Self { inner: ShInner::Ms(ms) })
130 }
131
132 pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
135 Ok(Self { inner: ShInner::SortedMulti(SortedMultiVec::new(k, pks)?) })
138 }
139
140 pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
142 Ok(Self { inner: ShInner::Wsh(Wsh::new(ms)?) })
143 }
144
145 pub fn new_with_wsh(wsh: Wsh<Pk>) -> Self { Self { inner: ShInner::Wsh(wsh) } }
147
148 pub fn sanity_check(&self) -> Result<(), Error> {
150 match self.inner {
151 ShInner::Wsh(ref wsh) => wsh.sanity_check()?,
152 ShInner::Wpkh(ref wpkh) => wpkh.sanity_check()?,
153 ShInner::SortedMulti(ref smv) => smv.sanity_check()?,
154 ShInner::Ms(ref ms) => ms.sanity_check()?,
155 }
156 Ok(())
157 }
158
159 pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
162 Ok(Self { inner: ShInner::Wsh(Wsh::new_sortedmulti(k, pks)?) })
165 }
166
167 pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
169 Ok(Self { inner: ShInner::Wpkh(Wpkh::new(pk)?) })
170 }
171
172 pub fn new_with_wpkh(wpkh: Wpkh<Pk>) -> Self { Self { inner: ShInner::Wpkh(wpkh) } }
174
175 pub fn max_weight_to_satisfy(&self) -> Result<Weight, Error> {
189 let (scriptsig_size, witness_size) = match self.inner {
190 ShInner::Wsh(ref wsh) => {
192 let scriptsig_size = 1 + 1 + 1 + 32;
194 let witness_size = wsh.max_weight_to_satisfy()?;
195 (scriptsig_size, witness_size)
196 }
197 ShInner::SortedMulti(ref smv) => {
198 let ss = smv.script_size();
199 let ps = push_opcode_size(ss);
200 let scriptsig_size = ps + ss + smv.max_satisfaction_size();
201 (scriptsig_size, Weight::ZERO)
202 }
203 ShInner::Wpkh(ref wpkh) => {
205 let scriptsig_size = 1 + 1 + 1 + 20;
207 let witness_size = wpkh.max_weight_to_satisfy();
208 (scriptsig_size, witness_size)
209 }
210 ShInner::Ms(ref ms) => {
211 let ss = ms.script_size();
212 let ps = push_opcode_size(ss);
213 let scriptsig_size = ps + ss + ms.max_satisfaction_size()?;
214 (scriptsig_size, Weight::ZERO)
215 }
216 };
217
218 let scriptsig_varint_diff = varint_len(scriptsig_size) - varint_len(0);
220
221 let wu = Weight::from_vb((scriptsig_varint_diff + scriptsig_size) as u64);
222 match wu {
223 Some(w) => Ok(w + witness_size),
224 None => Err(Error::CouldNotSatisfy),
225 }
226 }
227
228 #[deprecated(
238 since = "10.0.0",
239 note = "Use max_weight_to_satisfy instead. The method to count bytes was redesigned and the results will differ from max_weight_to_satisfy. For more details check rust-bitcoin/rust-miniscript#476."
240 )]
241 #[allow(deprecated)]
242 pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
243 Ok(match self.inner {
244 ShInner::Wsh(ref wsh) => 4 * 35 + wsh.max_satisfaction_weight()?,
246 ShInner::SortedMulti(ref smv) => {
247 let ss = smv.script_size();
248 let ps = push_opcode_size(ss);
249 let scriptsig_len = ps + ss + smv.max_satisfaction_size();
250 4 * (varint_len(scriptsig_len) + scriptsig_len)
251 }
252 ShInner::Wpkh(ref wpkh) => 4 * 23 + wpkh.max_satisfaction_weight(),
254 ShInner::Ms(ref ms) => {
255 let ss = ms.script_size();
256 let ps = push_opcode_size(ss);
257 let scriptsig_len = ps + ss + ms.max_satisfaction_size()?;
258 4 * (varint_len(scriptsig_len) + scriptsig_len)
259 }
260 })
261 }
262}
263
264impl<Pk: MiniscriptKey + ToPublicKey> Sh<Pk> {
265 pub fn script_pubkey(&self) -> ScriptBuf {
267 match self.inner {
268 ShInner::Wsh(ref wsh) => wsh.script_pubkey().to_p2sh(),
269 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey().to_p2sh(),
270 ShInner::SortedMulti(ref smv) => smv.encode().to_p2sh(),
271 ShInner::Ms(ref ms) => ms.encode().to_p2sh(),
272 }
273 }
274
275 pub fn address(&self, network: Network) -> Address {
277 let addr = self.address_fallible(network);
278
279 assert!(addr.is_ok());
281 addr.expect("only fails if size > MAX_SCRIPT_ELEMENT_SIZE")
282 }
283
284 fn address_fallible(&self, network: Network) -> Result<Address, Error> {
285 let script = match self.inner {
286 ShInner::Wsh(ref wsh) => wsh.script_pubkey(),
287 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
288 ShInner::SortedMulti(ref smv) => smv.encode(),
289 ShInner::Ms(ref ms) => ms.encode(),
290 };
291 let address = Address::p2sh(&script, network)?;
292
293 Ok(address)
294 }
295
296 pub fn inner_script(&self) -> ScriptBuf {
298 match self.inner {
299 ShInner::Wsh(ref wsh) => wsh.inner_script(),
300 ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
301 ShInner::SortedMulti(ref smv) => smv.encode(),
302 ShInner::Ms(ref ms) => ms.encode(),
303 }
304 }
305
306 pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
308 match self.inner {
309 ShInner::Wsh(ref wsh) => wsh.ecdsa_sighash_script_code(),
312 ShInner::SortedMulti(ref smv) => smv.encode(),
313 ShInner::Wpkh(ref wpkh) => wpkh.ecdsa_sighash_script_code(),
314 ShInner::Ms(ref ms) => ms.encode(),
316 }
317 }
318
319 pub fn unsigned_script_sig(&self) -> ScriptBuf {
327 match self.inner {
328 ShInner::Wsh(ref wsh) => {
329 let witness_script = wsh.inner_script().to_p2wsh();
331 let push_bytes = <&PushBytes>::try_from(witness_script.as_bytes())
332 .expect("Witness script is not too large");
333 script::Builder::new().push_slice(push_bytes).into_script()
334 }
335 ShInner::Wpkh(ref wpkh) => {
336 let redeem_script = wpkh.script_pubkey();
337 let push_bytes: &PushBytes =
338 <&PushBytes>::try_from(redeem_script.as_bytes()).expect("Script not too large");
339 script::Builder::new().push_slice(push_bytes).into_script()
340 }
341 ShInner::SortedMulti(..) | ShInner::Ms(..) => ScriptBuf::new(),
342 }
343 }
344
345 pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
349 where
350 S: Satisfier<Pk>,
351 {
352 let script_sig = self.unsigned_script_sig();
353 match self.inner {
354 ShInner::Wsh(ref wsh) => {
355 let (witness, _) = wsh.get_satisfaction(satisfier)?;
356 Ok((witness, script_sig))
357 }
358 ShInner::Wpkh(ref wpkh) => {
359 let (witness, _) = wpkh.get_satisfaction(satisfier)?;
360 Ok((witness, script_sig))
361 }
362 ShInner::SortedMulti(ref smv) => {
363 let mut script_witness = smv.satisfy(satisfier)?;
364 script_witness.push(smv.encode().into_bytes());
365 let script_sig = witness_to_scriptsig(&script_witness);
366 let witness = vec![];
367 Ok((witness, script_sig))
368 }
369 ShInner::Ms(ref ms) => {
370 let mut script_witness = ms.satisfy(satisfier)?;
371 script_witness.push(ms.encode().into_bytes());
372 let script_sig = witness_to_scriptsig(&script_witness);
373 let witness = vec![];
374 Ok((witness, script_sig))
375 }
376 }
377 }
378
379 pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
383 where
384 S: Satisfier<Pk>,
385 {
386 let script_sig = self.unsigned_script_sig();
387 match self.inner {
388 ShInner::Wsh(ref wsh) => {
389 let (witness, _) = wsh.get_satisfaction_mall(satisfier)?;
390 Ok((witness, script_sig))
391 }
392 ShInner::Ms(ref ms) => {
393 let mut script_witness = ms.satisfy_malleable(satisfier)?;
394 script_witness.push(ms.encode().into_bytes());
395 let script_sig = witness_to_scriptsig(&script_witness);
396 let witness = vec![];
397 Ok((witness, script_sig))
398 }
399 _ => self.get_satisfaction(satisfier),
400 }
401 }
402}
403
404impl Sh<DefiniteDescriptorKey> {
405 pub fn plan_satisfaction<P>(
407 &self,
408 provider: &P,
409 ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
410 where
411 P: AssetProvider<DefiniteDescriptorKey>,
412 {
413 match &self.inner {
414 ShInner::Wsh(ref wsh) => wsh.plan_satisfaction(provider),
415 ShInner::Wpkh(ref wpkh) => wpkh.plan_satisfaction(provider),
416 ShInner::SortedMulti(ref smv) => smv.build_template(provider),
417 ShInner::Ms(ref ms) => ms.build_template(provider),
418 }
419 }
420
421 pub fn plan_satisfaction_mall<P>(
423 &self,
424 provider: &P,
425 ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
426 where
427 P: AssetProvider<DefiniteDescriptorKey>,
428 {
429 match &self.inner {
430 ShInner::Wsh(ref wsh) => wsh.plan_satisfaction_mall(provider),
431 ShInner::Ms(ref ms) => ms.build_template_mall(provider),
432 _ => self.plan_satisfaction(provider),
433 }
434 }
435}
436
437impl<Pk: MiniscriptKey> ForEachKey<Pk> for Sh<Pk> {
438 fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
439 match self.inner {
440 ShInner::Wsh(ref wsh) => wsh.for_each_key(pred),
441 ShInner::SortedMulti(ref smv) => smv.for_each_key(pred),
442 ShInner::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
443 ShInner::Ms(ref ms) => ms.for_each_key(pred),
444 }
445 }
446}
447
448impl<P, Q> TranslatePk<P, Q> for Sh<P>
449where
450 P: MiniscriptKey,
451 Q: MiniscriptKey,
452{
453 type Output = Sh<Q>;
454
455 fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
456 where
457 T: Translator<P, Q, E>,
458 {
459 let inner = match self.inner {
460 ShInner::Wsh(ref wsh) => ShInner::Wsh(wsh.translate_pk(t)?),
461 ShInner::Wpkh(ref wpkh) => ShInner::Wpkh(wpkh.translate_pk(t)?),
462 ShInner::SortedMulti(ref smv) => ShInner::SortedMulti(smv.translate_pk(t)?),
463 ShInner::Ms(ref ms) => ShInner::Ms(ms.translate_pk(t)?),
464 };
465 Ok(Sh { inner })
466 }
467}