Thanks to visit codestin.com
Credit goes to docs.rs

miniscript/psbt/
mod.rs

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