From c7478d8fd05b917497bbfccda2fbc5b289cd489a Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Thu, 28 Oct 2021 00:43:02 -0700 Subject: [PATCH 1/4] Derive serde for taproot stuctures --- src/util/schnorr.rs | 1 + src/util/sighash.rs | 1 + src/util/taproot.rs | 10 ++++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/util/schnorr.rs b/src/util/schnorr.rs index 10455524..38c40e6a 100644 --- a/src/util/schnorr.rs +++ b/src/util/schnorr.rs @@ -110,6 +110,7 @@ impl TweakedPublicKey { /// A BIP340-341 serialized schnorr signature with the corresponding hash type. #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct SchnorrSig { /// The underlying schnorr signature pub sig: secp256k1::schnorrsig::Signature, diff --git a/src/util/sighash.rs b/src/util/sighash.rs index 10e333ee..2076c9ca 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -104,6 +104,7 @@ pub struct ScriptPath<'s> { /// Hashtype of an input's signature, encoded in the last byte of the signature /// Fixed values so they can be casted as integer types for encoding #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum SchnorrSigHashType { /// 0x0: Used when not explicitly specified, defaulting to [`SchnorrSigHashType::All`] Default = 0x00, diff --git a/src/util/taproot.rs b/src/util/taproot.rs index 57ebd938..1a824dfc 100644 --- a/src/util/taproot.rs +++ b/src/util/taproot.rs @@ -345,6 +345,7 @@ impl TaprootSpendInfo { /// branches in a DFS(Depth first search) walk to construct this tree. // Similar to Taproot Builder in bitcoin core #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TaprootBuilder { // The following doc-comment is from bitcoin core, but modified for rust // The comment below describes the current state of the builder for a given tree. @@ -484,7 +485,8 @@ impl TaprootBuilder { // Internally used structure to represent the node information in taproot tree #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -struct NodeInfo { +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub(crate) struct NodeInfo { /// Merkle Hash for this node hash: sha256::Hash, /// information about leaves inside this node @@ -537,7 +539,8 @@ impl NodeInfo { // Internally used structure to store information about taproot leaf node #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] -struct LeafInfo { +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub(crate) struct LeafInfo { // The underlying script script: Script, // The leaf version @@ -567,6 +570,7 @@ impl LeafInfo { // The type of hash is sha256::Hash because the vector might contain // both TapBranchHash and TapLeafHash #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TaprootMerkleBranch(Vec); impl TaprootMerkleBranch { @@ -638,6 +642,7 @@ impl TaprootMerkleBranch { /// Control Block data structure used in Tapscript satisfaction #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ControlBlock { /// The tapleaf version, pub leaf_version: LeafVersion, @@ -744,6 +749,7 @@ impl ControlBlock { /// The leaf version for tapleafs #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct LeafVersion(u8); impl Default for LeafVersion { From 108fc3d4dbfa36531016d2357f9ab5914bb4b2d1 Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Wed, 27 Oct 2021 03:17:19 -0700 Subject: [PATCH 2/4] Impl encodable traits for TapLeafhash --- src/consensus/encode.rs | 14 ++++++++++++++ src/util/taproot.rs | 1 + 2 files changed, 15 insertions(+) diff --git a/src/consensus/encode.rs b/src/consensus/encode.rs index eea64036..ec2aa198 100644 --- a/src/consensus/encode.rs +++ b/src/consensus/encode.rs @@ -39,6 +39,7 @@ use io::{self, Cursor, Read}; use util::endian; use util::psbt; +use util::taproot::TapLeafHash; use hashes::hex::ToHex; use blockdata::transaction::{TxOut, Transaction, TxIn}; @@ -594,6 +595,7 @@ impl_vec!(TxOut); impl_vec!(TxIn); impl_vec!(Vec); impl_vec!(u64); +impl_vec!(TapLeafHash); #[cfg(feature = "std")] impl_vec!(Inventory); #[cfg(feature = "std")] impl_vec!((u32, Address)); @@ -767,6 +769,18 @@ impl Decodable for sha256::Hash { } } +impl Encodable for TapLeafHash { + fn consensus_encode(&self, s: S) -> Result { + self.into_inner().consensus_encode(s) + } +} + +impl Decodable for TapLeafHash { + fn consensus_decode(d: D) -> Result { + Ok(Self::from_inner(<::Inner>::consensus_decode(d)?)) + } +} + // Tests #[cfg(test)] mod tests { diff --git a/src/util/taproot.rs b/src/util/taproot.rs index 1a824dfc..ad1baa62 100644 --- a/src/util/taproot.rs +++ b/src/util/taproot.rs @@ -68,6 +68,7 @@ macro_rules! sha256t_hash_newtype { #[doc = "The tag used for ["] #[doc = $sname] #[doc = "]"] + #[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)] pub struct $tag; impl sha256t::Tag for $tag { From d22e0149ad7cd3bf61071c4c0b92acb48ada44cd Mon Sep 17 00:00:00 2001 From: sanket1729 Date: Wed, 27 Oct 2021 03:20:21 -0700 Subject: [PATCH 3/4] Taproot psbt impl BIP 371 --- src/util/psbt/map/input.rs | 90 ++++++++++++++++++ src/util/psbt/map/mod.rs | 1 + src/util/psbt/map/output.rs | 109 ++++++++++++++++++++- src/util/psbt/mod.rs | 2 +- src/util/psbt/serialize.rs | 182 +++++++++++++++++++++++++++++++++++- src/util/taproot.rs | 19 +++- 6 files changed, 390 insertions(+), 13 deletions(-) diff --git a/src/util/psbt/map/input.rs b/src/util/psbt/map/input.rs index e6481b4e..a443f402 100644 --- a/src/util/psbt/map/input.rs +++ b/src/util/psbt/map/input.rs @@ -28,6 +28,9 @@ use util::psbt::raw; use util::psbt::serialize::Deserialize; use util::psbt::{Error, error}; +use schnorr; +use util::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapBranchHash}; + /// 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 @@ -54,6 +57,18 @@ const PSBT_IN_SHA256: u8 = 0x0b; const PSBT_IN_HASH160: u8 = 0x0c; /// Type: HASH256 preimage PSBT_IN_HASH256 = 0x0d const PSBT_IN_HASH256: u8 = 0x0d; +/// Type: Schnorr Signature in Key Spend PSBT_IN_TAP_KEY_SIG = 0x13 +const PSBT_IN_TAP_KEY_SIG: u8 = 0x13; +/// Type: Schnorr 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; @@ -104,6 +119,21 @@ pub struct Input { /// HAS256 hash to preimage map #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_byte_values"))] pub hash256_preimages: BTreeMap>, + /// Serialized schnorr signature with sighash type for key spend + pub tap_key_sig: Option, + /// Map of | with signature + #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq"))] + pub tap_script_sigs: BTreeMap<(schnorr::PublicKey, TapLeafHash), schnorr::SchnorrSig>, + /// Map of Control blocks to Script version pair + #[cfg_attr(feature = "serde", serde(with = "::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 = "::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 = "::serde_utils::btreemap_as_seq_byte_values"))] pub proprietary: BTreeMap>, @@ -177,6 +207,36 @@ impl Map for Input { 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: (Script, 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: schnorr::PublicKey> + } + } + PSBT_IN_TAP_MERKLE_ROOT => { + impl_psbt_insert_pair! { + self.tap_merkle_root <= |< raw_value: TapBranchHash> + } + } PSBT_IN_PROPRIETARY => match self.proprietary.entry(raw::ProprietaryKey::from_key(raw_key.clone())?) { btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);}, btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()), @@ -249,6 +309,30 @@ impl Map for Input { rv.push(self.hash256_preimages as |>) } + impl_psbt_get_pair! { + rv.push(self.tap_key_sig as |>) + } + + impl_psbt_get_pair! { + rv.push(self.tap_script_sigs as |>) + } + + impl_psbt_get_pair! { + rv.push(self.tap_scripts as |<(Script, LeafVersion)>) + } + + impl_psbt_get_pair! { + rv.push(self.tap_key_origins as |<(Vec, KeySource)>) + } + + impl_psbt_get_pair! { + rv.push(self.tap_internal_key as |) + } + + impl_psbt_get_pair! { + rv.push(self.tap_merkle_root as |) + } for (key, value) in self.proprietary.iter() { rv.push(raw::Pair { key: key.to_key(), @@ -280,6 +364,9 @@ impl Map for Input { 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); @@ -287,6 +374,9 @@ impl Map for Input { merge!(witness_script, self, other); merge!(final_script_sig, self, other); merge!(final_script_witness, self, other); + merge!(tap_key_sig, self, other); + merge!(tap_internal_key, self, other); + merge!(tap_merkle_root, self, other); Ok(()) } diff --git a/src/util/psbt/map/mod.rs b/src/util/psbt/map/mod.rs index 94506bc5..a40de9d2 100644 --- a/src/util/psbt/map/mod.rs +++ b/src/util/psbt/map/mod.rs @@ -55,3 +55,4 @@ mod output; pub use self::input::Input; pub use self::output::Output; +pub use self::output::TapTree; diff --git a/src/util/psbt/map/output.rs b/src/util/psbt/map/output.rs index 119f8c61..75e764c6 100644 --- a/src/util/psbt/map/output.rs +++ b/src/util/psbt/map/output.rs @@ -25,12 +25,23 @@ use util::psbt::map::Map; use util::psbt::raw; use util::psbt::Error; +use schnorr; +use util::taproot::TapLeafHash; + +use util::taproot::{NodeInfo, TaprootBuilder}; + /// Type: Redeem Script PSBT_OUT_REDEEM_SCRIPT = 0x00 const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00; /// Type: Witness Script 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; @@ -47,14 +58,67 @@ pub struct Output { /// corresponding master key fingerprints and derivation paths. #[cfg_attr(feature = "serde", serde(with = "::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 = "::serde_utils::btreemap_as_seq"))] + pub tap_key_origins: BTreeMap, KeySource)>, /// Proprietary key-value pairs for this output. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))] + #[cfg_attr( + feature = "serde", + serde(with = "::serde_utils::btreemap_as_seq_byte_values") + )] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this output. - #[cfg_attr(feature = "serde", serde(with = "::serde_utils::btreemap_as_seq_byte_values"))] + #[cfg_attr( + feature = "serde", + serde(with = "::serde_utils::btreemap_as_seq_byte_values") + )] pub unknown: BTreeMap>, } +/// Taproot Tree representing a finalized [`TaprootBuilder`] (a complete binary tree) +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +pub struct TapTree(pub(crate) TaprootBuilder); + +impl PartialEq for TapTree { + fn eq(&self, other: &Self) -> bool { + self.node_info().hash.eq(&other.node_info().hash) + } +} + +impl Eq for TapTree {} + +impl TapTree { + // get the inner node info as the builder is finalized + fn node_info(&self) -> &NodeInfo { + // The builder algorithm invariant guarantees that is_complete builder + // have only 1 element in branch and that is not None. + // We make sure that we only allow is_complete builders via the from_inner + // constructor + self.0.branch()[0].as_ref().expect("from_inner only parses is_complete builders") + } + + /// Convert a [`TaprootBuilder`] into a tree if it is complete binary tree. + /// Returns the inner as Err if it is not a complete tree + pub fn from_inner(inner: TaprootBuilder) -> Result { + if inner.is_complete() { + Ok(TapTree(inner)) + } else { + Err(inner) + } + } + + /// Convert self into builder [`TaprootBuilder`]. The builder is guaranteed to + /// be finalized. + pub fn into_inner(self) -> TaprootBuilder { + self.0 + } +} + impl Map for Output { fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), encode::Error> { let raw::Pair { @@ -82,10 +146,29 @@ impl Map for Output { btree_map::Entry::Vacant(empty_key) => {empty_key.insert(raw_value);}, btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key).into()), } - _ => 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()).into()), + 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()).into()) + } + }, } Ok(()) @@ -106,6 +189,19 @@ impl Map for Output { rv.push(self.bip32_derivation as |) } + impl_psbt_get_pair! { + rv.push(self.tap_internal_key as |) + } + + impl_psbt_get_pair! { + rv.push(self.tap_tree as |) + } + + impl_psbt_get_pair! { + rv.push(self.tap_key_origins as |<(Vec, KeySource)>) + } + for (key, value) in self.proprietary.iter() { rv.push(raw::Pair { key: key.to_key(), @@ -127,9 +223,12 @@ impl Map for Output { 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); merge!(redeem_script, self, other); merge!(witness_script, self, other); + merge!(tap_internal_key, self, other); + merge!(tap_tree, self, other); Ok(()) } diff --git a/src/util/psbt/mod.rs b/src/util/psbt/mod.rs index 85c7b82f..f7fda257 100644 --- a/src/util/psbt/mod.rs +++ b/src/util/psbt/mod.rs @@ -39,7 +39,7 @@ mod macros; pub mod serialize; mod map; -pub use self::map::{Map, Input, Output}; +pub use self::map::{Map, Input, Output, TapTree}; use util::bip32::{ExtendedPubKey, KeySource}; diff --git a/src/util/psbt/serialize.rs b/src/util/psbt/serialize.rs index 99e2cf61..7c9e7687 100644 --- a/src/util/psbt/serialize.rs +++ b/src/util/psbt/serialize.rs @@ -24,12 +24,18 @@ use io; use blockdata::script::Script; use blockdata::transaction::{EcdsaSigHashType, Transaction, TxOut}; -use consensus::encode::{self, serialize, Decodable}; +use consensus::encode::{self, serialize, Decodable, Encodable, deserialize_partial}; +use secp256k1::schnorrsig; use util::bip32::{ChildNumber, Fingerprint, KeySource}; use hashes::{hash160, ripemd160, sha256, sha256d, Hash}; use util::ecdsa::PublicKey; use util::psbt; +use util::taproot::{TapBranchHash, TapLeafHash, ControlBlock, LeafVersion}; +use schnorr; +use super::map::TapTree; +use util::taproot::TaprootBuilder; +use util::sighash::SchnorrSigHashType; /// A trait for serializing a value as raw data for insertion into PSBT /// key-value pairs. pub trait Serialize { @@ -48,9 +54,14 @@ impl_psbt_de_serialize!(TxOut); impl_psbt_de_serialize!(Vec>); // scriptWitness 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!(TapBranchHash); impl_psbt_hash_de_serialize!(hash160::Hash); impl_psbt_hash_de_serialize!(sha256d::Hash); +// taproot +impl_psbt_de_serialize!(Vec); + impl Serialize for Script { fn serialize(&self) -> Vec { self.to_bytes() @@ -80,7 +91,7 @@ impl Deserialize for PublicKey { impl Serialize for KeySource { fn serialize(&self) -> Vec { - let mut rv: Vec = Vec::with_capacity(4 + 4 * (self.1).as_ref().len()); + let mut rv: Vec = Vec::with_capacity(key_source_len(&self)); rv.append(&mut self.0.to_bytes().to_vec()); @@ -144,3 +155,170 @@ impl Deserialize for EcdsaSigHashType { } } } + +// Taproot related ser/deser +impl Serialize for schnorr::PublicKey { + fn serialize(&self) -> Vec { + schnorr::PublicKey::serialize(&self).to_vec() + } +} + +impl Deserialize for schnorr::PublicKey { + fn deserialize(bytes: &[u8]) -> Result { + schnorr::PublicKey::from_slice(bytes) + .map_err(|_| encode::Error::ParseFailed("Invalid xonly public key")) + } +} + +impl Serialize for schnorr::SchnorrSig { + fn serialize(&self) -> Vec { + self.to_vec() + } +} + +impl Deserialize for schnorr::SchnorrSig { + fn deserialize(bytes: &[u8]) -> Result { + match bytes.len() { + 65 => { + let hash_ty = SchnorrSigHashType::from_u8(bytes[64]) + .map_err(|_| encode::Error::ParseFailed("Invalid Sighash type"))?; + let sig = schnorrsig::Signature::from_slice(&bytes[..64]) + .map_err(|_| encode::Error::ParseFailed("Invalid Schnorr signature"))?; + Ok(schnorr::SchnorrSig{ sig, hash_ty }) + } + 64 => { + let sig = schnorrsig::Signature::from_slice(&bytes[..64]) + .map_err(|_| encode::Error::ParseFailed("Invalid Schnorr signature"))?; + Ok(schnorr::SchnorrSig{ sig, hash_ty: SchnorrSigHashType::Default }) + } + _ => Err(encode::Error::ParseFailed("Invalid Schnorr signature len")) + } + } +} + +impl Serialize for (schnorr::PublicKey, TapLeafHash) { + fn serialize(&self) -> Vec { + let ser_pk = self.0.serialize(); + let mut buf = Vec::with_capacity(ser_pk.len() + self.1.as_ref().len()); + buf.extend(&ser_pk); + buf.extend(self.1.as_ref()); + buf + } +} + +impl Deserialize for (schnorr::PublicKey, TapLeafHash) { + fn deserialize(bytes: &[u8]) -> Result { + if bytes.len() < 32 { + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + } + let a: schnorr::PublicKey = 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::from_slice(bytes) + .map_err(|_| encode::Error::ParseFailed("Invalid control block")) + } +} + +// Versioned Script +impl Serialize for (Script, 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.as_u8()); + buf + } +} + +impl Deserialize for (Script, 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 = Script::deserialize(&bytes[..bytes.len() - 1])?; + let leaf_ver = LeafVersion::from_u8(bytes[bytes.len() - 1]) + .map_err(|_| encode::Error::ParseFailed("invalid leaf version"))?; + 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 { + match (self.0.branch().len(), self.0.branch().last()) { + (1, Some(Some(root))) => { + let mut buf = Vec::new(); + for leaf_info in root.leaves.iter() { + // # 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.as_inner().len() as u8); + buf.push(leaf_info.ver.as_u8()); + leaf_info.script.consensus_encode(&mut buf).expect("Vecs dont err"); + } + buf + } + // This should be unreachable as we Taptree is already finalized + _ => unreachable!(), + } + } +} + +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(encode::Error::ParseFailed("Invalid Taproot Builder"))?; + let (script, consumed) = deserialize_partial::