Skip to content

Commit

Permalink
Implement TryFrom sha256::Hash for TaprootMerkleBranch
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
tcharding committed Jun 24, 2022
1 parent 95c74d7 commit ecf3bf2
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/util/sighash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,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());
Expand All @@ -1125,7 +1125,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::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap();
let hash_ty = SchnorrSighashType::try_from(Vec::<u8>::from_hex(&sig_str[128..]).unwrap()[0]).unwrap();
(secp256k1::schnorr::Signature::from_str(&sig_str[..128]).unwrap(), hash_ty)
};

Expand Down
39 changes: 34 additions & 5 deletions src/util/taproot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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<T: AsRef<[sha256::Hash]> + Into<Vec<sha256::Hash>>>(collection: T) -> Result<Self, TaprootError> {
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
Expand Down Expand Up @@ -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<sha256::Hash>) -> Result<Self, TaprootError> {
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.
Expand All @@ -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<Self, Self::Error> {
TaprootMerkleBranch::from_collection(v)
}
}
}
}
impl_try_from!(&[sha256::Hash]);
impl_try_from!(Vec<sha256::Hash>);
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))]
Expand Down

0 comments on commit ecf3bf2

Please sign in to comment.