What changed, and why it matters
This is a routine code-maintenance change: the developers are marking an old helper macro as deprecated and telling users how to write the same code by hand. There is no bug fix, no security patch, and no vulnerability being addressed in the commit itself.
No security action needed. Downstream users may plan migration away from sha256t_tag! when the deprecation becomes a hard removal, following the documented manual Tag implementation pattern.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit adds #[deprecated(since = “TBD”, note = “use sha256t::Tag instead”)] to the sha256t_tag! macro in rust-bitcoin’s hashes crate and updates documentation and tests to suppress deprecation warnings. It is a pure API-evolution/deprecation change; the macro still works and the generated code is unchanged. No cryptographic weakness, memory-safety issue, or vulnerability is mentioned or fixed.
Changed components
hashes/src/macros.rshashes/src/sha256t/mod.rshashes/tests/api.rsInspect captured patch +26 / −12
diff --git a/hashes/src/macros.rs b/hashes/src/macros.rs
index b8dd7e28..9f3dbd83 100644
--- a/hashes/src/macros.rs
+++ b/hashes/src/macros.rs
@@ -10,25 +10,34 @@
/// Macro used to define a tag.
///
-/// Defines new struct and implements [`Tag`](crate::sha256t::Tag) for it.
+/// # Deprecated
///
-/// The syntax is:
+/// This macro is deprecated in favor of implementing [`Tag`](crate::sha256t::Tag) by hand.
+/// [`Midstate::hash_tag`](crate::sha256::Midstate::hash_tag) and
+/// [`Midstate::new`](crate::sha256::Midstate::new) are `const fn`, so a tag's midstate can be
+/// computed in a `const` context without any macro:
///
/// ```
-/// # use bitcoin_hashes::sha256t_tag;
-/// sha256t_tag! {
-/// /// Optional documentation details here.
-/// /// Summary is always generated.
-/// pub struct FooTag = hash_str("foo");
+/// use bitcoin_hashes::{sha256, sha256t};
+///
+/// /// The tag for `FooHash`.
+/// #[derive(Copy, Clone, PartialEq, Eq, Default, PartialOrd, Ord, Hash)]
+/// pub struct FooTag;
+///
+/// impl sha256t::Tag for FooTag {
+/// const MIDSTATE: sha256::Midstate = sha256::Midstate::hash_tag(b"foo");
/// }
/// ```
+///
+/// The macro's three constructors map to these `MIDSTATE` expressions:
///
-/// The `hash_str` marker says the midstate should be generated by hashing the supplied string in a
-/// way described in BIP-0341. 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.
+/// - `hash_str("foo")` becomes `sha256::Midstate::hash_tag("foo".as_bytes())`
+/// - `hash_bytes(b"foo")` becomes `sha256::Midstate::hash_tag(b"foo")`
+/// - `raw(BYTES, LEN)` becomes `sha256::Midstate::new(BYTES, LEN)`
+///
+/// This macro dates to a time before SHA256 could be computed in a `const` context.
#[macro_export]
+#[deprecated(since = "TBD", note = "use `sha256t::Tag` instead")]
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!($tag), $(#[$($tag_attr)*])*);
@@ -567,6 +576,8 @@ macro_rules! impl_serde_traits(
#[cfg(test)]
mod test {
+ #![allow(deprecated_in_future)]
+
use crate::sha256;
#[test]
diff --git a/hashes/src/sha256t/mod.rs b/hashes/src/sha256t/mod.rs
index 45848e06..e69a9792 100644
--- a/hashes/src/sha256t/mod.rs
+++ b/hashes/src/sha256t/mod.rs
@@ -192,6 +192,8 @@ macro_rules! sha256t_tag_constructor {
#[cfg(test)]
mod tests {
+ #![allow(deprecated_in_future)]
+
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
use crate::sha256;
diff --git a/hashes/tests/api.rs b/hashes/tests/api.rs
index 76c1fa21..3784e66c 100644
--- a/hashes/tests/api.rs
+++ b/hashes/tests/api.rs
@@ -8,6 +8,7 @@
#![allow(dead_code)]
#![allow(unused_imports)]
+#![allow(deprecated_in_future)]
// Exclude lints we don't think are valuable.
#![allow(clippy::uninlined_format_args)] // Allow `format!("{}", x)` instead of enforcing `format!("{x}")`
Why this scored 16/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.