Replace impl_to_hex_from_lower_hex with deprecated inherent to_hex
What changed, and why it matters
This is a routine code cleanup change. It replaces an internal helper macro that generated `to_hex` methods with manually-written, equivalent `to_hex` methods that are marked as deprecated. The public API behavior stays the same; callers will just receive a deprecation warning encouraging them to use Rust's standard `format!("{var:x}")` instead. There is no security fix or vulnerability here.
No security action required. Treat as a normal API-deprecation commit. Downstream users may want to migrate from `to_hex()` to `format!("{var:x}")` when convenient, but this is not security-relevant.
Security signals we found
No security signals present in the diff or commit message.
Change is a pure refactor/deprecation with behavioral equivalence.
Evidence from the diff
The commit removes internals::impl_to_hex_from_lower_hex!, a macro that implemented pub fn to_hex(&self) -> String by pre-allocating a buffer of a caller-supplied length and writing via core::fmt::Write. It adds inherent to_hex methods on the affected types (SerializedSignature, XOnlyPublicKey, TweakedPublicKey, ServiceFlags, Magic, LeafVersion, FutureLeafVersion) that use alloc::format!("{:x}", self) and are annotated with #[deprecated(...)]. Functionality is preserved; the change is API-maintenance and deprecation groundwork.
Changed components
crypto/src/ecdsa.rscrypto/src/key.rscrypto/src/taproot.rsinternals/src/macros.rsp2p/src/lib.rstaproot-primitives/src/lib.rsInspect captured patch +49 / −50
diff --git a/crypto/src/ecdsa.rs b/crypto/src/ecdsa.rs
index 527db78a..58ad265d 100644
--- a/crypto/src/ecdsa.rs
+++ b/crypto/src/ecdsa.rs
@@ -4,6 +4,9 @@
//!
//! This module provides ECDSA signatures used by Bitcoin that can be roundtrip (de)serialized.
+#[cfg(feature = "hex")]
+#[cfg(feature = "alloc")]
+use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::borrow::Borrow;
@@ -19,9 +22,6 @@ use core::str::FromStr;
use arbitrary::{Arbitrary, Unstructured};
#[cfg(feature = "hex")]
use hex::DisplayHex;
-#[cfg(feature = "hex")]
-#[cfg(feature = "alloc")]
-use internals::impl_to_hex_from_lower_hex;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@@ -161,6 +161,12 @@ impl SerializedSignature {
/// Returns an iterator over bytes of the signature.
#[inline]
pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() }
+
+ /// Gets the hex representation of this type.
+ #[cfg(feature = "hex")]
+ #[cfg(feature = "alloc")]
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl fmt::Debug for SerializedSignature {
@@ -193,10 +199,6 @@ impl fmt::LowerHex for SerializedSignature {
fmt::LowerHex::fmt(&(**self).as_hex(), f)
}
}
-#[cfg(feature = "hex")]
-#[cfg(feature = "alloc")]
-impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignature| signature.len
- * 2);
#[cfg(feature = "hex")]
impl fmt::UpperHex for SerializedSignature {
diff --git a/crypto/src/key.rs b/crypto/src/key.rs
index d36f1cf0..851210b2 100644
--- a/crypto/src/key.rs
+++ b/crypto/src/key.rs
@@ -21,8 +21,6 @@ use hex::DisplayHex;
#[cfg(feature = "alloc")]
use internals::array::ArrayExt;
use internals::array_vec::ArrayVec;
-#[cfg(feature = "alloc")]
-use internals::impl_to_hex_from_lower_hex;
use network::NetworkKind;
#[cfg(feature = "rand")]
#[cfg(feature = "std")]
@@ -450,6 +448,11 @@ impl XOnlyPublicKey {
Err(_) => Err(TweakXOnlyPublicKeyError::ResultKeyInvalid),
}
}
+
+ /// Gets the hex representation of this type.
+ #[cfg(feature = "alloc")]
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl FromStr for XOnlyPublicKey {
@@ -494,9 +497,6 @@ impl fmt::LowerHex for XOnlyPublicKey {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.to_inner().fmt(f) }
}
-// Allocate for serialized size
-#[cfg(feature = "alloc")]
-impl_to_hex_from_lower_hex!(XOnlyPublicKey, |_| constants::SCHNORR_PUBLIC_KEY_SIZE * 2);
impl fmt::Display for XOnlyPublicKey {
#[inline]
@@ -1495,15 +1495,17 @@ impl TweakedPublicKey {
pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] {
self.as_x_only_public_key().serialize().0
}
+
+ /// Gets the hex representation of this type.
+ #[cfg(feature = "alloc")]
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl fmt::LowerHex for TweakedPublicKey {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_x_only_public_key().fmt(f) }
}
-// Allocate for serialized size
-#[cfg(feature = "alloc")]
-impl_to_hex_from_lower_hex!(TweakedPublicKey, |_| constants::SCHNORR_PUBLIC_KEY_SIZE * 2);
impl fmt::Display for TweakedPublicKey {
#[inline]
diff --git a/crypto/src/taproot.rs b/crypto/src/taproot.rs
index 2cd0bab5..7d6b182d 100644
--- a/crypto/src/taproot.rs
+++ b/crypto/src/taproot.rs
@@ -4,6 +4,9 @@
//!
//! This module provides Taproot signatures used by Bitcoin that can be roundtrip (de)serialized.
+#[cfg(feature = "hex")]
+#[cfg(feature = "alloc")]
+use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;
use core::borrow::Borrow;
@@ -15,9 +18,6 @@ use core::str::FromStr;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use internals::array::ArrayExt;
-#[cfg(feature = "alloc")]
-#[cfg(feature = "hex")]
-use internals::impl_to_hex_from_lower_hex;
pub use self::into_iter::IntoIter;
#[cfg(feature = "hex")]
@@ -220,6 +220,12 @@ impl SerializedSignature {
/// Set the length of the object.
#[inline]
pub(crate) fn set_len_unchecked(&mut self, len: usize) { self.len = len; }
+
+ /// Gets the hex representation of this type.
+ #[cfg(feature = "hex")]
+ #[cfg(feature = "alloc")]
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl fmt::Debug for SerializedSignature {
@@ -250,10 +256,6 @@ impl fmt::LowerHex for SerializedSignature {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_internal(f, hex::Case::Lower) }
}
-#[cfg(feature = "alloc")]
-#[cfg(feature = "hex")]
-impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignature| signature.len
- * 2);
#[cfg(feature = "hex")]
impl fmt::UpperHex for SerializedSignature {
diff --git a/internals/src/macros.rs b/internals/src/macros.rs
index 1486ce53..d9b3a9b6 100644
--- a/internals/src/macros.rs
+++ b/internals/src/macros.rs
@@ -15,26 +15,6 @@ macro_rules! const_assert {
}
}
-/// Adds an implementation of `pub fn to_hex(&self) -> String`.
-///
-/// The added function allocates a `String` then calls through to [`core::fmt::LowerHex`].
-#[macro_export]
-macro_rules! impl_to_hex_from_lower_hex {
- ($t:ident, $hex_len_fn:expr) => {
- impl $t {
- /// Gets the hex representation of this type
- pub fn to_hex(&self) -> alloc::string::String {
- use core::fmt::Write;
-
- let mut hex_string = alloc::string::String::with_capacity($hex_len_fn(self));
- write!(&mut hex_string, "{:x}", self).expect("writing to string shouldn't fail");
-
- hex_string
- }
- }
- };
-}
-
/// Constructs a transparent wrapper around an inner type and soundly implements reference casts.
///
/// This macro takes care of several issues related to newtypes that need to allow casting their
diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs
index a45b9561..fe362766 100644
--- a/p2p/src/lib.rs
+++ b/p2p/src/lib.rs
@@ -40,6 +40,7 @@ pub extern crate arbitrary;
pub extern crate hex;
use alloc::borrow::ToOwned;
+use alloc::string::String;
use core::borrow::{Borrow, BorrowMut};
use core::str::FromStr;
use core::{fmt, ops};
@@ -47,7 +48,6 @@ use core::{fmt, ops};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use encoding::{ArrayDecoder, ArrayEncoder};
-use internals::impl_to_hex_from_lower_hex;
use network::{Network, TestnetVersion};
#[rustfmt::skip]
@@ -215,13 +215,15 @@ impl ServiceFlags {
/// Gets the integer representation of this [`ServiceFlags`].
pub fn to_u64(self) -> u64 { self.0 }
+
+ /// Gets the hex representation of this type.
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl fmt::LowerHex for ServiceFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
}
-impl_to_hex_from_lower_hex!(ServiceFlags, |service_flags: &ServiceFlags| 16
- - service_flags.0.leading_zeros() as usize / 4);
impl fmt::UpperHex for ServiceFlags {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(&self.0, f) }
@@ -349,6 +351,10 @@ impl Magic {
/// Gets network magic bytes.
pub fn to_bytes(self) -> [u8; 4] { self.0 }
+
+ /// Gets the hex representation of this type.
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl FromStr for Magic {
@@ -406,7 +412,6 @@ impl fmt::LowerHex for Magic {
Ok(())
}
}
-impl_to_hex_from_lower_hex!(Magic, |_| 8);
impl fmt::UpperHex for Magic {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/taproot-primitives/src/lib.rs b/taproot-primitives/src/lib.rs
index cb972688..d92520b4 100644
--- a/taproot-primitives/src/lib.rs
+++ b/taproot-primitives/src/lib.rs
@@ -32,6 +32,8 @@ pub extern crate serde;
#[doc(no_inline)]
pub use self::error::InvalidTaprootLeafVersionError;
+#[cfg(feature = "alloc")]
+use alloc::string::String;
use core::fmt;
#[cfg(feature = "arbitrary")]
@@ -158,6 +160,11 @@ impl LeafVersion {
Self::Future(version) => version.to_consensus(),
}
}
+
+ /// Gets the hex representation of this type.
+ #[cfg(feature = "alloc")]
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl fmt::Display for LeafVersion {
@@ -176,8 +183,6 @@ impl fmt::LowerHex for LeafVersion {
fmt::LowerHex::fmt(&self.to_consensus(), f)
}
}
-#[cfg(feature = "alloc")]
-internals::impl_to_hex_from_lower_hex!(LeafVersion, |_| 2);
impl fmt::UpperHex for LeafVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -257,6 +262,11 @@ impl FutureLeafVersion {
/// Returns the consensus representation of this [`FutureLeafVersion`].
#[inline]
pub fn to_consensus(self) -> u8 { self.0 }
+
+ /// Gets the hex representation of this type.
+ #[cfg(feature = "alloc")]
+ #[deprecated(since = "TBD", note = "use `format!(\"{var:x}\")` instead")]
+ pub fn to_hex(&self) -> String { alloc::format!("{:x}", self) }
}
impl fmt::Display for FutureLeafVersion {
@@ -268,8 +278,6 @@ impl fmt::LowerHex for FutureLeafVersion {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) }
}
-#[cfg(feature = "alloc")]
-internals::impl_to_hex_from_lower_hex!(FutureLeafVersion, |_| 2);
impl fmt::UpperHex for FutureLeafVersion {
#[inline]
Why this scored 18/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.