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};
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, Legacy, Miniscript, MiniscriptKey, Satisfier, Segwitv0,
28    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_from_tree!(
85    Sh<Pk>,
86    fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
87        if top.name == "sh" && top.args.len() == 1 {
88            let top = &top.args[0];
89            let inner = match top.name {
90                "wsh" => ShInner::Wsh(Wsh::from_tree(top)?),
91                "wpkh" => ShInner::Wpkh(Wpkh::from_tree(top)?),
92                "sortedmulti" => ShInner::SortedMulti(SortedMultiVec::from_tree(top)?),
93                _ => {
94                    let sub = Miniscript::from_tree(top)?;
95                    Legacy::top_level_checks(&sub)?;
96                    ShInner::Ms(sub)
97                }
98            };
99            Ok(Sh { inner })
100        } else {
101            Err(Error::Unexpected(format!(
102                "{}({} args) while parsing sh descriptor",
103                top.name,
104                top.args.len(),
105            )))
106        }
107    }
108);
109
110impl_from_str!(
111    Sh<Pk>,
112    type Err = Error;,
113    fn from_str(s: &str) -> Result<Self, Self::Err> {
114        let desc_str = verify_checksum(s)?;
115        let top = expression::Tree::from_str(desc_str)?;
116        Self::from_tree(&top)
117    }
118);
119
120impl<Pk: MiniscriptKey> Sh<Pk> {
121    /// Get the Inner
122    pub fn into_inner(self) -> ShInner<Pk> { self.inner }
123
124    /// Get a reference to inner
125    pub fn as_inner(&self) -> &ShInner<Pk> { &self.inner }
126
127    /// Create a new p2sh descriptor with the raw miniscript
128    pub fn new(ms: Miniscript<Pk, Legacy>) -> Result<Self, Error> {
129        // do the top-level checks
130        Legacy::top_level_checks(&ms)?;
131        Ok(Self { inner: ShInner::Ms(ms) })
132    }
133
134    /// Create a new p2sh sortedmulti descriptor with threshold `k`
135    /// and Vec of `pks`.
136    pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
137        // The context checks will be carried out inside new function for
138        // sortedMultiVec
139        Ok(Self { inner: ShInner::SortedMulti(SortedMultiVec::new(k, pks)?) })
140    }
141
142    /// Create a new p2sh wrapped wsh descriptor with the raw miniscript
143    pub fn new_wsh(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
144        Ok(Self { inner: ShInner::Wsh(Wsh::new(ms)?) })
145    }
146
147    /// Create a new p2sh wrapper for the given wsh descriptor
148    pub fn new_with_wsh(wsh: Wsh<Pk>) -> Self { Self { inner: ShInner::Wsh(wsh) } }
149
150    /// Checks whether the descriptor is safe.
151    pub fn sanity_check(&self) -> Result<(), Error> {
152        match self.inner {
153            ShInner::Wsh(ref wsh) => wsh.sanity_check()?,
154            ShInner::Wpkh(ref wpkh) => wpkh.sanity_check()?,
155            ShInner::SortedMulti(ref smv) => smv.sanity_check()?,
156            ShInner::Ms(ref ms) => ms.sanity_check()?,
157        }
158        Ok(())
159    }
160
161    /// Create a new p2sh wrapped wsh sortedmulti descriptor from threshold
162    /// `k` and Vec of `pks`
163    pub fn new_wsh_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
164        // The context checks will be carried out inside new function for
165        // sortedMultiVec
166        Ok(Self { inner: ShInner::Wsh(Wsh::new_sortedmulti(k, pks)?) })
167    }
168
169    /// Create a new p2sh wrapped wpkh from `Pk`
170    pub fn new_wpkh(pk: Pk) -> Result<Self, Error> {
171        Ok(Self { inner: ShInner::Wpkh(Wpkh::new(pk)?) })
172    }
173
174    /// Create a new p2sh wrapper for the given wpkh descriptor
175    pub fn new_with_wpkh(wpkh: Wpkh<Pk>) -> Self { Self { inner: ShInner::Wpkh(wpkh) } }
176
177    /// Computes an upper bound on the difference between a non-satisfied
178    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
179    ///
180    /// Since this method uses `segwit_weight` instead of `legacy_weight`,
181    /// if you want to include only legacy inputs in your transaction,
182    /// you should remove 1WU from each input's `max_weight_to_satisfy`
183    /// for a more accurate estimate.
184    ///
185    /// Assumes all ec-signatures are 73 bytes, including push opcode and
186    /// sighash suffix.
187    ///
188    /// # Errors
189    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
190    pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
191        let (scriptsig_size, witness_size) = match self.inner {
192            // add weighted script sig, len byte stays the same
193            ShInner::Wsh(ref wsh) => {
194                // scriptSig: OP_34 <OP_0 OP_32 <32-byte-hash>>
195                let scriptsig_size = 1 + 1 + 1 + 32;
196                let witness_size = wsh.max_weight_to_satisfy()?;
197                (scriptsig_size, witness_size)
198            }
199            ShInner::SortedMulti(ref smv) => {
200                let ss = smv.script_size();
201                let ps = push_opcode_size(ss);
202                let scriptsig_size = ps + ss + smv.max_satisfaction_size();
203                (scriptsig_size, 0)
204            }
205            // add weighted script sig, len byte stays the same
206            ShInner::Wpkh(ref wpkh) => {
207                // scriptSig: OP_22 <OP_0 OP_20 <20-byte-hash>>
208                let scriptsig_size = 1 + 1 + 1 + 20;
209                let witness_size = wpkh.max_weight_to_satisfy();
210                (scriptsig_size, witness_size)
211            }
212            ShInner::Ms(ref ms) => {
213                let ss = ms.script_size();
214                let ps = push_opcode_size(ss);
215                let scriptsig_size = ps + ss + ms.max_satisfaction_size()?;
216                (scriptsig_size, 0)
217            }
218        };
219
220        // scriptSigLen varint difference between non-satisfied (0) and satisfied
221        let scriptsig_varint_diff = varint_len(scriptsig_size) - varint_len(0);
222
223        Ok(4 * (scriptsig_varint_diff + scriptsig_size) + witness_size)
224    }
225
226    /// Computes an upper bound on the weight of a satisfying witness to the
227    /// transaction.
228    ///
229    /// Assumes all ECDSA signatures are 73 bytes, including push opcode and
230    /// sighash suffix. Includes the weight of the VarInts encoding the
231    /// scriptSig and witness stack length.
232    ///
233    /// # Errors
234    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
235    #[deprecated(note = "use max_weight_to_satisfy instead")]
236    #[allow(deprecated)]
237    pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
238        Ok(match self.inner {
239            // add weighted script sig, len byte stays the same
240            ShInner::Wsh(ref wsh) => 4 * 35 + wsh.max_satisfaction_weight()?,
241            ShInner::SortedMulti(ref smv) => {
242                let ss = smv.script_size();
243                let ps = push_opcode_size(ss);
244                let scriptsig_len = ps + ss + smv.max_satisfaction_size();
245                4 * (varint_len(scriptsig_len) + scriptsig_len)
246            }
247            // add weighted script sig, len byte stays the same
248            ShInner::Wpkh(ref wpkh) => 4 * 23 + wpkh.max_satisfaction_weight(),
249            ShInner::Ms(ref ms) => {
250                let ss = ms.script_size();
251                let ps = push_opcode_size(ss);
252                let scriptsig_len = ps + ss + ms.max_satisfaction_size()?;
253                4 * (varint_len(scriptsig_len) + scriptsig_len)
254            }
255        })
256    }
257}
258
259impl<Pk: MiniscriptKey + ToPublicKey> Sh<Pk> {
260    /// Obtains the corresponding script pubkey for this descriptor.
261    pub fn script_pubkey(&self) -> ScriptBuf {
262        match self.inner {
263            ShInner::Wsh(ref wsh) => wsh.script_pubkey().to_p2sh(),
264            ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey().to_p2sh(),
265            ShInner::SortedMulti(ref smv) => smv.encode().to_p2sh(),
266            ShInner::Ms(ref ms) => ms.encode().to_p2sh(),
267        }
268    }
269
270    /// Obtains the corresponding address for this descriptor.
271    pub fn address(&self, network: Network) -> Address {
272        let addr = self.address_fallible(network);
273
274        // Size is checked in `check_global_consensus_validity`.
275        assert!(addr.is_ok());
276        addr.expect("only fails if size > MAX_SCRIPT_ELEMENT_SIZE")
277    }
278
279    fn address_fallible(&self, network: Network) -> Result<Address, Error> {
280        let script = match self.inner {
281            ShInner::Wsh(ref wsh) => wsh.script_pubkey(),
282            ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
283            ShInner::SortedMulti(ref smv) => smv.encode(),
284            ShInner::Ms(ref ms) => ms.encode(),
285        };
286        let address = Address::p2sh(&script, network)?;
287
288        Ok(address)
289    }
290
291    /// Obtain the underlying miniscript for this descriptor
292    pub fn inner_script(&self) -> ScriptBuf {
293        match self.inner {
294            ShInner::Wsh(ref wsh) => wsh.inner_script(),
295            ShInner::Wpkh(ref wpkh) => wpkh.script_pubkey(),
296            ShInner::SortedMulti(ref smv) => smv.encode(),
297            ShInner::Ms(ref ms) => ms.encode(),
298        }
299    }
300
301    /// Obtains the pre bip-340 signature script code for this descriptor.
302    pub fn ecdsa_sighash_script_code(&self) -> ScriptBuf {
303        match self.inner {
304            //     - For P2WSH witness program, if the witnessScript does not contain any `OP_CODESEPARATOR`,
305            //       the `scriptCode` is the `witnessScript` serialized as scripts inside CTxOut.
306            ShInner::Wsh(ref wsh) => wsh.ecdsa_sighash_script_code(),
307            ShInner::SortedMulti(ref smv) => smv.encode(),
308            ShInner::Wpkh(ref wpkh) => wpkh.ecdsa_sighash_script_code(),
309            // For "legacy" P2SH outputs, it is defined as the txo's redeemScript.
310            ShInner::Ms(ref ms) => ms.encode(),
311        }
312    }
313
314    /// Computes the scriptSig that will be in place for an unsigned input
315    /// spending an output with this descriptor. For pre-segwit descriptors,
316    /// which use the scriptSig for signatures, this returns the empty script.
317    ///
318    /// This is used in Segwit transactions to produce an unsigned transaction
319    /// whose txid will not change during signing (since only the witness data
320    /// will change).
321    pub fn unsigned_script_sig(&self) -> ScriptBuf {
322        match self.inner {
323            ShInner::Wsh(ref wsh) => {
324                // wsh explicit must contain exactly 1 element
325                let witness_script = wsh.inner_script().to_p2wsh();
326                let push_bytes = <&PushBytes>::try_from(witness_script.as_bytes())
327                    .expect("Witness script is not too large");
328                script::Builder::new().push_slice(push_bytes).into_script()
329            }
330            ShInner::Wpkh(ref wpkh) => {
331                let redeem_script = wpkh.script_pubkey();
332                let push_bytes: &PushBytes =
333                    <&PushBytes>::try_from(redeem_script.as_bytes()).expect("Script not too large");
334                script::Builder::new().push_slice(push_bytes).into_script()
335            }
336            ShInner::SortedMulti(..) | ShInner::Ms(..) => ScriptBuf::new(),
337        }
338    }
339
340    /// Returns satisfying non-malleable witness and scriptSig with minimum
341    /// weight to spend an output controlled by the given descriptor if it is
342    /// possible to construct one using the `satisfier`.
343    pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
344    where
345        S: Satisfier<Pk>,
346    {
347        let script_sig = self.unsigned_script_sig();
348        match self.inner {
349            ShInner::Wsh(ref wsh) => {
350                let (witness, _) = wsh.get_satisfaction(satisfier)?;
351                Ok((witness, script_sig))
352            }
353            ShInner::Wpkh(ref wpkh) => {
354                let (witness, _) = wpkh.get_satisfaction(satisfier)?;
355                Ok((witness, script_sig))
356            }
357            ShInner::SortedMulti(ref smv) => {
358                let mut script_witness = smv.satisfy(satisfier)?;
359                script_witness.push(smv.encode().into_bytes());
360                let script_sig = witness_to_scriptsig(&script_witness);
361                let witness = vec![];
362                Ok((witness, script_sig))
363            }
364            ShInner::Ms(ref ms) => {
365                let mut script_witness = ms.satisfy(satisfier)?;
366                script_witness.push(ms.encode().into_bytes());
367                let script_sig = witness_to_scriptsig(&script_witness);
368                let witness = vec![];
369                Ok((witness, script_sig))
370            }
371        }
372    }
373
374    /// Returns satisfying, possibly malleable, witness and scriptSig with
375    /// minimum weight to spend an output controlled by the given descriptor if
376    /// it is possible to construct one using the `satisfier`.
377    pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, ScriptBuf), Error>
378    where
379        S: Satisfier<Pk>,
380    {
381        let script_sig = self.unsigned_script_sig();
382        match self.inner {
383            ShInner::Wsh(ref wsh) => {
384                let (witness, _) = wsh.get_satisfaction_mall(satisfier)?;
385                Ok((witness, script_sig))
386            }
387            ShInner::Ms(ref ms) => {
388                let mut script_witness = ms.satisfy_malleable(satisfier)?;
389                script_witness.push(ms.encode().into_bytes());
390                let script_sig = witness_to_scriptsig(&script_witness);
391                let witness = vec![];
392                Ok((witness, script_sig))
393            }
394            _ => self.get_satisfaction(satisfier),
395        }
396    }
397}
398
399impl Sh<DefiniteDescriptorKey> {
400    /// Returns a plan if the provided assets are sufficient to produce a non-malleable satisfaction
401    pub fn plan_satisfaction<P>(
402        &self,
403        provider: &P,
404    ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
405    where
406        P: AssetProvider<DefiniteDescriptorKey>,
407    {
408        match &self.inner {
409            ShInner::Wsh(ref wsh) => wsh.plan_satisfaction(provider),
410            ShInner::Wpkh(ref wpkh) => wpkh.plan_satisfaction(provider),
411            ShInner::SortedMulti(ref smv) => smv.build_template(provider),
412            ShInner::Ms(ref ms) => ms.build_template(provider),
413        }
414    }
415
416    /// Returns a plan if the provided assets are sufficient to produce a malleable satisfaction
417    pub fn plan_satisfaction_mall<P>(
418        &self,
419        provider: &P,
420    ) -> Satisfaction<Placeholder<DefiniteDescriptorKey>>
421    where
422        P: AssetProvider<DefiniteDescriptorKey>,
423    {
424        match &self.inner {
425            ShInner::Wsh(ref wsh) => wsh.plan_satisfaction_mall(provider),
426            ShInner::Ms(ref ms) => ms.build_template_mall(provider),
427            _ => self.plan_satisfaction(provider),
428        }
429    }
430}
431
432impl<Pk: MiniscriptKey> ForEachKey<Pk> for Sh<Pk> {
433    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool {
434        match self.inner {
435            ShInner::Wsh(ref wsh) => wsh.for_each_key(pred),
436            ShInner::SortedMulti(ref smv) => smv.for_each_key(pred),
437            ShInner::Wpkh(ref wpkh) => wpkh.for_each_key(pred),
438            ShInner::Ms(ref ms) => ms.for_each_key(pred),
439        }
440    }
441}
442
443impl<P, Q> TranslatePk<P, Q> for Sh<P>
444where
445    P: MiniscriptKey,
446    Q: MiniscriptKey,
447{
448    type Output = Sh<Q>;
449
450    fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, TranslateErr<E>>
451    where
452        T: Translator<P, Q, E>,
453    {
454        let inner = match self.inner {
455            ShInner::Wsh(ref wsh) => ShInner::Wsh(wsh.translate_pk(t)?),
456            ShInner::Wpkh(ref wpkh) => ShInner::Wpkh(wpkh.translate_pk(t)?),
457            ShInner::SortedMulti(ref smv) => ShInner::SortedMulti(smv.translate_pk(t)?),
458            ShInner::Ms(ref ms) => ShInner::Ms(ms.translate_pk(t)?),
459        };
460        Ok(Sh { inner })
461    }
462}