elements_miniscript/descriptor/
segwitv0.rs

1// Written in 2020 by the rust-miniscript developers
2// SPDX-License-Identifier: CC0-1.0
3
4//! # Segwit Output Descriptors
5//!
6//! Implementation of Segwit Descriptors. Contains the implementation
7//! of wsh, wpkh and sortedmulti inside wsh.
8
9use core::fmt;
10use std::fmt::Write;
11use std::str::FromStr;
12
13use elements::{self, secp256k1_zkp, Address, Script};
14
15use super::checksum::verify_checksum;
16use super::{SortedMultiVec, ELMTS_STR};
17use crate::descriptor::checksum;
18use crate::expression::{self, FromTree};
19use crate::miniscript::context::{ScriptContext, ScriptContextError};
20use crate::policy::{semantic, Liftable};
21use crate::util::varint_len;
22use crate::{
23    elementssig_to_rawsig, Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0,
24    ToPublicKey, TranslatePk, Translator,
25};
26/// A Segwitv0 wsh descriptor
27#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
28pub struct Wsh<Pk: MiniscriptKey> {
29    /// underlying miniscript
30    inner: WshInner<Pk>,
31}
32
33impl<Pk: MiniscriptKey> Wsh<Pk> {
34    /// Get the Inner
35    pub fn into_inner(self) -> WshInner<Pk> {
36        self.inner
37    }
38
39    /// Get a reference to inner
40    pub fn as_inner(&self) -> &WshInner<Pk> {
41        &self.inner
42    }
43
44    /// Create a new wsh descriptor
45    pub fn new(ms: Miniscript<Pk, Segwitv0>) -> Result<Self, Error> {
46        // do the top-level checks
47        Segwitv0::top_level_checks(&ms)?;
48        Ok(Self {
49            inner: WshInner::Ms(ms),
50        })
51    }
52
53    /// Create a new sortedmulti wsh descriptor
54    pub fn new_sortedmulti(k: usize, pks: Vec<Pk>) -> Result<Self, Error> {
55        // The context checks will be carried out inside new function for
56        // sortedMultiVec
57        Ok(Self {
58            inner: WshInner::SortedMulti(SortedMultiVec::new(k, pks)?),
59        })
60    }
61
62    /// Get the descriptor without the checksum and the el prefix
63    pub fn to_string_no_el_pref(&self, f: &mut checksum::Formatter) -> fmt::Result {
64        match self.inner {
65            WshInner::SortedMulti(ref smv) => write!(f, "wsh({})", smv),
66            WshInner::Ms(ref ms) => write!(f, "wsh({})", ms),
67        }
68    }
69
70    /// Checks whether the descriptor is safe.
71    pub fn sanity_check(&self) -> Result<(), Error> {
72        match self.inner {
73            WshInner::SortedMulti(ref smv) => smv.sanity_check()?,
74            WshInner::Ms(ref ms) => ms.sanity_check()?,
75        }
76        Ok(())
77    }
78
79    /// Computes an upper bound on the difference between a non-satisfied
80    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
81    ///
82    /// Assumes all ECDSA signatures are 73 bytes, including push opcode and
83    /// sighash suffix.
84    ///
85    /// # Errors
86    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
87    pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
88        let (redeem_script_size, max_sat_elems, max_sat_size) = match self.inner {
89            WshInner::SortedMulti(ref smv) => (
90                smv.script_size(),
91                smv.max_satisfaction_witness_elements(),
92                smv.max_satisfaction_size(),
93            ),
94            WshInner::Ms(ref ms) => (
95                ms.script_size(),
96                ms.max_satisfaction_witness_elements()?,
97                ms.max_satisfaction_size()?,
98            ),
99        };
100        // stack size varint difference between non-satisfied (0) and satisfied
101        // `max_sat_elems` is inclusive of the "witness script" (redeem script)
102        let stack_varint_diff = varint_len(max_sat_elems) - varint_len(0);
103
104        Ok(stack_varint_diff + varint_len(redeem_script_size) + redeem_script_size + max_sat_size)
105    }
106
107    /// Computes an upper bound on the weight of a satisfying witness to the
108    /// transaction.
109    ///
110    /// Assumes all ec-signatures are 73 bytes, including push opcode and
111    /// sighash suffix. Includes the weight of the VarInts encoding the
112    /// scriptSig and witness stack length.
113    ///
114    /// # Errors
115    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
116    #[deprecated(note = "use max_weight_to_satisfy instead")]
117    pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
118        let (script_size, max_sat_elems, max_sat_size) = match self.inner {
119            WshInner::SortedMulti(ref smv) => (
120                smv.script_size(),
121                smv.max_satisfaction_witness_elements(),
122                smv.max_satisfaction_size(),
123            ),
124            WshInner::Ms(ref ms) => (
125                ms.script_size(),
126                ms.max_satisfaction_witness_elements()?,
127                ms.max_satisfaction_size()?,
128            ),
129        };
130        Ok(4 +  // scriptSig length byte
131            varint_len(script_size) +
132            script_size +
133            varint_len(max_sat_elems) +
134            max_sat_size)
135    }
136}
137
138#[rustfmt::skip]
139impl_block_str!(
140    Wsh<Pk>,
141    // Constructor for creating inner wsh for the sh fragment
142    pub(super) fn from_inner_tree(top: &expression::Tree<'_>, ) -> Result<Self, Error>
143    {
144        if top.name == "wsh" && top.args.len() == 1 {
145            let top = &top.args[0];
146            if top.name == "sortedmulti" {
147                return Ok(Wsh {
148                    inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
149                });
150            }
151            let sub = Miniscript::from_tree(top)?;
152            Segwitv0::top_level_checks(&sub)?;
153            Ok(Wsh {
154                inner: WshInner::Ms(sub),
155            })
156        } else {
157            Err(Error::Unexpected(format!(
158                "{}({} args) while parsing wsh descriptor",
159                top.name,
160                top.args.len(),
161            )))
162        }
163    }
164);
165
166impl<Pk: MiniscriptKey + ToPublicKey> Wsh<Pk> {
167    /// Obtains the corresponding script pubkey for this descriptor.
168    pub fn script_pubkey(&self) -> Script {
169        self.inner_script().to_v0_p2wsh()
170    }
171
172    /// Obtains the corresponding script pubkey for this descriptor.
173    pub fn address(
174        &self,
175        blinder: Option<secp256k1_zkp::PublicKey>,
176        params: &'static elements::AddressParams,
177    ) -> elements::Address {
178        match self.inner {
179            WshInner::SortedMulti(ref smv) => {
180                elements::Address::p2wsh(&smv.encode(), blinder, params)
181            }
182            WshInner::Ms(ref ms) => elements::Address::p2wsh(&ms.encode(), blinder, params),
183        }
184    }
185
186    /// Obtains the underlying miniscript for this descriptor.
187    pub fn inner_script(&self) -> Script {
188        match self.inner {
189            WshInner::SortedMulti(ref smv) => smv.encode(),
190            WshInner::Ms(ref ms) => ms.encode(),
191        }
192    }
193
194    /// Obtains the pre bip-340 signature script code for this descriptor.
195    pub fn ecdsa_sighash_script_code(&self) -> Script {
196        self.inner_script()
197    }
198
199    /// Returns satisfying non-malleable witness and scriptSig with minimum
200    /// weight to spend an output controlled by the given descriptor if it is
201    /// possible to construct one using the `satisfier`.
202    pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
203    where
204        S: Satisfier<Pk>,
205    {
206        let mut witness = match self.inner {
207            WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
208            WshInner::Ms(ref ms) => ms.satisfy(satisfier)?,
209        };
210        let witness_script = self.inner_script();
211        witness.push(witness_script.into_bytes());
212        let script_sig = Script::new();
213        Ok((witness, script_sig))
214    }
215
216    /// Returns satisfying, possibly malleable, witness and scriptSig with
217    /// minimum weight to spend an output controlled by the given descriptor if
218    /// it is possible to construct one using the `satisfier`.
219    pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
220    where
221        S: Satisfier<Pk>,
222    {
223        let mut witness = match self.inner {
224            WshInner::SortedMulti(ref smv) => smv.satisfy(satisfier)?,
225            WshInner::Ms(ref ms) => ms.satisfy_malleable(satisfier)?,
226        };
227        witness.push(self.inner_script().into_bytes());
228        let script_sig = Script::new();
229        Ok((witness, script_sig))
230    }
231}
232
233/// Wsh Inner
234#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
235pub enum WshInner<Pk: MiniscriptKey> {
236    /// Sorted Multi
237    SortedMulti(SortedMultiVec<Pk, Segwitv0>),
238    /// Wsh Miniscript
239    // no extensions in regular wsh or shwsh
240    // extensions are only supported in cov descriptors
241    Ms(Miniscript<Pk, Segwitv0>),
242}
243
244impl<Pk: MiniscriptKey> Liftable<Pk> for Wsh<Pk> {
245    fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
246        match self.inner {
247            WshInner::SortedMulti(ref smv) => smv.lift(),
248            WshInner::Ms(ref ms) => ms.lift(),
249        }
250    }
251}
252
253impl_from_tree!(
254    Wsh<Pk>,
255    fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
256        if top.name == "elwsh" && top.args.len() == 1 {
257            let top = &top.args[0];
258            if top.name == "sortedmulti" {
259                return Ok(Wsh {
260                    inner: WshInner::SortedMulti(SortedMultiVec::from_tree(top)?),
261                });
262            }
263            let sub = Miniscript::from_tree(top)?;
264            Segwitv0::top_level_checks(&sub)?;
265            Ok(Wsh {
266                inner: WshInner::Ms(sub),
267            })
268        } else {
269            Err(Error::Unexpected(format!(
270                "{}({} args) while parsing wsh descriptor",
271                top.name,
272                top.args.len(),
273            )))
274        }
275    }
276);
277
278impl<Pk: MiniscriptKey> fmt::Debug for Wsh<Pk> {
279    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
280        match self.inner {
281            WshInner::SortedMulti(ref smv) => write!(f, "{}wsh({:?})", ELMTS_STR, smv),
282            WshInner::Ms(ref ms) => write!(f, "{}wsh({:?})", ELMTS_STR, ms),
283        }
284    }
285}
286
287impl<Pk: MiniscriptKey> fmt::Display for Wsh<Pk> {
288    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
289        let mut wrapped_f = checksum::Formatter::new(f);
290        match self.inner {
291            WshInner::SortedMulti(ref smv) => write!(wrapped_f, "{}wsh({})", ELMTS_STR, smv)?,
292            WshInner::Ms(ref ms) => write!(wrapped_f, "{}wsh({})", ELMTS_STR, ms)?,
293        }
294        wrapped_f.write_checksum_if_not_alt()
295    }
296}
297
298impl_from_str!(
299    Wsh<Pk>,
300    type Err = Error;,
301    fn from_str(s: &str) -> Result<Self, Self::Err> {
302        let desc_str = verify_checksum(s)?;
303        let top = expression::Tree::from_str(desc_str)?;
304        Wsh::<Pk>::from_tree(&top)
305    }
306);
307
308impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wsh<Pk> {
309    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
310    where
311        Pk: 'a,
312    {
313        match self.inner {
314            WshInner::SortedMulti(ref smv) => smv.for_each_key(pred),
315            WshInner::Ms(ref ms) => ms.for_each_key(pred),
316        }
317    }
318}
319
320impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Wsh<P> {
321    type Output = Wsh<Q>;
322
323    fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
324    where
325        T: Translator<P, Q, E>,
326    {
327        let inner = match self.inner {
328            WshInner::SortedMulti(ref smv) => WshInner::SortedMulti(smv.translate_pk(t)?),
329            WshInner::Ms(ref ms) => WshInner::Ms(ms.translate_pk(t)?),
330        };
331        Ok(Wsh { inner })
332    }
333}
334
335/// A bare Wpkh descriptor at top level
336#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
337pub struct Wpkh<Pk: MiniscriptKey> {
338    /// underlying publickey
339    pk: Pk,
340}
341
342impl<Pk: MiniscriptKey> Wpkh<Pk> {
343    /// Create a new Wpkh descriptor
344    pub fn new(pk: Pk) -> Result<Self, Error> {
345        // do the top-level checks
346        if pk.is_uncompressed() {
347            Err(Error::ContextError(ScriptContextError::CompressedOnly(
348                pk.to_string(),
349            )))
350        } else {
351            Ok(Self { pk })
352        }
353    }
354
355    /// Get the inner key
356    pub fn into_inner(self) -> Pk {
357        self.pk
358    }
359
360    /// Get the inner key
361    pub fn as_inner(&self) -> &Pk {
362        &self.pk
363    }
364
365    /// Get the descriptor without the checksum and no el prefix
366    pub fn to_string_no_el_pref(&self, f: &mut checksum::Formatter) -> fmt::Result {
367        write!(f, "wpkh({})", self.pk)
368    }
369
370    /// Checks whether the descriptor is safe.
371    pub fn sanity_check(&self) -> Result<(), Error> {
372        if self.pk.is_uncompressed() {
373            Err(Error::ContextError(ScriptContextError::CompressedOnly(
374                self.pk.to_string(),
375            )))
376        } else {
377            Ok(())
378        }
379    }
380
381    /// Computes an upper bound on the difference between a non-satisfied
382    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
383    ///
384    /// Assumes all ec-signatures are 73 bytes, including push opcode and
385    /// sighash suffix.
386    pub fn max_weight_to_satisfy(&self) -> usize {
387        // stack items: <varint(sig+sigHash)> <sig(71)+sigHash(1)> <varint(pubkey)> <pubkey>
388        let stack_items_size = 73 + Segwitv0::pk_len(&self.pk);
389        // stackLen varint difference between non-satisfied (0) and satisfied
390        let stack_varint_diff = varint_len(2) - varint_len(0);
391        stack_varint_diff + stack_items_size
392    }
393
394    /// Computes an upper bound on the weight of a satisfying witness to the
395    /// transaction.
396    ///
397    /// Assumes all ec-signatures are 73 bytes, including push opcode and
398    /// sighash suffix. Includes the weight of the VarInts encoding the
399    /// scriptSig and witness stack length.
400    pub fn max_satisfaction_weight(&self) -> usize {
401        4 + 1 + 73 + Segwitv0::pk_len(&self.pk)
402    }
403
404    // Parse a bitcoin style wpkh tree. Useful when parsing nested trees
405    pub(super) fn from_inner_tree(top: &expression::Tree<'_>) -> Result<Self, Error>
406    where
407        Pk: FromStr,
408        <Pk as FromStr>::Err: ToString,
409    {
410        if top.name == "wpkh" && top.args.len() == 1 {
411            Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| {
412                Pk::from_str(pk)
413            })?)?)
414        } else {
415            Err(Error::Unexpected(format!(
416                "{}({} args) while parsing wpkh descriptor",
417                top.name,
418                top.args.len(),
419            )))
420        }
421    }
422}
423
424impl<Pk: MiniscriptKey + ToPublicKey> Wpkh<Pk> {
425    /// Obtains the corresponding script pubkey for this descriptor.
426    pub fn script_pubkey(&self) -> Script {
427        let addr = self.address(None, &elements::AddressParams::ELEMENTS);
428        addr.script_pubkey()
429    }
430
431    /// Obtains the corresponding script pubkey for this descriptor.
432    pub fn address(
433        &self,
434        blinder: Option<secp256k1_zkp::PublicKey>,
435        params: &'static elements::AddressParams,
436    ) -> elements::Address {
437        Address::p2wpkh(&self.pk.to_public_key(), blinder, params)
438    }
439
440    /// Obtains the underlying miniscript for this descriptor.
441    pub fn inner_script(&self) -> Script {
442        self.script_pubkey()
443    }
444
445    /// Obtains the pre bip-340 signature script code for this descriptor.
446    pub fn ecdsa_sighash_script_code(&self) -> Script {
447        // For SegWit outputs, it is defined by bip-0143 (quoted below) and is different from
448        // the previous txo's scriptPubKey.
449        // The item 5:
450        //     - For P2WPKH witness program, the scriptCode is `0x1976a914{20-byte-pubkey-hash}88ac`.
451        let addr = elements::Address::p2pkh(
452            &self.pk.to_public_key(),
453            None,
454            &elements::AddressParams::ELEMENTS,
455        );
456        // Need this expect in future
457        // .expect("wpkh descriptors have compressed keys");
458        addr.script_pubkey()
459    }
460
461    /// Returns satisfying non-malleable witness and scriptSig with minimum
462    /// weight to spend an output controlled by the given descriptor if it is
463    /// possible to construct one using the `satisfier`.
464    pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
465    where
466        S: Satisfier<Pk>,
467    {
468        if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
469            let sig_vec = elementssig_to_rawsig(&sig);
470            let script_sig = Script::new();
471            let witness = vec![sig_vec, self.pk.to_public_key().to_bytes()];
472            Ok((witness, script_sig))
473        } else {
474            Err(Error::MissingSig(self.pk.to_public_key()))
475        }
476    }
477
478    /// Returns satisfying, possibly malleable, witness and scriptSig with
479    /// minimum weight to spend an output controlled by the given descriptor if
480    /// it is possible to construct one using the `satisfier`.
481    pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
482    where
483        S: Satisfier<Pk>,
484    {
485        self.get_satisfaction(satisfier)
486    }
487}
488
489impl<Pk: MiniscriptKey> fmt::Debug for Wpkh<Pk> {
490    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491        write!(f, "{}wpkh({:?})", ELMTS_STR, self.pk)
492    }
493}
494
495impl<Pk: MiniscriptKey> fmt::Display for Wpkh<Pk> {
496    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
497        let mut wrapped_f = checksum::Formatter::new(f);
498        write!(wrapped_f, "{}wpkh({})", ELMTS_STR, self.pk)?;
499        wrapped_f.write_checksum_if_not_alt()
500    }
501}
502
503impl<Pk: MiniscriptKey> Liftable<Pk> for Wpkh<Pk> {
504    fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
505        Ok(semantic::Policy::Key(self.pk.clone()))
506    }
507}
508
509impl_from_tree!(
510    Wpkh<Pk>,
511    fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
512        if top.name == "elwpkh" && top.args.len() == 1 {
513            Ok(Wpkh::new(expression::terminal(&top.args[0], |pk| {
514                Pk::from_str(pk)
515            })?)?)
516        } else {
517            Err(Error::Unexpected(format!(
518                "{}({} args) while parsing wpkh descriptor",
519                top.name,
520                top.args.len(),
521            )))
522        }
523    }
524);
525
526impl_from_str!(
527    Wpkh<Pk>,
528    type Err = Error;,
529    fn from_str(s: &str) -> Result<Self, Self::Err> {
530        let desc_str = verify_checksum(s)?;
531        let top = expression::Tree::from_str(desc_str)?;
532        Self::from_tree(&top)
533    }
534);
535
536impl<Pk: MiniscriptKey> ForEachKey<Pk> for Wpkh<Pk> {
537    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
538    where
539        Pk: 'a,
540    {
541        pred(&self.pk)
542    }
543}
544
545impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Wpkh<P> {
546    type Output = Wpkh<Q>;
547
548    fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
549    where
550        T: Translator<P, Q, E>,
551    {
552        Ok(Wpkh::new(t.pk(&self.pk)?).expect("Uncompressed keys in Wpkh"))
553    }
554}