What changed, and why it matters
This commit only adds new unit tests for the existing hexadecimal encoding/decoding code. It does not change any production logic, so it cannot introduce or fix a security vulnerability on its own.
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 test cases in primitives/src/block.rs, primitives/src/hex_codec.rs, and primitives/src/transaction.rs. The tests exercise Display/UpperHex formatting flags, ParsePrimitiveError Clone/PartialEq behavior, and a large-buffer hex decode flush path. No runtime code is modified; only #[cfg(test)] blocks are expanded.
Changed components
primitives/src/block.rs testsprimitives/src/hex_codec.rs testsprimitives/src/transaction.rs testsInspect captured patch +55 / −1
diff --git a/primitives/src/block.rs b/primitives/src/block.rs
index 2fcc4c38..2d8dbc4d 100644
--- a/primitives/src/block.rs
+++ b/primitives/src/block.rs
@@ -1525,6 +1525,10 @@ mod tests {
assert_eq!(format!("{}", block), want);
assert_eq!(format!("{:x}", block), want);
+ assert_eq!(format!("0x{want}"), format!("{:#x}", block));
+ assert_eq!(format!("0X{}", want.to_ascii_uppercase()), format!("{:#X}", block));
+ assert_eq!(format!("{:>166}", format!("0x{want}")), format!("{:>#166x}", block));
+ assert_eq!(format!("{:.20}", want), format!("{:.20x}", block));
// Note this is pointless because the hex does not have letters in it, only numbers.
let want =
diff --git a/primitives/src/hex_codec.rs b/primitives/src/hex_codec.rs
index 787bfd4e..4bb19914 100644
--- a/primitives/src/hex_codec.rs
+++ b/primitives/src/hex_codec.rs
@@ -233,10 +233,11 @@ impl<T: Decodable> std::error::Error for ParsePrimitiveError<T> {
#[cfg(test)]
mod tests {
#[cfg(feature = "alloc")]
- use alloc::{format, string::ToString};
+ use alloc::{format, string::ToString, vec};
#[cfg(feature = "alloc")]
use super::*;
+ #[cfg(feature = "alloc")]
use crate::block;
#[test]
@@ -275,4 +276,47 @@ mod tests {
assert_eq!((&hex).into_iter().next(), Some(0u8));
assert!(!format!("{hex:?}").is_empty());
}
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn hex_primitive_from_str_flushes_full_buffer() {
+ // 300 headers force multiple full 4096-byte decoder flushes plus a final remainder flush.
+ let bytes = vec![0u8; block::Header::SIZE * 300];
+ let encoded = hex_unstable::DisplayHex::as_hex(&bytes).to_string();
+
+ let parsed = HexPrimitive::<block::Header>::from_str(&encoded).unwrap();
+
+ assert_eq!(parsed.version.to_consensus(), 0);
+ assert_eq!(parsed.prev_blockhash, crate::hash_types::BlockHash::from_byte_array([0; 32]));
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn hex_primitive_upper_hex_with_alternate_prefix() {
+ let header: block::Header =
+ encoding::decode_from_slice(&[0u8; block::Header::SIZE]).expect("valid header");
+
+ assert!(format!("{:#X}", HexPrimitive(&header)).starts_with("0X"));
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn parse_primitive_error_clone() {
+ let odd: ParsePrimitiveError<block::Header> = HexPrimitive::from_str("0").unwrap_err();
+ let invalid: ParsePrimitiveError<block::Header> = HexPrimitive::from_str("zz").unwrap_err();
+ let decode: ParsePrimitiveError<block::Header> = HexPrimitive::from_str("00").unwrap_err();
+
+ assert_eq!(odd.clone(), odd);
+ assert_eq!(invalid.clone(), invalid);
+ assert_eq!(decode.clone(), decode);
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn parse_primitive_error_partial_eq_false_for_different_variants() {
+ let odd: ParsePrimitiveError<block::Header> = HexPrimitive::from_str("0").unwrap_err();
+ let invalid: ParsePrimitiveError<block::Header> = HexPrimitive::from_str("zz").unwrap_err();
+
+ assert_ne!(odd, invalid);
+ }
}
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index 80ce6e9d..a8da3f95 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -1759,6 +1759,11 @@ mod tests {
// All of these should yield a lowercase hex
assert_eq!(encoded_tx, lower_hex_tx);
assert_eq!(encoded_tx, format!("{}", tx_orig));
+ assert_eq!(format!("0x{encoded_tx}"), format!("{:#x}", tx_orig));
+ assert_eq!(format!("{:>132}", encoded_tx), format!("{:>132x}", tx_orig));
+ assert_eq!(format!("{:<132}", encoded_tx), format!("{:<132x}", tx_orig));
+ assert_eq!(format!("{:^132}", encoded_tx), format!("{:^132x}", tx_orig));
+ assert_eq!(format!("{:.20}", encoded_tx), format!("{:.20x}", tx_orig));
// And this should yield uppercase hex
let upper_encoded = encoded_tx
@@ -1766,6 +1771,7 @@ mod tests {
.map(|chr| chr.to_ascii_uppercase())
.collect::<alloc::string::String>();
assert_eq!(upper_encoded, upper_hex_tx);
+ assert_eq!(format!("0X{upper_encoded}"), format!("{:#X}", tx_orig));
}
#[test]
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.