psbt_v2/v2/map/
global.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use core::convert::TryFrom;
4use core::fmt;
5
6use bitcoin::bip32::{ChildNumber, DerivationPath, Fingerprint, KeySource, Xpub};
7use bitcoin::consensus::{encode as consensus, Decodable};
8use bitcoin::locktime::absolute;
9use bitcoin::{bip32, transaction, VarInt};
10
11use crate::consts::{
12    PSBT_GLOBAL_FALLBACK_LOCKTIME, PSBT_GLOBAL_INPUT_COUNT, PSBT_GLOBAL_OUTPUT_COUNT,
13    PSBT_GLOBAL_PROPRIETARY, PSBT_GLOBAL_TX_MODIFIABLE, PSBT_GLOBAL_TX_VERSION,
14    PSBT_GLOBAL_UNSIGNED_TX, PSBT_GLOBAL_VERSION, PSBT_GLOBAL_XPUB,
15};
16use crate::error::{write_err, InconsistentKeySourcesError};
17use crate::io::{BufRead, Cursor, Read};
18use crate::prelude::*;
19use crate::serialize::Serialize;
20use crate::v2::map::Map;
21use crate::version::Version;
22use crate::{consts, raw, serialize, V2};
23
24/// The Inputs Modifiable Flag, set to 1 to indicate whether inputs can be added or removed.
25const INPUTS_MODIFIABLE: u8 = 0x01 << 0;
26/// The Outputs Modifiable Flag, set to 1 to indicate whether outputs can be added or removed.
27const OUTPUTS_MODIFIABLE: u8 = 0x01 << 1;
28/// The Has SIGHASH_SINGLE flag, set to 1 to indicate whether the transaction has a SIGHASH_SINGLE
29/// signature who's input and output pairing must be preserved. Essentially indicates that the
30/// Constructor must iterate the inputs to determine whether and how to add or remove an input.
31const SIGHASH_SINGLE: u8 = 0x01 << 2;
32
33/// The global key-value map.
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
37pub struct Global {
38    /// The version number of this PSBT.
39    pub version: Version,
40
41    /// The version number of the transaction being built.
42    pub tx_version: transaction::Version,
43
44    /// The transaction locktime to use if no inputs specify a required locktime.
45    pub fallback_lock_time: Option<absolute::LockTime>,
46
47    /// A bitfield for various transaction modification flags.
48    pub tx_modifiable_flags: u8,
49
50    /// The number of inputs in this PSBT.
51    pub input_count: usize, // Serialized in compact form as a u64 (VarInt).
52
53    /// The number of outputs in this PSBT.
54    pub output_count: usize, // Serialized in compact form as a u64 (VarInt).
55
56    /// A map from xpub to the used key fingerprint and derivation path as defined by BIP 32.
57    pub xpubs: BTreeMap<Xpub, KeySource>,
58
59    /// Global proprietary key-value pairs.
60    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
61    pub proprietaries: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
62
63    /// Unknown global key-value pairs.
64    #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
65    pub unknowns: BTreeMap<raw::Key, Vec<u8>>,
66}
67
68impl Global {
69    fn new() -> Self {
70        Global {
71            version: V2,
72            // TODO: Is this default correct?
73            tx_version: transaction::Version::TWO,
74            fallback_lock_time: None,
75            tx_modifiable_flags: 0x00,
76            input_count: 0,
77            output_count: 0,
78            xpubs: Default::default(),
79            proprietaries: Default::default(),
80            unknowns: Default::default(),
81        }
82    }
83
84    pub(crate) fn set_inputs_modifiable_flag(&mut self) {
85        self.tx_modifiable_flags |= INPUTS_MODIFIABLE;
86    }
87
88    pub(crate) fn set_outputs_modifiable_flag(&mut self) {
89        self.tx_modifiable_flags |= OUTPUTS_MODIFIABLE;
90    }
91
92    // TODO: Handle SIGHASH_SINGLE correctly.
93    #[allow(dead_code)]
94    pub(crate) fn set_sighash_single_flag(&mut self) { self.tx_modifiable_flags |= SIGHASH_SINGLE; }
95
96    pub(crate) fn clear_inputs_modifiable_flag(&mut self) {
97        self.tx_modifiable_flags &= !INPUTS_MODIFIABLE;
98    }
99
100    pub(crate) fn clear_outputs_modifiable_flag(&mut self) {
101        self.tx_modifiable_flags &= !OUTPUTS_MODIFIABLE;
102    }
103
104    // TODO: Handle SIGHASH_SINGLE correctly.
105    #[allow(dead_code)]
106    pub(crate) fn clear_sighash_single_flag(&mut self) {
107        self.tx_modifiable_flags &= !SIGHASH_SINGLE;
108    }
109
110    pub(crate) fn is_inputs_modifiable(&self) -> bool {
111        self.tx_modifiable_flags & INPUTS_MODIFIABLE > 0
112    }
113
114    pub(crate) fn is_outputs_modifiable(&self) -> bool {
115        self.tx_modifiable_flags & OUTPUTS_MODIFIABLE > 0
116    }
117
118    // TODO: Investigate if we should be using this function?
119    #[allow(dead_code)]
120    pub(crate) fn has_sighash_single(&self) -> bool {
121        self.tx_modifiable_flags & SIGHASH_SINGLE > 0
122    }
123
124    pub(crate) fn decode<R: BufRead + ?Sized>(r: &mut R) -> Result<Self, DecodeError> {
125        // TODO: Consider adding protection against memory exhaustion here by defining a maximum
126        // PBST size and using `take` as we do in rust-bitcoin consensus decoding.
127        let mut version: Option<Version> = None;
128        let mut tx_version: Option<transaction::Version> = None;
129        let mut fallback_lock_time: Option<absolute::LockTime> = None;
130        let mut tx_modifiable_flags: Option<u8> = None;
131        let mut input_count: Option<u64> = None;
132        let mut output_count: Option<u64> = None;
133        let mut xpubs: BTreeMap<Xpub, (Fingerprint, DerivationPath)> = Default::default();
134        let mut proprietaries: BTreeMap<raw::ProprietaryKey, Vec<u8>> = Default::default();
135        let mut unknowns: BTreeMap<raw::Key, Vec<u8>> = Default::default();
136
137        // Use a closure so we can insert pair into one of the mutable local variables above.
138        let mut insert_pair = |pair: raw::Pair| {
139            match pair.key.type_value {
140                PSBT_GLOBAL_VERSION =>
141                    if pair.key.key.is_empty() {
142                        if version.is_none() {
143                            let vlen: usize = pair.value.len();
144                            let mut decoder = Cursor::new(pair.value);
145                            if vlen != 4 {
146                                return Err::<(), InsertPairError>(
147                                    InsertPairError::ValueWrongLength(vlen, 4),
148                                );
149                            }
150                            let ver = Decodable::consensus_decode(&mut decoder)?;
151                            if ver != 2 {
152                                return Err(InsertPairError::WrongVersion(ver));
153                            }
154                            version = Some(Version::try_from(ver).expect("valid, this is 2"));
155                        } else {
156                            return Err(InsertPairError::DuplicateKey(pair.key));
157                        }
158                    } else {
159                        return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
160                    },
161                PSBT_GLOBAL_TX_VERSION =>
162                    if pair.key.key.is_empty() {
163                        if tx_version.is_none() {
164                            let vlen: usize = pair.value.len();
165                            let mut decoder = Cursor::new(pair.value);
166                            if vlen != 4 {
167                                return Err(InsertPairError::ValueWrongLength(vlen, 4));
168                            }
169                            // TODO: Consider doing checks for standard transaction version?
170                            tx_version = Some(Decodable::consensus_decode(&mut decoder)?);
171                        } else {
172                            return Err(InsertPairError::DuplicateKey(pair.key));
173                        }
174                    } else {
175                        return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
176                    },
177                PSBT_GLOBAL_FALLBACK_LOCKTIME =>
178                    if pair.key.key.is_empty() {
179                        if fallback_lock_time.is_none() {
180                            let vlen: usize = pair.value.len();
181                            if vlen != 4 {
182                                return Err(InsertPairError::ValueWrongLength(vlen, 4));
183                            }
184                            let mut decoder = Cursor::new(pair.value);
185                            fallback_lock_time = Some(Decodable::consensus_decode(&mut decoder)?);
186                        } else {
187                            return Err(InsertPairError::DuplicateKey(pair.key));
188                        }
189                    } else {
190                        return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
191                    },
192                PSBT_GLOBAL_INPUT_COUNT =>
193                    if pair.key.key.is_empty() {
194                        if output_count.is_none() {
195                            // TODO: Do we need to check the length for a VarInt?
196                            // let vlen: usize = pair.value.len();
197                            let mut decoder = Cursor::new(pair.value);
198                            let count: VarInt = Decodable::consensus_decode(&mut decoder)?;
199                            input_count = Some(count.0);
200                        } else {
201                            return Err(InsertPairError::DuplicateKey(pair.key));
202                        }
203                    } else {
204                        return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
205                    },
206                PSBT_GLOBAL_OUTPUT_COUNT =>
207                    if pair.key.key.is_empty() {
208                        if output_count.is_none() {
209                            // TODO: Do we need to check the length for a VarInt?
210                            // let vlen: usize = pair.value.len();
211                            let mut decoder = Cursor::new(pair.value);
212                            let count: VarInt = Decodable::consensus_decode(&mut decoder)?;
213                            output_count = Some(count.0);
214                        } else {
215                            return Err(InsertPairError::DuplicateKey(pair.key));
216                        }
217                    } else {
218                        return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
219                    },
220                PSBT_GLOBAL_TX_MODIFIABLE =>
221                    if pair.key.key.is_empty() {
222                        if tx_modifiable_flags.is_none() {
223                            let vlen: usize = pair.value.len();
224                            if vlen != 1 {
225                                return Err(InsertPairError::ValueWrongLength(vlen, 1));
226                            }
227                            let mut decoder = Cursor::new(pair.value);
228                            tx_modifiable_flags = Some(Decodable::consensus_decode(&mut decoder)?);
229                        } else {
230                            return Err(InsertPairError::DuplicateKey(pair.key));
231                        }
232                    } else {
233                        return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
234                    },
235                PSBT_GLOBAL_XPUB =>
236                    if !pair.key.key.is_empty() {
237                        let xpub = Xpub::decode(&pair.key.key)?;
238                        if pair.value.is_empty() {
239                            // TODO: keypair value is empty, consider adding a better error type.
240                            return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
241                        }
242                        if pair.value.len() < 4 {
243                            // TODO: Add better error here.
244                            return Err(InsertPairError::XpubInvalidFingerprint);
245                        }
246                        // TODO: Can we restrict the value further?
247                        if pair.value.len() % 4 != 0 {
248                            return Err(InsertPairError::XpubInvalidPath(pair.value.len()));
249                        }
250
251                        let child_count = pair.value.len() / 4 - 1;
252                        let mut decoder = Cursor::new(pair.value);
253                        let mut fingerprint = [0u8; 4];
254                        decoder
255                            .read_exact(&mut fingerprint[..])
256                            .expect("in-memory readers don't err");
257                        let mut path = Vec::<ChildNumber>::with_capacity(child_count);
258                        while let Ok(index) = u32::consensus_decode(&mut decoder) {
259                            path.push(ChildNumber::from(index))
260                        }
261                        let derivation = DerivationPath::from(path);
262                        // Keys, according to BIP-174, must be unique
263                        if let Some(key_source) =
264                            xpubs.insert(xpub, (Fingerprint::from(fingerprint), derivation))
265                        {
266                            return Err(InsertPairError::DuplicateXpub(key_source));
267                        }
268                    } else {
269                        return Err(InsertPairError::InvalidKeyDataEmpty(pair.key));
270                    },
271                // TODO: Remove clone by implementing TryFrom for reference.
272                PSBT_GLOBAL_PROPRIETARY =>
273                    if !pair.key.key.is_empty() {
274                        match proprietaries.entry(
275                            raw::ProprietaryKey::try_from(pair.key.clone())
276                                .map_err(|_| InsertPairError::InvalidProprietaryKey)?,
277                        ) {
278                            btree_map::Entry::Vacant(empty_key) => {
279                                empty_key.insert(pair.value);
280                            }
281                            btree_map::Entry::Occupied(_) =>
282                                return Err(InsertPairError::DuplicateKey(pair.key)),
283                        }
284                    } else {
285                        return Err(InsertPairError::InvalidKeyDataEmpty(pair.key));
286                    },
287                v if v == PSBT_GLOBAL_UNSIGNED_TX =>
288                    return Err(InsertPairError::ExcludedKey { key_type_value: v }),
289                _ => match unknowns.entry(pair.key) {
290                    btree_map::Entry::Vacant(empty_key) => {
291                        empty_key.insert(pair.value);
292                    }
293                    btree_map::Entry::Occupied(k) => {
294                        return Err(InsertPairError::DuplicateKey(k.key().clone()));
295                    }
296                },
297            }
298            Ok(())
299        };
300
301        loop {
302            match raw::Pair::decode(r) {
303                Ok(pair) => insert_pair(pair)?,
304                Err(serialize::Error::NoMorePairs) => break,
305                Err(e) => return Err(DecodeError::DeserPair(e)),
306            }
307        }
308
309        // TODO: Handle decoding either psbt v0 or psbt v2.
310        let version = version.ok_or(DecodeError::MissingVersion)?;
311
312        // TODO: Do checks for standard transaction version?
313        let tx_version = tx_version.ok_or(DecodeError::MissingTxVersion)?;
314
315        // TODO: Check this default is correct.
316        let tx_modifiable_flags = tx_modifiable_flags.unwrap_or(0_u8);
317
318        let input_count = usize::try_from(input_count.ok_or(DecodeError::MissingInputCount)?)
319            .map_err(|_| DecodeError::InputCountOverflow(input_count.expect("is some")))?;
320
321        let output_count = usize::try_from(output_count.ok_or(DecodeError::MissingOutputCount)?)
322            .map_err(|_| DecodeError::OutputCountOverflow(output_count.expect("is some")))?;
323
324        Ok(Global {
325            tx_version,
326            fallback_lock_time,
327            input_count,
328            output_count,
329            tx_modifiable_flags,
330            version,
331            xpubs,
332            proprietaries,
333            unknowns,
334        })
335    }
336
337    /// Combines [`Global`] with `other`.
338    ///
339    /// In accordance with BIP 174 this function is commutative i.e., `A.combine(B) == B.combine(A)`
340    pub fn combine(&mut self, other: Self) -> Result<(), CombineError> {
341        // Combining different versions of PSBT without explicit conversion is out of scope.
342        if self.version != other.version {
343            return Err(CombineError::VersionMismatch { this: self.version, that: other.version });
344        }
345
346        // No real reason to support this either.
347        if self.tx_version != other.tx_version {
348            return Err(CombineError::TxVersionMismatch {
349                this: self.tx_version,
350                that: other.tx_version,
351            });
352        }
353
354        // BIP 174: The Combiner must remove any duplicate key-value pairs, in accordance with
355        //          the specification. It can pick arbitrarily when conflicts occur.
356
357        // Merging xpubs
358        for (xpub, (fingerprint1, derivation1)) in other.xpubs {
359            match self.xpubs.entry(xpub) {
360                btree_map::Entry::Vacant(entry) => {
361                    entry.insert((fingerprint1, derivation1));
362                }
363                btree_map::Entry::Occupied(mut entry) => {
364                    // Here in case of the conflict we select the version with algorithm:
365                    // 1) if everything is equal we do nothing
366                    // 2) report an error if
367                    //    - derivation paths are equal and fingerprints are not
368                    //    - derivation paths are of the same length, but not equal
369                    //    - derivation paths has different length, but the shorter one
370                    //      is not the strict suffix of the longer one
371                    // 3) choose longest derivation otherwise
372
373                    let (fingerprint2, derivation2) = entry.get().clone();
374
375                    if (derivation1 == derivation2 && fingerprint1 == fingerprint2)
376                        || (derivation1.len() < derivation2.len()
377                            && derivation1[..]
378                                == derivation2[derivation2.len() - derivation1.len()..])
379                    {
380                        continue;
381                    } else if derivation2[..]
382                        == derivation1[derivation1.len() - derivation2.len()..]
383                    {
384                        entry.insert((fingerprint1, derivation1));
385                        continue;
386                    }
387                    return Err(InconsistentKeySourcesError(xpub).into());
388                }
389            }
390        }
391
392        v2_combine_map!(proprietaries, self, other);
393        v2_combine_map!(unknowns, self, other);
394
395        Ok(())
396    }
397}
398
399impl Default for Global {
400    fn default() -> Self { Self::new() }
401}
402
403impl Map for Global {
404    fn get_pairs(&self) -> Vec<raw::Pair> {
405        let mut rv: Vec<raw::Pair> = Default::default();
406
407        rv.push(raw::Pair {
408            key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key: vec![] },
409            value: self.version.serialize(),
410        });
411
412        rv.push(raw::Pair {
413            key: raw::Key { type_value: PSBT_GLOBAL_TX_VERSION, key: vec![] },
414            value: self.tx_version.serialize(),
415        });
416
417        v2_impl_psbt_get_pair! {
418            rv.push(self.fallback_lock_time, PSBT_GLOBAL_FALLBACK_LOCKTIME)
419        }
420
421        rv.push(raw::Pair {
422            key: raw::Key { type_value: PSBT_GLOBAL_INPUT_COUNT, key: vec![] },
423            value: VarInt::from(self.input_count).serialize(),
424        });
425
426        rv.push(raw::Pair {
427            key: raw::Key { type_value: PSBT_GLOBAL_OUTPUT_COUNT, key: vec![] },
428            value: VarInt::from(self.output_count).serialize(),
429        });
430
431        rv.push(raw::Pair {
432            key: raw::Key { type_value: PSBT_GLOBAL_TX_MODIFIABLE, key: vec![] },
433            value: vec![self.tx_modifiable_flags],
434        });
435
436        for (xpub, (fingerprint, derivation)) in &self.xpubs {
437            rv.push(raw::Pair {
438                key: raw::Key { type_value: PSBT_GLOBAL_XPUB, key: xpub.encode().to_vec() },
439                value: {
440                    let mut ret = Vec::with_capacity(4 + derivation.len() * 4);
441                    ret.extend(fingerprint.as_bytes());
442                    derivation.into_iter().for_each(|n| ret.extend(&u32::from(*n).to_le_bytes()));
443                    ret
444                },
445            });
446        }
447
448        for (key, value) in self.proprietaries.iter() {
449            rv.push(raw::Pair { key: key.to_key(), value: value.clone() });
450        }
451
452        for (key, value) in self.unknowns.iter() {
453            rv.push(raw::Pair { key: key.clone(), value: value.clone() });
454        }
455
456        rv
457    }
458}
459
460/// An error while decoding.
461#[derive(Debug)]
462#[non_exhaustive]
463pub enum DecodeError {
464    /// Error inserting a key-value pair.
465    InsertPair(InsertPairError),
466    /// Error deserializing a pair.
467    DeserPair(serialize::Error),
468    /// Serialized PSBT is missing the version number.
469    MissingVersion,
470    /// Serialized PSBT is missing the transaction version number.
471    MissingTxVersion,
472    /// Serialized PSBT is missing the input count.
473    MissingInputCount,
474    /// Input count overflows word size for current architecture.
475    InputCountOverflow(u64),
476    /// Serialized PSBT is missing the output count.
477    MissingOutputCount,
478    /// Output count overflows word size for current architecture.
479    OutputCountOverflow(u64),
480}
481
482impl fmt::Display for DecodeError {
483    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
484        use DecodeError::*;
485
486        match *self {
487            InsertPair(ref e) => write_err!(f, "error inserting a pair"; e),
488            DeserPair(ref e) => write_err!(f, "error deserializing a pair"; e),
489            MissingVersion => write!(f, "serialized PSBT is missing the version number"),
490            MissingTxVersion =>
491                write!(f, "serialized PSBT is missing the transaction version number"),
492            MissingInputCount => write!(f, "serialized PSBT is missing the input count"),
493            InputCountOverflow(count) =>
494                write!(f, "input count overflows word size for current architecture: {}", count),
495            MissingOutputCount => write!(f, "serialized PSBT is missing the output count"),
496            OutputCountOverflow(count) =>
497                write!(f, "output count overflows word size for current architecture: {}", count),
498        }
499    }
500}
501
502#[cfg(feature = "std")]
503impl std::error::Error for DecodeError {
504    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
505        use DecodeError::*;
506
507        match *self {
508            InsertPair(ref e) => Some(e),
509            DeserPair(ref e) => Some(e),
510            MissingVersion
511            | MissingTxVersion
512            | MissingInputCount
513            | InputCountOverflow(_)
514            | MissingOutputCount
515            | OutputCountOverflow(_) => None,
516        }
517    }
518}
519
520impl From<InsertPairError> for DecodeError {
521    fn from(e: InsertPairError) -> Self { Self::InsertPair(e) }
522}
523
524/// Error inserting a key-value pair.
525#[derive(Debug)]
526pub enum InsertPairError {
527    /// Keys within key-value map should never be duplicated.
528    DuplicateKey(raw::Key),
529    /// Key should contain data.
530    InvalidKeyDataEmpty(raw::Key),
531    /// Key should not contain data.
532    InvalidKeyDataNotEmpty(raw::Key),
533    /// Error deserializing raw value.
534    Deser(serialize::Error),
535    /// Error consensus deserializing value.
536    Consensus(consensus::Error),
537    /// Value was not the correct length (got, want).
538    // TODO: Use struct instead of tuple.
539    ValueWrongLength(usize, usize),
540    /// PSBT_GLOBAL_VERSION: PSBT v2 expects the version to be 2.
541    WrongVersion(u32),
542    /// PSBT_GLOBAL_XPUB: Must contain 4 bytes for the xpub fingerprint.
543    XpubInvalidFingerprint,
544    /// PSBT_GLOBAL_XPUB: derivation path must be a list of 32 byte varints.
545    XpubInvalidPath(usize),
546    /// PSBT_GLOBAL_XPUB: Failed to decode a BIP-32 type.
547    Bip32(bip32::Error),
548    /// PSBT_GLOBAL_XPUB: xpubs must be unique.
549    DuplicateXpub(KeySource),
550    /// PSBT_GLOBAL_PROPRIETARY: Invalid proprietary key.
551    InvalidProprietaryKey,
552    /// Key must be excluded from this version of PSBT (see consts.rs for u8 values).
553    ExcludedKey {
554        /// Key type value we found.
555        key_type_value: u8,
556    },
557}
558
559impl fmt::Display for InsertPairError {
560    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
561        use InsertPairError::*;
562
563        match *self {
564            DuplicateKey(ref key) => write!(f, "duplicate key: {}", key),
565            InvalidKeyDataEmpty(ref key) => write!(f, "key should contain data: {}", key),
566            InvalidKeyDataNotEmpty(ref key) => write!(f, "key should not contain data: {}", key),
567            Deser(ref e) => write_err!(f, "error deserializing raw value"; e),
568            Consensus(ref e) => write_err!(f, "error consensus deserializing type"; e),
569            ValueWrongLength(got, want) =>
570                write!(f, "value (keyvalue pair) wrong length (got, want) {} {}", got, want),
571            WrongVersion(v) =>
572                write!(f, "PSBT_GLOBAL_VERSION: PSBT v2 expects the version to be 2, found: {}", v),
573            XpubInvalidFingerprint =>
574                write!(f, "PSBT_GLOBAL_XPUB: derivation path must be a list of 32 byte varints"),
575            XpubInvalidPath(len) => write!(
576                f,
577                "PSBT_GLOBAL_XPUB: derivation path must be a list of 32 byte varints: {}",
578                len
579            ),
580            Bip32(ref e) => write_err!(f, "PSBT_GLOBAL_XPUB: Failed to decode a BIP-32 type"; e),
581            DuplicateXpub((fingerprint, ref derivation_path)) => write!(
582                f,
583                "PSBT_GLOBAL_XPUB: xpubs must be unique ({}, {})",
584                fingerprint, derivation_path
585            ),
586            InvalidProprietaryKey => write!(f, "PSBT_GLOBAL_PROPRIETARY: Invalid proprietary key"),
587            ExcludedKey { key_type_value } => write!(
588                f,
589                "found a keypair type that is explicitly excluded: {}",
590                consts::psbt_global_key_type_value_to_str(key_type_value)
591            ),
592        }
593    }
594}
595
596#[cfg(feature = "std")]
597impl std::error::Error for InsertPairError {
598    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
599        use InsertPairError::*;
600
601        match *self {
602            Deser(ref e) => Some(e),
603            Consensus(ref e) => Some(e),
604            Bip32(ref e) => Some(e),
605            DuplicateKey(_)
606            | InvalidKeyDataEmpty(_)
607            | InvalidKeyDataNotEmpty(_)
608            | ValueWrongLength(..)
609            | WrongVersion(_)
610            | XpubInvalidFingerprint
611            | XpubInvalidPath(_)
612            | DuplicateXpub(_)
613            | InvalidProprietaryKey
614            | ExcludedKey { .. } => None,
615        }
616    }
617}
618
619impl From<serialize::Error> for InsertPairError {
620    fn from(e: serialize::Error) -> Self { Self::Deser(e) }
621}
622
623impl From<consensus::Error> for InsertPairError {
624    fn from(e: consensus::Error) -> Self { Self::Consensus(e) }
625}
626
627impl From<bip32::Error> for InsertPairError {
628    fn from(e: bip32::Error) -> Self { Self::Bip32(e) }
629}
630
631/// Error combining two global maps.
632#[derive(Debug, Clone, PartialEq, Eq)]
633#[non_exhaustive]
634pub enum CombineError {
635    /// The version numbers are not the same.
636    VersionMismatch {
637        /// Attempted to combine a PBST with `this` version.
638        this: Version,
639        /// Into a PBST with `that` version.
640        that: Version,
641    },
642    /// The transaction version numbers are not the same.
643    TxVersionMismatch {
644        /// Attempted to combine a PBST with `this` tx version.
645        this: transaction::Version,
646        /// Into a PBST with `that` tx version.
647        that: transaction::Version,
648    },
649    /// Xpubs have inconsistent key sources.
650    InconsistentKeySources(InconsistentKeySourcesError),
651}
652
653impl fmt::Display for CombineError {
654    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
655        use CombineError::*;
656
657        match *self {
658            VersionMismatch { ref this, ref that } =>
659                write!(f, "combine two PSBTs with different versions: {:?} {:?}", this, that),
660            TxVersionMismatch { ref this, ref that } =>
661                write!(f, "combine two PSBTs with different tx versions: {:?} {:?}", this, that),
662            InconsistentKeySources(ref e) =>
663                write_err!(f, "combine with inconsistent key sources"; e),
664        }
665    }
666}
667
668#[cfg(feature = "std")]
669impl std::error::Error for CombineError {
670    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
671        use CombineError::*;
672
673        match *self {
674            InconsistentKeySources(ref e) => Some(e),
675            VersionMismatch { .. } | TxVersionMismatch { .. } => None,
676        }
677    }
678}
679
680impl From<InconsistentKeySourcesError> for CombineError {
681    fn from(e: InconsistentKeySourcesError) -> Self { Self::InconsistentKeySources(e) }
682}