primitives: Make hex optional
Make the `hex` dependency optional. This means not implementing `Display` for some types if `hex` is not enabled and only implementing `Debug`. Also without `hex` enabled: - We loose the ability to parse an `OutPoint` from string because we can no longer parse `Txid`. - We loose the hex formatting of witness elements. Note also that `primitives` builds with the `serde` feature even if `hex?/serde` is excluded from the `serde` feature. I found this surprising.
This commit is contained in:
parent
b4326f0806
commit
a5f904559d
|
@ -213,6 +213,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -215,6 +215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4afe881d0527571892c4034822e59bb10c6c991cce6abe8199b6f5cf10766f55"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -31,7 +31,7 @@ hashes = { package = "bitcoin_hashes", path = "../hashes", default-features = fa
|
|||
hex = { package = "hex-conservative", version = "0.3.0", default-features = false, features = ["alloc"] }
|
||||
internals = { package = "bitcoin-internals", path = "../internals", features = ["alloc", "hex"] }
|
||||
io = { package = "bitcoin-io", path = "../io", default-features = false, features = ["alloc", "hashes"] }
|
||||
primitives = { package = "bitcoin-primitives", path = "../primitives", default-features = false, features = ["alloc"] }
|
||||
primitives = { package = "bitcoin-primitives", path = "../primitives", default-features = false, features = ["alloc", "hex"] }
|
||||
secp256k1 = { version = "0.30.0", default-features = false, features = ["hashes", "alloc", "rand"] }
|
||||
units = { package = "bitcoin-units", path = "../units", default-features = false, features = ["alloc"] }
|
||||
|
||||
|
|
|
@ -15,19 +15,20 @@ rust-version = "1.63.0"
|
|||
exclude = ["tests", "contrib"]
|
||||
|
||||
[features]
|
||||
default = ["std"]
|
||||
std = ["alloc", "hashes/std", "hex/std", "internals/std", "units/std"]
|
||||
alloc = ["hashes/alloc", "hex/alloc", "internals/alloc", "units/alloc"]
|
||||
serde = ["dep:serde", "hashes/serde", "internals/serde", "units/serde", "alloc"]
|
||||
default = ["std", "hex"]
|
||||
std = ["alloc", "hashes/std", "hex?/std", "internals/std", "units/std"]
|
||||
alloc = ["hashes/alloc", "hex?/alloc", "internals/alloc", "units/alloc"]
|
||||
serde = ["dep:serde", "hashes/serde", "hex?/serde", "internals/serde", "units/serde", "alloc", "hex"]
|
||||
arbitrary = ["dep:arbitrary", "units/arbitrary"]
|
||||
hex = ["dep:hex", "hashes/hex", "internals/hex"]
|
||||
|
||||
[dependencies]
|
||||
hashes = { package = "bitcoin_hashes", path = "../hashes", default-features = false, features = ["hex"] }
|
||||
hex = { package = "hex-conservative", version = "0.3.0", default-features = false }
|
||||
internals = { package = "bitcoin-internals", path = "../internals", features = ["hex"] }
|
||||
hashes = { package = "bitcoin_hashes", path = "../hashes", default-features = false }
|
||||
internals = { package = "bitcoin-internals", path = "../internals" }
|
||||
units = { package = "bitcoin-units", path = "../units", default-features = false }
|
||||
|
||||
arbitrary = { version = "1.4", optional = true }
|
||||
hex = { package = "hex-conservative", version = "0.3.0", default-features = false, optional = true }
|
||||
serde = { version = "1.0.103", default-features = false, features = ["derive", "alloc"], optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
|
|
@ -310,7 +310,10 @@ hashes::hash_newtype! {
|
|||
pub struct WitnessCommitment(sha256d::Hash);
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
hashes::impl_hex_for_newtype!(BlockHash, WitnessCommitment);
|
||||
#[cfg(not(feature = "hex"))]
|
||||
hashes::impl_debug_only_for_newtype!(BlockHash, WitnessCommitment);
|
||||
#[cfg(feature = "serde")]
|
||||
hashes::impl_serde_for_newtype!(BlockHash, WitnessCommitment);
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@ hashes::hash_newtype! {
|
|||
pub struct WitnessMerkleNode(sha256d::Hash);
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
hashes::impl_hex_for_newtype!(TxMerkleNode, WitnessMerkleNode);
|
||||
#[cfg(not(feature = "hex"))]
|
||||
hashes::impl_debug_only_for_newtype!(TxMerkleNode, WitnessMerkleNode);
|
||||
#[cfg(feature = "serde")]
|
||||
hashes::impl_serde_for_newtype!(TxMerkleNode, WitnessMerkleNode);
|
||||
|
|
|
@ -10,6 +10,7 @@ use core::convert::Infallible;
|
|||
use core::fmt;
|
||||
|
||||
use hashes::{hash160, sha256};
|
||||
#[cfg(feature = "hex")]
|
||||
use hex::DisplayHex;
|
||||
use internals::script::{self, PushDataLenLen};
|
||||
|
||||
|
@ -49,7 +50,10 @@ hashes::hash_newtype! {
|
|||
pub struct WScriptHash(sha256::Hash);
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
hashes::impl_hex_for_newtype!(ScriptHash, WScriptHash);
|
||||
#[cfg(not(feature = "hex"))]
|
||||
hashes::impl_debug_only_for_newtype!(ScriptHash, WScriptHash);
|
||||
#[cfg(feature = "serde")]
|
||||
hashes::impl_serde_for_newtype!(ScriptHash, WScriptHash);
|
||||
|
||||
|
@ -425,6 +429,7 @@ impl fmt::Display for ScriptBuf {
|
|||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as_script(), f) }
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
impl fmt::LowerHex for Script {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -432,15 +437,19 @@ impl fmt::LowerHex for Script {
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
internals::impl_to_hex_from_lower_hex!(Script, |script: &Self| script.len() * 2);
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
impl fmt::LowerHex for ScriptBuf {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.as_script(), f) }
|
||||
}
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
internals::impl_to_hex_from_lower_hex!(ScriptBuf, |script_buf: &Self| script_buf.len() * 2);
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
impl fmt::UpperHex for Script {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -448,6 +457,7 @@ impl fmt::UpperHex for Script {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
impl fmt::UpperHex for ScriptBuf {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(self.as_script(), f) }
|
||||
|
@ -720,16 +730,24 @@ mod tests {
|
|||
fn script_display() {
|
||||
let script = Script::from_bytes(&[0xa1, 0xb2, 0xc3]);
|
||||
assert_eq!(format!("{}", script), "OP_LESSTHANOREQUAL OP_CSV OP_RETURN_195");
|
||||
assert_eq!(format!("{:x}", script), "a1b2c3");
|
||||
assert_eq!(format!("{:X}", script), "A1B2C3");
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
{
|
||||
assert_eq!(format!("{:x}", script), "a1b2c3");
|
||||
assert_eq!(format!("{:X}", script), "A1B2C3");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn scriptbuf_display() {
|
||||
let script_buf = ScriptBuf::from(vec![0xa1, 0xb2, 0xc3]);
|
||||
assert_eq!(format!("{}", script_buf), "OP_LESSTHANOREQUAL OP_CSV OP_RETURN_195");
|
||||
assert_eq!(format!("{:x}", script_buf), "a1b2c3");
|
||||
assert_eq!(format!("{:X}", script_buf), "A1B2C3");
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
{
|
||||
assert_eq!(format!("{:x}", script_buf), "a1b2c3");
|
||||
assert_eq!(format!("{:X}", script_buf), "A1B2C3");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#[cfg(feature = "alloc")]
|
||||
use core::cmp;
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
use core::convert::Infallible;
|
||||
use core::fmt;
|
||||
|
||||
|
@ -20,9 +21,13 @@ use core::fmt;
|
|||
use arbitrary::{Arbitrary, Unstructured};
|
||||
use hashes::sha256d;
|
||||
#[cfg(feature = "alloc")]
|
||||
use internals::{compact_size, write_err};
|
||||
use internals::compact_size;
|
||||
#[cfg(feature = "hex")]
|
||||
use internals::write_err;
|
||||
#[cfg(feature = "hex")]
|
||||
use units::parse;
|
||||
#[cfg(feature = "alloc")]
|
||||
use units::{parse, Amount, Weight};
|
||||
use units::{Amount, Weight};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::locktime::absolute;
|
||||
|
@ -389,6 +394,7 @@ impl OutPoint {
|
|||
pub const COINBASE_PREVOUT: Self = Self { txid: Txid::COINBASE_PREVOUT, vout: u32::MAX };
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
impl fmt::Display for OutPoint {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -397,6 +403,7 @@ impl fmt::Display for OutPoint {
|
|||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
impl core::str::FromStr for OutPoint {
|
||||
type Err = ParseOutPointError;
|
||||
|
||||
|
@ -424,6 +431,7 @@ impl core::str::FromStr for OutPoint {
|
|||
///
|
||||
/// Does not permit leading zeroes or non-digit characters.
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
fn parse_vout(s: &str) -> Result<u32, ParseOutPointError> {
|
||||
if s.len() > 1 {
|
||||
let first = s.chars().next().unwrap();
|
||||
|
@ -438,6 +446,7 @@ fn parse_vout(s: &str) -> Result<u32, ParseOutPointError> {
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
pub enum ParseOutPointError {
|
||||
/// Error in TXID part.
|
||||
Txid(hex::HexToArrayError),
|
||||
|
@ -452,12 +461,14 @@ pub enum ParseOutPointError {
|
|||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
impl From<Infallible> for ParseOutPointError {
|
||||
#[inline]
|
||||
fn from(never: Infallible) -> Self { match never {} }
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg(feature = "hex")]
|
||||
impl fmt::Display for ParseOutPointError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use ParseOutPointError as E;
|
||||
|
@ -473,6 +484,7 @@ impl fmt::Display for ParseOutPointError {
|
|||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg(feature = "hex")]
|
||||
impl std::error::Error for ParseOutPointError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
use ParseOutPointError as E;
|
||||
|
@ -500,7 +512,10 @@ hashes::hash_newtype! {
|
|||
pub struct Wtxid(sha256d::Hash);
|
||||
}
|
||||
|
||||
#[cfg(feature = "hex")]
|
||||
hashes::impl_hex_for_newtype!(Txid, Wtxid);
|
||||
#[cfg(not(feature = "hex"))]
|
||||
hashes::impl_debug_only_for_newtype!(Txid, Wtxid);
|
||||
#[cfg(feature = "serde")]
|
||||
hashes::impl_serde_for_newtype!(Txid, Wtxid);
|
||||
|
||||
|
@ -699,6 +714,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "hex")]
|
||||
fn outpoint_from_str() {
|
||||
// Check format errors
|
||||
let mut outpoint_str = "0".repeat(64); // No ":"
|
||||
|
@ -725,6 +741,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "hex")]
|
||||
fn canonical_vout() {
|
||||
assert_eq!(parse_vout("0").unwrap(), 0);
|
||||
assert_eq!(parse_vout("1").unwrap(), 1);
|
||||
|
|
|
@ -9,7 +9,6 @@ use core::ops::Index;
|
|||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
use hex::DisplayHex;
|
||||
use internals::compact_size;
|
||||
use internals::slice::SliceExt;
|
||||
use internals::wrap_debug::WrapDebug;
|
||||
|
@ -314,7 +313,7 @@ impl<T: core::borrow::Borrow<[u8]>> PartialEq<Witness> for alloc::sync::Arc<[T]>
|
|||
/// Debug implementation that displays the witness as a structured output containing:
|
||||
/// - Number of witness elements
|
||||
/// - Total bytes across all elements
|
||||
/// - List of hex-encoded witness elements
|
||||
/// - List of hex-encoded witness elements if `hex` features is enabled.
|
||||
#[allow(clippy::missing_fields_in_debug)] // We don't want to show `indices_start`.
|
||||
impl fmt::Debug for Witness {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
@ -326,7 +325,14 @@ impl fmt::Debug for Witness {
|
|||
.field(
|
||||
"elements",
|
||||
&WrapDebug(|f| {
|
||||
f.debug_list().entries(self.iter().map(DisplayHex::as_hex)).finish()
|
||||
#[cfg(feature = "hex")]
|
||||
{
|
||||
f.debug_list().entries(self.iter().map(hex::DisplayHex::as_hex)).finish()
|
||||
}
|
||||
#[cfg(not(feature = "hex"))]
|
||||
{
|
||||
f.debug_list().entries(self.iter()).finish()
|
||||
}
|
||||
}),
|
||||
)
|
||||
.finish()
|
||||
|
|
Loading…
Reference in New Issue