From af1628667939912992abf8f04027dfdca18f2241 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 25 May 2022 17:16:54 +1000 Subject: [PATCH] Implement TryFrom sha256::Hash for TaprootMerkleBranch TryFrom` became available in Rust 1.34 so we can use it now we have bumped our MSRV. Add a macro for implementing `TryFrom` for various lists of `sha256::Hash` types. Use the macro to for vec, slice, and boxed slice. --- src/util/sighash.rs | 4 ++-- src/util/taproot.rs | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/util/sighash.rs b/src/util/sighash.rs index a3b6abce..81734711 100644 --- a/src/util/sighash.rs +++ b/src/util/sighash.rs @@ -1113,7 +1113,7 @@ mod tests { } else { Some(hex_hash!(TapBranchHash, inp["given"]["merkleRoot"].as_str().unwrap())) }; - let hash_ty = SchnorrSighashType::from_u8(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap(); + let hash_ty = SchnorrSighashType::try_from(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap(); let expected_internal_pk = hex_hash!(XOnlyPublicKey, inp["intermediary"]["internalPubkey"].as_str().unwrap()); let expected_tweak = hex_hash!(TapTweakHash, inp["intermediary"]["tweak"].as_str().unwrap()); @@ -1124,7 +1124,7 @@ mod tests { let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 { (secp256k1::schnorr::Signature::from_str(sig_str).unwrap(), SchnorrSighashType::Default) } else { - let hash_ty = SchnorrSighashType::from_u8(Vec::::from_hex(&sig_str[128..]).unwrap()[0]).unwrap(); + let hash_ty = SchnorrSighashType::try_from(Vec::::from_hex(&sig_str[128..]).unwrap()[0]).unwrap(); (secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty) }; diff --git a/src/util/taproot.rs b/src/util/taproot.rs index 3cd050d6..afdba369 100644 --- a/src/util/taproot.rs +++ b/src/util/taproot.rs @@ -20,6 +20,7 @@ use crate::prelude::*; use crate::io; use secp256k1::{self, Secp256k1}; +use core::convert::TryFrom; use core::fmt; use core::cmp::Reverse; @@ -672,6 +673,18 @@ impl TaprootMerkleBranch { } } + /// Creates a merkle proof from list of hashes. + /// + /// # Errors + /// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128). + fn from_collection + Into>>(collection: T) -> Result { + if collection.as_ref().len() > TAPROOT_CONTROL_MAX_NODE_COUNT { + Err(TaprootError::InvalidMerkleTreeDepth(collection.as_ref().len())) + } else { + Ok(TaprootMerkleBranch(collection.into())) + } + } + /// Serializes to a writer. /// /// # Returns @@ -704,12 +717,9 @@ impl TaprootMerkleBranch { /// # Errors /// /// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128). + #[deprecated(since = "0.29.0", note = "use try_from instead")] pub fn from_inner(inner: Vec) -> Result { - if inner.len() > TAPROOT_CONTROL_MAX_NODE_COUNT { - Err(TaprootError::InvalidMerkleTreeDepth(inner.len())) - } else { - Ok(TaprootMerkleBranch(inner)) - } + Self::try_from(inner) } /// Returns the inner list of hashes. @@ -718,6 +728,25 @@ impl TaprootMerkleBranch { } } +macro_rules! impl_try_from { + ($from:ty) => { + impl TryFrom<$from> for TaprootMerkleBranch { + type Error = TaprootError; + + /// Creates a merkle proof from list of hashes. + /// + /// # Errors + /// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128). + fn try_from(v: $from) -> Result { + TaprootMerkleBranch::from_collection(v) + } + } + } +} +impl_try_from!(&[sha256::Hash]); +impl_try_from!(Vec); +impl_try_from!(Box<[sha256::Hash]>); + /// Control block data structure used in Tapscript satisfaction. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]