hashes: implement sha256t::Tag without the macro
What changed, and why it matters
This commit is a routine code cleanup in the rust-bitcoin library. It replaces a macro used to define SHA-256 tagged hash identifiers with direct Rust code that does the same thing. The actual hash values and behavior are unchanged; only the internal implementation style is different.
No security action required. Treat as normal refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit migrates sha256t tag definitions from the sha256t_tag! macro to manual impl sha256t::Tag blocks using the const fn sha256::Midstate::hash_tag. Affected tags are TapSighashTag, TapLeafTag, TapBranchTag, TapTweakTag, and an internal HKDF debug tag. The macro previously computed the midstate at compile time; the const fn now does the same. No functional or cryptographic changes are visible in the diff.
Changed components
bitcoin/src/crypto/sighash.rshashes/src/hkdf/mod.rstaproot-primitives/src/lib.rsInspect captured patch +30 / −13
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index ee063131..2e91d266 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -19,7 +19,7 @@ use arbitrary::{Arbitrary, Unstructured};
use crypto::key::{TweakedKeypair, UntweakedKeypair};
use crypto::{ecdsa, taproot, PrivateKey};
use encoding::CompactSizeEncoder;
-use hashes::{hash_newtype, sha256, sha256d, sha256t, sha256t_tag};
+use hashes::{hash_newtype, sha256, sha256d, sha256t};
use io::Write;
use crate::consensus::{encode, Encodable};
@@ -104,8 +104,12 @@ impl SegwitV0Sighash {
}
}
-sha256t_tag! {
- pub struct TapSighashTag = hash_str("TapSighash");
+/// The tag used for [`TapSighash`].
+#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
+pub struct TapSighashTag;
+
+impl sha256t::Tag for TapSighashTag {
+ const MIDSTATE: sha256::Midstate = sha256::Midstate::hash_tag(b"TapSighash");
}
hash_newtype! {
diff --git a/hashes/src/hkdf/mod.rs b/hashes/src/hkdf/mod.rs
index 9b10841b..59a4a06b 100644
--- a/hashes/src/hkdf/mod.rs
+++ b/hashes/src/hkdf/mod.rs
@@ -125,7 +125,7 @@ where
impl<T: HashEngine> fmt::Debug for Hkdf<T> {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- use crate::{sha256t, sha256t_tag};
+ use crate::{sha256, sha256t};
struct Fingerprint([u8; 8]); // Print 16 hex characters as a fingerprint.
@@ -133,8 +133,9 @@ impl<T: HashEngine> fmt::Debug for Hkdf<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { crate::debug_hex(&self.0, f) }
}
- sha256t_tag! {
- pub struct Tag = hash_str("bitcoin_hashes1DEBUG");
+ struct Tag;
+ impl sha256t::Tag for Tag {
+ const MIDSTATE: sha256::Midstate = sha256::Midstate::hash_tag(b"bitcoin_hashes1DEBUG");
}
let hash = sha256t::Hash::<Tag>::hash(self.prk.as_ref());
diff --git a/taproot-primitives/src/lib.rs b/taproot-primitives/src/lib.rs
index f4faa845..b01ae263 100644
--- a/taproot-primitives/src/lib.rs
+++ b/taproot-primitives/src/lib.rs
@@ -41,7 +41,7 @@ use arbitrary::{Arbitrary, Unstructured};
use crypto::key::{
TweakedKeypair, TweakedPublicKey, UntweakedKeypair, UntweakedPublicKey, XOnlyPublicKey,
};
-use hashes::{hash_newtype, sha256t, sha256t_tag, HashEngine as _};
+use hashes::{hash_newtype, sha256, sha256t, HashEngine as _};
use secp256k1::Scalar;
/// Maximum depth of a Taproot tree script spend path.
@@ -67,8 +67,12 @@ pub const TAPROOT_CONTROL_MAX_SIZE: usize =
TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT;
// Taproot test vectors from BIP-0341 state the hashes without any reversing
-sha256t_tag! {
- pub struct TapLeafTag = hash_str("TapLeaf");
+/// The tag used for [`TapLeafHash`].
+#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
+pub struct TapLeafTag;
+
+impl sha256t::Tag for TapLeafTag {
+ const MIDSTATE: sha256::Midstate = sha256::Midstate::hash_tag(b"TapLeaf");
}
hash_newtype! {
@@ -83,8 +87,12 @@ hashes::impl_hex_for_newtype!(TapLeafHash);
#[cfg(feature = "hex")]
hashes::impl_serde_for_newtype!(TapLeafHash);
-sha256t_tag! {
- pub struct TapBranchTag = hash_str("TapBranch");
+/// The tag used for [`TapNodeHash`].
+#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
+pub struct TapBranchTag;
+
+impl sha256t::Tag for TapBranchTag {
+ const MIDSTATE: sha256::Midstate = sha256::Midstate::hash_tag(b"TapBranch");
}
hash_newtype! {
@@ -101,8 +109,12 @@ hashes::impl_hex_for_newtype!(TapNodeHash);
#[cfg(feature = "hex")]
hashes::impl_serde_for_newtype!(TapNodeHash);
-sha256t_tag! {
- pub struct TapTweakTag = hash_str("TapTweak");
+/// The tag used for [`TapTweakHash`].
+#[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
+pub struct TapTweakTag;
+
+impl sha256t::Tag for TapTweakTag {
+ const MIDSTATE: sha256::Midstate = sha256::Midstate::hash_tag(b"TapTweak");
}
hash_newtype! {
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.