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