Skip to main content

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