miniscript/descriptor/
segwitv0.rs

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