Skip to content

Commit

Permalink
Make it clearer which extrinsic failed to decode (#1835)
Browse files Browse the repository at this point in the history
* Add an extrinsic index to decode errors so that we know which extrinsic failed

* Fix subxt::BlockError to align with subxt_core::BlockError

---------

Co-authored-by: Niklas Adolfsson <[email protected]>
  • Loading branch information
jsdw and niklasad1 authored Oct 23, 2024
1 parent 2f7ea3f commit 15cf58f
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 19 deletions.
26 changes: 19 additions & 7 deletions core/src/blocks/extrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ impl<T: Config> Extrinsics<T> {
pub fn decode_from(extrinsics: Vec<Vec<u8>>, metadata: Metadata) -> Result<Self, Error> {
let extrinsics = extrinsics
.into_iter()
.map(|bytes| {
.enumerate()
.map(|(extrinsic_index, bytes)| {
let cursor = &mut &*bytes;

// Try to decode the extrinsic.
Expand All @@ -41,12 +42,19 @@ impl<T: Config> Extrinsics<T> {
metadata.deref(),
metadata.types(),
)
.map_err(BlockError::ExtrinsicDecodeError)?
.map_err(|error| BlockError::ExtrinsicDecodeError {
extrinsic_index,
error,
})?
.into_owned();

// We didn't consume all bytes, so decoding probably failed.
if !cursor.is_empty() {
return Err(BlockError::LeftoverBytes(cursor.len()).into());
return Err(BlockError::LeftoverBytes {
extrinsic_index,
num_leftover_bytes: cursor.len(),
}
.into());
}

Ok(Arc::new((decoded_info, bytes)))
Expand Down Expand Up @@ -493,7 +501,10 @@ mod tests {
assert_matches!(
result.err(),
Some(crate::Error::Block(
crate::error::BlockError::ExtrinsicDecodeError(_)
crate::error::BlockError::ExtrinsicDecodeError {
extrinsic_index: 0,
error: _
}
))
);
}
Expand All @@ -510,9 +521,10 @@ mod tests {
assert_matches!(
result.err(),
Some(crate::Error::Block(
crate::error::BlockError::ExtrinsicDecodeError(
ExtrinsicDecodeError::VersionNotSupported(3)
)
crate::error::BlockError::ExtrinsicDecodeError {
extrinsic_index: 0,
error: ExtrinsicDecodeError::VersionNotSupported(3),
}
))
);
}
Expand Down
31 changes: 25 additions & 6 deletions core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,40 @@ impl_from!(codec::Error => Error::Codec);
#[derive(Debug)]
pub enum BlockError {
/// Leftover bytes found after decoding the extrinsic.
LeftoverBytes(usize),
LeftoverBytes {
/// Index of the extrinsic that failed to decode.
extrinsic_index: usize,
/// Number of bytes leftover after decoding the extrinsic.
num_leftover_bytes: usize,
},
/// Something went wrong decoding the extrinsic.
ExtrinsicDecodeError(ExtrinsicDecodeError),
ExtrinsicDecodeError {
/// Index of the extrinsic that failed to decode.
extrinsic_index: usize,
/// The decode error.
error: ExtrinsicDecodeError,
},
}
impl Display for BlockError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
BlockError::LeftoverBytes(n) => {
BlockError::LeftoverBytes {
extrinsic_index,
num_leftover_bytes,
} => {
write!(
f,
"After decoding, {n} bytes were left, suggesting that decoding may have failed"
"After decoding the extrinsic at index {extrinsic_index}, {num_leftover_bytes} bytes were left, suggesting that decoding may have failed"
)
}
BlockError::ExtrinsicDecodeError(e) => {
write!(f, "{e}")
BlockError::ExtrinsicDecodeError {
extrinsic_index,
error,
} => {
write!(
f,
"Failed to decode extrinsic at index {extrinsic_index}: {error}"
)
}
}
}
Expand Down
34 changes: 28 additions & 6 deletions subxt/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,18 +172,40 @@ pub enum BlockError {
#[error("Could not find a block with hash {0} (perhaps it was on a non-finalized fork?)")]
NotFound(String),
/// Leftover bytes found after decoding the extrinsic.
#[error("After decoding, {0} bytes were left, suggesting that decoding may have failed")]
LeftoverBytes(usize),
#[error("After decoding the exntrinsic at index {extrinsic_index}, {num_leftover_bytes} bytes were left, suggesting that decoding may have failed")]
LeftoverBytes {
/// Index of the extrinsic that failed to decode.
extrinsic_index: usize,
/// Number of bytes leftover after decoding the extrinsic.
num_leftover_bytes: usize,
},
/// Decoding error.
#[error("Cannot decode extrinsic: {0}")]
ExtrinsicDecodeError(subxt_core::error::ExtrinsicDecodeError),
#[error("Cannot decode extrinsic at index {extrinsic_index}: {error}")]
ExtrinsicDecodeError {
/// Index of the extrinsic that failed to decode.
extrinsic_index: usize,
/// The decode error.
error: subxt_core::error::ExtrinsicDecodeError,
},
}

impl From<CoreBlockError> for BlockError {
fn from(value: CoreBlockError) -> Self {
match value {
CoreBlockError::LeftoverBytes(n) => BlockError::LeftoverBytes(n),
CoreBlockError::ExtrinsicDecodeError(e) => BlockError::ExtrinsicDecodeError(e),
CoreBlockError::LeftoverBytes {
extrinsic_index,
num_leftover_bytes,
} => BlockError::LeftoverBytes {
extrinsic_index,
num_leftover_bytes,
},
CoreBlockError::ExtrinsicDecodeError {
extrinsic_index,
error,
} => BlockError::ExtrinsicDecodeError {
extrinsic_index,
error,
},
}
}
}
Expand Down

0 comments on commit 15cf58f

Please sign in to comment.