What changed, and why it matters
This commit is a simple code relocation: it moves the implementation of serde serialization/deserialization for the U256 type from one internal file to another, without changing the actual logic. There is no security-relevant change visible in the diff.
No security action required. Treat as a normal refactoring commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch moves the serde::Serialize and serde::Deserialize trait implementations for U256 from include/u256.rs to units/src/pow.rs. The implementation is byte-for-byte identical, including the human-readable hex string handling and the non-human-readable big-endian byte handling. A now-unused use units::parse_int; import is removed from bitcoin/src/pow.rs. No functional or security behavior is altered.
Changed components
include/u256.rsunits/src/pow.rsbitcoin/src/pow.rsInspect captured patch +88 / −90
diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs
index 6eb72a5a..fbfd5e35 100644
--- a/bitcoin/src/pow.rs
+++ b/bitcoin/src/pow.rs
@@ -10,8 +10,6 @@ use core::ops::{Add, Div, Mul, Not, Rem, Shl, Shr, Sub};
use core::{cmp, fmt};
use io::{BufRead, Write};
-#[cfg(feature = "serde")]
-use units::parse_int;
use crate::block::{BlockHash, BlockHeight, BlockHeightInterval, Header};
use crate::consensus::encode::{self, Decodable, Encodable};
diff --git a/include/u256.rs b/include/u256.rs
index 0f8346cb..a5229dd3 100644
--- a/include/u256.rs
+++ b/include/u256.rs
@@ -508,94 +508,6 @@ impl core::str::FromStr for U256 {
}
}
-#[cfg(feature = "serde")]
-impl serde::Serialize for U256 {
- fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
- where
- S: serde::Serializer,
- {
- struct DisplayHex(U256);
-
- impl fmt::Display for DisplayHex {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}", self.0) }
- }
-
- if serializer.is_human_readable() {
- serializer.collect_str(&DisplayHex(*self))
- } else {
- let bytes = self.to_be_bytes();
- serializer.serialize_bytes(&bytes)
- }
- }
-}
-
-#[cfg(feature = "serde")]
-impl<'de> serde::Deserialize<'de> for U256 {
- fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
- use serde::de;
-
- if d.is_human_readable() {
- struct HexVisitor;
-
- impl de::Visitor<'_> for HexVisitor {
- type Value = U256;
-
- fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
- f.write_str("a 32 byte ASCII hex string")
- }
-
- fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- if s.len() != 64 {
- return Err(de::Error::invalid_length(s.len(), &self));
- }
-
- let upper = parse_int::hex_u128_unprefixed(&s[..32])
- .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?;
- let lower = parse_int::hex_u128_unprefixed(&s[32..])
- .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?;
-
- Ok(U256(upper, lower))
- }
-
- fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
- where
- E: de::Error,
- {
- if let Ok(hex) = core::str::from_utf8(v) {
- self.visit_str(hex)
- } else {
- Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
- }
- }
- }
- d.deserialize_str(HexVisitor)
- } else {
- struct BytesVisitor;
-
- impl serde::de::Visitor<'_> for BytesVisitor {
- type Value = U256;
-
- fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- f.write_str("a sequence of bytes")
- }
-
- fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
- where
- E: serde::de::Error,
- {
- let b = v.try_into().map_err(|_| de::Error::invalid_length(v.len(), &self))?;
- Ok(U256::from_be_bytes(b))
- }
- }
-
- d.deserialize_bytes(BytesVisitor)
- }
- }
-}
-
/// Error returned when parsing a [`U256`] from a string.
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
diff --git a/units/src/pow.rs b/units/src/pow.rs
index 1c7ccee6..9d7d5b47 100644
--- a/units/src/pow.rs
+++ b/units/src/pow.rs
@@ -475,6 +475,94 @@ impl_hex!(
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F']
);
+#[cfg(feature = "serde")]
+impl serde::Serialize for U256 {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::Serializer,
+ {
+ struct DisplayHex(U256);
+
+ impl fmt::Display for DisplayHex {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{:x}", self.0) }
+ }
+
+ if serializer.is_human_readable() {
+ serializer.collect_str(&DisplayHex(*self))
+ } else {
+ let bytes = self.to_be_bytes();
+ serializer.serialize_bytes(&bytes)
+ }
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for U256 {
+ fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
+ use serde::de;
+
+ if d.is_human_readable() {
+ struct HexVisitor;
+
+ impl de::Visitor<'_> for HexVisitor {
+ type Value = U256;
+
+ fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_str("a 32 byte ASCII hex string")
+ }
+
+ fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ if s.len() != 64 {
+ return Err(de::Error::invalid_length(s.len(), &self));
+ }
+
+ let upper = parse_int::hex_u128_unprefixed(&s[..32])
+ .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?;
+ let lower = parse_int::hex_u128_unprefixed(&s[32..])
+ .map_err(|_| de::Error::invalid_value(de::Unexpected::Str(s), &self))?;
+
+ Ok(U256(upper, lower))
+ }
+
+ fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
+ where
+ E: de::Error,
+ {
+ if let Ok(hex) = core::str::from_utf8(v) {
+ self.visit_str(hex)
+ } else {
+ Err(E::invalid_value(::serde::de::Unexpected::Bytes(v), &self))
+ }
+ }
+ }
+ d.deserialize_str(HexVisitor)
+ } else {
+ struct BytesVisitor;
+
+ impl serde::de::Visitor<'_> for BytesVisitor {
+ type Value = U256;
+
+ fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
+ f.write_str("a sequence of bytes")
+ }
+
+ fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
+ where
+ E: serde::de::Error,
+ {
+ let b = v.try_into().map_err(|_| de::Error::invalid_length(v.len(), &self))?;
+ Ok(U256::from_be_bytes(b))
+ }
+ }
+
+ d.deserialize_bytes(BytesVisitor)
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
#[cfg(feature = "alloc")]
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.