Remove the unstable hex-conservative dependency
What changed, and why it matters
This commit is a routine dependency cleanup. The project previously had to use two different versions of the same hex-encoding helper library (one stable, one unstable preview) because a needed feature was only available in the unstable version. Now that the stable library released version 1.1.0 with that feature, the commit removes the unstable dependency and switches everything to the single stable version. It is not a security fix and does not change how the software behaves to users.
No security action required. Treat as a normal dependency upgrade and verify CI passes. Reviewers should confirm that all crates compile with the new single dependency and that downstream consumers are prepared for the breaking re-export name change from hex_stable/hex_unstable to hex.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The commit replaces the dual hex-conservative dependency setup (stable 1.0.0 + unstable 0.3.2) with a single hex-conservative 1.1.0 dependency across all workspace crates. Cargo.toml files, lock files, import names (hex_stable/hex_unstable -> hex), and API call sites are updated to match the 1.1.0 API. Notable API changes accommodated: HexToBytesIter is renamed to HexSliceToBytesIter and now yields [char; 2] per byte instead of a single char, requiring loop adjustments in primitives/src/hex_codec.rs and consensus_encoding/tests/iter.rs. The chacha20_poly1305 tests switch from Vec::from_hex to the hex! macro. No vulnerability fixes, cryptographic changes, or consensus behavior changes are present.
Changed components
Cargo dependency graph (hex-conservative)bitcoin crate imports and hex feature wiringcrypto crate imports and hex feature wiringhashes crate imports and hex feature wiringprimitives crate hex_codec, script, witness formattingp2p crate hex formattingchacha20_poly1305 test helpersconsensus_encoding hex iterator testskey_expression test helpersbase58 dev dependencyInspect captured patch +169 / −254
diff --git a/Cargo-minimal.lock b/Cargo-minimal.lock
index 60f14bfc..0462bb58 100644
--- a/Cargo-minimal.lock
+++ b/Cargo-minimal.lock
@@ -30,7 +30,7 @@ version = "0.4.0"
dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
]
[[package]]
@@ -92,8 +92,7 @@ dependencies = [
"bitcoin-units 0.3.0",
"bitcoin_hashes 0.20.0",
"bitcoinconsensus",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"secp256k1 0.32.0-beta.2",
"serde",
"serde_json",
@@ -113,7 +112,7 @@ name = "bitcoin-consensus-encoding"
version = "0.2.0"
dependencies = [
"bitcoin-internals 0.5.0",
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
]
[[package]]
@@ -125,8 +124,7 @@ dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin-network-kind",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"secp256k1 0.32.0-beta.2",
"serde",
"serde_test",
@@ -158,7 +156,7 @@ name = "bitcoin-internals"
version = "0.5.0"
dependencies = [
"bincode",
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
"serde",
"serde_json",
]
@@ -188,8 +186,7 @@ dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin-network-kind",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"secp256k1 0.32.0-beta.2",
"serde",
"serde_json",
@@ -217,8 +214,7 @@ dependencies = [
"bitcoin-primitives",
"bitcoin-units 0.3.0",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"serde",
]
@@ -232,8 +228,7 @@ dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin-units 0.3.0",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"serde",
"serde_json",
]
@@ -305,8 +300,7 @@ dependencies = [
"bitcoin-consensus-encoding",
"bitcoin-internals 0.5.0",
"cpufeatures",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"serde",
"serde_test",
]
@@ -348,7 +342,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
name = "chacha20-poly1305"
version = "0.2.0"
dependencies = [
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
]
[[package]]
@@ -383,19 +377,13 @@ dependencies = [
[[package]]
name = "hex-conservative"
-version = "0.3.2"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360"
+checksum = "a7289f6b628ce69fb1a371d0fdcf8ff38cd93ec00e3010eb055d1e044998c8d1"
dependencies = [
"arrayvec",
]
-[[package]]
-name = "hex-conservative"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ee770c000993d17c185713463d5ebfbd1af9afae4c17cc295640104383bfbf0"
-
[[package]]
name = "hex_lit"
version = "0.1.1"
diff --git a/Cargo-recent.lock b/Cargo-recent.lock
index de0526bf..c249ff42 100644
--- a/Cargo-recent.lock
+++ b/Cargo-recent.lock
@@ -30,7 +30,7 @@ version = "0.4.0"
dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
]
[[package]]
@@ -91,8 +91,7 @@ dependencies = [
"bitcoin-units 0.3.0",
"bitcoin_hashes 0.20.0",
"bitcoinconsensus",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"secp256k1 0.32.0-beta.2",
"serde",
"serde_json",
@@ -112,7 +111,7 @@ name = "bitcoin-consensus-encoding"
version = "0.2.0"
dependencies = [
"bitcoin-internals 0.5.0",
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
]
[[package]]
@@ -124,8 +123,7 @@ dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin-network-kind",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"secp256k1 0.32.0-beta.2",
"serde",
"serde_test",
@@ -157,7 +155,7 @@ name = "bitcoin-internals"
version = "0.5.0"
dependencies = [
"bincode",
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
"serde",
"serde_json",
]
@@ -187,8 +185,7 @@ dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin-network-kind",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"secp256k1 0.32.0-beta.2",
"serde",
"serde_json",
@@ -216,8 +213,7 @@ dependencies = [
"bitcoin-primitives",
"bitcoin-units 0.3.0",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"serde",
]
@@ -231,8 +227,7 @@ dependencies = [
"bitcoin-internals 0.5.0",
"bitcoin-units 0.3.0",
"bitcoin_hashes 0.20.0",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"serde",
"serde_json",
]
@@ -289,8 +284,7 @@ dependencies = [
"bitcoin-consensus-encoding",
"bitcoin-internals 0.5.0",
"cpufeatures",
- "hex-conservative 0.3.2",
- "hex-conservative 1.0.0",
+ "hex-conservative 1.1.0",
"serde",
"serde_test",
]
@@ -331,7 +325,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
name = "chacha20-poly1305"
version = "0.2.0"
dependencies = [
- "hex-conservative 0.3.2",
+ "hex-conservative 1.1.0",
]
[[package]]
@@ -366,19 +360,13 @@ dependencies = [
[[package]]
name = "hex-conservative"
-version = "0.3.2"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830e599c2904b08f0834ee6337d8fe8f0ed4a63b5d9e7a7f49c0ffa06d08d360"
+checksum = "a7289f6b628ce69fb1a371d0fdcf8ff38cd93ec00e3010eb055d1e044998c8d1"
dependencies = [
"arrayvec",
]
-[[package]]
-name = "hex-conservative"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ee770c000993d17c185713463d5ebfbd1af9afae4c17cc295640104383bfbf0"
-
[[package]]
name = "hex_lit"
version = "0.1.1"
diff --git a/base58/Cargo.toml b/base58/Cargo.toml
index 6a8f12e3..5a3081bd 100644
--- a/base58/Cargo.toml
+++ b/base58/Cargo.toml
@@ -23,7 +23,7 @@ hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.20.0", d
internals = { package = "bitcoin-internals", path = "../internals", version = "0.5.0" }
[dev-dependencies]
-hex = { package = "hex-conservative", version = "0.3.2" }
+hex = { package = "hex-conservative", version = "1.1.0" }
[package.metadata.docs.rs]
all-features = true
@@ -31,8 +31,3 @@ rustdoc-args = ["--cfg", "docsrs"]
[lints]
workspace = true
-
-[package.metadata.rbmt.lint]
-allowed_duplicates = [
- "hex-conservative",
-]
diff --git a/benches/Cargo.toml b/benches/Cargo.toml
index 4e93f541..0d1a8a72 100644
--- a/benches/Cargo.toml
+++ b/benches/Cargo.toml
@@ -12,7 +12,7 @@ chacha20-poly1305 = { path = "../chacha20_poly1305" }
encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding" }
criterion = "0.7"
-hex = { package = "hex-conservative", version = "0.3.2" }
+hex = { package = "hex-conservative", version = "1.1.0" }
[lints.clippy]
use_self = "warn"
diff --git a/bitcoin/Cargo.toml b/bitcoin/Cargo.toml
index 7585ef17..a06ccafa 100644
--- a/bitcoin/Cargo.toml
+++ b/bitcoin/Cargo.toml
@@ -17,7 +17,7 @@ exclude = ["tests", "contrib"]
# If you change features or optional dependencies in any way please update the "# Cargo features" section in lib.rs as well.
[features]
default = [ "std", "secp-recovery" ]
-std = ["base58/std", "bech32/std", "crypto/std", "key-expression/std", "encoding/std", "hashes/std", "hex-stable/std", "hex-unstable/std", "internals/std", "io/std", "network/std", "primitives/std", "secp256k1/std", "taproot-primitives/std", "units/std", "base64?/std", "bitcoinconsensus?/std"]
+std = ["base58/std", "bech32/std", "crypto/std", "key-expression/std", "encoding/std", "hashes/std", "hex/std", "internals/std", "io/std", "network/std", "primitives/std", "secp256k1/std", "taproot-primitives/std", "units/std", "base64?/std", "bitcoinconsensus?/std"]
rand = ["secp256k1/rand", "crypto/rand"]
serde = ["base64", "crypto/serde", "dep:serde", "hashes/serde", "internals/serde", "key-expression/serde", "network/serde", "primitives/serde", "secp256k1/serde", "taproot-primitives/serde", "units/serde"]
secp-global-context = ["secp256k1/global-context"]
@@ -32,8 +32,7 @@ crypto = { package = "bitcoin-crypto", path = "../crypto", version = "0.2.0", de
hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.20.0", default-features = false, features = ["alloc", "hex"] }
key-expression = { package = "bitcoin-key-expression", path = "../key_expression", version = "0.0.0", default-features = false, features = ["alloc"] }
encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "0.2.0", default-features = false, features = ["alloc"] }
-hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false, features = ["alloc"] }
-hex-unstable = { package = "hex-conservative", version = "0.3.2", default-features = false, features = ["alloc"] }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, features = ["alloc"] }
internals = { package = "bitcoin-internals", path = "../internals", version = "0.5.0", features = ["alloc", "hex"] }
io = { package = "bitcoin-io", path = "../io", version = "0.5.0", default-features = false, features = ["alloc", "hashes"] }
network = { package = "bitcoin-network-kind", path = "../network", version = "0.1.0", default-features = false, features = ["alloc"]}
@@ -109,10 +108,5 @@ exact_features = [
["std", "bitcoinconsensus", "secp-recovery", "base64", "serde"],
]
-[package.metadata.rbmt.lint]
-allowed_duplicates = [
- "hex-conservative",
-]
-
[package.metadata.rbmt.prerelease]
enabled = true
diff --git a/bitcoin/examples/sighash.rs b/bitcoin/examples/sighash.rs
index 92be84bc..766ecbed 100644
--- a/bitcoin/examples/sighash.rs
+++ b/bitcoin/examples/sighash.rs
@@ -3,7 +3,7 @@ use bitcoin::{
consensus, ecdsa, sighash, Amount, FullPublicKey, ScriptPubKey, ScriptPubKeyBuf, Transaction,
WitnessScript,
};
-use hex_unstable::hex;
+use hex::hex;
//These are real blockchain transactions examples of computing sighash for:
// - P2WPKH
diff --git a/bitcoin/src/address/mod.rs b/bitcoin/src/address/mod.rs
index 48c9d946..17cc91a2 100644
--- a/bitcoin/src/address/mod.rs
+++ b/bitcoin/src/address/mod.rs
@@ -1028,7 +1028,7 @@ fn segwit_redeem_hash(pubkey_hash: PubkeyHash) -> hash160::Hash {
mod tests {
use alloc::string::ToString;
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
use crate::network::Network::{Bitcoin, Testnet};
diff --git a/bitcoin/src/bip158.rs b/bitcoin/src/bip158.rs
index d0605ded..723f12cc 100644
--- a/bitcoin/src/bip158.rs
+++ b/bitcoin/src/bip158.rs
@@ -548,7 +548,7 @@ mod test {
#[cfg(feature = "std")]
use std::collections::HashMap;
- use hex_unstable::hex;
+ use hex::hex;
#[cfg(feature = "std")]
use serde_json::Value;
diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs
index 8f00b2de..0fe468d2 100644
--- a/bitcoin/src/blockdata/block.rs
+++ b/bitcoin/src/blockdata/block.rs
@@ -410,7 +410,7 @@ pub mod error {
mod tests {
use alloc::string::ToString;
- use hex_unstable::hex;
+ use hex::hex;
use internals::ToU64 as _;
use super::*;
diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs
index 66e6a8e4..7876d45b 100644
--- a/bitcoin/src/blockdata/constants.rs
+++ b/bitcoin/src/blockdata/constants.rs
@@ -286,7 +286,7 @@ impl ChainHash {
mod test {
use alloc::string::ToString;
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
use crate::consensus::encode::serialize;
diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs
index e1ad86b4..abbe0671 100644
--- a/bitcoin/src/blockdata/script/tests.rs
+++ b/bitcoin/src/blockdata/script/tests.rs
@@ -4,7 +4,7 @@
use alloc::borrow::ToOwned;
use alloc::string::ToString;
-use hex_unstable::hex;
+use hex::hex;
use super::*;
use crate::consensus::encode::{deserialize, serialize};
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index 1cbd446e..dabc34be 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -1302,7 +1302,7 @@ impl<'a> Arbitrary<'a> for InputWeightPrediction {
mod tests {
use alloc::string::ToString;
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
use crate::consensus::encode::deserialize;
diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs
index acb6a596..dc64b498 100644
--- a/bitcoin/src/blockdata/witness.rs
+++ b/bitcoin/src/blockdata/witness.rs
@@ -254,7 +254,7 @@ mod sealed {
mod test {
use alloc::vec::Vec;
- use hex_unstable::{hex, DisplayHex};
+ use hex::{hex, DisplayHex};
use super::*;
use crate::consensus::{deserialize, encode, serialize};
diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs
index c16435a1..8837c691 100644
--- a/bitcoin/src/consensus/encode.rs
+++ b/bitcoin/src/consensus/encode.rs
@@ -19,7 +19,7 @@ use core::{cmp, mem, slice};
use encoding::{CompactSizeEncoder, Encoder};
use hashes::{sha256, sha256d, Hash};
-use hex_unstable::DisplayHex as _;
+use hex::DisplayHex as _;
use internals::ToU64;
use io::{BufRead, Cursor, Read, Write};
@@ -59,7 +59,7 @@ pub fn deserialize<T: Decodable>(data: &[u8]) -> Result<T, DeserializeError> {
/// Deserializes any decodable type from a hex string, will error if said deserialization
/// doesn't consume the entire vector.
pub fn deserialize_hex<T: Decodable>(hex: &str) -> Result<T, FromHexError> {
- let iter = hex_unstable::HexSliceToBytesIter::new(hex)?;
+ let iter = hex::HexSliceToBytesIter::new(hex)?;
let reader = IterReader::new(iter);
Ok(reader.decode().map_err(FromHexError::Decode)?)
}
diff --git a/bitcoin/src/consensus/error.rs b/bitcoin/src/consensus/error.rs
index 91a8c035..f6d7ec24 100644
--- a/bitcoin/src/consensus/error.rs
+++ b/bitcoin/src/consensus/error.rs
@@ -5,7 +5,7 @@
use core::convert::Infallible;
use core::fmt;
-use hex_unstable::error::{InvalidCharError, OddLengthStringError};
+use hex::error::{InvalidCharError, OddLengthStringError};
use internals::write_err;
#[cfg(doc)]
diff --git a/bitcoin/src/consensus/serde.rs b/bitcoin/src/consensus/serde.rs
index dc486ef7..ba447ea3 100644
--- a/bitcoin/src/consensus/serde.rs
+++ b/bitcoin/src/consensus/serde.rs
@@ -38,7 +38,7 @@ pub mod hex {
use core::fmt;
use core::marker::PhantomData;
- use hex_unstable::buf_encoder::BufEncoder;
+ use hex::buf_encoder::BufEncoder;
/// Marker for upper/lower case type-level flags ("type-level enum").
///
@@ -54,15 +54,15 @@ pub mod hex {
mod sealed {
pub trait Case {
/// Internal detail, don't depend on it!!!
- const INTERNAL_CASE: hex_unstable::Case;
+ const INTERNAL_CASE: hex::Case;
}
impl Case for super::Lower {
- const INTERNAL_CASE: hex_unstable::Case = hex_unstable::Case::Lower;
+ const INTERNAL_CASE: hex::Case = hex::Case::Lower;
}
impl Case for super::Upper {
- const INTERNAL_CASE: hex_unstable::Case = hex_unstable::Case::Upper;
+ const INTERNAL_CASE: hex::Case = hex::Case::Upper;
}
}
@@ -101,18 +101,18 @@ pub mod hex {
/// Error returned when a hex string decoder can't be created.
#[derive(Debug, Clone, PartialEq, Eq)]
- pub struct DecodeInitError(hex_unstable::OddLengthStringError);
+ pub struct DecodeInitError(hex::OddLengthStringError);
/// Error returned when a hex string contains invalid characters.
#[derive(Debug, Clone, PartialEq, Eq)]
- pub struct DecodeError(hex_unstable::InvalidCharError);
+ pub struct DecodeError(hex::InvalidCharError);
/// Hex decoder state.
- pub struct Decoder<'a>(hex_unstable::HexSliceToBytesIter<'a>);
+ pub struct Decoder<'a>(hex::HexSliceToBytesIter<'a>);
impl<'a> Decoder<'a> {
fn new(s: &'a str) -> Result<Self, DecodeInitError> {
- match hex_unstable::HexToBytesIter::new(s) {
+ match hex::HexSliceToBytesIter::new(s) {
Ok(iter) => Ok(Decoder(iter)),
Err(error) => Err(DecodeInitError(error)),
}
diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs
index 9d1976e6..5be292db 100644
--- a/bitcoin/src/crypto/sighash.rs
+++ b/bitcoin/src/crypto/sighash.rs
@@ -1296,7 +1296,7 @@ mod tests {
use alloc::vec::Vec;
use hashes::HashEngine;
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
use crate::consensus::deserialize;
@@ -1624,7 +1624,7 @@ mod tests {
#[cfg(feature = "serde")]
#[test]
fn bip_341_sighash_tests() {
- use hex_unstable::DisplayHex;
+ use hex::DisplayHex;
fn sighash_deser_numeric<'de, D>(deserializer: D) -> Result<TapSighashType, D::Error>
where
diff --git a/bitcoin/src/lib.rs b/bitcoin/src/lib.rs
index a743dfbd..13416e7a 100644
--- a/bitcoin/src/lib.rs
+++ b/bitcoin/src/lib.rs
@@ -68,7 +68,7 @@ pub extern crate base64;
pub extern crate bech32;
pub extern crate encoding;
pub extern crate hashes;
-pub extern crate hex_stable as hex;
+pub extern crate hex;
pub extern crate io;
pub extern crate primitives;
pub extern crate secp256k1;
@@ -229,7 +229,7 @@ mod prelude {
pub use crate::io::sink;
- pub use hex_unstable::DisplayHex;
+ pub use hex::DisplayHex;
}
pub mod amount {
diff --git a/bitcoin/src/pow.rs b/bitcoin/src/pow.rs
index 1a2bee5a..37131892 100644
--- a/bitcoin/src/pow.rs
+++ b/bitcoin/src/pow.rs
@@ -418,13 +418,13 @@ macro_rules! impl_hex {
($hex:path, $case:expr) => {
impl $hex for U256 {
fn fmt(&self, f: &mut fmt::Formatter) -> core::fmt::Result {
- hex_unstable::fmt_hex_exact!(f, 32, &self.to_be_bytes(), $case)
+ hex::fmt_hex_exact!(f, 32, &self.to_be_bytes(), $case)
}
}
};
}
-impl_hex!(fmt::LowerHex, hex_unstable::Case::Lower);
-impl_hex!(fmt::UpperHex, hex_unstable::Case::Upper);
+impl_hex!(fmt::LowerHex, hex::Case::Lower);
+impl_hex!(fmt::UpperHex, hex::Case::Upper);
#[cfg(kani)]
impl kani::Arbitrary for U256 {
diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs
index e5037fed..d4e1dd58 100644
--- a/bitcoin/src/taproot/mod.rs
+++ b/bitcoin/src/taproot/mod.rs
@@ -1487,7 +1487,7 @@ mod test {
use alloc::string::ToString;
use hashes::sha256;
- use hex_unstable::DisplayHex;
+ use hex::DisplayHex;
use super::*;
use crate::sighash::TapSighashTag;
diff --git a/chacha20_poly1305/Cargo.toml b/chacha20_poly1305/Cargo.toml
index 88eee179..f7e2b421 100644
--- a/chacha20_poly1305/Cargo.toml
+++ b/chacha20_poly1305/Cargo.toml
@@ -19,7 +19,7 @@ std = ["alloc"]
alloc = []
[dev-dependencies]
-hex = { package = "hex-conservative", version = "0.3.2", default-features = false, features = ["alloc"] }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, features = ["alloc"] }
[package.metadata.docs.rs]
all-features = true
diff --git a/chacha20_poly1305/src/chacha20.rs b/chacha20_poly1305/src/chacha20.rs
index afe733c4..fc2d18f1 100644
--- a/chacha20_poly1305/src/chacha20.rs
+++ b/chacha20_poly1305/src/chacha20.rs
@@ -361,9 +361,7 @@ impl ChaCha20 {
#[cfg(test)]
#[cfg(feature = "alloc")]
mod tests {
- use alloc::vec::Vec;
-
- use hex::prelude::*;
+ use hex::{hex, DisplayHex as _};
use super::*;
@@ -393,12 +391,8 @@ mod tests {
#[test]
fn prepare_state() {
- let key =
- Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
- .unwrap()
- .try_into()
- .unwrap());
- let nonce = Nonce(Vec::from_hex("000000090000004a00000000").unwrap().try_into().unwrap());
+ let key = Key(hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
+ let nonce = Nonce(hex!("000000090000004a00000000"));
let count = 1;
let state = State::new(key, nonce, count);
assert_eq!(state.matrix[1].0[0].to_be_bytes().to_lower_hex_string(), "03020100");
@@ -410,12 +404,8 @@ mod tests {
#[test]
fn small_plaintext() {
- let key =
- Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
- .unwrap()
- .try_into()
- .unwrap());
- let nonce = Nonce(Vec::from_hex("000000090000004a00000000").unwrap().try_into().unwrap());
+ let key = Key(hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
+ let nonce = Nonce(hex!("000000090000004a00000000"));
let count = 1;
let mut chacha = ChaCha20::new(key, nonce, count);
let mut binding = [8; 3];
@@ -427,12 +417,8 @@ mod tests {
#[test]
fn modulo_64() {
- let key =
- Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
- .unwrap()
- .try_into()
- .unwrap());
- let nonce = Nonce(Vec::from_hex("000000090000004a00000000").unwrap().try_into().unwrap());
+ let key = Key(hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
+ let nonce = Nonce(hex!("000000090000004a00000000"));
let count = 1;
let mut chacha = ChaCha20::new(key, nonce, count);
let mut binding = [8; 64];
@@ -445,18 +431,14 @@ mod tests {
#[cfg(not(chacha20_poly1305_fuzz))]
#[test]
fn rfc_standard() {
- let key =
- Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
- .unwrap()
- .try_into()
- .unwrap());
- let nonce = Nonce(Vec::from_hex("000000000000004a00000000").unwrap().try_into().unwrap());
+ let key = Key(hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
+ let nonce = Nonce(hex!("000000000000004a00000000"));
let count = 64;
let mut chacha = ChaCha20::new(key, nonce, count);
let mut binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
let to = binding;
chacha.apply_keystream(&mut binding[..]);
- assert_eq!(binding[..], Vec::from_hex("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d").unwrap());
+ assert_eq!(binding[..], hex!("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d"));
let mut chacha = ChaCha20::new(key, nonce, count);
chacha.apply_keystream(&mut binding[..]);
let binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
@@ -466,18 +448,14 @@ mod tests {
#[cfg(not(chacha20_poly1305_fuzz))]
#[test]
fn new_from_block() {
- let key =
- Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
- .unwrap()
- .try_into()
- .unwrap());
- let nonce = Nonce(Vec::from_hex("000000000000004a00000000").unwrap().try_into().unwrap());
+ let key = Key(hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
+ let nonce = Nonce(hex!("000000000000004a00000000"));
let block: u32 = 1;
let mut chacha = ChaCha20::new_from_block(key, nonce, block);
let mut binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
let to = binding;
chacha.apply_keystream(&mut binding[..]);
- assert_eq!(binding[..], Vec::from_hex("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d").unwrap());
+ assert_eq!(binding[..], hex!("6e2e359a2568f98041ba0728dd0d6981e97e7aec1d4360c20a27afccfd9fae0bf91b65c5524733ab8f593dabcd62b3571639d624e65152ab8f530c359f0861d807ca0dbf500d6a6156a38e088a22b65e52bc514d16ccf806818ce91ab77937365af90bbf74a35be6b40b8eedf2785e42874d"));
chacha.block(block);
chacha.apply_keystream(&mut binding[..]);
let binding = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
@@ -486,12 +464,8 @@ mod tests {
#[test]
fn multiple_partial_applies() {
- let key =
- Key(Vec::from_hex("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
- .unwrap()
- .try_into()
- .unwrap());
- let nonce = Nonce(Vec::from_hex("000000000000004a00000000").unwrap().try_into().unwrap());
+ let key = Key(hex!("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"));
+ let nonce = Nonce(hex!("000000000000004a00000000"));
// Create two instances, one for a full single pass and one for chunked partial calls.
let mut chacha_full = ChaCha20::new(key, nonce, 0);
diff --git a/chacha20_poly1305/src/lib.rs b/chacha20_poly1305/src/lib.rs
index b37ce839..58f4a306 100644
--- a/chacha20_poly1305/src/lib.rs
+++ b/chacha20_poly1305/src/lib.rs
@@ -196,9 +196,7 @@ pub mod error {
#[cfg(test)]
#[cfg(feature = "alloc")]
mod tests {
- use alloc::vec::Vec;
-
- use hex::prelude::*;
+ use hex::{hex, DisplayHex as _};
use super::*;
@@ -206,15 +204,10 @@ mod tests {
#[test]
fn rfc7539() {
let mut message = *b"Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
- let aad = Vec::from_hex("50515253c0c1c2c3c4c5c6c7").unwrap();
- let key = Key::new(
- Vec::from_hex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f")
- .unwrap()
- .try_into()
- .unwrap(),
- );
- let nonce =
- Nonce::new(Vec::from_hex("070000004041424344454647").unwrap().try_into().unwrap());
+ let aad = hex!("50515253c0c1c2c3c4c5c6c7");
+ let key =
+ Key::new(hex!("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f"));
+ let nonce = Nonce::new(hex!("070000004041424344454647"));
let cipher = ChaCha20Poly1305::new(key, nonce);
let tag = cipher.encrypt(&mut message, Some(&aad));
diff --git a/chacha20_poly1305/src/poly1305.rs b/chacha20_poly1305/src/poly1305.rs
index 3143d848..21a8cd7a 100644
--- a/chacha20_poly1305/src/poly1305.rs
+++ b/chacha20_poly1305/src/poly1305.rs
@@ -247,20 +247,14 @@ fn _print_acc(num: &[u32; 5]) {
#[cfg(test)]
#[cfg(feature = "alloc")]
mod tests {
- use alloc::vec::Vec;
-
- use hex::prelude::*;
+ use hex::{hex, DisplayHex as _};
use super::*;
#[cfg(not(chacha20_poly1305_fuzz))]
#[test]
fn rfc7539() {
- let key = Vec::from_hex("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b")
- .unwrap()
- .as_slice()
- .try_into()
- .unwrap();
+ let key = hex!("85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b");
let mut poly = Poly1305::new(key);
let message = b"Cryptographic Forum Research Group";
poly.input(message);
diff --git a/consensus_encoding/Cargo.toml b/consensus_encoding/Cargo.toml
index e37c18b5..34ced043 100644
--- a/consensus_encoding/Cargo.toml
+++ b/consensus_encoding/Cargo.toml
@@ -23,7 +23,7 @@ alloc = ["internals/alloc"]
internals = { package = "bitcoin-internals", path = "../internals", version = "0.5.0" }
[dev-dependencies]
-hex = { package = "hex-conservative", version = "0.3.2" }
+hex = { package = "hex-conservative", version = "1.1.0" }
[package.metadata.docs.rs]
all-features = true
diff --git a/consensus_encoding/tests/iter.rs b/consensus_encoding/tests/iter.rs
index 07749bfc..918a20e3 100644
--- a/consensus_encoding/tests/iter.rs
+++ b/consensus_encoding/tests/iter.rs
@@ -52,9 +52,12 @@ fn hex_iter() {
let mut iter = BytesToHexIter::new(byte_iter, hex::Case::Upper);
let expect_str = "FFF00987";
- for byte in expect_str.chars() {
- let iter_byte = iter.next().unwrap();
- assert_eq!(iter_byte, byte);
+ let mut chars = expect_str.chars();
+ while let Some(hi) = chars.next() {
+ let iter_chars = iter.next().unwrap();
+ assert_eq!(char::from(iter_chars[0]), hi);
+ let lo = chars.next().unwrap();
+ assert_eq!(char::from(iter_chars[1]), lo);
}
let none = iter.next();
assert_eq!(none, None);
@@ -67,9 +70,13 @@ fn hex_iter_cat_encoder() {
let mut iter = BytesToHexIter::new(byte_iter, hex::Case::Lower);
let expect_str = "deadbeef";
- for byte in expect_str.chars() {
- let iter_byte = iter.next().unwrap();
- assert_eq!(iter_byte, byte);
+ let mut chars = expect_str.chars();
+ while let Some(hi) = chars.next() {
+ let iter_chars = iter.next().unwrap();
+ assert_eq!(char::from(iter_chars[0]), hi);
+ let lo = chars.next().unwrap();
+ assert_eq!(char::from(iter_chars[1]), lo);
+
}
let none = iter.next();
assert_eq!(none, None);
diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml
index 404550ab..7cd86b67 100644
--- a/crypto/Cargo.toml
+++ b/crypto/Cargo.toml
@@ -15,17 +15,16 @@ exclude = ["tests", "contrib"]
[features]
default = ["std"]
-std = ["alloc", "base58/std", "hashes/std", "hex-stable/std", "hex-unstable/std", "internals/std", "network/std", "secp256k1/std", "serde?/std"]
+std = ["alloc", "base58/std", "hashes/std", "hex/std", "internals/std", "network/std", "secp256k1/std", "serde?/std"]
rand = ["secp256k1/rand"]
-alloc = ["base58/alloc", "hashes/alloc", "hex-stable/alloc", "hex-unstable/alloc", "internals/alloc", "network/alloc", "secp256k1/alloc", "serde?/alloc"]
+alloc = ["base58/alloc", "hashes/alloc", "hex/alloc", "internals/alloc", "network/alloc", "secp256k1/alloc", "serde?/alloc"]
serde = ["dep:serde", "hashes/serde", "internals/serde", "secp256k1/serde"]
arbitrary = ["dep:arbitrary", "secp256k1/arbitrary"]
[dependencies]
base58 = { package = "base58ck", path = "../base58", version = "0.4.0", default-features = false }
hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.20.0", default-features = false, features = ["hex"] }
-hex-unstable = { package = "hex-conservative", version = "0.3.2", default-features = false }
-hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false }
internals = { package = "bitcoin-internals", path = "../internals", version = "0.5.0", features = ["hex"] }
network = { package = "bitcoin-network-kind", path = "../network", version = "0.1.0", default-features = false }
secp256k1 = { version = "0.32.0-beta.2", default-features = false }
@@ -42,8 +41,3 @@ rustdoc-args = ["--cfg", "docsrs"]
[lints]
workspace = true
-
-[package.metadata.rbmt.lint]
-allowed_duplicates = [
- "hex-conservative",
-]
diff --git a/crypto/src/ecdsa.rs b/crypto/src/ecdsa.rs
index 05c77e9a..5e7e0aaf 100644
--- a/crypto/src/ecdsa.rs
+++ b/crypto/src/ecdsa.rs
@@ -16,7 +16,7 @@ use core::str::FromStr;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
-use hex_unstable::DisplayHex;
+use hex::DisplayHex;
#[cfg(feature = "alloc")]
use internals::impl_to_hex_from_lower_hex;
#[cfg(feature = "serde")]
diff --git a/crypto/src/key.rs b/crypto/src/key.rs
index ade57a36..3f9f44cc 100644
--- a/crypto/src/key.rs
+++ b/crypto/src/key.rs
@@ -16,7 +16,7 @@ use core::str::FromStr;
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use hashes::hash160;
-use hex_unstable::DisplayHex;
+use hex::DisplayHex;
#[cfg(feature = "alloc")]
use internals::array::ArrayExt;
use internals::array_vec::ArrayVec;
diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs
index 880c33fa..bc035d1f 100644
--- a/crypto/src/lib.rs
+++ b/crypto/src/lib.rs
@@ -15,7 +15,7 @@ extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
-pub extern crate hex_stable as hex;
+pub extern crate hex;
pub extern crate base58;
diff --git a/crypto/src/taproot.rs b/crypto/src/taproot.rs
index d02474d3..2e01a051 100644
--- a/crypto/src/taproot.rs
+++ b/crypto/src/taproot.rs
@@ -166,11 +166,11 @@ impl SerializedSignature {
}
#[inline]
- fn fmt_internal(&self, f: &mut fmt::Formatter, case: hex_unstable::Case) -> fmt::Result {
+ fn fmt_internal(&self, f: &mut fmt::Formatter, case: hex::Case) -> fmt::Result {
if self.is_default() {
- hex_unstable::fmt_hex_exact!(f, MAX_LEN - 1, self, case)
+ hex::fmt_hex_exact!(f, MAX_LEN - 1, self, case)
} else {
- hex_unstable::fmt_hex_exact!(f, MAX_LEN, self, case)
+ hex::fmt_hex_exact!(f, MAX_LEN, self, case)
}
}
@@ -203,7 +203,7 @@ impl fmt::Display for SerializedSignature {
impl fmt::LowerHex for SerializedSignature {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.fmt_internal(f, hex_unstable::Case::Lower)
+ self.fmt_internal(f, hex::Case::Lower)
}
}
impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignature| signature.len
@@ -212,7 +212,7 @@ impl_to_hex_from_lower_hex!(SerializedSignature, |signature: &SerializedSignatur
impl fmt::UpperHex for SerializedSignature {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.fmt_internal(f, hex_unstable::Case::Upper)
+ self.fmt_internal(f, hex::Case::Upper)
}
}
diff --git a/hashes/Cargo.toml b/hashes/Cargo.toml
index 7d8709dc..0ccee82c 100644
--- a/hashes/Cargo.toml
+++ b/hashes/Cargo.toml
@@ -16,10 +16,9 @@ exclude = ["api", "tests", "contrib"]
[features]
default = ["std"]
-std = ["alloc", "hex-stable/std", "hex-unstable/std"]
-alloc = ["hex-stable/alloc", "hex-unstable/alloc"]
+std = ["alloc", "hex?/std"]
+alloc = ["hex?/alloc"]
serde = ["dep:serde", "hex"]
-hex = ["dep:hex-stable", "dep:hex-unstable"]
# Smaller (but slower) implementation of sha256, sha512 and ripemd160
small-hash = []
@@ -28,13 +27,10 @@ internals = { package = "bitcoin-internals", path = "../internals", version = "0
encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "0.2.0", default-features = false }
arbitrary = { version = "1.4.1", optional = true}
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, optional = true }
serde = { version = "1.0.195", default-features = false, optional = true }
cpufeatures = { version = "0.2", optional = true }
-# Both optional hex dependencies are behind the `hex` feature.
-hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false, optional = true }
-hex-unstable = { package = "hex-conservative", version = "0.3.2", default-features = false, optional = true }
-
[dev-dependencies]
serde_test = "1.0.19"
diff --git a/hashes/src/hkdf/mod.rs b/hashes/src/hkdf/mod.rs
index aa9434e4..95a29046 100644
--- a/hashes/src/hkdf/mod.rs
+++ b/hashes/src/hkdf/mod.rs
@@ -169,7 +169,7 @@ pub mod error {
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
mod tests {
- use hex_unstable::DisplayHex;
+ use hex::DisplayHex;
use super::*;
use crate::{hex, sha256};
diff --git a/hashes/src/lib.rs b/hashes/src/lib.rs
index 5818ca43..eccb7d73 100644
--- a/hashes/src/lib.rs
+++ b/hashes/src/lib.rs
@@ -82,9 +82,7 @@ extern crate serde_test;
pub extern crate encoding;
#[cfg(feature = "hex")]
-pub extern crate hex_stable as hex;
-#[cfg(feature = "hex")]
-pub extern crate hex_unstable;
+pub extern crate hex;
#[doc(hidden)]
pub mod _export {
diff --git a/hashes/src/macros.rs b/hashes/src/macros.rs
index 17f56528..c3e94f2e 100644
--- a/hashes/src/macros.rs
+++ b/hashes/src/macros.rs
@@ -279,21 +279,21 @@ macro_rules! impl_hex_string_traits {
fn fmt(&self, f: &mut $crate::_export::_core::fmt::Formatter) -> $crate::_export::_core::fmt::Result {
if $reverse {
let bytes = $crate::_export::_core::borrow::Borrow::<[u8]>::borrow(self).iter().rev();
- $crate::hex_unstable::fmt_hex_exact!(f, ($len), bytes, $case)
+ $crate::hex::fmt_hex_exact!(f, ($len), bytes, $case)
} else {
let bytes = $crate::_export::_core::borrow::Borrow::<[u8]>::borrow(self).iter();
- $crate::hex_unstable::fmt_hex_exact!(f, ($len), bytes, $case)
+ $crate::hex::fmt_hex_exact!(f, ($len), bytes, $case)
}
}
}
}
impl<$($gen: $gent),*> $crate::_export::_core::fmt::LowerHex for $ty<$($gen),*> {
- impl_case_hex!($crate::hex_unstable::Case::Lower);
+ impl_case_hex!($crate::hex::Case::Lower);
}
impl<$($gen: $gent),*> $crate::_export::_core::fmt::UpperHex for $ty<$($gen),*> {
- impl_case_hex!($crate::hex_unstable::Case::Upper);
+ impl_case_hex!($crate::hex::Case::Upper);
}
impl<$($gen: $gent),*> $crate::_export::_core::fmt::Display for $ty<$($gen),*> {
diff --git a/include/array_newtype.rs b/include/array_newtype.rs
index af19d362..7adba497 100644
--- a/include/array_newtype.rs
+++ b/include/array_newtype.rs
@@ -24,14 +24,14 @@ macro_rules! impl_array_newtype_stringify {
impl core::fmt::LowerHex for $t {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- use hex_unstable::{display, Case};
+ use hex::{display, Case};
display::fmt_hex_exact!(f, $len, &self.0, Case::Lower)
}
}
impl core::fmt::UpperHex for $t {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- use hex_unstable::{display, Case};
+ use hex::{display, Case};
display::fmt_hex_exact!(f, $len, &self.0, Case::Upper)
}
}
diff --git a/internals/Cargo.toml b/internals/Cargo.toml
index 9a1700d0..1c3d088d 100644
--- a/internals/Cargo.toml
+++ b/internals/Cargo.toml
@@ -22,7 +22,7 @@ alloc = ["hex?/alloc"]
test-serde = ["serde", "dep:serde_json", "dep:bincode"]
[dependencies]
-hex = { package = "hex-conservative", version = "0.3.2", default-features = false, optional = true }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, optional = true }
serde = { version = "1.0.195", default-features = false, optional = true }
# Behind the test-serde feature.
diff --git a/key_expression/Cargo.toml b/key_expression/Cargo.toml
index 9e368f86..839c6803 100644
--- a/key_expression/Cargo.toml
+++ b/key_expression/Cargo.toml
@@ -15,8 +15,8 @@ exclude = ["tests", "contrib"]
[features]
default = ["std"]
-std = ["alloc", "base58/std", "crypto/std", "hashes/std", "hex-unstable/std", "internals/std", "network/std", "secp256k1/std", "serde?/std"]
-alloc = ["base58/alloc", "crypto/alloc", "hashes/alloc", "hex-unstable/alloc", "internals/alloc", "network/alloc", "secp256k1/alloc", "serde?/alloc"]
+std = ["alloc", "base58/std", "crypto/std", "hashes/std", "hex/std", "internals/std", "network/std", "secp256k1/std", "serde?/std"]
+alloc = ["base58/alloc", "crypto/alloc", "hashes/alloc", "hex/alloc", "internals/alloc", "network/alloc", "secp256k1/alloc", "serde?/alloc"]
serde = ["dep:serde", "hashes/serde", "internals/serde", "secp256k1/serde"]
arbitrary = ["crypto/arbitrary", "dep:arbitrary", "hashes/arbitrary", "secp256k1/arbitrary", "network/arbitrary"]
@@ -24,8 +24,7 @@ arbitrary = ["crypto/arbitrary", "dep:arbitrary", "hashes/arbitrary", "secp256k1
base58 = { package = "base58ck", path = "../base58", version = "0.4.0", default-features = false }
crypto = { package = "bitcoin-crypto", path = "../crypto", version = "0.2.0", default-features = false }
hashes = { package = "bitcoin_hashes", path = "../hashes", version = "0.20.0", default-features = false, features = ["hex"] }
-hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false, features = ["alloc"] }
-hex-unstable = { package = "hex-conservative", version = "0.3.2", default-features = false }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, features = ["alloc"] }
internals = { package = "bitcoin-internals", path = "../internals", version = "0.5.0", features = ["hex"] }
network = { package = "bitcoin-network-kind", path = "../network", version = "0.1.0", default-features = false }
secp256k1 = { version = "0.32.0-beta.2", default-features = false }
@@ -37,11 +36,6 @@ serde = { version = "1.0.195", default-features = false, features = ["derive"],
internals = { package = "bitcoin-internals", path = "../internals", features = ["test-serde"] }
serde_json = "1.0.68"
-[package.metadata.rbmt.lint]
-allowed_duplicates = [
- "hex-conservative",
-]
-
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
diff --git a/key_expression/src/bip32.rs b/key_expression/src/bip32.rs
index a13fb7df..56049eea 100644
--- a/key_expression/src/bip32.rs
+++ b/key_expression/src/bip32.rs
@@ -1286,7 +1286,7 @@ impl<'a> Arbitrary<'a> for Xpriv {
mod tests {
use alloc::{string::ToString, format};
- use hex_unstable::hex;
+ use hex::hex;
#[cfg(feature = "serde")]
use internals::serde_round_trip;
diff --git a/key_expression/src/lib.rs b/key_expression/src/lib.rs
index 9220c39c..62d6cabf 100644
--- a/key_expression/src/lib.rs
+++ b/key_expression/src/lib.rs
@@ -20,7 +20,7 @@ extern crate std;
extern crate hashes;
-extern crate hex_stable as hex;
+extern crate hex;
#[cfg(feature = "serde")]
extern crate serde;
diff --git a/p2p/Cargo.toml b/p2p/Cargo.toml
index 14a832d5..93ad3ce1 100644
--- a/p2p/Cargo.toml
+++ b/p2p/Cargo.toml
@@ -15,7 +15,7 @@ exclude = ["tests", "contrib"]
[features]
default = ["std"]
-std = ["encoding/std", "hashes/std", "network/std", "hex-stable/std", "hex-unstable/std", "internals/std", "units/std", "primitives/std"]
+std = ["encoding/std", "hashes/std", "network/std", "hex/std", "internals/std", "units/std", "primitives/std"]
arbitrary = ["dep:arbitrary", "primitives/arbitrary"]
serde = ["dep:serde", "hashes/serde"]
@@ -24,8 +24,7 @@ encoding = { package = "bitcoin-consensus-encoding", version = "0.2.0", path = "
hashes = { package = "bitcoin_hashes", version = "0.20.0", path = "../hashes", default-features = false }
network = { package = "bitcoin-network-kind", path = "../network", version = "0.1.0", default-features = false }
primitives = { package = "bitcoin-primitives", path = "../primitives", version = "0.102.0", features = ["hex", "alloc"], default-features = false }
-hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false, features = ["alloc"] }
-hex-unstable = { package = "hex-conservative", version = "0.3.2", default-features = false }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, features = ["alloc"] }
internals = { package = "bitcoin-internals", path = "../internals", default-features = false }
units = { package = "bitcoin-units", path = "../units", version = "0.3.0", default-features = false }
@@ -51,8 +50,3 @@ workspace = true
exact_features = [
["std", "serde"],
]
-
-[package.metadata.rbmt.lint]
-allowed_duplicates = [
- "hex-conservative",
-]
diff --git a/p2p/src/address.rs b/p2p/src/address.rs
index bd5edbb2..3fda3b40 100644
--- a/p2p/src/address.rs
+++ b/p2p/src/address.rs
@@ -1109,7 +1109,7 @@ mod test {
use std::net::IpAddr;
use encoding::{Encode as _, Encoder as _, ExactSizeEncoder as _};
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
use crate::hex;
diff --git a/p2p/src/bip152.rs b/p2p/src/bip152.rs
index 7bfef4e0..570a404b 100644
--- a/p2p/src/bip152.rs
+++ b/p2p/src/bip152.rs
@@ -166,13 +166,13 @@ impl ShortId {
impl core::fmt::LowerHex for ShortId {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- hex_unstable::display::fmt_hex_exact!(f, 6, &self.0, hex_unstable::Case::Lower)
+ hex::display::fmt_hex_exact!(f, 6, &self.0, hex::Case::Lower)
}
}
impl core::fmt::UpperHex for ShortId {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
- hex_unstable::display::fmt_hex_exact!(f, 6, &self.0, hex_unstable::Case::Upper)
+ hex::display::fmt_hex_exact!(f, 6, &self.0, hex::Case::Upper)
}
}
diff --git a/p2p/src/lib.rs b/p2p/src/lib.rs
index 90d7e193..2ffe30bc 100644
--- a/p2p/src/lib.rs
+++ b/p2p/src/lib.rs
@@ -34,7 +34,7 @@ pub extern crate serde;
#[cfg(feature = "arbitrary")]
pub extern crate arbitrary;
-pub extern crate hex_stable as hex;
+pub extern crate hex;
use alloc::borrow::ToOwned;
use core::borrow::{Borrow, BorrowMut};
@@ -433,7 +433,7 @@ impl fmt::Debug for Magic {
impl fmt::LowerHex for Magic {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- hex_unstable::fmt_hex_exact!(f, 4, &self.0, hex_unstable::Case::Lower)?;
+ hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Lower)?;
Ok(())
}
}
@@ -441,7 +441,7 @@ impl_to_hex_from_lower_hex!(Magic, |_| 8);
impl fmt::UpperHex for Magic {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- hex_unstable::fmt_hex_exact!(f, 4, &self.0, hex_unstable::Case::Upper)?;
+ hex::fmt_hex_exact!(f, 4, &self.0, hex::Case::Upper)?;
Ok(())
}
}
diff --git a/p2p/src/merkle_tree.rs b/p2p/src/merkle_tree.rs
index ca92ee8d..d9c61b84 100644
--- a/p2p/src/merkle_tree.rs
+++ b/p2p/src/merkle_tree.rs
@@ -688,7 +688,7 @@ impl<'a> Arbitrary<'a> for MerkleBlock {
mod tests {
use core::cmp;
- use hex_unstable::{hex, DisplayHex};
+ use hex::{hex, DisplayHex};
use primitives::block::Unchecked;
use super::*;
diff --git a/p2p/src/message.rs b/p2p/src/message.rs
index 53431339..eaceddf9 100644
--- a/p2p/src/message.rs
+++ b/p2p/src/message.rs
@@ -2400,7 +2400,7 @@ mod test {
use alloc::vec;
use std::net::Ipv4Addr;
- use hex_unstable::hex;
+ use hex::hex;
use primitives::transaction::{Transaction, Txid};
use primitives::{Block, BlockHash};
use units::BlockHeight;
diff --git a/p2p/src/message_blockdata.rs b/p2p/src/message_blockdata.rs
index 33ef1f7d..e22da6ff 100644
--- a/p2p/src/message_blockdata.rs
+++ b/p2p/src/message_blockdata.rs
@@ -520,7 +520,7 @@ impl<'a> Arbitrary<'a> for Inventory {
#[cfg(test)]
mod tests {
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
diff --git a/p2p/src/message_network.rs b/p2p/src/message_network.rs
index 139f866c..8d31a488 100644
--- a/p2p/src/message_network.rs
+++ b/p2p/src/message_network.rs
@@ -870,7 +870,7 @@ impl<'a> Arbitrary<'a> for Alert {
mod tests {
use alloc::string::ToString;
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml
index ccb23bf0..11c5d9ae 100644
--- a/primitives/Cargo.toml
+++ b/primitives/Cargo.toml
@@ -15,11 +15,11 @@ exclude = ["api", "tests", "contrib"]
[features]
default = ["std", "hex"]
-std = ["alloc", "hashes/std", "hex-stable?/std", "hex-unstable?/std", "internals/std", "units/std"]
-alloc = ["hashes/alloc", "hex-stable?/alloc", "hex-unstable?/alloc", "internals/alloc", "units/alloc"]
+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", "hex"]
arbitrary = ["dep:arbitrary", "units/arbitrary"]
-hex = ["dep:hex-stable", "dep:hex-unstable", "hashes/hex", "internals/hex"]
+hex = ["dep:hex", "hashes/hex", "internals/hex"]
[dependencies]
encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "0.2.0", default-features = false }
@@ -28,10 +28,8 @@ internals = { package = "bitcoin-internals", path = "../internals", version = "0
units = { package = "bitcoin-units", path = "../units", version = "0.3.0", default-features = false, features = [ "encoding" ] }
arbitrary = { version = "1.4.1", optional = true }
+hex = { package = "hex-conservative", version = "1.1.0", default-features = false, optional = true }
serde = { version = "1.0.195", default-features = false, features = ["derive", "alloc"], optional = true }
-# Both optional hex dependencies are behind the `hex` feature.
-hex-stable = { package = "hex-conservative", version = "1.0.0", default-features = false, optional = true }
-hex-unstable = { package = "hex-conservative", version = "0.3.2", default-features = false, optional = true }
[dev-dependencies]
serde_json = "1.0.68"
diff --git a/primitives/src/block.rs b/primitives/src/block.rs
index 30ea2a55..8b954842 100644
--- a/primitives/src/block.rs
+++ b/primitives/src/block.rs
@@ -1014,7 +1014,7 @@ mod tests {
use encoding::Decode as _;
use encoding::{Decoder as _, Encode as _, Encoder as _};
#[cfg(feature = "hex")]
- use hex_unstable::hex;
+ use hex::hex;
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
#[cfg(feature = "serde")]
diff --git a/primitives/src/hex_codec.rs b/primitives/src/hex_codec.rs
index 3c1c1032..ee9ebe4a 100644
--- a/primitives/src/hex_codec.rs
+++ b/primitives/src/hex_codec.rs
@@ -13,7 +13,7 @@ use core::fmt;
use core::fmt::Write as _;
use encoding::{Decode, Decoder, Encode, EncoderByteIter};
-use hex_unstable::{BytesToHexIter, Case};
+use hex::{BytesToHexIter, Case};
use internals::write_err;
/// Hex encoding wrapper type for `Encode` + `Decode` types.
@@ -42,7 +42,7 @@ impl<T: Decode> HexPrimitive<'_, T> {
/// * `OddLength` or `InvalidChar` if decode the hex string to bytes fails.
/// * `Decode` if consensus decoding the hex-decoded bytes fails.
pub(crate) fn from_str(s: &str) -> Result<T, ParsePrimitiveError<T>> {
- let iter = hex_unstable::HexToBytesIter::new(s)?;
+ let iter = hex::HexSliceToBytesIter::new(s)?;
let mut decoder = T::decoder();
let mut buffer = [0u8; 4096]; // 4MB is bigger than most decodables, reducing push_bytes calls.
@@ -108,17 +108,25 @@ impl<T: Encode> HexPrimitive<'_, T> {
// Alt characters
if f.alternate() {
f.write_str(match case {
- hex_unstable::Case::Lower => "0x",
- hex_unstable::Case::Upper => "0X",
+ hex::Case::Lower => "0x",
+ hex::Case::Upper => "0X",
})?;
}
// Hex data
- for (i, ch) in iter.enumerate() {
- if i >= trunc_width {
+ let mut remaining = trunc_width;
+ for chars in iter {
+ if remaining == 0 {
break;
}
- f.write_char(ch)?;
+ f.write_char(chars[0].into())?;
+ remaining -= 1;
+
+ if remaining == 0 {
+ break;
+ }
+ f.write_char(chars[1].into())?;
+ remaining -= 1;
}
// Right padding
@@ -151,9 +159,9 @@ impl<T: Encode> fmt::UpperHex for HexPrimitive<'_, T> {
/// An error type for errors that can occur during parsing of a `Decode` type from hex.
pub(crate) enum ParsePrimitiveError<T: Decode> {
/// Tried to decode an odd length string
- OddLengthString(hex_unstable::OddLengthStringError),
+ OddLengthString(hex::OddLengthStringError),
/// Encountered an invalid hex character
- InvalidChar(hex_unstable::InvalidCharError),
+ InvalidChar(hex::InvalidCharError),
/// A decode error from `consensus_encoding`
Decode(encoding::DecodeError<<T::Decoder as encoding::Decoder>::Error>),
}
@@ -211,12 +219,12 @@ impl<T: Decode> fmt::Display for ParsePrimitiveError<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self, f) }
}
-impl<T: Decode> From<hex_unstable::OddLengthStringError> for ParsePrimitiveError<T> {
- fn from(err: hex_unstable::OddLengthStringError) -> Self { Self::OddLengthString(err) }
+impl<T: Decode> From<hex::OddLengthStringError> for ParsePrimitiveError<T> {
+ fn from(err: hex::OddLengthStringError) -> Self { Self::OddLengthString(err) }
}
-impl<T: Decode> From<hex_unstable::InvalidCharError> for ParsePrimitiveError<T> {
- fn from(err: hex_unstable::InvalidCharError) -> Self { Self::InvalidChar(err) }
+impl<T: Decode> From<hex::InvalidCharError> for ParsePrimitiveError<T> {
+ fn from(err: hex::InvalidCharError) -> Self { Self::InvalidChar(err) }
}
#[cfg(feature = "std")]
@@ -280,9 +288,11 @@ mod tests {
#[test]
#[cfg(feature = "alloc")]
fn hex_primitive_from_str_flushes_full_buffer() {
+ use hex::DisplayHex as _;
+
// 300 headers force multiple full 4096-byte decoder flushes plus a final remainder flush.
let bytes = vec![0u8; block::Header::SIZE * 300];
- let encoded = hex_unstable::DisplayHex::as_hex(&bytes).to_string();
+ let encoded = bytes.as_hex().to_string();
let parsed = HexPrimitive::<block::Header>::from_str(&encoded).unwrap();
diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs
index 650c79a1..4452c26b 100644
--- a/primitives/src/lib.rs
+++ b/primitives/src/lib.rs
@@ -35,7 +35,7 @@ pub extern crate arbitrary;
pub extern crate encoding;
#[cfg(feature = "hex")]
-pub extern crate hex_stable as hex;
+pub extern crate hex;
#[doc(hidden)]
pub mod _export {
diff --git a/primitives/src/script/borrowed.rs b/primitives/src/script/borrowed.rs
index f6e0413e..0b1a7cad 100644
--- a/primitives/src/script/borrowed.rs
+++ b/primitives/src/script/borrowed.rs
@@ -132,10 +132,10 @@ impl<T> Script<T> {
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
pub fn to_hex_string_prefixed(&self) -> String {
- use hex_unstable::{BytesToHexIter, Case};
+ use hex::{BytesToHexIter, Case};
let iter = encoding::EncoderByteIter::new(self.encoder());
- BytesToHexIter::new(iter, Case::Lower).collect()
+ BytesToHexIter::new(iter, Case::Lower).flatten().map(char::from).collect()
}
/// Encodes the script as lower-case hex.
@@ -145,7 +145,7 @@ impl<T> Script<T> {
#[cfg(feature = "alloc")]
#[cfg(feature = "hex")]
pub fn to_hex_string_no_length_prefix(&self) -> String {
- use hex_unstable::DisplayHex as _;
+ use hex::DisplayHex as _;
self.as_bytes().to_lower_hex_string()
}
diff --git a/primitives/src/script/mod.rs b/primitives/src/script/mod.rs
index 301b7001..3d7e4520 100644
--- a/primitives/src/script/mod.rs
+++ b/primitives/src/script/mod.rs
@@ -16,7 +16,7 @@ use core::fmt;
use core::marker::PhantomData;
#[cfg(feature = "hex")]
-use hex_unstable::DisplayHex;
+use hex::DisplayHex;
use internals::script::{self, PushDataLenLen};
use crate::prelude::rc::Rc;
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index c1f8f97d..309e1128 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -1614,7 +1614,7 @@ mod tests {
use encoding::{Decode as _, Decoder as _, Encoder as _};
#[cfg(feature = "hex")]
- use hex_unstable::hex;
+ use hex::hex;
use super::*;
#[cfg(feature = "hex")]
diff --git a/primitives/src/witness.rs b/primitives/src/witness.rs
index 9c0c23bd..8978e3e3 100644
--- a/primitives/src/witness.rs
+++ b/primitives/src/witness.rs
@@ -618,9 +618,7 @@ impl fmt::Debug for Witness {
&WrapDebug(|f| {
#[cfg(feature = "hex")]
{
- f.debug_list()
- .entries(self.iter().map(hex_unstable::DisplayHex::as_hex))
- .finish()
+ f.debug_list().entries(self.iter().map(hex::DisplayHex::as_hex)).finish()
}
#[cfg(not(feature = "hex"))]
{
diff --git a/primitives/tests/encoding.rs b/primitives/tests/encoding.rs
index e8af097c..e922e978 100644
--- a/primitives/tests/encoding.rs
+++ b/primitives/tests/encoding.rs
@@ -14,7 +14,7 @@ use bitcoin_primitives::{
ScriptPubKeyBuf, ScriptSigBuf, Sequence, Witness,
};
use encoding::{Decode as _, Decoder as _, Encode as _, Encoder as _};
-use hex_unstable::hex;
+use hex::hex;
const TC_TXID_BYTES: [u8; 32] = [
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9,
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.