diff --git a/bitcoin/src/bip152.rs b/bitcoin/src/bip152.rs index 8807f9ec1..ce5b7844b 100644 --- a/bitcoin/src/bip152.rs +++ b/bitcoin/src/bip152.rs @@ -13,7 +13,7 @@ use internals::impl_array_newtype; use io::{BufRead, Write}; use crate::consensus::encode::{self, Decodable, Encodable, VarInt}; -use crate::internal_macros::{impl_bytes_newtype, impl_consensus_encoding}; +use crate::internal_macros::{impl_array_newtype_stringify, impl_consensus_encoding}; use crate::prelude::*; use crate::{block, Block, BlockHash, Transaction}; @@ -94,7 +94,7 @@ impl Decodable for PrefilledTransaction { #[derive(PartialEq, Eq, Clone, Copy, Hash, Default, PartialOrd, Ord)] pub struct ShortId([u8; 6]); impl_array_newtype!(ShortId, u8, 6); -impl_bytes_newtype!(ShortId, 6); +impl_array_newtype_stringify!(ShortId, 6); impl ShortId { /// Calculate the SipHash24 keys used to calculate short IDs. diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs index 61c13740d..6199b3a34 100644 --- a/bitcoin/src/bip32.rs +++ b/bitcoin/src/bip32.rs @@ -15,7 +15,7 @@ use io::Write; use secp256k1::{Secp256k1, XOnlyPublicKey}; use crate::crypto::key::{CompressedPublicKey, Keypair, PrivateKey}; -use crate::internal_macros::impl_bytes_newtype; +use crate::internal_macros::impl_array_newtype_stringify; use crate::network::NetworkKind; use crate::prelude::*; @@ -40,7 +40,7 @@ pub type ExtendedPrivKey = Xpriv; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ChainCode([u8; 32]); impl_array_newtype!(ChainCode, u8, 32); -impl_bytes_newtype!(ChainCode, 32); +impl_array_newtype_stringify!(ChainCode, 32); impl ChainCode { fn from_hmac(hmac: Hmac) -> Self { @@ -52,7 +52,7 @@ impl ChainCode { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct Fingerprint([u8; 4]); impl_array_newtype!(Fingerprint, u8, 4); -impl_bytes_newtype!(Fingerprint, 4); +impl_array_newtype_stringify!(Fingerprint, 4); hash_newtype! { /// Extended key identifier as defined in BIP-32. diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index 9c8dc58e9..c652c4bf3 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -16,7 +16,7 @@ use crate::blockdata::script; use crate::blockdata::transaction::{self, OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; use crate::consensus::Params; -use crate::internal_macros::impl_bytes_newtype; +use crate::internal_macros::impl_array_newtype_stringify; use crate::network::Network; use crate::pow::CompactTarget; use crate::{Amount, BlockHash}; @@ -155,7 +155,7 @@ pub fn genesis_block(params: impl AsRef) -> Block { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct ChainHash([u8; 32]); impl_array_newtype!(ChainHash, u8, 32); -impl_bytes_newtype!(ChainHash, 32); +impl_array_newtype_stringify!(ChainHash, 32); impl ChainHash { // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md diff --git a/bitcoin/src/internal_macros.rs b/bitcoin/src/internal_macros.rs index 28df98d85..b33ac5fc5 100644 --- a/bitcoin/src/internal_macros.rs +++ b/bitcoin/src/internal_macros.rs @@ -43,30 +43,17 @@ macro_rules! impl_consensus_encoding { } pub(crate) use impl_consensus_encoding; -/// Implements several traits for byte-based newtypes. -/// Implements: -/// - core::fmt::LowerHex -/// - core::fmt::UpperHex -/// - core::fmt::Display -/// - core::str::FromStr -macro_rules! impl_bytes_newtype { +/// Implements several string-ish traits for byte-based newtypes. +/// +/// - `fmt::Display` and `str::FromStr` (using lowercase hex) +/// - `fmt::LowerHex` and `UpperHex` +/// - `fmt::Debug` (using `LowerHex`) +/// - `serde::Serialize` and `Deserialize` (using lowercase hex) +/// +/// As well as an inherent `from_hex` method. +macro_rules! impl_array_newtype_stringify { ($t:ident, $len:literal) => { impl $t { - /// Returns a reference the underlying bytes. - #[inline] - pub fn as_bytes(&self) -> &[u8; $len] { &self.0 } - - /// Returns the underlying bytes. - #[inline] - pub fn to_bytes(self) -> [u8; $len] { - // We rely on `Copy` being implemented for $t so conversion - // methods use the correct Rust naming conventions. - fn check_copy() {} - check_copy::<$t>(); - - self.0 - } - /// Creates `Self` from a hex string. pub fn from_hex(s: &str) -> Result { Ok($t($crate::hex::FromHex::from_hex(s)?)) @@ -185,7 +172,7 @@ macro_rules! impl_bytes_newtype { } }; } -pub(crate) use impl_bytes_newtype; +pub(crate) use impl_array_newtype_stringify; #[rustfmt::skip] macro_rules! impl_hashencode { diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index 5b48d3544..25e7890fb 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -184,7 +184,7 @@ impl Serialize for KeySource { fn serialize(&self) -> Vec { let mut rv: Vec = Vec::with_capacity(key_source_len(self)); - rv.append(&mut self.0.to_bytes().to_vec()); + rv.append(&mut self.0.to_byte_array().to_vec()); for cnum in self.1.into_iter() { rv.append(&mut serialize(&u32::from(*cnum))) diff --git a/internals/src/macros.rs b/internals/src/macros.rs index 4478c3545..6b9aa6aaf 100644 --- a/internals/src/macros.rs +++ b/internals/src/macros.rs @@ -7,6 +7,34 @@ macro_rules! impl_array_newtype { ($thing:ident, $ty:ty, $len:literal) => { impl $thing { + /// Creates `Self` by wrapping `bytes`. + #[inline] + pub fn from_byte_array(bytes: [u8; $len]) -> Self { Self(bytes) } + + /// Returns a reference the underlying byte array. + #[inline] + pub fn as_byte_array(&self) -> &[u8; $len] { &self.0 } + + /// Returns the underlying byte array. + #[inline] + pub fn to_byte_array(self) -> [u8; $len] { + // We rely on `Copy` being implemented for $thing so conversion + // methods use the correct Rust naming conventions. + fn check_copy() {} + check_copy::<$thing>(); + + self.0 + } + + /// Returns a slice of the underlying bytes. + #[inline] + pub fn as_bytes(&self) -> &[u8] { &self.0 } + + /// Copies the underlying bytes into a new `Vec`. + #[cfg(feature = "alloc")] + #[inline] + pub fn to_bytes(&self) -> alloc::vec::Vec { self.0.to_vec() } + /// Converts the object to a raw pointer. #[inline] pub fn as_ptr(&self) -> *const $ty {