1#![allow(clippy::result_large_err)]
11
12#[macro_use]
13mod macros;
14mod error;
15mod map;
16pub mod raw;
17pub mod serialize;
18
19use core::{cmp, fmt};
20#[cfg(feature = "std")]
21use std::collections::{HashMap, HashSet};
22
23use internals::write_err;
24use secp256k1::{Keypair, Message, Secp256k1, Signing, Verification};
25
26use crate::bip32::{self, DerivationPath, KeySource, Xpriv, Xpub};
27use crate::blockdata::transaction::{self, Transaction, TxOut};
28use crate::crypto::key::{PrivateKey, PublicKey};
29use crate::crypto::{ecdsa, taproot};
30use crate::key::{TapTweak, XOnlyPublicKey};
31use crate::prelude::*;
32use crate::sighash::{self, EcdsaSighashType, Prevouts, SighashCache};
33use crate::{Amount, FeeRate, TapLeafHash, TapSighashType};
34
35#[rustfmt::skip] #[doc(inline)]
37pub use self::{
38 map::{Input, Output, PsbtSighashType},
39 error::Error,
40};
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
46pub struct Psbt {
47 pub unsigned_tx: Transaction,
49 pub version: u32,
51 pub xpub: BTreeMap<Xpub, KeySource>,
54 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
56 pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
57 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
59 pub unknown: BTreeMap<raw::Key, Vec<u8>>,
60
61 pub inputs: Vec<Input>,
63 pub outputs: Vec<Output>,
65}
66
67impl Psbt {
68 pub fn iter_funding_utxos(&self) -> impl Iterator<Item = Result<&TxOut, Error>> {
81 assert_eq!(self.inputs.len(), self.unsigned_tx.input.len());
82 self.unsigned_tx.input.iter().zip(&self.inputs).map(|(tx_input, psbt_input)| {
83 match (&psbt_input.witness_utxo, &psbt_input.non_witness_utxo) {
84 (Some(witness_utxo), _) => Ok(witness_utxo),
85 (None, Some(non_witness_utxo)) => {
86 let vout = tx_input.previous_output.vout as usize;
87 non_witness_utxo.output.get(vout).ok_or(Error::PsbtUtxoOutOfbounds)
88 }
89 (None, None) => Err(Error::MissingUtxo),
90 }
91 })
92 }
93
94 fn unsigned_tx_checks(&self) -> Result<(), Error> {
96 for txin in &self.unsigned_tx.input {
97 if !txin.script_sig.is_empty() {
98 return Err(Error::UnsignedTxHasScriptSigs);
99 }
100
101 if !txin.witness.is_empty() {
102 return Err(Error::UnsignedTxHasScriptWitnesses);
103 }
104 }
105
106 Ok(())
107 }
108
109 pub fn from_unsigned_tx(tx: Transaction) -> Result<Self, Error> {
115 let psbt = Psbt {
116 inputs: vec![Default::default(); tx.input.len()],
117 outputs: vec![Default::default(); tx.output.len()],
118
119 unsigned_tx: tx,
120 xpub: Default::default(),
121 version: 0,
122 proprietary: Default::default(),
123 unknown: Default::default(),
124 };
125 psbt.unsigned_tx_checks()?;
126 Ok(psbt)
127 }
128
129 pub const DEFAULT_MAX_FEE_RATE: FeeRate = FeeRate::from_sat_per_vb_unchecked(25_000);
136
137 pub fn extract_tx(self) -> Result<Transaction, ExtractTxError> {
141 self.internal_extract_tx_with_fee_rate_limit(Self::DEFAULT_MAX_FEE_RATE)
142 }
143
144 pub fn extract_tx_fee_rate_limit(self) -> Result<Transaction, ExtractTxError> {
152 self.internal_extract_tx_with_fee_rate_limit(Self::DEFAULT_MAX_FEE_RATE)
153 }
154
155 pub fn extract_tx_with_fee_rate_limit(
163 self,
164 max_fee_rate: FeeRate,
165 ) -> Result<Transaction, ExtractTxError> {
166 self.internal_extract_tx_with_fee_rate_limit(max_fee_rate)
167 }
168
169 pub fn extract_tx_unchecked_fee_rate(self) -> Transaction { self.internal_extract_tx() }
175
176 #[inline]
177 fn internal_extract_tx(self) -> Transaction {
178 let mut tx: Transaction = self.unsigned_tx;
179
180 for (vin, psbtin) in tx.input.iter_mut().zip(self.inputs.into_iter()) {
181 vin.script_sig = psbtin.final_script_sig.unwrap_or_default();
182 vin.witness = psbtin.final_script_witness.unwrap_or_default();
183 }
184
185 tx
186 }
187
188 #[inline]
189 fn internal_extract_tx_with_fee_rate_limit(
190 self,
191 max_fee_rate: FeeRate,
192 ) -> Result<Transaction, ExtractTxError> {
193 let fee = match self.fee() {
194 Ok(fee) => fee,
195 Err(Error::MissingUtxo) =>
196 return Err(ExtractTxError::MissingInputValue { tx: self.internal_extract_tx() }),
197 Err(Error::NegativeFee) => return Err(ExtractTxError::SendingTooMuch { psbt: self }),
198 Err(Error::FeeOverflow) =>
199 return Err(ExtractTxError::AbsurdFeeRate {
200 fee_rate: FeeRate::MAX,
201 tx: self.internal_extract_tx(),
202 }),
203 _ => unreachable!(),
204 };
205
206 let tx = self.internal_extract_tx();
208
209 let fee_rate =
211 FeeRate::from_sat_per_kwu(fee.to_sat().saturating_mul(1000) / tx.weight().to_wu());
212 if fee_rate > max_fee_rate {
214 return Err(ExtractTxError::AbsurdFeeRate { fee_rate, tx });
215 }
216
217 Ok(tx)
218 }
219
220 pub fn combine(&mut self, other: Self) -> Result<(), Error> {
224 if self.unsigned_tx != other.unsigned_tx {
225 return Err(Error::UnexpectedUnsignedTx {
226 expected: Box::new(self.unsigned_tx.clone()),
227 actual: Box::new(other.unsigned_tx),
228 });
229 }
230
231 self.version = cmp::max(self.version, other.version);
236
237 for (xpub, (fingerprint1, derivation1)) in other.xpub {
239 match self.xpub.entry(xpub) {
240 btree_map::Entry::Vacant(entry) => {
241 entry.insert((fingerprint1, derivation1));
242 }
243 btree_map::Entry::Occupied(mut entry) => {
244 let (fingerprint2, derivation2) = entry.get().clone();
254
255 if (derivation1 == derivation2 && fingerprint1 == fingerprint2)
256 || (derivation1.len() < derivation2.len()
257 && derivation1[..]
258 == derivation2[derivation2.len() - derivation1.len()..])
259 {
260 continue;
261 } else if derivation2[..]
262 == derivation1[derivation1.len() - derivation2.len()..]
263 {
264 entry.insert((fingerprint1, derivation1));
265 continue;
266 }
267 return Err(Error::CombineInconsistentKeySources(Box::new(xpub)));
268 }
269 }
270 }
271
272 self.proprietary.extend(other.proprietary);
273 self.unknown.extend(other.unknown);
274
275 for (self_input, other_input) in self.inputs.iter_mut().zip(other.inputs.into_iter()) {
276 self_input.combine(other_input);
277 }
278
279 for (self_output, other_output) in self.outputs.iter_mut().zip(other.outputs.into_iter()) {
280 self_output.combine(other_output);
281 }
282
283 Ok(())
284 }
285
286 pub fn sign<C, K>(
298 &mut self,
299 k: &K,
300 secp: &Secp256k1<C>,
301 ) -> Result<SigningKeysMap, (SigningKeysMap, SigningErrors)>
302 where
303 C: Signing + Verification,
304 K: GetKey,
305 {
306 let tx = self.unsigned_tx.clone(); let mut cache = SighashCache::new(&tx);
308
309 let mut used = BTreeMap::new();
310 let mut errors = BTreeMap::new();
311
312 for i in 0..self.inputs.len() {
313 match self.signing_algorithm(i) {
314 Ok(SigningAlgorithm::Ecdsa) =>
315 match self.bip32_sign_ecdsa(k, i, &mut cache, secp) {
316 Ok(v) => {
317 used.insert(i, SigningKeys::Ecdsa(v));
318 }
319 Err(e) => {
320 errors.insert(i, e);
321 }
322 },
323 Ok(SigningAlgorithm::Schnorr) => {
324 match self.bip32_sign_schnorr(k, i, &mut cache, secp) {
325 Ok(v) => {
326 used.insert(i, SigningKeys::Schnorr(v));
327 }
328 Err(e) => {
329 errors.insert(i, e);
330 }
331 }
332 }
333 Err(e) => {
334 errors.insert(i, e);
335 }
336 }
337 }
338 if errors.is_empty() {
339 Ok(used)
340 } else {
341 Err((used, errors))
342 }
343 }
344
345 fn bip32_sign_ecdsa<C, K, T>(
353 &mut self,
354 k: &K,
355 input_index: usize,
356 cache: &mut SighashCache<T>,
357 secp: &Secp256k1<C>,
358 ) -> Result<Vec<PublicKey>, SignError>
359 where
360 C: Signing,
361 T: Borrow<Transaction>,
362 K: GetKey,
363 {
364 let msg_sighash_ty_res = self.sighash_ecdsa(input_index, cache);
365
366 let input = &mut self.inputs[input_index]; let mut used = vec![]; for (pk, key_source) in input.bip32_derivation.iter() {
371 let sk = if let Ok(Some(sk)) = k.get_key(KeyRequest::Bip32(key_source.clone()), secp) {
372 sk
373 } else if let Ok(Some(sk)) = k.get_key(KeyRequest::Pubkey(PublicKey::new(*pk)), secp) {
374 sk
375 } else {
376 continue;
377 };
378
379 let (msg, sighash_ty) = match msg_sighash_ty_res {
381 Err(e) => return Err(e),
382 Ok((msg, sighash_ty)) => (msg, sighash_ty),
383 };
384
385 let sig = ecdsa::Signature {
386 signature: secp.sign_ecdsa(&msg, &sk.inner),
387 sighash_type: sighash_ty,
388 };
389
390 let pk = sk.public_key(secp);
391
392 input.partial_sigs.insert(pk, sig);
393 used.push(pk);
394 }
395
396 Ok(used)
397 }
398
399 fn bip32_sign_schnorr<C, K, T>(
408 &mut self,
409 k: &K,
410 input_index: usize,
411 cache: &mut SighashCache<T>,
412 secp: &Secp256k1<C>,
413 ) -> Result<Vec<XOnlyPublicKey>, SignError>
414 where
415 C: Signing + Verification,
416 T: Borrow<Transaction>,
417 K: GetKey,
418 {
419 let mut input = self.checked_input(input_index)?.clone();
420
421 let mut used = vec![]; for (&xonly, (leaf_hashes, key_source)) in input.tap_key_origins.iter() {
424 let sk = if let Ok(Some(secret_key)) =
425 k.get_key(KeyRequest::Bip32(key_source.clone()), secp)
426 {
427 secret_key
428 } else if let Ok(Some(sk)) = k.get_key(KeyRequest::XOnlyPubkey(xonly), secp) {
429 sk
430 } else {
431 continue;
432 };
433
434 if let Some(internal_key) = input.tap_internal_key {
441 if internal_key == xonly && leaf_hashes.is_empty() && input.tap_key_sig.is_none() {
446 let (msg, sighash_type) = self.sighash_taproot(input_index, cache, None)?;
447 let key_pair = Keypair::from_secret_key(secp, &sk.inner)
448 .tap_tweak(secp, input.tap_merkle_root)
449 .to_keypair();
450
451 #[cfg(feature = "rand-std")]
452 let signature = secp.sign_schnorr(&msg, &key_pair);
453 #[cfg(not(feature = "rand-std"))]
454 let signature = secp.sign_schnorr_no_aux_rand(&msg, &key_pair);
455
456 let signature = taproot::Signature { signature, sighash_type };
457 input.tap_key_sig = Some(signature);
458
459 used.push(internal_key);
460 }
461 }
462
463 if let Some((leaf_hashes, _)) = input.tap_key_origins.get(&xonly) {
465 let leaf_hashes = leaf_hashes
466 .iter()
467 .filter(|lh| !input.tap_script_sigs.contains_key(&(xonly, **lh)))
468 .cloned()
469 .collect::<Vec<_>>();
470
471 if !leaf_hashes.is_empty() {
472 let key_pair = Keypair::from_secret_key(secp, &sk.inner);
473
474 for lh in leaf_hashes {
475 let (msg, sighash_type) =
476 self.sighash_taproot(input_index, cache, Some(lh))?;
477
478 #[cfg(feature = "rand-std")]
479 let signature = secp.sign_schnorr(&msg, &key_pair);
480 #[cfg(not(feature = "rand-std"))]
481 let signature = secp.sign_schnorr_no_aux_rand(&msg, &key_pair);
482
483 let signature = taproot::Signature { signature, sighash_type };
484 input.tap_script_sigs.insert((xonly, lh), signature);
485 }
486
487 used.push(sk.public_key(secp).into());
488 }
489 }
490 }
491
492 self.inputs[input_index] = input; Ok(used)
495 }
496
497 pub fn sighash_ecdsa<T: Borrow<Transaction>>(
503 &self,
504 input_index: usize,
505 cache: &mut SighashCache<T>,
506 ) -> Result<(Message, EcdsaSighashType), SignError> {
507 use OutputType::*;
508
509 if self.signing_algorithm(input_index)? != SigningAlgorithm::Ecdsa {
510 return Err(SignError::WrongSigningAlgorithm);
511 }
512
513 let input = self.checked_input(input_index)?;
514 let utxo = self.spend_utxo(input_index)?;
515 let spk = &utxo.script_pubkey; let hash_ty = input.ecdsa_hash_ty().map_err(|_| SignError::InvalidSighashType)?; match self.output_type(input_index)? {
520 Bare => {
521 let sighash = cache
522 .legacy_signature_hash(input_index, spk, hash_ty.to_u32())
523 .expect("input checked above");
524 Ok((Message::from(sighash), hash_ty))
525 }
526 Sh => {
527 let script_code =
528 input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?;
529 let sighash = cache
530 .legacy_signature_hash(input_index, script_code, hash_ty.to_u32())
531 .expect("input checked above");
532 Ok((Message::from(sighash), hash_ty))
533 }
534 Wpkh => {
535 let sighash = cache.p2wpkh_signature_hash(input_index, spk, utxo.value, hash_ty)?;
536 Ok((Message::from(sighash), hash_ty))
537 }
538 ShWpkh => {
539 let redeem_script = input.redeem_script.as_ref().expect("checked above");
540 let sighash =
541 cache.p2wpkh_signature_hash(input_index, redeem_script, utxo.value, hash_ty)?;
542 Ok((Message::from(sighash), hash_ty))
543 }
544 Wsh | ShWsh => {
545 let witness_script =
546 input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?;
547 let sighash = cache
548 .p2wsh_signature_hash(input_index, witness_script, utxo.value, hash_ty)
549 .map_err(SignError::SegwitV0Sighash)?;
550 Ok((Message::from(sighash), hash_ty))
551 }
552 Tr => {
553 Err(SignError::Unsupported)
555 }
556 }
557 }
558
559 fn sighash_taproot<T: Borrow<Transaction>>(
564 &self,
565 input_index: usize,
566 cache: &mut SighashCache<T>,
567 leaf_hash: Option<TapLeafHash>,
568 ) -> Result<(Message, TapSighashType), SignError> {
569 use OutputType::*;
570
571 if self.signing_algorithm(input_index)? != SigningAlgorithm::Schnorr {
572 return Err(SignError::WrongSigningAlgorithm);
573 }
574
575 let input = self.checked_input(input_index)?;
576
577 match self.output_type(input_index)? {
578 Tr => {
579 let hash_ty = input
580 .sighash_type
581 .unwrap_or_else(|| TapSighashType::Default.into())
582 .taproot_hash_ty()
583 .map_err(|_| SignError::InvalidSighashType)?;
584
585 let spend_utxos =
586 (0..self.inputs.len()).map(|i| self.spend_utxo(i).ok()).collect::<Vec<_>>();
587 let all_spend_utxos;
588
589 let is_anyone_can_pay = PsbtSighashType::from(hash_ty).to_u32() & 0x80 != 0;
590
591 let prev_outs = if is_anyone_can_pay {
592 Prevouts::One(
593 input_index,
594 spend_utxos[input_index].ok_or(SignError::MissingSpendUtxo)?,
595 )
596 } else if spend_utxos.iter().all(Option::is_some) {
597 all_spend_utxos = spend_utxos.iter().filter_map(|x| *x).collect::<Vec<_>>();
598 Prevouts::All(&all_spend_utxos)
599 } else {
600 return Err(SignError::MissingSpendUtxo);
601 };
602
603 let sighash = if let Some(leaf_hash) = leaf_hash {
604 cache.taproot_script_spend_signature_hash(
605 input_index,
606 &prev_outs,
607 leaf_hash,
608 hash_ty,
609 )?
610 } else {
611 cache.taproot_key_spend_signature_hash(input_index, &prev_outs, hash_ty)?
612 };
613 Ok((Message::from(sighash), hash_ty))
614 }
615 _ => Err(SignError::Unsupported),
616 }
617 }
618
619 pub fn spend_utxo(&self, input_index: usize) -> Result<&TxOut, SignError> {
621 let input = self.checked_input(input_index)?;
622 let utxo = if let Some(witness_utxo) = &input.witness_utxo {
623 witness_utxo
624 } else if let Some(non_witness_utxo) = &input.non_witness_utxo {
625 let vout = self.unsigned_tx.input[input_index].previous_output.vout;
626 &non_witness_utxo.output[vout as usize]
627 } else {
628 return Err(SignError::MissingSpendUtxo);
629 };
630 Ok(utxo)
631 }
632
633 fn checked_input(&self, input_index: usize) -> Result<&Input, IndexOutOfBoundsError> {
635 self.check_index_is_within_bounds(input_index)?;
636 Ok(&self.inputs[input_index])
637 }
638
639 fn check_index_is_within_bounds(
642 &self,
643 input_index: usize,
644 ) -> Result<(), IndexOutOfBoundsError> {
645 if input_index >= self.inputs.len() {
646 return Err(IndexOutOfBoundsError::Inputs {
647 index: input_index,
648 length: self.inputs.len(),
649 });
650 }
651
652 if input_index >= self.unsigned_tx.input.len() {
653 return Err(IndexOutOfBoundsError::TxInput {
654 index: input_index,
655 length: self.unsigned_tx.input.len(),
656 });
657 }
658
659 Ok(())
660 }
661
662 fn signing_algorithm(&self, input_index: usize) -> Result<SigningAlgorithm, SignError> {
664 let output_type = self.output_type(input_index)?;
665 Ok(output_type.signing_algorithm())
666 }
667
668 fn output_type(&self, input_index: usize) -> Result<OutputType, SignError> {
670 let input = self.checked_input(input_index)?;
671 let utxo = self.spend_utxo(input_index)?;
672 let spk = utxo.script_pubkey.clone();
673
674 if !(spk.is_witness_program() || spk.is_p2sh()) {
676 return Ok(OutputType::Bare);
677 }
678
679 if spk.is_p2wpkh() {
680 return Ok(OutputType::Wpkh);
681 }
682
683 if spk.is_p2wsh() {
684 return Ok(OutputType::Wsh);
685 }
686
687 if spk.is_p2sh() {
688 if input.redeem_script.as_ref().map(|s| s.is_p2wpkh()).unwrap_or(false) {
689 return Ok(OutputType::ShWpkh);
690 }
691 if input.redeem_script.as_ref().map(|x| x.is_p2wsh()).unwrap_or(false) {
692 return Ok(OutputType::ShWsh);
693 }
694 return Ok(OutputType::Sh);
695 }
696
697 if spk.is_p2tr() {
698 return Ok(OutputType::Tr);
699 }
700
701 Err(SignError::UnknownOutputType)
704 }
705
706 pub fn fee(&self) -> Result<Amount, Error> {
717 let mut inputs: u64 = 0;
718 for utxo in self.iter_funding_utxos() {
719 inputs = inputs.checked_add(utxo?.value.to_sat()).ok_or(Error::FeeOverflow)?;
720 }
721 let mut outputs: u64 = 0;
722 for out in &self.unsigned_tx.output {
723 outputs = outputs.checked_add(out.value.to_sat()).ok_or(Error::FeeOverflow)?;
724 }
725 inputs.checked_sub(outputs).map(Amount::from_sat).ok_or(Error::NegativeFee)
726 }
727}
728
729#[derive(Clone, Debug, PartialEq, Eq)]
731#[non_exhaustive]
732pub enum KeyRequest {
733 Pubkey(PublicKey),
735 Bip32(KeySource),
737 XOnlyPubkey(XOnlyPublicKey),
739}
740
741pub trait GetKey {
743 type Error: core::fmt::Debug;
745
746 fn get_key<C: Signing>(
753 &self,
754 key_request: KeyRequest,
755 secp: &Secp256k1<C>,
756 ) -> Result<Option<PrivateKey>, Self::Error>;
757}
758
759impl GetKey for Xpriv {
760 type Error = GetKeyError;
761
762 fn get_key<C: Signing>(
763 &self,
764 key_request: KeyRequest,
765 secp: &Secp256k1<C>,
766 ) -> Result<Option<PrivateKey>, Self::Error> {
767 match key_request {
768 KeyRequest::Pubkey(_) => Err(GetKeyError::NotSupported),
769 KeyRequest::XOnlyPubkey(_) => Err(GetKeyError::NotSupported),
770 KeyRequest::Bip32((fingerprint, path)) => {
771 let key = if self.fingerprint(secp) == fingerprint {
772 let k = self.derive_priv(secp, &path)?;
773 Some(k.to_priv())
774 } else if self.parent_fingerprint == fingerprint
775 && !path.is_empty()
776 && path[0] == self.child_number
777 {
778 let path = DerivationPath::from_iter(path.into_iter().skip(1).copied());
779 let k = self.derive_priv(secp, &path)?;
780 Some(k.to_priv())
781 } else {
782 None
783 };
784 Ok(key)
785 }
786 }
787 }
788}
789
790pub type SigningKeysMap = BTreeMap<usize, SigningKeys>;
792
793#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
795pub enum SigningKeys {
796 Ecdsa(Vec<PublicKey>),
798 Schnorr(Vec<XOnlyPublicKey>),
803}
804
805pub type SigningErrors = BTreeMap<usize, SignError>;
807
808#[rustfmt::skip]
809macro_rules! impl_get_key_for_set {
810 ($set:ident) => {
811
812impl GetKey for $set<Xpriv> {
813 type Error = GetKeyError;
814
815 fn get_key<C: Signing>(
816 &self,
817 key_request: KeyRequest,
818 secp: &Secp256k1<C>
819 ) -> Result<Option<PrivateKey>, Self::Error> {
820 self.iter()
823 .find_map(|xpriv| xpriv.get_key(key_request.clone(), secp).transpose())
824 .transpose()
825 }
826}}}
827impl_get_key_for_set!(BTreeSet);
828#[cfg(feature = "std")]
829impl_get_key_for_set!(HashSet);
830
831#[rustfmt::skip]
832macro_rules! impl_get_key_for_pubkey_map {
833 ($map:ident) => {
834
835impl GetKey for $map<PublicKey, PrivateKey> {
836 type Error = GetKeyError;
837
838 fn get_key<C: Signing>(
839 &self,
840 key_request: KeyRequest,
841 _: &Secp256k1<C>,
842 ) -> Result<Option<PrivateKey>, Self::Error> {
843 match key_request {
844 KeyRequest::Pubkey(pk) => Ok(self.get(&pk).cloned()),
845 KeyRequest::XOnlyPubkey(xonly) => {
846 let pubkey_even = PublicKey::new(xonly.public_key(secp256k1::Parity::Even));
847 let key = self.get(&pubkey_even).cloned();
848
849 if key.is_some() {
850 return Ok(key);
851 }
852
853 let pubkey_odd = PublicKey::new(xonly.public_key(secp256k1::Parity::Odd));
854 if let Some(priv_key) = self.get(&pubkey_odd).copied() {
855 let negated_priv_key = priv_key.negate();
856 return Ok(Some(negated_priv_key));
857 }
858
859 Ok(None)
860 },
861 KeyRequest::Bip32(_) => Err(GetKeyError::NotSupported),
862 }
863 }
864}}}
865impl_get_key_for_pubkey_map!(BTreeMap);
866#[cfg(feature = "std")]
867impl_get_key_for_pubkey_map!(HashMap);
868
869#[rustfmt::skip]
870macro_rules! impl_get_key_for_xonly_map {
871 ($map:ident) => {
872
873impl GetKey for $map<XOnlyPublicKey, PrivateKey> {
874 type Error = GetKeyError;
875
876 fn get_key<C: Signing>(
877 &self,
878 key_request: KeyRequest,
879 secp: &Secp256k1<C>,
880 ) -> Result<Option<PrivateKey>, Self::Error> {
881 match key_request {
882 KeyRequest::XOnlyPubkey(xonly) => Ok(self.get(&xonly).cloned()),
883 KeyRequest::Pubkey(pk) => {
884 let (xonly, parity) = pk.inner.x_only_public_key();
885
886 if let Some(mut priv_key) = self.get(&XOnlyPublicKey::from(xonly)).cloned() {
887 let computed_pk = priv_key.public_key(&secp);
888 let (_, computed_parity) = computed_pk.inner.x_only_public_key();
889
890 if computed_parity != parity {
891 priv_key = priv_key.negate();
892 }
893
894 return Ok(Some(priv_key));
895 }
896
897 Ok(None)
898 },
899 KeyRequest::Bip32(_) => Err(GetKeyError::NotSupported),
900 }
901 }
902}}}
903impl_get_key_for_xonly_map!(BTreeMap);
904#[cfg(feature = "std")]
905impl_get_key_for_xonly_map!(HashMap);
906
907#[derive(Debug, Clone, PartialEq, Eq)]
909#[non_exhaustive]
910pub enum GetKeyError {
911 Bip32(bip32::Error),
913 NotSupported,
915}
916
917internals::impl_from_infallible!(GetKeyError);
918
919impl fmt::Display for GetKeyError {
920 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
921 use GetKeyError::*;
922
923 match *self {
924 Bip32(ref e) => write_err!(f, "a bip23 error"; e),
925 NotSupported =>
926 f.write_str("the GetKey operation is not supported for this key request"),
927 }
928 }
929}
930
931#[cfg(feature = "std")]
932impl std::error::Error for GetKeyError {
933 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
934 use GetKeyError::*;
935
936 match *self {
937 NotSupported => None,
938 Bip32(ref e) => Some(e),
939 }
940 }
941}
942
943impl From<bip32::Error> for GetKeyError {
944 fn from(e: bip32::Error) -> Self { GetKeyError::Bip32(e) }
945}
946
947#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
949#[non_exhaustive]
950pub enum OutputType {
951 Bare,
953 Wpkh,
955 Wsh,
957 ShWpkh,
959 ShWsh,
961 Sh,
963 Tr,
965}
966
967impl OutputType {
968 pub fn signing_algorithm(&self) -> SigningAlgorithm {
970 use OutputType::*;
971
972 match self {
973 Bare | Wpkh | Wsh | ShWpkh | ShWsh | Sh => SigningAlgorithm::Ecdsa,
974 Tr => SigningAlgorithm::Schnorr,
975 }
976 }
977}
978
979#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
981pub enum SigningAlgorithm {
982 Ecdsa,
986 Schnorr,
990}
991
992#[derive(Debug, Clone, PartialEq, Eq)]
994#[non_exhaustive]
995pub enum SignError {
996 IndexOutOfBounds(IndexOutOfBoundsError),
998 InvalidSighashType,
1000 MissingInputUtxo,
1002 MissingRedeemScript,
1004 MissingSpendUtxo,
1006 MissingWitnessScript,
1008 MismatchedAlgoKey,
1010 NotEcdsa,
1012 NotWpkh,
1014 SegwitV0Sighash(transaction::InputsIndexError),
1016 P2wpkhSighash(sighash::P2wpkhError),
1018 TaprootError(sighash::TaprootError),
1020 UnknownOutputType,
1022 KeyNotFound,
1024 WrongSigningAlgorithm,
1026 Unsupported,
1028}
1029
1030internals::impl_from_infallible!(SignError);
1031
1032impl fmt::Display for SignError {
1033 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1034 use SignError::*;
1035
1036 match *self {
1037 IndexOutOfBounds(ref e) => write_err!(f, "index out of bounds"; e),
1038 InvalidSighashType => write!(f, "invalid sighash type"),
1039 MissingInputUtxo => write!(f, "missing input utxo in PBST"),
1040 MissingRedeemScript => write!(f, "missing redeem script"),
1041 MissingSpendUtxo => write!(f, "missing spend utxo in PSBT"),
1042 MissingWitnessScript => write!(f, "missing witness script"),
1043 MismatchedAlgoKey => write!(f, "signing algorithm and key type does not match"),
1044 NotEcdsa => write!(f, "attempted to ECDSA sign an non-ECDSA input"),
1045 NotWpkh => write!(f, "the scriptPubkey is not a P2WPKH script"),
1046 SegwitV0Sighash(ref e) => write_err!(f, "segwit v0 sighash"; e),
1047 P2wpkhSighash(ref e) => write_err!(f, "p2wpkh sighash"; e),
1048 TaprootError(ref e) => write_err!(f, "taproot sighash"; e),
1049 UnknownOutputType => write!(f, "unable to determine the output type"),
1050 KeyNotFound => write!(f, "unable to find key"),
1051 WrongSigningAlgorithm =>
1052 write!(f, "attempt to sign an input with the wrong signing algorithm"),
1053 Unsupported => write!(f, "signing request currently unsupported"),
1054 }
1055 }
1056}
1057
1058#[cfg(feature = "std")]
1059impl std::error::Error for SignError {
1060 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1061 use SignError::*;
1062
1063 match *self {
1064 SegwitV0Sighash(ref e) => Some(e),
1065 P2wpkhSighash(ref e) => Some(e),
1066 TaprootError(ref e) => Some(e),
1067 IndexOutOfBounds(ref e) => Some(e),
1068 InvalidSighashType
1069 | MissingInputUtxo
1070 | MissingRedeemScript
1071 | MissingSpendUtxo
1072 | MissingWitnessScript
1073 | MismatchedAlgoKey
1074 | NotEcdsa
1075 | NotWpkh
1076 | UnknownOutputType
1077 | KeyNotFound
1078 | WrongSigningAlgorithm
1079 | Unsupported => None,
1080 }
1081 }
1082}
1083
1084impl From<sighash::P2wpkhError> for SignError {
1085 fn from(e: sighash::P2wpkhError) -> Self { Self::P2wpkhSighash(e) }
1086}
1087
1088impl From<IndexOutOfBoundsError> for SignError {
1089 fn from(e: IndexOutOfBoundsError) -> Self { SignError::IndexOutOfBounds(e) }
1090}
1091
1092impl From<sighash::TaprootError> for SignError {
1093 fn from(e: sighash::TaprootError) -> Self { SignError::TaprootError(e) }
1094}
1095
1096#[derive(Debug, Clone, PartialEq, Eq)]
1098#[non_exhaustive]
1099pub enum ExtractTxError {
1100 AbsurdFeeRate {
1102 fee_rate: FeeRate,
1104 tx: Transaction,
1106 },
1107 MissingInputValue {
1109 tx: Transaction,
1111 },
1112 SendingTooMuch {
1114 psbt: Psbt,
1116 },
1117}
1118
1119internals::impl_from_infallible!(ExtractTxError);
1120
1121impl fmt::Display for ExtractTxError {
1122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1123 use ExtractTxError::*;
1124
1125 match *self {
1126 AbsurdFeeRate { fee_rate, .. } =>
1127 write!(f, "An absurdly high fee rate of {}", fee_rate),
1128 MissingInputValue { .. } => write!(
1129 f,
1130 "One of the inputs lacked value information (witness_utxo or non_witness_utxo)"
1131 ),
1132 SendingTooMuch { .. } => write!(
1133 f,
1134 "Transaction would be invalid due to output value being greater than input value."
1135 ),
1136 }
1137 }
1138}
1139
1140#[cfg(feature = "std")]
1141impl std::error::Error for ExtractTxError {
1142 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1143 use ExtractTxError::*;
1144
1145 match *self {
1146 AbsurdFeeRate { .. } | MissingInputValue { .. } | SendingTooMuch { .. } => None,
1147 }
1148 }
1149}
1150
1151#[derive(Debug, Clone, PartialEq, Eq)]
1153#[non_exhaustive]
1154pub enum IndexOutOfBoundsError {
1155 Inputs {
1157 index: usize,
1159 length: usize,
1161 },
1162 TxInput {
1164 index: usize,
1166 length: usize,
1168 },
1169}
1170
1171internals::impl_from_infallible!(IndexOutOfBoundsError);
1172
1173impl fmt::Display for IndexOutOfBoundsError {
1174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1175 use IndexOutOfBoundsError::*;
1176
1177 match *self {
1178 Inputs { ref index, ref length } => write!(
1179 f,
1180 "index {} is out-of-bounds for PSBT inputs vector length {}",
1181 index, length
1182 ),
1183 TxInput { ref index, ref length } => write!(
1184 f,
1185 "index {} is out-of-bounds for PSBT unsigned tx input vector length {}",
1186 index, length
1187 ),
1188 }
1189 }
1190}
1191
1192#[cfg(feature = "std")]
1193impl std::error::Error for IndexOutOfBoundsError {
1194 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1195 use IndexOutOfBoundsError::*;
1196
1197 match *self {
1198 Inputs { .. } | TxInput { .. } => None,
1199 }
1200 }
1201}
1202
1203#[cfg(feature = "base64")]
1204mod display_from_str {
1205 use core::fmt::{self, Display, Formatter};
1206 use core::str::FromStr;
1207
1208 use base64::display::Base64Display;
1209 use base64::prelude::{Engine as _, BASE64_STANDARD};
1210 use internals::write_err;
1211
1212 use super::{Error, Psbt};
1213
1214 #[derive(Debug)]
1216 #[non_exhaustive]
1217 pub enum PsbtParseError {
1218 PsbtEncoding(Error),
1220 Base64Encoding(::base64::DecodeError),
1222 }
1223
1224 internals::impl_from_infallible!(PsbtParseError);
1225
1226 impl Display for PsbtParseError {
1227 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1228 use self::PsbtParseError::*;
1229
1230 match *self {
1231 PsbtEncoding(ref e) => write_err!(f, "error in internal PSBT data structure"; e),
1232 Base64Encoding(ref e) => write_err!(f, "error in PSBT base64 encoding"; e),
1233 }
1234 }
1235 }
1236
1237 #[cfg(feature = "std")]
1238 impl std::error::Error for PsbtParseError {
1239 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1240 use self::PsbtParseError::*;
1241
1242 match self {
1243 PsbtEncoding(e) => Some(e),
1244 Base64Encoding(e) => Some(e),
1245 }
1246 }
1247 }
1248
1249 impl Display for Psbt {
1250 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1251 write!(f, "{}", Base64Display::new(&self.serialize(), &BASE64_STANDARD))
1252 }
1253 }
1254
1255 impl FromStr for Psbt {
1256 type Err = PsbtParseError;
1257
1258 fn from_str(s: &str) -> Result<Self, Self::Err> {
1259 let data = BASE64_STANDARD.decode(s).map_err(PsbtParseError::Base64Encoding)?;
1260 Psbt::deserialize(&data).map_err(PsbtParseError::PsbtEncoding)
1261 }
1262 }
1263}
1264#[cfg(feature = "base64")]
1265pub use self::display_from_str::PsbtParseError;
1266
1267#[cfg(test)]
1268mod tests {
1269 use hashes::{hash160, ripemd160, sha256, Hash};
1270 use hex::{test_hex_unwrap as hex, FromHex};
1271 #[cfg(feature = "rand-std")]
1272 use {
1273 crate::bip32::{DerivationPath, Fingerprint},
1274 crate::key::WPubkeyHash,
1275 crate::locktime,
1276 crate::witness_version::WitnessVersion,
1277 crate::WitnessProgram,
1278 secp256k1::{All, SecretKey},
1279 };
1280
1281 use super::*;
1282 use crate::bip32::ChildNumber;
1283 use crate::blockdata::locktime::absolute;
1284 use crate::blockdata::script::ScriptBuf;
1285 use crate::blockdata::transaction::{self, OutPoint, Sequence, TxIn};
1286 use crate::blockdata::witness::Witness;
1287 use crate::network::NetworkKind;
1288 use crate::psbt::serialize::{Deserialize, Serialize};
1289
1290 #[track_caller]
1291 pub fn hex_psbt(s: &str) -> Result<Psbt, crate::psbt::error::Error> {
1292 let r = Vec::from_hex(s);
1293 match r {
1294 Err(_e) => panic!("unable to parse hex string {}", s),
1295 Ok(v) => Psbt::deserialize(&v),
1296 }
1297 }
1298
1299 #[track_caller]
1300 fn psbt_with_values(input: u64, output: u64) -> Psbt {
1301 Psbt {
1302 unsigned_tx: Transaction {
1303 version: transaction::Version::TWO,
1304 lock_time: absolute::LockTime::ZERO,
1305 input: vec![TxIn {
1306 previous_output: OutPoint {
1307 txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126"
1308 .parse()
1309 .unwrap(),
1310 vout: 0,
1311 },
1312 script_sig: ScriptBuf::new(),
1313 sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
1314 witness: Witness::default(),
1315 }],
1316 output: vec![TxOut {
1317 value: Amount::from_sat(output),
1318 script_pubkey: ScriptBuf::from_hex(
1319 "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
1320 )
1321 .unwrap(),
1322 }],
1323 },
1324 xpub: Default::default(),
1325 version: 0,
1326 proprietary: BTreeMap::new(),
1327 unknown: BTreeMap::new(),
1328
1329 inputs: vec![Input {
1330 witness_utxo: Some(TxOut {
1331 value: Amount::from_sat(input),
1332 script_pubkey: ScriptBuf::from_hex(
1333 "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
1334 )
1335 .unwrap(),
1336 }),
1337 ..Default::default()
1338 }],
1339 outputs: vec![],
1340 }
1341 }
1342
1343 #[test]
1344 fn trivial_psbt() {
1345 let psbt = Psbt {
1346 unsigned_tx: Transaction {
1347 version: transaction::Version::TWO,
1348 lock_time: absolute::LockTime::ZERO,
1349 input: vec![],
1350 output: vec![],
1351 },
1352 xpub: Default::default(),
1353 version: 0,
1354 proprietary: BTreeMap::new(),
1355 unknown: BTreeMap::new(),
1356
1357 inputs: vec![],
1358 outputs: vec![],
1359 };
1360 assert_eq!(psbt.serialize_hex(), "70736274ff01000a0200000000000000000000");
1361 }
1362
1363 #[test]
1364 fn psbt_uncompressed_key() {
1365 let psbt: Psbt = hex_psbt("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap();
1366 assert!(psbt.inputs[0].partial_sigs.len() == 1);
1367 let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0;
1368 assert!(!pk.compressed);
1369 }
1370
1371 #[test]
1372 fn psbt_high_fee_checks() {
1373 let psbt = psbt_with_values(5_000_000_000_000, 1000);
1374 assert_eq!(
1375 psbt.clone().extract_tx().map_err(|e| match e {
1376 ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate,
1377 _ => panic!(""),
1378 }),
1379 Err(FeeRate::from_sat_per_kwu(15060240960843))
1380 );
1381 assert_eq!(
1382 psbt.clone().extract_tx_fee_rate_limit().map_err(|e| match e {
1383 ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate,
1384 _ => panic!(""),
1385 }),
1386 Err(FeeRate::from_sat_per_kwu(15060240960843))
1387 );
1388 assert_eq!(
1389 psbt.clone()
1390 .extract_tx_with_fee_rate_limit(FeeRate::from_sat_per_kwu(15060240960842))
1391 .map_err(|e| match e {
1392 ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate,
1393 _ => panic!(""),
1394 }),
1395 Err(FeeRate::from_sat_per_kwu(15060240960843))
1396 );
1397 assert!(psbt
1398 .extract_tx_with_fee_rate_limit(FeeRate::from_sat_per_kwu(15060240960843))
1399 .is_ok());
1400
1401 assert_eq!(
1403 psbt_with_values(2076001, 1000).extract_tx().map_err(|e| match e {
1404 ExtractTxError::AbsurdFeeRate { fee_rate, .. } => fee_rate,
1405 _ => panic!(""),
1406 }),
1407 Err(FeeRate::from_sat_per_kwu(6250003)) );
1409
1410 assert!(psbt_with_values(2076000, 1000).extract_tx().is_ok());
1413 }
1414
1415 #[test]
1416 fn serialize_then_deserialize_output() {
1417 let secp = &Secp256k1::new();
1418 let seed = hex!("000102030405060708090a0b0c0d0e0f");
1419
1420 let mut hd_keypaths: BTreeMap<secp256k1::PublicKey, KeySource> = Default::default();
1421
1422 let mut sk: Xpriv = Xpriv::new_master(NetworkKind::Main, &seed).unwrap();
1423
1424 let fprint = sk.fingerprint(secp);
1425
1426 let dpath: Vec<ChildNumber> = vec![
1427 ChildNumber::from_normal_idx(0).unwrap(),
1428 ChildNumber::from_normal_idx(1).unwrap(),
1429 ChildNumber::from_normal_idx(2).unwrap(),
1430 ChildNumber::from_normal_idx(4).unwrap(),
1431 ChildNumber::from_normal_idx(42).unwrap(),
1432 ChildNumber::from_hardened_idx(69).unwrap(),
1433 ChildNumber::from_normal_idx(420).unwrap(),
1434 ChildNumber::from_normal_idx(31337).unwrap(),
1435 ];
1436
1437 sk = sk.derive_priv(secp, &dpath).unwrap();
1438
1439 let pk = Xpub::from_priv(secp, &sk);
1440
1441 hd_keypaths.insert(pk.public_key, (fprint, dpath.into()));
1442
1443 let expected: Output = Output {
1444 redeem_script: Some(
1445 ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
1446 ),
1447 witness_script: Some(
1448 ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
1449 ),
1450 bip32_derivation: hd_keypaths,
1451 ..Default::default()
1452 };
1453
1454 let actual = Output::deserialize(&expected.serialize()).unwrap();
1455
1456 assert_eq!(expected, actual);
1457 }
1458
1459 #[test]
1460 fn serialize_then_deserialize_global() {
1461 let expected = Psbt {
1462 unsigned_tx: Transaction {
1463 version: transaction::Version::TWO,
1464 lock_time: absolute::LockTime::from_consensus(1257139),
1465 input: vec![TxIn {
1466 previous_output: OutPoint {
1467 txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126"
1468 .parse()
1469 .unwrap(),
1470 vout: 0,
1471 },
1472 script_sig: ScriptBuf::new(),
1473 sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
1474 witness: Witness::default(),
1475 }],
1476 output: vec![
1477 TxOut {
1478 value: Amount::from_sat(99_999_699),
1479 script_pubkey: ScriptBuf::from_hex(
1480 "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac",
1481 )
1482 .unwrap(),
1483 },
1484 TxOut {
1485 value: Amount::from_sat(100_000_000),
1486 script_pubkey: ScriptBuf::from_hex(
1487 "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787",
1488 )
1489 .unwrap(),
1490 },
1491 ],
1492 },
1493 xpub: Default::default(),
1494 version: 0,
1495 proprietary: Default::default(),
1496 unknown: Default::default(),
1497 inputs: vec![Input::default()],
1498 outputs: vec![Output::default(), Output::default()],
1499 };
1500
1501 let actual: Psbt = Psbt::deserialize(&expected.serialize()).unwrap();
1502 assert_eq!(expected, actual);
1503 }
1504
1505 #[test]
1506 fn serialize_then_deserialize_psbtkvpair() {
1507 let expected = raw::Pair {
1508 key: raw::Key { type_value: 0u8, key: vec![42u8, 69u8] },
1509 value: vec![69u8, 42u8, 4u8],
1510 };
1511
1512 let actual = raw::Pair::deserialize(&expected.serialize()).unwrap();
1513
1514 assert_eq!(expected, actual);
1515 }
1516
1517 #[test]
1518 fn deserialize_and_serialize_psbt_with_two_partial_sigs() {
1519 let hex = "70736274ff0100890200000001207ae985d787dfe6143d5c58fad79cc7105e0e799fcf033b7f2ba17e62d7b3200000000000ffffffff02563d03000000000022002019899534b9a011043c0dd57c3ff9a381c3522c5f27c6a42319085b56ca543a1d6adc020000000000220020618b47a07ebecca4e156edb1b9ea7c24bdee0139fc049237965ffdaf56d5ee73000000000001012b801a0600000000002200201148e93e9315e37dbed2121be5239257af35adc03ffdfc5d914b083afa44dab82202025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee076473044022007e06b362e89912abd4661f47945430739b006a85d1b2a16c01dc1a4bd07acab022061576d7aa834988b7ab94ef21d8eebd996ea59ea20529a19b15f0c9cebe3d8ac01220202b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a473044022002787f926d6817504431ee281183b8119b6845bfaa6befae45e13b6d430c9d2f02202859f149a6cd26ae2f03a107e7f33c7d91730dade305fe077bae677b5d44952a01010547522102b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a21025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee07652ae0001014752210283ef76537f2d58ae3aa3a4bd8ae41c3f230ccadffb1a0bd3ca504d871cff05e7210353d79cc0cb1396f4ce278d005f16d948e02a6aec9ed1109f13747ecb1507b37b52ae00010147522102b3937241777b6665e0d694e52f9c1b188433641df852da6fc42187b5d8a368a321034cdd474f01cc5aa7ff834ad8bcc882a87e854affc775486bc2a9f62e8f49bd7852ae00";
1520 let psbt: Psbt = hex_psbt(hex).unwrap();
1521 assert_eq!(hex, psbt.serialize_hex());
1522 }
1523
1524 #[cfg(feature = "serde")]
1525 #[test]
1526 fn test_serde_psbt() {
1527 use hashes::sha256d;
1529
1530 use crate::psbt::map::Input;
1531
1532 let tx = Transaction {
1534 version: transaction::Version::ONE,
1535 lock_time: absolute::LockTime::ZERO,
1536 input: vec![TxIn {
1537 previous_output: OutPoint {
1538 txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389"
1539 .parse()
1540 .unwrap(),
1541 vout: 1,
1542 },
1543 script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985")
1544 .unwrap(),
1545 sequence: Sequence::MAX,
1546 witness: Witness::from_slice(&[hex!(
1547 "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"
1548 )]),
1549 }],
1550 output: vec![TxOut {
1551 value: Amount::from_sat(190_303_501_938),
1552 script_pubkey: ScriptBuf::from_hex(
1553 "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587",
1554 )
1555 .unwrap(),
1556 }],
1557 };
1558 let unknown: BTreeMap<raw::Key, Vec<u8>> =
1559 vec![(raw::Key { type_value: 1, key: vec![0, 1] }, vec![3, 4, 5])]
1560 .into_iter()
1561 .collect();
1562 let key_source = ("deadbeef".parse().unwrap(), "0'/1".parse().unwrap());
1563 let keypaths: BTreeMap<secp256k1::PublicKey, KeySource> = vec![(
1564 "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
1565 key_source.clone(),
1566 )]
1567 .into_iter()
1568 .collect();
1569
1570 let proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = vec![(
1571 raw::ProprietaryKey {
1572 prefix: "prefx".as_bytes().to_vec(),
1573 subtype: 42,
1574 key: "test_key".as_bytes().to_vec(),
1575 },
1576 vec![5, 6, 7],
1577 )]
1578 .into_iter()
1579 .collect();
1580
1581 let psbt = Psbt {
1582 version: 0,
1583 xpub: {
1584 let xpub: Xpub =
1585 "xpub661MyMwAqRbcGoRVtwfvzZsq2VBJR1LAHfQstHUoxqDorV89vRoMxUZ27kLrraAj6MPi\
1586 QfrDb27gigC1VS1dBXi5jGpxmMeBXEkKkcXUTg4".parse().unwrap();
1587 vec![(xpub, key_source)].into_iter().collect()
1588 },
1589 unsigned_tx: {
1590 let mut unsigned = tx.clone();
1591 unsigned.input[0].script_sig = ScriptBuf::new();
1592 unsigned.input[0].witness = Witness::default();
1593 unsigned
1594 },
1595 proprietary: proprietary.clone(),
1596 unknown: unknown.clone(),
1597
1598 inputs: vec![
1599 Input {
1600 non_witness_utxo: Some(tx),
1601 witness_utxo: Some(TxOut {
1602 value: Amount::from_sat(190_303_501_938),
1603 script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
1604 }),
1605 sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<PsbtSighashType>().unwrap()),
1606 redeem_script: Some(vec![0x51].into()),
1607 witness_script: None,
1608 partial_sigs: vec![(
1609 "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
1610 "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(),
1611 )].into_iter().collect(),
1612 bip32_derivation: keypaths.clone(),
1613 final_script_witness: Some(Witness::from_slice(&[vec![1, 3], vec![5]])),
1614 ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
1615 sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
1616 hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
1617 hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
1618 proprietary: proprietary.clone(),
1619 unknown: unknown.clone(),
1620 ..Default::default()
1621 }
1622 ],
1623 outputs: vec![
1624 Output {
1625 bip32_derivation: keypaths,
1626 proprietary,
1627 unknown,
1628 ..Default::default()
1629 }
1630 ],
1631 };
1632 let encoded = serde_json::to_string(&psbt).unwrap();
1633 let decoded: Psbt = serde_json::from_str(&encoded).unwrap();
1634 assert_eq!(psbt, decoded);
1635 }
1636
1637 mod bip_vectors {
1638 #[cfg(feature = "base64")]
1639 use std::str::FromStr;
1640
1641 use super::*;
1642 use crate::psbt::map::Map;
1643
1644 #[test]
1645 #[should_panic(expected = "InvalidMagic")]
1646 fn invalid_vector_1() {
1647 hex_psbt("0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300").unwrap();
1648 }
1649
1650 #[cfg(feature = "base64")]
1651 #[test]
1652 #[should_panic(expected = "InvalidMagic")]
1653 fn invalid_vector_1_base64() {
1654 Psbt::from_str("AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA==").unwrap();
1655 }
1656
1657 #[test]
1658 #[should_panic(expected = "ConsensusEncoding")]
1659 fn invalid_vector_2() {
1660 hex_psbt("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000")
1661 .unwrap();
1662 }
1663
1664 #[cfg(feature = "base64")]
1665 #[test]
1666 #[should_panic(expected = "ConsensusEncoding")]
1667 fn invalid_vector_2_base64() {
1668 Psbt::from_str("cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==")
1669 .unwrap();
1670 }
1671
1672 #[test]
1673 #[should_panic(expected = "UnsignedTxHasScriptSigs")]
1674 fn invalid_vector_3() {
1675 hex_psbt("70736274ff0100fd0a010200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be4000000006a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa88292feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
1676 }
1677
1678 #[cfg(feature = "base64")]
1679 #[test]
1680 #[should_panic(expected = "UnsignedTxHasScriptSigs")]
1681 fn invalid_vector_3_base64() {
1682 Psbt::from_str("cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA=").unwrap();
1683 }
1684
1685 #[test]
1686 #[should_panic(expected = "MustHaveUnsignedTx")]
1687 fn invalid_vector_4() {
1688 hex_psbt("70736274ff000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000").unwrap();
1689 }
1690
1691 #[cfg(feature = "base64")]
1692 #[test]
1693 #[should_panic(expected = "MustHaveUnsignedTx")]
1694 fn invalid_vector_4_base64() {
1695 Psbt::from_str("cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==").unwrap();
1696 }
1697
1698 #[test]
1699 #[should_panic(expected = "DuplicateKey(Key { type_value: 0, key: [] })")]
1700 fn invalid_vector_5() {
1701 hex_psbt("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000000").unwrap();
1702 }
1703
1704 #[cfg(feature = "base64")]
1705 #[test]
1706 #[should_panic(expected = "DuplicateKey(Key { type_value: 0, key: [] })")]
1707 fn invalid_vector_5_base64() {
1708 Psbt::from_str("cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAQA/AgAAAAH//////////////////////////////////////////wAAAAAA/////wEAAAAAAAAAAANqAQAAAAAAAAAA").unwrap();
1709 }
1710
1711 #[test]
1712 fn valid_vector_1() {
1713 let unserialized = Psbt {
1714 unsigned_tx: Transaction {
1715 version: transaction::Version::TWO,
1716 lock_time: absolute::LockTime::from_consensus(1257139),
1717 input: vec![
1718 TxIn {
1719 previous_output: OutPoint {
1720 txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
1721 vout: 0,
1722 },
1723 script_sig: ScriptBuf::new(),
1724 sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
1725 witness: Witness::default(),
1726 }
1727 ],
1728 output: vec![
1729 TxOut {
1730 value: Amount::from_sat(99_999_699),
1731 script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
1732 },
1733 TxOut {
1734 value: Amount::from_sat(100_000_000),
1735 script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
1736 },
1737 ],
1738 },
1739 xpub: Default::default(),
1740 version: 0,
1741 proprietary: BTreeMap::new(),
1742 unknown: BTreeMap::new(),
1743
1744 inputs: vec![
1745 Input {
1746 non_witness_utxo: Some(Transaction {
1747 version: transaction::Version::ONE,
1748 lock_time: absolute::LockTime::ZERO,
1749 input: vec![
1750 TxIn {
1751 previous_output: OutPoint {
1752 txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
1753 vout: 1,
1754 },
1755 script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
1756 sequence: Sequence::MAX,
1757 witness: Witness::from_slice(&[
1758 hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"),
1759 hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"),
1760 ]),
1761 },
1762 TxIn {
1763 previous_output: OutPoint {
1764 txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
1765 vout: 1,
1766 },
1767 script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
1768 sequence: Sequence::MAX,
1769 witness: Witness::from_slice(&[
1770 hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"),
1771 hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"),
1772 ]),
1773 }
1774 ],
1775 output: vec![
1776 TxOut {
1777 value: Amount::from_sat(200_000_000),
1778 script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
1779 },
1780 TxOut {
1781 value: Amount::from_sat(190_303_501_938),
1782 script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
1783 },
1784 ],
1785 }),
1786 ..Default::default()
1787 },
1788 ],
1789 outputs: vec![
1790 Output {
1791 ..Default::default()
1792 },
1793 Output {
1794 ..Default::default()
1795 },
1796 ],
1797 };
1798
1799 let base16str = "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000";
1800
1801 assert_eq!(unserialized.serialize_hex(), base16str);
1802 assert_eq!(unserialized, hex_psbt(base16str).unwrap());
1803
1804 #[cfg(feature = "base64")]
1805 {
1806 let base64str = "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA";
1807 assert_eq!(Psbt::from_str(base64str).unwrap(), unserialized);
1808 assert_eq!(base64str, unserialized.to_string());
1809 assert_eq!(Psbt::from_str(base64str).unwrap(), hex_psbt(base16str).unwrap());
1810 }
1811 }
1812
1813 #[test]
1814 fn valid_vector_2() {
1815 let psbt: Psbt = hex_psbt("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
1816
1817 assert_eq!(psbt.inputs.len(), 2);
1818 assert_eq!(psbt.outputs.len(), 2);
1819
1820 assert!(&psbt.inputs[0].final_script_sig.is_some());
1821
1822 let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
1823 let expected_out =
1824 ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap();
1825
1826 assert!(redeem_script.is_p2wpkh());
1827 assert_eq!(
1828 redeem_script.to_p2sh(),
1829 psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey
1830 );
1831 assert_eq!(redeem_script.to_p2sh(), expected_out);
1832
1833 for output in psbt.outputs {
1834 assert_eq!(output.get_pairs().len(), 0)
1835 }
1836 }
1837
1838 #[test]
1839 fn valid_vector_3() {
1840 let psbt: Psbt = hex_psbt("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000").unwrap();
1841
1842 assert_eq!(psbt.inputs.len(), 1);
1843 assert_eq!(psbt.outputs.len(), 2);
1844
1845 let tx_input = &psbt.unsigned_tx.input[0];
1846 let psbt_non_witness_utxo = psbt.inputs[0].non_witness_utxo.as_ref().unwrap();
1847
1848 assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.compute_txid());
1849 assert!(psbt_non_witness_utxo.output[tx_input.previous_output.vout as usize]
1850 .script_pubkey
1851 .is_p2pkh());
1852 assert_eq!(
1853 psbt.inputs[0].sighash_type.as_ref().unwrap().ecdsa_hash_ty().unwrap(),
1854 EcdsaSighashType::All
1855 );
1856 }
1857
1858 #[test]
1859 fn valid_vector_4() {
1860 let psbt: Psbt = hex_psbt("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000").unwrap();
1861
1862 assert_eq!(psbt.inputs.len(), 2);
1863 assert_eq!(psbt.outputs.len(), 2);
1864
1865 assert!(&psbt.inputs[0].final_script_sig.is_none());
1866 assert!(&psbt.inputs[1].final_script_sig.is_none());
1867
1868 let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap();
1869 let expected_out =
1870 ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap();
1871
1872 assert!(redeem_script.is_p2wpkh());
1873 assert_eq!(
1874 redeem_script.to_p2sh(),
1875 psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey
1876 );
1877 assert_eq!(redeem_script.to_p2sh(), expected_out);
1878
1879 for output in psbt.outputs {
1880 assert!(!output.get_pairs().is_empty())
1881 }
1882 }
1883
1884 #[test]
1885 fn valid_vector_5() {
1886 let psbt: Psbt = hex_psbt("70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000").unwrap();
1887
1888 assert_eq!(psbt.inputs.len(), 1);
1889 assert_eq!(psbt.outputs.len(), 1);
1890
1891 assert!(&psbt.inputs[0].final_script_sig.is_none());
1892
1893 let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap();
1894 let expected_out =
1895 ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap();
1896
1897 assert!(redeem_script.is_p2wsh());
1898 assert_eq!(
1899 redeem_script.to_p2sh(),
1900 psbt.inputs[0].witness_utxo.as_ref().unwrap().script_pubkey
1901 );
1902
1903 assert_eq!(redeem_script.to_p2sh(), expected_out);
1904 }
1905
1906 #[test]
1907 fn valid_vector_6() {
1908 let psbt: Psbt = hex_psbt("70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000").unwrap();
1909
1910 assert_eq!(psbt.inputs.len(), 1);
1911 assert_eq!(psbt.outputs.len(), 1);
1912
1913 let tx = &psbt.unsigned_tx;
1914 assert_eq!(
1915 tx.compute_txid(),
1916 "75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115".parse().unwrap(),
1917 );
1918
1919 let mut unknown: BTreeMap<raw::Key, Vec<u8>> = BTreeMap::new();
1920 let key: raw::Key = raw::Key { type_value: 0x0fu8, key: hex!("010203040506070809") };
1921 let value: Vec<u8> = hex!("0102030405060708090a0b0c0d0e0f");
1922
1923 unknown.insert(key, value);
1924
1925 assert_eq!(psbt.inputs[0].unknown, unknown)
1926 }
1927 }
1928
1929 mod bip_371_vectors {
1930 use super::*;
1931
1932 #[test]
1933 fn invalid_vectors() {
1934 let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a075701172102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232000000").unwrap_err();
1935 assert_eq!(err.to_string(), "invalid xonly public key");
1936 let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011342173bb3d36c074afb716fec6307a069a2e450b995f3c82785945ab8df0e24260dcd703b0cbf34de399184a9481ac2b3586db6601f026a77f7e4938481bc34751701aa000000").unwrap_err();
1937 #[cfg(feature = "std")]
1938 assert_eq!(err.to_string(), "invalid taproot signature");
1939 #[cfg(not(feature = "std"))]
1940 assert_eq!(
1941 err.to_string(),
1942 "invalid taproot signature: invalid taproot signature size: 66"
1943 );
1944 let err = hex_psbt("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err();
1945 assert_eq!(err.to_string(), "invalid xonly public key");
1946 let err = hex_psbt("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000001052102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa23200").unwrap_err();
1947 assert_eq!(err.to_string(), "invalid xonly public key");
1948 let err = hex_psbt("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07570000220702fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da7560000800100008000000080010000000000000000").unwrap_err();
1949 assert_eq!(err.to_string(), "invalid xonly public key");
1950 let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6924214022cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094089756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err();
1951 #[cfg(feature = "std")]
1952 assert_eq!(err.to_string(), "invalid hash when parsing slice");
1953 #[cfg(not(feature = "std"))]
1954 assert_eq!(
1955 err.to_string(),
1956 "invalid hash when parsing slice: invalid slice length 33 (expected 32)"
1957 );
1958 let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err();
1959 #[cfg(feature = "std")]
1960 assert_eq!(err.to_string(), "invalid taproot signature");
1961 #[cfg(not(feature = "std"))]
1962 assert_eq!(
1963 err.to_string(),
1964 "invalid taproot signature: invalid taproot signature size: 66"
1965 );
1966 let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err();
1967 #[cfg(feature = "std")]
1968 assert_eq!(err.to_string(), "invalid taproot signature");
1969 #[cfg(not(feature = "std"))]
1970 assert_eq!(
1971 err.to_string(),
1972 "invalid taproot signature: invalid taproot signature size: 57"
1973 );
1974 let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
1975 assert_eq!(err.to_string(), "invalid control block");
1976 let err = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926115c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e123202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
1977 assert_eq!(err.to_string(), "invalid control block");
1978 }
1979
1980 fn rtt_psbt(psbt: Psbt) {
1981 let enc = Psbt::serialize(&psbt);
1982 let psbt2 = Psbt::deserialize(&enc).unwrap();
1983 assert_eq!(psbt, psbt2);
1984 }
1985
1986 #[test]
1987 fn valid_psbt_vectors() {
1988 let psbt = hex_psbt("70736274ff010052020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a01000000160014768e1eeb4cf420866033f80aceff0f9720744969000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232002202036b772a6db74d8753c98a827958de6c78ab3312109f37d3e0304484242ece73d818772b2da7540000800100008000000080000000000000000000").unwrap();
1989 let internal_key = psbt.inputs[0].tap_internal_key.unwrap();
1990 assert!(psbt.inputs[0].tap_key_origins.contains_key(&internal_key));
1991 rtt_psbt(psbt);
1992
1993 let psbt = hex_psbt("70736274ff010052020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a01000000160014768e1eeb4cf420866033f80aceff0f9720744969000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011340bb53ec917bad9d906af1ba87181c48b86ace5aae2b53605a725ca74625631476fc6f5baedaf4f2ee0f477f36f58f3970d5b8273b7e497b97af2e3f125c97af342116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232002202036b772a6db74d8753c98a827958de6c78ab3312109f37d3e0304484242ece73d818772b2da7540000800100008000000080000000000000000000").unwrap();
1995 let internal_key = psbt.inputs[0].tap_internal_key.unwrap();
1996 assert!(psbt.inputs[0].tap_key_origins.contains_key(&internal_key));
1997 assert!(psbt.inputs[0].tap_key_sig.is_some());
1998 rtt_psbt(psbt);
1999
2000 let psbt = hex_psbt("70736274ff01005e020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap();
2002 let internal_key = psbt.outputs[0].tap_internal_key.unwrap();
2003 assert!(psbt.outputs[0].tap_key_origins.contains_key(&internal_key));
2004 rtt_psbt(psbt);
2005
2006 let psbt = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f823202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc04215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac097c6e6fea5ff714ff5724499990810e406e98aa10f5bf7e5f6784bc1d0a9a6ce23204320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2acc06215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f82320fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca9acc021162cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d23901cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09772b2da7560000800100008002000080000000000000000021164320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b23901115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f8772b2da75600008001000080010000800000000000000000211650929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2116fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca939016f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970772b2da7560000800100008003000080000000000000000001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820f0362e2f75a6f420a5bde3eb221d96ae6720cf25f81890c95b1d775acb515e65000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap();
2008 assert!(psbt.inputs[0].tap_internal_key.is_some());
2009 assert!(psbt.inputs[0].tap_merkle_root.is_some());
2010 assert!(!psbt.inputs[0].tap_key_origins.is_empty());
2011 assert!(!psbt.inputs[0].tap_scripts.is_empty());
2012 rtt_psbt(psbt);
2013
2014 let psbt = hex_psbt("70736274ff01005e020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a010000002251200a8cbdc86de1ce1c0f9caeb22d6df7ced3683fe423e05d1e402a879341d6f6f5000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2320001052050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac001066f02c02220736e572900fe1252589a2143c8f3c79f71a0412d2353af755e9701c782694a02ac02c02220631c5f3b5832b8fbdebfb19704ceeb323c21f40f7a24f43d68ef0cc26b125969ac01c0222044faa49a0338de488c8dfffecdfb6f329f380bd566ef20c8df6d813eab1c4273ac210744faa49a0338de488c8dfffecdfb6f329f380bd566ef20c8df6d813eab1c42733901f06b798b92a10ed9a9d0bbfd3af173a53b1617da3a4159ca008216cd856b2e0e772b2da75600008001000080010000800000000003000000210750929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2107631c5f3b5832b8fbdebfb19704ceeb323c21f40f7a24f43d68ef0cc26b125969390118ace409889785e0ea70ceebb8e1ca892a7a78eaede0f2e296cf435961a8f4ca772b2da756000080010000800200008000000000030000002107736e572900fe1252589a2143c8f3c79f71a0412d2353af755e9701c782694a02390129a5b4915090162d759afd3fe0f93fa3326056d0b4088cb933cae7826cb8d82c772b2da7560000800100008003000080000000000300000000").unwrap();
2016 assert!(psbt.outputs[0].tap_internal_key.is_some());
2017 assert!(!psbt.outputs[0].tap_key_origins.is_empty());
2018 assert!(psbt.outputs[0].tap_tree.is_some());
2019 rtt_psbt(psbt);
2020
2021 let psbt = hex_psbt("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b0940bf818d9757d6ffeb538ba057fb4c1fc4e0f5ef186e765beb564791e02af5fd3d5e2551d4e34e33d86f276b82c99c79aed3f0395a081efcd2cc2c65dd7e693d7941144320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f840e1f1ab6fabfa26b236f21833719dc1d428ab768d80f91f9988d8abef47bfb863bb1f2a529f768c15f00ce34ec283cdc07e88f8428be28f6ef64043c32911811a4114fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca96f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae97040ec1f0379206461c83342285423326708ab031f0da4a253ee45aafa5b8c92034d8b605490f8cd13e00f989989b97e215faa36f12dee3693d2daccf3781c1757f66215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f823202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc04215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac097c6e6fea5ff714ff5724499990810e406e98aa10f5bf7e5f6784bc1d0a9a6ce23204320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2acc06215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f82320fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca9acc021162cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d23901cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09772b2da7560000800100008002000080000000000000000021164320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b23901115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f8772b2da75600008001000080010000800000000000000000211650929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2116fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca939016f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970772b2da7560000800100008003000080000000000000000001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820f0362e2f75a6f420a5bde3eb221d96ae6720cf25f81890c95b1d775acb515e65000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap();
2023 assert!(psbt.inputs[0].tap_internal_key.is_some());
2024 assert!(psbt.inputs[0].tap_merkle_root.is_some());
2025 assert!(!psbt.inputs[0].tap_scripts.is_empty());
2026 assert!(!psbt.inputs[0].tap_script_sigs.is_empty());
2027 assert!(!psbt.inputs[0].tap_key_origins.is_empty());
2028 rtt_psbt(psbt);
2029 }
2030 }
2031
2032 #[test]
2033 fn serialize_and_deserialize_preimage_psbt() {
2034 let mut sha256_preimages = BTreeMap::new();
2036 sha256_preimages.insert(sha256::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]);
2037 sha256_preimages.insert(sha256::Hash::hash(&[1u8]), vec![1u8]);
2038
2039 let mut hash160_preimages = BTreeMap::new();
2041 hash160_preimages.insert(hash160::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]);
2042 hash160_preimages.insert(hash160::Hash::hash(&[1u8]), vec![1u8]);
2043
2044 let mut unserialized = Psbt {
2046 unsigned_tx: Transaction {
2047 version: transaction::Version::TWO,
2048 lock_time: absolute::LockTime::from_consensus(1257139),
2049 input: vec![
2050 TxIn {
2051 previous_output: OutPoint {
2052 txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
2053 vout: 0,
2054 },
2055 script_sig: ScriptBuf::new(),
2056 sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
2057 witness: Witness::default(),
2058 }
2059 ],
2060 output: vec![
2061 TxOut {
2062 value: Amount::from_sat(99_999_699),
2063 script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(),
2064 },
2065 TxOut {
2066 value: Amount::from_sat(100_000_000),
2067 script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(),
2068 },
2069 ],
2070 },
2071 version: 0,
2072 xpub: Default::default(),
2073 proprietary: Default::default(),
2074 unknown: BTreeMap::new(),
2075
2076 inputs: vec![
2077 Input {
2078 non_witness_utxo: Some(Transaction {
2079 version: transaction::Version::ONE,
2080 lock_time: absolute::LockTime::ZERO,
2081 input: vec![
2082 TxIn {
2083 previous_output: OutPoint {
2084 txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
2085 vout: 1,
2086 },
2087 script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(),
2088 sequence: Sequence::MAX,
2089 witness: Witness::from_slice(&[
2090 hex!("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01"),
2091 hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105"),
2092 ]),
2093 },
2094 TxIn {
2095 previous_output: OutPoint {
2096 txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
2097 vout: 1,
2098 },
2099 script_sig: ScriptBuf::from_hex("160014fe3e9ef1a745e974d902c4355943abcb34bd5353").unwrap(),
2100 sequence: Sequence::MAX,
2101 witness: Witness::from_slice(&[
2102 hex!("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01"),
2103 hex!("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3"),
2104 ]),
2105 }
2106 ],
2107 output: vec![
2108 TxOut {
2109 value: Amount::from_sat(200_000_000),
2110 script_pubkey: ScriptBuf::from_hex("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac").unwrap(),
2111 },
2112 TxOut {
2113 value: Amount::from_sat(190_303_501_938),
2114 script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(),
2115 },
2116 ],
2117 }),
2118 ..Default::default()
2119 },
2120 ],
2121 outputs: vec![
2122 Output {
2123 ..Default::default()
2124 },
2125 Output {
2126 ..Default::default()
2127 },
2128 ],
2129 };
2130 unserialized.inputs[0].hash160_preimages = hash160_preimages;
2131 unserialized.inputs[0].sha256_preimages = sha256_preimages;
2132
2133 let rtt: Psbt = hex_psbt(&unserialized.serialize_hex()).unwrap();
2134 assert_eq!(rtt, unserialized);
2135
2136 let mut ripemd160_preimages = BTreeMap::new();
2138 ripemd160_preimages.insert(ripemd160::Hash::hash(&[17u8]), vec![18u8]);
2139 unserialized.inputs[0].ripemd160_preimages = ripemd160_preimages;
2140
2141 let rtt: Result<Psbt, _> = hex_psbt(&unserialized.serialize_hex());
2143 assert!(rtt.is_err());
2144 }
2145
2146 #[test]
2147 fn serialize_and_deserialize_proprietary() {
2148 let mut psbt: Psbt = hex_psbt("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
2149 psbt.proprietary.insert(
2150 raw::ProprietaryKey { prefix: b"test".to_vec(), subtype: 0u8, key: b"test".to_vec() },
2151 b"test".to_vec(),
2152 );
2153 assert!(!psbt.proprietary.is_empty());
2154 let rtt: Psbt = hex_psbt(&psbt.serialize_hex()).unwrap();
2155 assert!(!rtt.proprietary.is_empty());
2156 }
2157
2158 #[test]
2160 fn combine_psbts() {
2161 let mut psbt1 = hex_psbt(include_str!("../../tests/data/psbt1.hex")).unwrap();
2162 let psbt2 = hex_psbt(include_str!("../../tests/data/psbt2.hex")).unwrap();
2163 let psbt_combined = hex_psbt(include_str!("../../tests/data/psbt2.hex")).unwrap();
2164
2165 psbt1.combine(psbt2).expect("psbt combine to succeed");
2166 assert_eq!(psbt1, psbt_combined);
2167 }
2168
2169 #[test]
2170 fn combine_psbts_commutative() {
2171 let mut psbt1 = hex_psbt(include_str!("../../tests/data/psbt1.hex")).unwrap();
2172 let mut psbt2 = hex_psbt(include_str!("../../tests/data/psbt2.hex")).unwrap();
2173
2174 let psbt1_clone = psbt1.clone();
2175 let psbt2_clone = psbt2.clone();
2176
2177 psbt1.combine(psbt2_clone).expect("psbt1 combine to succeed");
2178 psbt2.combine(psbt1_clone).expect("psbt2 combine to succeed");
2179
2180 assert_eq!(psbt1, psbt2);
2181 }
2182
2183 #[cfg(feature = "rand-std")]
2184 fn gen_keys() -> (PrivateKey, PublicKey, Secp256k1<All>) {
2185 use secp256k1::rand::thread_rng;
2186
2187 let secp = Secp256k1::new();
2188
2189 let sk = SecretKey::new(&mut thread_rng());
2190 let priv_key = PrivateKey::new(sk, NetworkKind::Test);
2191 let pk = PublicKey::from_private_key(&secp, &priv_key);
2192
2193 (priv_key, pk, secp)
2194 }
2195
2196 #[test]
2197 #[cfg(feature = "rand-std")]
2198 fn get_key_btree_map() {
2199 let (priv_key, pk, secp) = gen_keys();
2200
2201 let mut key_map = BTreeMap::new();
2202 key_map.insert(pk, priv_key);
2203
2204 let got = key_map.get_key(KeyRequest::Pubkey(pk), &secp).expect("failed to get key");
2205 assert_eq!(got.unwrap(), priv_key)
2206 }
2207
2208 #[test]
2209 #[cfg(feature = "rand-std")]
2210 fn pubkey_map_get_key_negates_odd_parity_keys() {
2211 use crate::psbt::{GetKey, KeyRequest};
2212
2213 let (mut priv_key, mut pk, secp) = gen_keys();
2214 let (xonly, parity) = pk.inner.x_only_public_key();
2215
2216 let mut pubkey_map: HashMap<PublicKey, PrivateKey> = HashMap::new();
2217
2218 if parity == secp256k1::Parity::Even {
2219 priv_key = PrivateKey {
2220 compressed: priv_key.compressed,
2221 network: priv_key.network,
2222 inner: priv_key.inner.negate(),
2223 };
2224 pk = priv_key.public_key(&secp);
2225 }
2226
2227 pubkey_map.insert(pk, priv_key);
2228
2229 let req_result = pubkey_map.get_key(KeyRequest::XOnlyPubkey(xonly), &secp).unwrap();
2230
2231 let retrieved_key = req_result.unwrap();
2232
2233 let retrieved_pub_key = retrieved_key.public_key(&secp);
2234 let (retrieved_xonly, retrieved_parity) = retrieved_pub_key.inner.x_only_public_key();
2235
2236 assert_eq!(xonly, retrieved_xonly);
2237 assert_eq!(
2238 retrieved_parity,
2239 secp256k1::Parity::Even,
2240 "Key should be normalized to have even parity, even when original had odd parity"
2241 );
2242 }
2243
2244 #[test]
2245 fn fee() {
2246 let output_0_val = Amount::from_sat(99_999_699);
2247 let output_1_val = Amount::from_sat(100_000_000);
2248 let prev_output_val = Amount::from_sat(200_000_000);
2249
2250 let mut t = Psbt {
2251 unsigned_tx: Transaction {
2252 version: transaction::Version::TWO,
2253 lock_time: absolute::LockTime::from_consensus(1257139),
2254 input: vec![
2255 TxIn {
2256 previous_output: OutPoint {
2257 txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(),
2258 vout: 0,
2259 },
2260 sequence: Sequence::ENABLE_LOCKTIME_NO_RBF,
2261 ..Default::default()
2262 }
2263 ],
2264 output: vec![
2265 TxOut {
2266 value: output_0_val,
2267 script_pubkey: ScriptBuf::new()
2268 },
2269 TxOut {
2270 value: output_1_val,
2271 script_pubkey: ScriptBuf::new()
2272 },
2273 ],
2274 },
2275 xpub: Default::default(),
2276 version: 0,
2277 proprietary: BTreeMap::new(),
2278 unknown: BTreeMap::new(),
2279
2280 inputs: vec![
2281 Input {
2282 non_witness_utxo: Some(Transaction {
2283 version: transaction::Version::ONE,
2284 lock_time: absolute::LockTime::ZERO,
2285 input: vec![
2286 TxIn {
2287 previous_output: OutPoint {
2288 txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(),
2289 vout: 1,
2290 },
2291 sequence: Sequence::MAX,
2292 ..Default::default()
2293 },
2294 TxIn {
2295 previous_output: OutPoint {
2296 txid: "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886".parse().unwrap(),
2297 vout: 1,
2298 },
2299 sequence: Sequence::MAX,
2300 ..Default::default()
2301 }
2302 ],
2303 output: vec![
2304 TxOut {
2305 value: prev_output_val,
2306 script_pubkey: ScriptBuf::new()
2307 },
2308 TxOut {
2309 value: Amount::from_sat(190_303_501_938),
2310 script_pubkey: ScriptBuf::new()
2311 },
2312 ],
2313 }),
2314 ..Default::default()
2315 },
2316 ],
2317 outputs: vec![
2318 Output {
2319 ..Default::default()
2320 },
2321 Output {
2322 ..Default::default()
2323 },
2324 ],
2325 };
2326 assert_eq!(
2327 t.fee().expect("fee calculation"),
2328 prev_output_val - (output_0_val + output_1_val)
2329 );
2330 let mut t2 = t.clone();
2332 t2.inputs[0].non_witness_utxo = None;
2333 match t2.fee().unwrap_err() {
2334 Error::MissingUtxo => {}
2335 e => panic!("unexpected error: {:?}", e),
2336 }
2337 let mut t3 = t.clone();
2339 t3.unsigned_tx.output[0].value = prev_output_val;
2340 match t3.fee().unwrap_err() {
2341 Error::NegativeFee => {}
2342 e => panic!("unexpected error: {:?}", e),
2343 }
2344 t.unsigned_tx.output[0].value = Amount::MAX;
2346 t.unsigned_tx.output[1].value = Amount::MAX;
2347 match t.fee().unwrap_err() {
2348 Error::FeeOverflow => {}
2349 e => panic!("unexpected error: {:?}", e),
2350 }
2351 }
2352
2353 #[test]
2354 #[cfg(feature = "rand-std")]
2355 fn hashmap_can_sign_taproot() {
2356 let (priv_key, pk, secp) = gen_keys();
2357 let internal_key: XOnlyPublicKey = pk.inner.into();
2358
2359 let tx = Transaction {
2360 version: transaction::Version::TWO,
2361 lock_time: locktime::absolute::LockTime::ZERO,
2362 input: vec![TxIn::default()],
2363 output: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptBuf::new() }],
2364 };
2365
2366 let mut psbt = Psbt::from_unsigned_tx(tx).unwrap();
2367 psbt.inputs[0].tap_internal_key = Some(internal_key);
2368 psbt.inputs[0].witness_utxo = Some(transaction::TxOut {
2369 value: Amount::from_sat(10),
2370 script_pubkey: ScriptBuf::new_p2tr(&secp, internal_key, None),
2371 });
2372
2373 let mut key_map: HashMap<PublicKey, PrivateKey> = HashMap::new();
2374 key_map.insert(pk, priv_key);
2375
2376 let key_source = (Fingerprint::default(), DerivationPath::default());
2377 let mut tap_key_origins = std::collections::BTreeMap::new();
2378 tap_key_origins.insert(internal_key, (vec![], key_source));
2379 psbt.inputs[0].tap_key_origins = tap_key_origins;
2380
2381 let signing_keys = psbt.sign(&key_map, &secp).unwrap();
2382 assert_eq!(signing_keys.len(), 1);
2383 assert_eq!(signing_keys[&0], SigningKeys::Schnorr(vec![internal_key]));
2384 }
2385
2386 #[test]
2387 #[cfg(feature = "rand-std")]
2388 fn xonly_hashmap_can_sign_taproot() {
2389 let (priv_key, pk, secp) = gen_keys();
2390 let internal_key: XOnlyPublicKey = pk.inner.into();
2391
2392 let tx = Transaction {
2393 version: transaction::Version::TWO,
2394 lock_time: locktime::absolute::LockTime::ZERO,
2395 input: vec![TxIn::default()],
2396 output: vec![TxOut { value: Amount::ZERO, script_pubkey: ScriptBuf::new() }],
2397 };
2398
2399 let mut psbt = Psbt::from_unsigned_tx(tx).unwrap();
2400 psbt.inputs[0].tap_internal_key = Some(internal_key);
2401 psbt.inputs[0].witness_utxo = Some(transaction::TxOut {
2402 value: Amount::from_sat(10),
2403 script_pubkey: ScriptBuf::new_p2tr(&secp, internal_key, None),
2404 });
2405
2406 let mut xonly_key_map: HashMap<XOnlyPublicKey, PrivateKey> = HashMap::new();
2407 xonly_key_map.insert(internal_key, priv_key);
2408
2409 let key_source = (Fingerprint::default(), DerivationPath::default());
2410 let mut tap_key_origins = std::collections::BTreeMap::new();
2411 tap_key_origins.insert(internal_key, (vec![], key_source));
2412 psbt.inputs[0].tap_key_origins = tap_key_origins;
2413
2414 let signing_keys = psbt.sign(&xonly_key_map, &secp).unwrap();
2415 assert_eq!(signing_keys.len(), 1);
2416 assert_eq!(signing_keys[&0], SigningKeys::Schnorr(vec![internal_key]));
2417 }
2418
2419 #[test]
2420 #[cfg(feature = "rand-std")]
2421 fn sign_psbt() {
2422 let unsigned_tx = Transaction {
2423 version: transaction::Version::TWO,
2424 lock_time: absolute::LockTime::ZERO,
2425 input: vec![TxIn::default(), TxIn::default()],
2426 output: vec![TxOut::NULL],
2427 };
2428 let mut psbt = Psbt::from_unsigned_tx(unsigned_tx).unwrap();
2429
2430 let (priv_key, pk, secp) = gen_keys();
2431
2432 let mut key_map = BTreeMap::new();
2435 key_map.insert(pk, priv_key);
2436
2437 let txout_wpkh = TxOut {
2439 value: Amount::from_sat(10),
2440 script_pubkey: ScriptBuf::new_p2wpkh(&WPubkeyHash::hash(&pk.to_bytes())),
2441 };
2442 psbt.inputs[0].witness_utxo = Some(txout_wpkh);
2443
2444 let mut map = BTreeMap::new();
2445 map.insert(pk.inner, (Fingerprint::default(), DerivationPath::default()));
2446 psbt.inputs[0].bip32_derivation = map;
2447
2448 let unknown_prog = WitnessProgram::new(WitnessVersion::V4, &[0xaa; 34]).unwrap();
2450 let txout_unknown_future = TxOut {
2451 value: Amount::from_sat(10),
2452 script_pubkey: ScriptBuf::new_witness_program(&unknown_prog),
2453 };
2454 psbt.inputs[1].witness_utxo = Some(txout_unknown_future);
2455
2456 let (signing_keys, _) = psbt.sign(&key_map, &secp).unwrap_err();
2457
2458 assert_eq!(signing_keys.len(), 1);
2459 assert_eq!(signing_keys[&0], SigningKeys::Ecdsa(vec![pk]));
2460 }
2461}