What changed, and why it matters
This commit only adds new automated tests for Bitcoin hash types. It checks that converting hash values to and from byte arrays and hexadecimal strings works correctly. There are no changes to production code, so it cannot introduce a security vulnerability or fix one.
No security action needed. Treat as routine test-coverage improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff adds two Rust test macros (byte_array_roundtrip_test! and hex_roundtrip_test!) and invokes them for various hash types in primitives/src/hash_types/mod.rs. The tests verify from_byte_array/to_byte_array symmetry and Display/LowerHex/UpperHex formatting/parsing roundtrips under the hex feature. No runtime logic is modified.
Changed components
primitives/src/hash_types/mod.rs (tests only)Inspect captured patch +85 / −0
diff --git a/primitives/src/hash_types/mod.rs b/primitives/src/hash_types/mod.rs
index d8dee532..1056dbbc 100644
--- a/primitives/src/hash_types/mod.rs
+++ b/primitives/src/hash_types/mod.rs
@@ -201,6 +201,55 @@ pub mod serde_details {
mod tests {
use super::*;
+ macro_rules! byte_array_roundtrip_test {
+ ($name:ident, $ty:ident, $len:expr, $byte:expr $(, $check:ident)?) => {
+ #[test]
+ fn $name() {
+ let bytes = [$byte; $len];
+ let value = $ty::from_byte_array(bytes);
+
+ assert_eq!(value.to_byte_array(), bytes);
+ $(
+ let _ = stringify!($check);
+ assert_eq!(value.as_byte_array(), &bytes);
+ )?
+ }
+ };
+ }
+
+ macro_rules! hex_roundtrip_test {
+ (display, $name:ident, $ty:ident, $len:expr, $byte:expr) => {
+ #[test]
+ #[cfg(feature = "hex")]
+ fn $name() {
+ let value = $ty::from_byte_array([$byte; $len]);
+ let parsed = alloc::format!("{value}").parse::<$ty>().unwrap();
+
+ assert_eq!(parsed, value);
+ }
+ };
+ (lower, $name:ident, $ty:ident, $len:expr, $byte:expr) => {
+ #[test]
+ #[cfg(feature = "hex")]
+ fn $name() {
+ let value = $ty::from_byte_array([$byte; $len]);
+ let parsed = alloc::format!("{value:x}").parse::<$ty>().unwrap();
+
+ assert_eq!(parsed, value);
+ }
+ };
+ (upper, $name:ident, $ty:ident, $len:expr, $byte:expr) => {
+ #[test]
+ #[cfg(feature = "hex")]
+ fn $name() {
+ let value = $ty::from_byte_array([$byte; $len]);
+ let parsed = alloc::format!("{:X}", value).parse::<$ty>().unwrap();
+
+ assert_eq!(parsed, value);
+ }
+ };
+ }
+
#[cfg(feature = "serde")]
const DUMMY_TXID_HEX_STR: &str =
"e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389";
@@ -258,4 +307,40 @@ mod tests {
assert_eq!(borrowed, tc.as_byte_array());
assert_eq!(as_slice, tc.as_byte_array());
}
+
+ byte_array_roundtrip_test!(txid_byte_array_roundtrip, Txid, 32, 0x12);
+ byte_array_roundtrip_test!(ntxid_byte_array_roundtrip, Ntxid, 32, 0x13, as_byte_array);
+ byte_array_roundtrip_test!(wtxid_byte_array_roundtrip, Wtxid, 32, 0x14, as_byte_array);
+ byte_array_roundtrip_test!(block_hash_byte_array_roundtrip, BlockHash, 32, 0x15);
+ byte_array_roundtrip_test!(tx_merkle_node_byte_array_roundtrip, TxMerkleNode, 32, 0x16);
+ byte_array_roundtrip_test!(witness_merkle_node_byte_array_roundtrip, WitnessMerkleNode, 32, 0x17);
+ byte_array_roundtrip_test!(witness_commitment_byte_array_roundtrip, WitnessCommitment, 32, 0x18, as_byte_array);
+ byte_array_roundtrip_test!(script_hash_byte_array_roundtrip, ScriptHash, 20, 0x19, as_byte_array);
+ byte_array_roundtrip_test!(wscript_hash_byte_array_roundtrip, WScriptHash, 32, 0x1a, as_byte_array);
+
+ hex_roundtrip_test!(display, txid_display_roundtrip, Txid, 32, 0x1b);
+ hex_roundtrip_test!(lower, ntxid_lower_hex_roundtrip, Ntxid, 32, 0x1c);
+ hex_roundtrip_test!(lower, block_hash_lower_hex_roundtrip, BlockHash, 32, 0x1d);
+ hex_roundtrip_test!(lower, tx_merkle_node_lower_hex_roundtrip, TxMerkleNode, 32, 0x1e);
+ hex_roundtrip_test!(lower, witness_merkle_node_lower_hex_roundtrip, WitnessMerkleNode, 32, 0x1f);
+ hex_roundtrip_test!(lower, witness_commitment_lower_hex_roundtrip, WitnessCommitment, 32, 0x20);
+ hex_roundtrip_test!(lower, script_hash_lower_hex_roundtrip, ScriptHash, 20, 0x21);
+ hex_roundtrip_test!(lower, wscript_hash_lower_hex_roundtrip, WScriptHash, 32, 0x22);
+ hex_roundtrip_test!(display, ntxid_display_roundtrip, Ntxid, 32, 0x23);
+ hex_roundtrip_test!(display, wtxid_display_roundtrip, Wtxid, 32, 0x24);
+ hex_roundtrip_test!(display, block_hash_display_roundtrip, BlockHash, 32, 0x25);
+ hex_roundtrip_test!(display, tx_merkle_node_display_roundtrip, TxMerkleNode, 32, 0x26);
+ hex_roundtrip_test!(display, witness_merkle_node_display_roundtrip, WitnessMerkleNode, 32, 0x27);
+ hex_roundtrip_test!(display, witness_commitment_display_roundtrip, WitnessCommitment, 32, 0x28);
+ hex_roundtrip_test!(display, script_hash_display_roundtrip, ScriptHash, 20, 0x29);
+ hex_roundtrip_test!(display, wscript_hash_display_roundtrip, WScriptHash, 32, 0x2a);
+ hex_roundtrip_test!(upper, txid_upper_hex_roundtrip, Txid, 32, 0x2b);
+ hex_roundtrip_test!(upper, ntxid_upper_hex_roundtrip, Ntxid, 32, 0x2c);
+ hex_roundtrip_test!(upper, wtxid_upper_hex_roundtrip, Wtxid, 32, 0x2d);
+ hex_roundtrip_test!(upper, block_hash_upper_hex_roundtrip, BlockHash, 32, 0x2e);
+ hex_roundtrip_test!(upper, tx_merkle_node_upper_hex_roundtrip, TxMerkleNode, 32, 0x2f);
+ hex_roundtrip_test!(upper, witness_merkle_node_upper_hex_roundtrip, WitnessMerkleNode, 32, 0x30);
+ hex_roundtrip_test!(upper, witness_commitment_upper_hex_roundtrip, WitnessCommitment, 32, 0x31);
+ hex_roundtrip_test!(upper, script_hash_upper_hex_roundtrip, ScriptHash, 20, 0x32);
+ hex_roundtrip_test!(upper, wscript_hash_upper_hex_roundtrip, WScriptHash, 32, 0x33);
}
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.