bitcoin: Add explicit None return impl for std::error::Error
What changed, and why it matters
This commit is a code clarity improvement only. It replaces empty default implementations of Rust's standard error trait with explicit implementations that return 'None' for the underlying cause. The behavior is identical before and after the change; it just makes the code easier to read for future maintainers.
No security action needed. This is a non-functional refactor improving code readability.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch changes impl std::error::Error for T {} blocks to explicitly implement fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None } across seven files. For enum error types, it adds match arms returning None for each variant. This is semantically equivalent to the default trait implementation, which already returns None. No logic, parsing, cryptography, or network behavior is altered.
Changed components
bitcoin/src/address/error.rsbitcoin/src/bip32.rsbitcoin/src/blockdata/script/push_bytes.rsbitcoin/src/blockdata/script/witness_version.rsbitcoin/src/crypto/key.rsbitcoin/src/taproot/merkle_branch/mod.rsbitcoin/src/taproot/mod.rsInspect captured patch +77 / −19
diff --git a/bitcoin/src/address/error.rs b/bitcoin/src/address/error.rs
index 82290920..867809b9 100644
--- a/bitcoin/src/address/error.rs
+++ b/bitcoin/src/address/error.rs
@@ -156,7 +156,9 @@ impl fmt::Display for NetworkValidationError {
}
#[cfg(feature = "std")]
-impl std::error::Error for NetworkValidationError {}
+impl std::error::Error for NetworkValidationError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Bech32 related error.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -309,7 +311,9 @@ impl fmt::Display for InvalidBase58PayloadLengthError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidBase58PayloadLengthError {}
+impl std::error::Error for InvalidBase58PayloadLengthError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Legacy base58 address was too long, max 50 characters.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -334,7 +338,9 @@ impl fmt::Display for LegacyAddressTooLongError {
}
#[cfg(feature = "std")]
-impl std::error::Error for LegacyAddressTooLongError {}
+impl std::error::Error for LegacyAddressTooLongError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Invalid legacy address prefix in decoded base58 data.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -355,4 +361,6 @@ impl fmt::Display for InvalidLegacyPrefixError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidLegacyPrefixError {}
+impl std::error::Error for InvalidLegacyPrefixError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
diff --git a/bitcoin/src/bip32.rs b/bitcoin/src/bip32.rs
index fc0b718c..fa6004f4 100644
--- a/bitcoin/src/bip32.rs
+++ b/bitcoin/src/bip32.rs
@@ -642,7 +642,14 @@ pub enum DerivationError {
}
#[cfg(feature = "std")]
-impl std::error::Error for DerivationError {}
+impl std::error::Error for DerivationError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ match self {
+ Self::CannotDeriveHardenedChild => None,
+ Self::MaximumDepthExceeded => None,
+ }
+ }
+}
impl fmt::Display for DerivationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -676,7 +683,9 @@ impl fmt::Display for IndexOutOfRangeError {
}
#[cfg(feature = "std")]
-impl std::error::Error for IndexOutOfRangeError {}
+impl std::error::Error for IndexOutOfRangeError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Error parsing a child number.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1061,7 +1070,9 @@ impl fmt::Display for InvalidBase58PayloadLengthError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidBase58PayloadLengthError {}
+impl std::error::Error for InvalidBase58PayloadLengthError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
// Helps unify decoding
struct Common {
diff --git a/bitcoin/src/blockdata/script/push_bytes.rs b/bitcoin/src/blockdata/script/push_bytes.rs
index 572edd62..8591268f 100644
--- a/bitcoin/src/blockdata/script/push_bytes.rs
+++ b/bitcoin/src/blockdata/script/push_bytes.rs
@@ -447,7 +447,14 @@ pub enum ScriptIntError {
}
#[cfg(feature = "std")]
-impl std::error::Error for ScriptIntError {}
+impl std::error::Error for ScriptIntError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ match self {
+ Self::NumericOverflow => None,
+ Self::NonMinimal => None,
+ }
+ }
+}
impl fmt::Display for ScriptIntError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/bitcoin/src/blockdata/script/witness_version.rs b/bitcoin/src/blockdata/script/witness_version.rs
index bc09c68c..5a619eb2 100644
--- a/bitcoin/src/blockdata/script/witness_version.rs
+++ b/bitcoin/src/blockdata/script/witness_version.rs
@@ -247,4 +247,6 @@ impl fmt::Display for TryFromError {
}
#[cfg(feature = "std")]
-impl std::error::Error for TryFromError {}
+impl std::error::Error for TryFromError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs
index 2a975537..82c5cf46 100644
--- a/bitcoin/src/crypto/key.rs
+++ b/bitcoin/src/crypto/key.rs
@@ -1764,7 +1764,9 @@ impl fmt::Display for InvalidBase58PayloadLengthError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidBase58PayloadLengthError {}
+impl std::error::Error for InvalidBase58PayloadLengthError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Invalid address version in decoded base58 data.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1785,7 +1787,9 @@ impl fmt::Display for InvalidAddressVersionError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidAddressVersionError {}
+impl std::error::Error for InvalidAddressVersionError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Invalid compression flag for a WIF key
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1806,7 +1810,9 @@ impl fmt::Display for InvalidWifCompressionFlagError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidWifCompressionFlagError {}
+impl std::error::Error for InvalidWifCompressionFlagError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
impl SerializedXOnlyPublicKey {
/// Returns `XOnlyPublicKey` if the bytes are valid.
@@ -1850,7 +1856,13 @@ impl fmt::Display for ParseXOnlyPublicKeyError {
}
#[cfg(feature = "std")]
-impl std::error::Error for ParseXOnlyPublicKeyError {}
+impl std::error::Error for ParseXOnlyPublicKeyError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ match self {
+ Self::InvalidXCoordinate => None,
+ }
+ }
+}
/// Error that can occur when tweaking an [`XOnlyPublicKey`].
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1874,7 +1886,15 @@ impl fmt::Display for TweakXOnlyPublicKeyError {
}
#[cfg(feature = "std")]
-impl std::error::Error for TweakXOnlyPublicKeyError {}
+impl std::error::Error for TweakXOnlyPublicKeyError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ match self {
+ Self::BadTweak => None,
+ Self::ResultKeyInvalid => None,
+ Self::ParityError => None,
+ }
+ }
+}
#[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for PublicKey {
diff --git a/bitcoin/src/taproot/merkle_branch/mod.rs b/bitcoin/src/taproot/merkle_branch/mod.rs
index 56a14234..b86c2104 100644
--- a/bitcoin/src/taproot/merkle_branch/mod.rs
+++ b/bitcoin/src/taproot/merkle_branch/mod.rs
@@ -58,7 +58,9 @@ impl fmt::Display for DecodeError {
}
#[cfg(feature = "std")]
-impl std::error::Error for DecodeError {}
+impl std::error::Error for DecodeError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
impl From<DecodeError> for TaprootError {
fn from(value: DecodeError) -> Self {
diff --git a/bitcoin/src/taproot/mod.rs b/bitcoin/src/taproot/mod.rs
index c7aeb88a..04082545 100644
--- a/bitcoin/src/taproot/mod.rs
+++ b/bitcoin/src/taproot/mod.rs
@@ -1579,7 +1579,9 @@ impl fmt::Display for InvalidMerkleBranchSizeError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidMerkleBranchSizeError {}
+impl std::error::Error for InvalidMerkleBranchSizeError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Merkle tree depth must not be more than 128.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1605,7 +1607,9 @@ impl fmt::Display for InvalidMerkleTreeDepthError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidMerkleTreeDepthError {}
+impl std::error::Error for InvalidMerkleTreeDepthError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// The last bit of tapleaf version must be zero.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1627,7 +1631,9 @@ impl fmt::Display for InvalidTaprootLeafVersionError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidTaprootLeafVersionError {}
+impl std::error::Error for InvalidTaprootLeafVersionError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
/// Invalid control block size.
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -1653,7 +1659,9 @@ impl fmt::Display for InvalidControlBlockSizeError {
}
#[cfg(feature = "std")]
-impl std::error::Error for InvalidControlBlockSizeError {}
+impl std::error::Error for InvalidControlBlockSizeError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+}
#[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for TapLeafHash {
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.