miniscript/descriptor/
sh.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! # P2SH Descriptors
4//!
5//! Implementation of p2sh descriptors. Contains the implementation
6//! of sh, wrapped fragments for sh which include wsh, sortedmulti
7//! sh(miniscript), and sh(wpkh)
8//!
9
10use 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/// A Legacy p2sh Descriptor
32#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
33pub struct Sh<Pk: MiniscriptKey> {
34    /// underlying miniscript
35    inner: ShInner<Pk>,
36}
37
38/// Sh Inner
39#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
40pub enum ShInner<Pk: MiniscriptKey> {
41    /// Nested Wsh
42    Wsh(Wsh<Pk>),
43    /// Nested Wpkh
44    Wpkh(Wpkh<Pk>),
45    /// Inner Sorted Multi
46    SortedMulti(SortedMultiVec<Pk, Legacy>),
47    /// p2sh miniscript
48    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    /// Get the Inner
120    pub fn into_inner(self) -> ShInner<Pk> { self.inner }
121
122    /// Get a reference to inner
123    pub fn as_inner(&self) -> &ShInner<Pk> { &self.inner }
124
125    /// Create a new p2sh descriptor with the raw miniscript
126    pub fn new(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
127        // do the top-level checks
128        Legacy::top_level_checks(&ms)?;
129        Ok(Self { inner: ShInner::Ms(ms) })
130    }
131
132    /// Create a new p2sh sortedmulti descriptor with threshold `k`
133    /// and Vec of `pks`.
134    pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
135        // The context checks will be carried out inside new function for
136        // sortedMultiVec
137        Ok(Self { inner: ShInner::SortedMulti(SortedMultiVec::new(k, pks)?) })
138    }
139
140    /// Create a new p2sh wrapped wsh descriptor with the raw miniscript
141    pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
142        Ok(Self { inner: ShInner::Wsh(Wsh::new(ms)?) })
143    }
144
145    /// Create a new p2sh wrapper for the given wsh descriptor
146    pub fn new_with_wsh(wsh: Wsh<Pk>) -> Self { Self { inner: ShInner::Wsh(wsh) } }
147
148    /// Checks whether the descriptor is safe.
149    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    /// Create a new p2sh wrapped wsh sortedmulti descriptor from threshold
160    /// `k` and Vec of `pks`
161    pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
162        // The context checks will be carried out inside new function for
163        // sortedMultiVec
164        Ok(Self { inner: ShInner::Wsh(Wsh::new_sortedmulti(k, pks)?) })
165    }
166
167    /// Create a new p2sh wrapped wpkh from `Pk`
168    pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
169        Ok(Self { inner: ShInner::Wpkh(Wpkh::new(pk)?) })
170    }
171
172    /// Create a new p2sh wrapper for the given wpkh descriptor
173    pub fn new_with_wpkh(wpkh: Wpkh<Pk>) -> Self { Self { inner: ShInner::Wpkh(wpkh) } }
174
175    /// Computes an upper bound on the difference between a non-satisfied
176    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
177    ///
178    /// Since this method uses `segwit_weight` instead of `legacy_weight`,
179    /// if you want to include only legacy inputs in your transaction,
180    /// you should remove 1WU from each input's `max_weight_to_satisfy`
181    /// for a more accurate estimate.
182    ///
183    /// Assumes all ec-signatures are 73 bytes, including push opcode and
184    /// sighash suffix.
185    ///
186    /// # Errors
187    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
188    pub fn max_weight_to_satisfy(&self) -> Result<Weight, Error> {
189        let (scriptsig_size, witness_size) = match self.inner {
190            // add weighted script sig, len byte stays the same
191            ShInner::Wsh(ref wsh) => {
192                // scriptSig: OP_34 <OP_0 OP_32 <32-byte-hash>>
193                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            // add weighted script sig, len byte stays the same
204            ShInner::Wpkh(ref wpkh) => {
205                // scriptSig: OP_22 <OP_0 OP_20 <20-byte-hash>>
206                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        // scriptSigLen varint difference between non-satisfied (0) and satisfied
219        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    /// Computes an upper bound on the weight of a satisfying witness to the
229    /// transaction.
230    ///
231    /// Assumes all ECDSA signatures are 73 bytes, including push opcode and
232    /// sighash suffix. Includes the weight of the VarInts encoding the
233    /// scriptSig and witness stack length.
234    ///
235    /// # Errors
236    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
237    #[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            // add weighted script sig, len byte stays the same
245            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            // add weighted script sig, len byte stays the same
253            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    /// Obtains the corresponding script pubkey for this descriptor.
266    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    /// Obtains the corresponding address for this descriptor.
276    pub fn address(&self, network: Network) -> Address {
277        let addr = self.address_fallible(network);
278
279        // Size is checked in `check_global_consensus_validity`.
280        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    /// Obtain the underlying miniscript for this descriptor
297    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    /// Obtains the pre bip-340 signature script code for this descriptor.
307    pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
308        match self.inner {
309            //     - For P2WSH witness program, if the witnessScript does not contain any `OP_CODESEPARATOR`,
310            //       the `scriptCode` is the `witnessScript` serialized as scripts inside CTxOut.
311            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            // For "legacy" P2SH outputs, it is defined as the txo's redeemScript.
315            ShInner::Ms(ref ms) => ms.encode(),
316        }
317    }
318
319    /// Computes the scriptSig that will be in place for an unsigned input
320    /// spending an output with this descriptor. For pre-segwit descriptors,
321    /// which use the scriptSig for signatures, this returns the empty script.
322    ///
323    /// This is used in Segwit transactions to produce an unsigned transaction
324    /// whose txid will not change during signing (since only the witness data
325    /// will change).
326    pub fn unsigned_script_sig(&self) -> ScriptBuf {
327        match self.inner {
328            ShInner::Wsh(ref wsh) => {
329                // wsh explicit must contain exactly 1 element
330                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    /// Returns satisfying non-malleable witness and scriptSig with minimum
346    /// weight to spend an output controlled by the given descriptor if it is
347    /// possible to construct one using the `satisfier`.
348    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    /// Returns satisfying, possibly malleable, witness and scriptSig with
380    /// minimum weight to spend an output controlled by the given descriptor if
381    /// it is possible to construct one using the `satisfier`.
382    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    /// Returns a plan if the provided assets are sufficient to produce a non-malleable satisfaction
406    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    /// Returns a plan if the provided assets are sufficient to produce a malleable satisfaction
422    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}