1use core::convert::TryFrom;
12use core::fmt;
13#[cfg(feature = "std")]
14use std::error;
15
16use qtum::hashes::{hash160, sha256d, Hash};
17use qtum::psbt::{self, Psbt};
18use qtum::secp256k1::{self, Secp256k1, VerifyOnly};
19use qtum::sighash::{self, SighashCache};
20use qtum::taproot::{self, ControlBlock, LeafVersion, TapLeafHash};
21use qtum::{absolute, bip32, Script, ScriptBuf, Sequence};
22
23use crate::miniscript::context::SigType;
24use crate::prelude::*;
25use crate::{
26 descriptor, interpreter, DefiniteDescriptorKey, Descriptor, DescriptorPublicKey, MiniscriptKey,
27 Preimage32, Satisfier, ToPublicKey, TranslatePk, Translator,
28};
29
30mod finalizer;
31
32#[allow(deprecated)]
33pub use self::finalizer::{finalize, finalize_mall, interpreter_check};
34
35#[derive(Debug)]
37pub enum Error {
38 InputError(InputError, usize),
40 WrongInputCount {
42 in_tx: usize,
44 in_map: usize,
46 },
47 InputIdxOutofBounds {
49 psbt_inp: usize,
51 index: usize,
53 },
54}
55
56impl fmt::Display for Error {
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 match *self {
59 Error::InputError(ref inp_err, index) => write!(f, "{} at index {}", inp_err, index),
60 Error::WrongInputCount { in_tx, in_map } => write!(
61 f,
62 "PSBT had {} inputs in transaction but {} inputs in map",
63 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#[derive(Debug)]
88pub enum InputError {
89 SecpErr(qtum::secp256k1::Error),
91 KeyErr(qtum::key::Error),
93 CouldNotSatisfyTr,
98 Interpreter(interpreter::Error),
100 InvalidRedeemScript {
102 redeem: ScriptBuf,
104 p2sh_expected: ScriptBuf,
106 },
107 InvalidWitnessScript {
109 witness_script: ScriptBuf,
111 p2wsh_expected: ScriptBuf,
113 },
114 InvalidSignature {
116 pubkey: qtum::PublicKey,
118 sig: Vec<u8>,
120 },
121 MiniscriptError(super::Error),
123 MissingRedeemScript,
125 MissingWitness,
127 MissingPubkey,
129 MissingWitnessScript,
131 MissingUtxo,
133 NonEmptyWitnessScript,
135 NonEmptyRedeemScript,
137 NonStandardSighashType(sighash::NonStandardSighashType),
139 WrongSighashFlag {
141 required: sighash::EcdsaSighashType,
143 got: sighash::EcdsaSighashType,
145 pubkey: qtum::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 {
181 ref pubkey,
182 ref sig,
183 } => write!(f, "PSBT: bad signature {} for key {:?}", pubkey, sig),
184 InputError::KeyErr(ref e) => write!(f, "Key Err: {}", e),
185 InputError::Interpreter(ref e) => write!(f, "Interpreter: {}", e),
186 InputError::SecpErr(ref e) => write!(f, "Secp Err: {}", e),
187 InputError::InvalidRedeemScript {
188 ref redeem,
189 ref p2sh_expected,
190 } => write!(
191 f,
192 "Redeem script {} does not match the p2sh script {}",
193 redeem, p2sh_expected
194 ),
195 InputError::InvalidWitnessScript {
196 ref witness_script,
197 ref p2wsh_expected,
198 } => write!(
199 f,
200 "Witness script {} does not match the p2wsh script {}",
201 witness_script, p2wsh_expected
202 ),
203 InputError::MiniscriptError(ref e) => write!(f, "Miniscript Error: {}", e),
204 InputError::MissingWitness => write!(f, "PSBT is missing witness"),
205 InputError::MissingRedeemScript => write!(f, "PSBT is Redeem script"),
206 InputError::MissingUtxo => {
207 write!(f, "PSBT is missing both witness and non-witness UTXO")
208 }
209 InputError::MissingWitnessScript => write!(f, "PSBT is missing witness script"),
210 InputError::MissingPubkey => write!(f, "Missing pubkey for a pkh/wpkh"),
211 InputError::NonEmptyRedeemScript => write!(
212 f,
213 "PSBT has non-empty redeem script at for legacy transactions"
214 ),
215 InputError::NonEmptyWitnessScript => {
216 write!(f, "PSBT has non-empty witness script at for legacy input")
217 }
218 InputError::WrongSighashFlag {
219 required,
220 got,
221 pubkey,
222 } => write!(
223 f,
224 "PSBT: signature with key {:?} had \
225 sighashflag {:?} rather than required {:?}",
226 pubkey, got, required
227 ),
228 InputError::CouldNotSatisfyTr => write!(f, "Could not satisfy Tr descriptor"),
229 InputError::NonStandardSighashType(e) => write!(f, "Non-standard sighash type {}", e),
230 }
231 }
232}
233
234#[doc(hidden)]
235impl From<super::Error> for InputError {
236 fn from(e: super::Error) -> InputError {
237 InputError::MiniscriptError(e)
238 }
239}
240
241#[doc(hidden)]
242impl From<qtum::secp256k1::Error> for InputError {
243 fn from(e: qtum::secp256k1::Error) -> InputError {
244 InputError::SecpErr(e)
245 }
246}
247
248#[doc(hidden)]
249impl From<qtum::key::Error> for InputError {
250 fn from(e: qtum::key::Error) -> InputError {
251 InputError::KeyErr(e)
252 }
253}
254
255pub struct PsbtInputSatisfier<'psbt> {
261 pub psbt: &'psbt Psbt,
263 pub index: usize,
265}
266
267impl<'psbt> PsbtInputSatisfier<'psbt> {
268 pub fn new(psbt: &'psbt Psbt, index: usize) -> Self {
271 Self { psbt, index }
272 }
273}
274
275impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfier<'psbt> {
276 fn lookup_tap_key_spend_sig(&self) -> Option<qtum::taproot::Signature> {
277 self.psbt.inputs[self.index].tap_key_sig
278 }
279
280 fn lookup_tap_leaf_script_sig(
281 &self,
282 pk: &Pk,
283 lh: &TapLeafHash,
284 ) -> Option<qtum::taproot::Signature> {
285 self.psbt.inputs[self.index]
286 .tap_script_sigs
287 .get(&(pk.to_x_only_pubkey(), *lh))
288 .copied()
289 }
290
291 fn lookup_raw_pkh_pk(&self, pkh: &hash160::Hash) -> Option<qtum::PublicKey> {
292 self.psbt.inputs[self.index]
293 .bip32_derivation
294 .iter()
295 .find(|&(pubkey, _)| pubkey.to_pubkeyhash(SigType::Ecdsa) == *pkh)
296 .map(|(pubkey, _)| qtum::PublicKey::new(*pubkey))
297 }
298
299 fn lookup_tap_control_block_map(
300 &self,
301 ) -> Option<&BTreeMap<ControlBlock, (qtum::ScriptBuf, LeafVersion)>> {
302 Some(&self.psbt.inputs[self.index].tap_scripts)
303 }
304
305 fn lookup_raw_pkh_tap_leaf_script_sig(
306 &self,
307 pkh: &(hash160::Hash, TapLeafHash),
308 ) -> Option<(
309 qtum::secp256k1::XOnlyPublicKey,
310 qtum::taproot::Signature,
311 )> {
312 self.psbt.inputs[self.index]
313 .tap_script_sigs
314 .iter()
315 .find(|&((pubkey, lh), _sig)| {
316 pubkey.to_pubkeyhash(SigType::Schnorr) == pkh.0 && *lh == pkh.1
317 })
318 .map(|((x_only_pk, _leaf_hash), sig)| (*x_only_pk, *sig))
319 }
320
321 fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option<qtum::ecdsa::Signature> {
322 self.psbt.inputs[self.index]
323 .partial_sigs
324 .get(&pk.to_public_key())
325 .copied()
326 }
327
328 fn lookup_raw_pkh_ecdsa_sig(
329 &self,
330 pkh: &hash160::Hash,
331 ) -> Option<(qtum::PublicKey, qtum::ecdsa::Signature)> {
332 self.psbt.inputs[self.index]
333 .partial_sigs
334 .iter()
335 .find(|&(pubkey, _sig)| pubkey.to_pubkeyhash(SigType::Ecdsa) == *pkh)
336 .map(|(pk, sig)| (*pk, *sig))
337 }
338
339 fn check_after(&self, n: absolute::LockTime) -> bool {
340 if !self.psbt.unsigned_tx.input[self.index].enables_lock_time() {
341 return false;
342 }
343
344 let lock_time = absolute::LockTime::from(self.psbt.unsigned_tx.lock_time);
345
346 <dyn Satisfier<Pk>>::check_after(&lock_time, n)
347 }
348
349 fn check_older(&self, n: Sequence) -> bool {
350 let seq = self.psbt.unsigned_tx.input[self.index].sequence;
351
352 if !n.is_relative_lock_time() {
355 return true;
356 }
357
358 if self.psbt.unsigned_tx.version < 2 || !seq.is_relative_lock_time() {
359 return false;
360 }
361
362 <dyn Satisfier<Pk>>::check_older(&seq, n)
363 }
364
365 fn lookup_hash160(&self, h: &Pk::Hash160) -> Option<Preimage32> {
366 self.psbt.inputs[self.index]
367 .hash160_preimages
368 .get(&Pk::to_hash160(h))
369 .and_then(try_vec_as_preimage32)
370 }
371
372 fn lookup_sha256(&self, h: &Pk::Sha256) -> Option<Preimage32> {
373 self.psbt.inputs[self.index]
374 .sha256_preimages
375 .get(&Pk::to_sha256(h))
376 .and_then(try_vec_as_preimage32)
377 }
378
379 fn lookup_hash256(&self, h: &Pk::Hash256) -> Option<Preimage32> {
380 self.psbt.inputs[self.index]
381 .hash256_preimages
382 .get(&sha256d::Hash::from_byte_array(
383 Pk::to_hash256(h).to_byte_array(),
384 )) .and_then(try_vec_as_preimage32)
386 }
387
388 fn lookup_ripemd160(&self, h: &Pk::Ripemd160) -> Option<Preimage32> {
389 self.psbt.inputs[self.index]
390 .ripemd160_preimages
391 .get(&Pk::to_ripemd160(h))
392 .and_then(try_vec_as_preimage32)
393 }
394}
395
396fn try_vec_as_preimage32(vec: &Vec<u8>) -> Option<Preimage32> {
397 if vec.len() == 32 {
398 let mut arr = [0u8; 32];
399 arr.copy_from_slice(vec);
400 Some(arr)
401 } else {
402 None
403 }
404}
405
406fn sanity_check(psbt: &Psbt) -> Result<(), Error> {
410 if psbt.unsigned_tx.input.len() != psbt.inputs.len() {
411 return Err(Error::WrongInputCount {
412 in_tx: psbt.unsigned_tx.input.len(),
413 in_map: psbt.inputs.len(),
414 });
415 }
416
417 for (index, input) in psbt.inputs.iter().enumerate() {
419 let target_ecdsa_sighash_ty = match input.sighash_type {
421 Some(psbt_hash_ty) => psbt_hash_ty
422 .ecdsa_hash_ty()
423 .map_err(|e| Error::InputError(InputError::NonStandardSighashType(e), index))?,
424 None => sighash::EcdsaSighashType::All,
425 };
426 for (key, ecdsa_sig) in &input.partial_sigs {
427 let flag = sighash::EcdsaSighashType::from_standard(ecdsa_sig.hash_ty as u32).map_err(
428 |_| {
429 Error::InputError(
430 InputError::Interpreter(interpreter::Error::NonStandardSighash(
431 ecdsa_sig.to_vec(),
432 )),
433 index,
434 )
435 },
436 )?;
437 if target_ecdsa_sighash_ty != flag {
438 return Err(Error::InputError(
439 InputError::WrongSighashFlag {
440 required: target_ecdsa_sighash_ty,
441 got: flag,
442 pubkey: *key,
443 },
444 index,
445 ));
446 }
447 }
449 }
450
451 Ok(())
452}
453
454pub trait PsbtExt {
458 fn finalize_mut<C: secp256k1::Verification>(
475 &mut self,
476 secp: &secp256k1::Secp256k1<C>,
477 ) -> Result<(), Vec<Error>>;
478
479 fn finalize<C: secp256k1::Verification>(
487 self,
488 secp: &secp256k1::Secp256k1<C>,
489 ) -> Result<Psbt, (Psbt, Vec<Error>)>;
490
491 fn finalize_mall_mut<C: secp256k1::Verification>(
493 &mut self,
494 secp: &Secp256k1<C>,
495 ) -> Result<(), Vec<Error>>;
496
497 fn finalize_mall<C: secp256k1::Verification>(
499 self,
500 secp: &Secp256k1<C>,
501 ) -> Result<Psbt, (Psbt, Vec<Error>)>;
502
503 fn finalize_inp_mut<C: secp256k1::Verification>(
511 &mut self,
512 secp: &secp256k1::Secp256k1<C>,
513 index: usize,
514 ) -> Result<(), Error>;
515
516 fn finalize_inp<C: secp256k1::Verification>(
523 self,
524 secp: &secp256k1::Secp256k1<C>,
525 index: usize,
526 ) -> Result<Psbt, (Psbt, Error)>;
527
528 fn finalize_inp_mall_mut<C: secp256k1::Verification>(
530 &mut self,
531 secp: &secp256k1::Secp256k1<C>,
532 index: usize,
533 ) -> Result<(), Error>;
534
535 fn finalize_inp_mall<C: secp256k1::Verification>(
537 self,
538 secp: &secp256k1::Secp256k1<C>,
539 index: usize,
540 ) -> Result<Psbt, (Psbt, Error)>;
541
542 fn extract<C: secp256k1::Verification>(
548 &self,
549 secp: &Secp256k1<C>,
550 ) -> Result<qtum::Transaction, Error>;
551
552 fn update_input_with_descriptor(
571 &mut self,
572 input_index: usize,
573 descriptor: &Descriptor<DefiniteDescriptorKey>,
574 ) -> Result<(), UtxoUpdateError>;
575
576 fn update_output_with_descriptor(
586 &mut self,
587 output_index: usize,
588 descriptor: &Descriptor<DefiniteDescriptorKey>,
589 ) -> Result<(), OutputUpdateError>;
590
591 fn sighash_msg<T: Borrow<qtum::Transaction>>(
613 &self,
614 idx: usize,
615 cache: &mut SighashCache<T>,
616 tapleaf_hash: Option<TapLeafHash>,
617 ) -> Result<PsbtSighashMsg, SighashError>;
618}
619
620impl PsbtExt for Psbt {
621 fn finalize_mut<C: secp256k1::Verification>(
622 &mut self,
623 secp: &secp256k1::Secp256k1<C>,
624 ) -> Result<(), Vec<Error>> {
625 let mut errors = vec![];
627 for index in 0..self.inputs.len() {
628 match finalizer::finalize_input(self, index, secp, false) {
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<C: secp256k1::Verification>(
643 mut self,
644 secp: &secp256k1::Secp256k1<C>,
645 ) -> Result<Psbt, (Psbt, Vec<Error>)> {
646 match self.finalize_mut(secp) {
647 Ok(..) => Ok(self),
648 Err(e) => Err((self, e)),
649 }
650 }
651
652 fn finalize_mall_mut<C: secp256k1::Verification>(
653 &mut self,
654 secp: &secp256k1::Secp256k1<C>,
655 ) -> Result<(), Vec<Error>> {
656 let mut errors = vec![];
657 for index in 0..self.inputs.len() {
658 match finalizer::finalize_input(self, index, secp, true) {
659 Ok(..) => {}
660 Err(e) => {
661 errors.push(e);
662 }
663 }
664 }
665 if errors.is_empty() {
666 Ok(())
667 } else {
668 Err(errors)
669 }
670 }
671
672 fn finalize_mall<C: secp256k1::Verification>(
673 mut self,
674 secp: &Secp256k1<C>,
675 ) -> Result<Psbt, (Psbt, Vec<Error>)> {
676 match self.finalize_mall_mut(secp) {
677 Ok(..) => Ok(self),
678 Err(e) => Err((self, e)),
679 }
680 }
681
682 fn finalize_inp_mut<C: secp256k1::Verification>(
683 &mut self,
684 secp: &secp256k1::Secp256k1<C>,
685 index: usize,
686 ) -> Result<(), Error> {
687 if index >= self.inputs.len() {
688 return Err(Error::InputIdxOutofBounds {
689 psbt_inp: self.inputs.len(),
690 index,
691 });
692 }
693 finalizer::finalize_input(self, index, secp, false)
694 }
695
696 fn finalize_inp<C: secp256k1::Verification>(
697 mut self,
698 secp: &secp256k1::Secp256k1<C>,
699 index: usize,
700 ) -> Result<Psbt, (Psbt, Error)> {
701 match self.finalize_inp_mut(secp, index) {
702 Ok(..) => Ok(self),
703 Err(e) => Err((self, e)),
704 }
705 }
706
707 fn finalize_inp_mall_mut<C: secp256k1::Verification>(
708 &mut self,
709 secp: &secp256k1::Secp256k1<C>,
710 index: usize,
711 ) -> Result<(), Error> {
712 if index >= self.inputs.len() {
713 return Err(Error::InputIdxOutofBounds {
714 psbt_inp: self.inputs.len(),
715 index,
716 });
717 }
718 finalizer::finalize_input(self, index, secp, false)
719 }
720
721 fn finalize_inp_mall<C: secp256k1::Verification>(
722 mut self,
723 secp: &secp256k1::Secp256k1<C>,
724 index: usize,
725 ) -> Result<Psbt, (Psbt, Error)> {
726 match self.finalize_inp_mall_mut(secp, index) {
727 Ok(..) => Ok(self),
728 Err(e) => Err((self, e)),
729 }
730 }
731
732 fn extract<C: secp256k1::Verification>(
733 &self,
734 secp: &Secp256k1<C>,
735 ) -> Result<qtum::Transaction, Error> {
736 sanity_check(self)?;
737
738 let mut ret = self.unsigned_tx.clone();
739 for (n, input) in self.inputs.iter().enumerate() {
740 if input.final_script_sig.is_none() && input.final_script_witness.is_none() {
741 return Err(Error::InputError(InputError::MissingWitness, n));
742 }
743
744 if let Some(witness) = input.final_script_witness.as_ref() {
745 ret.input[n].witness = witness.clone();
746 }
747 if let Some(script_sig) = input.final_script_sig.as_ref() {
748 ret.input[n].script_sig = script_sig.clone();
749 }
750 }
751 interpreter_check(self, secp)?;
752 Ok(ret)
753 }
754
755 fn update_input_with_descriptor(
756 &mut self,
757 input_index: usize,
758 desc: &Descriptor<DefiniteDescriptorKey>,
759 ) -> Result<(), UtxoUpdateError> {
760 let n_inputs = self.inputs.len();
761 let input = self
762 .inputs
763 .get_mut(input_index)
764 .ok_or(UtxoUpdateError::IndexOutOfBounds(input_index, n_inputs))?;
765 let txin = self
766 .unsigned_tx
767 .input
768 .get(input_index)
769 .ok_or(UtxoUpdateError::MissingInputUtxo)?;
770
771 let desc_type = desc.desc_type();
772
773 if let Some(non_witness_utxo) = &input.non_witness_utxo {
774 if txin.previous_output.txid != non_witness_utxo.txid() {
775 return Err(UtxoUpdateError::UtxoCheck);
776 }
777 }
778
779 let expected_spk = {
780 match (&input.witness_utxo, &input.non_witness_utxo) {
781 (Some(witness_utxo), None) => {
782 if desc_type.segwit_version().is_some() {
783 witness_utxo.script_pubkey.clone()
784 } else {
785 return Err(UtxoUpdateError::UtxoCheck);
786 }
787 }
788 (None, Some(non_witness_utxo)) => non_witness_utxo
789 .output
790 .get(txin.previous_output.vout as usize)
791 .ok_or(UtxoUpdateError::UtxoCheck)?
792 .script_pubkey
793 .clone(),
794 (Some(witness_utxo), Some(non_witness_utxo)) => {
795 if witness_utxo
796 != non_witness_utxo
797 .output
798 .get(txin.previous_output.vout as usize)
799 .ok_or(UtxoUpdateError::UtxoCheck)?
800 {
801 return Err(UtxoUpdateError::UtxoCheck);
802 }
803
804 witness_utxo.script_pubkey.clone()
805 }
806 (None, None) => return Err(UtxoUpdateError::UtxoCheck),
807 }
808 };
809
810 let (_, spk_check_passed) =
811 update_item_with_descriptor_helper(input, desc, Some(&expected_spk))
812 .map_err(UtxoUpdateError::DerivationError)?;
813
814 if !spk_check_passed {
815 return Err(UtxoUpdateError::MismatchedScriptPubkey);
816 }
817
818 Ok(())
819 }
820
821 fn update_output_with_descriptor(
822 &mut self,
823 output_index: usize,
824 desc: &Descriptor<DefiniteDescriptorKey>,
825 ) -> Result<(), OutputUpdateError> {
826 let n_outputs = self.outputs.len();
827 let output = self
828 .outputs
829 .get_mut(output_index)
830 .ok_or(OutputUpdateError::IndexOutOfBounds(output_index, n_outputs))?;
831 let txout = self
832 .unsigned_tx
833 .output
834 .get(output_index)
835 .ok_or(OutputUpdateError::MissingTxOut)?;
836
837 let (_, spk_check_passed) =
838 update_item_with_descriptor_helper(output, desc, Some(&txout.script_pubkey))
839 .map_err(OutputUpdateError::DerivationError)?;
840
841 if !spk_check_passed {
842 return Err(OutputUpdateError::MismatchedScriptPubkey);
843 }
844
845 Ok(())
846 }
847
848 fn sighash_msg<T: Borrow<qtum::Transaction>>(
849 &self,
850 idx: usize,
851 cache: &mut SighashCache<T>,
852 tapleaf_hash: Option<TapLeafHash>,
853 ) -> Result<PsbtSighashMsg, SighashError> {
854 if idx >= self.inputs.len() {
856 return Err(SighashError::IndexOutOfBounds(idx, self.inputs.len()));
857 }
858 let inp = &self.inputs[idx];
859 let prevouts = finalizer::prevouts(self).map_err(|_e| SighashError::MissingSpendUtxos)?;
860 let prevouts = qtum::sighash::Prevouts::All(&prevouts);
863 let inp_spk =
864 finalizer::get_scriptpubkey(self, idx).map_err(|_e| SighashError::MissingInputUtxo)?;
865 if inp_spk.is_v1_p2tr() {
866 let hash_ty = inp
867 .sighash_type
868 .map(|sighash_type| sighash_type.taproot_hash_ty())
869 .unwrap_or(Ok(sighash::TapSighashType::Default))
870 .map_err(|_e| SighashError::InvalidSighashType)?;
871 match tapleaf_hash {
872 Some(leaf_hash) => {
873 let tap_sighash_msg = cache
874 .taproot_script_spend_signature_hash(idx, &prevouts, leaf_hash, hash_ty)?;
875 Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
876 }
877 None => {
878 let tap_sighash_msg =
879 cache.taproot_key_spend_signature_hash(idx, &prevouts, hash_ty)?;
880 Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
881 }
882 }
883 } else {
884 let hash_ty = inp
885 .sighash_type
886 .map(|sighash_type| sighash_type.ecdsa_hash_ty())
887 .unwrap_or(Ok(sighash::EcdsaSighashType::All))
888 .map_err(|_e| SighashError::InvalidSighashType)?;
889 let amt = finalizer::get_utxo(self, idx)
890 .map_err(|_e| SighashError::MissingInputUtxo)?
891 .value;
892 let is_nested_wpkh = inp_spk.is_p2sh()
893 && inp
894 .redeem_script
895 .as_ref()
896 .map(|x| x.is_v0_p2wpkh())
897 .unwrap_or(false);
898 let is_nested_wsh = inp_spk.is_p2sh()
899 && inp
900 .redeem_script
901 .as_ref()
902 .map(|x| x.is_v0_p2wsh())
903 .unwrap_or(false);
904 if inp_spk.is_v0_p2wpkh() || inp_spk.is_v0_p2wsh() || is_nested_wpkh || is_nested_wsh {
905 let msg = if inp_spk.is_v0_p2wpkh() {
906 let script_code = inp_spk
907 .p2wpkh_script_code()
908 .expect("checked is p2wpkh above");
909 cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
910 } else if is_nested_wpkh {
911 let script_code = inp
912 .redeem_script
913 .as_ref()
914 .expect("redeem script non-empty checked earlier")
915 .p2wpkh_script_code()
916 .expect("checked is p2wpkh above");
917 cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
918 } else {
919 let script_code = inp
921 .witness_script
922 .as_ref()
923 .ok_or(SighashError::MissingWitnessScript)?;
924 cache.segwit_signature_hash(idx, script_code, amt, hash_ty)?
925 };
926 Ok(PsbtSighashMsg::SegwitV0Sighash(msg))
927 } else {
928 let script_code = if inp_spk.is_p2sh() {
930 inp.redeem_script
931 .as_ref()
932 .ok_or(SighashError::MissingRedeemScript)?
933 } else {
934 &inp_spk
935 };
936 let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.to_u32())?;
937 Ok(PsbtSighashMsg::LegacySighash(msg))
938 }
939 }
940 }
941}
942
943pub trait PsbtInputExt {
945 fn update_with_descriptor_unchecked(
962 &mut self,
963 descriptor: &Descriptor<DefiniteDescriptorKey>,
964 ) -> Result<Descriptor<qtum::PublicKey>, descriptor::ConversionError>;
965}
966
967impl PsbtInputExt for psbt::Input {
968 fn update_with_descriptor_unchecked(
969 &mut self,
970 descriptor: &Descriptor<DefiniteDescriptorKey>,
971 ) -> Result<Descriptor<qtum::PublicKey>, descriptor::ConversionError> {
972 let (derived, _) = update_item_with_descriptor_helper(self, descriptor, None)?;
973 Ok(derived)
974 }
975}
976
977pub trait PsbtOutputExt {
979 fn update_with_descriptor_unchecked(
996 &mut self,
997 descriptor: &Descriptor<DefiniteDescriptorKey>,
998 ) -> Result<Descriptor<qtum::PublicKey>, descriptor::ConversionError>;
999}
1000
1001impl PsbtOutputExt for psbt::Output {
1002 fn update_with_descriptor_unchecked(
1003 &mut self,
1004 descriptor: &Descriptor<DefiniteDescriptorKey>,
1005 ) -> Result<Descriptor<qtum::PublicKey>, descriptor::ConversionError> {
1006 let (derived, _) = update_item_with_descriptor_helper(self, descriptor, None)?;
1007 Ok(derived)
1008 }
1009}
1010
1011struct KeySourceLookUp(
1014 pub BTreeMap<secp256k1::PublicKey, bip32::KeySource>,
1015 pub secp256k1::Secp256k1<VerifyOnly>,
1016);
1017
1018impl Translator<DefiniteDescriptorKey, qtum::PublicKey, descriptor::ConversionError>
1019 for KeySourceLookUp
1020{
1021 fn pk(
1022 &mut self,
1023 xpk: &DefiniteDescriptorKey,
1024 ) -> Result<qtum::PublicKey, descriptor::ConversionError> {
1025 let derived = xpk.derive_public_key(&self.1)?;
1026 self.0.insert(
1027 derived.to_public_key().inner,
1028 (
1029 xpk.master_fingerprint(),
1030 xpk.full_derivation_path()
1031 .ok_or(descriptor::ConversionError::MultiKey)?,
1032 ),
1033 );
1034 Ok(derived)
1035 }
1036
1037 translate_hash_clone!(
1038 DescriptorPublicKey,
1039 qtum::PublicKey,
1040 descriptor::ConversionError
1041 );
1042}
1043
1044trait PsbtFields {
1046 fn redeem_script(&mut self) -> &mut Option<ScriptBuf>;
1048 fn witness_script(&mut self) -> &mut Option<ScriptBuf>;
1049 fn bip32_derivation(&mut self) -> &mut BTreeMap<secp256k1::PublicKey, bip32::KeySource>;
1050 fn tap_internal_key(&mut self) -> &mut Option<qtum::key::XOnlyPublicKey>;
1051 fn tap_key_origins(
1052 &mut self,
1053 ) -> &mut BTreeMap<qtum::key::XOnlyPublicKey, (Vec<TapLeafHash>, bip32::KeySource)>;
1054 fn proprietary(&mut self) -> &mut BTreeMap<psbt::raw::ProprietaryKey, Vec<u8>>;
1055 fn unknown(&mut self) -> &mut BTreeMap<psbt::raw::Key, Vec<u8>>;
1056
1057 fn tap_tree(&mut self) -> Option<&mut Option<taproot::TapTree>> {
1059 None
1060 }
1061
1062 fn tap_scripts(&mut self) -> Option<&mut BTreeMap<ControlBlock, (ScriptBuf, LeafVersion)>> {
1064 None
1065 }
1066 fn tap_merkle_root(&mut self) -> Option<&mut Option<taproot::TapNodeHash>> {
1067 None
1068 }
1069}
1070
1071impl PsbtFields for psbt::Input {
1072 fn redeem_script(&mut self) -> &mut Option<ScriptBuf> {
1073 &mut self.redeem_script
1074 }
1075 fn witness_script(&mut self) -> &mut Option<ScriptBuf> {
1076 &mut self.witness_script
1077 }
1078 fn bip32_derivation(&mut self) -> &mut BTreeMap<secp256k1::PublicKey, bip32::KeySource> {
1079 &mut self.bip32_derivation
1080 }
1081 fn tap_internal_key(&mut self) -> &mut Option<qtum::key::XOnlyPublicKey> {
1082 &mut self.tap_internal_key
1083 }
1084 fn tap_key_origins(
1085 &mut self,
1086 ) -> &mut BTreeMap<qtum::key::XOnlyPublicKey, (Vec<TapLeafHash>, bip32::KeySource)> {
1087 &mut self.tap_key_origins
1088 }
1089 fn proprietary(&mut self) -> &mut BTreeMap<psbt::raw::ProprietaryKey, Vec<u8>> {
1090 &mut self.proprietary
1091 }
1092 fn unknown(&mut self) -> &mut BTreeMap<psbt::raw::Key, Vec<u8>> {
1093 &mut self.unknown
1094 }
1095
1096 fn tap_scripts(&mut self) -> Option<&mut BTreeMap<ControlBlock, (ScriptBuf, LeafVersion)>> {
1097 Some(&mut self.tap_scripts)
1098 }
1099 fn tap_merkle_root(&mut self) -> Option<&mut Option<taproot::TapNodeHash>> {
1100 Some(&mut self.tap_merkle_root)
1101 }
1102}
1103
1104impl PsbtFields for psbt::Output {
1105 fn redeem_script(&mut self) -> &mut Option<ScriptBuf> {
1106 &mut self.redeem_script
1107 }
1108 fn witness_script(&mut self) -> &mut Option<ScriptBuf> {
1109 &mut self.witness_script
1110 }
1111 fn bip32_derivation(&mut self) -> &mut BTreeMap<secp256k1::PublicKey, bip32::KeySource> {
1112 &mut self.bip32_derivation
1113 }
1114 fn tap_internal_key(&mut self) -> &mut Option<qtum::key::XOnlyPublicKey> {
1115 &mut self.tap_internal_key
1116 }
1117 fn tap_key_origins(
1118 &mut self,
1119 ) -> &mut BTreeMap<qtum::key::XOnlyPublicKey, (Vec<TapLeafHash>, bip32::KeySource)> {
1120 &mut self.tap_key_origins
1121 }
1122 fn proprietary(&mut self) -> &mut BTreeMap<psbt::raw::ProprietaryKey, Vec<u8>> {
1123 &mut self.proprietary
1124 }
1125 fn unknown(&mut self) -> &mut BTreeMap<psbt::raw::Key, Vec<u8>> {
1126 &mut self.unknown
1127 }
1128
1129 fn tap_tree(&mut self) -> Option<&mut Option<taproot::TapTree>> {
1130 Some(&mut self.tap_tree)
1131 }
1132}
1133
1134fn update_item_with_descriptor_helper<F: PsbtFields>(
1135 item: &mut F,
1136 descriptor: &Descriptor<DefiniteDescriptorKey>,
1137 check_script: Option<&Script>,
1138 ) -> Result<(Descriptor<qtum::PublicKey>, bool), descriptor::ConversionError> {
1142 let secp = secp256k1::Secp256k1::verification_only();
1143
1144 let derived = if let Descriptor::Tr(_) = &descriptor {
1145 let derived = descriptor.derived_descriptor(&secp)?;
1146
1147 if let Some(check_script) = check_script {
1148 if check_script != &derived.script_pubkey() {
1149 return Ok((derived, false));
1150 }
1151 }
1152
1153 if let (Descriptor::Tr(tr_derived), Descriptor::Tr(tr_xpk)) = (&derived, descriptor) {
1155 let spend_info = tr_derived.spend_info();
1156 let ik_derived = spend_info.internal_key();
1157 let ik_xpk = tr_xpk.internal_key();
1158 if let Some(merkle_root) = item.tap_merkle_root() {
1159 *merkle_root = spend_info.merkle_root();
1160 }
1161 *item.tap_internal_key() = Some(ik_derived);
1162 item.tap_key_origins().insert(
1163 ik_derived,
1164 (
1165 vec![],
1166 (
1167 ik_xpk.master_fingerprint(),
1168 ik_xpk
1169 .full_derivation_path()
1170 .ok_or(descriptor::ConversionError::MultiKey)?,
1171 ),
1172 ),
1173 );
1174
1175 let mut builder = taproot::TaprootBuilder::new();
1176
1177 for ((_depth_der, ms_derived), (depth, ms)) in
1178 tr_derived.iter_scripts().zip(tr_xpk.iter_scripts())
1179 {
1180 debug_assert_eq!(_depth_der, depth);
1181 let leaf_script = (ms_derived.encode(), LeafVersion::TapScript);
1182 let tapleaf_hash = TapLeafHash::from_script(&leaf_script.0, leaf_script.1);
1183 builder = builder
1184 .add_leaf(depth, leaf_script.0.clone())
1185 .expect("Computing spend data on a valid tree should always succeed");
1186 if let Some(tap_scripts) = item.tap_scripts() {
1187 let control_block = spend_info
1188 .control_block(&leaf_script)
1189 .expect("Control block must exist in script map for every known leaf");
1190 tap_scripts.insert(control_block, leaf_script);
1191 }
1192
1193 for (pk_pkh_derived, pk_pkh_xpk) in ms_derived.iter_pk().zip(ms.iter_pk()) {
1194 let (xonly, xpk) = (pk_pkh_derived.to_x_only_pubkey(), pk_pkh_xpk);
1195
1196 let xpk_full_derivation_path = xpk
1197 .full_derivation_path()
1198 .ok_or(descriptor::ConversionError::MultiKey)?;
1199 item.tap_key_origins()
1200 .entry(xonly)
1201 .and_modify(|(tapleaf_hashes, _)| {
1202 if tapleaf_hashes.last() != Some(&tapleaf_hash) {
1203 tapleaf_hashes.push(tapleaf_hash);
1204 }
1205 })
1206 .or_insert_with(|| {
1207 (
1208 vec![tapleaf_hash],
1209 (xpk.master_fingerprint(), xpk_full_derivation_path),
1210 )
1211 });
1212 }
1213 }
1214
1215 for (tapleaf_hashes, _) in item.tap_key_origins().values_mut() {
1219 tapleaf_hashes.sort();
1220 tapleaf_hashes.dedup();
1221 }
1222
1223 match item.tap_tree() {
1224 Some(tap_tree) if tr_derived.taptree().is_some() => {
1227 *tap_tree = Some(
1228 taproot::TapTree::try_from(builder)
1229 .expect("The tree should always be valid"),
1230 );
1231 }
1232 _ => {}
1233 }
1234 }
1235
1236 derived
1237 } else {
1238 let mut bip32_derivation = KeySourceLookUp(BTreeMap::new(), Secp256k1::verification_only());
1239 let derived = descriptor
1240 .translate_pk(&mut bip32_derivation)
1241 .map_err(|e| e.expect_translator_err("No Outer Context errors in translations"))?;
1242
1243 if let Some(check_script) = check_script {
1244 if check_script != &derived.script_pubkey() {
1245 return Ok((derived, false));
1246 }
1247 }
1248
1249 item.bip32_derivation().append(&mut bip32_derivation.0);
1250
1251 match &derived {
1252 Descriptor::Bare(_) | Descriptor::Pkh(_) | Descriptor::Wpkh(_) => {}
1253 Descriptor::Sh(sh) => match sh.as_inner() {
1254 descriptor::ShInner::Wsh(wsh) => {
1255 *item.witness_script() = Some(wsh.inner_script());
1256 *item.redeem_script() = Some(wsh.inner_script().to_v0_p2wsh());
1257 }
1258 descriptor::ShInner::Wpkh(..) => *item.redeem_script() = Some(sh.inner_script()),
1259 descriptor::ShInner::SortedMulti(_) | descriptor::ShInner::Ms(_) => {
1260 *item.redeem_script() = Some(sh.inner_script())
1261 }
1262 },
1263 Descriptor::Wsh(wsh) => *item.witness_script() = Some(wsh.inner_script()),
1264 Descriptor::Tr(_) => unreachable!("Tr is dealt with separately"),
1265 }
1266
1267 derived
1268 };
1269
1270 Ok((derived, true))
1271}
1272
1273#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1275pub enum UtxoUpdateError {
1276 IndexOutOfBounds(usize, usize),
1278 MissingInputUtxo,
1280 DerivationError(descriptor::ConversionError),
1282 UtxoCheck,
1284 MismatchedScriptPubkey,
1287}
1288
1289impl fmt::Display for UtxoUpdateError {
1290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1291 match self {
1292 UtxoUpdateError::IndexOutOfBounds(ind, len) => {
1293 write!(f, "index {}, psbt input len: {}", ind, len)
1294 }
1295 UtxoUpdateError::MissingInputUtxo => {
1296 write!(f, "Missing input in unsigned transaction")
1297 }
1298 UtxoUpdateError::DerivationError(e) => write!(f, "Key derivation error {}", e),
1299 UtxoUpdateError::UtxoCheck => write!(
1300 f,
1301 "The input's witness_utxo and/or non_witness_utxo were invalid or missing"
1302 ),
1303 UtxoUpdateError::MismatchedScriptPubkey => {
1304 write!(f, "The input's witness_utxo and/or non_witness_utxo had a script pubkey that didn't match the descriptor")
1305 }
1306 }
1307 }
1308}
1309
1310#[cfg(feature = "std")]
1311impl error::Error for UtxoUpdateError {
1312 fn cause(&self) -> Option<&dyn error::Error> {
1313 use self::UtxoUpdateError::*;
1314
1315 match self {
1316 IndexOutOfBounds(_, _) | MissingInputUtxo | UtxoCheck | MismatchedScriptPubkey => None,
1317 DerivationError(e) => Some(e),
1318 }
1319 }
1320}
1321
1322#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1324pub enum OutputUpdateError {
1325 IndexOutOfBounds(usize, usize),
1327 MissingTxOut,
1329 DerivationError(descriptor::ConversionError),
1331 MismatchedScriptPubkey,
1333}
1334
1335impl fmt::Display for OutputUpdateError {
1336 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1337 match self {
1338 OutputUpdateError::IndexOutOfBounds(ind, len) => {
1339 write!(f, "index {}, psbt output len: {}", ind, len)
1340 }
1341 OutputUpdateError::MissingTxOut => {
1342 write!(f, "Missing txout in the unsigned transaction")
1343 }
1344 OutputUpdateError::DerivationError(e) => write!(f, "Key derivation error {}", e),
1345 OutputUpdateError::MismatchedScriptPubkey => {
1346 write!(f, "The output's script pubkey didn't match the descriptor")
1347 }
1348 }
1349 }
1350}
1351
1352#[cfg(feature = "std")]
1353impl error::Error for OutputUpdateError {
1354 fn cause(&self) -> Option<&dyn error::Error> {
1355 use self::OutputUpdateError::*;
1356
1357 match self {
1358 IndexOutOfBounds(_, _) | MissingTxOut | MismatchedScriptPubkey => None,
1359 DerivationError(e) => Some(e),
1360 }
1361 }
1362}
1363
1364#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1366pub enum SighashError {
1367 IndexOutOfBounds(usize, usize),
1369 MissingInputUtxo,
1371 MissingSpendUtxos,
1373 InvalidSighashType,
1375 SighashComputationError(sighash::Error),
1379 MissingWitnessScript,
1381 MissingRedeemScript,
1383}
1384
1385impl fmt::Display for SighashError {
1386 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1387 match self {
1388 SighashError::IndexOutOfBounds(ind, len) => {
1389 write!(f, "index {}, psbt input len: {}", ind, len)
1390 }
1391 SighashError::MissingInputUtxo => write!(f, "Missing input utxo in pbst"),
1392 SighashError::MissingSpendUtxos => write!(f, "Missing Psbt spend utxos"),
1393 SighashError::InvalidSighashType => write!(f, "Invalid Sighash type"),
1394 SighashError::SighashComputationError(e) => {
1395 write!(f, "Sighash computation error : {}", e)
1396 }
1397 SighashError::MissingWitnessScript => write!(f, "Missing Witness Script"),
1398 SighashError::MissingRedeemScript => write!(f, "Missing Redeem Script"),
1399 }
1400 }
1401}
1402
1403#[cfg(feature = "std")]
1404impl error::Error for SighashError {
1405 fn cause(&self) -> Option<&dyn error::Error> {
1406 use self::SighashError::*;
1407
1408 match self {
1409 IndexOutOfBounds(_, _)
1410 | MissingInputUtxo
1411 | MissingSpendUtxos
1412 | InvalidSighashType
1413 | MissingWitnessScript
1414 | MissingRedeemScript => None,
1415 SighashComputationError(e) => Some(e),
1416 }
1417 }
1418}
1419
1420impl From<sighash::Error> for SighashError {
1421 fn from(e: sighash::Error) -> Self {
1422 SighashError::SighashComputationError(e)
1423 }
1424}
1425
1426#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1428pub enum PsbtSighashMsg {
1429 TapSighash(sighash::TapSighash),
1431 LegacySighash(sighash::LegacySighash),
1433 SegwitV0Sighash(sighash::SegwitV0Sighash),
1435}
1436
1437impl PsbtSighashMsg {
1438 pub fn to_secp_msg(&self) -> secp256k1::Message {
1440 match *self {
1441 PsbtSighashMsg::TapSighash(msg) => {
1442 secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1443 }
1444 PsbtSighashMsg::LegacySighash(msg) => {
1445 secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1446 }
1447 PsbtSighashMsg::SegwitV0Sighash(msg) => {
1448 secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1449 }
1450 }
1451 }
1452}
1453
1454#[cfg(test)]
1455mod tests {
1456 use std::str::FromStr;
1457
1458 use qtum::bip32::{DerivationPath, ExtendedPubKey};
1459 use qtum::consensus::encode::deserialize;
1460 use qtum::hashes::hex::FromHex;
1461 use qtum::key::XOnlyPublicKey;
1462 use qtum::secp256k1::PublicKey;
1463 use qtum::{absolute, OutPoint, TxIn, TxOut};
1464
1465 use super::*;
1466 use crate::Miniscript;
1467
1468 #[test]
1469 fn test_extract_bip174() {
1470 let psbt = qtum::psbt::PartiallySignedTransaction::deserialize(&Vec::<u8>::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap();
1471 let secp = Secp256k1::verification_only();
1472 let tx = psbt.extract(&secp).unwrap();
1473 let expected: qtum::Transaction = deserialize(&Vec::<u8>::from_hex("0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000").unwrap()).unwrap();
1474 assert_eq!(tx, expected);
1475 }
1476
1477 #[test]
1478 fn test_update_item_tr_no_script() {
1479 let root_xpub = ExtendedPubKey::from_str("xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8").unwrap();
1481 let fingerprint = root_xpub.fingerprint();
1482 let desc = format!("tr([{}/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)", fingerprint);
1483 let desc = Descriptor::from_str(&desc).unwrap();
1484 let mut psbt_input = psbt::Input::default();
1485 psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1486 let mut psbt_output = psbt::Output::default();
1487 psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1488 let internal_key = XOnlyPublicKey::from_str(
1489 "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
1490 )
1491 .unwrap();
1492 assert_eq!(psbt_input.tap_internal_key, Some(internal_key));
1493 assert_eq!(
1494 psbt_input.tap_key_origins.get(&internal_key),
1495 Some(&(
1496 vec![],
1497 (
1498 fingerprint,
1499 DerivationPath::from_str("m/86'/0'/0'/0/0").unwrap()
1500 )
1501 ))
1502 );
1503 assert_eq!(psbt_input.tap_key_origins.len(), 1);
1504 assert_eq!(psbt_input.tap_scripts.len(), 0);
1505 assert_eq!(psbt_input.tap_merkle_root, None);
1506
1507 assert_eq!(psbt_output.tap_internal_key, psbt_input.tap_internal_key);
1508 assert_eq!(psbt_output.tap_key_origins, psbt_input.tap_key_origins);
1509 assert_eq!(psbt_output.tap_tree, None);
1510 }
1511
1512 #[test]
1513 fn test_update_item_tr_with_tapscript() {
1514 use crate::Tap;
1515 let root_xpub = ExtendedPubKey::from_str("xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8").unwrap();
1517 let fingerprint = root_xpub.fingerprint();
1518 let xpub = format!("[{}/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ", fingerprint);
1519 let desc = format!(
1520 "tr({}/0/0,{{pkh({}/0/1),multi_a(2,{}/0/1,{}/1/0)}})",
1521 xpub, xpub, xpub, xpub
1522 );
1523
1524 let desc = Descriptor::from_str(&desc).unwrap();
1525 let internal_key = XOnlyPublicKey::from_str(
1526 "cc8a4bc64d897bddc5fbc2f670f7a8ba0b386779106cf1223c6fc5d7cd6fc115",
1527 )
1528 .unwrap();
1529 let mut psbt_input = psbt::Input::default();
1530 psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1531 let mut psbt_output = psbt::Output::default();
1532 psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1533 assert_eq!(psbt_input.tap_internal_key, Some(internal_key));
1534 assert_eq!(
1535 psbt_input.tap_key_origins.get(&internal_key),
1536 Some(&(
1537 vec![],
1538 (
1539 fingerprint,
1540 DerivationPath::from_str("m/86'/0'/0'/0/0").unwrap()
1541 )
1542 ))
1543 );
1544 assert_eq!(psbt_input.tap_key_origins.len(), 3);
1545 assert_eq!(psbt_input.tap_scripts.len(), 2);
1546 assert!(psbt_input.tap_merkle_root.is_some());
1547
1548 assert_eq!(psbt_output.tap_internal_key, psbt_input.tap_internal_key);
1549 assert_eq!(psbt_output.tap_key_origins, psbt_input.tap_key_origins);
1550 assert!(psbt_output.tap_tree.is_some());
1551
1552 let key_0_1 = XOnlyPublicKey::from_str(
1553 "83dfe85a3151d2517290da461fe2815591ef69f2b18a2ce63f01697a8b313145",
1554 )
1555 .unwrap();
1556 let first_leaf_hash = {
1557 let ms =
1558 Miniscript::<XOnlyPublicKey, Tap>::from_str(&format!("pkh({})", &key_0_1)).unwrap();
1559 let first_script = ms.encode();
1560 assert!(psbt_input
1561 .tap_scripts
1562 .values()
1563 .any(|value| *value == (first_script.clone(), LeafVersion::TapScript)));
1564 TapLeafHash::from_script(&first_script, LeafVersion::TapScript)
1565 };
1566
1567 {
1568 let (leaf_hashes, (key_fingerprint, deriv_path)) =
1570 psbt_input.tap_key_origins.get(&key_0_1).unwrap();
1571 assert_eq!(key_fingerprint, &fingerprint);
1572 assert_eq!(&deriv_path.to_string(), "m/86'/0'/0'/0/1");
1573 assert_eq!(leaf_hashes.len(), 2);
1574 assert!(leaf_hashes.contains(&first_leaf_hash));
1575 }
1576
1577 {
1578 let key_1_0 = XOnlyPublicKey::from_str(
1580 "399f1b2f4393f29a18c937859c5dd8a77350103157eb880f02e8c08214277cef",
1581 )
1582 .unwrap();
1583 let (leaf_hashes, (key_fingerprint, deriv_path)) =
1584 psbt_input.tap_key_origins.get(&key_1_0).unwrap();
1585 assert_eq!(key_fingerprint, &fingerprint);
1586 assert_eq!(&deriv_path.to_string(), "m/86'/0'/0'/1/0");
1587 assert_eq!(leaf_hashes.len(), 1);
1588 assert!(!leaf_hashes.contains(&first_leaf_hash));
1589 }
1590 }
1591
1592 #[test]
1593 fn test_update_item_non_tr_multi() {
1594 let root_xpub = ExtendedPubKey::from_str("xpub661MyMwAqRbcFkPHucMnrGNzDwb6teAX1RbKQmqtEF8kK3Z7LZ59qafCjB9eCRLiTVG3uxBxgKvRgbubRhqSKXnGGb1aoaqLrpMBDrVxga8").unwrap();
1596 let fingerprint = root_xpub.fingerprint();
1597 let xpub = format!("[{}/84'/0'/0']xpub6CatWdiZiodmUeTDp8LT5or8nmbKNcuyvz7WyksVFkKB4RHwCD3XyuvPEbvqAQY3rAPshWcMLoP2fMFMKHPJ4ZeZXYVUhLv1VMrjPC7PW6V", fingerprint);
1598 let pubkeys = [
1599 "0330d54fd0dd420a6e5f8d3624f5f3482cae350f79d5f0753bf5beef9c2d91af3c",
1600 "03e775fd51f0dfb8cd865d9ff1cca2a158cf651fe997fdc9fee9c1d3b5e995ea77",
1601 "03025324888e429ab8e3dbaf1f7802648b9cd01e9b418485c5fa4c1b9b5700e1a6",
1602 ];
1603
1604 let expected_bip32 = pubkeys
1605 .iter()
1606 .zip(["0/0", "0/1", "1/0"].iter())
1607 .map(|(pubkey, path)| {
1608 (
1609 PublicKey::from_str(pubkey).unwrap(),
1610 (
1611 fingerprint,
1612 DerivationPath::from_str(&format!("m/84'/0'/0'/{}", path)).unwrap(),
1613 ),
1614 )
1615 })
1616 .collect::<BTreeMap<_, _>>();
1617
1618 {
1619 let desc = format!("wsh(multi(2,{}/0/0,{}/0/1,{}/1/0))", xpub, xpub, xpub);
1621 let desc = Descriptor::from_str(&desc).unwrap();
1622 let derived = format!("wsh(multi(2,{}))", pubkeys.join(","));
1623 let derived = Descriptor::<qtum::PublicKey>::from_str(&derived).unwrap();
1624
1625 let mut psbt_input = psbt::Input::default();
1626 psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1627
1628 let mut psbt_output = psbt::Output::default();
1629 psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1630
1631 assert_eq!(expected_bip32, psbt_input.bip32_derivation);
1632 assert_eq!(
1633 psbt_input.witness_script,
1634 Some(derived.explicit_script().unwrap())
1635 );
1636
1637 assert_eq!(psbt_output.bip32_derivation, psbt_input.bip32_derivation);
1638 assert_eq!(psbt_output.witness_script, psbt_input.witness_script);
1639 }
1640
1641 {
1642 let desc = format!("sh(multi(2,{}/0/0,{}/0/1,{}/1/0))", xpub, xpub, xpub);
1644 let desc = Descriptor::from_str(&desc).unwrap();
1645 let derived = format!("sh(multi(2,{}))", pubkeys.join(","));
1646 let derived = Descriptor::<qtum::PublicKey>::from_str(&derived).unwrap();
1647
1648 let mut psbt_input = psbt::Input::default();
1649 psbt_input.update_with_descriptor_unchecked(&desc).unwrap();
1650
1651 let mut psbt_output = psbt::Output::default();
1652 psbt_output.update_with_descriptor_unchecked(&desc).unwrap();
1653
1654 assert_eq!(psbt_input.bip32_derivation, expected_bip32);
1655 assert_eq!(psbt_input.witness_script, None);
1656 assert_eq!(
1657 psbt_input.redeem_script,
1658 Some(derived.explicit_script().unwrap())
1659 );
1660
1661 assert_eq!(psbt_output.bip32_derivation, psbt_input.bip32_derivation);
1662 assert_eq!(psbt_output.witness_script, psbt_input.witness_script);
1663 assert_eq!(psbt_output.redeem_script, psbt_input.redeem_script);
1664 }
1665 }
1666
1667 #[test]
1668 fn test_update_input_checks() {
1669 let desc = "tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)";
1670 let desc = Descriptor::<DefiniteDescriptorKey>::from_str(&desc).unwrap();
1671
1672 let mut non_witness_utxo = qtum::Transaction {
1673 version: 1,
1674 lock_time: absolute::LockTime::ZERO,
1675 input: vec![],
1676 output: vec![TxOut {
1677 value: 1_000,
1678 script_pubkey: ScriptBuf::from_hex(
1679 "5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c",
1680 )
1681 .unwrap(),
1682 }],
1683 };
1684
1685 let tx = qtum::Transaction {
1686 version: 1,
1687 lock_time: absolute::LockTime::ZERO,
1688 input: vec![TxIn {
1689 previous_output: OutPoint {
1690 txid: non_witness_utxo.txid(),
1691 vout: 0,
1692 },
1693 ..Default::default()
1694 }],
1695 output: vec![],
1696 };
1697
1698 let mut psbt = Psbt::from_unsigned_tx(tx).unwrap();
1699 assert_eq!(
1700 psbt.update_input_with_descriptor(0, &desc),
1701 Err(UtxoUpdateError::UtxoCheck),
1702 "neither *_utxo are not set"
1703 );
1704 psbt.inputs[0].witness_utxo = Some(non_witness_utxo.output[0].clone());
1705 assert_eq!(
1706 psbt.update_input_with_descriptor(0, &desc),
1707 Ok(()),
1708 "witness_utxo is set which is ok"
1709 );
1710 psbt.inputs[0].non_witness_utxo = Some(non_witness_utxo.clone());
1711 assert_eq!(
1712 psbt.update_input_with_descriptor(0, &desc),
1713 Ok(()),
1714 "matching non_witness_utxo"
1715 );
1716 non_witness_utxo.version = 0;
1717 psbt.inputs[0].non_witness_utxo = Some(non_witness_utxo);
1718 assert_eq!(
1719 psbt.update_input_with_descriptor(0, &desc),
1720 Err(UtxoUpdateError::UtxoCheck),
1721 "non_witness_utxo no longer matches"
1722 );
1723 psbt.inputs[0].non_witness_utxo = None;
1724 psbt.inputs[0].witness_utxo.as_mut().unwrap().script_pubkey = ScriptBuf::default();
1725 assert_eq!(
1726 psbt.update_input_with_descriptor(0, &desc),
1727 Err(UtxoUpdateError::MismatchedScriptPubkey),
1728 "non_witness_utxo no longer matches"
1729 );
1730 }
1731
1732 #[test]
1733 fn test_update_output_checks() {
1734 let desc = "tr([73c5da0a/86'/0'/0']xpub6BgBgsespWvERF3LHQu6CnqdvfEvtMcQjYrcRzx53QJjSxarj2afYWcLteoGVky7D3UKDP9QyrLprQ3VCECoY49yfdDEHGCtMMj92pReUsQ/0/0)";
1735 let desc = Descriptor::<DefiniteDescriptorKey>::from_str(&desc).unwrap();
1736
1737 let tx = qtum::Transaction {
1738 version: 1,
1739 lock_time: absolute::LockTime::ZERO,
1740 input: vec![],
1741 output: vec![TxOut {
1742 value: 1_000,
1743 script_pubkey: ScriptBuf::from_hex(
1744 "5120a60869f0dbcf1dc659c9cecbaf8050135ea9e8cdc487053f1dc6880949dc684c",
1745 )
1746 .unwrap(),
1747 }],
1748 };
1749
1750 let mut psbt = Psbt::from_unsigned_tx(tx).unwrap();
1751 assert_eq!(
1752 psbt.update_output_with_descriptor(1, &desc),
1753 Err(OutputUpdateError::IndexOutOfBounds(1, 1)),
1754 "output index doesn't exist"
1755 );
1756 assert_eq!(
1757 psbt.update_output_with_descriptor(0, &desc),
1758 Ok(()),
1759 "script_pubkey should match"
1760 );
1761 psbt.unsigned_tx.output[0].script_pubkey = ScriptBuf::default();
1762 assert_eq!(
1763 psbt.update_output_with_descriptor(0, &desc),
1764 Err(OutputUpdateError::MismatchedScriptPubkey),
1765 "output script_pubkey no longer matches"
1766 );
1767 }
1768}