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 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
21use blockdata::script::Script;
22use blockdata::transaction::Transaction;
23use consensus::{encode, Encodable, Decodable};
24
25use std::io;
26
27mod error;
28pub use self::error::Error;
29
30pub mod raw;
31
32#[macro_use]
33mod macros;
34
35pub mod serialize;
36
37mod map;
38pub use self::map::{Map, Global, Input, Output};
39
40/// A Partially Signed Transaction.
41#[derive(Debug, Clone, PartialEq)]
42#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
43pub struct PartiallySignedTransaction {
44    /// The key-value pairs for all global data.
45    pub global: Global,
46    /// The corresponding key-value map for each input in the unsigned
47    /// transaction.
48    pub inputs: Vec<Input>,
49    /// The corresponding key-value map for each output in the unsigned
50    /// transaction.
51    pub outputs: Vec<Output>,
52}
53
54impl PartiallySignedTransaction {
55    /// Create a PartiallySignedTransaction from an unsigned transaction, error
56    /// if not unsigned
57    pub fn from_unsigned_tx(tx: Transaction) -> Result<Self, self::Error> {
58        Ok(PartiallySignedTransaction {
59            inputs: vec![Default::default(); tx.input.len()],
60            outputs: vec![Default::default(); tx.output.len()],
61            global: Global::from_unsigned_tx(tx)?,
62        })
63    }
64
65    /// Extract the Transaction from a PartiallySignedTransaction by filling in
66    /// the available signature information in place.
67    pub fn extract_tx(self) -> Transaction {
68        let mut tx: Transaction = self.global.unsigned_tx;
69
70        for (vin, psbtin) in tx.input.iter_mut().zip(self.inputs.into_iter()) {
71            vin.script_sig = psbtin.final_script_sig.unwrap_or_else(Script::new);
72            vin.witness = psbtin.final_script_witness.unwrap_or_else(Vec::new);
73        }
74
75        tx
76    }
77
78    /// Attempt to merge with another `PartiallySignedTransaction`.
79    pub fn merge(&mut self, other: Self) -> Result<(), self::Error> {
80        self.global.merge(other.global)?;
81
82        for (self_input, other_input) in self.inputs.iter_mut().zip(other.inputs.into_iter()) {
83            self_input.merge(other_input)?;
84        }
85
86        for (self_output, other_output) in self.outputs.iter_mut().zip(other.outputs.into_iter()) {
87            self_output.merge(other_output)?;
88        }
89
90        Ok(())
91    }
92}
93
94impl Encodable for PartiallySignedTransaction {
95    fn consensus_encode<S: io::Write>(
96        &self,
97        mut s: S,
98    ) -> Result<usize, io::Error> {
99        let mut len = 0;
100        len += b"psbt".consensus_encode(&mut s)?;
101
102        len += 0xff_u8.consensus_encode(&mut s)?;
103
104        len += self.global.consensus_encode(&mut s)?;
105
106        for i in &self.inputs {
107            len += i.consensus_encode(&mut s)?;
108        }
109
110        for i in &self.outputs {
111            len += i.consensus_encode(&mut s)?;
112        }
113
114        Ok(len)
115    }
116}
117
118impl Decodable for PartiallySignedTransaction {
119    fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
120        let magic: [u8; 4] = Decodable::consensus_decode(&mut d)?;
121
122        if *b"psbt" != magic {
123            return Err(Error::InvalidMagic.into());
124        }
125
126        if 0xff_u8 != u8::consensus_decode(&mut d)? {
127            return Err(Error::InvalidSeparator.into());
128        }
129
130        let global: Global = Decodable::consensus_decode(&mut d)?;
131
132        let inputs: Vec<Input> = {
133            let inputs_len: usize = (&global.unsigned_tx.input).len();
134
135            let mut inputs: Vec<Input> = Vec::with_capacity(inputs_len);
136
137            for _ in 0..inputs_len {
138                inputs.push(Decodable::consensus_decode(&mut d)?);
139            }
140
141            inputs
142        };
143
144        let outputs: Vec<Output> = {
145            let outputs_len: usize = (&global.unsigned_tx.output).len();
146
147            let mut outputs: Vec<Output> = Vec::with_capacity(outputs_len);
148
149            for _ in 0..outputs_len {
150                outputs.push(Decodable::consensus_decode(&mut d)?);
151            }
152
153            outputs
154        };
155
156        Ok(PartiallySignedTransaction {
157            global: global,
158            inputs: inputs,
159            outputs: outputs,
160        })
161    }
162}
163
164#[cfg(test)]
165mod tests {
166    use hashes::hex::FromHex;
167    use hashes::{sha256, hash160, Hash, ripemd160};
168    use hash_types::Txid;
169
170    use std::collections::BTreeMap;
171
172    use secp256k1::Secp256k1;
173
174    use blockdata::script::Script;
175    use blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint};
176    use network::constants::Network::Bitcoin;
177    use consensus::encode::{deserialize, serialize, serialize_hex};
178    use util::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, Fingerprint, KeySource};
179    use util::key::PublicKey;
180    use util::psbt::map::{Global, Output, Input};
181    use util::psbt::raw;
182
183    use super::PartiallySignedTransaction;
184
185    #[test]
186    fn trivial_psbt() {
187        let psbt = PartiallySignedTransaction {
188            global: Global {
189                unsigned_tx: Transaction {
190                    version: 2,
191                    lock_time: 0,
192                    input: vec![],
193                    output: vec![],
194                },
195                xpub: Default::default(),
196                version: 0,
197                proprietary: BTreeMap::new(),
198                unknown: BTreeMap::new(),
199            },
200            inputs: vec![],
201            outputs: vec![],
202        };
203        assert_eq!(
204            serialize_hex(&psbt),
205            "70736274ff01000a0200000000000000000000"
206        );
207    }
208
209    #[test]
210    fn serialize_then_deserialize_output() {
211        let secp = &Secp256k1::new();
212        let seed = Vec::from_hex("000102030405060708090a0b0c0d0e0f").unwrap();
213
214        let mut hd_keypaths: BTreeMap<PublicKey, KeySource> = Default::default();
215
216        let mut sk: ExtendedPrivKey = ExtendedPrivKey::new_master(&secp, Bitcoin, &seed).unwrap();
217
218        let fprint: Fingerprint = sk.fingerprint(&secp);
219
220        let dpath: Vec<ChildNumber> = vec![
221            ChildNumber::from_normal_idx(0).unwrap(),
222            ChildNumber::from_normal_idx(1).unwrap(),
223            ChildNumber::from_normal_idx(2).unwrap(),
224            ChildNumber::from_normal_idx(4).unwrap(),
225            ChildNumber::from_normal_idx(42).unwrap(),
226            ChildNumber::from_hardened_idx(69).unwrap(),
227            ChildNumber::from_normal_idx(420).unwrap(),
228            ChildNumber::from_normal_idx(31337).unwrap(),
229        ];
230
231        sk = sk.derive_priv(secp, &dpath).unwrap();
232
233        let pk: ExtendedPubKey = ExtendedPubKey::from_private(&secp, &sk);
234
235        hd_keypaths.insert(pk.public_key, (fprint, dpath.into()));
236
237        let expected: Output = Output {
238            redeem_script: Some(hex_script!(
239                "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"
240            )),
241            witness_script: Some(hex_script!(
242                "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"
243            )),
244            bip32_derivation: hd_keypaths,
245            ..Default::default()
246        };
247
248        let actual: Output = deserialize(&serialize(&expected)).unwrap();
249
250        assert_eq!(expected, actual);
251    }
252
253    #[test]
254    fn serialize_then_deserialize_global() {
255        let expected = Global {
256            unsigned_tx: Transaction {
257                version: 2,
258                lock_time: 1257139,
259                input: vec![TxIn {
260                    previous_output: OutPoint {
261                        txid: Txid::from_hex(
262                            "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
263                        ).unwrap(),
264                        vout: 0,
265                    },
266                    script_sig: Script::new(),
267                    sequence: 4294967294,
268                    witness: vec![],
269                }],
270                output: vec![
271                    TxOut {
272                        value: 99999699,
273                        script_pubkey: hex_script!(
274                            "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"
275                        ),
276                    },
277                    TxOut {
278                        value: 100000000,
279                        script_pubkey: hex_script!(
280                            "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"
281                        ),
282                    },
283                ],
284            },
285            xpub: Default::default(),
286            version: 0,
287            proprietary: Default::default(),
288            unknown: Default::default(),
289        };
290
291        let actual: Global = deserialize(&serialize(&expected)).unwrap();
292
293        assert_eq!(expected, actual);
294    }
295
296    #[test]
297    fn serialize_then_deserialize_psbtkvpair() {
298        let expected = raw::Pair {
299            key: raw::Key {
300                type_value: 0u8,
301                key: vec![42u8, 69u8],
302            },
303            value: vec![69u8, 42u8, 4u8],
304        };
305
306        let actual: raw::Pair = deserialize(&serialize(&expected)).unwrap();
307
308        assert_eq!(expected, actual);
309    }
310
311    #[test]
312    fn deserialize_and_serialize_psbt_with_two_partial_sigs() {
313        let hex = "70736274ff0100890200000001207ae985d787dfe6143d5c58fad79cc7105e0e799fcf033b7f2ba17e62d7b3200000000000ffffffff02563d03000000000022002019899534b9a011043c0dd57c3ff9a381c3522c5f27c6a42319085b56ca543a1d6adc020000000000220020618b47a07ebecca4e156edb1b9ea7c24bdee0139fc049237965ffdaf56d5ee73000000000001012b801a0600000000002200201148e93e9315e37dbed2121be5239257af35adc03ffdfc5d914b083afa44dab82202025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee076473044022007e06b362e89912abd4661f47945430739b006a85d1b2a16c01dc1a4bd07acab022061576d7aa834988b7ab94ef21d8eebd996ea59ea20529a19b15f0c9cebe3d8ac01220202b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a473044022002787f926d6817504431ee281183b8119b6845bfaa6befae45e13b6d430c9d2f02202859f149a6cd26ae2f03a107e7f33c7d91730dade305fe077bae677b5d44952a01010547522102b3fe93530020a8294f0e527e33fbdff184f047eb6b5a1558a352f62c29972f8a21025fe7371376d53cf8a2783917c28bf30bd690b0a4d4a207690093ca2b920ee07652ae0001014752210283ef76537f2d58ae3aa3a4bd8ae41c3f230ccadffb1a0bd3ca504d871cff05e7210353d79cc0cb1396f4ce278d005f16d948e02a6aec9ed1109f13747ecb1507b37b52ae00010147522102b3937241777b6665e0d694e52f9c1b188433641df852da6fc42187b5d8a368a321034cdd474f01cc5aa7ff834ad8bcc882a87e854affc775486bc2a9f62e8f49bd7852ae00";
314        let psbt: PartiallySignedTransaction = hex_psbt!(hex).unwrap();
315        assert_eq!(hex, serialize_hex(&psbt));
316    }
317
318    #[cfg(feature = "serde")]
319    #[test]
320    fn test_serde_psbt() {
321        //! Create a full PSBT value with various fields filled and make sure it can be JSONized.
322        use hashes::sha256d;
323        use util::psbt::map::Input;
324
325        // create some values to use in the PSBT
326        let tx = Transaction {
327            version: 1,
328            lock_time: 0,
329            input: vec![TxIn {
330                previous_output: OutPoint {
331                    txid: Txid::from_hex("e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389").unwrap(),
332                    vout: 1,
333                },
334                script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
335                sequence: 4294967295,
336                witness: vec![Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()],
337            }],
338            output: vec![
339                TxOut {
340                    value: 190303501938,
341                    script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
342                },
343            ],
344        };
345        let unknown: BTreeMap<raw::Key, Vec<u8>> = vec![(
346            raw::Key { type_value: 1, key: vec![0, 1] },
347            vec![3, 4 ,5],
348        )].into_iter().collect();
349        let key_source = ("deadbeef".parse().unwrap(), "m/0'/1".parse().unwrap());
350        let keypaths: BTreeMap<PublicKey, KeySource> = vec![(
351            "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
352            key_source.clone(),
353        )].into_iter().collect();
354
355        let proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = vec![(
356            raw::ProprietaryKey {
357                prefix: "prefx".as_bytes().to_vec(),
358                subtype: 42,
359                key: "test_key".as_bytes().to_vec(),
360            },
361            vec![5, 6, 7],
362        )].into_iter().collect();
363
364        let psbt = PartiallySignedTransaction {
365            global: Global {
366                version: 0,
367                xpub: {
368                    let xpub: ExtendedPubKey =
369                        "xpub661MyMwAqRbcGoRVtwfvzZsq2VBJR1LAHfQstHUoxqDorV89vRoMxUZ27kLrraAj6MPi\
370                        QfrDb27gigC1VS1dBXi5jGpxmMeBXEkKkcXUTg4".parse().unwrap();
371                    vec![(xpub, key_source.clone())].into_iter().collect()
372                },
373                unsigned_tx: {
374                    let mut unsigned = tx.clone();
375                    unsigned.input[0].script_sig = Script::new();
376                    unsigned.input[0].witness = Vec::new();
377                    unsigned
378                },
379                proprietary: proprietary.clone(),
380                unknown: unknown.clone(),
381            },
382            inputs: vec![Input {
383                non_witness_utxo: Some(tx),
384                witness_utxo: Some(TxOut {
385                    value: 190303501938,
386                    script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
387                }),
388                sighash_type: Some("SIGHASH_SINGLE|SIGHASH_ANYONECANPAY".parse().unwrap()),
389                redeem_script: Some(vec![0x51].into()),
390                witness_script: None,
391                partial_sigs: vec![(
392                    "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(),
393                    vec![8, 5, 4],
394                )].into_iter().collect(),
395                bip32_derivation: keypaths.clone(),
396                final_script_witness: Some(vec![vec![1, 3], vec![5]]),
397                ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
398                sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
399                hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
400                hash256_preimages: vec![(sha256d::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
401                proprietary: proprietary.clone(),
402                unknown: unknown.clone(),
403                ..Default::default()
404            }],
405            outputs: vec![Output {
406                bip32_derivation: keypaths.clone(),
407                proprietary: proprietary.clone(),
408                unknown: unknown.clone(),
409                ..Default::default()
410            }],
411        };
412        let encoded = ::serde_json::to_string(&psbt).unwrap();
413        println!("encoded PSBT: {}", encoded);
414        let decoded: PartiallySignedTransaction = ::serde_json::from_str(&encoded).unwrap();
415        assert_eq!(psbt, decoded);
416    }
417
418    mod bip_vectors {
419        use std::collections::BTreeMap;
420
421        use hashes::hex::FromHex;
422        use hash_types::Txid;
423
424        use blockdata::script::Script;
425        use blockdata::transaction::{SigHashType, Transaction, TxIn, TxOut, OutPoint};
426        use consensus::encode::serialize_hex;
427        use util::psbt::map::{Map, Global, Input, Output};
428        use util::psbt::raw;
429        use util::psbt::PartiallySignedTransaction;
430
431        #[test]
432        fn invalid_vector_1() {
433            let psbt: Result<PartiallySignedTransaction, _> = hex_psbt!("0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300");
434            assert!(psbt.is_err());
435        }
436
437        #[test]
438        fn invalid_vector_2() {
439            let psbt: Result<PartiallySignedTransaction, _> = hex_psbt!("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000");
440            assert!(psbt.is_err());
441        }
442
443        #[test]
444        fn invalid_vector_3() {
445            let psbt: Result<PartiallySignedTransaction, _> = hex_psbt!("70736274ff0100fd0a010200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be4000000006a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa88292feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000");
446            assert!(psbt.is_err());
447        }
448
449        #[test]
450        fn invalid_vector_4() {
451            let psbt: Result<PartiallySignedTransaction, _> = hex_psbt!("70736274ff000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000000");
452            assert!(psbt.is_err());
453        }
454
455        #[test]
456        fn invalid_vector_5() {
457            let psbt: Result<PartiallySignedTransaction, _> = hex_psbt!("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000000");
458            assert!(psbt.is_err());
459        }
460
461        #[test]
462        fn valid_vector_1() {
463            let unserialized = PartiallySignedTransaction {
464                global: Global {
465                    unsigned_tx: Transaction {
466                        version: 2,
467                        lock_time: 1257139,
468                        input: vec![TxIn {
469                            previous_output: OutPoint {
470                                txid: Txid::from_hex(
471                                    "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
472                                ).unwrap(),
473                                vout: 0,
474                            },
475                            script_sig: Script::new(),
476                            sequence: 4294967294,
477                            witness: vec![],
478                        }],
479                        output: vec![
480                            TxOut {
481                                value: 99999699,
482                                script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
483                            },
484                            TxOut {
485                                value: 100000000,
486                                script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
487                            },
488                        ],
489                    },
490                    xpub: Default::default(),
491                    version: 0,
492                    proprietary: BTreeMap::new(),
493                    unknown: BTreeMap::new(),
494                },
495                inputs: vec![Input {
496                    non_witness_utxo: Some(Transaction {
497                        version: 1,
498                        lock_time: 0,
499                        input: vec![TxIn {
500                            previous_output: OutPoint {
501                                txid: Txid::from_hex(
502                                    "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
503                                ).unwrap(),
504                                vout: 1,
505                            },
506                            script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
507                            sequence: 4294967295,
508                            witness: vec![
509                                Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
510                                Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
511                            ],
512                        },
513                        TxIn {
514                            previous_output: OutPoint {
515                                txid: Txid::from_hex(
516                                    "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
517                                ).unwrap(),
518                                vout: 1,
519                            },
520                            script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
521                            sequence: 4294967295,
522                            witness: vec![
523                                Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
524                                Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
525                            ],
526                        }],
527                        output: vec![
528                            TxOut {
529                                value: 200000000,
530                                script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
531                            },
532                            TxOut {
533                                value: 190303501938,
534                                script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
535                            },
536                        ],
537                    }),
538                    ..Default::default()
539                },],
540                outputs: vec![
541                    Output {
542                        ..Default::default()
543                    },
544                    Output {
545                        ..Default::default()
546                    },
547                ],
548            };
549
550            let serialized = "70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab300000000000000";
551
552            assert_eq!(serialize_hex(&unserialized), serialized);
553            assert_eq!(unserialized, hex_psbt!(serialized).unwrap());
554        }
555
556        #[test]
557        fn valid_vector_2() {
558            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap();
559
560            assert_eq!(psbt.inputs.len(), 2);
561            assert_eq!(psbt.outputs.len(), 2);
562
563            assert!(&psbt.inputs[0].final_script_sig.is_some());
564
565            let redeem_script: &Script = &psbt.inputs[1].redeem_script.as_ref().unwrap();
566            let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787");
567
568            assert!(redeem_script.is_v0_p2wpkh());
569            assert_eq!(
570                redeem_script.to_p2sh(),
571                psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey
572            );
573            assert_eq!(redeem_script.to_p2sh(), expected_out);
574
575            for output in psbt.outputs {
576                assert_eq!(output.get_pairs().unwrap().len(), 0)
577            }
578        }
579
580        #[test]
581        fn valid_vector_3() {
582            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100750200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf60000000000feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300000100fda5010100000000010289a3c71eab4d20e0371bbba4cc698fa295c9463afa2e397f8533ccb62f9567e50100000017160014be18d152a9b012039daf3da7de4f53349eecb985ffffffff86f8aa43a71dff1448893a530a7237ef6b4608bbb2dd2d0171e63aec6a4890b40100000017160014fe3e9ef1a745e974d902c4355943abcb34bd5353ffffffff0200c2eb0b000000001976a91485cff1097fd9e008bb34af709c62197b38978a4888ac72fef84e2c00000017a914339725ba21efd62ac753a9bcd067d6c7a6a39d05870247304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c012103d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f210502483045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01210223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab30000000001030401000000000000").unwrap();
583
584            assert_eq!(psbt.inputs.len(), 1);
585            assert_eq!(psbt.outputs.len(), 2);
586
587            let tx_input = &psbt.global.unsigned_tx.input[0];
588            let psbt_non_witness_utxo = (&psbt.inputs[0].non_witness_utxo).as_ref().unwrap();
589
590            assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.txid());
591            assert!(
592                psbt_non_witness_utxo.output[tx_input.previous_output.vout as usize]
593                    .script_pubkey
594                    .is_p2pkh()
595            );
596            assert_eq!(
597                (&psbt.inputs[0].sighash_type).as_ref().unwrap(),
598                &SigHashType::All
599            );
600        }
601
602        #[test]
603        fn valid_vector_4() {
604            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac00000000000100df0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e13000001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb8230800220202ead596687ca806043edc3de116cdf29d5e9257c196cd055cf698c8d02bf24e9910b4a6ba670000008000000080020000800022020394f62be9df19952c5587768aeb7698061ad2c4a25c894f47d8c162b4d7213d0510b4a6ba6700000080010000800200008000").unwrap();
605
606            assert_eq!(psbt.inputs.len(), 2);
607            assert_eq!(psbt.outputs.len(), 2);
608
609            assert!(&psbt.inputs[0].final_script_sig.is_none());
610            assert!(&psbt.inputs[1].final_script_sig.is_none());
611
612            let redeem_script: &Script = &psbt.inputs[1].redeem_script.as_ref().unwrap();
613            let expected_out = hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787");
614
615            assert!(redeem_script.is_v0_p2wpkh());
616            assert_eq!(
617                redeem_script.to_p2sh(),
618                psbt.inputs[1].witness_utxo.as_ref().unwrap().script_pubkey
619            );
620            assert_eq!(redeem_script.to_p2sh(), expected_out);
621
622            for output in psbt.outputs {
623                assert!(output.get_pairs().unwrap().len() > 0)
624            }
625        }
626
627        #[test]
628        fn valid_vector_5() {
629            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100550200000001279a2323a5dfb51fc45f220fa58b0fc13e1e3342792a85d7e36cd6333b5cbc390000000000ffffffff01a05aea0b000000001976a914ffe9c0061097cc3b636f2cb0460fa4fc427d2b4588ac0000000000010120955eea0b0000000017a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87220203b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4646304302200424b58effaaa694e1559ea5c93bbfd4a89064224055cdf070b6771469442d07021f5c8eb0fea6516d60b8acb33ad64ede60e8785bfb3aa94b99bdf86151db9a9a010104220020771fd18ad459666dd49f3d564e3dbc42f4c84774e360ada16816a8ed488d5681010547522103b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd462103de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd52ae220603b1341ccba7683b6af4f1238cd6e97e7167d569fac47f1e48d47541844355bd4610b4a6ba67000000800000008004000080220603de55d1e1dac805e3f8a58c1fbf9b94c02f3dbaafe127fefca4995f26f82083bd10b4a6ba670000008000000080050000800000").unwrap();
630
631            assert_eq!(psbt.inputs.len(), 1);
632            assert_eq!(psbt.outputs.len(), 1);
633
634            assert!(&psbt.inputs[0].final_script_sig.is_none());
635
636            let redeem_script: &Script = &psbt.inputs[0].redeem_script.as_ref().unwrap();
637            let expected_out = hex_script!("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87");
638
639            assert!(redeem_script.is_v0_p2wsh());
640            assert_eq!(
641                redeem_script.to_p2sh(),
642                psbt.inputs[0].witness_utxo.as_ref().unwrap().script_pubkey
643            );
644
645            assert_eq!(redeem_script.to_p2sh(), expected_out);
646        }
647
648        #[test]
649        fn valid_vector_6() {
650            let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003f0200000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ffffffff010000000000000000036a010000000000000a0f0102030405060708090f0102030405060708090a0b0c0d0e0f0000").unwrap();
651
652            assert_eq!(psbt.inputs.len(), 1);
653            assert_eq!(psbt.outputs.len(), 1);
654
655            let tx = &psbt.global.unsigned_tx;
656            assert_eq!(
657                tx.txid(),
658                Txid::from_hex(
659                    "75c5c9665a570569ad77dd1279e6fd4628a093c4dcbf8d41532614044c14c115"
660                ).unwrap()
661            );
662
663            let mut unknown: BTreeMap<raw::Key, Vec<u8>> = BTreeMap::new();
664            let key: raw::Key = raw::Key {
665                type_value: 0x0fu8,
666                key: Vec::from_hex("010203040506070809").unwrap(),
667            };
668            let value: Vec<u8> = Vec::from_hex("0102030405060708090a0b0c0d0e0f").unwrap();
669
670            unknown.insert(key, value);
671
672            assert_eq!(psbt.inputs[0].unknown, unknown)
673        }
674    }
675
676    #[test]
677    fn serialize_and_deserialize_preimage_psbt(){
678        // create a sha preimage map
679        let mut sha256_preimages = BTreeMap::new();
680        sha256_preimages.insert(sha256::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]);
681        sha256_preimages.insert(sha256::Hash::hash(&[1u8]), vec![1u8]);
682
683        // same for hash160
684        let mut hash160_preimages = BTreeMap::new();
685        hash160_preimages.insert(hash160::Hash::hash(&[1u8, 2u8]), vec![1u8, 2u8]);
686        hash160_preimages.insert(hash160::Hash::hash(&[1u8]), vec![1u8]);
687
688        // same vector as valid_vector_1 from BIPs with added
689        let mut unserialized = PartiallySignedTransaction {
690            global: Global {
691                unsigned_tx: Transaction {
692                    version: 2,
693                    lock_time: 1257139,
694                    input: vec![TxIn {
695                        previous_output: OutPoint {
696                            txid: Txid::from_hex(
697                                "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126",
698                            ).unwrap(),
699                            vout: 0,
700                        },
701                        script_sig: Script::new(),
702                        sequence: 4294967294,
703                        witness: vec![],
704                    }],
705                    output: vec![
706                        TxOut {
707                            value: 99999699,
708                            script_pubkey: hex_script!("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac"),
709                        },
710                        TxOut {
711                            value: 100000000,
712                            script_pubkey: hex_script!("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787"),
713                        },
714                    ],
715                },
716                version: 0,
717                xpub: Default::default(),
718                proprietary: Default::default(),
719                unknown: BTreeMap::new(),
720            },
721            inputs: vec![Input {
722                non_witness_utxo: Some(Transaction {
723                    version: 1,
724                    lock_time: 0,
725                    input: vec![TxIn {
726                        previous_output: OutPoint {
727                            txid: Txid::from_hex(
728                                "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389",
729                            ).unwrap(),
730                            vout: 1,
731                        },
732                        script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
733                        sequence: 4294967295,
734                        witness: vec![
735                            Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
736                            Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
737                        ],
738                    },
739                    TxIn {
740                        previous_output: OutPoint {
741                            txid: Txid::from_hex(
742                                "b490486aec3ae671012dddb2bb08466bef37720a533a894814ff1da743aaf886",
743                            ).unwrap(),
744                            vout: 1,
745                        },
746                        script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
747                        sequence: 4294967295,
748                        witness: vec![
749                            Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
750                            Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
751                        ],
752                    }],
753                    output: vec![
754                        TxOut {
755                            value: 200000000,
756                            script_pubkey: hex_script!("76a91485cff1097fd9e008bb34af709c62197b38978a4888ac"),
757                        },
758                        TxOut {
759                            value: 190303501938,
760                            script_pubkey: hex_script!("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587"),
761                        },
762                    ],
763                }),
764                ..Default::default()
765            },],
766            outputs: vec![
767                Output {
768                    ..Default::default()
769                },
770                Output {
771                    ..Default::default()
772                },
773            ],
774        };
775        unserialized.inputs[0].hash160_preimages = hash160_preimages;
776        unserialized.inputs[0].sha256_preimages = sha256_preimages;
777
778        let rtt : PartiallySignedTransaction = hex_psbt!(&serialize_hex(&unserialized)).unwrap();
779        assert_eq!(rtt, unserialized);
780
781        // Now add an ripemd160 with incorrect preimage
782        let mut ripemd160_preimages = BTreeMap::new();
783        ripemd160_preimages.insert(ripemd160::Hash::hash(&[17u8]), vec![18u8]);
784        unserialized.inputs[0].ripemd160_preimages = ripemd160_preimages;
785
786        // Now the roundtrip should fail as the preimage is incorrect.
787        let rtt : Result<PartiallySignedTransaction, _> = hex_psbt!(&serialize_hex(&unserialized));
788        assert!(rtt.is_err());
789    }
790}