Make it clearer which extrinsic failed to decode (#1835)

* 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 <niklasadolfsson1@gmail.com>
This commit is contained in:
James Wilson
2024-10-23 17:03:32 +01:00
committed by GitHub
parent 2f7ea3ff64
commit 15cf58f723
3 changed files with 72 additions and 19 deletions
+19 -7
View File
@@ -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.
@@ -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)))
@@ -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: _
}
))
);
}
@@ -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),
}
))
);
}
+25 -6
View File
@@ -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}"
)
}
}
}