1use std::collections::BTreeMap;
23use std::ops::{Deref, Range};
24use std::{error, fmt};
25
26use bitcoin::consensus::Encodable;
27use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash};
28use bitcoin::secp256k1::{self, Secp256k1};
29use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
30use bitcoin::util::sighash::SighashCache;
31use bitcoin::{self, SchnorrSighashType};
32use bitcoin::{EcdsaSighashType, Script};
33
34use bitcoin::util::taproot::{self, ControlBlock, LeafVersion, TapLeafHash};
35use descriptor;
36use interpreter;
37use miniscript::limits::SEQUENCE_LOCKTIME_DISABLE_FLAG;
38use miniscript::satisfy::{After, Older};
39use Preimage32;
40use Satisfier;
41use {Descriptor, DescriptorPublicKey, DescriptorTrait, MiniscriptKey, ToPublicKey};
42
43mod finalizer;
44
45#[allow(deprecated)]
46pub use self::finalizer::{finalize, finalize_mall, interpreter_check};
47
48#[derive(Debug)]
50pub enum InputError {
51 SecpErr(bitcoin::secp256k1::Error),
53 KeyErr(bitcoin::util::key::Error),
55 CouldNotSatisfyTr,
60 Interpreter(interpreter::Error),
62 InvalidRedeemScript {
64 redeem: Script,
66 p2sh_expected: Script,
68 },
69 InvalidWitnessScript {
71 witness_script: Script,
73 p2wsh_expected: Script,
75 },
76 InvalidSignature {
78 pubkey: bitcoin::PublicKey,
80 sig: Vec<u8>,
82 },
83 MiniscriptError(super::Error),
85 MissingRedeemScript,
87 MissingWitness,
89 MissingPubkey,
91 MissingWitnessScript,
93 MissingUtxo,
95 NonEmptyWitnessScript,
97 NonEmptyRedeemScript,
99 NonStandardSighashType(bitcoin::blockdata::transaction::NonStandardSighashType),
101 WrongSighashFlag {
103 required: bitcoin::EcdsaSighashType,
105 got: bitcoin::EcdsaSighashType,
107 pubkey: bitcoin::PublicKey,
109 },
110}
111
112#[derive(Debug)]
114pub enum Error {
115 InputError(InputError, usize),
117 WrongInputCount {
119 in_tx: usize,
121 in_map: usize,
123 },
124 InputIdxOutofBounds {
126 psbt_inp: usize,
128 index: usize,
130 },
131}
132
133impl fmt::Display for InputError {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 match *self {
136 InputError::InvalidSignature {
137 ref pubkey,
138 ref sig,
139 } => write!(f, "PSBT: bad signature {} for key {:?}", pubkey, sig),
140 InputError::KeyErr(ref e) => write!(f, "Key Err: {}", e),
141 InputError::Interpreter(ref e) => write!(f, "Interpreter: {}", e),
142 InputError::SecpErr(ref e) => write!(f, "Secp Err: {}", e),
143 InputError::InvalidRedeemScript {
144 ref redeem,
145 ref p2sh_expected,
146 } => write!(
147 f,
148 "Redeem script {} does not match the p2sh script {}",
149 redeem, p2sh_expected
150 ),
151 InputError::InvalidWitnessScript {
152 ref witness_script,
153 ref p2wsh_expected,
154 } => write!(
155 f,
156 "Witness script {} does not match the p2wsh script {}",
157 witness_script, p2wsh_expected
158 ),
159 InputError::MiniscriptError(ref e) => write!(f, "Miniscript Error: {}", e),
160 InputError::MissingWitness => write!(f, "PSBT is missing witness"),
161 InputError::MissingRedeemScript => write!(f, "PSBT is Redeem script"),
162 InputError::MissingUtxo => {
163 write!(f, "PSBT is missing both witness and non-witness UTXO")
164 }
165 InputError::MissingWitnessScript => write!(f, "PSBT is missing witness script"),
166 InputError::MissingPubkey => write!(f, "Missing pubkey for a pkh/wpkh"),
167 InputError::NonEmptyRedeemScript => write!(
168 f,
169 "PSBT has non-empty redeem script at for legacy transactions"
170 ),
171 InputError::NonEmptyWitnessScript => {
172 write!(f, "PSBT has non-empty witness script at for legacy input")
173 }
174 InputError::WrongSighashFlag {
175 required,
176 got,
177 pubkey,
178 } => write!(
179 f,
180 "PSBT: signature with key {:?} had \
181 sighashflag {:?} rather than required {:?}",
182 pubkey, got, required
183 ),
184 InputError::CouldNotSatisfyTr => {
185 write!(f, "Could not satisfy Tr descriptor")
186 }
187 InputError::NonStandardSighashType(e) => write!(f, "Non-standard sighash type {}", e),
188 }
189 }
190}
191
192#[doc(hidden)]
193impl From<super::Error> for InputError {
194 fn from(e: super::Error) -> InputError {
195 InputError::MiniscriptError(e)
196 }
197}
198
199#[doc(hidden)]
200impl From<bitcoin::secp256k1::Error> for InputError {
201 fn from(e: bitcoin::secp256k1::Error) -> InputError {
202 InputError::SecpErr(e)
203 }
204}
205
206#[doc(hidden)]
207impl From<bitcoin::util::key::Error> for InputError {
208 fn from(e: bitcoin::util::key::Error) -> InputError {
209 InputError::KeyErr(e)
210 }
211}
212
213impl error::Error for Error {}
214
215impl fmt::Display for Error {
216 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
217 match *self {
218 Error::InputError(ref inp_err, index) => write!(f, "{} at index {}", inp_err, index),
219 Error::WrongInputCount { in_tx, in_map } => write!(
220 f,
221 "PSBT had {} inputs in transaction but {} inputs in map",
222 in_tx, in_map
223 ),
224 Error::InputIdxOutofBounds { psbt_inp, index } => write!(
225 f,
226 "psbt input index {} out of bounds: psbt.inputs.len() {}",
227 index, psbt_inp
228 ),
229 }
230 }
231}
232
233pub struct PsbtInputSatisfier<'psbt> {
239 pub psbt: &'psbt Psbt,
241 pub index: usize,
243}
244
245impl<'psbt> PsbtInputSatisfier<'psbt> {
246 pub fn new(psbt: &'psbt Psbt, index: usize) -> Self {
249 Self {
250 psbt: psbt,
251 index: index,
252 }
253 }
254}
255
256impl<'psbt, Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for PsbtInputSatisfier<'psbt> {
257 fn lookup_tap_key_spend_sig(&self) -> Option<bitcoin::SchnorrSig> {
258 self.psbt.inputs[self.index].tap_key_sig
259 }
260
261 fn lookup_tap_leaf_script_sig(&self, pk: &Pk, lh: &TapLeafHash) -> Option<bitcoin::SchnorrSig> {
262 self.psbt.inputs[self.index]
263 .tap_script_sigs
264 .get(&(pk.to_x_only_pubkey(), *lh))
265 .map(|x| *x) }
267
268 fn lookup_tap_control_block_map(
269 &self,
270 ) -> Option<&BTreeMap<ControlBlock, (bitcoin::Script, LeafVersion)>> {
271 Some(&self.psbt.inputs[self.index].tap_scripts)
272 }
273
274 fn lookup_pkh_tap_leaf_script_sig(
275 &self,
276 pkh: &(Pk::Hash, TapLeafHash),
277 ) -> Option<(bitcoin::secp256k1::XOnlyPublicKey, bitcoin::SchnorrSig)> {
278 self.psbt.inputs[self.index]
279 .tap_script_sigs
280 .iter()
281 .filter(|&((pubkey, lh), _sig)| {
282 pubkey.to_pubkeyhash() == Pk::hash_to_hash160(&pkh.0) && *lh == pkh.1
283 })
284 .next()
285 .map(|((x_only_pk, _leaf_hash), sig)| (*x_only_pk, *sig))
286 }
287
288 fn lookup_ecdsa_sig(&self, pk: &Pk) -> Option<bitcoin::EcdsaSig> {
289 self.psbt.inputs[self.index]
290 .partial_sigs
291 .get(&pk.to_public_key())
292 .map(|sig| *sig)
293 }
294
295 fn lookup_pkh_ecdsa_sig(
296 &self,
297 pkh: &Pk::Hash,
298 ) -> Option<(bitcoin::PublicKey, bitcoin::EcdsaSig)> {
299 self.psbt.inputs[self.index]
300 .partial_sigs
301 .iter()
302 .filter(|&(pubkey, _sig)| pubkey.to_pubkeyhash() == Pk::hash_to_hash160(pkh))
303 .next()
304 .map(|(pk, sig)| (*pk, *sig))
305 }
306
307 fn check_after(&self, n: u32) -> bool {
308 let locktime = self.psbt.unsigned_tx.lock_time;
309 let seq = self.psbt.unsigned_tx.input[self.index].sequence;
310
311 if seq == 0xffffffff {
314 false
315 } else {
316 <dyn Satisfier<Pk>>::check_after(&After(locktime), n)
317 }
318 }
319
320 fn check_older(&self, n: u32) -> bool {
321 let seq = self.psbt.unsigned_tx.input[self.index].sequence;
322 if n & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
325 true
326 } else if self.psbt.unsigned_tx.version < 2 || (seq & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0) {
327 false
329 } else {
330 <dyn Satisfier<Pk>>::check_older(&Older(seq), n)
331 }
332 }
333
334 fn lookup_hash160(&self, h: hash160::Hash) -> Option<Preimage32> {
335 self.psbt.inputs[self.index]
336 .hash160_preimages
337 .get(&h)
338 .and_then(try_vec_as_preimage32)
339 }
340
341 fn lookup_sha256(&self, h: sha256::Hash) -> Option<Preimage32> {
342 self.psbt.inputs[self.index]
343 .sha256_preimages
344 .get(&h)
345 .and_then(try_vec_as_preimage32)
346 }
347
348 fn lookup_hash256(&self, h: sha256d::Hash) -> Option<Preimage32> {
349 self.psbt.inputs[self.index]
350 .hash256_preimages
351 .get(&h)
352 .and_then(try_vec_as_preimage32)
353 }
354
355 fn lookup_ripemd160(&self, h: ripemd160::Hash) -> Option<Preimage32> {
356 self.psbt.inputs[self.index]
357 .ripemd160_preimages
358 .get(&h)
359 .and_then(try_vec_as_preimage32)
360 }
361
362 fn check_tx_template(&self, h: sha256::Hash) -> bool {
363 get_ctv_hash(&self.psbt.clone().extract_tx(), self.index as u32) == h
365 }
366}
367
368pub(crate) fn get_ctv_hash(tx: &bitcoin::Transaction, input_index: u32) -> sha256::Hash {
369 let mut ctv_hash = sha256::Hash::engine();
370 tx.version.consensus_encode(&mut ctv_hash).unwrap();
371 tx.lock_time.consensus_encode(&mut ctv_hash).unwrap();
372 (tx.input.len() as u32)
373 .consensus_encode(&mut ctv_hash)
374 .unwrap();
375 {
376 let mut enc = sha256::Hash::engine();
377 for seq in tx.input.iter().map(|i| i.sequence) {
378 seq.consensus_encode(&mut enc).unwrap();
379 }
380 sha256::Hash::from_engine(enc)
381 .into_inner()
382 .consensus_encode(&mut ctv_hash)
383 .unwrap();
384 }
385
386 (tx.output.len() as u32)
387 .consensus_encode(&mut ctv_hash)
388 .unwrap();
389
390 {
391 let mut enc = sha256::Hash::engine();
392 for out in tx.output.iter() {
393 out.consensus_encode(&mut enc).unwrap();
394 }
395 sha256::Hash::from_engine(enc)
396 .into_inner()
397 .consensus_encode(&mut ctv_hash)
398 .unwrap();
399 }
400 input_index.consensus_encode(&mut ctv_hash).unwrap();
401 sha256::Hash::from_engine(ctv_hash)
402}
403fn try_vec_as_preimage32(vec: &Vec<u8>) -> Option<Preimage32> {
404 if vec.len() == 32 {
405 let mut arr = [0u8; 32];
406 arr.copy_from_slice(&vec);
407 Some(arr)
408 } else {
409 None
410 }
411}
412
413fn sanity_check(psbt: &Psbt) -> Result<(), Error> {
417 if psbt.unsigned_tx.input.len() != psbt.inputs.len() {
418 return Err(Error::WrongInputCount {
419 in_tx: psbt.unsigned_tx.input.len(),
420 in_map: psbt.inputs.len(),
421 }
422 .into());
423 }
424
425 for (index, input) in psbt.inputs.iter().enumerate() {
427 let target_ecdsa_sighash_ty = match input.sighash_type {
429 Some(psbt_hash_ty) => psbt_hash_ty
430 .ecdsa_hash_ty()
431 .map_err(|e| Error::InputError(InputError::NonStandardSighashType(e), index))?,
432 None => EcdsaSighashType::All,
433 };
434 for (key, ecdsa_sig) in &input.partial_sigs {
435 let flag = bitcoin::EcdsaSighashType::from_standard(ecdsa_sig.hash_ty as u32).map_err(
436 |_| {
437 Error::InputError(
438 InputError::Interpreter(interpreter::Error::NonStandardSighash(
439 ecdsa_sig.to_vec(),
440 )),
441 index,
442 )
443 },
444 )?;
445 if target_ecdsa_sighash_ty != flag {
446 return Err(Error::InputError(
447 InputError::WrongSighashFlag {
448 required: target_ecdsa_sighash_ty,
449 got: flag,
450 pubkey: *key,
451 },
452 index,
453 ));
454 }
455 }
457 }
458
459 Ok(())
460}
461
462pub trait PsbtExt {
466 fn finalize_mut<C: secp256k1::Verification>(
483 &mut self,
484 secp: &secp256k1::Secp256k1<C>,
485 ) -> Result<(), Vec<Error>>;
486
487 fn finalize<C: secp256k1::Verification>(
495 self,
496 secp: &secp256k1::Secp256k1<C>,
497 ) -> Result<Psbt, (Psbt, Vec<Error>)>;
498
499 fn finalize_mall_mut<C: secp256k1::Verification>(
501 &mut self,
502 secp: &Secp256k1<C>,
503 ) -> Result<(), Vec<Error>>;
504
505 fn finalize_mall<C: secp256k1::Verification>(
507 self,
508 secp: &Secp256k1<C>,
509 ) -> Result<Psbt, (Psbt, Vec<Error>)>;
510
511 fn finalize_inp_mut<C: secp256k1::Verification>(
519 &mut self,
520 secp: &secp256k1::Secp256k1<C>,
521 index: usize,
522 ) -> Result<(), Error>;
523
524 fn finalize_inp<C: secp256k1::Verification>(
531 self,
532 secp: &secp256k1::Secp256k1<C>,
533 index: usize,
534 ) -> Result<Psbt, (Psbt, Error)>;
535
536 fn finalize_inp_mall_mut<C: secp256k1::Verification>(
538 &mut self,
539 secp: &secp256k1::Secp256k1<C>,
540 index: usize,
541 ) -> Result<(), Error>;
542
543 fn finalize_inp_mall<C: secp256k1::Verification>(
545 self,
546 secp: &secp256k1::Secp256k1<C>,
547 index: usize,
548 ) -> Result<Psbt, (Psbt, Error)>;
549
550 fn extract<C: secp256k1::Verification>(
556 &self,
557 secp: &Secp256k1<C>,
558 ) -> Result<bitcoin::Transaction, Error>;
559
560 fn update_desc(
574 &mut self,
575 input_index: usize,
576 desc: &Descriptor<DescriptorPublicKey>,
577 range: Option<Range<u32>>,
578 ) -> Result<(), UxtoUpdateError>;
579
580 fn sighash_msg<T: Deref<Target = bitcoin::Transaction>>(
597 &self,
598 idx: usize,
599 cache: &mut SighashCache<T>,
600 tapleaf_hash: Option<TapLeafHash>,
601 ) -> Result<PsbtSighashMsg, SighashError>;
602}
603
604impl PsbtExt for Psbt {
605 fn finalize_mut<C: secp256k1::Verification>(
606 &mut self,
607 secp: &secp256k1::Secp256k1<C>,
608 ) -> Result<(), Vec<Error>> {
609 let mut errors = vec![];
611 for index in 0..self.inputs.len() {
612 match finalizer::finalize_input(self, index, secp, false) {
613 Ok(..) => {}
614 Err(e) => {
615 errors.push(e);
616 }
617 }
618 }
619 if errors.is_empty() {
620 Ok(())
621 } else {
622 Err(errors)
623 }
624 }
625
626 fn finalize<C: secp256k1::Verification>(
627 mut self,
628 secp: &secp256k1::Secp256k1<C>,
629 ) -> Result<Psbt, (Psbt, Vec<Error>)> {
630 match self.finalize_mut(secp) {
631 Ok(..) => Ok(self),
632 Err(e) => Err((self, e)),
633 }
634 }
635
636 fn finalize_mall_mut<C: secp256k1::Verification>(
637 &mut self,
638 secp: &secp256k1::Secp256k1<C>,
639 ) -> Result<(), Vec<Error>> {
640 let mut errors = vec![];
641 for index in 0..self.inputs.len() {
642 match finalizer::finalize_input(self, index, secp, true) {
643 Ok(..) => {}
644 Err(e) => {
645 errors.push(e);
646 }
647 }
648 }
649 if errors.is_empty() {
650 Ok(())
651 } else {
652 Err(errors)
653 }
654 }
655
656 fn finalize_mall<C: secp256k1::Verification>(
657 mut self,
658 secp: &Secp256k1<C>,
659 ) -> Result<Psbt, (Psbt, Vec<Error>)> {
660 match self.finalize_mall_mut(secp) {
661 Ok(..) => Ok(self),
662 Err(e) => Err((self, e)),
663 }
664 }
665
666 fn finalize_inp_mut<C: secp256k1::Verification>(
667 &mut self,
668 secp: &secp256k1::Secp256k1<C>,
669 index: usize,
670 ) -> Result<(), Error> {
671 if index >= self.inputs.len() {
672 return Err(Error::InputIdxOutofBounds {
673 psbt_inp: self.inputs.len(),
674 index: index,
675 });
676 }
677 finalizer::finalize_input(self, index, secp, false)
678 }
679
680 fn finalize_inp<C: secp256k1::Verification>(
681 mut self,
682 secp: &secp256k1::Secp256k1<C>,
683 index: usize,
684 ) -> Result<Psbt, (Psbt, Error)> {
685 match self.finalize_inp_mut(secp, index) {
686 Ok(..) => Ok(self),
687 Err(e) => Err((self, e)),
688 }
689 }
690
691 fn finalize_inp_mall_mut<C: secp256k1::Verification>(
692 &mut self,
693 secp: &secp256k1::Secp256k1<C>,
694 index: usize,
695 ) -> Result<(), Error> {
696 if index >= self.inputs.len() {
697 return Err(Error::InputIdxOutofBounds {
698 psbt_inp: self.inputs.len(),
699 index: index,
700 });
701 }
702 finalizer::finalize_input(self, index, secp, false)
703 }
704
705 fn finalize_inp_mall<C: secp256k1::Verification>(
706 mut self,
707 secp: &secp256k1::Secp256k1<C>,
708 index: usize,
709 ) -> Result<Psbt, (Psbt, Error)> {
710 match self.finalize_inp_mall_mut(secp, index) {
711 Ok(..) => Ok(self),
712 Err(e) => Err((self, e)),
713 }
714 }
715
716 fn extract<C: secp256k1::Verification>(
717 &self,
718 secp: &Secp256k1<C>,
719 ) -> Result<bitcoin::Transaction, Error> {
720 sanity_check(self)?;
721
722 let mut ret = self.unsigned_tx.clone();
723 for (n, input) in self.inputs.iter().enumerate() {
724 if input.final_script_sig.is_none() && input.final_script_witness.is_none() {
725 return Err(Error::InputError(InputError::MissingWitness, n));
726 }
727
728 if let Some(witness) = input.final_script_witness.as_ref() {
729 ret.input[n].witness = witness.clone();
730 }
731 if let Some(script_sig) = input.final_script_sig.as_ref() {
732 ret.input[n].script_sig = script_sig.clone();
733 }
734 }
735 interpreter_check(self, secp)?;
736 Ok(ret)
737 }
738
739 fn update_desc(
740 &mut self,
741 input_index: usize,
742 desc: &Descriptor<DescriptorPublicKey>,
743 range: Option<Range<u32>>,
744 ) -> Result<(), UxtoUpdateError> {
745 if input_index >= self.inputs.len() {
746 return Err(UxtoUpdateError::IndexOutOfBounds(
747 input_index,
748 self.inputs.len(),
749 ));
750 }
751 let mut derived_desc = None;
752 {
754 let inp_spk = finalizer::get_scriptpubkey(self, input_index)
755 .map_err(|_e| UxtoUpdateError::MissingInputUxto)?;
756 let secp = secp256k1::Secp256k1::verification_only();
757
758 match range {
759 None => {
760 if desc.is_deriveable() {
761 return Err(UxtoUpdateError::RangeMissingWildCardDescriptor);
762 } else {
763 derived_desc = desc
764 .derived_descriptor(&secp, 0)
765 .map_err(|e| UxtoUpdateError::DerivationError(e))
766 .ok();
767 }
768 }
769 Some(range) => {
770 for i in range {
771 let derived = desc
772 .derived_descriptor(&secp, i)
773 .map_err(|e| UxtoUpdateError::DerivationError(e))?;
774 if &derived.script_pubkey() == inp_spk {
775 derived_desc = Some(derived);
776 break;
777 }
778 }
779 }
780 }
781 }
782 let inp = &mut self.inputs[input_index];
783 let derived_desc = derived_desc.ok_or(UxtoUpdateError::IncorrectDescriptor)?;
784 match derived_desc {
785 Descriptor::Bare(_) | Descriptor::Pkh(_) | Descriptor::Wpkh(_) => {}
786 Descriptor::Sh(sh) => match sh.as_inner() {
787 descriptor::ShInner::Wsh(wsh) => {
788 inp.witness_script = Some(wsh.inner_script());
789 inp.redeem_script = Some(wsh.inner_script().to_v0_p2wsh());
790 }
791 descriptor::ShInner::Wpkh(..) => inp.redeem_script = Some(sh.inner_script()),
792 descriptor::ShInner::SortedMulti(_) | descriptor::ShInner::Ms(_) => {
793 inp.redeem_script = Some(sh.inner_script())
794 }
795 },
796 Descriptor::Wsh(wsh) => inp.witness_script = Some(wsh.inner_script()),
797 Descriptor::Tr(tr) => {
798 let spend_info = tr.spend_info();
799 inp.tap_internal_key = Some(spend_info.internal_key());
800 inp.tap_merkle_root = spend_info.merkle_root();
801 for (_depth, ms) in tr.iter_scripts() {
802 let leaf_script = (ms.encode(), LeafVersion::TapScript);
803 let control_block = spend_info
804 .control_block(&leaf_script)
805 .expect("Control block must exist in script map for every known leaf");
806 inp.tap_scripts.insert(control_block, leaf_script);
807 }
808 }
809 };
810 Ok(())
811 }
812
813 fn sighash_msg<T: Deref<Target = bitcoin::Transaction>>(
814 &self,
815 idx: usize,
816 cache: &mut SighashCache<T>,
817 tapleaf_hash: Option<TapLeafHash>,
818 ) -> Result<PsbtSighashMsg, SighashError> {
819 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 let prevouts = bitcoin::util::sighash::Prevouts::All(&prevouts);
828 let inp_spk =
829 finalizer::get_scriptpubkey(self, idx).map_err(|_e| SighashError::MissingInputUxto)?;
830 if inp_spk.is_v1_p2tr() {
831 let hash_ty = inp
832 .sighash_type
833 .map(|sighash_type| sighash_type.schnorr_hash_ty())
834 .unwrap_or(Ok(SchnorrSighashType::Default))
835 .map_err(|_e| SighashError::InvalidSighashType)?;
836 match tapleaf_hash {
837 Some(leaf_hash) => {
838 let tap_sighash_msg = cache
839 .taproot_script_spend_signature_hash(idx, &prevouts, leaf_hash, hash_ty)?;
840 Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
841 }
842 None => {
843 let tap_sighash_msg =
844 cache.taproot_key_spend_signature_hash(idx, &prevouts, hash_ty)?;
845 Ok(PsbtSighashMsg::TapSighash(tap_sighash_msg))
846 }
847 }
848 } else {
849 let hash_ty = inp
850 .sighash_type
851 .map(|sighash_type| sighash_type.ecdsa_hash_ty())
852 .unwrap_or(Ok(EcdsaSighashType::All))
853 .map_err(|_e| SighashError::InvalidSighashType)?;
854 let amt = finalizer::get_utxo(self, idx)
855 .map_err(|_e| SighashError::MissingInputUxto)?
856 .value;
857 let is_nested_wpkh = inp_spk.is_p2sh()
858 && inp
859 .redeem_script
860 .as_ref()
861 .map(|x| x.is_v0_p2wpkh())
862 .unwrap_or(false);
863 let is_nested_wsh = inp_spk.is_p2sh()
864 && inp
865 .redeem_script
866 .as_ref()
867 .map(|x| x.is_v0_p2wsh())
868 .unwrap_or(false);
869 if inp_spk.is_v0_p2wpkh() || inp_spk.is_v0_p2wsh() || is_nested_wpkh || is_nested_wsh {
870 let msg = if inp_spk.is_v0_p2wpkh() {
871 let script_code = script_code_wpkh(&inp_spk);
872 cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
873 } else if is_nested_wpkh {
874 let script_code = script_code_wpkh(
875 inp.redeem_script
876 .as_ref()
877 .expect("Redeem script non-empty checked earlier"),
878 );
879 cache.segwit_signature_hash(idx, &script_code, amt, hash_ty)?
880 } else {
881 let script_code = inp
883 .witness_script
884 .as_ref()
885 .ok_or(SighashError::MissingWitnessScript)?;
886 cache.segwit_signature_hash(idx, script_code, amt, hash_ty)?
887 };
888 Ok(PsbtSighashMsg::EcdsaSighash(msg))
889 } else {
890 let script_code = if inp_spk.is_p2sh() {
892 &inp.redeem_script
893 .as_ref()
894 .ok_or(SighashError::MissingRedeemScript)?
895 } else {
896 inp_spk
897 };
898 let msg = cache.legacy_signature_hash(idx, script_code, hash_ty.to_u32())?;
899 Ok(PsbtSighashMsg::EcdsaSighash(msg))
900 }
901 }
902 }
903}
904
905fn script_code_wpkh(script: &Script) -> Script {
907 assert!(script.is_v0_p2wpkh());
908 let mut script_code = vec![0x76u8, 0xa9, 0x14];
910 script_code.extend(&script.as_bytes()[2..]);
911 script_code.push(0x88);
912 script_code.push(0xac);
913 Script::from(script_code)
914}
915#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
917pub enum UxtoUpdateError {
918 IndexOutOfBounds(usize, usize),
920 DerivationError(descriptor::ConversionError),
922 MissingInputUxto,
924 RangeMissingWildCardDescriptor,
926 IncorrectDescriptor,
928}
929
930impl fmt::Display for UxtoUpdateError {
931 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
932 match self {
933 UxtoUpdateError::IndexOutOfBounds(ind, len) => {
934 write!(f, "index {}, psbt input len: {}", ind, len)
935 }
936 UxtoUpdateError::DerivationError(e) => write!(f, "Key Derivation error {}", e),
937 UxtoUpdateError::MissingInputUxto => write!(f, "Missing input utxo in pbst"),
938 UxtoUpdateError::RangeMissingWildCardDescriptor => {
939 write!(
940 f,
941 "Range missing must be supplied for a wild-card descriptor"
942 )
943 }
944 UxtoUpdateError::IncorrectDescriptor => {
945 write!(
946 f,
947 "Cannot derive the output script pubkey using the given descriptor and range"
948 )
949 }
950 }
951 }
952}
953
954impl error::Error for UxtoUpdateError {}
955
956#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
958pub enum SighashError {
959 IndexOutOfBounds(usize, usize),
961 MissingInputUxto,
963 MissingSpendUtxos,
965 InvalidSighashType,
967 SighashComputationError(bitcoin::util::sighash::Error),
971 MissingWitnessScript,
973 MissingRedeemScript,
975}
976
977impl fmt::Display for SighashError {
978 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
979 match self {
980 SighashError::IndexOutOfBounds(ind, len) => {
981 write!(f, "index {}, psbt input len: {}", ind, len)
982 }
983 SighashError::MissingInputUxto => write!(f, "Missing input utxo in pbst"),
984 SighashError::MissingSpendUtxos => write!(f, "Missing Psbt spend utxos"),
985 SighashError::InvalidSighashType => write!(f, "Invalid Sighash type"),
986 SighashError::SighashComputationError(e) => {
987 write!(f, "Sighash computation error : {}", e)
988 }
989 SighashError::MissingWitnessScript => write!(f, "Missing Witness Script"),
990 SighashError::MissingRedeemScript => write!(f, "Missing Redeem Script"),
991 }
992 }
993}
994
995impl From<bitcoin::util::sighash::Error> for SighashError {
996 fn from(e: bitcoin::util::sighash::Error) -> Self {
997 SighashError::SighashComputationError(e)
998 }
999}
1000
1001impl error::Error for SighashError {}
1002
1003#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
1005pub enum PsbtSighashMsg {
1006 TapSighash(taproot::TapSighashHash),
1008 EcdsaSighash(bitcoin::Sighash),
1010}
1011
1012impl PsbtSighashMsg {
1013 pub fn to_secp_msg(&self) -> secp256k1::Message {
1015 match *self {
1016 PsbtSighashMsg::TapSighash(msg) => {
1017 secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1018 }
1019 PsbtSighashMsg::EcdsaSighash(msg) => {
1020 secp256k1::Message::from_slice(msg.as_ref()).expect("Sighashes are 32 bytes")
1021 }
1022 }
1023 }
1024}
1025
1026#[cfg(test)]
1027mod tests {
1028 use super::*;
1029
1030 use bitcoin::consensus::encode::deserialize;
1031 use bitcoin::hashes::hex::FromHex;
1032
1033 #[test]
1034 fn test_extract_bip174() {
1035 let psbt: bitcoin::util::psbt::PartiallySignedTransaction = deserialize(&Vec::<u8>::from_hex("70736274ff01009a020000000258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd750000000000ffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d0100000000ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f00000000000100bb0200000001aad73931018bd25f84ae400b68848be09db706eac2ac18298babee71ab656f8b0000000048473044022058f6fc7c6a33e1b31548d481c826c015bd30135aad42cd67790dab66d2ad243b02204a1ced2604c6735b6393e5b41691dd78b00f0c5942fb9f751856faa938157dba01feffffff0280f0fa020000000017a9140fb9463421696b82c833af241c78c17ddbde493487d0f20a270100000017a91429ca74f8a08f81999428185c97b5d852e4063f6187650000000107da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752ae0001012000c2eb0b0000000017a914b7f5faf40e3d40a5a459b1db3535f2b72fa921e8870107232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b20289030108da0400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00220203a9a4c37f5996d3aa25dbac6b570af0650394492942460b354753ed9eeca5877110d90c6a4f000000800000008004000080002202027f6399757d2eff55a136ad02c684b1838b6556e5f1b6b34282a94b6b5005109610d90c6a4f00000080000000800500008000").unwrap()).unwrap();
1036 let secp = Secp256k1::verification_only();
1037 let tx = psbt.extract(&secp).unwrap();
1038 let expected: bitcoin::Transaction = deserialize(&Vec::<u8>::from_hex("0200000000010258e87a21b56daf0c23be8e7070456c336f7cbaa5c8757924f545887bb2abdd7500000000da00473044022074018ad4180097b873323c0015720b3684cc8123891048e7dbcd9b55ad679c99022073d369b740e3eb53dcefa33823c8070514ca55a7dd9544f157c167913261118c01483045022100f61038b308dc1da865a34852746f015772934208c6d24454393cd99bdf2217770220056e675a675a6d0a02b85b14e5e29074d8a25a9b5760bea2816f661910a006ea01475221029583bf39ae0a609747ad199addd634fa6108559d6c5cd39b4c2183f1ab96e07f2102dab61ff49a14db6a7d02b0cd1fbb78fc4b18312b5b4e54dae4dba2fbfef536d752aeffffffff838d0427d0ec650a68aa46bb0b098aea4422c071b2ca78352a077959d07cea1d01000000232200208c2353173743b595dfb4a07b72ba8e42e3797da74e87fe7d9d7497e3b2028903ffffffff0270aaf00800000000160014d85c2b71d0060b09c9886aeb815e50991dda124d00e1f5050000000016001400aea9a2e5f0f876a588df5546e8742d1d87008f000400473044022062eb7a556107a7c73f45ac4ab5a1dddf6f7075fb1275969a7f383efff784bcb202200c05dbb7470dbf2f08557dd356c7325c1ed30913e996cd3840945db12228da5f01473044022065f45ba5998b59a27ffe1a7bed016af1f1f90d54b3aa8f7450aa5f56a25103bd02207f724703ad1edb96680b284b56d4ffcb88f7fb759eabbe08aa30f29b851383d20147522103089dc10c7ac6db54f91329af617333db388cead0c231f723379d1b99030b02dc21023add904f3d6dcf59ddb906b0dee23529b7ffb9ed50e5e86151926860221f0e7352ae00000000").unwrap()).unwrap();
1039 assert_eq!(tx, expected);
1040 }
1041}