sapio_miniscript/psbt/
mod.rs

1// Miniscript
2// Written in 2019 by
3//     Andrew Poelstra <apoelstra@wpsoftware.net>
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! # Partially-Signed Bitcoin Transactions
16//!
17//! This module implements the Finalizer and Extractor roles defined in
18//! BIP 174, PSBT, described at
19//! `https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki`
20//!
21
22use std::collections::BTreeMap;
23use std::ops::{Deref, Range};
24use std::{error, fmt};
25
26use bitcoin::consensus::Encodable;
27use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
28use bitcoin::secp256k1::{self, Secp256k1};
29use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
30use bitcoin::util::sighash::SighashCache;
31use bitcoin::{self, SchnorrSighashType};
32use bitcoin::{EcdsaSighashType, Script};
33
34use bitcoin::util::taproot::{self, ControlBlock, LeafVersion, TapLeafHash};
35use descriptor;
36use interpreter;
37use miniscript::limits::SEQUENCE_LOCKTIME_DISABLE_FLAG;
38use miniscript::satisfy::{After, Older};
39use Preimage32;
40use Satisfier;
41use {Descriptor, DescriptorPublicKey, DescriptorTrait, MiniscriptKey, ToPublicKey};
42
43mod finalizer;
44
45#[allow(deprecated)]
46pub use self::finalizer::{finalize, finalize_mall, interpreter_check};
47
48/// Error type for Pbst Input
49#[derive(Debug)]
50pub enum InputError {
51    /// Get the secp Errors directly
52    SecpErr(bitcoin::secp256k1::Error),
53    /// Key errors
54    KeyErr(bitcoin::util::key::Error),
55    /// Could not satisfy taproot descriptor
56    /// This error is returned when both script path and key paths could not be
57    /// satisfied. We cannot return a detailed error because we try all miniscripts
58    /// in script spend path, we cannot know which miniscript failed.
59    CouldNotSatisfyTr,
60    /// Error doing an interpreter-check on a finalized psbt
61    Interpreter(interpreter::Error),
62    /// Redeem script does not match the p2sh hash
63    InvalidRedeemScript {
64        /// Redeem script
65        redeem: Script,
66        /// Expected p2sh Script
67        p2sh_expected: Script,
68    },
69    /// Witness script does not match the p2wsh hash
70    InvalidWitnessScript {
71        /// Witness Script
72        witness_script: Script,
73        /// Expected p2wsh script
74        p2wsh_expected: Script,
75    },
76    /// Invalid sig
77    InvalidSignature {
78        /// The bitcoin public key
79        pubkey: bitcoin::PublicKey,
80        /// The (incorrect) signature
81        sig: Vec<u8>,
82    },
83    /// Pass through the underlying errors in miniscript
84    MiniscriptError(super::Error),
85    /// Missing redeem script for p2sh
86    MissingRedeemScript,
87    /// Missing witness
88    MissingWitness,
89    /// used for public key corresponding to pkh/wpkh
90    MissingPubkey,
91    /// Missing witness script for segwit descriptors
92    MissingWitnessScript,
93    ///Missing both the witness and non-witness utxo
94    MissingUtxo,
95    /// Non empty Witness script for p2sh
96    NonEmptyWitnessScript,
97    /// Non empty Redeem script
98    NonEmptyRedeemScript,
99    /// Non Standard sighash type
100    NonStandardSighashType(bitcoin::blockdata::transaction::NonStandardSighashType),
101    /// Sighash did not match
102    WrongSighashFlag {
103        /// required sighash type
104        required: bitcoin::EcdsaSighashType,
105        /// the sighash type we got
106        got: bitcoin::EcdsaSighashType,
107        /// the corresponding publickey
108        pubkey: bitcoin::PublicKey,
109    },
110}
111
112/// Error type for entire Psbt
113#[derive(Debug)]
114pub enum Error {
115    /// Input Error type
116    InputError(InputError, usize),
117    /// Wrong Input Count
118    WrongInputCount {
119        /// Input count in tx
120        in_tx: usize,
121        /// Input count in psbt
122        in_map: usize,
123    },
124    /// Psbt Input index out of bounds
125    InputIdxOutofBounds {
126        /// Inputs in pbst
127        psbt_inp: usize,
128        /// requested index
129        index: usize,
130    },
131}
132
133impl fmt::Display for InputError {
134    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135        match *self {
136            InputError::InvalidSignature {
137                ref pubkey,
138                ref sig,
139            } => write!(f, "PSBT: bad signature {} for key {:?}", pubkey, sig),
140            InputError::KeyErr(ref e) => write!(f, "Key Err: {}", e),
141            InputError::Interpreter(ref e) => write!(f, "Interpreter: {}", e),
142            InputError::SecpErr(ref e) => write!(f, "Secp Err: {}", e),
143            InputError::InvalidRedeemScript {
144                ref redeem,
145                ref p2sh_expected,
146            } => write!(
147                f,
148                "Redeem script {} does not match the p2sh script {}",
149                redeem, p2sh_expected
150            ),
151            InputError::InvalidWitnessScript {
152                ref witness_script,
153                ref p2wsh_expected,
154            } => write!(
155                f,
156                "Witness script {} does not match the p2wsh script {}",
157                witness_script, p2wsh_expected
158            ),
159            InputError::MiniscriptError(ref e) => write!(f, "Miniscript Error: {}", e),
160            InputError::MissingWitness => write!(f, "PSBT is missing witness"),
161            InputError::MissingRedeemScript => write!(f, "PSBT is Redeem script"),
162            InputError::MissingUtxo => {
163                write!(f, "PSBT is missing both witness and non-witness UTXO")
164            }
165            InputError::MissingWitnessScript => write!(f, "PSBT is missing witness script"),
166            InputError::MissingPubkey => write!(f, "Missing pubkey for a pkh/wpkh"),
167            InputError::NonEmptyRedeemScript => write!(
168                f,
169                "PSBT has non-empty redeem script at for legacy transactions"
170            ),
171            InputError::NonEmptyWitnessScript => {
172                write!(f, "PSBT has non-empty witness script at for legacy input")
173            }
174            InputError::WrongSighashFlag {
175                required,
176                got,
177                pubkey,
178            } => write!(
179                f,
180                "PSBT: signature with key {:?} had \
181                 sighashflag {:?} rather than required {:?}",
182                pubkey, got, required
183            ),
184            InputError::CouldNotSatisfyTr => {
185                write!(f, "Could not satisfy Tr descriptor")
186            }
187            InputError::NonStandardSighashType(e) => write!(f, "Non-standard sighash type {}", e),
188        }
189    }
190}
191
192#[doc(hidden)]
193impl From<super::Error> for InputError {
194    fn from(e: super::Error) -> InputError {
195        InputError::MiniscriptError(e)
196    }
197}
198
199#[doc(hidden)]
200impl From<bitcoin::secp256k1::Error> for InputError {
201    fn from(e: bitcoin::secp256k1::Error) -> InputError {
202        InputError::SecpErr(e)
203    }
204}
205
206#[doc(hidden)]
207impl From<bitcoin::util::key::Error> for InputError {
208    fn from(e: bitcoin::util::key::Error) -> InputError {
209        InputError::KeyErr(e)
210    }
211}
212
213impl error::Error for Error {}
214
215impl fmt::Display for Error {
216    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
217        match *self {
218            Error::InputError(ref inp_err, index) => write!(f, "{} at index {}", inp_err, index),
219            Error::WrongInputCount { in_tx, in_map } => write!(
220                f,
221                "PSBT had {} inputs in transaction but {} inputs in map",
222                in_tx, in_map
223            ),
224            Error::InputIdxOutofBounds { psbt_inp, index } => write!(
225                f,
226                "psbt input index {} out of bounds: psbt.inputs.len() {}",
227                index, psbt_inp
228            ),
229        }
230    }
231}
232
233/// Psbt satisfier for at inputs at a particular index
234/// Takes in &psbt because multiple inputs will share
235/// the same psbt structure
236/// All operations on this structure will panic if index
237/// is more than number of inputs in pbst
238pub struct PsbtInputSatisfier<'psbt> {
239    /// pbst
240    pub psbt: &'psbt Psbt,
241    /// input index
242    pub index: usize,
243}
244
245impl<'psbt> PsbtInputSatisfier<'psbt> {
246    /// create a new PsbtInputsatisfier from
247    /// psbt and index
248    pub fn new(psbt: &'psbt Psbt, index: usize) -> Self {
249        Self {
250            psbt: psbt,
251            index: index,
252        }
253    }
254}
255
256impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfier<'psbt> {
257    fn lookup_tap_key_spend_sig(&self) -> Option<bitcoin::SchnorrSig> {
258        self.psbt.inputs[self.index].tap_key_sig
259    }
260
261    fn lookup_tap_leaf_script_sig(&self, pk: &Pk, lh: &TapLeafHash) -> Option<bitcoin::SchnorrSig> {
262        self.psbt.inputs[self.index]
263            .tap_script_sigs
264            .get(&(pk.to_x_only_pubkey(), *lh))
265            .map(|x| *x) // replace by copied in 1.36
266    }
267
268    fn lookup_tap_control_block_map(
269        &self,
270    ) -> Option<&BTreeMap<ControlBlock, (bitcoin::Script, LeafVersion)>> {
271        Some(&self.psbt.inputs[self.index].tap_scripts)
272    }
273
274    fn lookup_pkh_tap_leaf_script_sig(
275        &self,
276        pkh: &(Pk::Hash, TapLeafHash),
277    ) -> Option<(bitcoin::secp256k1::XOnlyPublicKey, bitcoin::SchnorrSig)> {
278        self.psbt.inputs[self.index]
279            .tap_script_sigs
280            .iter()
281            .filter(|&((pubkey, lh), _sig)| {
282                pubkey.to_pubkeyhash() == Pk::hash_to_hash160(&pkh.0) && *lh == pkh.1
283            })
284            .next()
285            .map(|((x_only_pk, _leaf_hash), sig)| (*x_only_pk, *sig))
286    }
287
288    fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option<bitcoin::EcdsaSig> {
289        self.psbt.inputs[self.index]
290            .partial_sigs
291            .get(&pk.to_public_key())
292            .map(|sig| *sig)
293    }
294
295    fn lookup_pkh_ecdsa_sig(
296        &self,
297        pkh: &Pk::Hash,
298    ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> {
299        self.psbt.inputs[self.index]
300            .partial_sigs
301            .iter()
302            .filter(|&(pubkey, _sig)| pubkey.to_pubkeyhash() == Pk::hash_to_hash160(pkh))
303            .next()
304            .map(|(pk, sig)| (*pk, *sig))
305    }
306
307    fn check_after(&self, n: u32) -> bool {
308        let locktime = self.psbt.unsigned_tx.lock_time;
309        let seq = self.psbt.unsigned_tx.input[self.index].sequence;
310
311        // https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki
312        // fail if TxIn is finalized
313        if seq == 0xffffffff {
314            false
315        } else {
316            <dyn Satisfier<Pk>>::check_after(&After(locktime), n)
317        }
318    }
319
320    fn check_older(&self, n: u32) -> bool {
321        let seq = self.psbt.unsigned_tx.input[self.index].sequence;
322        // https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
323        // Disable flag set. return true
324        if n & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
325            true
326        } else if self.psbt.unsigned_tx.version < 2 || (seq & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0) {
327            // transaction version and sequence check
328            false
329        } else {
330            <dyn Satisfier<Pk>>::check_older(&Older(seq), n)
331        }
332    }
333
334    fn lookup_hash160(&self, h: hash160::Hash) -> Option<Preimage32> {
335        self.psbt.inputs[self.index]
336            .hash160_preimages
337            .get(&h)
338            .and_then(try_vec_as_preimage32)
339    }
340
341    fn lookup_sha256(&self, h: sha256::Hash) -> Option<Preimage32> {
342        self.psbt.inputs[self.index]
343            .sha256_preimages
344            .get(&h)
345            .and_then(try_vec_as_preimage32)
346    }
347
348    fn lookup_hash256(&self, h: sha256d::Hash) -> Option<Preimage32> {
349        self.psbt.inputs[self.index]
350            .hash256_preimages
351            .get(&h)
352            .and_then(try_vec_as_preimage32)
353    }
354
355    fn lookup_ripemd160(&self, h: ripemd160::Hash) -> Option<Preimage32> {
356        self.psbt.inputs[self.index]
357            .ripemd160_preimages
358            .get(&h)
359            .and_then(try_vec_as_preimage32)
360    }
361
362    fn check_tx_template(&self, h: sha256::Hash) -> bool {
363        // do costly extract otherwise the scriptSigs are empty
364        get_ctv_hash(&self.psbt.clone().extract_tx(), self.index as u32) == h
365    }
366}
367
368pub(crate) fn get_ctv_hash(tx: &bitcoin::Transaction, input_index: u32) -> sha256::Hash {
369    let mut ctv_hash = sha256::Hash::engine();
370    tx.version.consensus_encode(&mut ctv_hash).unwrap();
371    tx.lock_time.consensus_encode(&mut ctv_hash).unwrap();
372    (tx.input.len() as u32)
373        .consensus_encode(&mut ctv_hash)
374        .unwrap();
375    {
376        let mut enc = sha256::Hash::engine();
377        for seq in tx.input.iter().map(|i| i.sequence) {
378            seq.consensus_encode(&mut enc).unwrap();
379        }
380        sha256::Hash::from_engine(enc)
381            .into_inner()
382            .consensus_encode(&mut ctv_hash)
383            .unwrap();
384    }
385
386    (tx.output.len() as u32)
387        .consensus_encode(&mut ctv_hash)
388        .unwrap();
389
390    {
391        let mut enc = sha256::Hash::engine();
392        for out in tx.output.iter() {
393            out.consensus_encode(&mut enc).unwrap();
394        }
395        sha256::Hash::from_engine(enc)
396            .into_inner()
397            .consensus_encode(&mut ctv_hash)
398            .unwrap();
399    }
400    input_index.consensus_encode(&mut ctv_hash).unwrap();
401    sha256::Hash::from_engine(ctv_hash)
402}
403fn try_vec_as_preimage32(vec: &Vec<u8>) -> Option<Preimage32> {
404    if vec.len() == 32 {
405        let mut arr = [0u8; 32];
406        arr.copy_from_slice(&vec);
407        Some(arr)
408    } else {
409        None
410    }
411}
412
413// Basic sanity checks on psbts.
414// rust-bitcoin TODO: (Long term)
415// Brainstorm about how we can enforce these in type system while having a nice API
416fn sanity_check(psbt: &Psbt) -> Result<(), Error> {
417    if psbt.unsigned_tx.input.len() != psbt.inputs.len() {
418        return Err(Error::WrongInputCount {
419            in_tx: psbt.unsigned_tx.input.len(),
420            in_map: psbt.inputs.len(),
421        }
422        .into());
423    }
424
425    // Check well-formedness of input data
426    for (index, input) in psbt.inputs.iter().enumerate() {
427        // TODO: fix this after https://github.com/rust-bitcoin/rust-bitcoin/issues/838
428        let target_ecdsa_sighash_ty = match input.sighash_type {
429            Some(psbt_hash_ty) => psbt_hash_ty
430                .ecdsa_hash_ty()
431                .map_err(|e| Error::InputError(InputError::NonStandardSighashType(e), index))?,
432            None => EcdsaSighashType::All,
433        };
434        for (key, ecdsa_sig) in &input.partial_sigs {
435            let flag = bitcoin::EcdsaSighashType::from_standard(ecdsa_sig.hash_ty as u32).map_err(
436                |_| {
437                    Error::InputError(
438                        InputError::Interpreter(interpreter::Error::NonStandardSighash(
439                            ecdsa_sig.to_vec(),
440                        )),
441                        index,
442                    )
443                },
444            )?;
445            if target_ecdsa_sighash_ty != flag {
446                return Err(Error::InputError(
447                    InputError::WrongSighashFlag {
448                        required: target_ecdsa_sighash_ty,
449                        got: flag,
450                        pubkey: *key,
451                    },
452                    index,
453                ));
454            }
455            // Signatures are well-formed in psbt partial sigs
456        }
457    }
458
459    Ok(())
460}
461
462/// Additional operations for miniscript descriptors for various psbt roles.
463/// Note that these APIs would generally error when used on scripts that are not
464/// miniscripts.
465pub trait PsbtExt {
466    /// Finalize the psbt. This function takes in a mutable reference to psbt
467    /// and populates the final_witness and final_scriptsig
468    /// for all miniscript inputs.
469    ///
470    /// Finalizes all inputs that it can finalize, and returns an error for each input
471    /// that it cannot finalize. Also performs a sanity interpreter check on the
472    /// finalized psbt which involves checking the signatures/ preimages/timelocks.
473    ///
474    /// Input finalization also fails if it is not possible to satisfy any of the inputs non-malleably
475    /// See [finalizer::finalize_mall] if you want to allow malleable satisfactions
476    ///
477    /// For finalizing individual inputs, see also [`PsbtExt::finalize_inp`]
478    ///
479    /// # Errors:
480    ///
481    /// - A vector of errors, one of each of failed finalized input
482    fn finalize_mut<C: secp256k1::Verification>(
483        &mut self,
484        secp: &secp256k1::Secp256k1<C>,
485    ) -> Result<(), Vec<Error>>;
486
487    /// Same as [`PsbtExt::finalize_mut`], but does not mutate the input psbt and
488    /// returns a new psbt
489    ///
490    /// # Errors:
491    ///
492    /// - Returns a mutated psbt with all inputs `finalize_mut` could finalize
493    /// - A vector of input errors, one of each of failed finalized input
494    fn finalize<C: secp256k1::Verification>(
495        self,
496        secp: &secp256k1::Secp256k1<C>,
497    ) -> Result<Psbt, (Psbt, Vec<Error>)>;
498
499    /// Same as [PsbtExt::finalize_mut], but allows for malleable satisfactions
500    fn finalize_mall_mut<C: secp256k1::Verification>(
501        &mut self,
502        secp: &Secp256k1<C>,
503    ) -> Result<(), Vec<Error>>;
504
505    /// Same as [PsbtExt::finalize], but allows for malleable satisfactions
506    fn finalize_mall<C: secp256k1::Verification>(
507        self,
508        secp: &Secp256k1<C>,
509    ) -> Result<Psbt, (Psbt, Vec<Error>)>;
510
511    /// Same as [`PsbtExt::finalize_mut`], but only tries to finalize a single input leaving other
512    /// inputs as is. Use this when not all of inputs that you are trying to
513    /// satisfy are miniscripts
514    ///
515    /// # Errors:
516    ///
517    /// - Input error detailing why the finalization failed. The psbt is not mutated when the finalization fails
518    fn finalize_inp_mut<C: secp256k1::Verification>(
519        &mut self,
520        secp: &secp256k1::Secp256k1<C>,
521        index: usize,
522    ) -> Result<(), Error>;
523
524    /// Same as [`PsbtExt::finalize_inp_mut`], but does not mutate the psbt and returns a new one
525    ///
526    /// # Errors:
527    ///  Returns a tuple containing
528    /// - Original psbt
529    /// - Input Error detailing why the input finalization failed
530    fn finalize_inp<C: secp256k1::Verification>(
531        self,
532        secp: &secp256k1::Secp256k1<C>,
533        index: usize,
534    ) -> Result<Psbt, (Psbt, Error)>;
535
536    /// Same as [`PsbtExt::finalize_inp_mut`], but allows for malleable satisfactions
537    fn finalize_inp_mall_mut<C: secp256k1::Verification>(
538        &mut self,
539        secp: &secp256k1::Secp256k1<C>,
540        index: usize,
541    ) -> Result<(), Error>;
542
543    /// Same as [`PsbtExt::finalize_inp`], but allows for malleable satisfactions
544    fn finalize_inp_mall<C: secp256k1::Verification>(
545        self,
546        secp: &secp256k1::Secp256k1<C>,
547        index: usize,
548    ) -> Result<Psbt, (Psbt, Error)>;
549
550    /// Psbt extractor as defined in BIP174 that takes in a psbt reference
551    /// and outputs a extracted bitcoin::Transaction
552    /// Also does the interpreter sanity check
553    /// Will error if the final ScriptSig or final Witness are missing
554    /// or the interpreter check fails.
555    fn extract<C: secp256k1::Verification>(
556        &self,
557        secp: &Secp256k1<C>,
558    ) -> Result<bitcoin::Transaction, Error>;
559
560    /// Update an psbt with the derived descriptor information. If the descriptor is
561    /// - Sh: Update the redeem script
562    /// - Wsh: Update the witness script
563    /// - ShWsh/ShWpkh: Updates redeem script and witness script(in nested wsh case)
564    /// - Tr: Update the control block maps, internal key and merkle root
565    ///
566    /// # Errors:
567    ///
568    /// - If the input Index out of bounds
569    /// - If there is [`descriptor::ConversionError`] while deriving keys
570    /// - Psbt does not have corresponding witness/non-witness utxo
571    /// - Ranged descriptor not supplied with a range to call at
572    /// - If the given descriptor cannot derive the output key.
573    fn update_desc(
574        &mut self,
575        input_index: usize,
576        desc: &Descriptor<DescriptorPublicKey>,
577        range: Option<Range<u32>>,
578    ) -> Result<(), UxtoUpdateError>;
579
580    /// Get the sighash message(data to sign) at input index `idx` based on the sighash
581    /// flag specified in the [`Psbt`] sighash field. If the input sighash flag psbt field is `None`
582    /// the [`SchnorrSighashType::Default`](bitcoin::util::sighash::SchnorrSighashType::Default) is chosen
583    /// for for taproot spends, otherwise [`EcdsaSignatureHashType::All`](bitcoin::EcdsaSighashType::All) is chosen.
584    /// If the utxo at `idx` is a taproot output, returns a [`PsbtSighashMsg::TapSighash`] variant.
585    /// If the utxo at `idx` is a pre-taproot output, returns a [`PsbtSighashMsg::EcdsaSighash`] variant.
586    /// The `tapleaf_hash` parameter can be used to specify which tapleaf script hash has to be computed. If
587    /// `tapleaf_hash` is [`None`], and the output is taproot output, the key spend hash is computed. This parameter must be
588    /// set to [`None`] while computing sighash for pre-taproot outputs.
589    /// The function also updates the sighash cache with transaction computed during sighash computation of this input
590    ///
591    /// # Arguments:
592    ///
593    /// * `idx`: The input index of psbt to sign
594    /// * `cache`: The [`sighash::SighashCache`] for used to cache/read previously cached computations
595    /// * `tapleaf_hash`: If the output is taproot, compute the sighash for this particular leaf.
596    fn sighash_msg<T: Deref<Target = bitcoin::Transaction>>(
597        &self,
598        idx: usize,
599        cache: &mut SighashCache<T>,
600        tapleaf_hash: Option<TapLeafHash>,
601    ) -> Result<PsbtSighashMsg, SighashError>;
602}
603
604impl PsbtExt for Psbt {
605    fn finalize_mut<C: secp256k1::Verification>(
606        &mut self,
607        secp: &secp256k1::Secp256k1<C>,
608    ) -> Result<(), Vec<Error>> {
609        // Actually construct the witnesses
610        let mut errors = vec![];
611        for index in 0..self.inputs.len() {
612            match finalizer::finalize_input(self, index, secp, /*allow_mall*/ false) {
613                Ok(..) => {}
614                Err(e) => {
615                    errors.push(e);
616                }
617            }
618        }
619        if errors.is_empty() {
620            Ok(())
621        } else {
622            Err(errors)
623        }
624    }
625
626    fn finalize<C: secp256k1::Verification>(
627        mut self,
628        secp: &secp256k1::Secp256k1<C>,
629    ) -> Result<Psbt, (Psbt, Vec<Error>)> {
630        match self.finalize_mut(secp) {
631            Ok(..) => Ok(self),
632            Err(e) => Err((self, e)),
633        }
634    }
635
636    fn finalize_mall_mut<C: secp256k1::Verification>(
637        &mut self,
638        secp: &secp256k1::Secp256k1<C>,
639    ) -> Result<(), Vec<Error>> {
640        let mut errors = vec![];
641        for index in 0..self.inputs.len() {
642            match finalizer::finalize_input(self, index, secp, /*allow_mall*/ true) {
643                Ok(..) => {}
644                Err(e) => {
645                    errors.push(e);
646                }
647            }
648        }
649        if errors.is_empty() {
650            Ok(())
651        } else {
652            Err(errors)
653        }
654    }
655
656    fn finalize_mall<C: secp256k1::Verification>(
657        mut self,
658        secp: &Secp256k1<C>,
659    ) -> Result<Psbt, (Psbt, Vec<Error>)> {
660        match self.finalize_mall_mut(secp) {
661            Ok(..) => Ok(self),
662            Err(e) => Err((self, e)),
663        }
664    }
665
666    fn finalize_inp_mut<C: secp256k1::Verification>(
667        &mut self,
668        secp: &secp256k1::Secp256k1<C>,
669        index: usize,
670    ) -> Result<(), Error> {
671        if index >= self.inputs.len() {
672            return Err(Error::InputIdxOutofBounds {
673                psbt_inp: self.inputs.len(),
674                index: index,
675            });
676        }
677        finalizer::finalize_input(self, index, secp, /*allow_mall*/ false)
678    }
679
680    fn finalize_inp<C: secp256k1::Verification>(
681        mut self,
682        secp: &secp256k1::Secp256k1<C>,
683        index: usize,
684    ) -> Result<Psbt, (Psbt, Error)> {
685        match self.finalize_inp_mut(secp, index) {
686            Ok(..) => Ok(self),
687            Err(e) => Err((self, e)),
688        }
689    }
690
691    fn finalize_inp_mall_mut<C: secp256k1::Verification>(
692        &mut self,
693        secp: &secp256k1::Secp256k1<C>,
694        index: usize,
695    ) -> Result<(), Error> {
696        if index >= self.inputs.len() {
697            return Err(Error::InputIdxOutofBounds {
698                psbt_inp: self.inputs.len(),
699                index: index,
700            });
701        }
702        finalizer::finalize_input(self, index, secp, /*allow_mall*/ false)
703    }
704
705    fn finalize_inp_mall<C: secp256k1::Verification>(
706        mut self,
707        secp: &secp256k1::Secp256k1<C>,
708        index: usize,
709    ) -> Result<Psbt, (Psbt, Error)> {
710        match self.finalize_inp_mall_mut(secp, index) {
711            Ok(..) => Ok(self),
712            Err(e) => Err((self, e)),
713        }
714    }
715
716    fn extract<C: secp256k1::Verification>(
717        &self,
718        secp: &Secp256k1<C>,
719    ) -> Result<bitcoin::Transaction, Error> {
720        sanity_check(self)?;
721
722        let mut ret = self.unsigned_tx.clone();
723        for (n, input) in self.inputs.iter().enumerate() {
724            if input.final_script_sig.is_none() && input.final_script_witness.is_none() {
725                return Err(Error::InputError(InputError::MissingWitness, n));
726            }
727
728            if let Some(witness) = input.final_script_witness.as_ref() {
729                ret.input[n].witness = witness.clone();
730            }
731            if let Some(script_sig) = input.final_script_sig.as_ref() {
732                ret.input[n].script_sig = script_sig.clone();
733            }
734        }
735        interpreter_check(self, secp)?;
736        Ok(ret)
737    }
738
739    fn update_desc(
740        &mut self,
741        input_index: usize,
742        desc: &Descriptor<DescriptorPublicKey>,
743        range: Option<Range<u32>>,
744    ) -> Result<(), UxtoUpdateError> {
745        if input_index >= self.inputs.len() {
746            return Err(UxtoUpdateError::IndexOutOfBounds(
747                input_index,
748                self.inputs.len(),
749            ));
750        }
751        let mut derived_desc = None;
752        // NLL block
753        {
754            let inp_spk = finalizer::get_scriptpubkey(self, input_index)
755                .map_err(|_e| UxtoUpdateError::MissingInputUxto)?;
756            let secp = secp256k1::Secp256k1::verification_only();
757
758            match range {
759                None => {
760                    if desc.is_deriveable() {
761                        return Err(UxtoUpdateError::RangeMissingWildCardDescriptor);
762                    } else {
763                        derived_desc = desc
764                            .derived_descriptor(&secp, 0)
765                            .map_err(|e| UxtoUpdateError::DerivationError(e))
766                            .ok();
767                    }
768                }
769                Some(range) => {
770                    for i in range {
771                        let derived = desc
772                            .derived_descriptor(&secp, i)
773                            .map_err(|e| UxtoUpdateError::DerivationError(e))?;
774                        if &derived.script_pubkey() == inp_spk {
775                            derived_desc = Some(derived);
776                            break;
777                        }
778                    }
779                }
780            }
781        }
782        let inp = &mut self.inputs[input_index];
783        let derived_desc = derived_desc.ok_or(UxtoUpdateError::IncorrectDescriptor)?;
784        match derived_desc {
785            Descriptor::Bare(_) | Descriptor::Pkh(_) | Descriptor::Wpkh(_) => {}
786            Descriptor::Sh(sh) => match sh.as_inner() {
787                descriptor::ShInner::Wsh(wsh) => {
788                    inp.witness_script = Some(wsh.inner_script());
789                    inp.redeem_script = Some(wsh.inner_script().to_v0_p2wsh());
790                }
791                descriptor::ShInner::Wpkh(..) => inp.redeem_script = Some(sh.inner_script()),
792                descriptor::ShInner::SortedMulti(_) | descriptor::ShInner::Ms(_) => {
793                    inp.redeem_script = Some(sh.inner_script())
794                }
795            },
796            Descriptor::Wsh(wsh) => inp.witness_script = Some(wsh.inner_script()),
797            Descriptor::Tr(tr) => {
798                let spend_info = tr.spend_info();
799                inp.tap_internal_key = Some(spend_info.internal_key());
800                inp.tap_merkle_root = spend_info.merkle_root();
801                for (_depth, ms) in tr.iter_scripts() {
802                    let leaf_script = (ms.encode(), LeafVersion::TapScript);
803                    let control_block = spend_info
804                        .control_block(&leaf_script)
805                        .expect("Control block must exist in script map for every known leaf");
806                    inp.tap_scripts.insert(control_block, leaf_script);
807                }
808            }
809        };
810        Ok(())
811    }
812
813    fn sighash_msg<T: Deref<Target = bitcoin::Transaction>>(
814        &self,
815        idx: usize,
816        cache: &mut SighashCache<T>,
817        tapleaf_hash: Option<TapLeafHash>,
818    ) -> Result<PsbtSighashMsg, SighashError> {
819        // Infer a descriptor at idx
820        if idx >= self.inputs.len() {
821            return Err(SighashError::IndexOutOfBounds(idx, self.inputs.len()));
822        }
823        let inp = &self.inputs[idx];
824        let prevouts = finalizer::prevouts(self).map_err(|_e| SighashError::MissingSpendUtxos)?;
825        // Note that as per Psbt spec we should have access to spent_utxos for the transaction
826        // Even if the transaction does not require SighashAll, we create `Prevouts::All` for code simplicity
827        let prevouts = bitcoin::util::sighash::Prevouts::All(&prevouts);
828        let inp_spk =
829            finalizer::get_scriptpubkey(self, idx).map_err(|_e| SighashError::MissingInputUxto)?;
830        if inp_spk.is_v1_p2tr() {
831            let hash_ty = inp
832                .sighash_type
833                .map(|sighash_type| sighash_type.schnorr_hash_ty())
834                .unwrap_or(Ok(SchnorrSighashType::Default))
835                .map_err(|_e| SighashError::InvalidSighashType)?;
836            match tapleaf_hash {
837                Some(leaf_hash) => {
838                    let tap_sighash_msg = cache
839                        .taproot_script_spend_signature_hash(idx, &prevouts, leaf_hash, hash_ty)?;
840                    Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
841                }
842                None => {
843                    let tap_sighash_msg =
844                        cache.taproot_key_spend_signature_hash(idx, &prevouts, hash_ty)?;
845                    Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
846                }
847            }
848        } else {
849            let hash_ty = inp
850                .sighash_type
851                .map(|sighash_type| sighash_type.ecdsa_hash_ty())
852                .unwrap_or(Ok(EcdsaSighashType::All))
853                .map_err(|_e| SighashError::InvalidSighashType)?;
854            let amt = finalizer::get_utxo(self, idx)
855                .map_err(|_e| SighashError::MissingInputUxto)?
856                .value;
857            let is_nested_wpkh = inp_spk.is_p2sh()
858                && inp
859                    .redeem_script
860                    .as_ref()
861                    .map(|x| x.is_v0_p2wpkh())
862                    .unwrap_or(false);
863            let is_nested_wsh = inp_spk.is_p2sh()
864                && inp
865                    .redeem_script
866                    .as_ref()
867                    .map(|x| x.is_v0_p2wsh())
868                    .unwrap_or(false);
869            if inp_spk.is_v0_p2wpkh() || inp_spk.is_v0_p2wsh() || is_nested_wpkh || is_nested_wsh {
870                let msg = if inp_spk.is_v0_p2wpkh() {
871                    let script_code = script_code_wpkh(&inp_spk);
872                    cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
873                } else if is_nested_wpkh {
874                    let script_code = script_code_wpkh(
875                        inp.redeem_script
876                            .as_ref()
877                            .expect("Redeem script non-empty checked earlier"),
878                    );
879                    cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
880                } else {
881                    // wsh and nested wsh, script code is witness script
882                    let script_code = inp
883                        .witness_script
884                        .as_ref()
885                        .ok_or(SighashError::MissingWitnessScript)?;
886                    cache.segwit_signature_hash(idx, script_code, amt, hash_ty)?
887                };
888                Ok(PsbtSighashMsg::EcdsaSighash(msg))
889            } else {
890                // legacy sighash case
891                let script_code = if inp_spk.is_p2sh() {
892                    &inp.redeem_script
893                        .as_ref()
894                        .ok_or(SighashError::MissingRedeemScript)?
895                } else {
896                    inp_spk
897                };
898                let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.to_u32())?;
899                Ok(PsbtSighashMsg::EcdsaSighash(msg))
900            }
901        }
902    }
903}
904
905// Get a script from witness script pubkey hash
906fn script_code_wpkh(script: &Script) -> Script {
907    assert!(script.is_v0_p2wpkh());
908    // ugly segwit stuff
909    let mut script_code = vec![0x76u8, 0xa9, 0x14];
910    script_code.extend(&script.as_bytes()[2..]);
911    script_code.push(0x88);
912    script_code.push(0xac);
913    Script::from(script_code)
914}
915/// Return error type for [`PsbtExt::update_desc`]
916#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
917pub enum UxtoUpdateError {
918    /// Index out of bounds
919    IndexOutOfBounds(usize, usize),
920    /// Derivation error
921    DerivationError(descriptor::ConversionError),
922    /// Missing input utxo
923    MissingInputUxto,
924    /// Range not supplied for a wild-card descriptor
925    RangeMissingWildCardDescriptor,
926    /// Cannot derive output script pubkey using the given descriptor
927    IncorrectDescriptor,
928}
929
930impl fmt::Display for UxtoUpdateError {
931    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
932        match self {
933            UxtoUpdateError::IndexOutOfBounds(ind, len) => {
934                write!(f, "index {}, psbt input len: {}", ind, len)
935            }
936            UxtoUpdateError::DerivationError(e) => write!(f, "Key Derivation error {}", e),
937            UxtoUpdateError::MissingInputUxto => write!(f, "Missing input utxo in pbst"),
938            UxtoUpdateError::RangeMissingWildCardDescriptor => {
939                write!(
940                    f,
941                    "Range missing must be supplied for a wild-card descriptor"
942                )
943            }
944            UxtoUpdateError::IncorrectDescriptor => {
945                write!(
946                    f,
947                    "Cannot derive the output script pubkey using the given descriptor and range"
948                )
949            }
950        }
951    }
952}
953
954impl error::Error for UxtoUpdateError {}
955
956/// Return error type for [`PsbtExt::sighash_msg`]
957#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
958pub enum SighashError {
959    /// Index out of bounds
960    IndexOutOfBounds(usize, usize),
961    /// Missing input utxo
962    MissingInputUxto,
963    /// Missing Prevouts
964    MissingSpendUtxos,
965    /// Invalid Sighash type
966    InvalidSighashType,
967    /// Sighash computation error
968    /// Only happens when single does not have corresponding output as psbts
969    /// already have information to compute the sighash
970    SighashComputationError(bitcoin::util::sighash::Error),
971    /// Missing Witness script
972    MissingWitnessScript,
973    /// Missing Redeem script,
974    MissingRedeemScript,
975}
976
977impl fmt::Display for SighashError {
978    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
979        match self {
980            SighashError::IndexOutOfBounds(ind, len) => {
981                write!(f, "index {}, psbt input len: {}", ind, len)
982            }
983            SighashError::MissingInputUxto => write!(f, "Missing input utxo in pbst"),
984            SighashError::MissingSpendUtxos => write!(f, "Missing Psbt spend utxos"),
985            SighashError::InvalidSighashType => write!(f, "Invalid Sighash type"),
986            SighashError::SighashComputationError(e) => {
987                write!(f, "Sighash computation error : {}", e)
988            }
989            SighashError::MissingWitnessScript => write!(f, "Missing Witness Script"),
990            SighashError::MissingRedeemScript => write!(f, "Missing Redeem Script"),
991        }
992    }
993}
994
995impl From<bitcoin::util::sighash::Error> for SighashError {
996    fn from(e: bitcoin::util::sighash::Error) -> Self {
997        SighashError::SighashComputationError(e)
998    }
999}
1000
1001impl error::Error for SighashError {}
1002
1003/// Sighash message(signing data) for a given psbt transaction input.
1004#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1005pub enum PsbtSighashMsg {
1006    /// Taproot Signature hash
1007    TapSighash(taproot::TapSighashHash),
1008    /// Ecdsa Sighash message (includes sighash for legacy/p2sh/segwitv0 outputs)
1009    EcdsaSighash(bitcoin::Sighash),
1010}
1011
1012impl PsbtSighashMsg {
1013    /// Convert the message to a [`secp256k1::Message`].
1014    pub fn to_secp_msg(&self) -> secp256k1::Message {
1015        match *self {
1016            PsbtSighashMsg::TapSighash(msg) => {
1017                secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1018            }
1019            PsbtSighashMsg::EcdsaSighash(msg) => {
1020                secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1021            }
1022        }
1023    }
1024}
1025
1026#[cfg(test)]
1027mod tests {
1028    use super::*;
1029
1030    use bitcoin::consensus::encode::deserialize;
1031    use bitcoin::hashes::hex::FromHex;
1032
1033    #[test]
1034    fn test_extract_bip174() {
1035        let psbt: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::<u8>::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap();
1036        let secp = Secp256k1::verification_only();
1037        let tx = psbt.extract(&secp).unwrap();
1038        let expected: bitcoin::Transaction = deserialize(&Vec::<u8>::from_hex("0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000").unwrap()).unwrap();
1039        assert_eq!(tx, expected);
1040    }
1041}