hashes: use Rust-like syntax in hash type macros
What changed, and why it matters
This commit is a purely cosmetic refactor of how hash types are declared in the rust-bitcoin library. It changes the internal macro syntax from a custom list of numbers and flags to something that looks more like ordinary Rust code. There is no change to the actual hashing behavior, output, or public API.
No security action required. This is a non-functional refactor. Reviewers may optionally verify that all macro invocations map the same bit widths and display directions as before.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit updates general_hash_type! and hash_type_no_default! macros in hashes/src/internal_macros.rs to accept a Rust-like struct declaration (pub struct Hash([u8; $len])) and a named constant (const DISPLAY_BACKWARD: bool = ...) instead of positional arguments ($bits, $reverse, $doc). All call sites are updated to use the new syntax. The generated code remains functionally equivalent: byte array length is still derived as ($len) * 8, and the DISPLAY_BACKWARD flag is passed through unchanged. No cryptographic logic, trait behavior, or public interface was modified.
Changed components
hashes/src/internal_macros.rshashes/src/hash160/mod.rshashes/src/ripemd160/mod.rshashes/src/sha1/mod.rshashes/src/sha256/mod.rshashes/src/sha256d/mod.rshashes/src/sha384/mod.rshashes/src/sha3_256/mod.rshashes/src/sha512/mod.rshashes/src/sha512_256/mod.rshashes/src/siphash24/mod.rsInspect captured patch +81 / −44
diff --git a/hashes/src/hash160/mod.rs b/hashes/src/hash160/mod.rs
index 499c6666..53309bd0 100644
--- a/hashes/src/hash160/mod.rs
+++ b/hashes/src/hash160/mod.rs
@@ -10,9 +10,10 @@
use crate::{ripemd160, sha256};
crate::internal_macros::general_hash_type! {
- 160,
- false,
- "Output of the Bitcoin HASH160 hash function. (RIPEMD160(SHA256))"
+ /// Output of the Bitcoin HASH160 hash function. (RIPEMD160(SHA256))
+ pub struct Hash([u8; 20]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/internal_macros.rs b/hashes/src/internal_macros.rs
index 498eb723..d3eff00e 100644
--- a/hashes/src/internal_macros.rs
+++ b/hashes/src/internal_macros.rs
@@ -47,17 +47,28 @@ pub(crate) use hash_trait_impls;
/// The created type has a single field and will have all standard derives as well as an
/// implementation of [`crate::Hash`].
///
-/// # Parameters
+/// # Syntax
+///
+/// ```ignore
+/// // Requires a `HashEngine` type in scope.
+/// general_hash_type! {
+/// /// Documentation for the hash type.
+/// pub struct Hash([u8; 32]);
///
-/// * `$bits` - the number of bits of the hash type
-/// * `$reverse` - `true` if the hash should be displayed backwards, `false` otherwise
-/// * `$doc` - the doc string to put on the type
+/// const DISPLAY_BACKWARD: bool = false;
+/// }
+/// ```
///
/// Restrictions on usage:
///
-/// * Requires a `HashEngine` type in this module implementing `Default` and `crate::HashEngine<Hash = Hash, Bytes = [u8; $bits / 8]>`.
+/// * Requires a `HashEngine` type in this module implementing `Default` and `crate::HashEngine<Hash = Hash, Bytes = [u8; $len]>`.
macro_rules! general_hash_type {
- ($bits:expr, $reverse:expr, $doc:literal) => {
+ (
+ $(#[$type_attrs:meta])*
+ pub struct Hash([u8; $len:expr]);
+
+ const DISPLAY_BACKWARD: bool = $reverse:expr;
+ ) => {
/// Hashes some bytes.
pub fn hash(data: &[u8]) -> Hash {
use crate::HashEngine as _;
@@ -82,7 +93,12 @@ macro_rules! general_hash_type {
engine.finalize()
}
- $crate::internal_macros::hash_type_no_default!($bits, $reverse, $doc);
+ $crate::internal_macros::hash_type_no_default! {
+ $(#[$type_attrs])*
+ pub struct Hash([u8; $len]);
+
+ const DISPLAY_BACKWARD: bool = $reverse;
+ }
impl Hash {
/// Constructs a new engine.
@@ -113,11 +129,16 @@ macro_rules! general_hash_type {
pub(crate) use general_hash_type;
macro_rules! hash_type_no_default {
- ($bits:expr, $reverse:expr, $doc:literal) => {
+ (
+ $(#[$type_attrs:meta])*
+ pub struct Hash([u8; $len:expr]);
+
+ const DISPLAY_BACKWARD: bool = $reverse:expr;
+ ) => {
internals::transparent_newtype! {
- #[doc = $doc]
+ $(#[$type_attrs])*
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
- pub struct Hash([u8; $bits / 8]);
+ pub struct Hash([u8; $len]);
impl Hash {
/// Zero cost conversion between a fixed length byte array shared reference and
@@ -132,16 +153,17 @@ macro_rules! hash_type_no_default {
impl Hash {
/// Constructs a new hash from the underlying byte array.
- pub const fn from_byte_array(bytes: [u8; $bits / 8]) -> Self { Hash(bytes) }
+ pub const fn from_byte_array(bytes: [u8; $len]) -> Self { Hash(bytes) }
/// Returns the underlying byte array.
- pub const fn to_byte_array(self) -> [u8; $bits / 8] { self.0 }
+ pub const fn to_byte_array(self) -> [u8; $len] { self.0 }
/// Returns a reference to the underlying byte array.
- pub const fn as_byte_array(&self) -> &[u8; $bits / 8] { &self.0 }
+ pub const fn as_byte_array(&self) -> &[u8; $len] { &self.0 }
}
- $crate::internal_macros::hash_trait_impls!($bits, $reverse);
+ // Parenthesize `$len` so additive expressions still map to the intended bit width.
+ $crate::internal_macros::hash_trait_impls!(($len) * 8, $reverse);
$crate::internal_macros::impl_write!(
HashEngine,
diff --git a/hashes/src/ripemd160/mod.rs b/hashes/src/ripemd160/mod.rs
index 3083b6b8..920d5405 100644
--- a/hashes/src/ripemd160/mod.rs
+++ b/hashes/src/ripemd160/mod.rs
@@ -12,9 +12,10 @@ mod tests;
use crate::incomplete_block_len;
crate::internal_macros::general_hash_type! {
- 160,
- false,
- "Output of the RIPEMD160 hash function."
+ /// Output of the RIPEMD160 hash function.
+ pub struct Hash([u8; 20]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/sha1/mod.rs b/hashes/src/sha1/mod.rs
index ebb4ded6..8fb8a908 100644
--- a/hashes/src/sha1/mod.rs
+++ b/hashes/src/sha1/mod.rs
@@ -12,9 +12,10 @@ mod tests;
use crate::incomplete_block_len;
crate::internal_macros::general_hash_type! {
- 160,
- false,
- "Output of the SHA1 hash function."
+ /// Output of the SHA1 hash function.
+ pub struct Hash([u8; 20]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/sha256/mod.rs b/hashes/src/sha256/mod.rs
index ecd453fa..750bfc26 100644
--- a/hashes/src/sha256/mod.rs
+++ b/hashes/src/sha256/mod.rs
@@ -17,9 +17,10 @@ use crate::{incomplete_block_len, sha256d};
use crate::{sha256t, sha256t_tag};
crate::internal_macros::general_hash_type! {
- 256,
- false,
- "Output of the SHA256 hash function."
+ /// Output of the SHA256 hash function.
+ pub struct Hash([u8; 32]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/sha256d/mod.rs b/hashes/src/sha256d/mod.rs
index 4a174106..11434a2b 100644
--- a/hashes/src/sha256d/mod.rs
+++ b/hashes/src/sha256d/mod.rs
@@ -5,9 +5,10 @@
use crate::sha256;
crate::internal_macros::general_hash_type! {
- 256,
- true,
- "Output of the SHA256d hash function."
+ /// Output of the SHA256d hash function.
+ pub struct Hash([u8; 32]);
+
+ const DISPLAY_BACKWARD: bool = true;
}
impl Hash {
diff --git a/hashes/src/sha384/mod.rs b/hashes/src/sha384/mod.rs
index baa5651c..5a5b0d72 100644
--- a/hashes/src/sha384/mod.rs
+++ b/hashes/src/sha384/mod.rs
@@ -5,9 +5,10 @@
use crate::sha512;
crate::internal_macros::general_hash_type! {
- 384,
- false,
- "Output of the SHA384 hash function."
+ /// Output of the SHA384 hash function.
+ pub struct Hash([u8; 48]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/sha3_256/mod.rs b/hashes/src/sha3_256/mod.rs
index 687513fc..3328ddca 100644
--- a/hashes/src/sha3_256/mod.rs
+++ b/hashes/src/sha3_256/mod.rs
@@ -27,9 +27,10 @@
use core::fmt;
crate::internal_macros::general_hash_type! {
- 256,
- false,
- "Output of the SHA3-256 hash function."
+ /// Output of the SHA3-256 hash function.
+ pub struct Hash([u8; 32]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
// The number of rows or columns.
const B: usize = 5;
diff --git a/hashes/src/sha512/mod.rs b/hashes/src/sha512/mod.rs
index 5f5a02ba..0d1b77c5 100644
--- a/hashes/src/sha512/mod.rs
+++ b/hashes/src/sha512/mod.rs
@@ -13,9 +13,10 @@ mod tests;
use crate::incomplete_block_len;
crate::internal_macros::general_hash_type! {
- 512,
- false,
- "Output of the SHA512 hash function."
+ /// Output of the SHA512 hash function.
+ pub struct Hash([u8; 64]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/sha512_256/mod.rs b/hashes/src/sha512_256/mod.rs
index a3b8071d..7854326e 100644
--- a/hashes/src/sha512_256/mod.rs
+++ b/hashes/src/sha512_256/mod.rs
@@ -9,9 +9,15 @@
use crate::sha512;
crate::internal_macros::general_hash_type! {
- 256,
- false,
- "Output of the SHA512/256 hash function.\n\nSHA512/256 is a hash function that uses the sha512 algorithm but it truncates the output to 256 bits. It has different initial constants than sha512 so it produces an entirely different hash compared to sha512. More information at <https://eprint.iacr.org/2010/548.pdf>."
+ /// Output of the SHA512/256 hash function.
+ ///
+ /// SHA512/256 is a hash function that uses the sha512 algorithm but it truncates the output to
+ /// 256 bits. It has different initial constants than sha512 so it produces an entirely
+ /// different hash compared to sha512. More information at
+ /// <https://eprint.iacr.org/2010/548.pdf>.
+ pub struct Hash([u8; 32]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
impl Hash {
diff --git a/hashes/src/siphash24/mod.rs b/hashes/src/siphash24/mod.rs
index a551ff3e..495f8650 100644
--- a/hashes/src/siphash24/mod.rs
+++ b/hashes/src/siphash24/mod.rs
@@ -9,9 +9,10 @@ use core::{cmp, mem};
use crate::HashEngine as _;
crate::internal_macros::hash_type_no_default! {
- 64,
- false,
- "Output of the SipHash24 hash function."
+ /// Output of the SipHash24 hash function.
+ pub struct Hash([u8; 8]);
+
+ const DISPLAY_BACKWARD: bool = false;
}
macro_rules! compress {
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.