diff --git a/src/v0/miniscript/error.rs b/src/v0/miniscript/error.rs deleted file mode 100644 index fff51b7..0000000 --- a/src/v0/miniscript/error.rs +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -use core::fmt; - -use crate::error::write_err; - -use miniscript::bip32::Xpub; -use miniscript::blockdata::transaction::Transaction; -use miniscript::consensus::encode; -use miniscript::prelude::*; -use miniscript::psbt::raw; -use miniscript::{hashes, io}; - -/// Enum for marking psbt hash error. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub enum PsbtHash { - Ripemd, - Sha256, - Hash160, - Hash256, -} -/// Ways that a Partially Signed Transaction might fail. -#[derive(Debug)] -#[non_exhaustive] -pub enum Error { - /// Magic bytes for a PSBT must be the ASCII for "psbt" serialized in most - /// significant byte order. - InvalidMagic, - /// Missing both the witness and non-witness utxo. - MissingUtxo, - /// The separator for a PSBT must be `0xff`. - InvalidSeparator, - /// Returned when output index is out of bounds in relation to the output in non-witness UTXO. - PsbtUtxoOutOfbounds, - /// Known keys must be according to spec. - InvalidKey(raw::Key), - /// Non-proprietary key type found when proprietary key was expected - InvalidProprietaryKey, - /// Keys within key-value map should never be duplicated. - DuplicateKey(raw::Key), - /// The scriptSigs for the unsigned transaction must be empty. - UnsignedTxHasScriptSigs, - /// The scriptWitnesses for the unsigned transaction must be empty. - UnsignedTxHasScriptWitnesses, - /// A PSBT must have an unsigned transaction. - MustHaveUnsignedTx, - /// Signals that there are no more key-value pairs in a key-value map. - NoMorePairs, - /// Attempting to combine with a PSBT describing a different unsigned - /// transaction. - UnexpectedUnsignedTx { - /// Expected - expected: Box, - /// Actual - actual: Box, - }, - /// Unable to parse as a standard sighash type. - NonStandardSighashType(u32), - /// Invalid hash when parsing slice. - InvalidHash(hashes::FromSliceError), - /// The pre-image must hash to the correponding psbt hash - InvalidPreimageHashPair { - /// Hash-type - hash_type: PsbtHash, - /// Pre-image - preimage: Box<[u8]>, - /// Hash value - hash: Box<[u8]>, - }, - /// Conflicting data during combine procedure: - /// global extended public key has inconsistent key sources - CombineInconsistentKeySources(Box), - /// Serialization error in bitcoin consensus-encoded structures - ConsensusEncoding(encode::Error), - /// Negative fee - NegativeFee, - /// Integer overflow in fee calculation - FeeOverflow, - /// Parsing error indicating invalid public keys - InvalidPublicKey(crate::crypto::key::Error), - /// Parsing error indicating invalid secp256k1 public keys - InvalidSecp256k1PublicKey(secp256k1::Error), - /// Parsing error indicating invalid xonly public keys - InvalidXOnlyPublicKey, - /// Parsing error indicating invalid ECDSA signatures - InvalidEcdsaSignature(crate::crypto::ecdsa::Error), - /// Parsing error indicating invalid taproot signatures - InvalidTaprootSignature(crate::crypto::taproot::SigFromSliceError), - /// Parsing error indicating invalid control block - InvalidControlBlock, - /// Parsing error indicating invalid leaf version - InvalidLeafVersion, - /// Parsing error indicating a taproot error - Taproot(&'static str), - /// Taproot tree deserilaization error - TapTree(crate::taproot::IncompleteBuilderError), - /// Error related to an xpub key - XPubKey(&'static str), - /// Error related to PSBT version - Version(&'static str), - /// PSBT data is not consumed entirely - PartialDataConsumption, - /// I/O error. - Io(io::Error), -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use Error::*; - - match *self { - InvalidMagic => f.write_str("invalid magic"), - MissingUtxo => f.write_str("UTXO information is not present in PSBT"), - InvalidSeparator => f.write_str("invalid separator"), - PsbtUtxoOutOfbounds => - f.write_str("output index is out of bounds of non witness script output array"), - InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), - InvalidProprietaryKey => - write!(f, "non-proprietary key type found when proprietary key was expected"), - DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), - UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), - UnsignedTxHasScriptWitnesses => - f.write_str("the unsigned transaction has script witnesses"), - MustHaveUnsignedTx => - f.write_str("partially signed transactions must have an unsigned transaction"), - NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), - UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!( - f, - "different unsigned transaction: expected {}, actual {}", - e.txid(), - a.txid() - ), - NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), - InvalidHash(ref e) => write_err!(f, "invalid hash when parsing slice"; e), - 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) - } - CombineInconsistentKeySources(ref s) => { - write!(f, "combine conflict: {}", s) - } - ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e), - NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"), - FeeOverflow => f.write_str("integer overflow in fee calculation"), - InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e), - InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e), - InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"), - InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e), - InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e), - InvalidControlBlock => f.write_str("invalid control block"), - InvalidLeafVersion => f.write_str("invalid leaf version"), - Taproot(s) => write!(f, "taproot error - {}", s), - TapTree(ref e) => write_err!(f, "taproot tree error"; e), - XPubKey(s) => write!(f, "xpub key error - {}", s), - Version(s) => write!(f, "version error {}", s), - PartialDataConsumption => - f.write_str("data not consumed entirely when explicitly deserializing"), - Io(ref e) => write_err!(f, "I/O error"; e), - } - } -} - -#[cfg(feature = "std")] -impl std::error::Error for Error { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use Error::*; - - match *self { - InvalidHash(ref e) => Some(e), - ConsensusEncoding(ref e) => Some(e), - Io(ref e) => Some(e), - InvalidMagic - | MissingUtxo - | InvalidSeparator - | PsbtUtxoOutOfbounds - | InvalidKey(_) - | InvalidProprietaryKey - | DuplicateKey(_) - | UnsignedTxHasScriptSigs - | UnsignedTxHasScriptWitnesses - | MustHaveUnsignedTx - | NoMorePairs - | UnexpectedUnsignedTx { .. } - | NonStandardSighashType(_) - | InvalidPreimageHashPair { .. } - | CombineInconsistentKeySources(_) - | NegativeFee - | FeeOverflow - | InvalidPublicKey(_) - | InvalidSecp256k1PublicKey(_) - | InvalidXOnlyPublicKey - | InvalidEcdsaSignature(_) - | InvalidTaprootSignature(_) - | InvalidControlBlock - | InvalidLeafVersion - | Taproot(_) - | TapTree(_) - | XPubKey(_) - | Version(_) - | PartialDataConsumption => None, - } - } -} - -impl From for Error { - fn from(e: hashes::FromSliceError) -> Error { Error::InvalidHash(e) } -} - -impl From for Error { - fn from(e: encode::Error) -> Self { Error::ConsensusEncoding(e) } -} - -impl From for Error { - fn from(e: io::Error) -> Self { Error::Io(e) } -} diff --git a/src/v0/miniscript/macros.rs b/src/v0/miniscript/macros.rs deleted file mode 100644 index f07e5bb..0000000 --- a/src/v0/miniscript/macros.rs +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -#[allow(unused_macros)] -macro_rules! combine { - ($thing:ident, $slf:ident, $other:ident) => { - if let (&None, Some($thing)) = (&$slf.$thing, $other.$thing) { - $slf.$thing = Some($thing); - } - }; -} - -macro_rules! impl_psbt_de_serialize { - ($thing:ty) => { - impl_psbt_serialize!($thing); - impl_psbt_deserialize!($thing); - }; -} - -macro_rules! impl_psbt_deserialize { - ($thing:ty) => { - impl $crate::psbt::serialize::Deserialize for $thing { - fn deserialize(bytes: &[u8]) -> Result { - $crate::consensus::deserialize(&bytes[..]).map_err(|e| $crate::psbt::Error::from(e)) - } - } - }; -} - -macro_rules! impl_psbt_serialize { - ($thing:ty) => { - impl $crate::psbt::serialize::Serialize for $thing { - fn serialize(&self) -> $crate::prelude::Vec { $crate::consensus::serialize(self) } - } - }; -} - -macro_rules! impl_psbtmap_serialize { - ($thing:ty) => { - impl $crate::psbt::serialize::Serialize for $thing { - fn serialize(&self) -> Vec { self.serialize_map() } - } - }; -} - -macro_rules! impl_psbtmap_deserialize { - ($thing:ty) => { - impl $crate::psbt::serialize::Deserialize for $thing { - fn deserialize(bytes: &[u8]) -> Result { - let mut decoder = bytes; - Self::decode(&mut decoder) - } - } - }; -} - -macro_rules! impl_psbtmap_decoding { - ($thing:ty) => { - impl $thing { - pub(crate) fn decode( - r: &mut R, - ) -> Result { - let mut rv: Self = core::default::Default::default(); - - loop { - match $crate::psbt::raw::Pair::decode(r) { - Ok(pair) => rv.insert_pair(pair)?, - Err($crate::psbt::Error::NoMorePairs) => return Ok(rv), - Err(e) => return Err(e), - } - } - } - } - }; -} - -macro_rules! impl_psbtmap_ser_de_serialize { - ($thing:ty) => { - impl_psbtmap_decoding!($thing); - impl_psbtmap_serialize!($thing); - impl_psbtmap_deserialize!($thing); - }; -} - -#[rustfmt::skip] -macro_rules! impl_psbt_insert_pair { - ($slf:ident.$unkeyed_name:ident <= <$raw_key:ident: _>|<$raw_value:ident: $unkeyed_value_type:ty>) => { - if $raw_key.key.is_empty() { - if $slf.$unkeyed_name.is_none() { - let val: $unkeyed_value_type = $crate::psbt::serialize::Deserialize::deserialize(&$raw_value)?; - $slf.$unkeyed_name = Some(val) - } else { - return Err($crate::psbt::Error::DuplicateKey($raw_key).into()); - } - } else { - return Err($crate::psbt::Error::InvalidKey($raw_key).into()); - } - }; - ($slf:ident.$keyed_name:ident <= <$raw_key:ident: $keyed_key_type:ty>|<$raw_value:ident: $keyed_value_type:ty>) => { - if !$raw_key.key.is_empty() { - let key_val: $keyed_key_type = $crate::psbt::serialize::Deserialize::deserialize(&$raw_key.key)?; - match $slf.$keyed_name.entry(key_val) { - $crate::prelude::btree_map::Entry::Vacant(empty_key) => { - let val: $keyed_value_type = $crate::psbt::serialize::Deserialize::deserialize(&$raw_value)?; - empty_key.insert(val); - } - $crate::prelude::btree_map::Entry::Occupied(_) => return Err($crate::psbt::Error::DuplicateKey($raw_key).into()), - } - } else { - return Err($crate::psbt::Error::InvalidKey($raw_key).into()); - } - }; -} - -#[rustfmt::skip] -macro_rules! impl_psbt_get_pair { - ($rv:ident.push($slf:ident.$unkeyed_name:ident, $unkeyed_typeval:ident)) => { - if let Some(ref $unkeyed_name) = $slf.$unkeyed_name { - $rv.push($crate::psbt::raw::Pair { - key: $crate::psbt::raw::Key { - type_value: $unkeyed_typeval, - key: vec![], - }, - value: $crate::psbt::serialize::Serialize::serialize($unkeyed_name), - }); - } - }; - ($rv:ident.push_map($slf:ident.$keyed_name:ident, $keyed_typeval:ident)) => { - for (key, val) in &$slf.$keyed_name { - $rv.push($crate::psbt::raw::Pair { - key: $crate::psbt::raw::Key { - type_value: $keyed_typeval, - key: $crate::psbt::serialize::Serialize::serialize(key), - }, - value: $crate::psbt::serialize::Serialize::serialize(val), - }); - } - }; -} - -// macros for serde of hashes -macro_rules! impl_psbt_hash_de_serialize { - ($hash_type:ty) => { - impl_psbt_hash_serialize!($hash_type); - impl_psbt_hash_deserialize!($hash_type); - }; -} - -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)) - } - } - }; -} - -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() } - } - }; -} diff --git a/src/v0/miniscript/map/global.rs b/src/v0/miniscript/map/global.rs deleted file mode 100644 index 1e14093..0000000 --- a/src/v0/miniscript/map/global.rs +++ /dev/null @@ -1,215 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -use core::convert::TryFrom; - -use miniscript::bip32::{ChildNumber, DerivationPath, Fingerprint, Xpub}; -use miniscript::blockdata::transaction::Transaction; -use miniscript::consensus::encode::MAX_VEC_SIZE; -use miniscript::consensus::{encode, Decodable}; -use miniscript::io::{self, Cursor, Read}; -use miniscript::prelude::*; -use miniscript::psbt::map::Map; -use miniscript::psbt::{raw, Error, Psbt}; - -/// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00 -const PSBT_GLOBAL_UNSIGNED_TX: u8 = 0x00; -/// Type: Extended Public Key PSBT_GLOBAL_XPUB = 0x01 -const PSBT_GLOBAL_XPUB: u8 = 0x01; -/// Type: Version Number PSBT_GLOBAL_VERSION = 0xFB -const PSBT_GLOBAL_VERSION: u8 = 0xFB; -/// Type: Proprietary Use Type PSBT_GLOBAL_PROPRIETARY = 0xFC -const PSBT_GLOBAL_PROPRIETARY: u8 = 0xFC; - -impl Map for Psbt { - fn get_pairs(&self) -> Vec { - let mut rv: Vec = Default::default(); - - rv.push(raw::Pair { - key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key: vec![] }, - value: { - // Manually serialized to ensure 0-input txs are serialized - // without witnesses. - let mut ret = Vec::new(); - ret.extend(encode::serialize(&self.unsigned_tx.version)); - ret.extend(encode::serialize(&self.unsigned_tx.input)); - ret.extend(encode::serialize(&self.unsigned_tx.output)); - ret.extend(encode::serialize(&self.unsigned_tx.lock_time)); - ret - }, - }); - - for (xpub, (fingerprint, derivation)) in &self.xpub { - rv.push(raw::Pair { - 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(), - }); - } - - for (key, value) in self.proprietary.iter() { - 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 - } -} - -impl Psbt { - pub(crate) fn decode_global(r: &mut R) -> Result { - let mut r = r.take(MAX_VEC_SIZE as u64); - 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 proprietary: BTreeMap> = Default::default(); - - loop { - match raw::Pair::decode(&mut r) { - Ok(pair) => { - match pair.key.type_value { - PSBT_GLOBAL_UNSIGNED_TX => { - // key has to be empty - if pair.key.key.is_empty() { - // there can only be one unsigned transaction - if tx.is_none() { - let vlen: usize = pair.value.len(); - let mut decoder = Cursor::new(pair.value); - - // Manually deserialized to ensure 0-input - // txs without witnesses are deserialized - // properly. - tx = Some(Transaction { - version: Decodable::consensus_decode(&mut decoder)?, - input: Decodable::consensus_decode(&mut decoder)?, - output: Decodable::consensus_decode(&mut decoder)?, - lock_time: Decodable::consensus_decode(&mut decoder)?, - }); - - if decoder.position() != vlen as u64 { - return Err(Error::PartialDataConsumption); - } - } else { - return Err(Error::DuplicateKey(pair.key)); - } - } else { - return Err(Error::InvalidKey(pair.key)); - } - } - PSBT_GLOBAL_XPUB => { - if !pair.key.key.is_empty() { - let xpub = Xpub::decode(&pair.key.key) - .map_err(|_| Error::XPubKey( - "Can't deserialize ExtendedPublicKey from global XPUB key data" - ))?; - - if pair.value.is_empty() || pair.value.len() % 4 != 0 { - 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") - })?; - 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")); - } - } else { - return Err(Error::XPubKey( - "Xpub global key must contain serialized Xpub data", - )); - } - } - PSBT_GLOBAL_VERSION => { - // key has to be empty - if pair.key.key.is_empty() { - // there can only be one version - if version.is_none() { - 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)", - )); - } - 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", - )); - } - } else { - return Err(Error::DuplicateKey(pair.key)); - } - } else { - return Err(Error::InvalidKey(pair.key)); - } - } - 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)), - }, - _ => 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())), - }, - } - } - Err(crate::psbt::Error::NoMorePairs) => break, - Err(e) => return Err(e), - } - } - - if let Some(tx) = tx { - Ok(Psbt { - unsigned_tx: tx, - version: version.unwrap_or(0), - xpub: xpub_map, - proprietary, - unknown: unknowns, - inputs: vec![], - outputs: vec![], - }) - } else { - Err(Error::MustHaveUnsignedTx) - } - } -} diff --git a/src/v0/miniscript/map/input.rs b/src/v0/miniscript/map/input.rs deleted file mode 100644 index c4d343d..0000000 --- a/src/v0/miniscript/map/input.rs +++ /dev/null @@ -1,582 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -use core::convert::TryFrom; -use core::fmt; -use core::str::FromStr; - -use bitcoin::hashes::{self, hash160, ripemd160, sha256, sha256d}; -use bitcoin::secp256k1::XOnlyPublicKey; - -use miniscript::bip32::KeySource; -use miniscript::blockdata::script::ScriptBuf; -use miniscript::blockdata::transaction::{Transaction, TxOut}; -use miniscript::blockdata::witness::Witness; -use miniscript::crypto::key::PublicKey; -use miniscript::crypto::{ecdsa, taproot}; -use miniscript::prelude::*; -use miniscript::psbt::map::Map; -use miniscript::psbt::serialize::Deserialize; -use miniscript::psbt::{self, error, raw, Error}; -use miniscript::sighash::{ - EcdsaSighashType, InvalidSighashTypeError, NonStandardSighashTypeError, SighashTypeParseError, - TapSighashType, -}; -use miniscript::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash}; - -/// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 -const PSBT_IN_NON_WITNESS_UTXO: u8 = 0x00; -/// Type: Witness UTXO PSBT_IN_WITNESS_UTXO = 0x01 -const PSBT_IN_WITNESS_UTXO: u8 = 0x01; -/// Type: Partial Signature PSBT_IN_PARTIAL_SIG = 0x02 -const PSBT_IN_PARTIAL_SIG: u8 = 0x02; -/// Type: Sighash Type PSBT_IN_SIGHASH_TYPE = 0x03 -const PSBT_IN_SIGHASH_TYPE: u8 = 0x03; -/// Type: Redeem Script PSBT_IN_REDEEM_SCRIPT = 0x04 -const PSBT_IN_REDEEM_SCRIPT: u8 = 0x04; -/// Type: Witness Script PSBT_IN_WITNESS_SCRIPT = 0x05 -const PSBT_IN_WITNESS_SCRIPT: u8 = 0x05; -/// Type: BIP 32 Derivation Path PSBT_IN_BIP32_DERIVATION = 0x06 -const PSBT_IN_BIP32_DERIVATION: u8 = 0x06; -/// Type: Finalized scriptSig PSBT_IN_FINAL_SCRIPTSIG = 0x07 -const PSBT_IN_FINAL_SCRIPTSIG: u8 = 0x07; -/// Type: Finalized scriptWitness PSBT_IN_FINAL_SCRIPTWITNESS = 0x08 -const PSBT_IN_FINAL_SCRIPTWITNESS: u8 = 0x08; -/// Type: RIPEMD160 preimage PSBT_IN_RIPEMD160 = 0x0a -const PSBT_IN_RIPEMD160: u8 = 0x0a; -/// Type: SHA256 preimage PSBT_IN_SHA256 = 0x0b -const PSBT_IN_SHA256: u8 = 0x0b; -/// Type: HASH160 preimage PSBT_IN_HASH160 = 0x0c -const PSBT_IN_HASH160: u8 = 0x0c; -/// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d -const PSBT_IN_HASH256: u8 = 0x0d; -/// Type: Taproot Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13 -const PSBT_IN_TAP_KEY_SIG: u8 = 0x13; -/// Type: Taproot Signature in Script Spend PSBT_IN_TAP_SCRIPT_SIG = 0x14 -const PSBT_IN_TAP_SCRIPT_SIG: u8 = 0x14; -/// Type: Taproot Leaf Script PSBT_IN_TAP_LEAF_SCRIPT = 0x14 -const PSBT_IN_TAP_LEAF_SCRIPT: u8 = 0x15; -/// Type: Taproot Key BIP 32 Derivation Path PSBT_IN_TAP_BIP32_DERIVATION = 0x16 -const PSBT_IN_TAP_BIP32_DERIVATION: u8 = 0x16; -/// Type: Taproot Internal Key PSBT_IN_TAP_INTERNAL_KEY = 0x17 -const PSBT_IN_TAP_INTERNAL_KEY: u8 = 0x17; -/// Type: Taproot Merkle Root PSBT_IN_TAP_MERKLE_ROOT = 0x18 -const PSBT_IN_TAP_MERKLE_ROOT: u8 = 0x18; -/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC -const PSBT_IN_PROPRIETARY: u8 = 0xFC; - -/// A key-value map for an input of the corresponding index in the unsigned -/// transaction. -#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct Input { - /// The non-witness transaction this input spends from. Should only be - /// `Option::Some` for inputs which spend non-segwit outputs or - /// if it is unknown whether an input spends a segwit output. - pub non_witness_utxo: Option, - /// The transaction output this input spends from. Should only be - /// `Option::Some` for inputs which spend segwit outputs, - /// including P2SH embedded ones. - pub witness_utxo: Option, - /// A map from public keys to their corresponding signature as would be - /// pushed to the stack from a scriptSig or witness for a non-taproot inputs. - pub partial_sigs: BTreeMap, - /// The sighash type to be used for this input. Signatures for this input - /// must use the sighash type. - pub sighash_type: Option, - /// The redeem script for this input. - pub redeem_script: Option, - /// The witness script for this input. - pub witness_script: Option, - /// A map from public keys needed to sign this input to their corresponding - /// master key fingerprints and derivation paths. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] - pub bip32_derivation: BTreeMap, - /// The finalized, fully-constructed scriptSig with signatures and any other - /// scripts necessary for this input to pass validation. - pub final_script_sig: Option, - /// The finalized, fully-constructed scriptWitness with signatures and any - /// other scripts necessary for this input to pass validation. - pub final_script_witness: Option, - /// TODO: Proof of reserves commitment - /// RIPEMD160 hash to preimage map. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] - pub ripemd160_preimages: BTreeMap>, - /// SHA256 hash to preimage map. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] - pub sha256_preimages: BTreeMap>, - /// HSAH160 hash to preimage map. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] - pub hash160_preimages: BTreeMap>, - /// HAS256 hash to preimage map. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_byte_values"))] - pub hash256_preimages: BTreeMap>, - /// Serialized taproot signature with sighash type for key spend. - pub tap_key_sig: Option, - /// Map of `|` with signature. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] - pub tap_script_sigs: BTreeMap<(XOnlyPublicKey, TapLeafHash), taproot::Signature>, - /// Map of Control blocks to Script version pair. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] - pub tap_scripts: BTreeMap, - /// Map of tap root x only keys to origin info and leaf hashes contained in it. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] - pub tap_key_origins: BTreeMap, KeySource)>, - /// Taproot Internal key. - pub tap_internal_key: Option, - /// Taproot Merkle root. - pub tap_merkle_root: Option, - /// Proprietary key-value pairs for this input. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] - pub proprietary: BTreeMap>, - /// Unknown key-value pairs for this input. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] - 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 -/// for converting to/from [`PsbtSighashType`] from/to the desired signature hash type they need. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct PsbtSighashType { - pub(in crate::psbt) inner: u32, -} - -impl fmt::Display for PsbtSighashType { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.taproot_hash_ty() { - Err(_) => write!(f, "{:#x}", self.inner), - Ok(taproot_hash_ty) => fmt::Display::fmt(&taproot_hash_ty, f), - } - } -} - -impl FromStr for PsbtSighashType { - type Err = SighashTypeParseError; - - #[inline] - fn from_str(s: &str) -> Result { - // We accept strings of form: "SIGHASH_ALL" etc. - // - // NB: some of Taproot sighash types are non-standard for pre-taproot - // inputs. We also do not support SIGHASH_RESERVED in verbatim form - // ("0xFF" string should be used instead). - if let Ok(ty) = TapSighashType::from_str(s) { - return Ok(ty.into()); - } - - // We accept non-standard sighash values. - if let Ok(inner) = u32::from_str_radix(s.trim_start_matches("0x"), 16) { - return Ok(PsbtSighashType { inner }); - } - - Err(SighashTypeParseError { unrecognized: s.to_owned() }) - } -} -impl From for PsbtSighashType { - fn from(ecdsa_hash_ty: EcdsaSighashType) -> Self { - PsbtSighashType { inner: ecdsa_hash_ty as u32 } - } -} - -impl From for PsbtSighashType { - fn from(taproot_hash_ty: TapSighashType) -> Self { - PsbtSighashType { inner: taproot_hash_ty as u32 } - } -} - -impl PsbtSighashType { - /// Returns the [`EcdsaSighashType`] if the [`PsbtSighashType`] can be - /// converted to one. - pub fn ecdsa_hash_ty(self) -> Result { - EcdsaSighashType::from_standard(self.inner) - } - - /// Returns the [`TapSighashType`] if the [`PsbtSighashType`] can be - /// converted to one. - pub fn taproot_hash_ty(self) -> Result { - if self.inner > 0xffu32 { - Err(InvalidSighashTypeError(self.inner)) - } else { - TapSighashType::from_consensus_u8(self.inner as u8) - } - } - - /// Creates a [`PsbtSighashType`] from a raw `u32`. - /// - /// Allows construction of a non-standard or non-valid sighash flag - /// ([`EcdsaSighashType`], [`TapSighashType`] respectively). - 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 } -} - -impl Input { - /// Obtains the [`EcdsaSighashType`] for this input if one is specified. If no sighash type is - /// specified, returns [`EcdsaSighashType::All`]. - /// - /// # Errors - /// - /// If the `sighash_type` field is set to a non-standard ECDSA sighash value. - pub fn ecdsa_hash_ty(&self) -> Result { - self.sighash_type - .map(|sighash_type| sighash_type.ecdsa_hash_ty()) - .unwrap_or(Ok(EcdsaSighashType::All)) - } - - /// Obtains the [`TapSighashType`] for this input if one is specified. If no sighash type is - /// specified, returns [`TapSighashType::Default`]. - /// - /// # Errors - /// - /// If the `sighash_type` field is set to a invalid Taproot sighash value. - pub fn taproot_hash_ty(&self) -> Result { - self.sighash_type - .map(|sighash_type| sighash_type.taproot_hash_ty()) - .unwrap_or(Ok(TapSighashType::Default)) - } - - pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { - let raw::Pair { key: raw_key, value: raw_value } = pair; - - match raw_key.type_value { - PSBT_IN_NON_WITNESS_UTXO => { - impl_psbt_insert_pair! { - self.non_witness_utxo <= | - } - } - PSBT_IN_WITNESS_UTXO => { - impl_psbt_insert_pair! { - self.witness_utxo <= | - } - } - PSBT_IN_PARTIAL_SIG => { - impl_psbt_insert_pair! { - self.partial_sigs <= | - } - } - PSBT_IN_SIGHASH_TYPE => { - impl_psbt_insert_pair! { - self.sighash_type <= | - } - } - PSBT_IN_REDEEM_SCRIPT => { - impl_psbt_insert_pair! { - self.redeem_script <= | - } - } - PSBT_IN_WITNESS_SCRIPT => { - impl_psbt_insert_pair! { - self.witness_script <= | - } - } - PSBT_IN_BIP32_DERIVATION => { - impl_psbt_insert_pair! { - self.bip32_derivation <= | - } - } - PSBT_IN_FINAL_SCRIPTSIG => { - impl_psbt_insert_pair! { - self.final_script_sig <= | - } - } - PSBT_IN_FINAL_SCRIPTWITNESS => { - impl_psbt_insert_pair! { - self.final_script_witness <= | - } - } - PSBT_IN_RIPEMD160 => { - 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_IN_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_IN_TAP_KEY_SIG => { - impl_psbt_insert_pair! { - self.tap_key_sig <= | - } - } - PSBT_IN_TAP_SCRIPT_SIG => { - impl_psbt_insert_pair! { - self.tap_script_sigs <= | - } - } - PSBT_IN_TAP_LEAF_SCRIPT => { - impl_psbt_insert_pair! { - self.tap_scripts <= |< raw_value: (ScriptBuf, LeafVersion)> - } - } - PSBT_IN_TAP_BIP32_DERIVATION => { - impl_psbt_insert_pair! { - self.tap_key_origins <= |< raw_value: (Vec, KeySource)> - } - } - PSBT_IN_TAP_INTERNAL_KEY => { - impl_psbt_insert_pair! { - self.tap_internal_key <= |< raw_value: XOnlyPublicKey> - } - } - PSBT_IN_TAP_MERKLE_ROOT => { - impl_psbt_insert_pair! { - self.tap_merkle_root <= |< raw_value: TapNodeHash> - } - } - PSBT_IN_PROPRIETARY => { - let key = raw::ProprietaryKey::try_from(raw_key.clone())?; - 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)), - } - } - _ => match self.unknown.entry(raw_key) { - btree_map::Entry::Vacant(empty_key) => { - empty_key.insert(raw_value); - } - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), - }, - } - - Ok(()) - } - - /// Combines this [`Input`] with `other` `Input` (as described by BIP 174). - pub fn combine(&mut self, other: Self) { - combine!(non_witness_utxo, self, other); - - if let (&None, Some(witness_utxo)) = (&self.witness_utxo, other.witness_utxo) { - self.witness_utxo = Some(witness_utxo); - self.non_witness_utxo = None; // Clear out any non-witness UTXO when we set a witness one - } - - self.partial_sigs.extend(other.partial_sigs); - self.bip32_derivation.extend(other.bip32_derivation); - self.ripemd160_preimages.extend(other.ripemd160_preimages); - self.sha256_preimages.extend(other.sha256_preimages); - self.hash160_preimages.extend(other.hash160_preimages); - self.hash256_preimages.extend(other.hash256_preimages); - self.tap_script_sigs.extend(other.tap_script_sigs); - self.tap_scripts.extend(other.tap_scripts); - self.tap_key_origins.extend(other.tap_key_origins); - self.proprietary.extend(other.proprietary); - self.unknown.extend(other.unknown); - - combine!(redeem_script, self, other); - combine!(witness_script, self, other); - combine!(final_script_sig, self, other); - combine!(final_script_witness, self, other); - combine!(tap_key_sig, self, other); - combine!(tap_internal_key, self, other); - combine!(tap_merkle_root, self, other); - } -} - -impl Map for Input { - fn get_pairs(&self) -> Vec { - let mut rv: Vec = Default::default(); - - impl_psbt_get_pair! { - rv.push(self.non_witness_utxo, PSBT_IN_NON_WITNESS_UTXO) - } - - impl_psbt_get_pair! { - rv.push(self.witness_utxo, PSBT_IN_WITNESS_UTXO) - } - - impl_psbt_get_pair! { - rv.push_map(self.partial_sigs, PSBT_IN_PARTIAL_SIG) - } - - impl_psbt_get_pair! { - rv.push(self.sighash_type, PSBT_IN_SIGHASH_TYPE) - } - - impl_psbt_get_pair! { - rv.push(self.redeem_script, PSBT_IN_REDEEM_SCRIPT) - } - - impl_psbt_get_pair! { - rv.push(self.witness_script, PSBT_IN_WITNESS_SCRIPT) - } - - impl_psbt_get_pair! { - rv.push_map(self.bip32_derivation, PSBT_IN_BIP32_DERIVATION) - } - - impl_psbt_get_pair! { - rv.push(self.final_script_sig, PSBT_IN_FINAL_SCRIPTSIG) - } - - impl_psbt_get_pair! { - rv.push(self.final_script_witness, PSBT_IN_FINAL_SCRIPTWITNESS) - } - - impl_psbt_get_pair! { - rv.push_map(self.ripemd160_preimages, PSBT_IN_RIPEMD160) - } - - impl_psbt_get_pair! { - rv.push_map(self.sha256_preimages, PSBT_IN_SHA256) - } - - impl_psbt_get_pair! { - rv.push_map(self.hash160_preimages, PSBT_IN_HASH160) - } - - impl_psbt_get_pair! { - rv.push_map(self.hash256_preimages, PSBT_IN_HASH256) - } - - impl_psbt_get_pair! { - rv.push(self.tap_key_sig, PSBT_IN_TAP_KEY_SIG) - } - - impl_psbt_get_pair! { - rv.push_map(self.tap_script_sigs, PSBT_IN_TAP_SCRIPT_SIG) - } - - impl_psbt_get_pair! { - rv.push_map(self.tap_scripts, PSBT_IN_TAP_LEAF_SCRIPT) - } - - impl_psbt_get_pair! { - rv.push_map(self.tap_key_origins, PSBT_IN_TAP_BIP32_DERIVATION) - } - - impl_psbt_get_pair! { - rv.push(self.tap_internal_key, PSBT_IN_TAP_INTERNAL_KEY) - } - - impl_psbt_get_pair! { - 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() }); - } - - for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { key: key.clone(), value: value.clone() }); - } - - rv - } -} - -impl_psbtmap_ser_de_serialize!(Input); - -fn psbt_insert_hash_pair( - map: &mut BTreeMap>, - raw_key: raw::Key, - raw_value: Vec, - hash_type: error::PsbtHash, -) -> Result<(), Error> -where - H: hashes::Hash + Deserialize, -{ - if raw_key.key.is_empty() { - return Err(psbt::Error::InvalidKey(raw_key)); - } - let key_val: H = Deserialize::deserialize(&raw_key.key)?; - match map.entry(key_val) { - btree_map::Entry::Vacant(empty_key) => { - let val: Vec = Deserialize::deserialize(&raw_value)?; - if ::hash(&val) != key_val { - return Err(psbt::Error::InvalidPreimageHashPair { - preimage: val.into_boxed_slice(), - hash: Box::from(key_val.borrow()), - hash_type, - }); - } - empty_key.insert(val); - Ok(()) - } - btree_map::Entry::Occupied(_) => Err(psbt::Error::DuplicateKey(raw_key)), - } -} - -#[cfg(test)] -mod test { - use super::*; - - #[test] - fn psbt_sighash_type_ecdsa() { - for ecdsa in &[ - EcdsaSighashType::All, - EcdsaSighashType::None, - EcdsaSighashType::Single, - EcdsaSighashType::AllPlusAnyoneCanPay, - EcdsaSighashType::NonePlusAnyoneCanPay, - EcdsaSighashType::SinglePlusAnyoneCanPay, - ] { - let sighash = PsbtSighashType::from(*ecdsa); - let s = format!("{}", sighash); - let back = PsbtSighashType::from_str(&s).unwrap(); - assert_eq!(back, sighash); - assert_eq!(back.ecdsa_hash_ty().unwrap(), *ecdsa); - } - } - - #[test] - fn psbt_sighash_type_taproot() { - for tap in &[ - TapSighashType::Default, - TapSighashType::All, - TapSighashType::None, - TapSighashType::Single, - TapSighashType::AllPlusAnyoneCanPay, - TapSighashType::NonePlusAnyoneCanPay, - TapSighashType::SinglePlusAnyoneCanPay, - ] { - let sighash = PsbtSighashType::from(*tap); - let s = format!("{}", sighash); - let back = PsbtSighashType::from_str(&s).unwrap(); - assert_eq!(back, sighash); - assert_eq!(back.taproot_hash_ty().unwrap(), *tap); - } - } - - #[test] - fn psbt_sighash_type_notstd() { - let nonstd = 0xdddddddd; - let sighash = PsbtSighashType { inner: nonstd }; - let s = format!("{}", sighash); - let back = PsbtSighashType::from_str(&s).unwrap(); - - assert_eq!(back, sighash); - assert_eq!(back.ecdsa_hash_ty(), Err(NonStandardSighashTypeError(nonstd))); - assert_eq!(back.taproot_hash_ty(), Err(InvalidSighashTypeError(nonstd))); - } -} diff --git a/src/v0/miniscript/map/mod.rs b/src/v0/miniscript/map/mod.rs deleted file mode 100644 index 6fa03e8..0000000 --- a/src/v0/miniscript/map/mod.rs +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -use miniscript::prelude::*; -use miniscript::psbt::raw; - -mod global; -mod input; -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. -pub(super) trait Map { - /// Attempt to get all key-value pairs. - fn get_pairs(&self) -> Vec; - - /// Serialize Psbt binary map data according to BIP-174 specification. - /// - /// := * 0x00 - /// - /// Why is the separator here 0x00 instead of 0xff? The separator here is used to distinguish between each chunk of data. - /// A separator of 0x00 would mean that the unserializer can read it as a key length of 0, which would never occur with - /// actual keys. It can thus be used as a separator and allow for easier unserializer implementation. - fn serialize_map(&self) -> Vec { - let mut buf = Vec::new(); - for pair in Map::get_pairs(self) { - buf.extend(&pair.serialize()); - } - buf.push(0x00_u8); - buf - } -} diff --git a/src/v0/miniscript/map/output.rs b/src/v0/miniscript/map/output.rs deleted file mode 100644 index b9bbdd9..0000000 --- a/src/v0/miniscript/map/output.rs +++ /dev/null @@ -1,168 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -use core::convert::TryFrom; - -use bitcoin::secp256k1::XOnlyPublicKey; -use {core, secp256k1}; - -use miniscript::bip32::KeySource; -use miniscript::blockdata::script::ScriptBuf; -use miniscript::prelude::*; -use miniscript::psbt::map::Map; -use miniscript::psbt::{raw, Error}; -use miniscript::taproot::{TapLeafHash, TapTree}; - -/// Type: Redeem ScriptBuf PSBT_OUT_REDEEM_SCRIPT = 0x00 -const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00; -/// Type: Witness ScriptBuf PSBT_OUT_WITNESS_SCRIPT = 0x01 -const PSBT_OUT_WITNESS_SCRIPT: u8 = 0x01; -/// Type: BIP 32 Derivation Path PSBT_OUT_BIP32_DERIVATION = 0x02 -const PSBT_OUT_BIP32_DERIVATION: u8 = 0x02; -/// Type: Taproot Internal Key PSBT_OUT_TAP_INTERNAL_KEY = 0x05 -const PSBT_OUT_TAP_INTERNAL_KEY: u8 = 0x05; -/// Type: Taproot Tree PSBT_OUT_TAP_TREE = 0x06 -const PSBT_OUT_TAP_TREE: u8 = 0x06; -/// Type: Taproot Key BIP 32 Derivation Path PSBT_OUT_TAP_BIP32_DERIVATION = 0x07 -const PSBT_OUT_TAP_BIP32_DERIVATION: u8 = 0x07; -/// Type: Proprietary Use Type PSBT_IN_PROPRIETARY = 0xFC -const PSBT_OUT_PROPRIETARY: u8 = 0xFC; - -/// A key-value map for an output of the corresponding index in the unsigned -/// transaction. -#[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct Output { - /// The redeem script for this output. - pub redeem_script: Option, - /// The witness script for this output. - pub witness_script: Option, - /// A map from public keys needed to spend this output to their - /// corresponding master key fingerprints and derivation paths. - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] - pub bip32_derivation: BTreeMap, - /// The internal pubkey. - pub tap_internal_key: Option, - /// Taproot Output tree. - pub tap_tree: Option, - /// Map of tap root x only keys to origin info and leaf hashes contained in it. - #[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"))] - pub proprietary: BTreeMap>, - /// Unknown key-value pairs for this output. - #[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; - - match raw_key.type_value { - PSBT_OUT_REDEEM_SCRIPT => { - impl_psbt_insert_pair! { - self.redeem_script <= | - } - } - PSBT_OUT_WITNESS_SCRIPT => { - impl_psbt_insert_pair! { - self.witness_script <= | - } - } - PSBT_OUT_BIP32_DERIVATION => { - impl_psbt_insert_pair! { - self.bip32_derivation <= | - } - } - PSBT_OUT_PROPRIETARY => { - let key = raw::ProprietaryKey::try_from(raw_key.clone())?; - 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)), - } - } - PSBT_OUT_TAP_INTERNAL_KEY => { - impl_psbt_insert_pair! { - self.tap_internal_key <= | - } - } - PSBT_OUT_TAP_TREE => { - impl_psbt_insert_pair! { - self.tap_tree <= | - } - } - PSBT_OUT_TAP_BIP32_DERIVATION => { - impl_psbt_insert_pair! { - self.tap_key_origins <= |< raw_value: (Vec, KeySource)> - } - } - _ => match self.unknown.entry(raw_key) { - btree_map::Entry::Vacant(empty_key) => { - empty_key.insert(raw_value); - } - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), - }, - } - - Ok(()) - } - - /// Combines this [`Output`] with `other` `Output` (as described by BIP 174). - pub fn combine(&mut self, other: Self) { - self.bip32_derivation.extend(other.bip32_derivation); - self.proprietary.extend(other.proprietary); - self.unknown.extend(other.unknown); - self.tap_key_origins.extend(other.tap_key_origins); - - combine!(redeem_script, self, other); - combine!(witness_script, self, other); - combine!(tap_internal_key, self, other); - combine!(tap_tree, self, other); - } -} - -impl Map for Output { - fn get_pairs(&self) -> Vec { - let mut rv: Vec = Default::default(); - - impl_psbt_get_pair! { - rv.push(self.redeem_script, PSBT_OUT_REDEEM_SCRIPT) - } - - impl_psbt_get_pair! { - rv.push(self.witness_script, PSBT_OUT_WITNESS_SCRIPT) - } - - impl_psbt_get_pair! { - rv.push_map(self.bip32_derivation, PSBT_OUT_BIP32_DERIVATION) - } - - impl_psbt_get_pair! { - rv.push(self.tap_internal_key, PSBT_OUT_TAP_INTERNAL_KEY) - } - - impl_psbt_get_pair! { - rv.push(self.tap_tree, PSBT_OUT_TAP_TREE) - } - - impl_psbt_get_pair! { - rv.push_map(self.tap_key_origins, PSBT_OUT_TAP_BIP32_DERIVATION) - } - - for (key, value) in self.proprietary.iter() { - 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 - } -} - -impl_psbtmap_ser_de_serialize!(Output); diff --git a/src/v0/miniscript/raw.rs b/src/v0/miniscript/raw.rs deleted file mode 100644 index b23dedd..0000000 --- a/src/v0/miniscript/raw.rs +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -//! Raw PSBT key-value pairs. -//! -//! Raw PSBT key-value pairs as defined at -//! . -//! - -use core::convert::TryFrom; -use core::fmt; - -use super::serialize::{Deserialize, Serialize}; -use miniscript::consensus::encode::{ - self, deserialize, serialize, Decodable, Encodable, ReadExt, VarInt, WriteExt, MAX_VEC_SIZE, -}; -use miniscript::io; -use miniscript::prelude::*; -use miniscript::psbt::Error; - -/// A PSBT key in its raw byte form. -#[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct Key { - /// The type of this PSBT key. - pub type_value: u8, - /// The key itself in raw byte form. - /// ` := ` - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))] - pub key: Vec, -} - -/// A PSBT key-value pair in its raw byte form. -/// ` := ` -#[derive(Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct Pair { - /// The key of this key-value pair. - pub key: Key, - /// The value data of this key-value pair in raw byte form. - /// ` := ` - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))] - pub value: Vec, -} - -/// Default implementation for proprietary key subtyping -pub type ProprietaryType = u8; - -/// Proprietary keys (i.e. keys starting with 0xFC byte) with their internal -/// structure according to BIP 174. -#[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, -{ - /// 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"))] - pub prefix: Vec, - /// Custom proprietary subtype - pub subtype: Subtype, - /// Additional key bytes (like serialized public key data etc) - #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))] - pub key: Vec, -} - -impl fmt::Display for Key { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "type: {:#x}, key: {:x}", self.type_value, self.key.as_hex()) - } -} - -impl Key { - pub(crate) fn decode(r: &mut R) -> Result { - let VarInt(byte_size): VarInt = Decodable::consensus_decode(r)?; - - if byte_size == 0 { - return Err(Error::NoMorePairs); - } - - let key_byte_size: u64 = byte_size - 1; - - if key_byte_size > MAX_VEC_SIZE as u64 { - return Err(encode::Error::OversizedVectorAllocation { - requested: key_byte_size as usize, - max: MAX_VEC_SIZE, - } - .into()); - } - - let type_value: u8 = Decodable::consensus_decode(r)?; - - let mut key = Vec::with_capacity(key_byte_size as usize); - for _ in 0..key_byte_size { - key.push(Decodable::consensus_decode(r)?); - } - - Ok(Key { type_value, key }) - } -} - -impl Serialize for Key { - fn serialize(&self) -> Vec { - let mut buf = Vec::new(); - VarInt::from(self.key.len() + 1) - .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"); - - for key in &self.key { - key.consensus_encode(&mut buf).expect("in-memory writers don't error"); - } - - buf - } -} - -impl Serialize for Pair { - fn serialize(&self) -> Vec { - let mut buf = Vec::new(); - buf.extend(self.key.serialize()); - // := - self.value.consensus_encode(&mut buf).unwrap(); - buf - } -} - -impl Deserialize for Pair { - fn deserialize(bytes: &[u8]) -> Result { - let mut decoder = bytes; - Pair::decode(&mut decoder) - } -} - -impl Pair { - pub(crate) fn decode(r: &mut R) -> Result { - Ok(Pair { key: Key::decode(r)?, value: Decodable::consensus_decode(r)? }) - } -} - -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())?; - w.write_all(&self.key)?; - len += self.key.len(); - Ok(len) - } -} - -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()?); - let key = read_to_end(r)?; - - Ok(ProprietaryKey { prefix, subtype, key }) - } -} - -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) } } -} - -impl TryFrom for ProprietaryKey -where - Subtype: Copy + From + Into, -{ - type Error = Error; - - /// Constructs a [`ProprietaryKey`] from a [`Key`]. - /// - /// # Errors - /// 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); - } - - Ok(deserialize(&key.key)?) - } -} - -// core2 doesn't have read_to_end -pub(crate) fn read_to_end(mut d: D) -> Result, io::Error> { - let mut result = vec![]; - let mut buf = [0u8; 64]; - loop { - 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(e) => return Err(e), - }; - } - Ok(result) -} diff --git a/src/v0/miniscript/serialize.rs b/src/v0/miniscript/serialize.rs deleted file mode 100644 index b4476ba..0000000 --- a/src/v0/miniscript/serialize.rs +++ /dev/null @@ -1,453 +0,0 @@ -// SPDX-License-Identifier: CC0-1.0 - -//! PSBT serialization. -//! -//! Traits to serialize PSBT values to and from raw bytes -//! according to the BIP-174 specification. -//! - -use core::convert::{TryFrom, TryInto}; - -use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; -use bitcoin::secp256k1::{self, XOnlyPublicKey}; - -use super::map::{Input, Map, Output, PsbtSighashType}; -use miniscript::bip32::{ChildNumber, Fingerprint, KeySource}; -use miniscript::blockdata::script::ScriptBuf; -use miniscript::blockdata::transaction::{Transaction, TxOut}; -use miniscript::blockdata::witness::Witness; -use miniscript::consensus::encode::{self, deserialize_partial, serialize, Decodable, Encodable}; -use miniscript::crypto::key::PublicKey; -use miniscript::crypto::{ecdsa, taproot}; -use miniscript::prelude::*; -use miniscript::psbt::{Error, Psbt}; -use miniscript::taproot::{ - ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder, -}; -use miniscript::{io, VarInt}; -/// A trait for serializing a value as raw data for insertion into PSBT -/// key-value maps. -pub(crate) trait Serialize { - /// Serialize a value as raw data. - fn serialize(&self) -> Vec; -} - -/// A trait for deserializing a value from raw data in PSBT key-value maps. -pub(crate) trait Deserialize: Sized { - /// Deserialize a value from raw data. - fn deserialize(bytes: &[u8]) -> Result; -} - -impl Psbt { - /// Serialize a value as bytes in hex. - pub fn serialize_hex(&self) -> String { self.serialize().to_lower_hex_string() } - - /// Serialize as raw binary data - pub fn serialize(&self) -> Vec { - let mut buf: Vec = Vec::new(); - - // - buf.extend_from_slice(b"psbt"); - - buf.push(0xff_u8); - - buf.extend(self.serialize_map()); - - for i in &self.inputs { - buf.extend(i.serialize_map()); - } - - for i in &self.outputs { - buf.extend(i.serialize_map()); - } - - buf - } - - /// Deserialize a value from raw binary data. - pub fn deserialize(bytes: &[u8]) -> Result { - const MAGIC_BYTES: &[u8] = b"psbt"; - if bytes.get(0..MAGIC_BYTES.len()) != Some(MAGIC_BYTES) { - return Err(Error::InvalidMagic); - } - - const PSBT_SERPARATOR: u8 = 0xff_u8; - if bytes.get(MAGIC_BYTES.len()) != Some(&PSBT_SERPARATOR) { - return Err(Error::InvalidSeparator); - } - - let mut d = bytes.get(5..).ok_or(Error::NoMorePairs)?; - - let mut global = Psbt::decode_global(&mut d)?; - global.unsigned_tx_checks()?; - - let inputs: Vec = { - let inputs_len: usize = (global.unsigned_tx.input).len(); - - let mut inputs: Vec = Vec::with_capacity(inputs_len); - - for _ in 0..inputs_len { - inputs.push(Input::decode(&mut d)?); - } - - inputs - }; - - let outputs: Vec = { - let outputs_len: usize = (global.unsigned_tx.output).len(); - - let mut outputs: Vec = Vec::with_capacity(outputs_len); - - for _ in 0..outputs_len { - outputs.push(Output::decode(&mut d)?); - } - - outputs - }; - - global.inputs = inputs; - global.outputs = outputs; - Ok(global) - } -} -impl_psbt_de_serialize!(Transaction); -impl_psbt_de_serialize!(TxOut); -impl_psbt_de_serialize!(Witness); -impl_psbt_hash_de_serialize!(ripemd160::Hash); -impl_psbt_hash_de_serialize!(sha256::Hash); -impl_psbt_hash_de_serialize!(TapLeafHash); -impl_psbt_hash_de_serialize!(TapNodeHash); -impl_psbt_hash_de_serialize!(hash160::Hash); -impl_psbt_hash_de_serialize!(sha256d::Hash); - -// taproot -impl_psbt_de_serialize!(Vec); - -impl Serialize for ScriptBuf { - fn serialize(&self) -> Vec { self.to_bytes() } -} - -impl Deserialize for ScriptBuf { - fn deserialize(bytes: &[u8]) -> Result { Ok(Self::from(bytes.to_vec())) } -} - -impl Serialize for PublicKey { - fn serialize(&self) -> Vec { - let mut buf = Vec::new(); - self.write_into(&mut buf).expect("vecs don't error"); - buf - } -} - -impl Deserialize for PublicKey { - fn deserialize(bytes: &[u8]) -> Result { - PublicKey::from_slice(bytes).map_err(Error::InvalidPublicKey) - } -} - -impl Serialize for secp256k1::PublicKey { - 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) - } -} - -impl Serialize for ecdsa::Signature { - fn serialize(&self) -> Vec { self.to_vec() } -} - -impl Deserialize for ecdsa::Signature { - fn deserialize(bytes: &[u8]) -> Result { - // NB: Since BIP-174 says "the signature as would be pushed to the stack from - // a scriptSig or witness" we should ideally use a consensus deserialization and do - // not error on a non-standard values. However, - // - // 1) the current implementation of from_u32_consensus(`flag`) does not preserve - // the sighash byte `flag` mapping all unknown values to EcdsaSighashType::All or - // EcdsaSighashType::AllPlusAnyOneCanPay. Therefore, break the invariant - // EcdsaSig::from_slice(&sl[..]).to_vec = sl. - // - // 2) This would cause to have invalid signatures because the sighash message - // 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::SighashType(err) => Error::NonStandardSighashType(err.0), - ecdsa::Error::Secp256k1(..) => Error::InvalidEcdsaSignature(e), - ecdsa::Error::Hex(..) => unreachable!("Decoding from slice, not hex"), - }) - } -} - -impl Serialize for KeySource { - fn serialize(&self) -> Vec { - let mut rv: Vec = Vec::with_capacity(key_source_len(self)); - - rv.append(&mut self.0.to_bytes().to_vec()); - - for cnum in self.1.into_iter() { - rv.append(&mut serialize(&u32::from(*cnum))) - } - - rv - } -} - -impl Deserialize for KeySource { - fn deserialize(bytes: &[u8]) -> Result { - if bytes.len() < 4 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); - } - - let fprint: Fingerprint = bytes[0..4].try_into().expect("4 is the fingerprint length"); - let mut dpath: Vec = Default::default(); - - let mut d = &bytes[4..]; - while !d.is_empty() { - match u32::consensus_decode(&mut d) { - Ok(index) => dpath.push(index.into()), - Err(e) => return Err(e.into()), - } - } - - Ok((fprint, dpath.into())) - } -} - -// partial sigs -impl Serialize for Vec { - fn serialize(&self) -> Vec { self.clone() } -} - -impl Deserialize for Vec { - fn deserialize(bytes: &[u8]) -> Result { Ok(bytes.to_vec()) } -} - -impl Serialize for PsbtSighashType { - fn serialize(&self) -> Vec { serialize(&self.to_u32()) } -} - -impl Deserialize for PsbtSighashType { - fn deserialize(bytes: &[u8]) -> Result { - let raw: u32 = encode::deserialize(bytes)?; - Ok(PsbtSighashType { inner: raw }) - } -} - -// Taproot related ser/deser -impl Serialize for XOnlyPublicKey { - 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) - } -} - -impl Serialize for taproot::Signature { - fn serialize(&self) -> Vec { self.to_vec() } -} - -impl Deserialize for taproot::Signature { - fn deserialize(bytes: &[u8]) -> Result { - use taproot::SigFromSliceError::*; - - taproot::Signature::from_slice(bytes).map_err(|e| match e { - SighashType(err) => Error::NonStandardSighashType(err.0), - InvalidSignatureSize(_) => Error::InvalidTaprootSignature(e), - Secp256k1(..) => Error::InvalidTaprootSignature(e), - }) - } -} - -impl Serialize for (XOnlyPublicKey, TapLeafHash) { - fn serialize(&self) -> Vec { - let ser_pk = self.0.serialize(); - let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_byte_array().len()); - buf.extend(&ser_pk); - buf.extend(self.1.as_byte_array()); - buf - } -} - -impl Deserialize for (XOnlyPublicKey, TapLeafHash) { - fn deserialize(bytes: &[u8]) -> Result { - if bytes.len() < 32 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); - } - let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?; - let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?; - Ok((a, b)) - } -} - -impl Serialize for ControlBlock { - fn serialize(&self) -> Vec { ControlBlock::serialize(self) } -} - -impl Deserialize for ControlBlock { - fn deserialize(bytes: &[u8]) -> Result { - Self::decode(bytes).map_err(|_| Error::InvalidControlBlock) - } -} - -// Versioned ScriptBuf -impl Serialize for (ScriptBuf, LeafVersion) { - fn serialize(&self) -> Vec { - let mut buf = Vec::with_capacity(self.0.len() + 1); - buf.extend(self.0.as_bytes()); - buf.push(self.1.to_consensus()); - buf - } -} - -impl Deserialize for (ScriptBuf, LeafVersion) { - fn deserialize(bytes: &[u8]) -> Result { - if bytes.is_empty() { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); - } - // The last byte is LeafVersion. - let script = ScriptBuf::deserialize(&bytes[..bytes.len() - 1])?; - let leaf_ver = LeafVersion::from_consensus(bytes[bytes.len() - 1]) - .map_err(|_| Error::InvalidLeafVersion)?; - Ok((script, leaf_ver)) - } -} - -impl Serialize for (Vec, KeySource) { - fn serialize(&self) -> Vec { - 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()); - buf - } -} - -impl Deserialize for (Vec, KeySource) { - fn deserialize(bytes: &[u8]) -> Result { - let (leafhash_vec, consumed) = deserialize_partial::>(bytes)?; - let key_source = KeySource::deserialize(&bytes[consumed..])?; - Ok((leafhash_vec, key_source)) - } -} - -impl Serialize for TapTree { - fn serialize(&self) -> Vec { - let capacity = self - .script_leaves() - .map(|l| { - l.script().len() + VarInt::from(l.script().len()).size() // script version - + 1 // merkle branch - + 1 // leaf version - }) - .sum::(); - let mut buf = Vec::with_capacity(capacity); - for leaf_info in self.script_leaves() { - // # Cast Safety: - // - // TaprootMerkleBranch can only have len atmost 128(TAPROOT_CONTROL_MAX_NODE_COUNT). - // safe to cast from usize to u8 - buf.push(leaf_info.merkle_branch().len() as u8); - buf.push(leaf_info.version().to_consensus()); - leaf_info.script().consensus_encode(&mut buf).expect("Vecs dont err"); - } - buf - } -} - -impl Deserialize for TapTree { - fn deserialize(bytes: &[u8]) -> Result { - let mut builder = TaprootBuilder::new(); - let mut bytes_iter = bytes.iter(); - while let Some(depth) = bytes_iter.next() { - let version = bytes_iter.next().ok_or(Error::Taproot("Invalid Taproot Builder"))?; - let (script, consumed) = deserialize_partial::(bytes_iter.as_slice())?; - 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) - .map_err(|_| Error::Taproot("Tree not in DFS order"))?; - } - TapTree::try_from(builder).map_err(Error::TapTree) - } -} - -// Helper function to compute key source len -fn key_source_len(key_source: &KeySource) -> usize { 4 + 4 * (key_source.1).as_ref().len() } - -#[cfg(test)] -mod tests { - use core::convert::TryFrom; - - use super::*; - - // 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 { - let mut val = opcode; - let mut builder = TaprootBuilder::new(); - for depth in depth_map { - let script = ScriptBuf::from_hex(&format!("{:02x}", val)).unwrap(); - builder = builder.add_leaf(*depth, script).unwrap(); - let (new_val, _) = val.overflowing_add(1); - val = new_val; - } - builder - } - - #[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_hidden_node(3, TapNodeHash::all_zeros()).unwrap(); - assert!(TapTree::try_from(builder).is_err()); - } - - #[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(); - let tree = TapTree::try_from(builder).unwrap(); - let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap(); - assert_eq!(tree, tree_prime); - } - - #[test] - fn can_deserialize_non_standard_psbt_sighash_type() { - let non_standard_sighash = [222u8, 0u8, 0u8, 0u8]; // 32 byte value. - let sighash = PsbtSighashType::deserialize(&non_standard_sighash); - assert!(sighash.is_ok()) - } - - #[test] - #[should_panic(expected = "InvalidMagic")] - fn invalid_vector_1() { - let hex_psbt = b"0200000001268171371edff285e937adeea4b37b78000c0566cbb3ad64641713ca42171bf6000000006a473044022070b2245123e6bf474d60c5b50c043d4c691a5d2435f09a34a7662a9dc251790a022001329ca9dacf280bdf30740ec0390422422c81cb45839457aeb76fc12edd95b3012102657d118d3357b8e0f4c2cd46db7b39f6d9c38d9a70abcb9b2de5dc8dbfe4ce31feffffff02d3dff505000000001976a914d0c59903c5bac2868760e90fd521a4665aa7652088ac00e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787b32e1300"; - Psbt::deserialize(hex_psbt).unwrap(); - } -}