Remove HexPrimitive use in ScriptBuf::from_hex_prefixed
What changed, and why it matters
This commit is a routine internal cleanup in the rust-bitcoin library. It removes a custom error type and switches one function to use a newer, shared hex-decoding path. There is no indication this fixes a security bug; it is a refactoring change.
No security action required. Treat as a normal API/dependency refactor. Reviewers may want to confirm the new `encoding::FromHexError` exposes equivalent error information for downstream users.
Security signals we found
No security-relevant keywords in commit title or message
No bug-fix or vulnerability description present
Refactoring-only change: removes dead error type and consolidates decoding path
No changes to cryptographic, consensus, or script validation logic
Evidence from the diff
The patch removes the single-use script::FromHexError type and replaces ScriptBuf::from_hex_prefixed’s use of HexPrimitive with encoding::decode_from_hex from bitcoin-consensus-encoding. This is a code-simplification refactor enabled by the stabilization of consensus_encoding. The public API changes slightly (returned error type changes), but the functional behavior—parsing a length-prefixed hex script—remains the same.
Changed components
bitcoin/src/blockdata/script/mod.rsprimitives/Cargo.tomlprimitives/src/script/error.rsprimitives/src/script/mod.rsprimitives/src/script/owned.rsInspect captured patch +7 / −65
diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs
index f6be5a0d..10bc098a 100644
--- a/bitcoin/src/blockdata/script/mod.rs
+++ b/bitcoin/src/blockdata/script/mod.rs
@@ -87,8 +87,7 @@ pub use primitives::script::{
pub(crate) use self::borrowed::ScriptExtPriv;
#[doc(no_inline)]
pub use self::error::{
- Error, FromHexError, PushBytesError, RedeemScriptSizeError, ScriptIntError,
- WitnessScriptSizeError,
+ Error, PushBytesError, RedeemScriptSizeError, ScriptIntError, WitnessScriptSizeError,
};
pub(crate) use self::owned::ScriptBufExtPriv;
@@ -251,8 +250,7 @@ pub mod error {
pub use super::push_bytes::ScriptIntError;
#[doc(no_inline)]
pub use primitives::script::error::{
- FromHexError, PushBytesError, RedeemScriptSizeError, ScriptBufDecoderError,
- WitnessScriptSizeError,
+ PushBytesError, RedeemScriptSizeError, ScriptBufDecoderError, WitnessScriptSizeError,
};
/// Ways that a script might fail. Not everything is split up as
diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml
index 0e6011d9..2d2f197d 100644
--- a/primitives/Cargo.toml
+++ b/primitives/Cargo.toml
@@ -19,7 +19,7 @@ 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", "hashes/hex", "internals/hex"]
+hex = ["dep:hex", "hashes/hex", "internals/hex", "encoding/hex"]
[dependencies]
encoding = { package = "bitcoin-consensus-encoding", path = "../consensus_encoding", version = "1.0.0", default-features = false }
diff --git a/primitives/src/script/error.rs b/primitives/src/script/error.rs
index 639d4b55..d76749e2 100644
--- a/primitives/src/script/error.rs
+++ b/primitives/src/script/error.rs
@@ -30,50 +30,3 @@ impl fmt::Display for ScriptBufDecoderError {
impl std::error::Error for ScriptBufDecoderError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
}
-
-/// An error parsing a script from hex.
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[non_exhaustive]
-#[cfg(feature = "hex")]
-pub enum FromHexError {
- /// Error parsing the hex input string.
- Hex(hex::DecodeVariableLengthBytesError),
- /// Error when decoding the script.
- Decoder(encoding::DecodeError<ScriptBufDecoderError>),
-}
-
-#[cfg(feature = "hex")]
-impl From<Infallible> for FromHexError {
- fn from(never: Infallible) -> Self { match never {} }
-}
-
-#[cfg(feature = "hex")]
-impl fmt::Display for FromHexError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Self::Hex(ref e) => write_err!(f, "script hex"; e),
- Self::Decoder(ref e) => write_err!(f, "script decoder"; e),
- }
- }
-}
-
-#[cfg(feature = "hex")]
-#[cfg(feature = "std")]
-impl std::error::Error for FromHexError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match *self {
- Self::Hex(ref e) => Some(e),
- Self::Decoder(ref e) => Some(e),
- }
- }
-}
-
-#[cfg(feature = "hex")]
-impl From<hex::DecodeVariableLengthBytesError> for FromHexError {
- fn from(e: hex::DecodeVariableLengthBytesError) -> Self { Self::Hex(e) }
-}
-
-#[cfg(feature = "hex")]
-impl From<encoding::DecodeError<ScriptBufDecoderError>> for FromHexError {
- fn from(e: encoding::DecodeError<ScriptBufDecoderError>) -> Self { Self::Decoder(e) }
-}
diff --git a/primitives/src/script/mod.rs b/primitives/src/script/mod.rs
index 024da01f..e84f4390 100644
--- a/primitives/src/script/mod.rs
+++ b/primitives/src/script/mod.rs
@@ -34,9 +34,6 @@ pub use self::{
tag::{Tag, RedeemScriptTag, ScriptPubKeyTag, ScriptSigTag, SignetBlockScriptTag, TapScriptTag, WitnessScriptTag},
};
#[doc(no_inline)]
-#[cfg(feature = "hex")]
-pub use self::error::FromHexError;
-#[doc(no_inline)]
pub use self::error::{
PushBytesError, RedeemScriptSizeError, ScriptBufDecoderError, WitnessScriptSizeError,
};
diff --git a/primitives/src/script/owned.rs b/primitives/src/script/owned.rs
index 06336d22..b054fd64 100644
--- a/primitives/src/script/owned.rs
+++ b/primitives/src/script/owned.rs
@@ -7,8 +7,6 @@ use core::ops::{Deref, DerefMut};
use arbitrary::{Arbitrary, Unstructured};
use encoding::{ByteVecDecoder, DecoderStatus};
-#[cfg(feature = "hex")]
-use super::error::FromHexError;
use super::{Script, ScriptBufDecoderError};
use crate::prelude::{Box, Vec};
@@ -59,14 +57,10 @@ impl<T> ScriptBuf<T> {
/// * If `s` cannot be parsed into a vector.
/// * If the parsed bytes cannot be decoded as a valid script (incl.the length prefix).
#[cfg(feature = "hex")]
- pub fn from_hex_prefixed(s: &str) -> Result<Self, FromHexError> {
- use crate::hex_codec::{HexPrimitive, ParsePrimitiveError as P};
-
- HexPrimitive::<Self>::from_str(s).map_err(|err| match err {
- P::OddLengthString(e) => FromHexError::Hex(e.into()),
- P::InvalidChar(e) => FromHexError::Hex(e.into()),
- P::Decode(e) => e.into(),
- })
+ pub fn from_hex_prefixed(
+ s: &str,
+ ) -> Result<Self, encoding::FromHexError<ScriptBufDecoderError>> {
+ encoding::decode_from_hex(s)
}
/// Constructs a new [`ScriptBuf`] from a hex string.
Why this scored 17/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.