miniscript_debug/descriptor/
segwitv0.rs

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