1use 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
30const INPUTS_MODIFIABLE: u8 = 0x01 << 0;
32const OUTPUTS_MODIFIABLE: u8 = 0x01 << 1;
34const SIGHASH_SINGLE: u8 = 0x01 << 2;
38
39#[derive(Debug, Clone, PartialEq, Eq, Hash)]
41#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42pub struct Global {
43 pub version: Version,
45
46 pub tx_version: transaction::Version,
48
49 pub fallback_lock_time: Option<absolute::LockTime>,
51
52 pub tx_modifiable_flags: u8,
54
55 pub input_count: usize, pub output_count: usize, pub xpubs: BTreeMap<Xpub, KeySource>,
63
64 #[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 #[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 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
76 pub proprietaries: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
77
78 #[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 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 #[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 #[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 #[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 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 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 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 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 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 return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
268 }
269 if pair.value.len() < 4 {
270 return Err(InsertPairError::XpubInvalidFingerprint);
272 }
273 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 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 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 let version = version.ok_or(DecodeError::MissingVersion)?;
352
353 let tx_version = tx_version.ok_or(DecodeError::MissingTxVersion)?;
355
356 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 pub fn combine(&mut self, other: Self) -> Result<(), CombineError> {
395 if self.version != other.version {
397 return Err(CombineError::VersionMismatch { this: self.version, that: other.version });
398 }
399
400 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 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 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#[derive(Debug)]
542#[non_exhaustive]
543pub enum DecodeError {
544 InsertPair(InsertPairError),
546 DeserPair(serialize::Error),
548 MissingVersion,
550 MissingTxVersion,
552 MissingInputCount,
554 InputCountOverflow(u64),
556 MissingOutputCount,
558 OutputCountOverflow(u64),
560 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#[derive(Debug)]
615pub enum InsertPairError {
616 DuplicateKey(raw::Key),
618 InvalidKeyDataEmpty(raw::Key),
620 InvalidKeyDataNotEmpty(raw::Key),
622 Deser(serialize::Error),
624 Consensus(consensus::Error),
626 ValueWrongLength(usize, usize),
629 WrongVersion(u32),
631 XpubInvalidFingerprint,
633 XpubInvalidPath(usize),
635 Bip32(bip32::Error),
637 DuplicateXpub(KeySource),
639 InvalidProprietaryKey,
641 ExcludedKey {
643 key_type_value: u8,
645 },
646 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#[derive(Debug, Clone, PartialEq, Eq)]
731#[non_exhaustive]
732pub enum CombineError {
733 VersionMismatch {
735 this: Version,
737 that: Version,
739 },
740 TxVersionMismatch {
742 this: transaction::Version,
744 that: transaction::Version,
746 },
747 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}