Skip to main content

elements_miniscript/descriptor/
bare.rs

1// Written in 2020 by the rust-miniscript developers
2// SPDX-License-Identifier: CC0-1.0
3
4//! # Bare Output Descriptors
5//!
6//! Implementation of Bare Descriptors (i.e descriptors that are)
7//! wrapped inside wsh, or sh fragments.
8//! Also includes pk, and pkh descriptors
9//!
10
11use core::fmt;
12
13use elements::{self, script, secp256k1_zkp, Script};
14
15use super::ELMTS_STR;
16use crate::descriptor::checksum::{self, verify_checksum};
17use crate::expression::{self, FromTree};
18use crate::miniscript::context::ScriptContext;
19use crate::policy::{semantic, Liftable};
20use crate::util::{varint_len, witness_to_scriptsig};
21use crate::{
22    elementssig_to_rawsig, BareCtx, Error, ForEachKey, Miniscript, MiniscriptKey, Satisfier,
23    ToPublicKey, TranslatePk, Translator,
24};
25
26/// Create a Bare Descriptor. That is descriptor that is
27/// not wrapped in sh or wsh. This covers the Pk descriptor
28#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
29pub struct Bare<Pk: MiniscriptKey> {
30    /// underlying miniscript
31    ms: Miniscript<Pk, BareCtx>,
32}
33
34impl<Pk: MiniscriptKey> Bare<Pk> {
35    /// Create a new raw descriptor
36    pub fn new(ms: Miniscript<Pk, BareCtx>) -> Result<Self, Error> {
37        // do the top-level checks
38        BareCtx::top_level_checks(&ms)?;
39        Ok(Self { ms })
40    }
41
42    /// get the inner
43    pub fn into_inner(self) -> Miniscript<Pk, BareCtx> {
44        self.ms
45    }
46
47    /// get the inner
48    pub fn as_inner(&self) -> &Miniscript<Pk, BareCtx> {
49        &self.ms
50    }
51
52    /// Checks whether the descriptor is safe.
53    pub fn sanity_check(&self) -> Result<(), Error> {
54        self.ms.sanity_check()?;
55        Ok(())
56    }
57
58    /// Computes an upper bound on the difference between a non-satisfied
59    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
60    ///
61    /// Since this method uses `segwit_weight` instead of `legacy_weight`,
62    /// if you want to include only legacy inputs in your transaction,
63    /// you should remove 1WU from each input's `max_weight_to_satisfy`
64    /// for a more accurate estimate.
65    ///
66    /// Assumes all ECDSA signatures are 73 bytes, including push opcode and
67    /// sighash suffix.
68    ///
69    /// # Errors
70    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
71    pub fn max_weight_to_satisfy(&self) -> Result<usize, Error> {
72        let scriptsig_size = self.ms.max_satisfaction_size()?;
73        // scriptSig varint difference between non-satisfied (0) and satisfied
74        let scriptsig_varint_diff = varint_len(scriptsig_size) - varint_len(0);
75        Ok(4 * (scriptsig_varint_diff + scriptsig_size))
76    }
77
78    /// Computes an upper bound on the weight of a satisfying witness to the
79    /// transaction.
80    ///
81    /// Assumes all ec-signatures are 73 bytes, including push opcode and
82    /// sighash suffix. Includes the weight of the VarInts encoding the
83    /// scriptSig and witness stack length.
84    ///
85    /// # Errors
86    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
87    #[deprecated(note = "use max_weight_to_satisfy instead")]
88    pub fn max_satisfaction_weight(&self) -> Result<usize, Error> {
89        let scriptsig_len = self.ms.max_satisfaction_size()?;
90        Ok(4 * (varint_len(scriptsig_len) + scriptsig_len))
91    }
92}
93
94impl<Pk: MiniscriptKey + ToPublicKey> Bare<Pk> {
95    /// Obtains the corresponding script pubkey for this descriptor.
96    pub fn script_pubkey(&self) -> Script {
97        self.ms.encode()
98    }
99
100    /// Obtains the underlying miniscript for this descriptor.
101    pub fn inner_script(&self) -> Script {
102        self.script_pubkey()
103    }
104
105    /// Obtains the pre bip-340 signature script code for this descriptor.
106    pub fn ecdsa_sighash_script_code(&self) -> Script {
107        self.script_pubkey()
108    }
109
110    /// Returns satisfying non-malleable witness and scriptSig with minimum
111    /// weight to spend an output controlled by the given descriptor if it is
112    /// possible to construct one using the `satisfier`.
113    pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
114    where
115        S: Satisfier<Pk>,
116    {
117        let ms = self.ms.satisfy(satisfier)?;
118        let script_sig = witness_to_scriptsig(&ms);
119        let witness = vec![];
120        Ok((witness, script_sig))
121    }
122
123    /// Returns satisfying, possibly malleable, witness and scriptSig with
124    /// minimum weight to spend an output controlled by the given descriptor if
125    /// it is possible to construct one using the `satisfier`.
126    pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
127    where
128        S: Satisfier<Pk>,
129    {
130        let ms = self.ms.satisfy_malleable(satisfier)?;
131        let script_sig = witness_to_scriptsig(&ms);
132        let witness = vec![];
133        Ok((witness, script_sig))
134    }
135}
136
137impl<Pk: MiniscriptKey> fmt::Debug for Bare<Pk> {
138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
139        write!(f, "{}{:?}", ELMTS_STR, self.ms)
140    }
141}
142
143impl<Pk: MiniscriptKey> fmt::Display for Bare<Pk> {
144    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
145        use fmt::Write;
146        let mut wrapped_f = checksum::Formatter::new(f);
147        write!(wrapped_f, "{}{}", ELMTS_STR, self.ms)?;
148        wrapped_f.write_checksum_if_not_alt()
149    }
150}
151
152impl<Pk: MiniscriptKey> Liftable<Pk> for Bare<Pk> {
153    fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
154        self.ms.lift()
155    }
156}
157
158impl_from_tree!(
159    Bare<Pk>,
160    fn from_tree(top: &expression::Tree<'_>) -> Result<Self, Error> {
161        // extra allocations to use the existing code as is.
162        if top.name.starts_with("el") {
163            let new_tree = expression::Tree {
164                name: top.name.split_at(2).1,
165                args: top.args.clone(),
166            };
167            let sub = Miniscript::<Pk, BareCtx>::from_tree(&new_tree)?;
168            BareCtx::top_level_checks(&sub)?;
169            Bare::new(sub)
170        } else {
171            Err(Error::Unexpected("Not an elements descriptor".to_string()))
172        }
173    }
174);
175
176impl_from_str!(
177    Bare<Pk>,
178    type Err = Error;,
179    fn from_str(s: &str) -> Result<Self, Self::Err> {
180        let desc_str = verify_checksum(s)?;
181        let top = expression::Tree::from_str(&desc_str[2..])?;
182        Self::from_tree(&top)
183    }
184);
185
186impl<Pk: MiniscriptKey> ForEachKey<Pk> for Bare<Pk> {
187    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, pred: F) -> bool
188    where
189        Pk: 'a,
190    {
191        self.ms.for_each_key(pred)
192    }
193}
194
195impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Bare<P> {
196    type Output = Bare<Q>;
197
198    fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
199    where
200        T: Translator<P, Q, E>,
201    {
202        Ok(Bare::new(self.ms.translate_pk(t)?).expect("Translation cannot fail inside Bare"))
203    }
204}
205
206/// A bare PkH descriptor at top level
207#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
208pub struct Pkh<Pk: MiniscriptKey> {
209    /// underlying publickey
210    pk: Pk,
211}
212
213impl<Pk: MiniscriptKey> Pkh<Pk> {
214    /// Create a new Pkh descriptor
215    pub fn new(pk: Pk) -> Self {
216        // do the top-level checks
217        Self { pk }
218    }
219
220    /// Get a reference to the inner key
221    pub fn as_inner(&self) -> &Pk {
222        &self.pk
223    }
224
225    /// Get the inner key
226    pub fn into_inner(self) -> Pk {
227        self.pk
228    }
229
230    /// Computes an upper bound on the difference between a non-satisfied
231    /// `TxIn`'s `segwit_weight` and a satisfied `TxIn`'s `segwit_weight`
232    ///
233    /// Since this method uses `segwit_weight` instead of `legacy_weight`,
234    /// if you want to include only legacy inputs in your transaction,
235    /// you should remove 1WU from each input's `max_weight_to_satisfy`
236    /// for a more accurate estimate.
237    ///
238    /// Assumes all ECDSA signatures are 73 bytes, including push opcode and
239    /// sighash suffix.
240    ///
241    /// # Errors
242    /// When the descriptor is impossible to safisfy (ex: sh(OP_FALSE)).
243    pub fn max_weight_to_satisfy(&self) -> usize {
244        // OP_72 + <sig(71)+sigHash(1)> + OP_33 + <pubkey>
245        let scriptsig_size = 73 + BareCtx::pk_len(&self.pk);
246        // scriptSig varint different between non-satisfied (0) and satisfied
247        let scriptsig_varint_diff = varint_len(scriptsig_size) - varint_len(0);
248        4 * (scriptsig_varint_diff + scriptsig_size)
249    }
250
251    /// Computes an upper bound on the weight of a satisfying witness to the
252    /// transaction.
253    ///
254    /// Assumes all ec-signatures are 73 bytes, including push opcode and
255    /// sighash suffix. Includes the weight of the VarInts encoding the
256    /// scriptSig and witness stack length.
257    pub fn max_satisfaction_weight(&self) -> usize {
258        4 * (1 + 73 + BareCtx::pk_len(&self.pk))
259    }
260}
261
262impl<Pk: MiniscriptKey + ToPublicKey> Pkh<Pk> {
263    /// Obtains the corresponding script pubkey for this descriptor.
264    pub fn script_pubkey(&self) -> Script {
265        // Fine to hard code the `Network` here because we immediately call
266        // `script_pubkey` which does not use the `network` field of `Address`.
267        let addr = elements::Address::p2pkh(
268            &self.pk.to_public_key(),
269            None,
270            &elements::AddressParams::ELEMENTS,
271        );
272        addr.script_pubkey()
273    }
274
275    /// Obtains the corresponding script pubkey for this descriptor.
276    pub fn address(
277        &self,
278        blinder: Option<secp256k1_zkp::PublicKey>,
279        params: &'static elements::address::AddressParams,
280    ) -> elements::Address {
281        elements::Address::p2pkh(&self.pk.to_public_key(), blinder, params)
282    }
283
284    /// Obtains the underlying miniscript for this descriptor.
285    pub fn inner_script(&self) -> Script {
286        self.script_pubkey()
287    }
288
289    /// Obtains the pre bip-340 signature script code for this descriptor.
290    pub fn ecdsa_sighash_script_code(&self) -> Script {
291        self.script_pubkey()
292    }
293
294    /// Returns satisfying non-malleable witness and scriptSig with minimum
295    /// weight to spend an output controlled by the given descriptor if it is
296    /// possible to construct one using the `satisfier`.
297    pub fn get_satisfaction<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
298    where
299        S: Satisfier<Pk>,
300    {
301        if let Some(sig) = satisfier.lookup_ecdsa_sig(&self.pk) {
302            let sig_vec = elementssig_to_rawsig(&sig);
303            let script_sig = script::Builder::new()
304                .push_slice(&sig_vec[..])
305                .push_key(&self.pk.to_public_key())
306                .into_script();
307            let witness = vec![];
308            Ok((witness, script_sig))
309        } else {
310            Err(Error::MissingSig(self.pk.to_public_key()))
311        }
312    }
313
314    /// Returns satisfying, possibly malleable, witness and scriptSig with
315    /// minimum weight to spend an output controlled by the given descriptor if
316    /// it is possible to construct one using the `satisfier`.
317    pub fn get_satisfaction_mall<S>(&self, satisfier: S) -> Result<(Vec<Vec<u8>>, Script), Error>
318    where
319        S: Satisfier<Pk>,
320    {
321        self.get_satisfaction(satisfier)
322    }
323}
324
325impl<Pk: MiniscriptKey> fmt::Debug for Pkh<Pk> {
326    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327        write!(f, "{}pkh({:?})", ELMTS_STR, self.pk)
328    }
329}
330
331impl<Pk: MiniscriptKey> fmt::Display for Pkh<Pk> {
332    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333        use fmt::Write;
334        let mut wrapped_f = checksum::Formatter::new(f);
335        write!(wrapped_f, "{}pkh({})", ELMTS_STR, self.pk)?;
336        wrapped_f.write_checksum_if_not_alt()
337    }
338}
339
340impl<Pk: MiniscriptKey> Liftable<Pk> for Pkh<Pk> {
341    fn lift(&self) -> Result<semantic::Policy<Pk>, Error> {
342        Ok(semantic::Policy::Key(self.pk.clone()))
343    }
344}
345
346impl_from_tree!(
347    Pkh<Pk>,
348    fn from_tree(top: &expression::Tree) -> Result<Self, Error> {
349        if top.name == "elpkh" && top.args.len() == 1 {
350            Ok(Pkh::new(expression::terminal(&top.args[0], |pk| {
351                Pk::from_str(pk)
352            })?))
353        } else {
354            Err(Error::Unexpected(format!(
355                "{}({} args) while parsing pkh descriptor",
356                top.name,
357                top.args.len(),
358            )))
359        }
360    }
361);
362
363impl_from_str!(
364    Pkh<Pk>,
365    type Err = Error;,
366    fn from_str(s: &str) -> Result<Self, Self::Err> {
367        let desc_str = verify_checksum(s)?;
368        let top = expression::Tree::from_str(desc_str)?;
369        Self::from_tree(&top)
370    }
371);
372
373impl<Pk: MiniscriptKey> ForEachKey<Pk> for Pkh<Pk> {
374    fn for_each_key<'a, F: FnMut(&'a Pk) -> bool>(&'a self, mut pred: F) -> bool
375    where
376        Pk: 'a,
377    {
378        pred(&self.pk)
379    }
380}
381
382impl<P: MiniscriptKey, Q: MiniscriptKey> TranslatePk<P, Q> for Pkh<P> {
383    type Output = Pkh<Q>;
384
385    fn translate_pk<T, E>(&self, t: &mut T) -> Result<Self::Output, E>
386    where
387        T: Translator<P, Q, E>,
388    {
389        Ok(Pkh::new(t.pk(&self.pk)?))
390    }
391}