Fix decoder error Display and source impls
What changed, and why it matters
This commit fixes how several Bitcoin data-decoding error types print messages and report their underlying cause. The changes are cosmetic/correctness improvements to error formatting and the `source()` chain used by Rust's standard error handling. There is no evidence of a security vulnerability, remote exploit, or memory-safety bug in the diff.
No security action required. Treat as a normal bugfix/correctness patch. If consuming these error types programmatically, note that `source()` now points to the wrapper error rather than its inner variant, which may affect error-chain traversal.
Security signals we found
No parsing or validation logic changed
No buffer, integer, or cryptographic operations modified
Changes confined to error message strings and error source chaining
No vendor security disclosure or advisory referenced
Evidence from the diff
The patch corrects Display and std::error::Error::source implementations for decoder error wrappers in rust-bitcoin. It replaces incorrect copy-pasted messages (e.g., ‘sequence decoder error’ used for tx merkle node, witness merkle node, and compact target errors) with accurate labels, and changes source() to return the wrapped composite error directly rather than pattern-matching on its variants. ParseTransactionError::fmt is also switched from a Debug fallback to a proper write_err! message. These are API/UX correctness fixes; they do not alter parsing logic, bounds checks, or cryptographic validation.
Changed components
p2p/src/message_bloom.rs (FilterAddDecoderError Display)primitives/src/block.rs (BlockDecoderError Display/source)primitives/src/hash_types/transaction_merkle_node.rs (TxMerkleNodeDecoderError Display)primitives/src/hash_types/witness_merkle_node.rs (WitnessMerkleNodeDecoderError Display)primitives/src/transaction.rs (ParseTransactionError Display, TxInDecoderError Display/source, TxOutDecoderError Display/source)units/src/pow.rs (CompactTargetDecoderError Display)Inspect captured patch +11 / −37
diff --git a/p2p/src/message_bloom.rs b/p2p/src/message_bloom.rs
index 455742aa..1b974ed7 100644
--- a/p2p/src/message_bloom.rs
+++ b/p2p/src/message_bloom.rs
@@ -318,7 +318,7 @@ impl From<Infallible> for FilterAddDecoderError {
impl fmt::Display for FilterAddDecoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write_err!(f, "filteradd error"; self)
+ write_err!(f, "filteradd error"; self.0)
}
}
diff --git a/primitives/src/block.rs b/primitives/src/block.rs
index e035a562..d30a87b6 100644
--- a/primitives/src/block.rs
+++ b/primitives/src/block.rs
@@ -412,22 +412,14 @@ impl From<Infallible> for BlockDecoderError {
#[cfg(feature = "alloc")]
impl fmt::Display for BlockDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match &self.0 {
- encoding::Decoder2Error::First(ref e) => write_err!(f, "block decoder error"; e),
- encoding::Decoder2Error::Second(ref e) => write_err!(f, "block decoder error"; e),
- }
+ write_err!(f, "block decoder error"; self.0)
}
}
#[cfg(feature = "alloc")]
#[cfg(feature = "std")]
impl std::error::Error for BlockDecoderError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match &self.0 {
- encoding::Decoder2Error::First(ref e) => Some(e),
- encoding::Decoder2Error::Second(ref e) => Some(e),
- }
- }
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
}
/// Invalid block error.
diff --git a/primitives/src/hash_types/transaction_merkle_node.rs b/primitives/src/hash_types/transaction_merkle_node.rs
index 14e2b648..6df8e727 100644
--- a/primitives/src/hash_types/transaction_merkle_node.rs
+++ b/primitives/src/hash_types/transaction_merkle_node.rs
@@ -110,7 +110,7 @@ impl From<Infallible> for TxMerkleNodeDecoderError {
impl fmt::Display for TxMerkleNodeDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write_err!(f, "sequence decoder error"; self.0)
+ write_err!(f, "tx merkle node decoder error"; self.0)
}
}
diff --git a/primitives/src/hash_types/witness_merkle_node.rs b/primitives/src/hash_types/witness_merkle_node.rs
index 0e685610..78b4b253 100644
--- a/primitives/src/hash_types/witness_merkle_node.rs
+++ b/primitives/src/hash_types/witness_merkle_node.rs
@@ -110,7 +110,7 @@ impl From<Infallible> for WitnessMerkleNodeDecoderError {
impl fmt::Display for WitnessMerkleNodeDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write_err!(f, "sequence decoder error"; self.0)
+ write_err!(f, "witness merkle node decoder error"; self.0)
}
}
diff --git a/primitives/src/transaction.rs b/primitives/src/transaction.rs
index 508c4eea..54175d00 100644
--- a/primitives/src/transaction.rs
+++ b/primitives/src/transaction.rs
@@ -422,7 +422,7 @@ impl fmt::Debug for ParseTransactionError {
#[cfg(all(feature = "hex", feature = "alloc"))]
impl fmt::Display for ParseTransactionError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self, f) }
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write_err!(f, "parse transaction error"; self.0) }
}
#[cfg(all(feature = "hex", feature = "alloc", feature = "std"))]
@@ -1014,24 +1014,14 @@ impl From<Infallible> for TxInDecoderError {
#[cfg(feature = "alloc")]
impl fmt::Display for TxInDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match &self.0 {
- encoding::Decoder3Error::First(ref e) => write_err!(f, "txin decoder error"; e),
- encoding::Decoder3Error::Second(ref e) => write_err!(f, "txin decoder error"; e),
- encoding::Decoder3Error::Third(ref e) => write_err!(f, "txin decoder error"; e),
- }
+ write_err!(f, "txin decoder error"; self.0)
}
}
#[cfg(feature = "alloc")]
#[cfg(feature = "std")]
impl std::error::Error for TxInDecoderError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match &self.0 {
- encoding::Decoder3Error::First(ref e) => Some(e),
- encoding::Decoder3Error::Second(ref e) => Some(e),
- encoding::Decoder3Error::Third(ref e) => Some(e),
- }
- }
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
}
/// Bitcoin transaction output.
@@ -1120,21 +1110,13 @@ impl From<Infallible> for TxOutDecoderError {
#[cfg(feature = "alloc")]
impl fmt::Display for TxOutDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match &self.0 {
- encoding::Decoder2Error::First(ref e) => write_err!(f, "txout decoder error"; e),
- encoding::Decoder2Error::Second(ref e) => write_err!(f, "txout decoder error"; e),
- }
+ write_err!(f, "txout decoder error"; self.0)
}
}
#[cfg(feature = "std")]
impl std::error::Error for TxOutDecoderError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
- match &self.0 {
- encoding::Decoder2Error::First(ref e) => Some(e),
- encoding::Decoder2Error::Second(ref e) => Some(e),
- }
- }
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
}
/// A reference to a transaction output.
diff --git a/units/src/pow.rs b/units/src/pow.rs
index e1057795..32815a4e 100644
--- a/units/src/pow.rs
+++ b/units/src/pow.rs
@@ -156,7 +156,7 @@ impl From<Infallible> for CompactTargetDecoderError {
#[cfg(feature = "encoding")]
impl fmt::Display for CompactTargetDecoderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write_err!(f, "sequence decoder error"; self.0)
+ write_err!(f, "compact target decoder error"; self.0)
}
}
Why this scored 18/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.