bitcoin/util/psbt/map/
input.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
15use std::io;
16use std::collections::btree_map::{BTreeMap, Entry};
17
18use blockdata::script::Script;
19use blockdata::transaction::{SigHashType, Transaction, TxOut};
20use consensus::encode;
21use util::bip32::KeySource;
22use hashes::{self, hash160, ripemd160, sha256, sha256d};
23use util::key::PublicKey;
24use util::psbt;
25use util::psbt::map::Map;
26use util::psbt::raw;
27use util::psbt::serialize::Deserialize;
28use util::psbt::{Error, error};
29
30/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00
31const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00;
32/// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01
33const PSBT_IN_WITNESS_UTXO: u8 = 0x01;
34/// Type: Partial Signature PSBT_IN_PARTIAL_SIG = 0x02
35const PSBT_IN_PARTIAL_SIG: u8 = 0x02;
36/// Type: Sighash Type PSBT_IN_SIGHASH_TYPE = 0x03
37const PSBT_IN_SIGHASH_TYPE: u8 = 0x03;
38/// Type: Redeem Script PSBT_IN_REDEEM_SCRIPT = 0x04
39const PSBT_IN_REDEEM_SCRIPT: u8 = 0x04;
40/// Type: Witness Script PSBT_IN_WITNESS_SCRIPT = 0x05
41const PSBT_IN_WITNESS_SCRIPT: u8 = 0x05;
42/// Type: BIP 32 Derivation Path PSBT_IN_BIP32_DERIVATION = 0x06
43const PSBT_IN_BIP32_DERIVATION: u8 = 0x06;
44/// Type: Finalized scriptSig PSBT_IN_FINAL_SCRIPTSIG = 0x07
45const PSBT_IN_FINAL_SCRIPTSIG: u8 = 0x07;
46/// Type: Finalized scriptWitness PSBT_IN_FINAL_SCRIPTWITNESS = 0x08
47const PSBT_IN_FINAL_SCRIPTWITNESS: u8 = 0x08;
48/// Type: RIPEMD160 preimage PSBT_IN_RIPEMD160 = 0x0a
49const PSBT_IN_RIPEMD160: u8 = 0x0a;
50/// Type: SHA256 preimage PSBT_IN_SHA256 = 0x0b
51const PSBT_IN_SHA256: u8 = 0x0b;
52/// Type: HASH160 preimage PSBT_IN_HASH160 = 0x0c
53const PSBT_IN_HASH160: u8 = 0x0c;
54/// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d
55const PSBT_IN_HASH256: u8 = 0x0d;
56/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC
57const PSBT_IN_PROPRIETARY: u8 = 0xFC;
58
59/// A key-value map for an input of the corresponding index in the unsigned
60/// transaction.
61#[derive(Clone, Default, Debug, PartialEq)]
62#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
63pub struct Input {
64    /// The non-witness transaction this input spends from. Should only be
65    /// [std::option::Option::Some] for inputs which spend non-segwit outputs or
66    /// if it is unknown whether an input spends a segwit output.
67    pub non_witness_utxo: Option<Transaction>,
68    /// The transaction output this input spends from. Should only be
69    /// [std::option::Option::Some] for inputs which spend segwit outputs,
70    /// including P2SH embedded ones.
71    pub witness_utxo: Option<TxOut>,
72    /// A map from public keys to their corresponding signature as would be
73    /// pushed to the stack from a scriptSig or witness.
74    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
75    pub partial_sigs: BTreeMap<PublicKey, Vec<u8>>,
76    /// The sighash type to be used for this input. Signatures for this input
77    /// must use the sighash type.
78    pub sighash_type: Option<SigHashType>,
79    /// The redeem script for this input.
80    pub redeem_script: Option<Script>,
81    /// The witness script for this input.
82    pub witness_script: Option<Script>,
83    /// A map from public keys needed to sign this input to their corresponding
84    /// master key fingerprints and derivation paths.
85    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))]
86    pub bip32_derivation: BTreeMap<PublicKey, KeySource>,
87    /// The finalized, fully-constructed scriptSig with signatures and any other
88    /// scripts necessary for this input to pass validation.
89    pub final_script_sig: Option<Script>,
90    /// The finalized, fully-constructed scriptWitness with signatures and any
91    /// other scripts necessary for this input to pass validation.
92    pub final_script_witness: Option<Vec<Vec<u8>>>,
93    /// TODO: Proof of reserves commitment
94    /// RIPEMD160 hash to preimage map
95    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
96    pub ripemd160_preimages: BTreeMap<ripemd160::Hash, Vec<u8>>,
97    /// SHA256 hash to preimage map
98    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
99    pub sha256_preimages: BTreeMap<sha256::Hash, Vec<u8>>,
100    /// HSAH160 hash to preimage map
101    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
102    pub hash160_preimages: BTreeMap<hash160::Hash, Vec<u8>>,
103    /// HAS256 hash to preimage map
104    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))]
105    pub hash256_preimages: BTreeMap<sha256d::Hash, Vec<u8>>,
106    /// Proprietary key-value pairs for this input.
107    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
108    pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
109    /// Unknown key-value pairs for this input.
110    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
111    pub unknown: BTreeMap<raw::Key, Vec<u8>>,
112}
113
114impl Map for Input {
115    fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
116        let raw::Pair {
117            key: raw_key,
118            value: raw_value,
119        } = pair;
120
121        match raw_key.type_value {
122            PSBT_IN_NON_WITNESS_UTXO => {
123                impl_psbt_insert_pair! {
124                    self.non_witness_utxo <= <raw_key: _>|<raw_value: Transaction>
125                }
126            }
127            PSBT_IN_WITNESS_UTXO => {
128                impl_psbt_insert_pair! {
129                    self.witness_utxo <= <raw_key: _>|<raw_value: TxOut>
130                }
131            }
132            PSBT_IN_PARTIAL_SIG => {
133                impl_psbt_insert_pair! {
134                    self.partial_sigs <= <raw_key: PublicKey>|<raw_value: Vec<u8>>
135                }
136            }
137            PSBT_IN_SIGHASH_TYPE => {
138                impl_psbt_insert_pair! {
139                    self.sighash_type <= <raw_key: _>|<raw_value: SigHashType>
140                }
141            }
142            PSBT_IN_REDEEM_SCRIPT => {
143                impl_psbt_insert_pair! {
144                    self.redeem_script <= <raw_key: _>|<raw_value: Script>
145                }
146            }
147            PSBT_IN_WITNESS_SCRIPT => {
148                impl_psbt_insert_pair! {
149                    self.witness_script <= <raw_key: _>|<raw_value: Script>
150                }
151            }
152            PSBT_IN_BIP32_DERIVATION => {
153                impl_psbt_insert_pair! {
154                    self.bip32_derivation <= <raw_key: PublicKey>|<raw_value: KeySource>
155                }
156            }
157            PSBT_IN_FINAL_SCRIPTSIG => {
158                impl_psbt_insert_pair! {
159                    self.final_script_sig <= <raw_key: _>|<raw_value: Script>
160                }
161            }
162            PSBT_IN_FINAL_SCRIPTWITNESS => {
163                impl_psbt_insert_pair! {
164                    self.final_script_witness <= <raw_key: _>|<raw_value: Vec<Vec<u8>>>
165                }
166            }
167            PSBT_IN_RIPEMD160 => {
168                psbt_insert_hash_pair(&mut self.ripemd160_preimages, raw_key, raw_value, error::PsbtHash::Ripemd)?;
169            }
170            PSBT_IN_SHA256 => {
171                psbt_insert_hash_pair(&mut self.sha256_preimages, raw_key, raw_value, error::PsbtHash::Sha256)?;
172            }
173            PSBT_IN_HASH160 => {
174                psbt_insert_hash_pair(&mut self.hash160_preimages, raw_key, raw_value, error::PsbtHash::Hash160)?;
175            }
176            PSBT_IN_HASH256 => {
177                psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?;
178            }
179            PSBT_IN_PROPRIETARY => match self.proprietary.entry(raw::ProprietaryKey::from_key(raw_key.clone())?) {
180                ::std::collections::btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
181                ::std::collections::btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()),
182            }
183            _ => match self.unknown.entry(raw_key) {
184                Entry::Vacant(empty_key) => {
185                    empty_key.insert(raw_value);
186                }
187                Entry::Occupied(k) => {
188                    return Err(Error::DuplicateKey(k.key().clone()).into())
189                }
190            },
191        }
192
193        Ok(())
194    }
195
196    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error> {
197        let mut rv: Vec<raw::Pair> = Default::default();
198
199        impl_psbt_get_pair! {
200            rv.push(self.non_witness_utxo as <PSBT_IN_NON_WITNESS_UTXO, _>|<Transaction>)
201        }
202
203        impl_psbt_get_pair! {
204            rv.push(self.witness_utxo as <PSBT_IN_WITNESS_UTXO, _>|<TxOut>)
205        }
206
207        impl_psbt_get_pair! {
208            rv.push(self.partial_sigs as <PSBT_IN_PARTIAL_SIG, PublicKey>|<Vec<u8>>)
209        }
210
211        impl_psbt_get_pair! {
212            rv.push(self.sighash_type as <PSBT_IN_SIGHASH_TYPE, _>|<SigHashType>)
213        }
214
215        impl_psbt_get_pair! {
216            rv.push(self.redeem_script as <PSBT_IN_REDEEM_SCRIPT, _>|<Script>)
217        }
218
219        impl_psbt_get_pair! {
220            rv.push(self.witness_script as <PSBT_IN_WITNESS_SCRIPT, _>|<Script>)
221        }
222
223        impl_psbt_get_pair! {
224            rv.push(self.bip32_derivation as <PSBT_IN_BIP32_DERIVATION, PublicKey>|<KeySource>)
225        }
226
227        impl_psbt_get_pair! {
228            rv.push(self.final_script_sig as <PSBT_IN_FINAL_SCRIPTSIG, _>|<Script>)
229        }
230
231        impl_psbt_get_pair! {
232            rv.push(self.final_script_witness as <PSBT_IN_FINAL_SCRIPTWITNESS, _>|<Script>)
233        }
234
235        impl_psbt_get_pair! {
236            rv.push(self.ripemd160_preimages as <PSBT_IN_RIPEMD160, ripemd160::Hash>|<Vec<u8>>)
237        }
238
239        impl_psbt_get_pair! {
240            rv.push(self.sha256_preimages as <PSBT_IN_SHA256, sha256::Hash>|<Vec<u8>>)
241        }
242
243        impl_psbt_get_pair! {
244            rv.push(self.hash160_preimages as <PSBT_IN_HASH160, hash160::Hash>|<Vec<u8>>)
245        }
246
247        impl_psbt_get_pair! {
248            rv.push(self.hash256_preimages as <PSBT_IN_HASH256, sha256d::Hash>|<Vec<u8>>)
249        }
250
251        for (key, value) in self.proprietary.iter() {
252            rv.push(raw::Pair {
253                key: key.to_key(),
254                value: value.clone(),
255            });
256        }
257
258        for (key, value) in self.unknown.iter() {
259            rv.push(raw::Pair {
260                key: key.clone(),
261                value: value.clone(),
262            });
263        }
264
265        Ok(rv)
266    }
267
268    fn merge(&mut self, other: Self) -> Result<(), psbt::Error> {
269        merge!(non_witness_utxo, self, other);
270
271        if let (&None, Some(witness_utxo)) = (&self.witness_utxo, other.witness_utxo) {
272            self.witness_utxo = Some(witness_utxo);
273            self.non_witness_utxo = None; // Clear out any non-witness UTXO when we set a witness one
274        }
275
276        self.partial_sigs.extend(other.partial_sigs);
277        self.bip32_derivation.extend(other.bip32_derivation);
278        self.ripemd160_preimages.extend(other.ripemd160_preimages);
279        self.sha256_preimages.extend(other.sha256_preimages);
280        self.hash160_preimages.extend(other.hash160_preimages);
281        self.hash256_preimages.extend(other.hash256_preimages);
282        self.proprietary.extend(other.proprietary);
283        self.unknown.extend(other.unknown);
284
285        merge!(redeem_script, self, other);
286        merge!(witness_script, self, other);
287        merge!(final_script_sig, self, other);
288        merge!(final_script_witness, self, other);
289
290        Ok(())
291    }
292}
293
294impl_psbtmap_consensus_enc_dec_oding!(Input);
295
296fn psbt_insert_hash_pair<H>(
297    map: &mut BTreeMap<H, Vec<u8>>,
298    raw_key: raw::Key,
299    raw_value: Vec<u8>,
300    hash_type: error::PsbtHash,
301) -> Result<(), encode::Error>
302where
303    H: hashes::Hash + Deserialize,
304{
305    if raw_key.key.is_empty() {
306        return Err(psbt::Error::InvalidKey(raw_key).into());
307    }
308    let key_val: H = Deserialize::deserialize(&raw_key.key)?;
309    match map.entry(key_val) {
310        Entry::Vacant(empty_key) => {
311            let val: Vec<u8> = Deserialize::deserialize(&raw_value)?;
312            if <H as hashes::Hash>::hash(&val) != key_val {
313                return Err(psbt::Error::InvalidPreimageHashPair {
314                    preimage: val,
315                    hash: Vec::from(key_val.borrow()),
316                    hash_type: hash_type,
317                }
318                .into());
319            }
320            empty_key.insert(val);
321            Ok(())
322        }
323        Entry::Occupied(_) => return Err(psbt::Error::DuplicateKey(raw_key).into()),
324    }
325}