mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-25 12:57:58 +00:00
Migrate custom error trait impls to thiserror (#1856)
* Migrate to thiserror * missing bits * review comment * Apply suggestions from code review Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> * From<scale_decode::visitor::Error> to remove Into::intos * scale crates for core::error::Error * bump msrv 1.81 * make signer crate compile --------- Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> Co-authored-by: James Wilson <james.wilson@parity.io>
This commit is contained in:
+55
-154
@@ -4,61 +4,56 @@
|
||||
|
||||
//! The errors that can be emitted in this crate.
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use alloc::string::String;
|
||||
use subxt_metadata::StorageHasher;
|
||||
use thiserror::Error as DeriveError;
|
||||
|
||||
/// The error emitted when something goes wrong.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, DeriveError)]
|
||||
pub enum Error {
|
||||
/// Codec error.
|
||||
#[error("Codec error: {0}")]
|
||||
Codec(codec::Error),
|
||||
/// Metadata error.
|
||||
Metadata(MetadataError),
|
||||
#[error(transparent)]
|
||||
Metadata(#[from] MetadataError),
|
||||
/// Storage address error.
|
||||
StorageAddress(StorageAddressError),
|
||||
#[error(transparent)]
|
||||
StorageAddress(#[from] StorageAddressError),
|
||||
/// Error decoding to a [`crate::dynamic::Value`].
|
||||
Decode(scale_decode::Error),
|
||||
#[error("Error decoding into dynamic value: {0}")]
|
||||
Decode(#[from] scale_decode::Error),
|
||||
/// Error encoding from a [`crate::dynamic::Value`].
|
||||
Encode(scale_encode::Error),
|
||||
#[error("Error encoding from dynamic value: {0}")]
|
||||
Encode(#[from] scale_encode::Error),
|
||||
/// Error constructing the appropriate extrinsic params.
|
||||
ExtrinsicParams(ExtrinsicParamsError),
|
||||
#[error(transparent)]
|
||||
ExtrinsicParams(#[from] ExtrinsicParamsError),
|
||||
/// Block body error.
|
||||
Block(BlockError),
|
||||
#[error("Error working with block_body: {0}")]
|
||||
Block(#[from] BlockError),
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
Error::Codec(e) => write!(f, "Scale codec error: {e}"),
|
||||
Error::Metadata(e) => write!(f, "Metadata Error: {e}"),
|
||||
Error::StorageAddress(e) => write!(f, "Storage Error: {e}"),
|
||||
Error::Decode(e) => write!(f, "Error decoding into dynamic value: {e}"),
|
||||
Error::Encode(e) => write!(f, "Error encoding from dynamic value: {e}"),
|
||||
Error::ExtrinsicParams(e) => write!(f, "Extrinsic params error: {e}"),
|
||||
Error::Block(e) => write!(f, "Error working with block_body: {}", e),
|
||||
}
|
||||
impl From<scale_decode::visitor::DecodeError> for Error {
|
||||
fn from(err: scale_decode::visitor::DecodeError) -> Error {
|
||||
Error::Decode(err.into())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
impl_from!(ExtrinsicParamsError => Error::ExtrinsicParams);
|
||||
impl_from!(BlockError => Error::Block);
|
||||
impl_from!(MetadataError => Error::Metadata);
|
||||
impl_from!(scale_decode::Error => Error::Decode);
|
||||
impl_from!(scale_decode::visitor::DecodeError => Error::Decode);
|
||||
impl_from!(scale_encode::Error => Error::Encode);
|
||||
impl_from!(StorageAddressError => Error::StorageAddress);
|
||||
impl_from!(codec::Error => Error::Codec);
|
||||
// TODO: when `codec::Error` implements `core::Error`
|
||||
// remove this impl and replace it by thiserror #[from]
|
||||
impl From<codec::Error> for Error {
|
||||
fn from(err: codec::Error) -> Error {
|
||||
Error::Codec(err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Block error
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, DeriveError)]
|
||||
pub enum BlockError {
|
||||
/// Leftover bytes found after decoding the extrinsic.
|
||||
#[error("After decoding the extrinsic 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,
|
||||
@@ -66,6 +61,7 @@ pub enum BlockError {
|
||||
num_leftover_bytes: usize,
|
||||
},
|
||||
/// Something went wrong decoding the extrinsic.
|
||||
#[error("Failed to decode extrinsic at index {extrinsic_index}: {error}")]
|
||||
ExtrinsicDecodeError {
|
||||
/// Index of the extrinsic that failed to decode.
|
||||
extrinsic_index: usize,
|
||||
@@ -73,121 +69,74 @@ pub enum BlockError {
|
||||
error: ExtrinsicDecodeError,
|
||||
},
|
||||
}
|
||||
impl Display for BlockError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
BlockError::LeftoverBytes {
|
||||
extrinsic_index,
|
||||
num_leftover_bytes,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
"After decoding the extrinsic at index {extrinsic_index}, {num_leftover_bytes} bytes were left, suggesting that decoding may have failed"
|
||||
)
|
||||
}
|
||||
BlockError::ExtrinsicDecodeError {
|
||||
extrinsic_index,
|
||||
error,
|
||||
} => {
|
||||
write!(
|
||||
f,
|
||||
"Failed to decode extrinsic at index {extrinsic_index}: {error}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An alias for [`frame_decode::extrinsics::ExtrinsicDecodeError`].
|
||||
///
|
||||
pub type ExtrinsicDecodeError = frame_decode::extrinsics::ExtrinsicDecodeError;
|
||||
|
||||
/// Something went wrong trying to access details in the metadata.
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[derive(Clone, Debug, PartialEq, DeriveError)]
|
||||
#[non_exhaustive]
|
||||
pub enum MetadataError {
|
||||
/// The DispatchError type isn't available in the metadata
|
||||
#[error("The DispatchError type isn't available")]
|
||||
DispatchErrorNotFound,
|
||||
/// Type not found in metadata.
|
||||
#[error("Type with ID {0} not found")]
|
||||
TypeNotFound(u32),
|
||||
/// Pallet not found (index).
|
||||
#[error("Pallet with index {0} not found")]
|
||||
PalletIndexNotFound(u8),
|
||||
/// Pallet not found (name).
|
||||
#[error("Pallet with name {0} not found")]
|
||||
PalletNameNotFound(String),
|
||||
/// Variant not found.
|
||||
#[error("Variant with index {0} not found")]
|
||||
VariantIndexNotFound(u8),
|
||||
/// Constant not found.
|
||||
#[error("Constant with name {0} not found")]
|
||||
ConstantNameNotFound(String),
|
||||
/// Call not found.
|
||||
#[error("Call with name {0} not found")]
|
||||
CallNameNotFound(String),
|
||||
/// Runtime trait not found.
|
||||
#[error("Runtime trait with name {0} not found")]
|
||||
RuntimeTraitNotFound(String),
|
||||
/// Runtime method not found.
|
||||
#[error("Runtime method with name {0} not found")]
|
||||
RuntimeMethodNotFound(String),
|
||||
/// Call type not found in metadata.
|
||||
#[error("Call type not found in pallet with index {0}")]
|
||||
CallTypeNotFoundInPallet(u8),
|
||||
/// Event type not found in metadata.
|
||||
#[error("Event type not found in pallet with index {0}")]
|
||||
EventTypeNotFoundInPallet(u8),
|
||||
/// Storage details not found in metadata.
|
||||
#[error("Storage details not found in pallet with name {0}")]
|
||||
StorageNotFoundInPallet(String),
|
||||
/// Storage entry not found.
|
||||
#[error("Storage entry {0} not found")]
|
||||
StorageEntryNotFound(String),
|
||||
/// The generated interface used is not compatible with the node.
|
||||
#[error("The generated code is not compatible with the node")]
|
||||
IncompatibleCodegen,
|
||||
/// Custom value not found.
|
||||
#[error("Custom value with name {0} not found")]
|
||||
CustomValueNameNotFound(String),
|
||||
}
|
||||
impl Display for MetadataError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
MetadataError::DispatchErrorNotFound => {
|
||||
write!(f, "The DispatchError type isn't available")
|
||||
}
|
||||
MetadataError::TypeNotFound(e) => write!(f, "Type with ID {e} not found"),
|
||||
MetadataError::PalletIndexNotFound(e) => write!(f, "Pallet with index {e} not found"),
|
||||
MetadataError::PalletNameNotFound(e) => write!(f, "Pallet with name {e} not found"),
|
||||
MetadataError::VariantIndexNotFound(e) => write!(f, "Variant with index {e} not found"),
|
||||
MetadataError::ConstantNameNotFound(e) => write!(f, "Constant with name {e} not found"),
|
||||
MetadataError::CallNameNotFound(e) => write!(f, "Call with name {e} not found"),
|
||||
MetadataError::RuntimeTraitNotFound(e) => {
|
||||
write!(f, "Runtime trait with name {e} not found")
|
||||
}
|
||||
MetadataError::RuntimeMethodNotFound(e) => {
|
||||
write!(f, "Runtime method with name {e} not found")
|
||||
}
|
||||
MetadataError::CallTypeNotFoundInPallet(e) => {
|
||||
write!(f, "Call type not found in pallet with index {e}")
|
||||
}
|
||||
MetadataError::EventTypeNotFoundInPallet(e) => {
|
||||
write!(f, "Event type not found in pallet with index {e}")
|
||||
}
|
||||
MetadataError::StorageNotFoundInPallet(e) => {
|
||||
write!(f, "Storage details not found in pallet with name {e}")
|
||||
}
|
||||
MetadataError::StorageEntryNotFound(e) => write!(f, "Storage entry {e} not found"),
|
||||
MetadataError::IncompatibleCodegen => {
|
||||
write!(f, "The generated code is not compatible with the node")
|
||||
}
|
||||
MetadataError::CustomValueNameNotFound(e) => {
|
||||
write!(f, "Custom value with name {e} not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for MetadataError {}
|
||||
|
||||
/// Something went wrong trying to encode or decode a storage address.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, DeriveError)]
|
||||
#[non_exhaustive]
|
||||
pub enum StorageAddressError {
|
||||
/// Storage lookup does not have the expected number of keys.
|
||||
#[error("Storage lookup requires {expected} keys but more keys have been provided.")]
|
||||
TooManyKeys {
|
||||
/// The number of keys provided in the storage address.
|
||||
expected: usize,
|
||||
},
|
||||
/// This storage entry in the metadata does not have the correct number of hashers to fields.
|
||||
#[error("Storage entry in metadata does not have the correct number of hashers to fields")]
|
||||
WrongNumberOfHashers {
|
||||
/// The number of hashers in the metadata for this storage entry.
|
||||
hashers: usize,
|
||||
@@ -195,12 +144,16 @@ pub enum StorageAddressError {
|
||||
fields: usize,
|
||||
},
|
||||
/// We weren't given enough bytes to decode the storage address/key.
|
||||
#[error("Not enough remaining bytes to decode the storage address/key")]
|
||||
NotEnoughBytes,
|
||||
/// We have leftover bytes after decoding the storage address.
|
||||
#[error("We have leftover bytes after decoding the storage address")]
|
||||
TooManyBytes,
|
||||
/// The bytes of a storage address are not the expected address for decoding the storage keys of the address.
|
||||
#[error("Storage address bytes are not the expected format. Addresses need to be at least 16 bytes (pallet ++ entry) and follow a structure given by the hashers defined in the metadata")]
|
||||
UnexpectedAddressBytes,
|
||||
/// An invalid hasher was used to reconstruct a value from a chunk of bytes that is part of a storage address. Hashers where the hash does not contain the original value are invalid for this purpose.
|
||||
#[error("An invalid hasher was used to reconstruct a value with type ID {ty_id} from a hash formed by a {hasher:?} hasher. This is only possible for concat-style hashers or the identity hasher")]
|
||||
HasherCannotReconstructKey {
|
||||
/// Type id of the key's type.
|
||||
ty_id: u32,
|
||||
@@ -209,47 +162,14 @@ pub enum StorageAddressError {
|
||||
},
|
||||
}
|
||||
|
||||
impl Display for StorageAddressError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
StorageAddressError::TooManyKeys { expected } => write!(
|
||||
f,
|
||||
"Storage lookup requires {expected} keys but more keys have been provided."
|
||||
),
|
||||
StorageAddressError::WrongNumberOfHashers { .. } => write!(
|
||||
f,
|
||||
"Storage entry in metadata does not have the correct number of hashers to fields"
|
||||
),
|
||||
StorageAddressError::NotEnoughBytes => write!(
|
||||
f,
|
||||
"Not enough remaining bytes to decode the storage address/key"
|
||||
),
|
||||
StorageAddressError::TooManyBytes => write!(
|
||||
f,
|
||||
"We have leftover bytes after decoding the storage address"
|
||||
),
|
||||
StorageAddressError::UnexpectedAddressBytes => write!(
|
||||
f,
|
||||
"Storage address bytes are not the expected format. Addresses need to be at least 16 bytes (pallet ++ entry) and follow a structure given by the hashers defined in the metadata"
|
||||
),
|
||||
StorageAddressError::HasherCannotReconstructKey { ty_id, hasher } => write!(
|
||||
f,
|
||||
"An invalid hasher was used to reconstruct a value with type ID {ty_id} from a hash formed by a {hasher:?} hasher. This is only possible for concat-style hashers or the identity hasher"
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for StorageAddressError {}
|
||||
|
||||
/// An error that can be emitted when trying to construct an instance of [`crate::config::ExtrinsicParams`],
|
||||
/// encode data from the instance, or match on signed extensions.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, DeriveError)]
|
||||
#[non_exhaustive]
|
||||
pub enum ExtrinsicParamsError {
|
||||
/// Cannot find a type id in the metadata. The context provides some additional
|
||||
/// information about the source of the error (eg the signed extension name).
|
||||
#[error("Cannot find type id '{type_id} in the metadata (context: {context})")]
|
||||
MissingTypeId {
|
||||
/// Type ID.
|
||||
type_id: u32,
|
||||
@@ -257,29 +177,13 @@ pub enum ExtrinsicParamsError {
|
||||
context: &'static str,
|
||||
},
|
||||
/// A signed extension in use on some chain was not provided.
|
||||
#[error("The chain expects a signed extension with the name {0}, but we did not provide one")]
|
||||
UnknownSignedExtension(String),
|
||||
/// Some custom error.
|
||||
#[error("Error constructing extrinsic parameters: {0}")]
|
||||
Custom(Box<dyn CustomError>),
|
||||
}
|
||||
|
||||
impl Display for ExtrinsicParamsError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
ExtrinsicParamsError::MissingTypeId { type_id, context } => write!(
|
||||
f,
|
||||
"Cannot find type id '{type_id} in the metadata (context: {context})"
|
||||
),
|
||||
ExtrinsicParamsError::UnknownSignedExtension(e) => write!(
|
||||
f,
|
||||
"The chain expects a signed extension with the name {e}, but we did not provide one"
|
||||
),
|
||||
ExtrinsicParamsError::Custom(e) => {
|
||||
write!(f, "Error constructing extrinsic parameters: {e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Anything implementing this trait can be used in [`ExtrinsicParamsError::Custom`].
|
||||
#[cfg(feature = "std")]
|
||||
pub trait CustomError: std::error::Error + Send + Sync + 'static {}
|
||||
@@ -292,9 +196,6 @@ pub trait CustomError: core::fmt::Debug + core::fmt::Display + Send + Sync + 'st
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: core::fmt::Debug + core::fmt::Display + Send + Sync + 'static> CustomError for T {}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for ExtrinsicParamsError {}
|
||||
|
||||
impl From<core::convert::Infallible> for ExtrinsicParamsError {
|
||||
fn from(value: core::convert::Infallible) -> Self {
|
||||
match value {}
|
||||
|
||||
@@ -18,14 +18,4 @@ macro_rules! cfg_substrate_compat {
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_from {
|
||||
($module_path:path => $delegate_ty:ident :: $variant:ident) => {
|
||||
impl From<$module_path> for $delegate_ty {
|
||||
fn from(val: $module_path) -> Self {
|
||||
$delegate_ty::$variant(val.into())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use {cfg_feature, cfg_substrate_compat};
|
||||
|
||||
@@ -265,6 +265,7 @@ impl StorageKey for Vec<scale_value::Value> {
|
||||
Some(value_bytes) => {
|
||||
let value =
|
||||
scale_value::scale::decode_as_type(&mut &*value_bytes, ty_id, types)?;
|
||||
|
||||
result.push(value.remove_context());
|
||||
}
|
||||
None => {
|
||||
|
||||
@@ -6,14 +6,13 @@
|
||||
//! This doesn't contain much functionality itself, but is easy to convert to/from an `sp_core::AccountId32`
|
||||
//! for instance, to gain functionality without forcing a dependency on Substrate crates here.
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
use alloc::format;
|
||||
use alloc::string::String;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use codec::{Decode, Encode};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error as DeriveError;
|
||||
|
||||
/// A 32-byte cryptographic identifier. This is a simplified version of Substrate's
|
||||
/// `sp_core::crypto::AccountId32`. To obtain more functionality, convert this into
|
||||
@@ -106,29 +105,19 @@ impl AccountId32 {
|
||||
}
|
||||
|
||||
/// An error obtained from trying to interpret an SS58 encoded string into an AccountId32
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, DeriveError)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum FromSs58Error {
|
||||
#[error("Base 58 requirement is violated")]
|
||||
BadBase58,
|
||||
#[error("Length is bad")]
|
||||
BadLength,
|
||||
#[error("Invalid checksum")]
|
||||
InvalidChecksum,
|
||||
#[error("Invalid SS58 prefix byte.")]
|
||||
InvalidPrefix,
|
||||
}
|
||||
|
||||
impl Display for FromSs58Error {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
FromSs58Error::BadBase58 => write!(f, "Base 58 requirement is violated"),
|
||||
FromSs58Error::BadLength => write!(f, "Length is bad"),
|
||||
FromSs58Error::InvalidChecksum => write!(f, "Invalid checksum"),
|
||||
FromSs58Error::InvalidPrefix => write!(f, "Invalid SS58 prefix byte."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for FromSs58Error {}
|
||||
|
||||
// We do this just to get a checksum to help verify the validity of the address in to_ss58check
|
||||
fn ss58hash(data: &[u8]) -> Vec<u8> {
|
||||
use blake2::{Blake2b512, Digest};
|
||||
|
||||
@@ -4,13 +4,12 @@
|
||||
|
||||
//! `AccountId20` is a representation of Ethereum address derived from hashing the public key.
|
||||
|
||||
use core::fmt::Display;
|
||||
|
||||
use alloc::format;
|
||||
use alloc::string::String;
|
||||
use codec::{Decode, Encode};
|
||||
use keccak_hash::keccak;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error as DeriveError;
|
||||
|
||||
#[derive(
|
||||
Copy,
|
||||
@@ -72,27 +71,17 @@ impl AccountId20 {
|
||||
}
|
||||
|
||||
/// An error obtained from trying to interpret a hex encoded string into an AccountId20
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq, Debug, DeriveError)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum FromChecksumError {
|
||||
#[error("Length is bad")]
|
||||
BadLength,
|
||||
#[error("Invalid checksum")]
|
||||
InvalidChecksum,
|
||||
#[error("Invalid checksum prefix byte.")]
|
||||
InvalidPrefix,
|
||||
}
|
||||
|
||||
impl Display for FromChecksumError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
FromChecksumError::BadLength => write!(f, "Length is bad"),
|
||||
FromChecksumError::InvalidChecksum => write!(f, "Invalid checksum"),
|
||||
FromChecksumError::InvalidPrefix => write!(f, "Invalid checksum prefix byte."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for FromChecksumError {}
|
||||
|
||||
impl Serialize for AccountId20 {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
|
||||
Reference in New Issue
Block a user