units: Add derives to encoders and decoders
What changed, and why it matters
This commit adds standard Rust helper traits (Debug and Clone) to a set of data encoder/decoder structs in the rust-bitcoin library. These traits only affect how developers can print, inspect, or duplicate encoder/decoder objects; they do not change serialization logic, parsing rules, or security behavior. There is no indication this fixes a vulnerability.
No security action required. Treat as a normal API-ergonomics improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch derives Debug and Clone on six Encoder and six Decoder newtypes in the units crate (Amount, BlockHeight, LockTime, CompactTarget, Sequence, BlockTime). These are pure convenience derives. The underlying ArrayEncoder/ArrayDecoder types already carried these derives in consensus_encoding, so this change merely brings parity. No logic, bounds checking, or encoding format is altered.
Changed components
units/src/amount/unsigned.rsunits/src/block.rsunits/src/locktime/absolute/mod.rsunits/src/pow.rsunits/src/sequence.rsunits/src/time.rsInspect captured patch +12 / −0
diff --git a/units/src/amount/unsigned.rs b/units/src/amount/unsigned.rs
index c052f0a9..ff08fd0a 100644
--- a/units/src/amount/unsigned.rs
+++ b/units/src/amount/unsigned.rs
@@ -591,6 +591,7 @@ impl TryFrom<SignedAmount> for Amount {
#[cfg(feature = "encoding")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`Amount`] type.
+ #[derive(Debug, Clone)]
pub struct AmountEncoder<'e>(encoding::ArrayEncoder<8>);
}
@@ -606,6 +607,7 @@ impl encoding::Encodable for Amount {
/// The decoder for the [`Amount`] type.
#[cfg(feature = "encoding")]
+#[derive(Debug, Clone)]
pub struct AmountDecoder(encoding::ArrayDecoder<8>);
#[cfg(feature = "encoding")]
diff --git a/units/src/block.rs b/units/src/block.rs
index 7aee6320..2a743a3c 100644
--- a/units/src/block.rs
+++ b/units/src/block.rs
@@ -198,6 +198,7 @@ impl TryFrom<BlockHeight> for absolute::Height {
#[cfg(feature = "encoding")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`BlockHeight`] type.
+ #[derive(Debug, Clone)]
pub struct BlockHeightEncoder<'e>(encoding::ArrayEncoder<4>);
}
@@ -213,6 +214,7 @@ impl encoding::Encodable for BlockHeight {
/// The decoder for the [`BlockHeight`] type.
#[cfg(feature = "encoding")]
+#[derive(Debug, Clone)]
pub struct BlockHeightDecoder(encoding::ArrayDecoder<4>);
#[cfg(feature = "encoding")]
diff --git a/units/src/locktime/absolute/mod.rs b/units/src/locktime/absolute/mod.rs
index 4d7b30ad..510f799f 100644
--- a/units/src/locktime/absolute/mod.rs
+++ b/units/src/locktime/absolute/mod.rs
@@ -400,6 +400,7 @@ parse_int::impl_parse_str_from_int_infallible!(LockTime, u32, from_consensus);
#[cfg(feature = "encoding")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`LockTime`] type.
+ #[derive(Debug, Clone)]
pub struct LockTimeEncoder<'e>(encoding::ArrayEncoder<4>);
}
@@ -415,6 +416,7 @@ impl encoding::Encodable for LockTime {
/// The decoder for the [`LockTime`] type.
#[cfg(feature = "encoding")]
+#[derive(Debug, Clone)]
pub struct LockTimeDecoder(encoding::ArrayDecoder<4>);
#[cfg(feature = "encoding")]
diff --git a/units/src/pow.rs b/units/src/pow.rs
index 53403819..0553f53a 100644
--- a/units/src/pow.rs
+++ b/units/src/pow.rs
@@ -90,6 +90,7 @@ parse_int::impl_parse_str_from_int_infallible!(CompactTarget, u32, from_consensu
#[cfg(feature = "encoding")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`CompactTarget`] type.
+ #[derive(Debug, Clone)]
pub struct CompactTargetEncoder<'e>(encoding::ArrayEncoder<4>);
}
@@ -105,6 +106,7 @@ impl encoding::Encodable for CompactTarget {
/// The decoder for the [`CompactTarget`] type.
#[cfg(feature = "encoding")]
+#[derive(Debug, Clone)]
pub struct CompactTargetDecoder(encoding::ArrayDecoder<4>);
#[cfg(feature = "encoding")]
diff --git a/units/src/sequence.rs b/units/src/sequence.rs
index 0007a8e4..19dca441 100644
--- a/units/src/sequence.rs
+++ b/units/src/sequence.rs
@@ -261,6 +261,7 @@ parse_int::impl_parse_str_from_int_infallible!(Sequence, u32, from_consensus);
#[cfg(feature = "encoding")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`Sequence`] type.
+ #[derive(Debug, Clone)]
pub struct SequenceEncoder<'e>(encoding::ArrayEncoder<4>);
}
@@ -276,6 +277,7 @@ impl encoding::Encodable for Sequence {
/// The decoder for the [`Sequence`] type.
#[cfg(feature = "encoding")]
+#[derive(Debug, Clone)]
pub struct SequenceDecoder(encoding::ArrayDecoder<4>);
#[cfg(feature = "encoding")]
diff --git a/units/src/time.rs b/units/src/time.rs
index a3fa5f92..c9f88549 100644
--- a/units/src/time.rs
+++ b/units/src/time.rs
@@ -119,6 +119,7 @@ impl<'de> Deserialize<'de> for BlockTime {
#[cfg(feature = "encoding")]
encoding::encoder_newtype_exact! {
/// The encoder for the [`BlockTime`] type.
+ #[derive(Debug, Clone)]
pub struct BlockTimeEncoder<'e>(encoding::ArrayEncoder<4>);
}
@@ -134,6 +135,7 @@ impl encoding::Encodable for BlockTime {
/// The decoder for the [`BlockTime`] type.
#[cfg(feature = "encoding")]
+#[derive(Debug, Clone)]
pub struct BlockTimeDecoder(encoding::ArrayDecoder<4>);
#[cfg(feature = "encoding")]
Why this scored 20/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.