Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it clearer which extrinsic failed to decode #1835

Merged
merged 4 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading