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;
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
24const INPUTS_MODIFIABLE: u8 = 0x01 << 0;
26const OUTPUTS_MODIFIABLE: u8 = 0x01 << 1;
28const SIGHASH_SINGLE: u8 = 0x01 << 2;
32
33#[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 pub version: Version,
40
41 pub tx_version: transaction::Version,
43
44 pub fallback_lock_time: Option<absolute::LockTime>,
46
47 pub tx_modifiable_flags: u8,
49
50 pub input_count: usize, pub output_count: usize, pub xpubs: BTreeMap<Xpub, KeySource>,
58
59 #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))]
61 pub proprietaries: BTreeMap<raw::ProprietaryKey, Vec<u8>>,
62
63 #[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 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 #[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 #[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 #[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 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 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 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 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 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 return Err(InsertPairError::InvalidKeyDataNotEmpty(pair.key));
241 }
242 if pair.value.len() < 4 {
243 return Err(InsertPairError::XpubInvalidFingerprint);
245 }
246 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 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 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 let version = version.ok_or(DecodeError::MissingVersion)?;
311
312 let tx_version = tx_version.ok_or(DecodeError::MissingTxVersion)?;
314
315 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 pub fn combine(&mut self, other: Self) -> Result<(), CombineError> {
341 if self.version != other.version {
343 return Err(CombineError::VersionMismatch { this: self.version, that: other.version });
344 }
345
346 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 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 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#[derive(Debug)]
462#[non_exhaustive]
463pub enum DecodeError {
464 InsertPair(InsertPairError),
466 DeserPair(serialize::Error),
468 MissingVersion,
470 MissingTxVersion,
472 MissingInputCount,
474 InputCountOverflow(u64),
476 MissingOutputCount,
478 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#[derive(Debug)]
526pub enum InsertPairError {
527 DuplicateKey(raw::Key),
529 InvalidKeyDataEmpty(raw::Key),
531 InvalidKeyDataNotEmpty(raw::Key),
533 Deser(serialize::Error),
535 Consensus(consensus::Error),
537 ValueWrongLength(usize, usize),
540 WrongVersion(u32),
542 XpubInvalidFingerprint,
544 XpubInvalidPath(usize),
546 Bip32(bip32::Error),
548 DuplicateXpub(KeySource),
550 InvalidProprietaryKey,
552 ExcludedKey {
554 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#[derive(Debug, Clone, PartialEq, Eq)]
633#[non_exhaustive]
634pub enum CombineError {
635 VersionMismatch {
637 this: Version,
639 that: Version,
641 },
642 TxVersionMismatch {
644 this: transaction::Version,
646 that: transaction::Version,
648 },
649 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}