Skip to main content

bitcoin/util/psbt/map/
global.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::collections::BTreeMap;
16use std::collections::btree_map::Entry;
17use std::io::{self, Cursor, Read};
18use std::cmp;
19use secp256k1::{ContextFlag, Secp256k1};
20
21use blockdata::transaction::Transaction;
22use consensus::{encode, Encodable, Decodable};
23use util::psbt::map::Map;
24use util::psbt::raw;
25use util::psbt;
26use util::psbt::Error;
27use util::endian::u32_to_array_le;
28use util::bip32::{ExtendedPubKey, KeySource, Fingerprint, DerivationPath, ChildNumber};
29
30/// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00
31const PSBT_GLOBAL_UNSIGNED_TX: u8 = 0x00;
32/// Type: Extended Public Key PSBT_GLOBAL_XPUB = 0x01
33const PSBT_GLOBAL_XPUB: u8 = 0x01;
34/// Type: Version Number PSBT_GLOBAL_VERSION = 0xFB
35const PSBT_GLOBAL_VERSION: u8 = 0xFB;
36/// Type: Proprietary Use Type PSBT_GLOBAL_PROPRIETARY = 0xFC
37const PSBT_GLOBAL_PROPRIETARY: u8 = 0xFC;
38
39/// A key-value map for global data.
40#[derive(Clone, Debug, PartialEq)]
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42pub struct Global {
43    /// The unsigned transaction, scriptSigs and witnesses for each input must be
44    /// empty.
45    pub unsigned_tx: Transaction,
46    /// The version number of this PSBT. If omitted, the version number is 0.
47    pub version: u32,
48    /// A global map from extended public keys to the used key fingerprint and
49    /// derivation path as defined by BIP 32
50    pub xpub: BTreeMap<ExtendedPubKey, KeySource>,
51    /// Global proprietary key-value pairs.
52    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
53    pub proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
54    /// Unknown global key-value pairs.
55    #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))]
56    pub unknown: BTreeMap<raw::Key, Vec<u8>>,
57}
58
59impl Global {
60    /// Create a Global from an unsigned transaction, error if not unsigned
61    pub fn from_unsigned_tx(tx: Transaction) -> Result<Self, psbt::Error> {
62        for txin in &tx.input {
63            if !txin.script_sig.is_empty() {
64                return Err(Error::UnsignedTxHasScriptSigs);
65            }
66
67            if !txin.witness.is_empty() {
68                return Err(Error::UnsignedTxHasScriptWitnesses);
69            }
70        }
71
72        Ok(Global {
73            unsigned_tx: tx,
74            xpub: Default::default(),
75            version: 0,
76            proprietary: Default::default(),
77            unknown: Default::default(),
78        })
79    }
80}
81
82impl Map for Global {
83    fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> {
84        let raw::Pair {
85            key: raw_key,
86            value: raw_value,
87        } = pair;
88
89        match raw_key.type_value {
90            PSBT_GLOBAL_UNSIGNED_TX => return Err(Error::DuplicateKey(raw_key).into()),
91            PSBT_GLOBAL_PROPRIETARY => match self.proprietary.entry(raw::ProprietaryKey::from_key(raw_key.clone())?) {
92                Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
93                Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()),
94            }
95            _ => match self.unknown.entry(raw_key) {
96                Entry::Vacant(empty_key) => {empty_key.insert(raw_value);},
97                Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
98            }
99        }
100
101        Ok(())
102    }
103
104    fn get_pairs(&self) -> Result<Vec<raw::Pair>, io::Error> {
105        let mut rv: Vec<raw::Pair> = Default::default();
106
107        rv.push(raw::Pair {
108            key: raw::Key {
109                type_value: PSBT_GLOBAL_UNSIGNED_TX,
110                key: vec![],
111            },
112            value: {
113                // Manually serialized to ensure 0-input txs are serialized
114                // without witnesses.
115                let mut ret = Vec::new();
116                self.unsigned_tx.version.consensus_encode(&mut ret)?;
117                self.unsigned_tx.input.consensus_encode(&mut ret)?;
118                self.unsigned_tx.output.consensus_encode(&mut ret)?;
119                self.unsigned_tx.lock_time.consensus_encode(&mut ret)?;
120                ret
121            },
122        });
123
124        let secp = Secp256k1::with_caps(ContextFlag::None);
125
126        for (xpub, (fingerprint, derivation)) in &self.xpub {
127            rv.push(raw::Pair {
128                key: raw::Key {
129                    type_value: PSBT_GLOBAL_XPUB,
130                    key: xpub.encode(&secp).to_vec(),
131                },
132                value: {
133                    let mut ret = Vec::with_capacity(4 + derivation.len() * 4);
134                    ret.extend(fingerprint.as_bytes());
135                    derivation.into_iter().for_each(|n| ret.extend(&u32_to_array_le((*n).into())));
136                    ret
137                }
138            });
139        }
140
141        // Serializing version only for non-default value; otherwise test vectors fail
142        if self.version > 0 {
143            rv.push(raw::Pair {
144                key: raw::Key {
145                    type_value: PSBT_GLOBAL_VERSION,
146                    key: vec![],
147                },
148                value: u32_to_array_le(self.version).to_vec()
149            });
150        }
151
152        for (key, value) in self.proprietary.iter() {
153            rv.push(raw::Pair {
154                key: key.to_key(),
155                value: value.clone(),
156            });
157        }
158
159        for (key, value) in self.unknown.iter() {
160            rv.push(raw::Pair {
161                key: key.clone(),
162                value: value.clone(),
163            });
164        }
165
166        Ok(rv)
167    }
168
169    // Keep in mind that according to BIP 174 this function must be commutative, i.e.
170    // A.merge(B) == B.merge(A)
171    fn merge(&mut self, other: Self) -> Result<(), psbt::Error> {
172        if self.unsigned_tx != other.unsigned_tx {
173            return Err(psbt::Error::UnexpectedUnsignedTx {
174                expected: self.unsigned_tx.clone(),
175                actual: other.unsigned_tx,
176            });
177        }
178
179        // BIP 174: The Combiner must remove any duplicate key-value pairs, in accordance with
180        //          the specification. It can pick arbitrarily when conflicts occur.
181
182        // Keeping the highest version
183        self.version = cmp::max(self.version, other.version);
184
185        // Merging xpubs
186        for (xpub, (fingerprint1, derivation1)) in other.xpub {
187            match self.xpub.entry(xpub.clone()) {
188                Entry::Vacant(entry) => {
189                    entry.insert((fingerprint1, derivation1));
190                },
191                Entry::Occupied(mut entry) => {
192                    // Here in case of the conflict we select the version with algorithm:
193                    // 1) if everything is equal we do nothing
194                    // 2) report an error if
195                    //    - derivation paths are equal and fingerprints are not
196                    //    - derivation paths are of the same length, but not equal
197                    //    - derivation paths has different length, but the shorter one
198                    //      is not the strict suffix of the longer one
199                    // 3) choose longest derivation otherwise
200
201                    let (fingerprint2, derivation2) = entry.get().clone();
202
203                    if derivation1 == derivation2 && fingerprint1 == fingerprint2
204                    {
205                        continue
206                    }
207                    else if
208                        derivation1.len() < derivation2.len() &&
209                        derivation1[..] == derivation2[derivation2.len() - derivation1.len()..]
210                    {
211                        continue
212                    }
213                    else if derivation2[..] == derivation1[derivation1.len() - derivation2.len()..]
214                    {
215                        entry.insert((fingerprint1, derivation1));
216                        continue
217                    }
218                    return Err(psbt::Error::MergeConflict(format!(
219                        "global xpub {} has inconsistent key sources", xpub
220                    ).to_owned()));
221                }
222            }
223        }
224
225        self.proprietary.extend(other.proprietary);
226        self.unknown.extend(other.unknown);
227        Ok(())
228    }
229}
230
231impl_psbtmap_consensus_encoding!(Global);
232
233impl Decodable for Global {
234    fn consensus_decode<D: io::Read>(mut d: D) -> Result<Self, encode::Error> {
235
236        let mut tx: Option<Transaction> = None;
237        let mut version: Option<u32> = None;
238        let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();
239        let mut xpub_map: BTreeMap<ExtendedPubKey, (Fingerprint, DerivationPath)> = Default::default();
240        let mut proprietary: BTreeMap<raw::ProprietaryKey, Vec<u8>> = Default::default();
241
242        let secp = Secp256k1::with_caps(ContextFlag::None);
243
244        loop {
245            match raw::Pair::consensus_decode(&mut d) {
246                Ok(pair) => {
247                    match pair.key.type_value {
248                        PSBT_GLOBAL_UNSIGNED_TX => {
249                            // key has to be empty
250                            if pair.key.key.is_empty() {
251                                // there can only be one unsigned transaction
252                                if tx.is_none() {
253                                    let vlen: usize = pair.value.len();
254                                    let mut decoder = Cursor::new(pair.value);
255
256                                    // Manually deserialized to ensure 0-input
257                                    // txs without witnesses are deserialized
258                                    // properly.
259                                    tx = Some(Transaction {
260                                        version: Decodable::consensus_decode(&mut decoder)?,
261                                        input: Decodable::consensus_decode(&mut decoder)?,
262                                        output: Decodable::consensus_decode(&mut decoder)?,
263                                        lock_time: Decodable::consensus_decode(&mut decoder)?,
264                                    });
265
266                                    if decoder.position() != vlen as u64 {
267                                        return Err(encode::Error::ParseFailed("data not consumed entirely when explicitly deserializing"))
268                                    }
269                                } else {
270                                    return Err(Error::DuplicateKey(pair.key).into())
271                                }
272                            } else {
273                                return Err(Error::InvalidKey(pair.key).into())
274                            }
275                        }
276                        PSBT_GLOBAL_XPUB => {
277                            if !pair.key.key.is_empty() {
278                                let xpub = ExtendedPubKey::decode(&secp, &pair.key.key)
279                                    .map_err(|_| encode::Error::ParseFailed(
280                                        "Can't deserialize ExtendedPublicKey from global XPUB key data"
281                                    ))?;
282
283                                if pair.value.is_empty() || pair.value.len() % 4 != 0 {
284                                    return Err(encode::Error::ParseFailed("Incorrect length of global xpub derivation data"))
285                                }
286
287                                let child_count = pair.value.len() / 4 - 1;
288                                let mut decoder = Cursor::new(pair.value);
289                                let mut fingerprint = [0u8; 4];
290                                decoder.read_exact(&mut fingerprint[..])?;
291                                let mut path = Vec::<ChildNumber>::with_capacity(child_count);
292                                while let Ok(index) = u32::consensus_decode(&mut decoder) {
293                                    path.push(ChildNumber::from(index))
294                                }
295                                let derivation = DerivationPath::from(path);
296                                // Keys, according to BIP-174, must be unique
297                                if xpub_map.insert(xpub, (Fingerprint::from(&fingerprint[..]), derivation)).is_some() {
298                                    return Err(encode::Error::ParseFailed("Repeated global xpub key"))
299                                }
300                            } else {
301                                return Err(encode::Error::ParseFailed("Xpub global key must contain serialized Xpub data"))
302                            }
303                        }
304                        PSBT_GLOBAL_VERSION => {
305                            // key has to be empty
306                            if pair.key.key.is_empty() {
307                                // there can only be one version
308                                if version.is_none() {
309                                    let vlen: usize = pair.value.len();
310                                    let mut decoder = Cursor::new(pair.value);
311                                    if vlen != 4 {
312                                        return Err(encode::Error::ParseFailed("Wrong global version value length (must be 4 bytes)"))
313                                    }
314                                    version = Some(Decodable::consensus_decode(&mut decoder)?);
315                                    // We only understand version 0 PSBTs. According to BIP-174 we
316                                    // should throw an error if we see anything other than version 0.
317                                    if version != Some(0) {
318                                        return Err(encode::Error::ParseFailed("PSBT versions greater than 0 are not supported"))
319                                    }
320                                } else {
321                                    return Err(Error::DuplicateKey(pair.key).into())
322                                }
323                            } else {
324                                return Err(Error::InvalidKey(pair.key).into())
325                            }
326                        }
327                        PSBT_GLOBAL_PROPRIETARY => match proprietary.entry(raw::ProprietaryKey::from_key(pair.key.clone())?) {
328                            Entry::Vacant(empty_key) => {empty_key.insert(pair.value);},
329                            Entry::Occupied(_) => return Err(Error::DuplicateKey(pair.key).into()),
330                        }
331                        _ => match unknowns.entry(pair.key) {
332                            Entry::Vacant(empty_key) => {empty_key.insert(pair.value);},
333                            Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone()).into()),
334                        }
335                    }
336                }
337                Err(::consensus::encode::Error::Psbt(::util::psbt::Error::NoMorePairs)) => break,
338                Err(e) => return Err(e),
339            }
340        }
341
342        if let Some(tx) = tx {
343            let mut rv: Global = Global::from_unsigned_tx(tx)?;
344            rv.version = version.unwrap_or(0);
345            rv.xpub = xpub_map;
346            rv.unknown = unknowns;
347            Ok(rv)
348        } else {
349            Err(Error::MustHaveUnsignedTx.into())
350        }
351    }
352}