Skip to main content

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