bitcoin: Move transaction module errors to error submodule
What changed, and why it matters
This commit is a straightforward internal code reorganization. It moves several error type definitions from one place in the transaction module into a new 'error' submodule and re-exports them so existing code can still use them the same way. There is no functional change to how transactions are validated, parsed, or secured.
No security action needed; treat as routine refactoring.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch refactors bitcoin/src/blockdata/transaction.rs by creating a new error submodule and moving IndexOutOfBoundsError, InputsIndexError, and OutputsIndexError into it, along with re-exporting decoder/parse errors from primitives::transaction::error. Public API paths are preserved via pub use self::error::{...}. The write_err import is relocated accordingly and core::fmt is no longer imported at the module top level. No logic, bounds checks, or behavior changed.
Changed components
bitcoin/src/blockdata/transaction.rsInspect captured patch +87 / −68
diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs
index b7cb8262..d6ae56d9 100644
--- a/bitcoin/src/blockdata/transaction.rs
+++ b/bitcoin/src/blockdata/transaction.rs
@@ -10,12 +10,10 @@
//!
//! This module provides the structures and functions needed to support transactions.
-use core::fmt;
-
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
use encoding::CompactSizeEncoder;
-use internals::{const_casts, write_err, ToU64};
+use internals::{const_casts, ToU64};
use io::{BufRead, Write};
use super::Weight;
@@ -33,18 +31,21 @@ use crate::{internal_macros, Amount, FeeRate, Sequence, SignedAmount};
#[rustfmt::skip] // Keep public re-exports separate.
#[doc(no_inline)]
-pub use primitives::transaction::{
- BlockHashDecoderError, OutPointDecoderError, ParseTransactionError, ParseOutPointError,
- TransactionDecoderError, TxInDecoderError, TxOutDecoderError,
- VersionDecoderError,
-};
+pub use primitives::transaction::BlockHashDecoderError;
#[doc(inline)]
pub use primitives::transaction::{
- error, BlockHashDecoder, Ntxid, OutPoint, OutPointDecoder, OutPointEncoder, Transaction,
+ BlockHashDecoder, Ntxid, OutPoint, OutPointDecoder, OutPointEncoder, Transaction,
TransactionDecoder, TransactionEncoder, TxIn, TxInDecoder, TxInEncoder, TxOut, TxOutDecoder,
TxOutEncoder, Txid, Version, VersionDecoder, VersionEncoder, WitnessesEncoder, Wtxid,
};
+#[doc(no_inline)]
+pub use self::error::{
+ IndexOutOfBoundsError, InputsIndexError, OutPointDecoderError, OutputsIndexError,
+ ParseOutPointError, ParseTransactionError, TransactionDecoderError, TxInDecoderError,
+ TxOutDecoderError, VersionDecoderError,
+};
+
impl Encodable for Txid {
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
self.to_byte_array().consensus_encode(w)
@@ -610,65 +611,6 @@ impl TransactionExtPriv for Transaction {
}
}
-/// Error attempting to do an out of bounds access on the transaction inputs vector.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct InputsIndexError(pub IndexOutOfBoundsError);
-
-impl fmt::Display for InputsIndexError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write_err!(f, "invalid input index"; self.0)
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for InputsIndexError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
-}
-
-impl From<IndexOutOfBoundsError> for InputsIndexError {
- fn from(e: IndexOutOfBoundsError) -> Self { Self(e) }
-}
-
-/// Error attempting to do an out of bounds access on the transaction outputs vector.
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct OutputsIndexError(pub IndexOutOfBoundsError);
-
-impl fmt::Display for OutputsIndexError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write_err!(f, "invalid output index"; self.0)
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for OutputsIndexError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
-}
-
-impl From<IndexOutOfBoundsError> for OutputsIndexError {
- fn from(e: IndexOutOfBoundsError) -> Self { Self(e) }
-}
-
-/// Error attempting to do an out of bounds access on a vector.
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[non_exhaustive]
-pub struct IndexOutOfBoundsError {
- /// Attempted index access.
- pub index: usize,
- /// Length of the vector where access was attempted.
- pub length: usize,
-}
-
-impl fmt::Display for IndexOutOfBoundsError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "index {} is out-of-bounds for vector with length {}", self.index, self.length)
- }
-}
-
-#[cfg(feature = "std")]
-impl std::error::Error for IndexOutOfBoundsError {
- fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
-}
-
impl Encodable for Version {
fn consensus_encode<W: Write + ?Sized>(&self, w: &mut W) -> Result<usize, io::Error> {
self.to_u32().consensus_encode(w)
@@ -1255,6 +1197,83 @@ mod sealed {
impl Sealed for super::Version {}
}
+/// Error types for Bitcoin transactions.
+pub mod error {
+ use core::fmt;
+
+ use internals::write_err;
+
+ #[rustfmt::skip] // Keep public re-exports separate.
+ #[doc(no_inline)]
+ pub use primitives::transaction::error::{
+ ParseTransactionError, TransactionDecoderError, TxInDecoderError,
+ TxOutDecoderError, OutPointDecoderError, ParseOutPointError, VersionDecoderError,
+ };
+
+ /// Error attempting to do an out of bounds access on the transaction inputs vector.
+ #[derive(Debug, Clone, PartialEq, Eq)]
+ pub struct InputsIndexError(pub IndexOutOfBoundsError);
+
+ impl fmt::Display for InputsIndexError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "invalid input index"; self.0)
+ }
+ }
+
+ #[cfg(feature = "std")]
+ impl std::error::Error for InputsIndexError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+ }
+
+ impl From<IndexOutOfBoundsError> for InputsIndexError {
+ fn from(e: IndexOutOfBoundsError) -> Self { Self(e) }
+ }
+
+ /// Error attempting to do an out of bounds access on the transaction outputs vector.
+ #[derive(Debug, Clone, PartialEq, Eq)]
+ pub struct OutputsIndexError(pub IndexOutOfBoundsError);
+
+ impl fmt::Display for OutputsIndexError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write_err!(f, "invalid output index"; self.0)
+ }
+ }
+
+ #[cfg(feature = "std")]
+ impl std::error::Error for OutputsIndexError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(&self.0) }
+ }
+
+ impl From<IndexOutOfBoundsError> for OutputsIndexError {
+ fn from(e: IndexOutOfBoundsError) -> Self { Self(e) }
+ }
+
+ /// Error attempting to do an out of bounds access on a vector.
+ #[derive(Debug, Clone, PartialEq, Eq)]
+ #[non_exhaustive]
+ pub struct IndexOutOfBoundsError {
+ /// Attempted index access.
+ pub index: usize,
+ /// Length of the vector where access was attempted.
+ pub length: usize,
+ }
+
+ impl fmt::Display for IndexOutOfBoundsError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(
+ f,
+ "index {} is out-of-bounds for vector with length {}",
+ self.index, self.length
+ )
+ }
+ }
+
+ #[cfg(feature = "std")]
+ impl std::error::Error for IndexOutOfBoundsError {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None }
+ }
+}
+
#[cfg(feature = "arbitrary")]
impl<'a> Arbitrary<'a> for InputWeightPrediction {
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
Why this scored 19/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.