Skip to content

Commit 6f9164f

Browse files
committed
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.
1 parent 1004ba2 commit 6f9164f

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

src/util/sighash.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ mod tests {
11131113
} else {
11141114
Some(hex_hash!(TapBranchHash, inp["given"]["merkleRoot"].as_str().unwrap()))
11151115
};
1116-
let hash_ty = SchnorrSighashType::from_u8(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap();
1116+
let hash_ty = SchnorrSighashType::try_from(inp["given"]["hashType"].as_u64().unwrap() as u8).unwrap();
11171117

11181118
let expected_internal_pk = hex_hash!(XOnlyPublicKey, inp["intermediary"]["internalPubkey"].as_str().unwrap());
11191119
let expected_tweak = hex_hash!(TapTweakHash, inp["intermediary"]["tweak"].as_str().unwrap());
@@ -1124,7 +1124,7 @@ mod tests {
11241124
let (expected_key_spend_sig, expected_hash_ty) = if sig_str.len() == 128 {
11251125
(secp256k1::schnorr::Signature::from_str(sig_str).unwrap(), SchnorrSighashType::Default)
11261126
} else {
1127-
let hash_ty = SchnorrSighashType::from_u8(Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap();
1127+
let hash_ty = SchnorrSighashType::try_from(Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap();
11281128
(secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty)
11291129
};
11301130

src/util/taproot.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::prelude::*;
2020
use crate::io;
2121
use secp256k1::{self, Secp256k1};
2222

23+
use core::convert::TryFrom;
2324
use core::fmt;
2425
use core::cmp::Reverse;
2526

@@ -672,6 +673,18 @@ impl TaprootMerkleBranch {
672673
}
673674
}
674675

676+
/// Creates a merkle proof from list of hashes.
677+
///
678+
/// # Errors
679+
/// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128).
680+
fn from_collection<T: AsRef<[sha256::Hash]> + Into<Vec<sha256::Hash>>>(collection: T) -> Result<Self, TaprootError> {
681+
if collection.as_ref().len() > TAPROOT_CONTROL_MAX_NODE_COUNT {
682+
Err(TaprootError::InvalidMerkleTreeDepth(collection.as_ref().len()))
683+
} else {
684+
Ok(TaprootMerkleBranch(collection.into()))
685+
}
686+
}
687+
675688
/// Serializes to a writer.
676689
///
677690
/// # Returns
@@ -704,12 +717,9 @@ impl TaprootMerkleBranch {
704717
/// # Errors
705718
///
706719
/// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128).
720+
#[deprecated(since = "0.29.0", note = "use try_from instead")]
707721
pub fn from_inner(inner: Vec<sha256::Hash>) -> Result<Self, TaprootError> {
708-
if inner.len() > TAPROOT_CONTROL_MAX_NODE_COUNT {
709-
Err(TaprootError::InvalidMerkleTreeDepth(inner.len()))
710-
} else {
711-
Ok(TaprootMerkleBranch(inner))
712-
}
722+
Self::try_from(inner)
713723
}
714724

715725
/// Returns the inner list of hashes.
@@ -718,6 +728,25 @@ impl TaprootMerkleBranch {
718728
}
719729
}
720730

731+
macro_rules! impl_try_from {
732+
($from:ty) => {
733+
impl TryFrom<$from> for TaprootMerkleBranch {
734+
type Error = TaprootError;
735+
736+
/// Creates a merkle proof from list of hashes.
737+
///
738+
/// # Errors
739+
/// If inner proof length is more than [`TAPROOT_CONTROL_MAX_NODE_COUNT`] (128).
740+
fn try_from(v: $from) -> Result<Self, Self::Error> {
741+
TaprootMerkleBranch::from_collection(v)
742+
}
743+
}
744+
}
745+
}
746+
impl_try_from!(&[sha256::Hash]);
747+
impl_try_from!(Vec<sha256::Hash>);
748+
impl_try_from!(Box<[sha256::Hash]>);
749+
721750
/// Control block data structure used in Tapscript satisfaction.
722751
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
723752
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]

0 commit comments

Comments
 (0)