miniscript_debug/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 core::convert::TryFrom;
23use core::fmt;
24use core::ops::Deref;
25#[cfg(feature = "std")]
26use std::error;
27
28use bitcoin::hashes::{hash160, sha256d, Hash};
29use bitcoin::secp256k1::{self, Secp256k1, VerifyOnly};
30use bitcoin::util::bip32;
31use bitcoin::util::psbt::{self, PartiallySignedTransaction as Psbt};
32use bitcoin::util::sighash::SighashCache;
33use bitcoin::util::taproot::{self, ControlBlock, LeafVersion, TapLeafHash};
34use bitcoin::{self, EcdsaSighashType, LockTime, SchnorrSighashType, Script, Sequence};
35
36use crate::miniscript::context::SigType;
37use crate::prelude::*;
38use crate::{
39    descriptor, interpreter, DefiniteDescriptorKey, Descriptor, DescriptorPublicKey, MiniscriptKey,
40    Preimage32, Satisfier, ToPublicKey, TranslatePk, Translator,
41};
42
43mod finalizer;
44
45#[allow(deprecated)]
46pub use self::finalizer::{finalize, finalize_mall, interpreter_check};
47
48/// Error type for entire Psbt
49#[derive(Debug)]
50pub enum Error {
51    /// Input Error type
52    InputError(InputError, usize),
53    /// Wrong Input Count
54    WrongInputCount {
55        /// Input count in tx
56        in_tx: usize,
57        /// Input count in psbt
58        in_map: usize,
59    },
60    /// Psbt Input index out of bounds
61    InputIdxOutofBounds {
62        /// Inputs in pbst
63        psbt_inp: usize,
64        /// requested index
65        index: usize,
66    },
67}
68
69impl fmt::Display for Error {
70    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71        match *self {
72            Error::InputError(ref inp_err, index) => write!(f, "{} at index {}", inp_err, index),
73            Error::WrongInputCount { in_tx, in_map } => write!(
74                f,
75                "PSBT had {} inputs in transaction but {} inputs in map",
76                in_tx, in_map
77            ),
78            Error::InputIdxOutofBounds { psbt_inp, index } => write!(
79                f,
80                "psbt input index {} out of bounds: psbt.inputs.len() {}",
81                index, psbt_inp
82            ),
83        }
84    }
85}
86
87#[cfg(feature = "std")]
88impl error::Error for Error {
89    fn cause(&self) -> Option<&dyn error::Error> {
90        use self::Error::*;
91
92        match self {
93            InputError(e, _) => Some(e),
94            WrongInputCount { .. } | InputIdxOutofBounds { .. } => None,
95        }
96    }
97}
98
99/// Error type for Pbst Input
100#[derive(Debug)]
101pub enum InputError {
102    /// Get the secp Errors directly
103    SecpErr(bitcoin::secp256k1::Error),
104    /// Key errors
105    KeyErr(bitcoin::util::key::Error),
106    /// Could not satisfy taproot descriptor
107    /// This error is returned when both script path and key paths could not be
108    /// satisfied. We cannot return a detailed error because we try all miniscripts
109    /// in script spend path, we cannot know which miniscript failed.
110    CouldNotSatisfyTr,
111    /// Error doing an interpreter-check on a finalized psbt
112    Interpreter(interpreter::Error),
113    /// Redeem script does not match the p2sh hash
114    InvalidRedeemScript {
115        /// Redeem script
116        redeem: Script,
117        /// Expected p2sh Script
118        p2sh_expected: Script,
119    },
120    /// Witness script does not match the p2wsh hash
121    InvalidWitnessScript {
122        /// Witness Script
123        witness_script: Script,
124        /// Expected p2wsh script
125        p2wsh_expected: Script,
126    },
127    /// Invalid sig
128    InvalidSignature {
129        /// The bitcoin public key
130        pubkey: bitcoin::PublicKey,
131        /// The (incorrect) signature
132        sig: Vec<u8>,
133    },
134    /// Pass through the underlying errors in miniscript
135    MiniscriptError(super::Error),
136    /// Missing redeem script for p2sh
137    MissingRedeemScript,
138    /// Missing witness
139    MissingWitness,
140    /// used for public key corresponding to pkh/wpkh
141    MissingPubkey,
142    /// Missing witness script for segwit descriptors
143    MissingWitnessScript,
144    ///Missing both the witness and non-witness utxo
145    MissingUtxo,
146    /// Non empty Witness script for p2sh
147    NonEmptyWitnessScript,
148    /// Non empty Redeem script
149    NonEmptyRedeemScript,
150    /// Non Standard sighash type
151    NonStandardSighashType(bitcoin::blockdata::transaction::NonStandardSighashType),
152    /// Sighash did not match
153    WrongSighashFlag {
154        /// required sighash type
155        required: bitcoin::EcdsaSighashType,
156        /// the sighash type we got
157        got: bitcoin::EcdsaSighashType,
158        /// the corresponding publickey
159        pubkey: bitcoin::PublicKey,
160    },
161}
162
163#[cfg(feature = "std")]
164impl error::Error for InputError {
165    fn cause(&self) -> Option<&dyn error::Error> {
166        use self::InputError::*;
167
168        match self {
169            CouldNotSatisfyTr
170            | InvalidRedeemScript { .. }
171            | InvalidWitnessScript { .. }
172            | InvalidSignature { .. }
173            | MissingRedeemScript
174            | MissingWitness
175            | MissingPubkey
176            | MissingWitnessScript
177            | MissingUtxo
178            | NonEmptyWitnessScript
179            | NonEmptyRedeemScript
180            | NonStandardSighashType(_)
181            | WrongSighashFlag { .. } => None,
182            SecpErr(e) => Some(e),
183            KeyErr(e) => Some(e),
184            Interpreter(e) => Some(e),
185            MiniscriptError(e) => Some(e),
186        }
187    }
188}
189
190impl fmt::Display for InputError {
191    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
192        match *self {
193            InputError::InvalidSignature {
194                ref pubkey,
195                ref sig,
196            } => write!(f, "PSBT: bad signature {} for key {:?}", pubkey, sig),
197            InputError::KeyErr(ref e) => write!(f, "Key Err: {}", e),
198            InputError::Interpreter(ref e) => write!(f, "Interpreter: {}", e),
199            InputError::SecpErr(ref e) => write!(f, "Secp Err: {}", e),
200            InputError::InvalidRedeemScript {
201                ref redeem,
202                ref p2sh_expected,
203            } => write!(
204                f,
205                "Redeem script {} does not match the p2sh script {}",
206                redeem, p2sh_expected
207            ),
208            InputError::InvalidWitnessScript {
209                ref witness_script,
210                ref p2wsh_expected,
211            } => write!(
212                f,
213                "Witness script {} does not match the p2wsh script {}",
214                witness_script, p2wsh_expected
215            ),
216            InputError::MiniscriptError(ref e) => write!(f, "Miniscript Error: {}", e),
217            InputError::MissingWitness => write!(f, "PSBT is missing witness"),
218            InputError::MissingRedeemScript => write!(f, "PSBT is Redeem script"),
219            InputError::MissingUtxo => {
220                write!(f, "PSBT is missing both witness and non-witness UTXO")
221            }
222            InputError::MissingWitnessScript => write!(f, "PSBT is missing witness script"),
223            InputError::MissingPubkey => write!(f, "Missing pubkey for a pkh/wpkh"),
224            InputError::NonEmptyRedeemScript => write!(
225                f,
226                "PSBT has non-empty redeem script at for legacy transactions"
227            ),
228            InputError::NonEmptyWitnessScript => {
229                write!(f, "PSBT has non-empty witness script at for legacy input")
230            }
231            InputError::WrongSighashFlag {
232                required,
233                got,
234                pubkey,
235            } => write!(
236                f,
237                "PSBT: signature with key {:?} had \
238                 sighashflag {:?} rather than required {:?}",
239                pubkey, got, required
240            ),
241            InputError::CouldNotSatisfyTr => write!(f, "Could not satisfy Tr descriptor"),
242            InputError::NonStandardSighashType(e) => write!(f, "Non-standard sighash type {}", e),
243        }
244    }
245}
246
247#[doc(hidden)]
248impl From<super::Error> for InputError {
249    fn from(e: super::Error) -> InputError {
250        InputError::MiniscriptError(e)
251    }
252}
253
254#[doc(hidden)]
255impl From<bitcoin::secp256k1::Error> for InputError {
256    fn from(e: bitcoin::secp256k1::Error) -> InputError {
257        InputError::SecpErr(e)
258    }
259}
260
261#[doc(hidden)]
262impl From<bitcoin::util::key::Error> for InputError {
263    fn from(e: bitcoin::util::key::Error) -> InputError {
264        InputError::KeyErr(e)
265    }
266}
267
268/// Psbt satisfier for at inputs at a particular index
269/// Takes in &psbt because multiple inputs will share
270/// the same psbt structure
271/// All operations on this structure will panic if index
272/// is more than number of inputs in pbst
273pub struct PsbtInputSatisfier<'psbt> {
274    /// pbst
275    pub psbt: &'psbt Psbt,
276    /// input index
277    pub index: usize,
278}
279
280impl<'psbt> PsbtInputSatisfier<'psbt> {
281    /// create a new PsbtInputsatisfier from
282    /// psbt and index
283    pub fn new(psbt: &'psbt Psbt, index: usize) -> Self {
284        Self { psbt, index }
285    }
286}
287
288impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfier<'psbt> {
289    fn lookup_tap_key_spend_sig(&self) -> Option<bitcoin::SchnorrSig> {
290        self.psbt.inputs[self.index].tap_key_sig
291    }
292
293    fn lookup_tap_leaf_script_sig(&self, pk: &Pk, lh: &TapLeafHash) -> Option<bitcoin::SchnorrSig> {
294        self.psbt.inputs[self.index]
295            .tap_script_sigs
296            .get(&(pk.to_x_only_pubkey(), *lh))
297            .copied()
298    }
299
300    fn lookup_raw_pkh_pk(&self, pkh: &hash160::Hash) -> Option<bitcoin::PublicKey> {
301        self.psbt.inputs[self.index]
302            .bip32_derivation
303            .iter()
304            .find(|&(pubkey, _)| pubkey.to_pubkeyhash(SigType::Ecdsa) == *pkh)
305            .map(|(pubkey, _)| bitcoin::PublicKey::new(*pubkey))
306    }
307
308    fn lookup_tap_control_block_map(
309        &self,
310    ) -> Option<&BTreeMap<ControlBlock, (bitcoin::Script, LeafVersion)>> {
311        Some(&self.psbt.inputs[self.index].tap_scripts)
312    }
313
314    fn lookup_raw_pkh_tap_leaf_script_sig(
315        &self,
316        pkh: &(hash160::Hash, TapLeafHash),
317    ) -> Option<(bitcoin::secp256k1::XOnlyPublicKey, bitcoin::SchnorrSig)> {
318        self.psbt.inputs[self.index]
319            .tap_script_sigs
320            .iter()
321            .find(|&((pubkey, lh), _sig)| {
322                pubkey.to_pubkeyhash(SigType::Schnorr) == pkh.0 && *lh == pkh.1
323            })
324            .map(|((x_only_pk, _leaf_hash), sig)| (*x_only_pk, *sig))
325    }
326
327    fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option<bitcoin::EcdsaSig> {
328        self.psbt.inputs[self.index]
329            .partial_sigs
330            .get(&pk.to_public_key())
331            .copied()
332    }
333
334    fn lookup_raw_pkh_ecdsa_sig(
335        &self,
336        pkh: &hash160::Hash,
337    ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> {
338        self.psbt.inputs[self.index]
339            .partial_sigs
340            .iter()
341            .find(|&(pubkey, _sig)| pubkey.to_pubkeyhash(SigType::Ecdsa) == *pkh)
342            .map(|(pk, sig)| (*pk, *sig))
343    }
344
345    fn check_after(&self, n: LockTime) -> bool {
346        if !self.psbt.unsigned_tx.input[self.index].enables_lock_time() {
347            return false;
348        }
349
350        let lock_time = LockTime::from(self.psbt.unsigned_tx.lock_time);
351
352        <dyn Satisfier<Pk>>::check_after(&lock_time, n)
353    }
354
355    fn check_older(&self, n: Sequence) -> bool {
356        let seq = self.psbt.unsigned_tx.input[self.index].sequence;
357
358        // https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
359        // Disable flag set => return true.
360        if !n.is_relative_lock_time() {
361            return true;
362        }
363
364        if self.psbt.unsigned_tx.version < 2 || !seq.is_relative_lock_time() {
365            return false;
366        }
367
368        <dyn Satisfier<Pk>>::check_older(&seq, n)
369    }
370
371    fn lookup_hash160(&self, h: &Pk::Hash160) -> Option<Preimage32> {
372        self.psbt.inputs[self.index]
373            .hash160_preimages
374            .get(&Pk::to_hash160(h))
375            .and_then(try_vec_as_preimage32)
376    }
377
378    fn lookup_sha256(&self, h: &Pk::Sha256) -> Option<Preimage32> {
379        self.psbt.inputs[self.index]
380            .sha256_preimages
381            .get(&Pk::to_sha256(h))
382            .and_then(try_vec_as_preimage32)
383    }
384
385    fn lookup_hash256(&self, h: &Pk::Hash256) -> Option<Preimage32> {
386        self.psbt.inputs[self.index]
387            .hash256_preimages
388            .get(&sha256d::Hash::from_inner(Pk::to_hash256(h).into_inner())) // upstream psbt operates on hash256
389            .and_then(try_vec_as_preimage32)
390    }
391
392    fn lookup_ripemd160(&self, h: &Pk::Ripemd160) -> Option<Preimage32> {
393        self.psbt.inputs[self.index]
394            .ripemd160_preimages
395            .get(&Pk::to_ripemd160(h))
396            .and_then(try_vec_as_preimage32)
397    }
398}
399
400fn try_vec_as_preimage32(vec: &Vec<u8>) -> Option<Preimage32> {
401    if vec.len() == 32 {
402        let mut arr = [0u8; 32];
403        arr.copy_from_slice(vec);
404        Some(arr)
405    } else {
406        None
407    }
408}
409
410// Basic sanity checks on psbts.
411// rust-bitcoin TODO: (Long term)
412// Brainstorm about how we can enforce these in type system while having a nice API
413fn sanity_check(psbt: &Psbt) -> Result<(), Error> {
414    if psbt.unsigned_tx.input.len() != psbt.inputs.len() {
415        return Err(Error::WrongInputCount {
416            in_tx: psbt.unsigned_tx.input.len(),
417            in_map: psbt.inputs.len(),
418        });
419    }
420
421    // Check well-formedness of input data
422    for (index, input) in psbt.inputs.iter().enumerate() {
423        // TODO: fix this after https://github.com/rust-bitcoin/rust-bitcoin/issues/838
424        let target_ecdsa_sighash_ty = match input.sighash_type {
425            Some(psbt_hash_ty) => psbt_hash_ty
426                .ecdsa_hash_ty()
427                .map_err(|e| Error::InputError(InputError::NonStandardSighashType(e), index))?,
428            None => EcdsaSighashType::All,
429        };
430        for (key, ecdsa_sig) in &input.partial_sigs {
431            let flag = bitcoin::EcdsaSighashType::from_standard(ecdsa_sig.hash_ty as u32).map_err(
432                |_| {
433                    Error::InputError(
434                        InputError::Interpreter(interpreter::Error::NonStandardSighash(
435                            ecdsa_sig.to_vec(),
436                        )),
437                        index,
438                    )
439                },
440            )?;
441            if target_ecdsa_sighash_ty != flag {
442                return Err(Error::InputError(
443                    InputError::WrongSighashFlag {
444                        required: target_ecdsa_sighash_ty,
445                        got: flag,
446                        pubkey: *key,
447                    },
448                    index,
449                ));
450            }
451            // Signatures are well-formed in psbt partial sigs
452        }
453    }
454
455    Ok(())
456}
457
458/// Additional operations for miniscript descriptors for various psbt roles.
459/// Note that these APIs would generally error when used on scripts that are not
460/// miniscripts.
461pub trait PsbtExt {
462    /// Finalize the psbt. This function takes in a mutable reference to psbt
463    /// and populates the final_witness and final_scriptsig
464    /// for all miniscript inputs.
465    ///
466    /// Finalizes all inputs that it can finalize, and returns an error for each input
467    /// that it cannot finalize. Also performs a sanity interpreter check on the
468    /// finalized psbt which involves checking the signatures/ preimages/timelocks.
469    ///
470    /// Input finalization also fails if it is not possible to satisfy any of the inputs non-malleably
471    /// See [finalizer::finalize_mall] if you want to allow malleable satisfactions
472    ///
473    /// For finalizing individual inputs, see also [`PsbtExt::finalize_inp`]
474    ///
475    /// # Errors:
476    ///
477    /// - A vector of errors, one of each of failed finalized input
478    fn finalize_mut<C: secp256k1::Verification>(
479        &mut self,
480        secp: &secp256k1::Secp256k1<C>,
481    ) -> Result<(), Vec<Error>>;
482
483    /// Same as [`PsbtExt::finalize_mut`], but does not mutate the input psbt and
484    /// returns a new psbt
485    ///
486    /// # Errors:
487    ///
488    /// - Returns a mutated psbt with all inputs `finalize_mut` could finalize
489    /// - A vector of input errors, one of each of failed finalized input
490    fn finalize<C: secp256k1::Verification>(
491        self,
492        secp: &secp256k1::Secp256k1<C>,
493    ) -> Result<Psbt, (Psbt, Vec<Error>)>;
494
495    /// Same as [PsbtExt::finalize_mut], but allows for malleable satisfactions
496    fn finalize_mall_mut<C: secp256k1::Verification>(
497        &mut self,
498        secp: &Secp256k1<C>,
499    ) -> Result<(), Vec<Error>>;
500
501    /// Same as [PsbtExt::finalize], but allows for malleable satisfactions
502    fn finalize_mall<C: secp256k1::Verification>(
503        self,
504        secp: &Secp256k1<C>,
505    ) -> Result<Psbt, (Psbt, Vec<Error>)>;
506
507    /// Same as [`PsbtExt::finalize_mut`], but only tries to finalize a single input leaving other
508    /// inputs as is. Use this when not all of inputs that you are trying to
509    /// satisfy are miniscripts
510    ///
511    /// # Errors:
512    ///
513    /// - Input error detailing why the finalization failed. The psbt is not mutated when the finalization fails
514    fn finalize_inp_mut<C: secp256k1::Verification>(
515        &mut self,
516        secp: &secp256k1::Secp256k1<C>,
517        index: usize,
518    ) -> Result<(), Error>;
519
520    /// Same as [`PsbtExt::finalize_inp_mut`], but does not mutate the psbt and returns a new one
521    ///
522    /// # Errors:
523    ///  Returns a tuple containing
524    /// - Original psbt
525    /// - Input Error detailing why the input finalization failed
526    fn finalize_inp<C: secp256k1::Verification>(
527        self,
528        secp: &secp256k1::Secp256k1<C>,
529        index: usize,
530    ) -> Result<Psbt, (Psbt, Error)>;
531
532    /// Same as [`PsbtExt::finalize_inp_mut`], but allows for malleable satisfactions
533    fn finalize_inp_mall_mut<C: secp256k1::Verification>(
534        &mut self,
535        secp: &secp256k1::Secp256k1<C>,
536        index: usize,
537    ) -> Result<(), Error>;
538
539    /// Same as [`PsbtExt::finalize_inp`], but allows for malleable satisfactions
540    fn finalize_inp_mall<C: secp256k1::Verification>(
541        self,
542        secp: &secp256k1::Secp256k1<C>,
543        index: usize,
544    ) -> Result<Psbt, (Psbt, Error)>;
545
546    /// Psbt extractor as defined in BIP174 that takes in a psbt reference
547    /// and outputs a extracted bitcoin::Transaction
548    /// Also does the interpreter sanity check
549    /// Will error if the final ScriptSig or final Witness are missing
550    /// or the interpreter check fails.
551    fn extract<C: secp256k1::Verification>(
552        &self,
553        secp: &Secp256k1<C>,
554    ) -> Result<bitcoin::Transaction, Error>;
555
556    /// Update PSBT input with a descriptor and check consistency of `*_utxo` fields.
557    ///
558    /// This is the checked version of [`update_with_descriptor_unchecked`]. It checks that the
559    /// `witness_utxo` and `non_witness_utxo` are sane and have a `script_pubkey` that matches the
560    /// descriptor. In particular, it makes sure pre-segwit descriptors always have `non_witness_utxo`
561    /// present (and the txid matches). If both `witness_utxo` and `non_witness_utxo` are present
562    /// then it also checks they are consistent with each other.
563    ///
564    /// Hint: because of the *[segwit bug]* some PSBT signers require that `non_witness_utxo` is
565    /// present on segwitv0 inputs regardless but this function doesn't enforce this so you will
566    /// have to do this check its presence manually (if it is present this *will* check its
567    /// validity).
568    ///
569    /// The `descriptor` **must not have any wildcards** in it
570    /// otherwise an error will be returned however it can (and should) have extended keys in it.
571    ///
572    /// [`update_with_descriptor_unchecked`]: PsbtInputExt::update_with_descriptor_unchecked
573    /// [segwit bug]: https://bitcoinhackers.org/@lukedashjr/104287698361196952
574    fn update_input_with_descriptor(
575        &mut self,
576        input_index: usize,
577        descriptor: &Descriptor<DefiniteDescriptorKey>,
578    ) -> Result<(), UtxoUpdateError>;
579
580    /// Update PSBT output with a descriptor and check consistency of the output's `script_pubkey`
581    ///
582    /// This is the checked version of [`update_with_descriptor_unchecked`]. It checks that the
583    /// output's `script_pubkey` matches the descriptor.
584    ///
585    /// The `descriptor` **must not have any wildcards** in it
586    /// otherwise an error will be returned however it can (and should) have extended keys in it.
587    ///
588    /// [`update_with_descriptor_unchecked`]: PsbtOutputExt::update_with_descriptor_unchecked
589    fn update_output_with_descriptor(
590        &mut self,
591        output_index: usize,
592        descriptor: &Descriptor<DefiniteDescriptorKey>,
593    ) -> Result<(), OutputUpdateError>;
594
595    /// Get the sighash message(data to sign) at input index `idx` based on the sighash
596    /// flag specified in the [`Psbt`] sighash field. If the input sighash flag psbt field is `None`
597    /// the [`SchnorrSighashType::Default`](bitcoin::util::sighash::SchnorrSighashType::Default) is chosen
598    /// for for taproot spends, otherwise [`EcdsaSignatureHashType::All`](bitcoin::EcdsaSighashType::All) is chosen.
599    /// If the utxo at `idx` is a taproot output, returns a [`PsbtSighashMsg::TapSighash`] variant.
600    /// If the utxo at `idx` is a pre-taproot output, returns a [`PsbtSighashMsg::EcdsaSighash`] variant.
601    /// The `tapleaf_hash` parameter can be used to specify which tapleaf script hash has to be computed. If
602    /// `tapleaf_hash` is [`None`], and the output is taproot output, the key spend hash is computed. This parameter must be
603    /// set to [`None`] while computing sighash for pre-taproot outputs.
604    /// The function also updates the sighash cache with transaction computed during sighash computation of this input
605    ///
606    /// # Arguments:
607    ///
608    /// * `idx`: The input index of psbt to sign
609    /// * `cache`: The [`SighashCache`] for used to cache/read previously cached computations
610    /// * `tapleaf_hash`: If the output is taproot, compute the sighash for this particular leaf.
611    ///
612    /// [`SighashCache`]: bitcoin::util::sighash::SighashCache
613    fn sighash_msg<T: Deref<Target = bitcoin::Transaction>>(
614        &self,
615        idx: usize,
616        cache: &mut SighashCache<T>,
617        tapleaf_hash: Option<TapLeafHash>,
618    ) -> Result<PsbtSighashMsg, SighashError>;
619}
620
621impl PsbtExt for Psbt {
622    fn finalize_mut<C: secp256k1::Verification>(
623        &mut self,
624        secp: &secp256k1::Secp256k1<C>,
625    ) -> Result<(), Vec<Error>> {
626        // Actually construct the witnesses
627        let mut errors = vec![];
628        for index in 0..self.inputs.len() {
629            match finalizer::finalize_input(self, index, secp, /*allow_mall*/ false) {
630                Ok(..) => {}
631                Err(e) => {
632                    errors.push(e);
633                }
634            }
635        }
636        if errors.is_empty() {
637            Ok(())
638        } else {
639            Err(errors)
640        }
641    }
642
643    fn finalize<C: secp256k1::Verification>(
644        mut self,
645        secp: &secp256k1::Secp256k1<C>,
646    ) -> Result<Psbt, (Psbt, Vec<Error>)> {
647        match self.finalize_mut(secp) {
648            Ok(..) => Ok(self),
649            Err(e) => Err((self, e)),
650        }
651    }
652
653    fn finalize_mall_mut<C: secp256k1::Verification>(
654        &mut self,
655        secp: &secp256k1::Secp256k1<C>,
656    ) -> Result<(), Vec<Error>> {
657        let mut errors = vec![];
658        for index in 0..self.inputs.len() {
659            match finalizer::finalize_input(self, index, secp, /*allow_mall*/ true) {
660                Ok(..) => {}
661                Err(e) => {
662                    errors.push(e);
663                }
664            }
665        }
666        if errors.is_empty() {
667            Ok(())
668        } else {
669            Err(errors)
670        }
671    }
672
673    fn finalize_mall<C: secp256k1::Verification>(
674        mut self,
675        secp: &Secp256k1<C>,
676    ) -> Result<Psbt, (Psbt, Vec<Error>)> {
677        match self.finalize_mall_mut(secp) {
678            Ok(..) => Ok(self),
679            Err(e) => Err((self, e)),
680        }
681    }
682
683    fn finalize_inp_mut<C: secp256k1::Verification>(
684        &mut self,
685        secp: &secp256k1::Secp256k1<C>,
686        index: usize,
687    ) -> Result<(), Error> {
688        if index >= self.inputs.len() {
689            return Err(Error::InputIdxOutofBounds {
690                psbt_inp: self.inputs.len(),
691                index,
692            });
693        }
694        finalizer::finalize_input(self, index, secp, /*allow_mall*/ false)
695    }
696
697    fn finalize_inp<C: secp256k1::Verification>(
698        mut self,
699        secp: &secp256k1::Secp256k1<C>,
700        index: usize,
701    ) -> Result<Psbt, (Psbt, Error)> {
702        match self.finalize_inp_mut(secp, index) {
703            Ok(..) => Ok(self),
704            Err(e) => Err((self, e)),
705        }
706    }
707
708    fn finalize_inp_mall_mut<C: secp256k1::Verification>(
709        &mut self,
710        secp: &secp256k1::Secp256k1<C>,
711        index: usize,
712    ) -> Result<(), Error> {
713        if index >= self.inputs.len() {
714            return Err(Error::InputIdxOutofBounds {
715                psbt_inp: self.inputs.len(),
716                index,
717            });
718        }
719        finalizer::finalize_input(self, index, secp, /*allow_mall*/ false)
720    }
721
722    fn finalize_inp_mall<C: secp256k1::Verification>(
723        mut self,
724        secp: &secp256k1::Secp256k1<C>,
725        index: usize,
726    ) -> Result<Psbt, (Psbt, Error)> {
727        match self.finalize_inp_mall_mut(secp, index) {
728            Ok(..) => Ok(self),
729            Err(e) => Err((self, e)),
730        }
731    }
732
733    fn extract<C: secp256k1::Verification>(
734        &self,
735        secp: &Secp256k1<C>,
736    ) -> Result<bitcoin::Transaction, Error> {
737        sanity_check(self)?;
738
739        let mut ret = self.unsigned_tx.clone();
740        for (n, input) in self.inputs.iter().enumerate() {
741            if input.final_script_sig.is_none() && input.final_script_witness.is_none() {
742                return Err(Error::InputError(InputError::MissingWitness, n));
743            }
744
745            if let Some(witness) = input.final_script_witness.as_ref() {
746                ret.input[n].witness = witness.clone();
747            }
748            if let Some(script_sig) = input.final_script_sig.as_ref() {
749                ret.input[n].script_sig = script_sig.clone();
750            }
751        }
752        interpreter_check(self, secp)?;
753        Ok(ret)
754    }
755
756    fn update_input_with_descriptor(
757        &mut self,
758        input_index: usize,
759        desc: &Descriptor<DefiniteDescriptorKey>,
760    ) -> Result<(), UtxoUpdateError> {
761        let n_inputs = self.inputs.len();
762        let input = self
763            .inputs
764            .get_mut(input_index)
765            .ok_or(UtxoUpdateError::IndexOutOfBounds(input_index, n_inputs))?;
766        let txin = self
767            .unsigned_tx
768            .input
769            .get(input_index)
770            .ok_or(UtxoUpdateError::MissingInputUtxo)?;
771
772        let desc_type = desc.desc_type();
773
774        if let Some(non_witness_utxo) = &input.non_witness_utxo {
775            if txin.previous_output.txid != non_witness_utxo.txid() {
776                return Err(UtxoUpdateError::UtxoCheck);
777            }
778        }
779
780        let expected_spk = {
781            match (&input.witness_utxo, &input.non_witness_utxo) {
782                (Some(witness_utxo), None) => {
783                    if desc_type.segwit_version().is_some() {
784                        witness_utxo.script_pubkey.clone()
785                    } else {
786                        return Err(UtxoUpdateError::UtxoCheck);
787                    }
788                }
789                (None, Some(non_witness_utxo)) => non_witness_utxo
790                    .output
791                    .get(txin.previous_output.vout as usize)
792                    .ok_or(UtxoUpdateError::UtxoCheck)?
793                    .script_pubkey
794                    .clone(),
795                (Some(witness_utxo), Some(non_witness_utxo)) => {
796                    if witness_utxo
797                        != non_witness_utxo
798                            .output
799                            .get(txin.previous_output.vout as usize)
800                            .ok_or(UtxoUpdateError::UtxoCheck)?
801                    {
802                        return Err(UtxoUpdateError::UtxoCheck);
803                    }
804
805                    witness_utxo.script_pubkey.clone()
806                }
807                (None, None) => return Err(UtxoUpdateError::UtxoCheck),
808            }
809        };
810
811        let (_, spk_check_passed) =
812            update_item_with_descriptor_helper(input, desc, Some(&expected_spk))
813                .map_err(UtxoUpdateError::DerivationError)?;
814
815        if !spk_check_passed {
816            return Err(UtxoUpdateError::MismatchedScriptPubkey);
817        }
818
819        Ok(())
820    }
821
822    fn update_output_with_descriptor(
823        &mut self,
824        output_index: usize,
825        desc: &Descriptor<DefiniteDescriptorKey>,
826    ) -> Result<(), OutputUpdateError> {
827        let n_outputs = self.outputs.len();
828        let output = self
829            .outputs
830            .get_mut(output_index)
831            .ok_or(OutputUpdateError::IndexOutOfBounds(output_index, n_outputs))?;
832        let txout = self
833            .unsigned_tx
834            .output
835            .get(output_index)
836            .ok_or(OutputUpdateError::MissingTxOut)?;
837
838        let (_, spk_check_passed) =
839            update_item_with_descriptor_helper(output, desc, Some(&txout.script_pubkey))
840                .map_err(OutputUpdateError::DerivationError)?;
841
842        if !spk_check_passed {
843            return Err(OutputUpdateError::MismatchedScriptPubkey);
844        }
845
846        Ok(())
847    }
848
849    fn sighash_msg<T: Deref<Target = bitcoin::Transaction>>(
850        &self,
851        idx: usize,
852        cache: &mut SighashCache<T>,
853        tapleaf_hash: Option<TapLeafHash>,
854    ) -> Result<PsbtSighashMsg, SighashError> {
855        // Infer a descriptor at idx
856        if idx >= self.inputs.len() {
857            return Err(SighashError::IndexOutOfBounds(idx, self.inputs.len()));
858        }
859        let inp = &self.inputs[idx];
860        let prevouts = finalizer::prevouts(self).map_err(|_e| SighashError::MissingSpendUtxos)?;
861        // Note that as per Psbt spec we should have access to spent_utxos for the transaction
862        // Even if the transaction does not require SighashAll, we create `Prevouts::All` for code simplicity
863        let prevouts = bitcoin::util::sighash::Prevouts::All(&prevouts);
864        let inp_spk =
865            finalizer::get_scriptpubkey(self, idx).map_err(|_e| SighashError::MissingInputUtxo)?;
866        if inp_spk.is_v1_p2tr() {
867            let hash_ty = inp
868                .sighash_type
869                .map(|sighash_type| sighash_type.schnorr_hash_ty())
870                .unwrap_or(Ok(SchnorrSighashType::Default))
871                .map_err(|_e| SighashError::InvalidSighashType)?;
872            match tapleaf_hash {
873                Some(leaf_hash) => {
874                    let tap_sighash_msg = cache
875                        .taproot_script_spend_signature_hash(idx, &prevouts, leaf_hash, hash_ty)?;
876                    Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
877                }
878                None => {
879                    let tap_sighash_msg =
880                        cache.taproot_key_spend_signature_hash(idx, &prevouts, hash_ty)?;
881                    Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
882                }
883            }
884        } else {
885            let hash_ty = inp
886                .sighash_type
887                .map(|sighash_type| sighash_type.ecdsa_hash_ty())
888                .unwrap_or(Ok(EcdsaSighashType::All))
889                .map_err(|_e| SighashError::InvalidSighashType)?;
890            let amt = finalizer::get_utxo(self, idx)
891                .map_err(|_e| SighashError::MissingInputUtxo)?
892                .value;
893            let is_nested_wpkh = inp_spk.is_p2sh()
894                && inp
895                    .redeem_script
896                    .as_ref()
897                    .map(|x| x.is_v0_p2wpkh())
898                    .unwrap_or(false);
899            let is_nested_wsh = inp_spk.is_p2sh()
900                && inp
901                    .redeem_script
902                    .as_ref()
903                    .map(|x| x.is_v0_p2wsh())
904                    .unwrap_or(false);
905            if inp_spk.is_v0_p2wpkh() || inp_spk.is_v0_p2wsh() || is_nested_wpkh || is_nested_wsh {
906                let msg = if inp_spk.is_v0_p2wpkh() {
907                    let script_code = script_code_wpkh(inp_spk);
908                    cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
909                } else if is_nested_wpkh {
910                    let script_code = script_code_wpkh(
911                        inp.redeem_script
912                            .as_ref()
913                            .expect("Redeem script non-empty checked earlier"),
914                    );
915                    cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
916                } else {
917                    // wsh and nested wsh, script code is witness script
918                    let script_code = inp
919                        .witness_script
920                        .as_ref()
921                        .ok_or(SighashError::MissingWitnessScript)?;
922                    cache.segwit_signature_hash(idx, script_code, amt, hash_ty)?
923                };
924                Ok(PsbtSighashMsg::EcdsaSighash(msg))
925            } else {
926                // legacy sighash case
927                let script_code = if inp_spk.is_p2sh() {
928                    inp.redeem_script
929                        .as_ref()
930                        .ok_or(SighashError::MissingRedeemScript)?
931                } else {
932                    inp_spk
933                };
934                let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.to_u32())?;
935                Ok(PsbtSighashMsg::EcdsaSighash(msg))
936            }
937        }
938    }
939}
940
941/// Extension trait for PSBT inputs
942pub trait PsbtInputExt {
943    /// Given the descriptor for a utxo being spent populate the PSBT input's fields so it can be signed.
944    ///
945    /// If the descriptor contains wildcards or otherwise cannot be transformed into a concrete
946    /// descriptor an error will be returned. The descriptor *can* (and should) have extended keys in
947    /// it so PSBT fields like `bip32_derivation` and `tap_key_origins` can be populated.
948    ///
949    /// Note that his method doesn't check that the `witness_utxo` or `non_witness_utxo` is
950    /// consistent with the descriptor. To do that see [`update_input_with_descriptor`].
951    ///
952    /// ## Return value
953    ///
954    /// For convenience, this returns the concrete descriptor that is computed internally to fill
955    /// out the PSBT input fields. This can be used to manually check that the `script_pubkey` in
956    /// `witness_utxo` and/or `non_witness_utxo` is consistent with the descriptor.
957    ///
958    /// [`update_input_with_descriptor`]: PsbtExt::update_input_with_descriptor
959    fn update_with_descriptor_unchecked(
960        &mut self,
961        descriptor: &Descriptor<DefiniteDescriptorKey>,
962    ) -> Result<Descriptor<bitcoin::PublicKey>, descriptor::ConversionError>;
963}
964
965impl PsbtInputExt for psbt::Input {
966    fn update_with_descriptor_unchecked(
967        &mut self,
968        descriptor: &Descriptor<DefiniteDescriptorKey>,
969    ) -> Result<Descriptor<bitcoin::PublicKey>, descriptor::ConversionError> {
970        let (derived, _) = update_item_with_descriptor_helper(self, descriptor, None)?;
971        Ok(derived)
972    }
973}
974
975/// Extension trait for PSBT outputs
976pub trait PsbtOutputExt {
977    /// Given the descriptor of a PSBT output populate the relevant metadata
978    ///
979    /// If the descriptor contains wildcards or otherwise cannot be transformed into a concrete
980    /// descriptor an error will be returned. The descriptor *can* (and should) have extended keys in
981    /// it so PSBT fields like `bip32_derivation` and `tap_key_origins` can be populated.
982    ///
983    /// Note that this method doesn't check that the `script_pubkey` of the output being
984    /// updated matches the descriptor. To do that see [`update_output_with_descriptor`].
985    ///
986    /// ## Return value
987    ///
988    /// For convenience, this returns the concrete descriptor that is computed internally to fill
989    /// out the PSBT output fields. This can be used to manually check that the `script_pubkey` is
990    /// consistent with the descriptor.
991    ///
992    /// [`update_output_with_descriptor`]: PsbtExt::update_output_with_descriptor
993    fn update_with_descriptor_unchecked(
994        &mut self,
995        descriptor: &Descriptor<DefiniteDescriptorKey>,
996    ) -> Result<Descriptor<bitcoin::PublicKey>, descriptor::ConversionError>;
997}
998
999impl PsbtOutputExt for psbt::Output {
1000    fn update_with_descriptor_unchecked(
1001        &mut self,
1002        descriptor: &Descriptor<DefiniteDescriptorKey>,
1003    ) -> Result<Descriptor<bitcoin::PublicKey>, descriptor::ConversionError> {
1004        let (derived, _) = update_item_with_descriptor_helper(self, descriptor, None)?;
1005        Ok(derived)
1006    }
1007}
1008
1009// Traverse the pkh lookup while maintaining a reverse map for storing the map
1010// hash160 -> (XonlyPublicKey)/PublicKey
1011struct KeySourceLookUp(
1012    pub BTreeMap<secp256k1::PublicKey, bip32::KeySource>,
1013    pub secp256k1::Secp256k1<VerifyOnly>,
1014);
1015
1016impl Translator<DefiniteDescriptorKey, bitcoin::PublicKey, descriptor::ConversionError>
1017    for KeySourceLookUp
1018{
1019    fn pk(
1020        &mut self,
1021        xpk: &DefiniteDescriptorKey,
1022    ) -> Result<bitcoin::PublicKey, descriptor::ConversionError> {
1023        let derived = xpk.derive_public_key(&self.1)?;
1024        self.0.insert(
1025            derived.to_public_key().inner,
1026            (xpk.master_fingerprint(), xpk.full_derivation_path()),
1027        );
1028        Ok(derived)
1029    }
1030
1031    translate_hash_clone!(
1032        DescriptorPublicKey,
1033        bitcoin::PublicKey,
1034        descriptor::ConversionError
1035    );
1036}
1037
1038// Provides generalized access to PSBT fields common to inputs and outputs
1039trait PsbtFields {
1040    // Common fields are returned as a mutable ref of the same type
1041    fn redeem_script(&mut self) -> &mut Option<Script>;
1042    fn witness_script(&mut self) -> &mut Option<Script>;
1043    fn bip32_derivation(&mut self) -> &mut BTreeMap<secp256k1::PublicKey, bip32::KeySource>;
1044    fn tap_internal_key(&mut self) -> &mut Option<bitcoin::XOnlyPublicKey>;
1045    fn tap_key_origins(
1046        &mut self,
1047    ) -> &mut BTreeMap<bitcoin::XOnlyPublicKey, (Vec<TapLeafHash>, bip32::KeySource)>;
1048    fn proprietary(&mut self) -> &mut BTreeMap<psbt::raw::ProprietaryKey, Vec<u8>>;
1049    fn unknown(&mut self) -> &mut BTreeMap<psbt::raw::Key, Vec<u8>>;
1050
1051    // `tap_tree` only appears in psbt::Output, so it's returned as an option of a mutable ref
1052    fn tap_tree(&mut self) -> Option<&mut Option<psbt::TapTree>> {
1053        None
1054    }
1055
1056    // `tap_scripts` and `tap_merkle_root` only appear in psbt::Input
1057    fn tap_scripts(&mut self) -> Option<&mut BTreeMap<ControlBlock, (Script, LeafVersion)>> {
1058        None
1059    }
1060    fn tap_merkle_root(&mut self) -> Option<&mut Option<taproot::TapBranchHash>> {
1061        None
1062    }
1063}
1064
1065impl PsbtFields for psbt::Input {
1066    fn redeem_script(&mut self) -> &mut Option<Script> {
1067        &mut self.redeem_script
1068    }
1069    fn witness_script(&mut self) -> &mut Option<Script> {
1070        &mut self.witness_script
1071    }
1072    fn bip32_derivation(&mut self) -> &mut BTreeMap<secp256k1::PublicKey, bip32::KeySource> {
1073        &mut self.bip32_derivation
1074    }
1075    fn tap_internal_key(&mut self) -> &mut Option<bitcoin::XOnlyPublicKey> {
1076        &mut self.tap_internal_key
1077    }
1078    fn tap_key_origins(
1079        &mut self,
1080    ) -> &mut BTreeMap<bitcoin::XOnlyPublicKey, (Vec<TapLeafHash>, bip32::KeySource)> {
1081        &mut self.tap_key_origins
1082    }
1083    fn proprietary(&mut self) -> &mut BTreeMap<psbt::raw::ProprietaryKey, Vec<u8>> {
1084        &mut self.proprietary
1085    }
1086    fn unknown(&mut self) -> &mut BTreeMap<psbt::raw::Key, Vec<u8>> {
1087        &mut self.unknown
1088    }
1089
1090    fn tap_scripts(&mut self) -> Option<&mut BTreeMap<ControlBlock, (Script, LeafVersion)>> {
1091        Some(&mut self.tap_scripts)
1092    }
1093    fn tap_merkle_root(&mut self) -> Option<&mut Option<taproot::TapBranchHash>> {
1094        Some(&mut self.tap_merkle_root)
1095    }
1096}
1097
1098impl PsbtFields for psbt::Output {
1099    fn redeem_script(&mut self) -> &mut Option<Script> {
1100        &mut self.redeem_script
1101    }
1102    fn witness_script(&mut self) -> &mut Option<Script> {
1103        &mut self.witness_script
1104    }
1105    fn bip32_derivation(&mut self) -> &mut BTreeMap<secp256k1::PublicKey, bip32::KeySource> {
1106        &mut self.bip32_derivation
1107    }
1108    fn tap_internal_key(&mut self) -> &mut Option<bitcoin::XOnlyPublicKey> {
1109        &mut self.tap_internal_key
1110    }
1111    fn tap_key_origins(
1112        &mut self,
1113    ) -> &mut BTreeMap<bitcoin::XOnlyPublicKey, (Vec<TapLeafHash>, bip32::KeySource)> {
1114        &mut self.tap_key_origins
1115    }
1116    fn proprietary(&mut self) -> &mut BTreeMap<psbt::raw::ProprietaryKey, Vec<u8>> {
1117        &mut self.proprietary
1118    }
1119    fn unknown(&mut self) -> &mut BTreeMap<psbt::raw::Key, Vec<u8>> {
1120        &mut self.unknown
1121    }
1122
1123    fn tap_tree(&mut self) -> Option<&mut Option<psbt::TapTree>> {
1124        Some(&mut self.tap_tree)
1125    }
1126}
1127
1128fn update_item_with_descriptor_helper<F: PsbtFields>(
1129    item: &mut F,
1130    descriptor: &Descriptor<DefiniteDescriptorKey>,
1131    check_script: Option<&Script>,
1132    // the return value is a tuple here since the two internal calls to it require different info.
1133    // One needs the derived descriptor and the other needs to know whether the script_pubkey check
1134    // failed.
1135) -> Result<(Descriptor<bitcoin::PublicKey>, bool), descriptor::ConversionError> {
1136    let secp = secp256k1::Secp256k1::verification_only();
1137
1138    let derived = if let Descriptor::Tr(_) = &descriptor {
1139        let derived = descriptor.derived_descriptor(&secp)?;
1140
1141        if let Some(check_script) = check_script {
1142            if check_script != &derived.script_pubkey() {
1143                return Ok((derived, false));
1144            }
1145        }
1146
1147        // NOTE: they will both always be Tr
1148        if let (Descriptor::Tr(tr_derived), Descriptor::Tr(tr_xpk)) = (&derived, descriptor) {
1149            let spend_info = tr_derived.spend_info();
1150            let ik_derived = spend_info.internal_key();
1151            let ik_xpk = tr_xpk.internal_key();
1152            if let Some(merkle_root) = item.tap_merkle_root() {
1153                *merkle_root = spend_info.merkle_root();
1154            }
1155            *item.tap_internal_key() = Some(ik_derived);
1156            item.tap_key_origins().insert(
1157                ik_derived,
1158                (
1159                    vec![],
1160                    (ik_xpk.master_fingerprint(), ik_xpk.full_derivation_path()),
1161                ),
1162            );
1163
1164            let mut builder = taproot::TaprootBuilder::new();
1165
1166            for ((_depth_der, ms_derived), (depth, ms)) in
1167                tr_derived.iter_scripts().zip(tr_xpk.iter_scripts())
1168            {
1169                debug_assert_eq!(_depth_der, depth);
1170                let leaf_script = (ms_derived.encode(), LeafVersion::TapScript);
1171                let tapleaf_hash = TapLeafHash::from_script(&leaf_script.0, leaf_script.1);
1172                builder = builder
1173                    .add_leaf(depth, leaf_script.0.clone())
1174                    .expect("Computing spend data on a valid tree should always succeed");
1175                if let Some(tap_scripts) = item.tap_scripts() {
1176                    let control_block = spend_info
1177                        .control_block(&leaf_script)
1178                        .expect("Control block must exist in script map for every known leaf");
1179                    tap_scripts.insert(control_block, leaf_script);
1180                }
1181
1182                for (pk_pkh_derived, pk_pkh_xpk) in ms_derived.iter_pk().zip(ms.iter_pk()) {
1183                    let (xonly, xpk) = (pk_pkh_derived.to_x_only_pubkey(), pk_pkh_xpk);
1184
1185                    item.tap_key_origins()
1186                        .entry(xonly)
1187                        .and_modify(|(tapleaf_hashes, _)| {
1188                            if tapleaf_hashes.last() != Some(&tapleaf_hash) {
1189                                tapleaf_hashes.push(tapleaf_hash);
1190                            }
1191                        })
1192                        .or_insert_with(|| {
1193                            (
1194                                vec![tapleaf_hash],
1195                                (xpk.master_fingerprint(), xpk.full_derivation_path()),
1196                            )
1197                        });
1198                }
1199            }
1200
1201            // Ensure there are no duplicated leaf hashes. This can happen if some of them were
1202            // already present in the map when this function is called, since this only appends new
1203            // data to the psbt without checking what's already present.
1204            for (tapleaf_hashes, _) in item.tap_key_origins().values_mut() {
1205                tapleaf_hashes.sort();
1206                tapleaf_hashes.dedup();
1207            }
1208
1209            match item.tap_tree() {
1210                // Only set the tap_tree if the item supports it (it's an output) and the descriptor actually
1211                // contains one, otherwise it'll just be empty
1212                Some(tap_tree) if tr_derived.taptree().is_some() => {
1213                    *tap_tree = Some(
1214                        psbt::TapTree::try_from(builder).expect("The tree should always be valid"),
1215                    );
1216                }
1217                _ => {}
1218            }
1219        }
1220
1221        derived
1222    } else {
1223        let mut bip32_derivation = KeySourceLookUp(BTreeMap::new(), Secp256k1::verification_only());
1224        let derived = descriptor.translate_pk(&mut bip32_derivation)?;
1225
1226        if let Some(check_script) = check_script {
1227            if check_script != &derived.script_pubkey() {
1228                return Ok((derived, false));
1229            }
1230        }
1231
1232        item.bip32_derivation().append(&mut bip32_derivation.0);
1233
1234        match &derived {
1235            Descriptor::Bare(_) | Descriptor::Pkh(_) | Descriptor::Wpkh(_) => {}
1236            Descriptor::Sh(sh) => match sh.as_inner() {
1237                descriptor::ShInner::Wsh(wsh) => {
1238                    *item.witness_script() = Some(wsh.inner_script());
1239                    *item.redeem_script() = Some(wsh.inner_script().to_v0_p2wsh());
1240                }
1241                descriptor::ShInner::Wpkh(..) => *item.redeem_script() = Some(sh.inner_script()),
1242                descriptor::ShInner::SortedMulti(_) | descriptor::ShInner::Ms(_) => {
1243                    *item.redeem_script() = Some(sh.inner_script())
1244                }
1245            },
1246            Descriptor::Wsh(wsh) => *item.witness_script() = Some(wsh.inner_script()),
1247            Descriptor::Tr(_) => unreachable!("Tr is dealt with separately"),
1248        }
1249
1250        derived
1251    };
1252
1253    Ok((derived, true))
1254}
1255
1256// Get a script from witness script pubkey hash
1257fn script_code_wpkh(script: &Script) -> Script {
1258    assert!(script.is_v0_p2wpkh());
1259    // ugly segwit stuff
1260    let mut script_code = vec![0x76u8, 0xa9, 0x14];
1261    script_code.extend(&script.as_bytes()[2..]);
1262    script_code.push(0x88);
1263    script_code.push(0xac);
1264    Script::from(script_code)
1265}
1266
1267/// Return error type for [`PsbtExt::update_input_with_descriptor`]
1268#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1269pub enum UtxoUpdateError {
1270    /// Index out of bounds
1271    IndexOutOfBounds(usize, usize),
1272    /// The unsigned transaction didn't have an input at that index
1273    MissingInputUtxo,
1274    /// Derivation error
1275    DerivationError(descriptor::ConversionError),
1276    /// The PSBT's `witness_utxo` and/or `non_witness_utxo` were invalid or missing
1277    UtxoCheck,
1278    /// The PSBT's `witness_utxo` and/or `non_witness_utxo` had a script_pubkey that did not match
1279    /// the descriptor
1280    MismatchedScriptPubkey,
1281}
1282
1283impl fmt::Display for UtxoUpdateError {
1284    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1285        match self {
1286            UtxoUpdateError::IndexOutOfBounds(ind, len) => {
1287                write!(f, "index {}, psbt input len: {}", ind, len)
1288            }
1289            UtxoUpdateError::MissingInputUtxo => {
1290                write!(f, "Missing input in unsigned transaction")
1291            }
1292            UtxoUpdateError::DerivationError(e) => write!(f, "Key derivation error {}", e),
1293            UtxoUpdateError::UtxoCheck => write!(
1294                f,
1295                "The input's witness_utxo and/or non_witness_utxo were invalid or missing"
1296            ),
1297            UtxoUpdateError::MismatchedScriptPubkey => {
1298                write!(f, "The input's witness_utxo and/or non_witness_utxo had a script pubkey that didn't match the descriptor")
1299            }
1300        }
1301    }
1302}
1303
1304#[cfg(feature = "std")]
1305impl error::Error for UtxoUpdateError {
1306    fn cause(&self) -> Option<&dyn error::Error> {
1307        use self::UtxoUpdateError::*;
1308
1309        match self {
1310            IndexOutOfBounds(_, _) | MissingInputUtxo | UtxoCheck | MismatchedScriptPubkey => None,
1311            DerivationError(e) => Some(e),
1312        }
1313    }
1314}
1315
1316/// Return error type for [`PsbtExt::update_output_with_descriptor`]
1317#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1318pub enum OutputUpdateError {
1319    /// Index out of bounds
1320    IndexOutOfBounds(usize, usize),
1321    /// The raw unsigned transaction didn't have an output at that index
1322    MissingTxOut,
1323    /// Derivation error
1324    DerivationError(descriptor::ConversionError),
1325    /// The output's script_pubkey did not match the descriptor
1326    MismatchedScriptPubkey,
1327}
1328
1329impl fmt::Display for OutputUpdateError {
1330    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1331        match self {
1332            OutputUpdateError::IndexOutOfBounds(ind, len) => {
1333                write!(f, "index {}, psbt output len: {}", ind, len)
1334            }
1335            OutputUpdateError::MissingTxOut => {
1336                write!(f, "Missing txout in the unsigned transaction")
1337            }
1338            OutputUpdateError::DerivationError(e) => write!(f, "Key derivation error {}", e),
1339            OutputUpdateError::MismatchedScriptPubkey => {
1340                write!(f, "The output's script pubkey didn't match the descriptor")
1341            }
1342        }
1343    }
1344}
1345
1346#[cfg(feature = "std")]
1347impl error::Error for OutputUpdateError {
1348    fn cause(&self) -> Option<&dyn error::Error> {
1349        use self::OutputUpdateError::*;
1350
1351        match self {
1352            IndexOutOfBounds(_, _) | MissingTxOut | MismatchedScriptPubkey => None,
1353            DerivationError(e) => Some(e),
1354        }
1355    }
1356}
1357
1358/// Return error type for [`PsbtExt::sighash_msg`]
1359#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1360pub enum SighashError {
1361    /// Index out of bounds
1362    IndexOutOfBounds(usize, usize),
1363    /// Missing input utxo
1364    MissingInputUtxo,
1365    /// Missing Prevouts
1366    MissingSpendUtxos,
1367    /// Invalid Sighash type
1368    InvalidSighashType,
1369    /// Sighash computation error
1370    /// Only happens when single does not have corresponding output as psbts
1371    /// already have information to compute the sighash
1372    SighashComputationError(bitcoin::util::sighash::Error),
1373    /// Missing Witness script
1374    MissingWitnessScript,
1375    /// Missing Redeem script,
1376    MissingRedeemScript,
1377}
1378
1379impl fmt::Display for SighashError {
1380    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1381        match self {
1382            SighashError::IndexOutOfBounds(ind, len) => {
1383                write!(f, "index {}, psbt input len: {}", ind, len)
1384            }
1385            SighashError::MissingInputUtxo => write!(f, "Missing input utxo in pbst"),
1386            SighashError::MissingSpendUtxos => write!(f, "Missing Psbt spend utxos"),
1387            SighashError::InvalidSighashType => write!(f, "Invalid Sighash type"),
1388            SighashError::SighashComputationError(e) => {
1389                write!(f, "Sighash computation error : {}", e)
1390            }
1391            SighashError::MissingWitnessScript => write!(f, "Missing Witness Script"),
1392            SighashError::MissingRedeemScript => write!(f, "Missing Redeem Script"),
1393        }
1394    }
1395}
1396
1397#[cfg(feature = "std")]
1398impl error::Error for SighashError {
1399    fn cause(&self) -> Option<&dyn error::Error> {
1400        use self::SighashError::*;
1401
1402        match self {
1403            IndexOutOfBounds(_, _)
1404            | MissingInputUtxo
1405            | MissingSpendUtxos
1406            | InvalidSighashType
1407            | MissingWitnessScript
1408            | MissingRedeemScript => None,
1409            SighashComputationError(e) => Some(e),
1410        }
1411    }
1412}
1413
1414impl From<bitcoin::util::sighash::Error> for SighashError {
1415    fn from(e: bitcoin::util::sighash::Error) -> Self {
1416        SighashError::SighashComputationError(e)
1417    }
1418}
1419
1420/// Sighash message(signing data) for a given psbt transaction input.
1421#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1422pub enum PsbtSighashMsg {
1423    /// Taproot Signature hash
1424    TapSighash(taproot::TapSighashHash),
1425    /// Ecdsa Sighash message (includes sighash for legacy/p2sh/segwitv0 outputs)
1426    EcdsaSighash(bitcoin::Sighash),
1427}
1428
1429impl PsbtSighashMsg {
1430    /// Convert the message to a [`secp256k1::Message`].
1431    pub fn to_secp_msg(&self) -> secp256k1::Message {
1432        match *self {
1433            PsbtSighashMsg::TapSighash(msg) => {
1434                secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1435            }
1436            PsbtSighashMsg::EcdsaSighash(msg) => {
1437                secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1438            }
1439        }
1440    }
1441}
1442
1443#[cfg(test)]
1444mod tests {
1445    use std::str::FromStr;
1446
1447    use bitcoin::consensus::encode::deserialize;
1448    use bitcoin::hashes::hex::FromHex;
1449    use bitcoin::secp256k1::PublicKey;
1450    use bitcoin::util::bip32::{DerivationPath, ExtendedPubKey};
1451    use bitcoin::{OutPoint, PackedLockTime, TxIn, TxOut, XOnlyPublicKey};
1452
1453    use super::*;
1454    use crate::Miniscript;
1455
1456    #[test]
1457    fn test_extract_bip174() {
1458        let psbt: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::<u8>::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap();
1459        let secp = Secp256k1::verification_only();
1460        let tx = psbt.extract(&secp).unwrap();
1461        let expected: bitcoin::Transaction = deserialize(&Vec::<u8>::from_hex("0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000").unwrap()).unwrap();
1462        assert_eq!(tx, expected);
1463    }
1464
1465    #[test]
1466    fn test_update_item_tr_no_script() {
1467        // keys taken from: https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#Specifications
1468        let root_xpub = ExtendedPubKey::from_str("xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8").unwrap();
1469        let fingerprint = root_xpub.fingerprint();
1470        let desc = format!("tr([{}/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)", fingerprint);
1471        let desc = Descriptor::from_str(&desc).unwrap();
1472        let mut psbt_input = psbt::Input::default();
1473        psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1474        let mut psbt_output = psbt::Output::default();
1475        psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1476        let internal_key = XOnlyPublicKey::from_str(
1477            "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
1478        )
1479        .unwrap();
1480        assert_eq!(psbt_input.tap_internal_key, Some(internal_key));
1481        assert_eq!(
1482            psbt_input.tap_key_origins.get(&internal_key),
1483            Some(&(
1484                vec![],
1485                (
1486                    fingerprint,
1487                    DerivationPath::from_str("m/86'/0'/0'/0/0").unwrap()
1488                )
1489            ))
1490        );
1491        assert_eq!(psbt_input.tap_key_origins.len(), 1);
1492        assert_eq!(psbt_input.tap_scripts.len(), 0);
1493        assert_eq!(psbt_input.tap_merkle_root, None);
1494
1495        assert_eq!(psbt_output.tap_internal_key, psbt_input.tap_internal_key);
1496        assert_eq!(psbt_output.tap_key_origins, psbt_input.tap_key_origins);
1497        assert_eq!(psbt_output.tap_tree, None);
1498    }
1499
1500    #[test]
1501    fn test_update_item_tr_with_tapscript() {
1502        use crate::Tap;
1503        // keys taken from: https://github.com/bitcoin/bips/blob/master/bip-0086.mediawiki#Specifications
1504        let root_xpub = ExtendedPubKey::from_str("xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8").unwrap();
1505        let fingerprint = root_xpub.fingerprint();
1506        let xpub = format!("[{}/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ", fingerprint);
1507        let desc = format!(
1508            "tr({}/0/0,{{pkh({}/0/1),multi_a(2,{}/0/1,{}/1/0)}})",
1509            xpub, xpub, xpub, xpub
1510        );
1511
1512        let desc = Descriptor::from_str(&desc).unwrap();
1513        let internal_key = XOnlyPublicKey::from_str(
1514            "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
1515        )
1516        .unwrap();
1517        let mut psbt_input = psbt::Input::default();
1518        psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1519        let mut psbt_output = psbt::Output::default();
1520        psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1521        assert_eq!(psbt_input.tap_internal_key, Some(internal_key));
1522        assert_eq!(
1523            psbt_input.tap_key_origins.get(&internal_key),
1524            Some(&(
1525                vec![],
1526                (
1527                    fingerprint,
1528                    DerivationPath::from_str("m/86'/0'/0'/0/0").unwrap()
1529                )
1530            ))
1531        );
1532        assert_eq!(psbt_input.tap_key_origins.len(), 3);
1533        assert_eq!(psbt_input.tap_scripts.len(), 2);
1534        assert!(psbt_input.tap_merkle_root.is_some());
1535
1536        assert_eq!(psbt_output.tap_internal_key, psbt_input.tap_internal_key);
1537        assert_eq!(psbt_output.tap_key_origins, psbt_input.tap_key_origins);
1538        assert!(psbt_output.tap_tree.is_some());
1539
1540        let key_0_1 = XOnlyPublicKey::from_str(
1541            "83dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145",
1542        )
1543        .unwrap();
1544        let first_leaf_hash = {
1545            let ms =
1546                Miniscript::<XOnlyPublicKey, Tap>::from_str(&format!("pkh({})", &key_0_1)).unwrap();
1547            let first_script = ms.encode();
1548            assert!(psbt_input
1549                .tap_scripts
1550                .values()
1551                .find(|value| *value == &(first_script.clone(), LeafVersion::TapScript))
1552                .is_some());
1553            TapLeafHash::from_script(&first_script, LeafVersion::TapScript)
1554        };
1555
1556        {
1557            // check 0/1
1558            let (leaf_hashes, (key_fingerprint, deriv_path)) =
1559                psbt_input.tap_key_origins.get(&key_0_1).unwrap();
1560            assert_eq!(key_fingerprint, &fingerprint);
1561            assert_eq!(&deriv_path.to_string(), "m/86'/0'/0'/0/1");
1562            assert_eq!(leaf_hashes.len(), 2);
1563            assert!(leaf_hashes.contains(&first_leaf_hash));
1564        }
1565
1566        {
1567            // check 1/0
1568            let key_1_0 = XOnlyPublicKey::from_str(
1569                "399f1b2f4393f29a18c937859c5dd8a77350103157eb880f02e8c08214277cef",
1570            )
1571            .unwrap();
1572            let (leaf_hashes, (key_fingerprint, deriv_path)) =
1573                psbt_input.tap_key_origins.get(&key_1_0).unwrap();
1574            assert_eq!(key_fingerprint, &fingerprint);
1575            assert_eq!(&deriv_path.to_string(), "m/86'/0'/0'/1/0");
1576            assert_eq!(leaf_hashes.len(), 1);
1577            assert!(!leaf_hashes.contains(&first_leaf_hash));
1578        }
1579    }
1580
1581    #[test]
1582    fn test_update_item_non_tr_multi() {
1583        // values taken from https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki (after removing zpub thingy)
1584        let root_xpub = ExtendedPubKey::from_str("xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8").unwrap();
1585        let fingerprint = root_xpub.fingerprint();
1586        let xpub = format!("[{}/84'/0'/0']xpub6CatWdiZiodmUeTDp8LT5or8nmbKNcuyvz7WyksVFkKB4RHwCD3XyuvPEbvqAQY3rAPshWcMLoP2fMFMKHPJ4ZeZXYVUhLv1VMrjPC7PW6V", fingerprint);
1587        let pubkeys = [
1588            "0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c",
1589            "03e775fd51f0dfb8cd865d9ff1cca2a158cf651fe997fdc9fee9c1d3b5e995ea77",
1590            "03025324888e429ab8e3dbaf1f7802648b9cd01e9b418485c5fa4c1b9b5700e1a6",
1591        ];
1592
1593        let expected_bip32 = pubkeys
1594            .iter()
1595            .zip(["0/0", "0/1", "1/0"].iter())
1596            .map(|(pubkey, path)| {
1597                (
1598                    PublicKey::from_str(pubkey).unwrap(),
1599                    (
1600                        fingerprint,
1601                        DerivationPath::from_str(&format!("m/84'/0'/0'/{}", path)).unwrap(),
1602                    ),
1603                )
1604            })
1605            .collect::<BTreeMap<_, _>>();
1606
1607        {
1608            // test segwit
1609            let desc = format!("wsh(multi(2,{}/0/0,{}/0/1,{}/1/0))", xpub, xpub, xpub);
1610            let desc = Descriptor::from_str(&desc).unwrap();
1611            let derived = format!("wsh(multi(2,{}))", pubkeys.join(","));
1612            let derived = Descriptor::<bitcoin::PublicKey>::from_str(&derived).unwrap();
1613
1614            let mut psbt_input = psbt::Input::default();
1615            psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1616
1617            let mut psbt_output = psbt::Output::default();
1618            psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1619
1620            assert_eq!(expected_bip32, psbt_input.bip32_derivation);
1621            assert_eq!(
1622                psbt_input.witness_script,
1623                Some(derived.explicit_script().unwrap())
1624            );
1625
1626            assert_eq!(psbt_output.bip32_derivation, psbt_input.bip32_derivation);
1627            assert_eq!(psbt_output.witness_script, psbt_input.witness_script);
1628        }
1629
1630        {
1631            // test non-segwit
1632            let desc = format!("sh(multi(2,{}/0/0,{}/0/1,{}/1/0))", xpub, xpub, xpub);
1633            let desc = Descriptor::from_str(&desc).unwrap();
1634            let derived = format!("sh(multi(2,{}))", pubkeys.join(","));
1635            let derived = Descriptor::<bitcoin::PublicKey>::from_str(&derived).unwrap();
1636
1637            let mut psbt_input = psbt::Input::default();
1638            psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1639
1640            let mut psbt_output = psbt::Output::default();
1641            psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1642
1643            assert_eq!(psbt_input.bip32_derivation, expected_bip32);
1644            assert_eq!(psbt_input.witness_script, None);
1645            assert_eq!(
1646                psbt_input.redeem_script,
1647                Some(derived.explicit_script().unwrap())
1648            );
1649
1650            assert_eq!(psbt_output.bip32_derivation, psbt_input.bip32_derivation);
1651            assert_eq!(psbt_output.witness_script, psbt_input.witness_script);
1652            assert_eq!(psbt_output.redeem_script, psbt_input.redeem_script);
1653        }
1654    }
1655
1656    #[test]
1657    fn test_update_input_checks() {
1658        let desc = format!("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)");
1659        let desc = Descriptor::<DefiniteDescriptorKey>::from_str(&desc).unwrap();
1660
1661        let mut non_witness_utxo = bitcoin::Transaction {
1662            version: 1,
1663            lock_time: PackedLockTime::ZERO,
1664            input: vec![],
1665            output: vec![TxOut {
1666                value: 1_000,
1667                script_pubkey: Script::from_str(
1668                    "5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c",
1669                )
1670                .unwrap(),
1671            }],
1672        };
1673
1674        let tx = bitcoin::Transaction {
1675            version: 1,
1676            lock_time: PackedLockTime::ZERO,
1677            input: vec![TxIn {
1678                previous_output: OutPoint {
1679                    txid: non_witness_utxo.txid(),
1680                    vout: 0,
1681                },
1682                ..Default::default()
1683            }],
1684            output: vec![],
1685        };
1686
1687        let mut psbt = Psbt::from_unsigned_tx(tx.clone()).unwrap();
1688        assert_eq!(
1689            psbt.update_input_with_descriptor(0, &desc),
1690            Err(UtxoUpdateError::UtxoCheck),
1691            "neither *_utxo are not set"
1692        );
1693        psbt.inputs[0].witness_utxo = Some(non_witness_utxo.output[0].clone());
1694        assert_eq!(
1695            psbt.update_input_with_descriptor(0, &desc),
1696            Ok(()),
1697            "witness_utxo is set which is ok"
1698        );
1699        psbt.inputs[0].non_witness_utxo = Some(non_witness_utxo.clone());
1700        assert_eq!(
1701            psbt.update_input_with_descriptor(0, &desc),
1702            Ok(()),
1703            "matching non_witness_utxo"
1704        );
1705        non_witness_utxo.version = 0;
1706        psbt.inputs[0].non_witness_utxo = Some(non_witness_utxo.clone());
1707        assert_eq!(
1708            psbt.update_input_with_descriptor(0, &desc),
1709            Err(UtxoUpdateError::UtxoCheck),
1710            "non_witness_utxo no longer matches"
1711        );
1712        psbt.inputs[0].non_witness_utxo = None;
1713        psbt.inputs[0].witness_utxo.as_mut().unwrap().script_pubkey = Script::default();
1714        assert_eq!(
1715            psbt.update_input_with_descriptor(0, &desc),
1716            Err(UtxoUpdateError::MismatchedScriptPubkey),
1717            "non_witness_utxo no longer matches"
1718        );
1719    }
1720
1721    #[test]
1722    fn test_update_output_checks() {
1723        let desc = format!("tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)");
1724        let desc = Descriptor::<DefiniteDescriptorKey>::from_str(&desc).unwrap();
1725
1726        let tx = bitcoin::Transaction {
1727            version: 1,
1728            lock_time: PackedLockTime::ZERO,
1729            input: vec![],
1730            output: vec![TxOut {
1731                value: 1_000,
1732                script_pubkey: Script::from_str(
1733                    "5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c",
1734                )
1735                .unwrap(),
1736            }],
1737        };
1738
1739        let mut psbt = Psbt::from_unsigned_tx(tx.clone()).unwrap();
1740        assert_eq!(
1741            psbt.update_output_with_descriptor(1, &desc),
1742            Err(OutputUpdateError::IndexOutOfBounds(1, 1)),
1743            "output index doesn't exist"
1744        );
1745        assert_eq!(
1746            psbt.update_output_with_descriptor(0, &desc),
1747            Ok(()),
1748            "script_pubkey should match"
1749        );
1750        psbt.unsigned_tx.output[0].script_pubkey = Script::default();
1751        assert_eq!(
1752            psbt.update_output_with_descriptor(0, &desc),
1753            Err(OutputUpdateError::MismatchedScriptPubkey),
1754            "output script_pubkey no longer matches"
1755        );
1756    }
1757}