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