sapio_bitcoin/util/psbt/
mod.rs

1// Rust Bitcoin Library
2// Written by
3//   The Rust Bitcoin developers
4//
5// To the extent possible under law, the author(s) have dedicated all
6// copyright and related and neighboring rights to this software to
7// the public domain worldwide. This software is distributed without
8// any warranty.
9//
10// You should have received a copy of the CC0 Public Domain Dedication
11// along with this software.
12// If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
13//
14
15//! Partially Signed Bitcoin Transactions.
16//!
17//! Implementation of BIP174 Partially Signed Bitcoin Transaction Format as
18//! defined at <https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki>
19//! except we define PSBTs containing non-standard sighash types as invalid.
20//!
21
22use core::cmp;
23
24use blockdata::script::Script;
25use blockdata::transaction::Transaction;
26use consensus::{encode, Encodable, Decodable};
27use consensus::encode::MAX_VEC_SIZE;
28
29use prelude::*;
30
31use io;
32
33mod error;
34pub use self::error::Error;
35
36pub mod raw;
37
38#[macro_use]
39mod macros;
40
41pub mod serialize;
42
43mod map;
44pub use self::map::{Input, Output, TapTree, PsbtSighashType, IncompleteTapTree};
45use self::map::Map;
46
47use util::bip32::{ExtendedPubKey, KeySource};
48
49/// A Partially Signed Transaction.
50#[derive(Debug, Clone, PartialEq, Eq)]
51#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
52pub struct PartiallySignedTransaction {
53    /// The unsigned transaction, scriptSigs and witnesses for each input must be
54    /// empty.
55    pub unsigned_tx: Transaction,
56    /// The version number of this PSBT. If omitted, the version number is 0.
57    pub version: u32,
58    /// A global map from extended public keys to the used key fingerprint and
59    /// derivation path as defined by BIP 32
60    pub xpub: BTreeMap<ExtendedPubKey, KeySource>,
61    /// Global proprietary key-value pairs.
62    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
63    pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
64    /// Unknown global key-value pairs.
65    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
66    pub unknown: BTreeMap<raw::Key, Vec<u8>>,
67
68    /// The corresponding key-value map for each input in the unsigned
69    /// transaction.
70    pub inputs: Vec<Input>,
71    /// The corresponding key-value map for each output in the unsigned
72    /// transaction.
73    pub outputs: Vec<Output>,
74}
75
76impl PartiallySignedTransaction {
77    /// Checks that unsigned transaction does not have scriptSig's or witness
78    /// data
79    fn unsigned_tx_checks(&self) -> Result<(), Error> {
80        for txin in &self.unsigned_tx.input {
81            if !txin.script_sig.is_empty() {
82                return Err(Error::UnsignedTxHasScriptSigs);
83            }
84
85            if !txin.witness.is_empty() {
86                return Err(Error::UnsignedTxHasScriptWitnesses);
87            }
88        }
89
90        Ok(())
91    }
92
93    /// Create a PartiallySignedTransaction from an unsigned transaction, error
94    /// if not unsigned
95    pub fn from_unsigned_tx(tx: Transaction) -> Result<Self, Error> {
96        let psbt = PartiallySignedTransaction {
97            inputs: vec![Default::default(); tx.input.len()],
98            outputs: vec![Default::default(); tx.output.len()],
99
100            unsigned_tx: tx,
101            xpub: Default::default(),
102            version: 0,
103            proprietary: Default::default(),
104            unknown: Default::default(),
105        };
106        psbt.unsigned_tx_checks()?;
107        Ok(psbt)
108    }
109
110    /// Extract the Transaction from a PartiallySignedTransaction by filling in
111    /// the available signature information in place.
112    pub fn extract_tx(self) -> Transaction {
113        let mut tx: Transaction = self.unsigned_tx;
114
115        for (vin, psbtin) in tx.input.iter_mut().zip(self.inputs.into_iter()) {
116            vin.script_sig = psbtin.final_script_sig.unwrap_or_else(Script::new);
117            vin.witness = psbtin.final_script_witness.unwrap_or_default();
118        }
119
120        tx
121    }
122
123    /// Combines this [`PartiallySignedTransaction`] with `other` PSBT as described by BIP 174.
124    ///
125    /// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
126    pub fn combine(&mut self, other: Self) -> Result<(), Error> {
127        if self.unsigned_tx != other.unsigned_tx {
128            return Err(Error::UnexpectedUnsignedTx {
129                expected: Box::new(self.unsigned_tx.clone()),
130                actual: Box::new(other.unsigned_tx),
131            });
132        }
133
134        // BIP 174: The Combiner must remove any duplicate key-value pairs, in accordance with
135        //          the specification. It can pick arbitrarily when conflicts occur.
136
137        // Keeping the highest version
138        self.version = cmp::max(self.version, other.version);
139
140        // Merging xpubs
141        for (xpub, (fingerprint1, derivation1)) in other.xpub {
142            match self.xpub.entry(xpub) {
143                btree_map::Entry::Vacant(entry) => {
144                    entry.insert((fingerprint1, derivation1));
145                },
146                btree_map::Entry::Occupied(mut entry) => {
147                    // Here in case of the conflict we select the version with algorithm:
148                    // 1) if everything is equal we do nothing
149                    // 2) report an error if
150                    //    - derivation paths are equal and fingerprints are not
151                    //    - derivation paths are of the same length, but not equal
152                    //    - derivation paths has different length, but the shorter one
153                    //      is not the strict suffix of the longer one
154                    // 3) choose longest derivation otherwise
155
156                    let (fingerprint2, derivation2) = entry.get().clone();
157
158                    if (derivation1 == derivation2 && fingerprint1 == fingerprint2) ||
159                        (derivation1.len() < derivation2.len() && derivation1[..] == derivation2[derivation2.len() - derivation1.len()..])
160                    {
161                        continue
162                    }
163                    else if derivation2[..] == derivation1[derivation1.len() - derivation2.len()..]
164                    {
165                        entry.insert((fingerprint1, derivation1));
166                        continue
167                    }
168                    return Err(Error::CombineInconsistentKeySources(xpub));
169                }
170            }
171        }
172
173        self.proprietary.extend(other.proprietary);
174        self.unknown.extend(other.unknown);
175
176        for (self_input, other_input) in self.inputs.iter_mut().zip(other.inputs.into_iter()) {
177            self_input.combine(other_input);
178        }
179
180        for (self_output, other_output) in self.outputs.iter_mut().zip(other.outputs.into_iter()) {
181            self_output.combine(other_output);
182        }
183
184        Ok(())
185    }
186}
187
188#[cfg(feature = "base64")]
189mod display_from_str {
190    use super::PartiallySignedTransaction;
191    use core::fmt::{Display, Formatter, self};
192    use core::str::FromStr;
193    use consensus::encode::{Error, self};
194    use ::base64::display::Base64Display;
195
196    /// Error happening during PSBT decoding from Base64 string
197    #[derive(Debug)]
198    #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
199    pub enum PsbtParseError {
200        /// Error in internal PSBT data structure
201        PsbtEncoding(Error),
202        /// Error in PSBT Base64 encoding
203        Base64Encoding(::base64::DecodeError)
204    }
205
206    impl Display for PsbtParseError {
207        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
208            match self {
209                PsbtParseError::PsbtEncoding(err) => Display::fmt(err, f),
210                PsbtParseError::Base64Encoding(err) => Display::fmt(err, f),
211            }
212        }
213    }
214
215    #[cfg(feature = "std")]
216    #[cfg_attr(docsrs, doc(cfg(feature = "std")))]
217    impl ::std::error::Error for PsbtParseError {}
218
219    #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
220    impl Display for PartiallySignedTransaction {
221        fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
222            write!(f, "{}", Base64Display::with_config(&encode::serialize(self), ::base64::STANDARD))
223        }
224    }
225
226    #[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
227    impl FromStr for PartiallySignedTransaction {
228        type Err = PsbtParseError;
229
230        fn from_str(s: &str) -> Result<Self, Self::Err> {
231            let data = ::base64::decode(s).map_err(PsbtParseError::Base64Encoding)?;
232            Ok(encode::deserialize(&data).map_err(PsbtParseError::PsbtEncoding)?)
233        }
234    }
235}
236#[cfg(feature = "base64")]
237#[cfg_attr(docsrs, doc(cfg(feature = "base64")))]
238pub use self::display_from_str::PsbtParseError;
239
240impl Encodable for PartiallySignedTransaction {
241    fn consensus_encode<S: io::Write>(&self, mut s: S) -> Result<usize, io::Error> {
242        let mut len = 0;
243        len += b"psbt".consensus_encode(&mut s)?;
244
245        len += 0xff_u8.consensus_encode(&mut s)?;
246
247        len += self.consensus_encode_map(&mut s)?;
248
249        for i in &self.inputs {
250            len += i.consensus_encode(&mut s)?;
251        }
252
253        for i in &self.outputs {
254            len += i.consensus_encode(&mut s)?;
255        }
256
257        Ok(len)
258    }
259}
260
261impl Decodable for PartiallySignedTransaction {
262    fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> {
263        let mut d = d.take(MAX_VEC_SIZE as u64);
264        let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?;
265
266        if *b"psbt" != magic {
267            return Err(Error::InvalidMagic.into());
268        }
269
270        if 0xff_u8 != u8::consensus_decode(&mut d)? {
271            return Err(Error::InvalidSeparator.into());
272        }
273
274        let mut global = PartiallySignedTransaction::consensus_decode_global(&mut d)?;
275        global.unsigned_tx_checks()?;
276
277        let inputs: Vec<Input> = {
278            let inputs_len: usize = (&global.unsigned_tx.input).len();
279
280            let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
281
282            for _ in 0..inputs_len {
283                inputs.push(Decodable::consensus_decode(&mut d)?);
284            }
285
286            inputs
287        };
288
289        let outputs: Vec<Output> = {
290            let outputs_len: usize = (&global.unsigned_tx.output).len();
291
292            let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
293
294            for _ in 0..outputs_len {
295                outputs.push(Decodable::consensus_decode(&mut d)?);
296            }
297
298            outputs
299        };
300
301        global.inputs = inputs;
302        global.outputs = outputs;
303        Ok(global)
304    }
305}
306
307#[cfg(test)]
308mod tests {
309    use super::*;
310
311    use hashes::hex::FromHex;
312    use hashes::{sha256, hash160, Hash, ripemd160};
313    use hash_types::Txid;
314
315    use secp256k1::{Secp256k1, self};
316
317    use blockdata::script::Script;
318    use blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint};
319    use network::constants::Network::Bitcoin;
320    use consensus::encode::{deserialize, serialize, serialize_hex};
321    use util::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, Fingerprint, KeySource};
322    use util::psbt::map::{Output, Input};
323    use util::psbt::raw;
324
325    use std::collections::BTreeMap;
326    use blockdata::witness::Witness;
327
328    #[test]
329    fn trivial_psbt() {
330        let psbt = PartiallySignedTransaction {
331            unsigned_tx: Transaction {
332                version: 2,
333                lock_time: 0,
334                input: vec![],
335                output: vec![],
336            },
337            xpub: Default::default(),
338            version: 0,
339            proprietary: BTreeMap::new(),
340            unknown: BTreeMap::new(),
341
342            inputs: vec![],
343            outputs: vec![],
344        };
345        assert_eq!(serialize_hex(&psbt), "70736274ff01000a0200000000000000000000");
346    }
347
348    #[test]
349   fn psbt_uncompressed_key() {
350
351       let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap();
352
353       assert!(psbt.inputs[0].partial_sigs.len() == 1);
354       let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0;
355       assert!(!pk.compressed);
356   }
357
358    #[test]
359    fn serialize_then_deserialize_output() {
360        let secp = &Secp256k1::new();
361        let seed = Vec::from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
362
363        let mut hd_keypaths: BTreeMap<secp256k1::PublicKey, KeySource> = Default::default();
364
365        let mut sk: ExtendedPrivKey = ExtendedPrivKey::new_master(Bitcoin, &seed).unwrap();
366
367        let fprint: Fingerprint = sk.fingerprint(&secp);
368
369        let dpath: Vec<ChildNumber> = vec![
370            ChildNumber::from_normal_idx(0).unwrap(),
371            ChildNumber::from_normal_idx(1).unwrap(),
372            ChildNumber::from_normal_idx(2).unwrap(),
373            ChildNumber::from_normal_idx(4).unwrap(),
374            ChildNumber::from_normal_idx(42).unwrap(),
375            ChildNumber::from_hardened_idx(69).unwrap(),
376            ChildNumber::from_normal_idx(420).unwrap(),
377            ChildNumber::from_normal_idx(31337).unwrap(),
378        ];
379
380        sk = sk.derive_priv(secp, &dpath).unwrap();
381
382        let pk: ExtendedPubKey = ExtendedPubKey::from_priv(&secp, &sk);
383
384        hd_keypaths.insert(pk.public_key, (fprint, dpath.into()));
385
386        let expected: Output = Output {
387            redeem_script: Some(hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac")),
388            witness_script: Some(hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787")),
389            bip32_derivation: hd_keypaths,
390            ..Default::default()
391        };
392
393        let actual: Output = deserialize(&serialize(&expected)).unwrap();
394
395        assert_eq!(expected, actual);
396    }
397
398    #[test]
399    fn serialize_then_deserialize_global() {
400        let expected = PartiallySignedTransaction {
401            unsigned_tx: Transaction {
402                version: 2,
403                lock_time: 1257139,
404                input: vec![TxIn {
405                    previous_output: OutPoint {
406                        txid: Txid::from_hex(
407                            "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
408                        ).unwrap(),
409                        vout: 0,
410                    },
411                    script_sig: Script::new(),
412                    sequence: 4294967294,
413                    witness: Witness::default(),
414                }],
415                output: vec![
416                    TxOut {
417                        value: 99999699,
418                        script_pubkey: hex_script!(
419                            "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"
420                        ),
421                    },
422                    TxOut {
423                        value: 100000000,
424                        script_pubkey: hex_script!(
425                            "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"
426                        ),
427                    },
428                ],
429            },
430            xpub: Default::default(),
431            version: 0,
432            proprietary: Default::default(),
433            unknown: Default::default(),
434            inputs: vec![Input::default()],
435            outputs: vec![Output::default(), Output::default()],
436        };
437
438        let actual: PartiallySignedTransaction = deserialize(&serialize(&expected)).unwrap();
439
440        assert_eq!(expected, actual);
441    }
442
443    #[test]
444    fn serialize_then_deserialize_psbtkvpair() {
445        let expected = raw::Pair {
446            key: raw::Key {
447                type_value: 0u8,
448                key: vec![42u8, 69u8],
449            },
450            value: vec![69u8, 42u8, 4u8],
451        };
452
453        let actual: raw::Pair = deserialize(&serialize(&expected)).unwrap();
454
455        assert_eq!(expected, actual);
456    }
457
458    #[test]
459    fn deserialize_and_serialize_psbt_with_two_partial_sigs() {
460        let hex = "70736274ff0100890200000001207ae985d787dfe6143d5c58fad79cc7105e0e799fcf033b7f2ba17e62d7b3200000000000ffffffff02563d03000000000022002019899534b9a011043c0dd57c3ff9a381c3522c5f27c6a42319085b56ca543a1d6adc020000000000220020618b47a07ebecca4e156edb1b9ea7c24bdee0139fc049237965ffdaf56d5ee73000000000001012b801a0600000000002200201148e93e9315e37dbed2121be5239257af35adc03ffdfc5d914b083afa44dab82202025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee076473044022007e06b362e89912abd4661f47945430739b006a85d1b2a16c01dc1a4bd07acab022061576d7aa834988b7ab94ef21d8eebd996ea59ea20529a19b15f0c9cebe3d8ac01220202b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a473044022002787f926d6817504431ee281183b8119b6845bfaa6befae45e13b6d430c9d2f02202859f149a6cd26ae2f03a107e7f33c7d91730dade305fe077bae677b5d44952a01010547522102b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a21025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee07652ae0001014752210283ef76537f2d58ae3aa3a4bd8ae41c3f230ccadffb1a0bd3ca504d871cff05e7210353d79cc0cb1396f4ce278d005f16d948e02a6aec9ed1109f13747ecb1507b37b52ae00010147522102b3937241777b6665e0d694e52f9c1b188433641df852da6fc42187b5d8a368a321034cdd474f01cc5aa7ff834ad8bcc882a87e854affc775486bc2a9f62e8f49bd7852ae00";
461        let psbt: PartiallySignedTransaction = hex_psbt!(hex).unwrap();
462        assert_eq!(hex, serialize_hex(&psbt));
463    }
464
465    #[cfg(feature = "serde")]
466    #[test]
467    fn test_serde_psbt() {
468        //! Create a full PSBT value with various fields filled and make sure it can be JSONized.
469        use hashes::sha256d;
470        use util::psbt::map::Input;
471        use EcdsaSighashType;
472
473        // create some values to use in the PSBT
474        let tx = Transaction {
475            version: 1,
476            lock_time: 0,
477            input: vec![TxIn {
478                previous_output: OutPoint {
479                    txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(),
480                    vout: 1,
481                },
482                script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
483                sequence: 4294967295,
484                witness: Witness::from_vec(vec![Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()]),
485            }],
486            output: vec![
487                TxOut {
488                    value: 190303501938,
489                    script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
490                },
491            ],
492        };
493        let unknown: BTreeMap<raw::Key, Vec<u8>> = vec![(
494            raw::Key { type_value: 1, key: vec![0, 1] },
495            vec![3, 4 ,5],
496        )].into_iter().collect();
497        let key_source = ("deadbeef".parse().unwrap(), "m/0'/1".parse().unwrap());
498        let keypaths: BTreeMap<secp256k1::PublicKey, KeySource> = vec![(
499            "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
500            key_source.clone(),
501        )].into_iter().collect();
502
503        let proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = vec![(
504            raw::ProprietaryKey {
505                prefix: "prefx".as_bytes().to_vec(),
506                subtype: 42,
507                key: "test_key".as_bytes().to_vec(),
508            },
509            vec![5, 6, 7],
510        )].into_iter().collect();
511
512        let psbt = PartiallySignedTransaction {
513            version: 0,
514            xpub: {
515                let xpub: ExtendedPubKey =
516                    "xpub661MyMwAqRbcGoRVtwfvzZsq2VBJR1LAHfQstHUoxqDorV89vRoMxUZ27kLrraAj6MPi\
517                    QfrDb27gigC1VS1dBXi5jGpxmMeBXEkKkcXUTg4".parse().unwrap();
518                vec![(xpub, key_source.clone())].into_iter().collect()
519            },
520            unsigned_tx: {
521                let mut unsigned = tx.clone();
522                unsigned.input[0].script_sig = Script::new();
523                unsigned.input[0].witness = Witness::default();
524                unsigned
525            },
526            proprietary: proprietary.clone(),
527            unknown: unknown.clone(),
528
529            inputs: vec![Input {
530                non_witness_utxo: Some(tx),
531                witness_utxo: Some(TxOut {
532                    value: 190303501938,
533                    script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
534                }),
535                sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse::<EcdsaSighashType>().unwrap().into()),
536                redeem_script: Some(vec![0x51].into()),
537                witness_script: None,
538                partial_sigs: vec![(
539                    "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
540                    "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(),
541                )].into_iter().collect(),
542                bip32_derivation: keypaths.clone(),
543                final_script_witness: Some(Witness::from_vec(vec![vec![1, 3], vec![5]])),
544                ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
545                sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
546                hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
547                hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
548                proprietary: proprietary.clone(),
549                unknown: unknown.clone(),
550                ..Default::default()
551            }],
552            outputs: vec![Output {
553                bip32_derivation: keypaths,
554                proprietary: proprietary.clone(),
555                unknown: unknown.clone(),
556                ..Default::default()
557            }],
558        };
559        let encoded = ::serde_json::to_string(&psbt).unwrap();
560        let decoded: PartiallySignedTransaction = ::serde_json::from_str(&encoded).unwrap();
561        assert_eq!(psbt, decoded);
562    }
563
564    mod bip_vectors {
565        #[cfg(feature = "base64")]
566        use std::str::FromStr;
567
568        use hashes::hex::FromHex;
569        use hash_types::Txid;
570
571        use blockdata::script::Script;
572        use blockdata::transaction::{EcdsaSighashType, Transaction, TxIn, TxOut, OutPoint};
573        use consensus::encode::serialize_hex;
574        use util::psbt::map::{Map, Input, Output};
575        use util::psbt::raw;
576        use util::psbt::{PartiallySignedTransaction, Error};
577        use std::collections::BTreeMap;
578        use blockdata::witness::Witness;
579
580        #[test]
581        #[should_panic(expected = "InvalidMagic")]
582        fn invalid_vector_1() {
583            hex_psbt!("0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300").unwrap();
584        }
585
586        #[cfg(feature = "base64")]
587        #[test]
588        #[should_panic(expected = "InvalidMagic")]
589        fn invalid_vector_1_base64() {
590            PartiallySignedTransaction::from_str("AgAAAAEmgXE3Ht/yhek3re6ks3t4AAwFZsuzrWRkFxPKQhcb9gAAAABqRzBEAiBwsiRRI+a/R01gxbUMBD1MaRpdJDXwmjSnZiqdwlF5CgIgATKcqdrPKAvfMHQOwDkEIkIsgctFg5RXrrdvwS7dlbMBIQJlfRGNM1e44PTCzUbbezn22cONmnCry5st5dyNv+TOMf7///8C09/1BQAAAAAZdqkU0MWZA8W6woaHYOkP1SGkZlqnZSCIrADh9QUAAAAAF6kUNUXm4zuDLEcFDyTT7rk8nAOUi8eHsy4TAA==").unwrap();
591        }
592
593        #[test]
594        #[should_panic(expected = "ConsensusEncoding")]
595        fn invalid_vector_2() {
596            hex_psbt!("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000")
597                // This weird thing is necessary since rustc 0.29 prints out I/O error in a different format than later versions
598                .map_err(Error::from)
599                .unwrap();
600        }
601
602        #[cfg(feature = "base64")]
603        #[test]
604        #[should_panic(expected = "ConsensusEncoding")]
605        fn invalid_vector_2_base64() {
606            use util::psbt::PsbtParseError;
607            PartiallySignedTransaction::from_str("cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==")
608                // This weird thing is necessary since rustc 0.29 prints out I/O error in a different format than later versions
609                .map_err(|err| match err {
610                    PsbtParseError::PsbtEncoding(err) => err,
611                    PsbtParseError::Base64Encoding(_) => panic!("PSBT Base64 decoding failed")
612                })
613                .map_err(Error::from)
614                .unwrap();
615        }
616
617        #[test]
618        #[should_panic(expected = "UnsignedTxHasScriptSigs")]
619        fn invalid_vector_3() {
620            hex_psbt!("70736274ff0100fd0a010200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be4000000006a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa88292feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
621        }
622
623        #[cfg(feature = "base64")]
624        #[test]
625        #[should_panic(expected = "UnsignedTxHasScriptSigs")]
626        fn invalid_vector_3_base64() {
627            PartiallySignedTransaction::from_str("cHNidP8BAP0KAQIAAAACqwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QAAAAAakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpL+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAABASAA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHhwEEFgAUhdE1N/LiZUBaNNuvqePdoB+4IwgAAAA=").unwrap();
628        }
629
630        #[test]
631        #[should_panic(expected = "MustHaveUnsignedTx")]
632        fn invalid_vector_4() {
633            hex_psbt!("70736274ff000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000").unwrap();
634        }
635
636        #[cfg(feature = "base64")]
637        #[test]
638        #[should_panic(expected = "MustHaveUnsignedTx")]
639        fn invalid_vector_4_base64() {
640            PartiallySignedTransaction::from_str("cHNidP8AAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAA==").unwrap();
641        }
642
643        #[test]
644        #[should_panic(expected = "DuplicateKey(Key { type_value: 0, key: [] })")]
645        fn invalid_vector_5() {
646            hex_psbt!("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000000").unwrap();
647        }
648
649        #[cfg(feature = "base64")]
650        #[test]
651        #[should_panic(expected = "DuplicateKey(Key { type_value: 0, key: [] })")]
652        fn invalid_vector_5_base64() {
653            PartiallySignedTransaction::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();
654        }
655
656        #[test]
657        fn valid_vector_1() {
658            let unserialized = PartiallySignedTransaction {
659                unsigned_tx: Transaction {
660                    version: 2,
661                    lock_time: 1257139,
662                    input: vec![TxIn {
663                        previous_output: OutPoint {
664                            txid: Txid::from_hex(
665                                "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
666                            ).unwrap(),
667                            vout: 0,
668                        },
669                        script_sig: Script::new(),
670                        sequence: 4294967294,
671                        witness: Witness::default(),
672                    }],
673                    output: vec![
674                        TxOut {
675                            value: 99999699,
676                            script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
677                        },
678                        TxOut {
679                            value: 100000000,
680                            script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
681                        },
682                    ],
683                },
684                xpub: Default::default(),
685                version: 0,
686                proprietary: BTreeMap::new(),
687                unknown: BTreeMap::new(),
688
689                inputs: vec![Input {
690                    non_witness_utxo: Some(Transaction {
691                        version: 1,
692                        lock_time: 0,
693                        input: vec![TxIn {
694                            previous_output: OutPoint {
695                                txid: Txid::from_hex(
696                                    "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
697                                ).unwrap(),
698                                vout: 1,
699                            },
700                            script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
701                            sequence: 4294967295,
702                            witness: Witness::from_vec(vec![
703                                Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
704                                Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
705                            ]),
706                        },
707                        TxIn {
708                            previous_output: OutPoint {
709                                txid: Txid::from_hex(
710                                    "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
711                                ).unwrap(),
712                                vout: 1,
713                            },
714                            script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
715                            sequence: 4294967295,
716                            witness: Witness::from_vec(vec![
717                                Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
718                                Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
719                            ]),
720                        }],
721                        output: vec![
722                            TxOut {
723                                value: 200000000,
724                                script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
725                            },
726                            TxOut {
727                                value: 190303501938,
728                                script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
729                            },
730                        ],
731                    }),
732                    ..Default::default()
733                },],
734                outputs: vec![
735                    Output {
736                        ..Default::default()
737                    },
738                    Output {
739                        ..Default::default()
740                    },
741                ],
742            };
743
744            let base16str = "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000";
745
746            assert_eq!(serialize_hex(&unserialized), base16str);
747            assert_eq!(unserialized, hex_psbt!(base16str).unwrap());
748
749            #[cfg(feature = "base64")] {
750                let base64str = "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA";
751                assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), unserialized);
752                assert_eq!(base64str, unserialized.to_string());
753                assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), hex_psbt!(base16str).unwrap());
754            }
755        }
756
757        #[test]
758        fn valid_vector_2() {
759            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
760
761            assert_eq!(psbt.inputs.len(), 2);
762            assert_eq!(psbt.outputs.len(), 2);
763
764            assert!(&psbt.inputs[0].final_script_sig.is_some());
765
766            let redeem_script: &Script = &psbt.inputs[1].redeem_script.as_ref().unwrap();
767            let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787");
768
769            assert!(redeem_script.is_v0_p2wpkh());
770            assert_eq!(
771                redeem_script.to_p2sh(),
772                psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey
773            );
774            assert_eq!(redeem_script.to_p2sh(), expected_out);
775
776            for output in psbt.outputs {
777                assert_eq!(output.get_pairs().unwrap().len(), 0)
778            }
779        }
780
781        #[test]
782        fn valid_vector_3() {
783            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000").unwrap();
784
785            assert_eq!(psbt.inputs.len(), 1);
786            assert_eq!(psbt.outputs.len(), 2);
787
788            let tx_input = &psbt.unsigned_tx.input[0];
789            let psbt_non_witness_utxo = (&psbt.inputs[0].non_witness_utxo).as_ref().unwrap();
790
791            assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.txid());
792            assert!(psbt_non_witness_utxo.output[tx_input.previous_output.vout as usize]
793                    .script_pubkey
794                    .is_p2pkh()
795            );
796            assert_eq!(
797                (&psbt.inputs[0].sighash_type).as_ref().unwrap().ecdsa_hash_ty().unwrap(),
798                EcdsaSighashType::All
799            );
800        }
801
802        #[test]
803        fn valid_vector_4() {
804            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000").unwrap();
805
806            assert_eq!(psbt.inputs.len(), 2);
807            assert_eq!(psbt.outputs.len(), 2);
808
809            assert!(&psbt.inputs[0].final_script_sig.is_none());
810            assert!(&psbt.inputs[1].final_script_sig.is_none());
811
812            let redeem_script: &Script = &psbt.inputs[1].redeem_script.as_ref().unwrap();
813            let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787");
814
815            assert!(redeem_script.is_v0_p2wpkh());
816            assert_eq!(
817                redeem_script.to_p2sh(),
818                psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey
819            );
820            assert_eq!(redeem_script.to_p2sh(), expected_out);
821
822            for output in psbt.outputs {
823                assert!(output.get_pairs().unwrap().len() > 0)
824            }
825        }
826
827        #[test]
828        fn valid_vector_5() {
829            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000").unwrap();
830
831            assert_eq!(psbt.inputs.len(), 1);
832            assert_eq!(psbt.outputs.len(), 1);
833
834            assert!(&psbt.inputs[0].final_script_sig.is_none());
835
836            let redeem_script: &Script = &psbt.inputs[0].redeem_script.as_ref().unwrap();
837            let expected_out = hex_script!("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87");
838
839            assert!(redeem_script.is_v0_p2wsh());
840            assert_eq!(
841                redeem_script.to_p2sh(),
842                psbt.inputs[0].witness_utxo.as_ref().unwrap().script_pubkey
843            );
844
845            assert_eq!(redeem_script.to_p2sh(), expected_out);
846        }
847
848        #[test]
849        fn valid_vector_6() {
850            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000").unwrap();
851
852            assert_eq!(psbt.inputs.len(), 1);
853            assert_eq!(psbt.outputs.len(), 1);
854
855            let tx = &psbt.unsigned_tx;
856            assert_eq!(
857                tx.txid(),
858                Txid::from_hex("75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115").unwrap(),
859            );
860
861            let mut unknown: BTreeMap<raw::Key, Vec<u8>> = BTreeMap::new();
862            let key: raw::Key = raw::Key {
863                type_value: 0x0fu8,
864                key: Vec::from_hex("010203040506070809").unwrap(),
865            };
866            let value: Vec<u8> = Vec::from_hex("0102030405060708090a0b0c0d0e0f").unwrap();
867
868            unknown.insert(key, value);
869
870            assert_eq!(psbt.inputs[0].unknown, unknown)
871        }
872    }
873
874    mod bip_371_vectors {
875        use super::*;
876        use super::serialize;
877
878        #[test]
879        fn invalid_vectors() {
880            let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a075701172102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232000000").unwrap_err();
881            assert_eq!(err.to_string(), "parse failed: Invalid xonly public key");
882            let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011342173bb3d36c074afb716fec6307a069a2e450b995f3c82785945ab8df0e24260dcd703b0cbf34de399184a9481ac2b3586db6601f026a77f7e4938481bc34751701aa000000").unwrap_err();
883            assert_eq!(err.to_string(), "parse failed: Invalid Schnorr signature length");
884            let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err();
885            assert_eq!(err.to_string(), "parse failed: Invalid xonly public key");
886            let err = hex_psbt!("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000001052102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa23200").unwrap_err();
887            assert_eq!(err.to_string(), "parse failed: Invalid xonly public key");
888            let err = hex_psbt!("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07570000220702fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da7560000800100008000000080010000000000000000").unwrap_err();
889            assert_eq!(err.to_string(), "parse failed: Invalid xonly public key");
890            let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6924214022cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094089756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err();
891            assert_eq!(err.to_string(), "PSBT error: Hash Parse Error: bad slice length 33 (expected 32)");
892            let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b094289756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb01010000").unwrap_err();
893            assert_eq!(err.to_string(), "parse failed: Invalid Schnorr signature length");
894            let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err();
895            assert_eq!(err.to_string(), "parse failed: Invalid Schnorr signature length");
896            let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
897            assert_eq!(err.to_string(), "parse failed: Invalid control block");
898            let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926115c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e123202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err();
899            assert_eq!(err.to_string(), "parse failed: Invalid control block");
900        }
901
902        fn rtt_psbt(psbt: PartiallySignedTransaction) {
903            let enc = serialize(&psbt);
904            let psbt2 = deserialize::<PartiallySignedTransaction>(&enc).unwrap();
905            assert_eq!(psbt, psbt2);
906        }
907
908        #[test]
909        fn valid_psbt_vectors() {
910            let psbt = hex_psbt!("70736274ff010052020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a01000000160014768e1eeb4cf420866033f80aceff0f9720744969000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232002202036b772a6db74d8753c98a827958de6c78ab3312109f37d3e0304484242ece73d818772b2da7540000800100008000000080000000000000000000").unwrap();
911            let internal_key = psbt.inputs[0].tap_internal_key.unwrap();
912            assert!(psbt.inputs[0].tap_key_origins.contains_key(&internal_key));
913            rtt_psbt(psbt);
914
915            // vector 2
916            let psbt = hex_psbt!("70736274ff010052020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a01000000160014768e1eeb4cf420866033f80aceff0f9720744969000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757011340bb53ec917bad9d906af1ba87181c48b86ace5aae2b53605a725ca74625631476fc6f5baedaf4f2ee0f477f36f58f3970d5b8273b7e497b97af2e3f125c97af342116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232002202036b772a6db74d8753c98a827958de6c78ab3312109f37d3e0304484242ece73d818772b2da7540000800100008000000080000000000000000000").unwrap();
917            let internal_key = psbt.inputs[0].tap_internal_key.unwrap();
918            assert!(psbt.inputs[0].tap_key_origins.contains_key(&internal_key));
919            assert!(psbt.inputs[0].tap_key_sig.is_some());
920            rtt_psbt(psbt);
921
922            // vector 3
923            let psbt = hex_psbt!("70736274ff01005e020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa232000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap();
924            let internal_key = psbt.outputs[0].tap_internal_key.unwrap();
925            assert!(psbt.outputs[0].tap_key_origins.contains_key(&internal_key));
926            rtt_psbt(psbt);
927
928            // vector 4
929            let psbt = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f823202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc04215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac097c6e6fea5ff714ff5724499990810e406e98aa10f5bf7e5f6784bc1d0a9a6ce23204320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2acc06215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f82320fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca9acc021162cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d23901cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09772b2da7560000800100008002000080000000000000000021164320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b23901115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f8772b2da75600008001000080010000800000000000000000211650929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2116fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca939016f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970772b2da7560000800100008003000080000000000000000001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820f0362e2f75a6f420a5bde3eb221d96ae6720cf25f81890c95b1d775acb515e65000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap();
930            assert!(psbt.inputs[0].tap_internal_key.is_some());
931            assert!(psbt.inputs[0].tap_merkle_root.is_some());
932            assert!(!psbt.inputs[0].tap_key_origins.is_empty());
933            assert!(!psbt.inputs[0].tap_scripts.is_empty());
934            rtt_psbt(psbt);
935
936            // vector 5
937            let psbt = hex_psbt!("70736274ff01005e020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff0148e6052a010000002251200a8cbdc86de1ce1c0f9caeb22d6df7ced3683fe423e05d1e402a879341d6f6f5000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a07572116fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000011720fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2320001052050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac001066f02c02220736e572900fe1252589a2143c8f3c79f71a0412d2353af755e9701c782694a02ac02c02220631c5f3b5832b8fbdebfb19704ceeb323c21f40f7a24f43d68ef0cc26b125969ac01c0222044faa49a0338de488c8dfffecdfb6f329f380bd566ef20c8df6d813eab1c4273ac210744faa49a0338de488c8dfffecdfb6f329f380bd566ef20c8df6d813eab1c42733901f06b798b92a10ed9a9d0bbfd3af173a53b1617da3a4159ca008216cd856b2e0e772b2da75600008001000080010000800000000003000000210750929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2107631c5f3b5832b8fbdebfb19704ceeb323c21f40f7a24f43d68ef0cc26b125969390118ace409889785e0ea70ceebb8e1ca892a7a78eaede0f2e296cf435961a8f4ca772b2da756000080010000800200008000000000030000002107736e572900fe1252589a2143c8f3c79f71a0412d2353af755e9701c782694a02390129a5b4915090162d759afd3fe0f93fa3326056d0b4088cb933cae7826cb8d82c772b2da7560000800100008003000080000000000300000000").unwrap();
938            assert!(psbt.outputs[0].tap_internal_key.is_some());
939            assert!(!psbt.outputs[0].tap_key_origins.is_empty());
940            assert!(psbt.outputs[0].tap_tree.is_some());
941            rtt_psbt(psbt);
942
943            // vector 6
944            let psbt = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a0100000022512083698e458c6664e1595d75da2597de1e22ee97d798e706c4c0a4b5a9823cd743000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b0940bf818d9757d6ffeb538ba057fb4c1fc4e0f5ef186e765beb564791e02af5fd3d5e2551d4e34e33d86f276b82c99c79aed3f0395a081efcd2cc2c65dd7e693d7941144320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f840e1f1ab6fabfa26b236f21833719dc1d428ab768d80f91f9988d8abef47bfb863bb1f2a529f768c15f00ce34ec283cdc07e88f8428be28f6ef64043c32911811a4114fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca96f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae97040ec1f0379206461c83342285423326708ab031f0da4a253ee45aafa5b8c92034d8b605490f8cd13e00f989989b97e215faa36f12dee3693d2daccf3781c1757f66215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f823202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc04215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac097c6e6fea5ff714ff5724499990810e406e98aa10f5bf7e5f6784bc1d0a9a6ce23204320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b2acc06215c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f82320fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca9acc021162cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d23901cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b09772b2da7560000800100008002000080000000000000000021164320b0bf16f011b53ea7be615924aa7f27e5d29ad20ea1155d848676c3bad1b23901115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f8772b2da75600008001000080010000800000000000000000211650929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac005007c461e5d2116fa0f7a3cef3b1d0c0a6ce7d26e17ada0b2e5c92d19efad48b41859cb8a451ca939016f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970772b2da7560000800100008003000080000000000000000001172050929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac0011820f0362e2f75a6f420a5bde3eb221d96ae6720cf25f81890c95b1d775acb515e65000105201124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e67121071124da7aec92ccd06c954562647f437b138b95721a84be2bf2276bbddab3e6711900772b2da7560000800100008000000080000000000500000000").unwrap();
945            assert!(psbt.inputs[0].tap_internal_key.is_some());
946            assert!(psbt.inputs[0].tap_merkle_root.is_some());
947            assert!(!psbt.inputs[0].tap_scripts.is_empty());
948            assert!(!psbt.inputs[0].tap_script_sigs.is_empty());
949            assert!(!psbt.inputs[0].tap_key_origins.is_empty());
950            rtt_psbt(psbt);
951        }
952    }
953
954    #[test]
955    fn serialize_and_deserialize_preimage_psbt() {
956        // create a sha preimage map
957        let mut sha256_preimages = BTreeMap::new();
958        sha256_preimages.insert(sha256::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]);
959        sha256_preimages.insert(sha256::Hash::hash(&[1u8]), vec![1u8]);
960
961        // same for hash160
962        let mut hash160_preimages = BTreeMap::new();
963        hash160_preimages.insert(hash160::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]);
964        hash160_preimages.insert(hash160::Hash::hash(&[1u8]), vec![1u8]);
965
966        // same vector as valid_vector_1 from BIPs with added
967        let mut unserialized = PartiallySignedTransaction {
968            unsigned_tx: Transaction {
969                version: 2,
970                lock_time: 1257139,
971                input: vec![TxIn {
972                    previous_output: OutPoint {
973                        txid: Txid::from_hex(
974                            "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
975                        ).unwrap(),
976                        vout: 0,
977                    },
978                    script_sig: Script::new(),
979                    sequence: 4294967294,
980                    witness: Witness::default(),
981                }],
982                output: vec![
983                    TxOut {
984                        value: 99999699,
985                        script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
986                    },
987                    TxOut {
988                        value: 100000000,
989                        script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
990                    },
991                ],
992            },
993            version: 0,
994            xpub: Default::default(),
995            proprietary: Default::default(),
996            unknown: BTreeMap::new(),
997
998            inputs: vec![Input {
999                non_witness_utxo: Some(Transaction {
1000                    version: 1,
1001                    lock_time: 0,
1002                    input: vec![TxIn {
1003                        previous_output: OutPoint {
1004                            txid: Txid::from_hex(
1005                                "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
1006                            ).unwrap(),
1007                            vout: 1,
1008                        },
1009                        script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
1010                        sequence: 4294967295,
1011                        witness: Witness::from_vec(vec![
1012                            Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
1013                            Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
1014                        ]),
1015                    },
1016                    TxIn {
1017                        previous_output: OutPoint {
1018                            txid: Txid::from_hex(
1019                                "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
1020                            ).unwrap(),
1021                            vout: 1,
1022                        },
1023                        script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
1024                        sequence: 4294967295,
1025                        witness: Witness::from_vec(vec![
1026                            Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
1027                            Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
1028                        ]),
1029                    }],
1030                    output: vec![
1031                        TxOut {
1032                            value: 200000000,
1033                            script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
1034                        },
1035                        TxOut {
1036                            value: 190303501938,
1037                            script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
1038                        },
1039                    ],
1040                }),
1041                ..Default::default()
1042            },],
1043            outputs: vec![
1044                Output {
1045                    ..Default::default()
1046                },
1047                Output {
1048                    ..Default::default()
1049                },
1050            ],
1051        };
1052        unserialized.inputs[0].hash160_preimages = hash160_preimages;
1053        unserialized.inputs[0].sha256_preimages = sha256_preimages;
1054
1055        let rtt: PartiallySignedTransaction = hex_psbt!(&serialize_hex(&unserialized)).unwrap();
1056        assert_eq!(rtt, unserialized);
1057
1058        // Now add an ripemd160 with incorrect preimage
1059        let mut ripemd160_preimages = BTreeMap::new();
1060        ripemd160_preimages.insert(ripemd160::Hash::hash(&[17u8]), vec![18u8]);
1061        unserialized.inputs[0].ripemd160_preimages = ripemd160_preimages;
1062
1063        // Now the roundtrip should fail as the preimage is incorrect.
1064        let rtt: Result<PartiallySignedTransaction, _> = hex_psbt!(&serialize_hex(&unserialized));
1065        assert!(rtt.is_err());
1066    }
1067
1068    #[test]
1069    fn serialize_and_deserialize_proprietary() {
1070        let mut psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
1071        psbt.proprietary.insert(raw::ProprietaryKey {
1072            prefix: b"test".to_vec(),
1073            subtype: 0u8,
1074            key: b"test".to_vec(),
1075        }, b"test".to_vec());
1076        assert!(!psbt.proprietary.is_empty());
1077        let rtt: PartiallySignedTransaction = hex_psbt!(&serialize_hex(&psbt)).unwrap();
1078        assert!(!rtt.proprietary.is_empty());
1079    }
1080
1081    // PSBTs taken from BIP 174 test vectors.
1082    #[test]
1083    fn combine_psbts() {
1084        let mut psbt1 = hex_psbt!(include_str!("../../../test_data/psbt1.hex")).unwrap();
1085        let psbt2 = hex_psbt!(include_str!("../../../test_data/psbt2.hex")).unwrap();
1086        let psbt_combined = hex_psbt!(include_str!("../../../test_data/psbt2.hex")).unwrap();
1087
1088        psbt1.combine(psbt2).expect("psbt combine to succeed");
1089        assert_eq!(psbt1, psbt_combined);
1090    }
1091
1092    #[test]
1093    fn combine_psbts_commutative() {
1094        let mut psbt1 = hex_psbt!(include_str!("../../../test_data/psbt1.hex")).unwrap();
1095        let mut psbt2 = hex_psbt!(include_str!("../../../test_data/psbt2.hex")).unwrap();
1096
1097        let psbt1_clone = psbt1.clone();
1098        let psbt2_clone = psbt2.clone();
1099
1100        psbt1.combine(psbt2_clone).expect("psbt1 combine to succeed");
1101        psbt2.combine(psbt1_clone).expect("psbt2 combine to succeed");
1102
1103        assert_eq!(psbt1, psbt2);
1104    }
1105}