diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index f6511f02..75a17222 100644 --- a/bitcoin/src/psbt/error.rs +++ b/bitcoin/src/psbt/error.rs @@ -1,18 +1,15 @@ // SPDX-License-Identifier: CC0-1.0 -use crate::prelude::*; - use core::fmt; use bitcoin_internals::write_err; +use crate::bip32::ExtendedPubKey; use crate::blockdata::transaction::Transaction; use crate::consensus::encode; +use crate::prelude::*; use crate::psbt::raw; - -use crate::hashes; -use crate::io; -use crate::bip32::ExtendedPubKey; +use crate::{hashes, io}; /// Enum for marking psbt hash error. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -113,29 +110,41 @@ impl fmt::Display for Error { Error::InvalidMagic => f.write_str("invalid magic"), Error::MissingUtxo => f.write_str("UTXO information is not present in PSBT"), Error::InvalidSeparator => f.write_str("invalid separator"), - Error::PsbtUtxoOutOfbounds => f.write_str("output index is out of bounds of non witness script output array"), + Error::PsbtUtxoOutOfbounds => + f.write_str("output index is out of bounds of non witness script output array"), Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), - Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"), + Error::InvalidProprietaryKey => + write!(f, "non-proprietary key type found when proprietary key was expected"), Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), - Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), - Error::UnsignedTxHasScriptWitnesses => f.write_str("the unsigned transaction has script witnesses"), - Error::MustHaveUnsignedTx => { - f.write_str("partially signed transactions must have an unsigned transaction") - } + Error::UnsignedTxHasScriptSigs => + f.write_str("the unsigned transaction has script sigs"), + Error::UnsignedTxHasScriptWitnesses => + f.write_str("the unsigned transaction has script witnesses"), + Error::MustHaveUnsignedTx => + f.write_str("partially signed transactions must have an unsigned transaction"), Error::NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), - Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()), - Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), + Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!( + f, + "different unsigned transaction: expected {}, actual {}", + e.txid(), + a.txid() + ), + Error::NonStandardSighashType(ref sht) => + write!(f, "non-standard sighash type: {}", sht), Error::HashParse(ref e) => write_err!(f, "hash parse error"; e), - Error::InvalidPreimageHashPair{ref preimage, ref hash, ref hash_type} => { + Error::InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => { // directly using debug forms of psbthash enums - write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash ) - }, - Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) }, + write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash) + } + Error::CombineInconsistentKeySources(ref s) => { + write!(f, "combine conflict: {}", s) + } Error::ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e), Error::NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"), Error::FeeOverflow => f.write_str("integer overflow in fee calculation"), Error::InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e), - Error::InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e), + Error::InvalidSecp256k1PublicKey(ref e) => + write_err!(f, "invalid secp256k1 public key"; e), Error::InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"), Error::InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e), Error::InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e), @@ -145,7 +154,8 @@ impl fmt::Display for Error { Error::TapTree(ref e) => write_err!(f, "taproot tree error"; e), Error::XPubKey(s) => write!(f, "xpub key error - {}", s), Error::Version(s) => write!(f, "version error {}", s), - Error::PartialDataConsumption => f.write_str("data not consumed entirely when explicitly deserializing"), + Error::PartialDataConsumption => + f.write_str("data not consumed entirely when explicitly deserializing"), Error::Io(ref e) => write_err!(f, "I/O error"; e), } } @@ -161,7 +171,7 @@ impl std::error::Error for Error { HashParse(e) => Some(e), ConsensusEncoding(e) => Some(e), Io(e) => Some(e), - | InvalidMagic + InvalidMagic | MissingUtxo | InvalidSeparator | PsbtUtxoOutOfbounds @@ -174,7 +184,7 @@ impl std::error::Error for Error { | NoMorePairs | UnexpectedUnsignedTx { .. } | NonStandardSighashType(_) - | InvalidPreimageHashPair{ .. } + | InvalidPreimageHashPair { .. } | CombineInconsistentKeySources(_) | NegativeFee | FeeOverflow @@ -189,26 +199,20 @@ impl std::error::Error for Error { | TapTree(_) | XPubKey(_) | Version(_) - | PartialDataConsumption=> None, + | PartialDataConsumption => None, } } } #[doc(hidden)] impl From for Error { - fn from(e: hashes::Error) -> Error { - Error::HashParse(e) - } + fn from(e: hashes::Error) -> Error { Error::HashParse(e) } } impl From for Error { - fn from(e: encode::Error) -> Self { - Error::ConsensusEncoding(e) - } + fn from(e: encode::Error) -> Self { Error::ConsensusEncoding(e) } } impl From for Error { - fn from(e: io::Error) -> Self { - Error::Io(e) - } + fn from(e: io::Error) -> Self { Error::Io(e) } } diff --git a/bitcoin/src/psbt/macros.rs b/bitcoin/src/psbt/macros.rs index 77da1679..187d0eef 100644 --- a/bitcoin/src/psbt/macros.rs +++ b/bitcoin/src/psbt/macros.rs @@ -2,7 +2,11 @@ #[allow(unused_macros)] macro_rules! hex_psbt { - ($s:expr) => { <$crate::psbt::PartiallySignedTransaction>::deserialize(&<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) }; + ($s:expr) => { + <$crate::psbt::PartiallySignedTransaction>::deserialize( + &<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap(), + ) + }; } macro_rules! combine { @@ -33,9 +37,7 @@ macro_rules! impl_psbt_deserialize { macro_rules! impl_psbt_serialize { ($thing:ty) => { impl $crate::psbt::serialize::Serialize for $thing { - fn serialize(&self) -> $crate::prelude::Vec { - $crate::consensus::serialize(self) - } + fn serialize(&self) -> $crate::prelude::Vec { $crate::consensus::serialize(self) } } }; } @@ -43,9 +45,7 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_serialize { ($thing:ty) => { impl $crate::psbt::serialize::Serialize for $thing { - fn serialize(&self) -> Vec { - self.serialize_map() - } + fn serialize(&self) -> Vec { self.serialize_map() } } }; } @@ -157,9 +157,7 @@ macro_rules! impl_psbt_hash_deserialize { ($hash_type:ty) => { impl $crate::psbt::serialize::Deserialize for $hash_type { fn deserialize(bytes: &[u8]) -> Result { - <$hash_type>::from_slice(&bytes[..]).map_err(|e| { - $crate::psbt::Error::from(e) - }) + <$hash_type>::from_slice(&bytes[..]).map_err(|e| $crate::psbt::Error::from(e)) } } }; @@ -168,9 +166,7 @@ macro_rules! impl_psbt_hash_deserialize { macro_rules! impl_psbt_hash_serialize { ($hash_type:ty) => { impl $crate::psbt::serialize::Serialize for $hash_type { - fn serialize(&self) -> $crate::prelude::Vec { - self.as_byte_array().to_vec() - } + fn serialize(&self) -> $crate::prelude::Vec { self.as_byte_array().to_vec() } } }; } diff --git a/bitcoin/src/psbt/map/global.rs b/bitcoin/src/psbt/map/global.rs index 908b2a7c..1add4f8d 100644 --- a/bitcoin/src/psbt/map/global.rs +++ b/bitcoin/src/psbt/map/global.rs @@ -2,16 +2,14 @@ use core::convert::TryFrom; -use crate::prelude::*; - -use crate::io::{self, Cursor, Read}; - +use crate::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint}; use crate::blockdata::transaction::Transaction; use crate::consensus::encode::MAX_VEC_SIZE; use crate::consensus::{encode, Decodable}; +use crate::io::{self, Cursor, Read}; +use crate::prelude::*; use crate::psbt::map::Map; use crate::psbt::{raw, Error, PartiallySignedTransaction}; -use crate::bip32::{ExtendedPubKey, Fingerprint, DerivationPath, ChildNumber}; /// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00 const PSBT_GLOBAL_UNSIGNED_TX: u8 = 0x00; @@ -27,10 +25,7 @@ impl Map for PartiallySignedTransaction { let mut rv: Vec = Default::default(); rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_UNSIGNED_TX, - key: vec![], - }, + key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key: vec![] }, value: { // Manually serialized to ensure 0-input txs are serialized // without witnesses. @@ -45,42 +40,30 @@ impl Map for PartiallySignedTransaction { for (xpub, (fingerprint, derivation)) in &self.xpub { rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_XPUB, - key: xpub.encode().to_vec(), - }, + key: raw::Key { type_value: PSBT_GLOBAL_XPUB, key: xpub.encode().to_vec() }, value: { let mut ret = Vec::with_capacity(4 + derivation.len() * 4); ret.extend(fingerprint.as_bytes()); derivation.into_iter().for_each(|n| ret.extend(&u32::from(*n).to_le_bytes())); ret - } + }, }); } // Serializing version only for non-default value; otherwise test vectors fail if self.version > 0 { rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_VERSION, - key: vec![], - }, - value: self.version.to_le_bytes().to_vec() + key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key: vec![] }, + value: self.version.to_le_bytes().to_vec(), }); } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } rv @@ -93,7 +76,8 @@ impl PartiallySignedTransaction { let mut tx: Option = None; let mut version: Option = None; let mut unknowns: BTreeMap> = Default::default(); - let mut xpub_map: BTreeMap = Default::default(); + let mut xpub_map: BTreeMap = + Default::default(); let mut proprietary: BTreeMap> = Default::default(); loop { @@ -119,13 +103,13 @@ impl PartiallySignedTransaction { }); if decoder.position() != vlen as u64 { - return Err(Error::PartialDataConsumption) + return Err(Error::PartialDataConsumption); } } else { - return Err(Error::DuplicateKey(pair.key)) + return Err(Error::DuplicateKey(pair.key)); } } else { - return Err(Error::InvalidKey(pair.key)) + return Err(Error::InvalidKey(pair.key)); } } PSBT_GLOBAL_XPUB => { @@ -136,24 +120,33 @@ impl PartiallySignedTransaction { ))?; if pair.value.is_empty() || pair.value.len() % 4 != 0 { - return Err(Error::XPubKey("Incorrect length of global xpub derivation data")) + return Err(Error::XPubKey( + "Incorrect length of global xpub derivation data", + )); } let child_count = pair.value.len() / 4 - 1; let mut decoder = Cursor::new(pair.value); let mut fingerprint = [0u8; 4]; - decoder.read_exact(&mut fingerprint[..]).map_err(|_| Error::XPubKey("Can't read global xpub fingerprint"))?; + decoder.read_exact(&mut fingerprint[..]).map_err(|_| { + Error::XPubKey("Can't read global xpub fingerprint") + })?; let mut path = Vec::::with_capacity(child_count); while let Ok(index) = u32::consensus_decode(&mut decoder) { path.push(ChildNumber::from(index)) } let derivation = DerivationPath::from(path); // Keys, according to BIP-174, must be unique - if xpub_map.insert(xpub, (Fingerprint::from(fingerprint), derivation)).is_some() { - return Err(Error::XPubKey("Repeated global xpub key")) + if xpub_map + .insert(xpub, (Fingerprint::from(fingerprint), derivation)) + .is_some() + { + return Err(Error::XPubKey("Repeated global xpub key")); } } else { - return Err(Error::XPubKey("Xpub global key must contain serialized Xpub data")) + return Err(Error::XPubKey( + "Xpub global key must contain serialized Xpub data", + )); } } PSBT_GLOBAL_VERSION => { @@ -164,33 +157,41 @@ impl PartiallySignedTransaction { let vlen: usize = pair.value.len(); let mut decoder = Cursor::new(pair.value); if vlen != 4 { - return Err(Error::Version("invalid global version value length (must be 4 bytes)")) + return Err(Error::Version( + "invalid global version value length (must be 4 bytes)", + )); } version = Some(Decodable::consensus_decode(&mut decoder)?); // We only understand version 0 PSBTs. According to BIP-174 we // should throw an error if we see anything other than version 0. if version != Some(0) { - return Err(Error::Version("PSBT versions greater than 0 are not supported")) + return Err(Error::Version( + "PSBT versions greater than 0 are not supported", + )); } } else { - return Err(Error::DuplicateKey(pair.key)) + return Err(Error::DuplicateKey(pair.key)); } } else { - return Err(Error::InvalidKey(pair.key)) + return Err(Error::InvalidKey(pair.key)); } } - PSBT_GLOBAL_PROPRIETARY => match proprietary.entry(raw::ProprietaryKey::try_from(pair.key.clone())?) { + PSBT_GLOBAL_PROPRIETARY => match proprietary + .entry(raw::ProprietaryKey::try_from(pair.key.clone())?) + { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(pair.value); - }, - btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(pair.key)), - } + } + btree_map::Entry::Occupied(_) => + return Err(Error::DuplicateKey(pair.key)), + }, _ => match unknowns.entry(pair.key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(pair.value); - }, - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), - } + } + btree_map::Entry::Occupied(k) => + return Err(Error::DuplicateKey(k.key().clone())), + }, } } Err(crate::psbt::Error::NoMorePairs) => break, @@ -206,7 +207,7 @@ impl PartiallySignedTransaction { proprietary, unknown: unknowns, inputs: vec![], - outputs: vec![] + outputs: vec![], }) } else { Err(Error::MustHaveUnsignedTx) diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs index 20882b07..723ce407 100644 --- a/bitcoin/src/psbt/map/input.rs +++ b/bitcoin/src/psbt/map/input.rs @@ -1,24 +1,25 @@ // SPDX-License-Identifier: CC0-1.0 -use crate::prelude::*; - +use core::convert::TryFrom; use core::fmt; use core::str::FromStr; -use core::convert::TryFrom; use secp256k1::XOnlyPublicKey; -use crate::blockdata::script::ScriptBuf; -use crate::blockdata::witness::Witness; -use crate::blockdata::transaction::{Transaction, TxOut}; -use crate::crypto::{ecdsa, taproot}; -use crate::crypto::key::PublicKey; -use crate::hashes::{self, hash160, ripemd160, sha256, sha256d}; use crate::bip32::KeySource; +use crate::blockdata::script::ScriptBuf; +use crate::blockdata::transaction::{Transaction, TxOut}; +use crate::blockdata::witness::Witness; +use crate::crypto::key::PublicKey; +use crate::crypto::{ecdsa, taproot}; +use crate::hashes::{self, hash160, ripemd160, sha256, sha256d}; +use crate::prelude::*; use crate::psbt::map::Map; use crate::psbt::serialize::Deserialize; use crate::psbt::{self, error, raw, Error}; -use crate::sighash::{self, NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, TapSighashType}; +use crate::sighash::{ + self, EcdsaSighashType, NonStandardSighashType, SighashTypeParseError, TapSighashType, +}; use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash}; /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 @@ -132,7 +133,6 @@ pub struct Input { pub unknown: BTreeMap>, } - /// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash /// type can be either [`EcdsaSighashType`] or [`TapSighashType`] but it is not possible to know /// directly which signature hash type the user is dealing with. Therefore, the user is responsible @@ -141,7 +141,7 @@ pub struct Input { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct PsbtSighashType { - pub (in crate::psbt) inner: u32, + pub(in crate::psbt) inner: u32, } impl fmt::Display for PsbtSighashType { @@ -172,7 +172,7 @@ impl FromStr for PsbtSighashType { return Ok(PsbtSighashType { inner }); } - Err(SighashTypeParseError{ unrecognized: s.to_owned() }) + Err(SighashTypeParseError { unrecognized: s.to_owned() }) } } impl From for PsbtSighashType { @@ -208,17 +208,12 @@ impl PsbtSighashType { /// /// Allows construction of a non-standard or non-valid sighash flag /// ([`EcdsaSighashType`], [`TapSighashType`] respectively). - pub fn from_u32(n: u32) -> PsbtSighashType { - PsbtSighashType { inner: n } - } - + pub fn from_u32(n: u32) -> PsbtSighashType { PsbtSighashType { inner: n } } /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag. /// /// No guarantees are made as to the standardness or validity of the returned value. - pub fn to_u32(self) -> u32 { - self.inner - } + pub fn to_u32(self) -> u32 { self.inner } } impl Input { @@ -247,10 +242,7 @@ impl Input { } pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { - let raw::Pair { - key: raw_key, - value: raw_value, - } = pair; + let raw::Pair { key: raw_key, value: raw_value } = pair; match raw_key.type_value { PSBT_IN_NON_WITNESS_UTXO => { @@ -299,16 +291,36 @@ impl Input { } } PSBT_IN_RIPEMD160 => { - psbt_insert_hash_pair(&mut self.ripemd160_preimages, raw_key, raw_value, error::PsbtHash::Ripemd)?; + psbt_insert_hash_pair( + &mut self.ripemd160_preimages, + raw_key, + raw_value, + error::PsbtHash::Ripemd, + )?; } PSBT_IN_SHA256 => { - psbt_insert_hash_pair(&mut self.sha256_preimages, raw_key, raw_value, error::PsbtHash::Sha256)?; + psbt_insert_hash_pair( + &mut self.sha256_preimages, + raw_key, + raw_value, + error::PsbtHash::Sha256, + )?; } PSBT_IN_HASH160 => { - psbt_insert_hash_pair(&mut self.hash160_preimages, raw_key, raw_value, error::PsbtHash::Hash160)?; + psbt_insert_hash_pair( + &mut self.hash160_preimages, + raw_key, + raw_value, + error::PsbtHash::Hash160, + )?; } PSBT_IN_HASH256 => { - psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?; + psbt_insert_hash_pair( + &mut self.hash256_preimages, + raw_key, + raw_value, + error::PsbtHash::Hash256, + )?; } PSBT_IN_TAP_KEY_SIG => { impl_psbt_insert_pair! { @@ -345,7 +357,7 @@ impl Input { match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); - }, + } btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)), } } @@ -471,17 +483,11 @@ impl Map for Input { rv.push(self.tap_merkle_root, PSBT_IN_TAP_MERKLE_ROOT) } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } rv diff --git a/bitcoin/src/psbt/map/mod.rs b/bitcoin/src/psbt/map/mod.rs index 4a2a3d94..91d455e0 100644 --- a/bitcoin/src/psbt/map/mod.rs +++ b/bitcoin/src/psbt/map/mod.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 use crate::prelude::*; - use crate::psbt::raw; mod global; @@ -10,7 +9,6 @@ mod output; pub use self::input::{Input, PsbtSighashType}; pub use self::output::Output; - use super::serialize::Serialize; /// A trait that describes a PSBT key-value map. diff --git a/bitcoin/src/psbt/map/output.rs b/bitcoin/src/psbt/map/output.rs index 4621bc79..4f032019 100644 --- a/bitcoin/src/psbt/map/output.rs +++ b/bitcoin/src/psbt/map/output.rs @@ -1,18 +1,16 @@ // SPDX-License-Identifier: CC0-1.0 -use crate::prelude::*; -use core; use core::convert::TryFrom; -use crate::blockdata::script::ScriptBuf; use secp256k1::XOnlyPublicKey; -use crate::bip32::KeySource; -use secp256k1; -use crate::psbt::map::Map; -use crate::psbt::raw; -use crate::psbt::Error; +use {core, secp256k1}; -use crate::taproot::{TapTree, TapLeafHash}; +use crate::bip32::KeySource; +use crate::blockdata::script::ScriptBuf; +use crate::prelude::*; +use crate::psbt::map::Map; +use crate::psbt::{raw, Error}; +use crate::taproot::{TapLeafHash, TapTree}; /// Type: Redeem ScriptBuf PSBT_OUT_REDEEM_SCRIPT = 0x00 const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00; @@ -51,25 +49,16 @@ pub struct Output { #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] pub tap_key_origins: BTreeMap, KeySource)>, /// Proprietary key-value pairs for this output. - #[cfg_attr( - feature = "serde", - serde(with = "crate::serde_utils::btreemap_as_seq_byte_values") - )] + #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this output. - #[cfg_attr( - feature = "serde", - serde(with = "crate::serde_utils::btreemap_as_seq_byte_values") - )] + #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] pub unknown: BTreeMap>, } impl Output { pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { - let raw::Pair { - key: raw_key, - value: raw_value, - } = pair; + let raw::Pair { key: raw_key, value: raw_value } = pair; match raw_key.type_value { PSBT_OUT_REDEEM_SCRIPT => { @@ -92,7 +81,7 @@ impl Output { match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); - }, + } btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)), } } @@ -116,7 +105,7 @@ impl Output { empty_key.insert(raw_value); } btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), - } + }, } Ok(()) @@ -165,17 +154,11 @@ impl Map for Output { } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } rv diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index e2bf4f54..ee5a0c7d 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -7,24 +7,22 @@ //! except we define PSBTs containing non-standard sighash types as invalid. //! +use core::{cmp, fmt}; #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; -use core::{fmt, cmp}; - -use secp256k1::{Message, Secp256k1, Signing}; use bitcoin_internals::write_err; +use secp256k1::{Message, Secp256k1, Signing}; -use crate::{prelude::*, Amount}; - +use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource}; use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::{Transaction, TxOut}; -use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource}; use crate::crypto::ecdsa; -use crate::crypto::key::{PublicKey, PrivateKey}; -use crate::sighash::{self, EcdsaSighashType, SighashCache}; - +use crate::crypto::key::{PrivateKey, PublicKey}; +use crate::prelude::*; pub use crate::sighash::Prevouts; +use crate::sighash::{self, EcdsaSighashType, SighashCache}; +use crate::Amount; #[macro_use] mod macros; @@ -86,7 +84,7 @@ impl PartiallySignedTransaction { (None, Some(non_witness_utxo)) => { let vout = tx_input.previous_output.vout as usize; non_witness_utxo.output.get(vout).ok_or(Error::PsbtUtxoOutOfbounds) - }, + } (None, None) => Err(Error::MissingUtxo), } }) @@ -161,7 +159,7 @@ impl PartiallySignedTransaction { match self.xpub.entry(xpub) { btree_map::Entry::Vacant(entry) => { entry.insert((fingerprint1, derivation1)); - }, + } btree_map::Entry::Occupied(mut entry) => { // Here in case of the conflict we select the version with algorithm: // 1) if everything is equal we do nothing @@ -174,15 +172,17 @@ impl PartiallySignedTransaction { let (fingerprint2, derivation2) = entry.get().clone(); - if (derivation1 == derivation2 && fingerprint1 == fingerprint2) || - (derivation1.len() < derivation2.len() && derivation1[..] == derivation2[derivation2.len() - derivation1.len()..]) + if (derivation1 == derivation2 && fingerprint1 == fingerprint2) + || (derivation1.len() < derivation2.len() + && derivation1[..] + == derivation2[derivation2.len() - derivation1.len()..]) { - continue - } - else if derivation2[..] == derivation1[derivation1.len() - derivation2.len()..] + continue; + } else if derivation2[..] + == derivation1[derivation1.len() - derivation2.len()..] { entry.insert((fingerprint1, derivation1)); - continue + continue; } return Err(Error::CombineInconsistentKeySources(Box::new(xpub))); } @@ -237,8 +237,12 @@ impl PartiallySignedTransaction { for i in 0..self.inputs.len() { if let Ok(SigningAlgorithm::Ecdsa) = self.signing_algorithm(i) { match self.bip32_sign_ecdsa(k, i, &mut cache, secp) { - Ok(v) => { used.insert(i, v); }, - Err(e) => { errors.insert(i, e); }, + Ok(v) => { + used.insert(i, v); + } + Err(e) => { + errors.insert(i, e); + } } }; } @@ -272,7 +276,7 @@ impl PartiallySignedTransaction { let input = &mut self.inputs[input_index]; // Index checked in call to `sighash_ecdsa`. - let mut used = vec![]; // List of pubkeys used to sign the input. + let mut used = vec![]; // List of pubkeys used to sign the input. for (pk, key_source) in input.bip32_derivation.iter() { let sk = if let Ok(Some(sk)) = k.get_key(KeyRequest::Bip32(key_source.clone()), secp) { @@ -289,10 +293,8 @@ impl PartiallySignedTransaction { Ok((msg, sighash_ty)) => (msg, sighash_ty), }; - let sig = ecdsa::Signature { - sig: secp.sign_ecdsa(&msg, &sk.inner), - hash_ty: sighash_ty, - }; + let sig = + ecdsa::Signature { sig: secp.sign_ecdsa(&msg, &sk.inner), hash_ty: sighash_ty }; let pk = sk.public_key(secp); @@ -323,35 +325,42 @@ impl PartiallySignedTransaction { let utxo = self.spend_utxo(input_index)?; let spk = &utxo.script_pubkey; // scriptPubkey for input spend utxo. - let hash_ty = input.ecdsa_hash_ty() - .map_err(|_| SignError::InvalidSighashType)?; // Only support standard sighash types. + let hash_ty = input.ecdsa_hash_ty().map_err(|_| SignError::InvalidSighashType)?; // Only support standard sighash types. match self.output_type(input_index)? { Bare => { let sighash = cache.legacy_signature_hash(input_index, spk, hash_ty.to_u32())?; Ok((Message::from(sighash), hash_ty)) - }, + } Sh => { - let script_code = input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?; - let sighash = cache.legacy_signature_hash(input_index, script_code, hash_ty.to_u32())?; + let script_code = + input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?; + let sighash = + cache.legacy_signature_hash(input_index, script_code, hash_ty.to_u32())?; Ok((Message::from(sighash), hash_ty)) - }, + } Wpkh => { let script_code = ScriptBuf::p2wpkh_script_code(spk).ok_or(SignError::NotWpkh)?; - let sighash = cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; + let sighash = + cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; Ok((Message::from(sighash), hash_ty)) - }, + } ShWpkh => { - let script_code = ScriptBuf::p2wpkh_script_code(input.redeem_script.as_ref().expect("checked above")) - .ok_or(SignError::NotWpkh)?; - let sighash = cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; + let script_code = ScriptBuf::p2wpkh_script_code( + input.redeem_script.as_ref().expect("checked above"), + ) + .ok_or(SignError::NotWpkh)?; + let sighash = + cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; Ok((Message::from(sighash), hash_ty)) - }, + } Wsh | ShWsh => { - let script_code = input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?; - let sighash = cache.segwit_signature_hash(input_index, script_code, utxo.value, hash_ty)?; + let script_code = + input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?; + let sighash = + cache.segwit_signature_hash(input_index, script_code, utxo.value, hash_ty)?; Ok((Message::from(sighash), hash_ty)) - }, + } Tr => { // This PSBT signing API is WIP, taproot to come shortly. Err(SignError::Unsupported) @@ -368,7 +377,7 @@ impl PartiallySignedTransaction { let vout = self.unsigned_tx.input[input_index].previous_output.vout; &non_witness_utxo.output[vout as usize] } else { - return Err(SignError::MissingSpendUtxo); + return Err(SignError::MissingSpendUtxo); }; Ok(utxo) } @@ -481,13 +490,21 @@ pub trait GetKey { /// - `Some(key)` if the key is found. /// - `None` if the key was not found but no error was encountered. /// - `Err` if an error was encountered while looking for the key. - fn get_key(&self, key_request: KeyRequest, secp: &Secp256k1) -> Result, Self::Error>; + fn get_key( + &self, + key_request: KeyRequest, + secp: &Secp256k1, + ) -> Result, Self::Error>; } impl GetKey for ExtendedPrivKey { type Error = GetKeyError; - fn get_key(&self, key_request: KeyRequest, secp: &Secp256k1) -> Result, Self::Error> { + fn get_key( + &self, + key_request: KeyRequest, + secp: &Secp256k1, + ) -> Result, Self::Error> { match key_request { KeyRequest::Pubkey(_) => Err(GetKeyError::NotSupported), KeyRequest::Bip32((fingerprint, path)) => { @@ -577,7 +594,8 @@ impl fmt::Display for GetKeyError { match *self { Bip32(ref e) => write_err!(f, "a bip23 error"; e), - NotSupported => f.write_str("the GetKey operation is not supported for this key request"), + NotSupported => + f.write_str("the GetKey operation is not supported for this key request"), } } } @@ -596,9 +614,7 @@ impl std::error::Error for GetKeyError { } impl From for GetKeyError { - fn from(e: bip32::Error) -> Self { - GetKeyError::Bip32(e) - } + fn from(e: bip32::Error) -> Self { GetKeyError::Bip32(e) } } /// The various output types supported by the Bitcoin network. @@ -676,7 +692,7 @@ pub enum SignError { /// Attempt to sign an input with the wrong signing algorithm. WrongSigningAlgorithm, /// Signing request currently unsupported. - Unsupported + Unsupported, } impl fmt::Display for SignError { @@ -698,7 +714,8 @@ impl fmt::Display for SignError { SighashComputation(e) => write!(f, "sighash: {}", e), UnknownOutputType => write!(f, "unable to determine the output type"), KeyNotFound => write!(f, "unable to find key"), - WrongSigningAlgorithm => write!(f, "attempt to sign an input with the wrong signing algorithm"), + WrongSigningAlgorithm => + write!(f, "attempt to sign an input with the wrong signing algorithm"), Unsupported => write!(f, "signing request currently unsupported"), } } @@ -712,37 +729,37 @@ impl std::error::Error for SignError { match *self { IndexOutOfBounds(_, _) - | InvalidSighashType - | MissingInputUtxo - | MissingRedeemScript - | MissingSpendUtxo - | MissingWitnessScript - | MismatchedAlgoKey - | NotEcdsa - | NotWpkh - | UnknownOutputType - | KeyNotFound - | WrongSigningAlgorithm - | Unsupported => None, + | InvalidSighashType + | MissingInputUtxo + | MissingRedeemScript + | MissingSpendUtxo + | MissingWitnessScript + | MismatchedAlgoKey + | NotEcdsa + | NotWpkh + | UnknownOutputType + | KeyNotFound + | WrongSigningAlgorithm + | Unsupported => None, SighashComputation(ref e) => Some(e), } } } impl From for SignError { - fn from(e: sighash::Error) -> Self { - SignError::SighashComputation(e) - } + fn from(e: sighash::Error) -> Self { SignError::SighashComputation(e) } } #[cfg(feature = "base64")] mod display_from_str { - use super::{PartiallySignedTransaction, Error}; - use core::fmt::{Display, Formatter, self}; + use core::fmt::{self, Display, Formatter}; use core::str::FromStr; + use base64::display::Base64Display; use bitcoin_internals::write_err; + use super::{Error, PartiallySignedTransaction}; + /// Error encountered during PSBT decoding from Base64 string. #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "base64")))] @@ -751,7 +768,7 @@ mod display_from_str { /// Error in internal PSBT data structure. PsbtEncoding(Error), /// Error in PSBT Base64 encoding. - Base64Encoding(::base64::DecodeError) + Base64Encoding(::base64::DecodeError), } impl Display for PsbtParseError { @@ -801,26 +818,24 @@ pub use self::display_from_str::PsbtParseError; #[cfg(test)] mod tests { - use super::*; + use std::collections::BTreeMap; - use crate::blockdata::locktime::absolute; - use crate::hashes::{sha256, hash160, Hash, ripemd160}; - use crate::psbt::serialize::{Serialize, Deserialize}; - - use secp256k1::{Secp256k1, self}; + use secp256k1::{self, Secp256k1}; #[cfg(feature = "rand-std")] use secp256k1::{All, SecretKey}; - use crate::blockdata::script::ScriptBuf; - use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence}; - use crate::network::constants::Network::Bitcoin; + use super::*; use crate::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource}; - use crate::psbt::map::{Output, Input}; - use crate::psbt::raw; - use crate::internal_macros::hex; - - use std::collections::BTreeMap; + use crate::blockdata::locktime::absolute; + use crate::blockdata::script::ScriptBuf; + use crate::blockdata::transaction::{OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; + use crate::hashes::{hash160, ripemd160, sha256, Hash}; + use crate::internal_macros::hex; + use crate::network::constants::Network::Bitcoin; + use crate::psbt::map::{Input, Output}; + use crate::psbt::raw; + use crate::psbt::serialize::{Deserialize, Serialize}; #[test] fn trivial_psbt() { @@ -843,14 +858,13 @@ mod tests { } #[test] - fn psbt_uncompressed_key() { + fn psbt_uncompressed_key() { + let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); - let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); - - assert!(psbt.inputs[0].partial_sigs.len() == 1); - let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; - assert!(!pk.compressed); - } + assert!(psbt.inputs[0].partial_sigs.len() == 1); + let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; + assert!(!pk.compressed); + } #[test] fn serialize_then_deserialize_output() { @@ -881,8 +895,12 @@ mod tests { hd_keypaths.insert(pk.public_key, (fprint, dpath.into())); let expected: Output = Output { - redeem_script: Some(ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap()), - witness_script: Some(ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap()), + redeem_script: Some( + ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), + ), + witness_script: Some( + ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), + ), bip32_derivation: hd_keypaths, ..Default::default() }; @@ -898,25 +916,31 @@ mod tests { unsigned_tx: Transaction { version: 2, lock_time: absolute::LockTime::from_consensus(1257139), - input: vec![ - TxIn { - previous_output: OutPoint { - txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), - vout: 0, - }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, - witness: Witness::default(), - } - ], + input: vec![TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126" + .parse() + .unwrap(), + vout: 0, + }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + }], output: vec![ TxOut { value: 99999699, - script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), + script_pubkey: ScriptBuf::from_hex( + "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac", + ) + .unwrap(), }, TxOut { value: 100000000, - script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), + script_pubkey: ScriptBuf::from_hex( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(), }, ], }, @@ -935,10 +959,7 @@ mod tests { #[test] fn serialize_then_deserialize_psbtkvpair() { let expected = raw::Pair { - key: raw::Key { - type_value: 0u8, - key: vec![42u8, 69u8], - }, + key: raw::Key { type_value: 0u8, key: vec![42u8, 69u8] }, value: vec![69u8, 42u8, 4u8], }; @@ -965,33 +986,39 @@ mod tests { let tx = Transaction { version: 1, lock_time: absolute::LockTime::ZERO, - input: vec![ - TxIn { - previous_output: OutPoint { - txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), - vout: 1, - }, - script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]), - } - ], - output: vec![ - TxOut { - value: 190303501938, - script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + input: vec![TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389" + .parse() + .unwrap(), + vout: 1, }, - ], + script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985") + .unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[hex!( + "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105" + )]), + }], + output: vec![TxOut { + value: 190303501938, + script_pubkey: ScriptBuf::from_hex( + "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587", + ) + .unwrap(), + }], }; - let unknown: BTreeMap> = vec![( - raw::Key { type_value: 1, key: vec![0, 1] }, - vec![3, 4 ,5], - )].into_iter().collect(); + let unknown: BTreeMap> = + vec![(raw::Key { type_value: 1, key: vec![0, 1] }, vec![3, 4, 5])] + .into_iter() + .collect(); let key_source = ("deadbeef".parse().unwrap(), "m/0'/1".parse().unwrap()); let keypaths: BTreeMap = vec![( "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), key_source.clone(), - )].into_iter().collect(); + )] + .into_iter() + .collect(); let proprietary: BTreeMap> = vec![( raw::ProprietaryKey { @@ -1000,7 +1027,9 @@ mod tests { key: "test_key".as_bytes().to_vec(), }, vec![5, 6, 7], - )].into_iter().collect(); + )] + .into_iter() + .collect(); let psbt = PartiallySignedTransaction { version: 0, @@ -1059,19 +1088,18 @@ mod tests { } mod bip_vectors { - use super::*; - + use std::collections::BTreeMap; #[cfg(feature = "base64")] use std::str::FromStr; - use crate::blockdata::script::ScriptBuf; - use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence}; + use super::*; use crate::blockdata::locktime::absolute; - use crate::psbt::map::{Map, Input, Output}; - use crate::psbt::{raw, PartiallySignedTransaction, Error}; - use crate::sighash::EcdsaSighashType; - use std::collections::BTreeMap; + use crate::blockdata::script::ScriptBuf; + use crate::blockdata::transaction::{OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; + use crate::psbt::map::{Input, Map, Output}; + use crate::psbt::{raw, Error, PartiallySignedTransaction}; + use crate::sighash::EcdsaSighashType; #[test] #[should_panic(expected = "InvalidMagic")] @@ -1242,11 +1270,15 @@ mod tests { assert_eq!(unserialized.serialize_hex(), base16str); assert_eq!(unserialized, hex_psbt!(base16str).unwrap()); - #[cfg(feature = "base64")] { + #[cfg(feature = "base64")] + { let base64str = "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA"; assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), unserialized); assert_eq!(base64str, unserialized.to_string()); - assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), hex_psbt!(base16str).unwrap()); + assert_eq!( + PartiallySignedTransaction::from_str(base64str).unwrap(), + hex_psbt!(base16str).unwrap() + ); } } @@ -1260,7 +1292,8 @@ mod tests { assert!(&psbt.inputs[0].final_script_sig.is_some()); let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); - let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); + let expected_out = + ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); assert!(redeem_script.is_v0_p2wpkh()); assert_eq!( @@ -1286,9 +1319,8 @@ mod tests { assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.txid()); assert!(psbt_non_witness_utxo.output[tx_input.previous_output.vout as usize] - .script_pubkey - .is_p2pkh() - ); + .script_pubkey + .is_p2pkh()); assert_eq!( psbt.inputs[0].sighash_type.as_ref().unwrap().ecdsa_hash_ty().unwrap(), EcdsaSighashType::All @@ -1306,7 +1338,8 @@ mod tests { assert!(&psbt.inputs[1].final_script_sig.is_none()); let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); - let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); + let expected_out = + ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); assert!(redeem_script.is_v0_p2wpkh()); assert_eq!( @@ -1330,7 +1363,8 @@ mod tests { assert!(&psbt.inputs[0].final_script_sig.is_none()); let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap(); - let expected_out = ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap(); + let expected_out = + ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap(); assert!(redeem_script.is_v0_p2wsh()); assert_eq!( @@ -1355,10 +1389,7 @@ mod tests { ); let mut unknown: BTreeMap> = BTreeMap::new(); - let key: raw::Key = raw::Key { - type_value: 0x0fu8, - key: hex!("010203040506070809"), - }; + let key: raw::Key = raw::Key { type_value: 0x0fu8, key: hex!("010203040506070809") }; let value: Vec = hex!("0102030405060708090a0b0c0d0e0f"); unknown.insert(key, value); @@ -1378,7 +1409,10 @@ mod tests { #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid taproot signature"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 66"); + assert_eq!( + err.to_string(), + "invalid taproot signature: invalid taproot signature size: 66" + ); let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err(); assert_eq!(err.to_string(), "invalid xonly public key"); let err = hex_psbt!("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000001052102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa23200").unwrap_err(); @@ -1394,12 +1428,18 @@ mod tests { #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid taproot signature"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 66"); + assert_eq!( + err.to_string(), + "invalid taproot signature: invalid taproot signature size: 66" + ); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err(); #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid taproot signature"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 57"); + assert_eq!( + err.to_string(), + "invalid taproot signature: invalid taproot signature size: 57" + ); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err(); assert_eq!(err.to_string(), "invalid control block"); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926115c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e123202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err(); @@ -1575,11 +1615,10 @@ mod tests { #[test] fn serialize_and_deserialize_proprietary() { let mut psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap(); - psbt.proprietary.insert(raw::ProprietaryKey { - prefix: b"test".to_vec(), - subtype: 0u8, - key: b"test".to_vec(), - }, b"test".to_vec()); + psbt.proprietary.insert( + raw::ProprietaryKey { prefix: b"test".to_vec(), subtype: 0u8, key: b"test".to_vec() }, + b"test".to_vec(), + ); assert!(!psbt.proprietary.is_empty()); let rtt: PartiallySignedTransaction = hex_psbt!(&psbt.serialize_hex()).unwrap(); assert!(!rtt.proprietary.is_empty()); @@ -1725,31 +1764,31 @@ mod tests { let mut t2 = t.clone(); t2.inputs[0].non_witness_utxo = None; match t2.fee().unwrap_err() { - Error::MissingUtxo => {}, - e => panic!("unexpected error: {:?}", e) + Error::MissingUtxo => {} + e => panic!("unexpected error: {:?}", e), } // negative fee let mut t3 = t.clone(); t3.unsigned_tx.output[0].value = prev_output_val; match t3.fee().unwrap_err() { - Error::NegativeFee => {}, - e => panic!("unexpected error: {:?}", e) + Error::NegativeFee => {} + e => panic!("unexpected error: {:?}", e), } // overflow t.unsigned_tx.output[0].value = u64::max_value(); t.unsigned_tx.output[1].value = u64::max_value(); match t.fee().unwrap_err() { - Error::FeeOverflow => {}, - e => panic!("unexpected error: {:?}", e) + Error::FeeOverflow => {} + e => panic!("unexpected error: {:?}", e), } } #[test] #[cfg(feature = "rand-std")] fn sign_psbt() { - use crate::WPubkeyHash; use crate::address::WitnessProgram; - use crate::bip32::{Fingerprint, DerivationPath}; + use crate::bip32::{DerivationPath, Fingerprint}; + use crate::WPubkeyHash; let unsigned_tx = Transaction { version: 2, @@ -1767,7 +1806,7 @@ mod tests { key_map.insert(pk, priv_key); // First input we can spend. See comment above on key_map for why we use defaults here. - let txout_wpkh = TxOut{ + let txout_wpkh = TxOut { value: 10, script_pubkey: ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&pk.to_bytes())), }; @@ -1778,13 +1817,10 @@ mod tests { psbt.inputs[0].bip32_derivation = map; // Second input is unspendable by us e.g., from another wallet that supports future upgrades. - let unknown_prog = WitnessProgram::new( - crate::address::WitnessVersion::V4, vec![0xaa; 34] - ).unwrap(); - let txout_unknown_future = TxOut{ - value: 10, - script_pubkey: ScriptBuf::new_witness_program(&unknown_prog), - }; + let unknown_prog = + WitnessProgram::new(crate::address::WitnessVersion::V4, vec![0xaa; 34]).unwrap(); + let txout_unknown_future = + TxOut { value: 10, script_pubkey: ScriptBuf::new_witness_program(&unknown_prog) }; psbt.inputs[1].witness_utxo = Some(txout_unknown_future); let sigs = psbt.sign(&key_map, &secp).unwrap(); diff --git a/bitcoin/src/psbt/raw.rs b/bitcoin/src/psbt/raw.rs index 94ab4eab..aa312413 100644 --- a/bitcoin/src/psbt/raw.rs +++ b/bitcoin/src/psbt/raw.rs @@ -6,16 +6,17 @@ //! . //! -use crate::prelude::*; -use core::fmt; use core::convert::TryFrom; +use core::fmt; +use super::serialize::{Deserialize, Serialize}; +use crate::consensus::encode::{ + self, deserialize, serialize, Decodable, Encodable, ReadExt, VarInt, WriteExt, MAX_VEC_SIZE, +}; use crate::io; -use crate::consensus::encode::{self, ReadExt, WriteExt, Decodable, Encodable, VarInt, serialize, deserialize, MAX_VEC_SIZE}; +use crate::prelude::*; use crate::psbt::Error; -use super::serialize::{Serialize, Deserialize}; - /// A PSBT key in its raw byte form. #[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -51,7 +52,10 @@ pub type ProprietaryType = u8; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct ProprietaryKey where Subtype: Copy + From + Into { +pub struct ProprietaryKey +where + Subtype: Copy + From + Into, +{ /// Proprietary type prefix used for grouping together keys under some /// application and avoid namespace collision #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))] @@ -83,7 +87,7 @@ impl Key { return Err(encode::Error::OversizedVectorAllocation { requested: key_byte_size as usize, max: MAX_VEC_SIZE, - })? + })?; } let type_value: u8 = Decodable::consensus_decode(r)?; @@ -100,7 +104,9 @@ impl Key { impl Serialize for Key { fn serialize(&self) -> Vec { let mut buf = Vec::new(); - VarInt((self.key.len() + 1) as u64).consensus_encode(&mut buf).expect("in-memory writers don't error"); + VarInt((self.key.len() + 1) as u64) + .consensus_encode(&mut buf) + .expect("in-memory writers don't error"); self.type_value.consensus_encode(&mut buf).expect("in-memory writers don't error"); @@ -131,14 +137,14 @@ impl Deserialize for Pair { impl Pair { pub(crate) fn decode(r: &mut R) -> Result { - Ok(Pair { - key: Key::decode(r)?, - value: Decodable::consensus_decode(r)?, - }) + Ok(Pair { key: Key::decode(r)?, value: Decodable::consensus_decode(r)? }) } } -impl Encodable for ProprietaryKey where Subtype: Copy + From + Into { +impl Encodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ fn consensus_encode(&self, w: &mut W) -> Result { let mut len = self.prefix.consensus_encode(w)? + 1; w.emit_u8(self.subtype.into())?; @@ -148,7 +154,10 @@ impl Encodable for ProprietaryKey where Subtype: Copy + From Decodable for ProprietaryKey where Subtype: Copy + From + Into { +impl Decodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ fn consensus_decode(r: &mut R) -> Result { let prefix = Vec::::consensus_decode(r)?; let subtype = Subtype::from(r.read_u8()?); @@ -158,19 +167,18 @@ impl Decodable for ProprietaryKey where Subtype: Copy + From ProprietaryKey where Subtype: Copy + From + Into { +impl ProprietaryKey +where + Subtype: Copy + From + Into, +{ /// Constructs full [Key] corresponding to this proprietary key type - pub fn to_key(&self) -> Key { - Key { - type_value: 0xFC, - key: serialize(self) - } - } + pub fn to_key(&self) -> Key { Key { type_value: 0xFC, key: serialize(self) } } } impl TryFrom for ProprietaryKey where - Subtype:Copy + From + Into { + Subtype: Copy + From + Into, +{ type Error = Error; /// Constructs a [`ProprietaryKey`] from a [`Key`]. @@ -179,7 +187,7 @@ where /// Returns [`Error::InvalidProprietaryKey`] if `key` does not start with `0xFC` byte. fn try_from(key: Key) -> Result { if key.type_value != 0xFC { - return Err(Error::InvalidProprietaryKey) + return Err(Error::InvalidProprietaryKey); } Ok(deserialize(&key.key)?) @@ -194,7 +202,7 @@ pub(crate) fn read_to_end(mut d: D) -> Result, io::Error> { match d.read(&mut buf) { Ok(0) => break, Ok(n) => result.extend_from_slice(&buf[0..n]), - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => return Err(e), }; } diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index 5f965824..c3a21d54 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -6,31 +6,26 @@ //! according to the BIP-174 specification. //! -use core::convert::TryFrom; -use core::convert::TryInto; +use core::convert::{TryFrom, TryInto}; -use crate::VarInt; -use crate::prelude::*; - -use crate::io; - -use crate::blockdata::script::ScriptBuf; -use crate::blockdata::witness::Witness; -use crate::blockdata::transaction::{Transaction, TxOut}; -use crate::consensus::encode::{self, serialize, Decodable, Encodable, deserialize_partial}; -use crate::taproot::TapTree; use secp256k1::{self, XOnlyPublicKey}; -use crate::bip32::{ChildNumber, Fingerprint, KeySource}; -use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; -use crate::crypto::{ecdsa, taproot}; -use crate::psbt::{Error, PartiallySignedTransaction}; -use crate::taproot::{TapNodeHash, TapLeafHash, ControlBlock, LeafVersion}; -use crate::crypto::key::PublicKey; -use super::map::{Map, Input, Output, PsbtSighashType}; +use super::map::{Input, Map, Output, PsbtSighashType}; use super::Psbt; - -use crate::taproot::TaprootBuilder; +use crate::bip32::{ChildNumber, Fingerprint, KeySource}; +use crate::blockdata::script::ScriptBuf; +use crate::blockdata::transaction::{Transaction, TxOut}; +use crate::blockdata::witness::Witness; +use crate::consensus::encode::{self, deserialize_partial, serialize, Decodable, Encodable}; +use crate::crypto::key::PublicKey; +use crate::crypto::{ecdsa, taproot}; +use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use crate::prelude::*; +use crate::psbt::{Error, PartiallySignedTransaction}; +use crate::taproot::{ + ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder, +}; +use crate::{io, VarInt}; /// A trait for serializing a value as raw data for insertion into PSBT /// key-value maps. pub(crate) trait Serialize { @@ -46,9 +41,7 @@ pub(crate) trait Deserialize: Sized { impl PartiallySignedTransaction { /// Serialize a value as bytes in hex. - pub fn serialize_hex(&self) -> String { - self.serialize().to_lower_hex_string() - } + pub fn serialize_hex(&self) -> String { self.serialize().to_lower_hex_string() } /// Serialize as raw binary data pub fn serialize(&self) -> Vec { @@ -72,7 +65,6 @@ impl PartiallySignedTransaction { buf } - /// Deserialize a value from raw binary data. pub fn deserialize(bytes: &[u8]) -> Result { const MAGIC_BYTES: &[u8] = b"psbt"; @@ -133,15 +125,11 @@ impl_psbt_hash_de_serialize!(sha256d::Hash); impl_psbt_de_serialize!(Vec); impl Serialize for ScriptBuf { - fn serialize(&self) -> Vec { - self.to_bytes() - } + fn serialize(&self) -> Vec { self.to_bytes() } } impl Deserialize for ScriptBuf { - fn deserialize(bytes: &[u8]) -> Result { - Ok(Self::from(bytes.to_vec())) - } + fn deserialize(bytes: &[u8]) -> Result { Ok(Self::from(bytes.to_vec())) } } impl Serialize for PublicKey { @@ -154,28 +142,22 @@ impl Serialize for PublicKey { impl Deserialize for PublicKey { fn deserialize(bytes: &[u8]) -> Result { - PublicKey::from_slice(bytes) - .map_err(Error::InvalidPublicKey) + PublicKey::from_slice(bytes).map_err(Error::InvalidPublicKey) } } impl Serialize for secp256k1::PublicKey { - fn serialize(&self) -> Vec { - self.serialize().to_vec() - } + fn serialize(&self) -> Vec { self.serialize().to_vec() } } impl Deserialize for secp256k1::PublicKey { fn deserialize(bytes: &[u8]) -> Result { - secp256k1::PublicKey::from_slice(bytes) - .map_err(Error::InvalidSecp256k1PublicKey) + secp256k1::PublicKey::from_slice(bytes).map_err(Error::InvalidSecp256k1PublicKey) } } impl Serialize for ecdsa::Signature { - fn serialize(&self) -> Vec { - self.to_vec() - } + fn serialize(&self) -> Vec { self.to_vec() } } impl Deserialize for ecdsa::Signature { @@ -193,21 +175,14 @@ impl Deserialize for ecdsa::Signature { // also has a field sighash_u32 (See BIP141). For example, when signing with non-standard // 0x05, the sighash message would have the last field as 0x05u32 while, the verification // would use check the signature assuming sighash_u32 as `0x01`. - ecdsa::Signature::from_slice(bytes) - .map_err(|e| match e { - ecdsa::Error::EmptySignature => { - Error::InvalidEcdsaSignature(e) - } - ecdsa::Error::NonStandardSighashType(flag) => { - Error::NonStandardSighashType(flag) - } - ecdsa::Error::Secp256k1(..) => { - Error::InvalidEcdsaSignature(e) - } - ecdsa::Error::HexEncoding(..) => { - unreachable!("Decoding from slice, not hex") - } - }) + ecdsa::Signature::from_slice(bytes).map_err(|e| match e { + ecdsa::Error::EmptySignature => Error::InvalidEcdsaSignature(e), + ecdsa::Error::NonStandardSighashType(flag) => Error::NonStandardSighashType(flag), + ecdsa::Error::Secp256k1(..) => Error::InvalidEcdsaSignature(e), + ecdsa::Error::HexEncoding(..) => { + unreachable!("Decoding from slice, not hex") + } + }) } } @@ -228,7 +203,7 @@ impl Serialize for KeySource { impl Deserialize for KeySource { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 4 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } let fprint: Fingerprint = bytes[0..4].try_into().expect("4 is the fingerprint length"); @@ -248,21 +223,15 @@ impl Deserialize for KeySource { // partial sigs impl Serialize for Vec { - fn serialize(&self) -> Vec { - self.clone() - } + fn serialize(&self) -> Vec { self.clone() } } impl Deserialize for Vec { - fn deserialize(bytes: &[u8]) -> Result { - Ok(bytes.to_vec()) - } + fn deserialize(bytes: &[u8]) -> Result { Ok(bytes.to_vec()) } } impl Serialize for PsbtSighashType { - fn serialize(&self) -> Vec { - serialize(&self.to_u32()) - } + fn serialize(&self) -> Vec { serialize(&self.to_u32()) } } impl Deserialize for PsbtSighashType { @@ -274,38 +243,26 @@ impl Deserialize for PsbtSighashType { // Taproot related ser/deser impl Serialize for XOnlyPublicKey { - fn serialize(&self) -> Vec { - XOnlyPublicKey::serialize(self).to_vec() - } + fn serialize(&self) -> Vec { XOnlyPublicKey::serialize(self).to_vec() } } impl Deserialize for XOnlyPublicKey { fn deserialize(bytes: &[u8]) -> Result { - XOnlyPublicKey::from_slice(bytes) - .map_err(|_| Error::InvalidXOnlyPublicKey) + XOnlyPublicKey::from_slice(bytes).map_err(|_| Error::InvalidXOnlyPublicKey) } } -impl Serialize for taproot::Signature { - fn serialize(&self) -> Vec { - self.to_vec() - } +impl Serialize for taproot::Signature { + fn serialize(&self) -> Vec { self.to_vec() } } impl Deserialize for taproot::Signature { fn deserialize(bytes: &[u8]) -> Result { - taproot::Signature::from_slice(bytes) - .map_err(|e| match e { - taproot::Error::InvalidSighashType(flag) => { - Error::NonStandardSighashType(flag as u32) - } - taproot::Error::InvalidSignatureSize(_) => { - Error::InvalidTaprootSignature(e) - } - taproot::Error::Secp256k1(..) => { - Error::InvalidTaprootSignature(e) - } - }) + taproot::Signature::from_slice(bytes).map_err(|e| match e { + taproot::Error::InvalidSighashType(flag) => Error::NonStandardSighashType(flag as u32), + taproot::Error::InvalidSignatureSize(_) => Error::InvalidTaprootSignature(e), + taproot::Error::Secp256k1(..) => Error::InvalidTaprootSignature(e), + }) } } @@ -322,7 +279,7 @@ impl Serialize for (XOnlyPublicKey, TapLeafHash) { impl Deserialize for (XOnlyPublicKey, TapLeafHash) { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 32 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?; let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?; @@ -331,15 +288,12 @@ impl Deserialize for (XOnlyPublicKey, TapLeafHash) { } impl Serialize for ControlBlock { - fn serialize(&self) -> Vec { - ControlBlock::serialize(self) - } + fn serialize(&self) -> Vec { ControlBlock::serialize(self) } } impl Deserialize for ControlBlock { fn deserialize(bytes: &[u8]) -> Result { - Self::decode(bytes) - .map_err(|_| Error::InvalidControlBlock) + Self::decode(bytes).map_err(|_| Error::InvalidControlBlock) } } @@ -356,7 +310,7 @@ impl Serialize for (ScriptBuf, LeafVersion) { impl Deserialize for (ScriptBuf, LeafVersion) { fn deserialize(bytes: &[u8]) -> Result { if bytes.is_empty() { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } // The last byte is LeafVersion. let script = ScriptBuf::deserialize(&bytes[..bytes.len() - 1])?; @@ -366,10 +320,9 @@ impl Deserialize for (ScriptBuf, LeafVersion) { } } - impl Serialize for (Vec, KeySource) { fn serialize(&self) -> Vec { - let mut buf = Vec::with_capacity( 32 * self.0.len() + key_source_len(&self.1)); + let mut buf = Vec::with_capacity(32 * self.0.len() + key_source_len(&self.1)); self.0.consensus_encode(&mut buf).expect("Vecs don't error allocation"); // TODO: Add support for writing into a writer for key-source buf.extend(self.1.serialize()); @@ -387,11 +340,14 @@ impl Deserialize for (Vec, KeySource) { impl Serialize for TapTree { fn serialize(&self) -> Vec { - let capacity = self.script_leaves().map(|l| { - l.script().len() + VarInt(l.script().len() as u64).len() // script version + let capacity = self + .script_leaves() + .map(|l| { + l.script().len() + VarInt(l.script().len() as u64).len() // script version + 1 // merkle branch + 1 // leaf version - }).sum::(); + }) + .sum::(); let mut buf = Vec::with_capacity(capacity); for leaf_info in self.script_leaves() { // # Cast Safety: @@ -416,9 +372,10 @@ impl Deserialize for TapTree { if consumed > 0 { bytes_iter.nth(consumed - 1); } - let leaf_version = LeafVersion::from_consensus(*version) - .map_err(|_| Error::InvalidLeafVersion)?; - builder = builder.add_leaf_with_ver(*depth, script, leaf_version) + let leaf_version = + LeafVersion::from_consensus(*version).map_err(|_| Error::InvalidLeafVersion)?; + builder = builder + .add_leaf_with_ver(*depth, script, leaf_version) .map_err(|_| Error::Taproot("Tree not in DFS order"))?; } TapTree::try_from(builder).map_err(Error::TapTree) @@ -426,9 +383,7 @@ impl Deserialize for TapTree { } // Helper function to compute key source len -fn key_source_len(key_source: &KeySource) -> usize { - 4 + 4 * (key_source.1).as_ref().len() -} +fn key_source_len(key_source: &KeySource) -> usize { 4 + 4 * (key_source.1).as_ref().len() } #[cfg(test)] mod tests { @@ -439,7 +394,10 @@ mod tests { // Composes tree matching a given depth map, filled with dumb script leafs, // each of which consists of a single push-int op code, with int value // increased for each consecutive leaf. - pub fn compose_taproot_builder<'map>(opcode: u8, depth_map: impl IntoIterator) -> TaprootBuilder { + pub fn compose_taproot_builder<'map>( + opcode: u8, + depth_map: impl IntoIterator, + ) -> TaprootBuilder { let mut val = opcode; let mut builder = TaprootBuilder::new(); for depth in depth_map { @@ -454,7 +412,13 @@ mod tests { #[test] fn taptree_hidden() { let mut builder = compose_taproot_builder(0x51, &[2, 2, 2]); - builder = builder.add_leaf_with_ver(3, ScriptBuf::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap(); + builder = builder + .add_leaf_with_ver( + 3, + ScriptBuf::from_hex("b9").unwrap(), + LeafVersion::from_consensus(0xC2).unwrap(), + ) + .unwrap(); builder = builder.add_hidden_node(3, TapNodeHash::all_zeros()).unwrap(); assert!(TapTree::try_from(builder).is_err()); } @@ -462,7 +426,13 @@ mod tests { #[test] fn taptree_roundtrip() { let mut builder = compose_taproot_builder(0x51, &[2, 2, 2, 3]); - builder = builder.add_leaf_with_ver(3, ScriptBuf::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap(); + builder = builder + .add_leaf_with_ver( + 3, + ScriptBuf::from_hex("b9").unwrap(), + LeafVersion::from_consensus(0xC2).unwrap(), + ) + .unwrap(); let tree = TapTree::try_from(builder).unwrap(); let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap(); assert_eq!(tree, tree_prime);