Reduce API surface of tagged wrapped hash types
Recently we made it so that wrapper types created with `hash_newtype` were not general purpose hash types i.e., one could not easily hash arbitrary data into them. We would like to do the same for tagged wrapped hash types. In `hashes` do: - Create a new macro `sha256t_tag` that does just the tag/engine stuff out of the `sha256t_hash_newtype` macro. - Deprecate the `sha256t_hash_newtype` macro. In `bitcoin` do: - Use a combination of `sha256t_tag` and `hash_newtype` to create tagged wrapped hash types. Note that we do not add private helper functions `engine` and `from_engine` to the tagged wrapper types as we do for legacy/segwit in `sighash`. Can be done later if wanted/needed.
This commit is contained in:
parent
c061d936fb
commit
39f7dcb816
|
@ -13,14 +13,14 @@
|
|||
|
||||
use core::{fmt, str};
|
||||
|
||||
use hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype};
|
||||
use hashes::{hash_newtype, sha256, sha256d, sha256t, sha256t_tag};
|
||||
use internals::write_err;
|
||||
use io::Write;
|
||||
|
||||
use crate::address::script_pubkey::ScriptExt as _;
|
||||
use crate::consensus::{encode, Encodable};
|
||||
use crate::prelude::{Borrow, BorrowMut, String, ToOwned, Vec};
|
||||
use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX};
|
||||
use crate::taproot::{LeafVersion, TapLeafHash, TapLeafTag, TAPROOT_ANNEX_PREFIX};
|
||||
use crate::witness::Witness;
|
||||
use crate::{transaction, Amount, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut};
|
||||
|
||||
|
@ -68,13 +68,15 @@ impl SegwitV0Sighash {
|
|||
fn from_engine(e: sha256d::HashEngine) -> Self { Self(sha256d::Hash::from_engine(e)) }
|
||||
}
|
||||
|
||||
sha256t_hash_newtype! {
|
||||
sha256t_tag! {
|
||||
pub struct TapSighashTag = hash_str("TapSighash");
|
||||
}
|
||||
|
||||
hash_newtype! {
|
||||
/// Taproot-tagged hash with tag \"TapSighash\".
|
||||
///
|
||||
/// This hash type is used for computing Taproot signature hash."
|
||||
pub struct TapSighash(_);
|
||||
pub struct TapSighash(sha256t::Hash<TapSighashTag>);
|
||||
}
|
||||
|
||||
impl_message_from_hash!(TapSighash);
|
||||
|
@ -322,7 +324,7 @@ impl<'s> ScriptPath<'s> {
|
|||
pub fn with_defaults(script: &'s Script) -> Self { Self::new(script, LeafVersion::TapScript) }
|
||||
/// Computes the leaf hash for this `ScriptPath`.
|
||||
pub fn leaf_hash(&self) -> TapLeafHash {
|
||||
let mut enc = TapLeafHash::engine();
|
||||
let mut enc = sha256t::Hash::<TapLeafTag>::engine();
|
||||
|
||||
self.leaf_version
|
||||
.to_consensus()
|
||||
|
@ -330,7 +332,8 @@ impl<'s> ScriptPath<'s> {
|
|||
.expect("writing to hash enging should never fail");
|
||||
self.script.consensus_encode(&mut enc).expect("writing to hash enging should never fail");
|
||||
|
||||
TapLeafHash::from_engine(enc)
|
||||
let inner = sha256t::Hash::<TapLeafTag>::from_engine(enc);
|
||||
TapLeafHash::from_byte_array(inner.to_byte_array())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -588,9 +591,9 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
/// Encodes the BIP341 signing data for any flag type into a given object implementing the
|
||||
/// [`io::Write`] trait.
|
||||
///
|
||||
/// In order to sign, the data written by this function must be hashed using a tagged hash. This
|
||||
/// can be achieved by using the [`TapSighash::engine()`] function, writing to the engine, then
|
||||
/// finalizing the hash with [`TapSighash::from_engine()`].
|
||||
/// In order to sign, the data written by this function must be hashed using a tagged hash. For
|
||||
/// example usage see [`Self::taproot_signature_hash`] and
|
||||
/// [`Self::taproot_key_spend_signature_hash`].
|
||||
pub fn taproot_encode_signing_data_to<W: Write + ?Sized, T: Borrow<TxOut>>(
|
||||
&mut self,
|
||||
writer: &mut W,
|
||||
|
@ -719,7 +722,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
leaf_hash_code_separator: Option<(TapLeafHash, u32)>,
|
||||
sighash_type: TapSighashType,
|
||||
) -> Result<TapSighash, TaprootError> {
|
||||
let mut enc = TapSighash::engine();
|
||||
let mut enc = sha256t::Hash::<TapSighashTag>::engine();
|
||||
self.taproot_encode_signing_data_to(
|
||||
&mut enc,
|
||||
input_index,
|
||||
|
@ -729,7 +732,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
sighash_type,
|
||||
)
|
||||
.map_err(SigningDataError::unwrap_sighash)?;
|
||||
Ok(TapSighash::from_engine(enc))
|
||||
let inner = sha256t::Hash::<TapSighashTag>::from_engine(enc);
|
||||
Ok(TapSighash::from_byte_array(inner.to_byte_array()))
|
||||
}
|
||||
|
||||
/// Computes the BIP341 sighash for a key spend.
|
||||
|
@ -739,7 +743,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
prevouts: &Prevouts<T>,
|
||||
sighash_type: TapSighashType,
|
||||
) -> Result<TapSighash, TaprootError> {
|
||||
let mut enc = TapSighash::engine();
|
||||
let mut enc = sha256t::Hash::<TapSighashTag>::engine();
|
||||
self.taproot_encode_signing_data_to(
|
||||
&mut enc,
|
||||
input_index,
|
||||
|
@ -749,7 +753,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
sighash_type,
|
||||
)
|
||||
.map_err(SigningDataError::unwrap_sighash)?;
|
||||
Ok(TapSighash::from_engine(enc))
|
||||
let inner = sha256t::Hash::<TapSighashTag>::from_engine(enc);
|
||||
Ok(TapSighash::from_byte_array(inner.to_byte_array()))
|
||||
}
|
||||
|
||||
/// Computes the BIP341 sighash for a script spend.
|
||||
|
@ -763,7 +768,7 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
leaf_hash: S,
|
||||
sighash_type: TapSighashType,
|
||||
) -> Result<TapSighash, TaprootError> {
|
||||
let mut enc = TapSighash::engine();
|
||||
let mut enc = sha256t::Hash::<TapSighashTag>::engine();
|
||||
self.taproot_encode_signing_data_to(
|
||||
&mut enc,
|
||||
input_index,
|
||||
|
@ -773,7 +778,8 @@ impl<R: Borrow<Transaction>> SighashCache<R> {
|
|||
sighash_type,
|
||||
)
|
||||
.map_err(SigningDataError::unwrap_sighash)?;
|
||||
Ok(TapSighash::from_engine(enc))
|
||||
let inner = sha256t::Hash::<TapSighashTag>::from_engine(enc);
|
||||
Ok(TapSighash::from_byte_array(inner.to_byte_array()))
|
||||
}
|
||||
|
||||
/// Encodes the BIP143 signing data for any flag type into a given object implementing the
|
||||
|
@ -1540,9 +1546,9 @@ mod tests {
|
|||
fn test_tap_sighash_hash() {
|
||||
let bytes = hex!("00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000");
|
||||
let expected = hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0");
|
||||
let mut enc = TapSighash::engine();
|
||||
let mut enc = sha256t::Hash::<TapSighashTag>::engine();
|
||||
enc.input(&bytes);
|
||||
let hash = TapSighash::from_engine(enc);
|
||||
let hash = sha256t::Hash::<TapSighashTag>::from_engine(enc);
|
||||
assert_eq!(expected, hash.to_byte_array());
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ use core::cmp::Reverse;
|
|||
use core::fmt;
|
||||
use core::iter::FusedIterator;
|
||||
|
||||
use hashes::{sha256t_hash_newtype, HashEngine};
|
||||
use hashes::{hash_newtype, sha256t_tag, sha256t, HashEngine};
|
||||
use internals::write_err;
|
||||
use io::Write;
|
||||
use secp256k1::{Scalar, Secp256k1};
|
||||
|
@ -29,31 +29,37 @@ pub use crate::crypto::taproot::{SigFromSliceError, Signature};
|
|||
pub use merkle_branch::TaprootMerkleBranch;
|
||||
|
||||
// Taproot test vectors from BIP-341 state the hashes without any reversing
|
||||
sha256t_hash_newtype! {
|
||||
sha256t_tag! {
|
||||
pub struct TapLeafTag = hash_str("TapLeaf");
|
||||
}
|
||||
|
||||
hash_newtype! {
|
||||
/// Taproot-tagged hash with tag \"TapLeaf\".
|
||||
///
|
||||
/// This is used for computing tapscript script spend hash.
|
||||
pub struct TapLeafHash(_);
|
||||
pub struct TapLeafHash(sha256t::Hash<TapLeafTag>);
|
||||
}
|
||||
|
||||
sha256t_hash_newtype! {
|
||||
sha256t_tag! {
|
||||
pub struct TapBranchTag = hash_str("TapBranch");
|
||||
}
|
||||
|
||||
hash_newtype! {
|
||||
/// Tagged hash used in Taproot trees.
|
||||
///
|
||||
/// See BIP-340 for tagging rules.
|
||||
pub struct TapNodeHash(_);
|
||||
pub struct TapNodeHash(sha256t::Hash<TapBranchTag>);
|
||||
}
|
||||
|
||||
sha256t_hash_newtype! {
|
||||
sha256t_tag! {
|
||||
pub struct TapTweakTag = hash_str("TapTweak");
|
||||
}
|
||||
|
||||
hash_newtype! {
|
||||
/// Taproot-tagged hash with tag \"TapTweak\".
|
||||
///
|
||||
/// This hash type is used while computing the tweaked public key.
|
||||
pub struct TapTweakHash(_);
|
||||
pub struct TapTweakHash(sha256t::Hash<TapTweakTag>);
|
||||
}
|
||||
|
||||
impl TapTweakHash {
|
||||
|
@ -63,7 +69,7 @@ impl TapTweakHash {
|
|||
internal_key: UntweakedPublicKey,
|
||||
merkle_root: Option<TapNodeHash>,
|
||||
) -> TapTweakHash {
|
||||
let mut eng = TapTweakHash::engine();
|
||||
let mut eng = sha256t::Hash::<TapTweakTag>::engine();
|
||||
// always hash the key
|
||||
eng.input(&internal_key.serialize());
|
||||
if let Some(h) = merkle_root {
|
||||
|
@ -71,7 +77,8 @@ impl TapTweakHash {
|
|||
} else {
|
||||
// nothing to hash
|
||||
}
|
||||
TapTweakHash::from_engine(eng)
|
||||
let inner = sha256t::Hash::<TapTweakTag>::from_engine(eng);
|
||||
TapTweakHash::from_byte_array(inner.to_byte_array())
|
||||
}
|
||||
|
||||
/// Converts a `TapTweakHash` into a `Scalar` ready for use with key tweaking API.
|
||||
|
@ -84,10 +91,11 @@ impl TapTweakHash {
|
|||
impl TapLeafHash {
|
||||
/// Computes the leaf hash from components.
|
||||
pub fn from_script(script: &Script, ver: LeafVersion) -> TapLeafHash {
|
||||
let mut eng = TapLeafHash::engine();
|
||||
let mut eng = sha256t::Hash::<TapLeafTag>::engine();
|
||||
ver.to_consensus().consensus_encode(&mut eng).expect("engines don't error");
|
||||
script.consensus_encode(&mut eng).expect("engines don't error");
|
||||
TapLeafHash::from_engine(eng)
|
||||
let inner = sha256t::Hash::<TapTweakTag>::from_engine(eng);
|
||||
TapLeafHash::from_byte_array(inner.to_byte_array())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +116,7 @@ impl TapNodeHash {
|
|||
/// Computes branch hash given two hashes of the nodes underneath it and returns
|
||||
/// whether the left node was the one hashed first.
|
||||
fn combine_node_hashes(a: TapNodeHash, b: TapNodeHash) -> (TapNodeHash, bool) {
|
||||
let mut eng = TapNodeHash::engine();
|
||||
let mut eng = sha256t::Hash::<TapBranchTag>::engine();
|
||||
if a < b {
|
||||
eng.input(a.as_ref());
|
||||
eng.input(b.as_ref());
|
||||
|
@ -116,7 +124,8 @@ impl TapNodeHash {
|
|||
eng.input(b.as_ref());
|
||||
eng.input(a.as_ref());
|
||||
};
|
||||
(TapNodeHash::from_engine(eng), a < b)
|
||||
let inner = sha256t::Hash::<TapBranchTag>::from_engine(eng);
|
||||
(TapNodeHash::from_byte_array(inner.to_byte_array()), a < b)
|
||||
}
|
||||
|
||||
/// Assumes the given 32 byte array as hidden [`TapNodeHash`].
|
||||
|
@ -1545,7 +1554,7 @@ mod test {
|
|||
|
||||
use super::*;
|
||||
use crate::script::ScriptBufExt as _;
|
||||
use crate::sighash::{TapSighash, TapSighashTag};
|
||||
use crate::sighash::TapSighashTag;
|
||||
use crate::{Address, KnownHrp};
|
||||
extern crate serde_json;
|
||||
|
||||
|
@ -1566,6 +1575,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_midstates() {
|
||||
use sha256t::Hash;
|
||||
// test that engine creation roundtrips
|
||||
assert_eq!(tag_engine("TapLeaf").midstate(), TapLeafTag::engine().midstate());
|
||||
assert_eq!(tag_engine("TapBranch").midstate(), TapBranchTag::engine().midstate());
|
||||
|
@ -1576,35 +1586,36 @@ mod test {
|
|||
fn empty_hash(tag_name: &str) -> [u8; 32] {
|
||||
let mut e = tag_engine(tag_name);
|
||||
e.input(&[]);
|
||||
TapNodeHash::from_engine(e).to_byte_array()
|
||||
Hash::<TapBranchTag>::from_engine(e).to_byte_array()
|
||||
}
|
||||
assert_eq!(empty_hash("TapLeaf"), TapLeafHash::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapBranch"), TapNodeHash::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapTweak"), TapTweakHash::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapSighash"), TapSighash::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapLeaf"), Hash::<TapLeafTag>::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapBranch"), Hash::<TapBranchTag>::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapTweak"), Hash::<TapTweakTag>::hash(&[]).to_byte_array());
|
||||
assert_eq!(empty_hash("TapSighash"), Hash::<TapSighashTag>::hash(&[]).to_byte_array());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vectors_core() {
|
||||
//! Test vectors taken from Core
|
||||
use sha256t::Hash;
|
||||
|
||||
// uninitialized writers
|
||||
// CHashWriter writer = HasherTapLeaf;
|
||||
// writer.GetSHA256().GetHex()
|
||||
assert_eq!(
|
||||
TapLeafHash::from_engine(TapLeafTag::engine()).to_string(),
|
||||
Hash::<TapLeafTag>::from_engine(TapLeafTag::engine()).to_string(),
|
||||
"5212c288a377d1f8164962a5a13429f9ba6a7b84e59776a52c6637df2106facb"
|
||||
);
|
||||
assert_eq!(
|
||||
TapNodeHash::from_engine(TapBranchTag::engine()).to_string(),
|
||||
Hash::<TapBranchTag>::from_engine(TapBranchTag::engine()).to_string(),
|
||||
"53c373ec4d6f3c53c1f5fb2ff506dcefe1a0ed74874f93fa93c8214cbe9ffddf"
|
||||
);
|
||||
assert_eq!(
|
||||
TapTweakHash::from_engine(TapTweakTag::engine()).to_string(),
|
||||
Hash::<TapTweakTag>::from_engine(TapTweakTag::engine()).to_string(),
|
||||
"8aa4229474ab0100b2d6f0687f031d1fc9d8eef92a042ad97d279bff456b15e4"
|
||||
);
|
||||
assert_eq!(
|
||||
TapSighash::from_engine(TapSighashTag::engine()).to_string(),
|
||||
Hash::<TapSighashTag>::from_engine(TapSighashTag::engine()).to_string(),
|
||||
"dabc11914abcd8072900042a2681e52f8dba99ce82e224f97b5fdb7cd4b9c803"
|
||||
);
|
||||
|
||||
|
@ -1614,19 +1625,19 @@ mod test {
|
|||
// writer.GetSHA256().GetHex()
|
||||
// Note that Core writes the 0 length prefix when an empty vector is written.
|
||||
assert_eq!(
|
||||
TapLeafHash::hash(&[0]).to_string(),
|
||||
Hash::<TapLeafTag>::hash(&[0]).to_string(),
|
||||
"ed1382037800c9dd938dd8854f1a8863bcdeb6705069b4b56a66ec22519d5829"
|
||||
);
|
||||
assert_eq!(
|
||||
TapNodeHash::hash(&[0]).to_string(),
|
||||
Hash::<TapBranchTag>::hash(&[0]).to_string(),
|
||||
"92534b1960c7e6245af7d5fda2588db04aa6d646abc2b588dab2b69e5645eb1d"
|
||||
);
|
||||
assert_eq!(
|
||||
TapTweakHash::hash(&[0]).to_string(),
|
||||
Hash::<TapTweakTag>::hash(&[0]).to_string(),
|
||||
"cd8737b5e6047fc3f16f03e8b9959e3440e1bdf6dd02f7bb899c352ad490ea1e"
|
||||
);
|
||||
assert_eq!(
|
||||
TapSighash::hash(&[0]).to_string(),
|
||||
Hash::<TapSighashTag>::hash(&[0]).to_string(),
|
||||
"c2fd0de003889a09c4afcf676656a0d8a1fb706313ff7d509afb00c323c010cd"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use hex::DisplayHex;
|
|||
|
||||
use crate::{sha256d, HashEngine as _};
|
||||
#[cfg(doc)]
|
||||
use crate::{sha256t, sha256t_hash_newtype};
|
||||
use crate::{sha256t, sha256t_tag};
|
||||
|
||||
crate::internal_macros::hash_type! {
|
||||
256,
|
||||
|
@ -169,8 +169,8 @@ impl Hash {
|
|||
/// fixed 64-byte prefix, it makes sense to hash the prefix once, store the midstate as a constant,
|
||||
/// and hash any future data starting from the constant rather than from a fresh hash engine.
|
||||
///
|
||||
/// For BIP-340 support we provide the [`sha256t`] module, and the [`sha256t_hash_newtype`]
|
||||
/// macro which will create the midstate for you in const context and use it for tagged hashing.
|
||||
/// For BIP-340 support we provide the [`sha256t`] module, and the [`sha256t_tag`] macro which will
|
||||
/// create the midstate for you in const context.
|
||||
#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Midstate {
|
||||
/// Raw bytes of the midstate i.e., the already-hashed contents of the hash engine.
|
||||
|
|
|
@ -157,6 +157,41 @@ where
|
|||
Hash::from_byte_array(sha256::Hash::from_engine(e).to_byte_array())
|
||||
}
|
||||
|
||||
/// Macro used to define a tag.
|
||||
///
|
||||
/// Defines new struct and implements `Tag` for it.
|
||||
///
|
||||
/// The syntax is:
|
||||
///
|
||||
/// ```
|
||||
/// # use bitcoin_hashes::sha256t_tag;
|
||||
/// sha256t_tag! {
|
||||
/// /// Optional documentation details here.
|
||||
/// /// Summary is always generated.
|
||||
/// pub struct FooTag = hash_str("foo");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The `hash_str` marker says the midstate should be generated by hashing the supplied string in a
|
||||
/// way described in BIP-341. Alternatively, you can supply `hash_bytes` to hash raw bytes. If you
|
||||
/// have the midstate already pre-computed and prefer **compiler** performance to readability you
|
||||
/// may use `raw(MIDSTATE_BYTES, HASHED_BYTES_LENGTH)` instead, note that HASHED_BYTES_LENGTH must
|
||||
/// be a multiple of 64.
|
||||
#[macro_export]
|
||||
macro_rules! sha256t_tag {
|
||||
($(#[$($tag_attr:tt)*])* $tag_vis:vis struct $tag:ident = $constructor:tt($($tag_value:tt)+);) => {
|
||||
$crate::sha256t_tag_struct!($tag_vis, $tag, stringify!($hash_name), $(#[$($tag_attr)*])*);
|
||||
|
||||
impl $crate::sha256t::Tag for $tag {
|
||||
#[inline]
|
||||
fn engine() -> $crate::sha256::HashEngine {
|
||||
const MIDSTATE: $crate::sha256::Midstate = $crate::sha256t_tag_constructor!($constructor, $($tag_value)+);
|
||||
$crate::sha256::HashEngine::from_midstate(MIDSTATE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Macro used to define a newtype tagged hash.
|
||||
///
|
||||
/// This macro creates two types:
|
||||
|
@ -195,14 +230,15 @@ where
|
|||
///
|
||||
/// [`hash_newtype`]: crate::hash_newtype
|
||||
#[macro_export]
|
||||
#[deprecated(since = "0.0.0-NEXT-RELEASE", note = "use `sha256_tag!` combined with `hash_newtype!`")]
|
||||
macro_rules! sha256t_hash_newtype {
|
||||
($(#[$($tag_attr:tt)*])* $tag_vis:vis struct $tag:ident = $constructor:tt($($tag_value:tt)+); $(#[$($hash_attr:tt)*])* $hash_vis:vis struct $hash_name:ident($(#[$($field_attr:tt)*])* _);) => {
|
||||
$crate::sha256t_hash_newtype_tag!($tag_vis, $tag, stringify!($hash_name), $(#[$($tag_attr)*])*);
|
||||
$crate::sha256t_tag_struct!($tag_vis, $tag, stringify!($hash_name), $(#[$($tag_attr)*])*);
|
||||
|
||||
impl $crate::sha256t::Tag for $tag {
|
||||
#[inline]
|
||||
fn engine() -> $crate::sha256::HashEngine {
|
||||
const MIDSTATE: $crate::sha256::Midstate = $crate::sha256t_hash_newtype_tag_constructor!($constructor, $($tag_value)+);
|
||||
const MIDSTATE: $crate::sha256::Midstate = $crate::sha256t_tag_constructor!($constructor, $($tag_value)+);
|
||||
$crate::sha256::HashEngine::from_midstate(MIDSTATE)
|
||||
}
|
||||
}
|
||||
|
@ -266,7 +302,7 @@ macro_rules! sha256t_hash_newtype {
|
|||
// Workaround macros being unavailable in attributes.
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! sha256t_hash_newtype_tag {
|
||||
macro_rules! sha256t_tag_struct {
|
||||
($vis:vis, $tag:ident, $name:expr, $(#[$($attr:meta)*])*) => {
|
||||
#[doc = "The tag used for [`"]
|
||||
#[doc = $name]
|
||||
|
@ -279,7 +315,7 @@ macro_rules! sha256t_hash_newtype_tag {
|
|||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! sha256t_hash_newtype_tag_constructor {
|
||||
macro_rules! sha256t_tag_constructor {
|
||||
(hash_str, $value:expr) => {
|
||||
$crate::sha256::Midstate::hash_tag($value.as_bytes())
|
||||
};
|
||||
|
@ -330,35 +366,45 @@ mod tests {
|
|||
assert_eq!(TestHash::hash(&[0]).to_string(), HASH_ZERO_FORWARD);
|
||||
}
|
||||
|
||||
// We also provide a macro to create the tag and the hash type.
|
||||
sha256t_hash_newtype! {
|
||||
// We also provide macros to create the tag and the hash type.
|
||||
sha256t_tag! {
|
||||
/// Test detailed explanation.
|
||||
struct NewTypeTagBackward = raw(TEST_MIDSTATE, 64);
|
||||
|
||||
}
|
||||
hash_newtype! {
|
||||
/// A test hash.
|
||||
#[hash_newtype(backward)]
|
||||
struct NewTypeHashBackward(_);
|
||||
struct NewTypeHashBackward(sha256t::Hash<NewTypeTagBackward>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn macro_created_sha256t_hash_type_backward() {
|
||||
assert_eq!(NewTypeHashBackward::hash(&[0]).to_string(), HASH_ZERO_BACKWARD);
|
||||
let inner = sha256t::Hash::<NewTypeTagBackward>::hash(&[0]);
|
||||
let hash = NewTypeHashBackward::from_byte_array(inner.to_byte_array());
|
||||
assert_eq!(hash.to_string(), HASH_ZERO_BACKWARD);
|
||||
// Note one has to use the new wrapper type to get backwards formatting.
|
||||
assert_eq!(sha256t::Hash::<NewTypeTagBackward>::hash(&[0]).to_string(), HASH_ZERO_FORWARD);
|
||||
}
|
||||
|
||||
// We also provide a macro to create the tag and the hash type.
|
||||
sha256t_hash_newtype! {
|
||||
sha256t_tag! {
|
||||
/// Test detailed explanation.
|
||||
struct NewTypeTagForward = raw(TEST_MIDSTATE, 64);
|
||||
|
||||
}
|
||||
hash_newtype! {
|
||||
/// A test hash.
|
||||
#[hash_newtype(forward)]
|
||||
struct NewTypeHashForward(_);
|
||||
struct NewTypeHashForward(sha256t::Hash<NewTypeTagForward>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn macro_created_sha256t_hash_type_prints_forward() {
|
||||
assert_eq!(NewTypeHashForward::hash(&[0]).to_string(), HASH_ZERO_FORWARD);
|
||||
let inner = sha256t::Hash::<NewTypeTagForward>::hash(&[0]);
|
||||
let hash = NewTypeHashForward::from_byte_array(inner.to_byte_array());
|
||||
assert_eq!(hash.to_string(), HASH_ZERO_FORWARD);
|
||||
// We can also just use the `sha256t::Hash` type directly.
|
||||
assert_eq!(sha256t::Hash::<NewTypeTagForward>::hash(&[0]).to_string(), HASH_ZERO_FORWARD);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue