primitives: Add fmt traits for simple wrapper types
What changed, and why it matters
This commit adds extra text formatting abilities (like showing numbers in hexadecimal, binary, or octal) to three simple numeric wrapper types in the rust-bitcoin library: block version, transaction version, and compact target. It is a routine usability improvement with no security relevance.
No security action needed; treat as normal feature/maintenance commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch implements core::fmt::Binary, LowerHex, UpperHex, Octal, and Display traits for CompactTarget, block::Version, and transaction::Version by delegating to the underlying u32. It also updates public API snapshots and adds unit tests verifying formatting output. No logic, serialization, consensus rules, or cryptographic code is changed.
Changed components
primitives/src/block.rsprimitives/src/pow.rsprimitives/src/transaction.rsInspect captured patch +127 / −0
diff --git a/api/primitives/all-features.txt b/api/primitives/all-features.txt
index 323d71d9..9077f82c 100644
--- a/api/primitives/all-features.txt
+++ b/api/primitives/all-features.txt
@@ -379,6 +379,9 @@ impl core::error::Error for bitcoin_primitives::transaction::TxOutDecoderError
impl core::error::Error for bitcoin_primitives::transaction::VersionDecoderError
impl core::error::Error for bitcoin_primitives::witness::UnexpectedEofError
impl core::error::Error for bitcoin_primitives::witness::WitnessDecoderError
+impl core::fmt::Binary for bitcoin_primitives::block::Version
+impl core::fmt::Binary for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::Binary for bitcoin_primitives::transaction::Version
impl core::fmt::Debug for bitcoin_primitives::BlockHash
impl core::fmt::Debug for bitcoin_primitives::Ntxid
impl core::fmt::Debug for bitcoin_primitives::TxMerkleNode
@@ -432,7 +435,9 @@ impl core::fmt::Display for bitcoin_primitives::block::Header
impl core::fmt::Display for bitcoin_primitives::block::HeaderDecoderError
impl core::fmt::Display for bitcoin_primitives::block::InvalidBlockError
impl core::fmt::Display for bitcoin_primitives::block::ParseHeaderError
+impl core::fmt::Display for bitcoin_primitives::block::Version
impl core::fmt::Display for bitcoin_primitives::block::VersionDecoderError
+impl core::fmt::Display for bitcoin_primitives::pow::CompactTarget
impl core::fmt::Display for bitcoin_primitives::pow::CompactTargetDecoderError
impl core::fmt::Display for bitcoin_primitives::script::RedeemScriptSizeError
impl core::fmt::Display for bitcoin_primitives::script::ScriptBufDecoderError
@@ -460,10 +465,15 @@ impl core::fmt::LowerHex for bitcoin_primitives::WitnessCommitment
impl core::fmt::LowerHex for bitcoin_primitives::WitnessMerkleNode
impl core::fmt::LowerHex for bitcoin_primitives::Wtxid
impl core::fmt::LowerHex for bitcoin_primitives::block::Header
+impl core::fmt::LowerHex for bitcoin_primitives::block::Version
impl core::fmt::LowerHex for bitcoin_primitives::pow::CompactTarget
impl core::fmt::LowerHex for bitcoin_primitives::script::ScriptHash
impl core::fmt::LowerHex for bitcoin_primitives::script::WScriptHash
impl core::fmt::LowerHex for bitcoin_primitives::transaction::Transaction
+impl core::fmt::LowerHex for bitcoin_primitives::transaction::Version
+impl core::fmt::Octal for bitcoin_primitives::block::Version
+impl core::fmt::Octal for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::Octal for bitcoin_primitives::transaction::Version
impl core::fmt::UpperHex for bitcoin_primitives::BlockHash
impl core::fmt::UpperHex for bitcoin_primitives::Ntxid
impl core::fmt::UpperHex for bitcoin_primitives::TxMerkleNode
@@ -472,10 +482,12 @@ impl core::fmt::UpperHex for bitcoin_primitives::WitnessCommitment
impl core::fmt::UpperHex for bitcoin_primitives::WitnessMerkleNode
impl core::fmt::UpperHex for bitcoin_primitives::Wtxid
impl core::fmt::UpperHex for bitcoin_primitives::block::Header
+impl core::fmt::UpperHex for bitcoin_primitives::block::Version
impl core::fmt::UpperHex for bitcoin_primitives::pow::CompactTarget
impl core::fmt::UpperHex for bitcoin_primitives::script::ScriptHash
impl core::fmt::UpperHex for bitcoin_primitives::script::WScriptHash
impl core::fmt::UpperHex for bitcoin_primitives::transaction::Transaction
+impl core::fmt::UpperHex for bitcoin_primitives::transaction::Version
impl core::hash::Hash for bitcoin_primitives::BlockHash
impl core::hash::Hash for bitcoin_primitives::Ntxid
impl core::hash::Hash for bitcoin_primitives::TxMerkleNode
diff --git a/api/primitives/alloc-only.txt b/api/primitives/alloc-only.txt
index f6b7bd2d..ab653f82 100644
--- a/api/primitives/alloc-only.txt
+++ b/api/primitives/alloc-only.txt
@@ -354,6 +354,9 @@ impl core::default::Default for bitcoin_primitives::transaction::TxMerkleNodeDec
impl core::default::Default for bitcoin_primitives::transaction::VersionDecoder
impl core::default::Default for bitcoin_primitives::witness::Witness
impl core::default::Default for bitcoin_primitives::witness::WitnessDecoder
+impl core::fmt::Binary for bitcoin_primitives::block::Version
+impl core::fmt::Binary for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::Binary for bitcoin_primitives::transaction::Version
impl core::fmt::Debug for bitcoin_primitives::BlockHash
impl core::fmt::Debug for bitcoin_primitives::Ntxid
impl core::fmt::Debug for bitcoin_primitives::TxMerkleNode
@@ -395,7 +398,9 @@ impl core::fmt::Display for bitcoin_primitives::block::BlockDecoderError
impl core::fmt::Display for bitcoin_primitives::block::BlockHashDecoderError
impl core::fmt::Display for bitcoin_primitives::block::HeaderDecoderError
impl core::fmt::Display for bitcoin_primitives::block::InvalidBlockError
+impl core::fmt::Display for bitcoin_primitives::block::Version
impl core::fmt::Display for bitcoin_primitives::block::VersionDecoderError
+impl core::fmt::Display for bitcoin_primitives::pow::CompactTarget
impl core::fmt::Display for bitcoin_primitives::pow::CompactTargetDecoderError
impl core::fmt::Display for bitcoin_primitives::script::RedeemScriptSizeError
impl core::fmt::Display for bitcoin_primitives::script::ScriptBufDecoderError
@@ -409,8 +414,15 @@ impl core::fmt::Display for bitcoin_primitives::transaction::Version
impl core::fmt::Display for bitcoin_primitives::transaction::VersionDecoderError
impl core::fmt::Display for bitcoin_primitives::witness::UnexpectedEofError
impl core::fmt::Display for bitcoin_primitives::witness::WitnessDecoderError
+impl core::fmt::LowerHex for bitcoin_primitives::block::Version
impl core::fmt::LowerHex for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::LowerHex for bitcoin_primitives::transaction::Version
+impl core::fmt::Octal for bitcoin_primitives::block::Version
+impl core::fmt::Octal for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::Octal for bitcoin_primitives::transaction::Version
+impl core::fmt::UpperHex for bitcoin_primitives::block::Version
impl core::fmt::UpperHex for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::UpperHex for bitcoin_primitives::transaction::Version
impl core::hash::Hash for bitcoin_primitives::BlockHash
impl core::hash::Hash for bitcoin_primitives::Ntxid
impl core::hash::Hash for bitcoin_primitives::TxMerkleNode
diff --git a/api/primitives/no-features.txt b/api/primitives/no-features.txt
index 26e73edd..db11642e 100644
--- a/api/primitives/no-features.txt
+++ b/api/primitives/no-features.txt
@@ -174,6 +174,9 @@ impl core::default::Default for bitcoin_primitives::pow::CompactTargetDecoder
impl core::default::Default for bitcoin_primitives::transaction::OutPointDecoder
impl core::default::Default for bitcoin_primitives::transaction::TxMerkleNodeDecoder
impl core::default::Default for bitcoin_primitives::transaction::VersionDecoder
+impl core::fmt::Binary for bitcoin_primitives::block::Version
+impl core::fmt::Binary for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::Binary for bitcoin_primitives::transaction::Version
impl core::fmt::Debug for bitcoin_primitives::BlockHash
impl core::fmt::Debug for bitcoin_primitives::Ntxid
impl core::fmt::Debug for bitcoin_primitives::TxMerkleNode
@@ -193,14 +196,23 @@ impl core::fmt::Debug for bitcoin_primitives::transaction::TxMerkleNodeDecoderEr
impl core::fmt::Debug for bitcoin_primitives::transaction::Version
impl core::fmt::Debug for bitcoin_primitives::transaction::VersionDecoderError
impl core::fmt::Display for bitcoin_primitives::block::BlockHashDecoderError
+impl core::fmt::Display for bitcoin_primitives::block::Version
impl core::fmt::Display for bitcoin_primitives::block::VersionDecoderError
+impl core::fmt::Display for bitcoin_primitives::pow::CompactTarget
impl core::fmt::Display for bitcoin_primitives::pow::CompactTargetDecoderError
impl core::fmt::Display for bitcoin_primitives::transaction::OutPointDecoderError
impl core::fmt::Display for bitcoin_primitives::transaction::TxMerkleNodeDecoderError
impl core::fmt::Display for bitcoin_primitives::transaction::Version
impl core::fmt::Display for bitcoin_primitives::transaction::VersionDecoderError
+impl core::fmt::LowerHex for bitcoin_primitives::block::Version
impl core::fmt::LowerHex for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::LowerHex for bitcoin_primitives::transaction::Version
+impl core::fmt::Octal for bitcoin_primitives::block::Version
+impl core::fmt::Octal for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::Octal for bitcoin_primitives::transaction::Version
+impl core::fmt::UpperHex for bitcoin_primitives::block::Version
impl core::fmt::UpperHex for bitcoin_primitives::pow::CompactTarget
+impl core::fmt::UpperHex for bitcoin_primitives::transaction::Version
impl core::hash::Hash for bitcoin_primitives::BlockHash
impl core::hash::Hash for bitcoin_primitives::Ntxid
impl core::hash::Hash for bitcoin_primitives::TxMerkleNode
diff --git a/primitives/src/block.rs b/primitives/src/block.rs
index 052ac10b..ee1e7f5b 100644
--- a/primitives/src/block.rs
+++ b/primitives/src/block.rs
@@ -800,6 +800,32 @@ impl Version {
}
}
+impl fmt::Display for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
+}
+
+impl fmt::LowerHex for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
+}
+
+impl fmt::UpperHex for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
+}
+
+impl fmt::Octal for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Octal::fmt(&self.0, f) }
+}
+
+impl fmt::Binary for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Binary::fmt(&self.0, f) }
+
+}
+
impl Default for Version {
#[inline]
fn default() -> Self { Self::NO_SOFT_FORK_SIGNALLING }
@@ -980,6 +1006,21 @@ mod tests {
assert_eq!(version.to_consensus(), Version::NO_SOFT_FORK_SIGNALLING.to_consensus());
}
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn version_display() {
+ let version = Version(75);
+ assert_eq!(format!("{}", version), "75");
+ assert_eq!(format!("{:x}", version), "4b");
+ assert_eq!(format!("{:#x}", version), "0x4b");
+ assert_eq!(format!("{:X}", version), "4B");
+ assert_eq!(format!("{:#X}", version), "0x4B");
+ assert_eq!(format!("{:o}", version), "113");
+ assert_eq!(format!("{:#o}", version), "0o113");
+ assert_eq!(format!("{:b}", version), "1001011");
+ assert_eq!(format!("{:#b}", version), "0b1001011");
+ }
+
// Check that the size of the header consensus serialization matches the const SIZE value
#[test]
fn header_size() {
diff --git a/primitives/src/pow.rs b/primitives/src/pow.rs
index a7f1c813..25c47186 100644
--- a/primitives/src/pow.rs
+++ b/primitives/src/pow.rs
@@ -41,6 +41,11 @@ impl CompactTarget {
pub fn to_hex(self) -> alloc::string::String { alloc::format!("{:x}", self) }
}
+impl fmt::Display for CompactTarget {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
+}
+
impl fmt::LowerHex for CompactTarget {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
@@ -51,6 +56,16 @@ impl fmt::UpperHex for CompactTarget {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
}
+impl fmt::Octal for CompactTarget {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Octal::fmt(&self.0, f) }
+}
+
+impl fmt::Binary for CompactTarget {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Binary::fmt(&self.0, f) }
+}
+
encoding::encoder_newtype_exact! {
/// The encoder for the [`CompactTarget`] type.
pub struct CompactTargetEncoder(encoding::ArrayEncoder<4>);
@@ -188,8 +203,15 @@ mod tests {
#[cfg(feature = "alloc")]
fn compact_target_formatting() {
let compact_target = CompactTarget::from_consensus(0x1d00_ffff);
+ assert_eq!(format!("{}", compact_target), "486604799");
assert_eq!(format!("{:x}", compact_target), "1d00ffff");
+ assert_eq!(format!("{:#x}", compact_target), "0x1d00ffff");
assert_eq!(format!("{:X}", compact_target), "1D00FFFF");
+ assert_eq!(format!("{:#X}", compact_target), "0x1D00FFFF");
+ assert_eq!(format!("{:o}", compact_target), "3500177777");
+ assert_eq!(format!("{:#o}", compact_target), "0o3500177777");
+ assert_eq!(format!("{:b}", compact_target), "11101000000001111111111111111");
+ assert_eq!(format!("{:#b}", compact_target), "0b11101000000001111111111111111");
assert_eq!(compact_target.to_consensus(), 0x1d00_ffff);
}
}
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index 61024cbb..444a890f 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -1497,6 +1497,26 @@ impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
}
+impl fmt::LowerHex for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
+}
+
+impl fmt::UpperHex for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
+}
+
+impl fmt::Octal for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Octal::fmt(&self.0, f) }
+}
+
+impl fmt::Binary for Version {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Binary::fmt(&self.0, f) }
+}
+
impl From<Version> for u32 {
#[inline]
fn from(version: Version) -> Self { version.0 }
@@ -1870,6 +1890,14 @@ mod tests {
fn version_display() {
let version = Version(123);
assert_eq!(format!("{}", version), "123");
+ assert_eq!(format!("{:x}", version), "7b");
+ assert_eq!(format!("{:#x}", version), "0x7b");
+ assert_eq!(format!("{:X}", version), "7B");
+ assert_eq!(format!("{:#X}", version), "0x7B");
+ assert_eq!(format!("{:o}", version), "173");
+ assert_eq!(format!("{:#o}", version), "0o173");
+ assert_eq!(format!("{:b}", version), "1111011");
+ assert_eq!(format!("{:#b}", version), "0b1111011");
}
// Creates an arbitrary dummy outpoint.
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.