hashes: Introduce MuHash wrapper type
What changed, and why it matters
This commit adds a new public type called MuHash to the rust-bitcoin hashes library. It is purely a wrapper around a 384-byte byte array so that downstream projects can label muhash3072 digests with a meaningful Rust type. The commit does not implement the hash algorithm itself, change any existing behavior, or fix any bug. There is no security-relevant change.
No security action needed. Treat as a normal API addition.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch introduces hashes/src/muhash/mod.rs, exports muhash::Hash as MuHash from hashes/src/lib.rs, and updates tests to import the new module/alias. The type is a transparent newtype over [u8; 384] generated by internals::transparent_newtype!, with from_byte_array/to_byte_array/as_byte_array helpers and standard hash trait impls. The documentation explicitly states the crate cannot compute this hash and that the wrapper exists only for semantic meaning.
Changed components
hashes/src/lib.rshashes/src/muhash/mod.rshashes/tests/api.rsInspect captured patch +51 / −6
diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs
index 1ec86ffd..2043b8fd 100644
--- a/hashes/src/lib.rs
+++ b/hashes/src/lib.rs
@@ -99,6 +99,7 @@ pub mod hkdf;
pub mod hmac;
#[macro_use]
pub mod macros;
+pub mod muhash;
pub mod ripemd160;
pub mod sha1;
pub mod sha256;
@@ -124,6 +125,9 @@ pub use self::{
/// HASH-160: Alias for the [`hash160::Hash`] hash type.
#[doc(inline)]
pub use hash160::Hash as Hash160;
+/// MuHash3072: Alias for the [`muhash::Hash`] hash type.
+#[doc(inline)]
+pub use muhash::Hash as MuHash;
/// RIPEMD-160: Alias for the [`ripemd160::Hash`] hash type.
#[doc(inline)]
pub use ripemd160::Hash as Ripemd160;
diff --git a/hashes/src/muhash/mod.rs b/hashes/src/muhash/mod.rs
new file mode 100644
index 00000000..531e3cc0
--- /dev/null
+++ b/hashes/src/muhash/mod.rs
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: CC0-1.0
+
+//! MuHash3072 implementation.
+//!
+//! Unlike other hash algorithms in this crate, [`MuHash`] is a wrapper type that provides
+//! semantic meaning to a plain byte array. It cannot be computed by this crate.
+//!
+//! [`MuHash`]: `super::MuHash`
+
+/// The size in bytes of the hash output.
+const BYTE_SIZE: usize = 384;
+
+// This code is the exact same as calling `hash_type_no_default!` but excludes call to `impl_write`.
+internals::transparent_newtype! {
+ #[doc = "Output of the MuHash3072 hash function."]
+ #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+ pub struct Hash([u8; BYTE_SIZE]);
+
+ impl Hash {
+ /// Zero cost conversion between a fixed length byte array shared reference and
+ /// a shared reference to this Hash type.
+ pub fn from_bytes_ref(bytes: &_) -> &Self;
+
+ /// Zero cost conversion between a fixed length byte array exclusive reference and
+ /// an exclusive reference to this Hash type.
+ pub fn from_bytes_mut(bytes: &mut _) -> &mut Self;
+ }
+}
+
+impl Hash {
+ /// Constructs a new hash from the underlying byte array.
+ pub const fn from_byte_array(bytes: [u8; BYTE_SIZE]) -> Self { Self(bytes) }
+
+ /// Returns the underlying byte array.
+ pub const fn to_byte_array(self) -> [u8; BYTE_SIZE] { self.0 }
+
+ /// Returns a reference to the underlying byte array.
+ pub const fn as_byte_array(&self) -> &[u8; BYTE_SIZE] { &self.0 }
+}
+
+crate::internal_macros::hash_trait_impls!(BYTE_SIZE * 8, false);
diff --git a/hashes/tests/api.rs b/hashes/tests/api.rs
index 387b316d..bd53713d 100644
--- a/hashes/tests/api.rs
+++ b/hashes/tests/api.rs
@@ -18,8 +18,8 @@ use bitcoin_hashes::{
};
// Import using type alias style e.g., `Sha256`.
use bitcoin_hashes::{
- Hash160, Hkdf, Hmac, HmacEngine, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha3_256,
- Sha512, Sha512_256, Siphash24,
+ Hash160, Hkdf, Hmac, HmacEngine, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384,
+ Sha3_256, Sha512, Sha512_256, Siphash24,
};
// Arbitrary midstate value; taken from as sha256t unit tests.
@@ -172,16 +172,16 @@ struct Errors {
#[test]
fn api_can_use_modules_from_crate_root() {
use bitcoin_hashes::{
- hash160, hkdf, hmac, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512, sha512_256,
- siphash24,
+ hash160, hkdf, hmac, muhash, ripemd160, sha1, sha256, sha256d, sha256t, sha384, sha512,
+ sha512_256, siphash24,
};
}
#[test]
fn api_can_use_alias_from_crate_root() {
use bitcoin_hashes::{
- Hash160, Hkdf, Hmac, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha512, Sha512_256,
- Siphash24,
+ Hash160, Hkdf, Hmac, MuHash, Ripemd160, Sha1, Sha256, Sha256d, Sha256t, Sha384, Sha512,
+ Sha512_256, Siphash24,
};
}
Why this scored 17/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.