hashes: Add hash type name to Debug output
What changed, and why it matters
This commit only changes how hash values look when printed in debugging output. Instead of showing just the raw hex string, the debug format now also includes the type name, like 'Txid(bitcoin_hashes::sha256d::Hash(...))'. It does not change any behavior that handles real bitcoin data, secrets, or network messages, and it introduces no security risk.
No security action required. This is a cosmetic/formatting change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch modifies Debug implementations for hash wrapper types in rust-bitcoin. It replaces a shared macro-driven implementation with explicit LowerHex, UpperHex, Display, and Debug impls, and wraps the hex formatter so that debug_tuple can include core::any::type_name of the concrete hash type. Test expectations are updated to match the new output format. There are no changes to hashing logic, serialization, consensus rules, cryptography, or secret handling.
Changed components
hashes/src/macros.rsprimitives/src/hash_types/mod.rsbitcoin/src/blockdata/transaction.rsInspect captured patch +72 / −14
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 70af986e..3fdf519e 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -2105,16 +2105,23 @@ mod tests {
fn outpoint_format() {
let outpoint = OutPoint::COINBASE_PREVOUT;
- let debug = "OutPoint { txid: Txid(0000000000000000000000000000000000000000000000000000000000000000), vout: 4294967295 }";
+ let debug = "OutPoint { txid: Txid(bitcoin_hashes::sha256d::Hash(0000000000000000000000000000000000000000000000000000000000000000)), vout: 4294967295 }";
assert_eq!(debug, format!("{:?}", &outpoint));
let display = "0000000000000000000000000000000000000000000000000000000000000000:4294967295";
assert_eq!(display, format!("{}", &outpoint));
- let pretty_debug = "OutPoint {\n txid: Txid(\n 0x0000000000000000000000000000000000000000000000000000000000000000,\n ),\n vout: 4294967295,\n}";
+ let pretty_debug = "OutPoint {
+ txid: Txid(
+ bitcoin_hashes::sha256d::Hash(
+ 0x0000000000000000000000000000000000000000000000000000000000000000,
+ ),
+ ),
+ vout: 4294967295,
+}";
assert_eq!(pretty_debug, format!("{:#?}", &outpoint));
- let debug_txid = "Txid(0000000000000000000000000000000000000000000000000000000000000000)";
+ let debug_txid = "Txid(bitcoin_hashes::sha256d::Hash(0000000000000000000000000000000000000000000000000000000000000000))";
assert_eq!(debug_txid, format!("{:?}", &outpoint.txid));
let display_txid = "0000000000000000000000000000000000000000000000000000000000000000";
diff --git a/hashes/src/macros.rs b/hashes/src/macros.rs
index bc4ba68d..739f9a5c 100644
--- a/hashes/src/macros.rs
+++ b/hashes/src/macros.rs
@@ -274,10 +274,51 @@ macro_rules! impl_hex_string_traits {
}
}
- $crate::hex::impl_fmt_traits! {
- #[display_backward($reverse)]
- impl<$($gen: $gent),*> fmt_traits for $ty<$($gen),*> {
- const LENGTH: usize = ($len); // parens required due to rustc parser weirdness
+ /// Helper to prevent duplicating code for Upper/LowerHex.
+ macro_rules! impl_case_hex {
+ ($case:expr) => {
+ #[inline]
+ fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
+ if $reverse {
+ let bytes = $crate::_export::_core::borrow::Borrow::<[u8]>::borrow(self).iter().rev();
+ $crate::hex::fmt_hex_exact!(f, ($len), bytes, $case)
+ } else {
+ let bytes = $crate::_export::_core::borrow::Borrow::<[u8]>::borrow(self).iter();
+ $crate::hex::fmt_hex_exact!(f, ($len), bytes, $case)
+ }
+ }
+ }
+ }
+
+ impl<$($gen: $gent),*> $crate::_export::_core::fmt::LowerHex for $ty<$($gen),*> {
+ impl_case_hex!($crate::hex::Case::Lower);
+ }
+
+ impl<$($gen: $gent),*> $crate::_export::_core::fmt::UpperHex for $ty<$($gen),*> {
+ impl_case_hex!($crate::hex::Case::Upper);
+ }
+
+ impl<$($gen: $gent),*> $crate::_export::_core::fmt::Display for $ty<$($gen),*> {
+ #[inline]
+ fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
+ $crate::_export::_core::fmt::LowerHex::fmt(self, f)
+ }
+ }
+
+ impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> {
+ #[inline]
+ fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
+ struct HexWrap<'a, T: $crate::_export::_core::fmt::LowerHex>(&'a T);
+
+ impl<T: $crate::_export::_core::fmt::LowerHex> $crate::_export::_core::fmt::Debug for HexWrap<'_, T> {
+ fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
+ $crate::_export::_core::fmt::LowerHex::fmt(&self.0, f)
+ }
+ }
+
+ f.debug_tuple(core::any::type_name::<$ty<$($gen),*>>())
+ .field(&HexWrap(self))
+ .finish()
}
}
}
@@ -291,11 +332,21 @@ macro_rules! impl_debug_only {
impl<$($gen: $gent),*> $crate::_export::_core::fmt::Debug for $ty<$($gen),*> {
#[inline]
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
- if $reverse {
- $crate::debug_hex(self.as_byte_array().iter().rev(), f)
- } else {
- $crate::debug_hex(self.as_byte_array(), f)
+ struct HexWrap<'a, T: $crate::Hash>(&'a T);
+
+ impl<T: $crate::Hash> $crate::_export::_core::fmt::Debug for HexWrap<'_, T> {
+ fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
+ if $reverse {
+ $crate::debug_hex(self.0.as_ref().iter().rev(), f)
+ } else {
+ $crate::debug_hex(self.0.as_ref(), f)
+ }
+ }
}
+
+ f.debug_tuple(core::any::type_name::<$ty<$($gen),*>>())
+ .field(&HexWrap(self))
+ .finish()
}
}
}
@@ -579,7 +630,7 @@ mod test {
fn debug() {
use alloc::format;
- let want = "0000000000000000000000000000000000000000000000000000000000000000";
+ let want = "bitcoin_hashes::macros::test::TestHash(0000000000000000000000000000000000000000000000000000000000000000)";
let got = format!("{:?}", TestHash::all_zeros());
assert_eq!(got, want);
@@ -587,7 +638,7 @@ mod test {
let mut bytes = [0u8; 32];
bytes[31] = 0xff;
let hash = TestHash::from_byte_array(bytes);
- let want = "ff00000000000000000000000000000000000000000000000000000000000000";
+ let want = "bitcoin_hashes::macros::test::TestHash(ff00000000000000000000000000000000000000000000000000000000000000)";
let got = format!("{:?}", hash);
assert_eq!(got, want);
}
diff --git a/primitives/src/hash_types/mod.rs b/primitives/src/hash_types/mod.rs
index 8fb183e9..4c2919c9 100644
--- a/primitives/src/hash_types/mod.rs
+++ b/primitives/src/hash_types/mod.rs
@@ -214,7 +214,7 @@ mod tests {
let mut a = [0xab; 32];
a[0] = 0xff; // Just so we can see which way the array is printing.
let tc = Txid::from_byte_array(a);
- let want = "Txid(abababababababababababababababababababababababababababababababff)";
+ let want = "Txid(bitcoin_hashes::sha256d::Hash(abababababababababababababababababababababababababababababababff))";
(tc, want)
}
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.