units: Implement serde traits for relative lock times
What changed, and why it matters
This commit adds standard data serialization/deserialization support (serde traits) for two relative lock time types in the rust-bitcoin library. It is a routine API completeness change with no security relevance visible in the code or commit message.
No security action required. Review as a normal API-guideline compliance change.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch implements Serialize and Deserialize for NumberOfBlocks and NumberOf512Seconds under the existing serde feature gate. Serialization uses the canonical unit representations (block height and 512-second intervals respectively) and deserialization delegates to the existing u16-based constructors, which are infallible for the valid u16 range. No new unsafe code, no parsing of untrusted formats beyond what serde already handles, and no changes to consensus-critical logic.
Changed components
units/src/locktime/relative/mod.rsInspect captured patch +45 / −0
diff --git a/units/src/locktime/relative/mod.rs b/units/src/locktime/relative/mod.rs
index 4ae2afda..76441629 100644
--- a/units/src/locktime/relative/mod.rs
+++ b/units/src/locktime/relative/mod.rs
@@ -13,6 +13,8 @@ use core::{convert, fmt};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use internals::const_casts;
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::parse_int::{self, PrefixedHexError, UnprefixedHexError};
#[cfg(doc)]
@@ -459,6 +461,27 @@ impl fmt::Display for NumberOfBlocks {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
+#[cfg(feature = "serde")]
+impl Serialize for NumberOfBlocks {
+ #[inline]
+ fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ u16::serialize(&self.to_height(), s)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> Deserialize<'de> for NumberOfBlocks {
+ #[inline]
+ fn deserialize<D>(d: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ Ok(Self::from_height(u16::deserialize(d)?))
+ }
+}
/// A relative lock time lock-by-time value.
///
@@ -576,6 +599,28 @@ impl fmt::Display for NumberOf512Seconds {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
+#[cfg(feature = "serde")]
+impl Serialize for NumberOf512Seconds {
+ #[inline]
+ fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ u16::serialize(&self.to_512_second_intervals(), s)
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de> Deserialize<'de> for NumberOf512Seconds {
+ #[inline]
+ fn deserialize<D>(d: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ Ok(Self::from_512_second_intervals(u16::deserialize(d)?))
+ }
+}
+
#[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for LockTime {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
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.