use snafu in core

This commit is contained in:
Pavlo Khrystenko
2024-05-22 18:11:39 +02:00
parent e99d7faf00
commit 63e7fd467f
19 changed files with 268 additions and 121 deletions
+1 -1
View File
@@ -45,7 +45,7 @@ scale-encode = { workspace = true, default-features = false, features = ["derive
frame-metadata = { workspace = true, default-features = false } frame-metadata = { workspace = true, default-features = false }
subxt-metadata = { workspace = true, default-features = false } subxt-metadata = { workspace = true, default-features = false }
derive-where = { workspace = true } derive-where = { workspace = true }
derive_more = { workspace = true } snafu = { workspace = true }
hex = { workspace = true, default-features = false, features = ["alloc"] } hex = { workspace = true, default-features = false, features = ["alloc"] }
serde = { workspace = true, default-features = false, features = ["derive"] } serde = { workspace = true, default-features = false, features = ["derive"] }
serde_json = { workspace = true, default-features = false, features = ["raw_value", "alloc"] } serde_json = { workspace = true, default-features = false, features = ["raw_value", "alloc"] }
@@ -51,8 +51,9 @@ impl<'a, T: Config> ExtrinsicSignedExtensions<'a, T> {
metadata.types(), metadata.types(),
scale_decode::visitor::IgnoreVisitor::new(), scale_decode::visitor::IgnoreVisitor::new(),
) )
.map_err(|e| Error::Decode(e.into())) .map_err(|e| Error::Decode {
{ source: crate::error_utils::DisplayError(e.into()),
}) {
index = num_signed_extensions; // (such that None is returned in next iteration) index = num_signed_extensions; // (such that None is returned in next iteration)
return Some(Err(err)); return Some(Err(err));
} }
+8 -6
View File
@@ -180,7 +180,7 @@ where
let version = first_byte & VERSION_MASK; let version = first_byte & VERSION_MASK;
if version != LATEST_EXTRINSIC_VERSION { if version != LATEST_EXTRINSIC_VERSION {
return Err(BlockError::UnsupportedVersion(version).into()); return Err(BlockError::UnsupportedVersion { version }.into());
} }
let is_signed = first_byte & SIGNATURE_MASK != 0; let is_signed = first_byte & SIGNATURE_MASK != 0;
@@ -355,7 +355,9 @@ where
let pallet = self.metadata.pallet_by_index_err(self.pallet_index())?; let pallet = self.metadata.pallet_by_index_err(self.pallet_index())?;
let variant = pallet let variant = pallet
.call_variant_by_index(self.variant_index()) .call_variant_by_index(self.variant_index())
.ok_or_else(|| MetadataError::VariantIndexNotFound(self.variant_index()))?; .ok_or_else(|| MetadataError::VariantIndexNotFound {
variant_idx: self.variant_index(),
})?;
Ok(ExtrinsicMetadataDetails { pallet, variant }) Ok(ExtrinsicMetadataDetails { pallet, variant })
} }
@@ -610,7 +612,7 @@ mod tests {
// Decode with empty bytes. // Decode with empty bytes.
let result = ExtrinsicDetails::<SubstrateConfig>::decode_from(0, &[], metadata, ids); let result = ExtrinsicDetails::<SubstrateConfig>::decode_from(0, &[], metadata, ids);
assert_matches!(result.err(), Some(crate::Error::Codec(_))); assert_matches!(result.err(), Some(crate::Error::Codec { source: _ }));
} }
#[test] #[test]
@@ -624,9 +626,9 @@ mod tests {
assert_matches!( assert_matches!(
result.err(), result.err(),
Some(crate::Error::Block( Some(crate::Error::Block {
crate::error::BlockError::UnsupportedVersion(3) source: crate::error::BlockError::UnsupportedVersion { version: 3 }
)) })
); );
} }
+3 -1
View File
@@ -429,7 +429,9 @@ macro_rules! impl_tuples {
if is_type_empty(e.extra_ty(), types) { if is_type_empty(e.extra_ty(), types) {
continue continue
} else { } else {
return Err(ExtrinsicParamsError::UnknownSignedExtension(e.identifier().to_owned())); return Err(ExtrinsicParamsError::UnknownSignedExtension {
extension: e.identifier().to_owned()
});
} }
}; };
params.push(ext); params.push(ext);
+5 -3
View File
@@ -55,8 +55,8 @@ pub fn validate<Addr: Address>(address: &Addr, metadata: &Metadata) -> Result<()
let expected_hash = metadata let expected_hash = metadata
.pallet_by_name_err(address.pallet_name())? .pallet_by_name_err(address.pallet_name())?
.constant_hash(address.constant_name()) .constant_hash(address.constant_name())
.ok_or_else(|| { .ok_or_else(|| MetadataError::ConstantNameNotFound {
MetadataError::ConstantNameNotFound(address.constant_name().to_owned()) name: address.constant_name().to_owned(),
})?; })?;
if actual_hash != expected_hash { if actual_hash != expected_hash {
return Err(MetadataError::IncompatibleCodegen.into()); return Err(MetadataError::IncompatibleCodegen.into());
@@ -75,7 +75,9 @@ pub fn get<Addr: Address>(address: &Addr, metadata: &Metadata) -> Result<Addr::T
let constant = metadata let constant = metadata
.pallet_by_name_err(address.pallet_name())? .pallet_by_name_err(address.pallet_name())?
.constant_by_name(address.constant_name()) .constant_by_name(address.constant_name())
.ok_or_else(|| MetadataError::ConstantNameNotFound(address.constant_name().to_owned()))?; .ok_or_else(|| MetadataError::ConstantNameNotFound {
name: address.constant_name().to_owned(),
})?;
let value = <Addr::Target as DecodeWithMetadata>::decode_with_metadata( let value = <Addr::Target as DecodeWithMetadata>::decode_with_metadata(
&mut constant.value(), &mut constant.value(),
constant.ty(), constant.ty(),
+6 -3
View File
@@ -43,9 +43,12 @@ use alloc::vec::Vec;
pub fn validate<Addr: Address + ?Sized>(address: &Addr, metadata: &Metadata) -> Result<(), Error> { pub fn validate<Addr: Address + ?Sized>(address: &Addr, metadata: &Metadata) -> Result<(), Error> {
if let Some(actual_hash) = address.validation_hash() { if let Some(actual_hash) = address.validation_hash() {
let custom = metadata.custom(); let custom = metadata.custom();
let custom_value = custom let custom_value =
.get(address.name()) custom
.ok_or_else(|| MetadataError::CustomValueNameNotFound(address.name().into()))?; .get(address.name())
.ok_or_else(|| MetadataError::CustomValueNameNotFound {
name: address.name().into(),
})?;
let expected_hash = custom_value.hash(); let expected_hash = custom_value.hash();
if actual_hash != expected_hash { if actual_hash != expected_hash {
return Err(MetadataError::IncompatibleCodegen.into()); return Err(MetadataError::IncompatibleCodegen.into());
+159 -76
View File
@@ -6,33 +6,59 @@
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::string::String; use alloc::string::String;
use derive_more::{Display, From}; use snafu::Snafu;
use subxt_metadata::StorageHasher; use subxt_metadata::StorageHasher;
use crate::error_utils::DisplayError;
/// The error emitted when something goes wrong. /// The error emitted when something goes wrong.
#[derive(Debug, Display, From)] #[derive(Debug, Snafu)]
pub enum Error { pub enum Error {
/// Codec error. /// Codec error.
#[display(fmt = "Scale codec error: {_0}")] #[snafu(display("Scale codec error: {source}"), context(false))]
Codec(codec::Error), Codec {
/// Error source
#[snafu(source(from(codec::Error, DisplayError)))]
source: DisplayError<codec::Error>,
},
/// Metadata error. /// Metadata error.
#[display(fmt = "Metadata Error: {_0}")] #[snafu(display("Metadata Error: {source}"), context(false))]
Metadata(MetadataError), Metadata {
/// Error source
source: MetadataError,
},
/// Storage address error. /// Storage address error.
#[display(fmt = "Storage Error: {_0}")] #[snafu(display("Storage Error: {source}"), context(false))]
StorageAddress(StorageAddressError), StorageAddress {
/// Error source
source: StorageAddressError,
},
/// Error decoding to a [`crate::dynamic::Value`]. /// Error decoding to a [`crate::dynamic::Value`].
#[display(fmt = "Error decoding into dynamic value: {_0}")] #[snafu(display("Error decoding into dynamic value: {source}"), context(false))]
Decode(scale_decode::Error), Decode {
/// Error source
#[snafu(source(from(scale_decode::Error, DisplayError)))]
source: DisplayError<scale_decode::Error>,
},
/// Error encoding from a [`crate::dynamic::Value`]. /// Error encoding from a [`crate::dynamic::Value`].
#[display(fmt = "Error encoding from dynamic value: {_0}")] #[snafu(display("Error encoding from dynamic value: {source}"), context(false))]
Encode(scale_encode::Error), Encode {
/// Error source
#[snafu(source(from(scale_encode::Error, DisplayError)))]
source: DisplayError<scale_encode::Error>,
},
/// Error constructing the appropriate extrinsic params. /// Error constructing the appropriate extrinsic params.
#[display(fmt = "Extrinsic params error: {_0}")] #[snafu(display("Extrinsic params error: {source}"), context(false))]
ExtrinsicParams(ExtrinsicParamsError), ExtrinsicParams {
/// Error source
source: ExtrinsicParamsError,
},
/// Block body error. /// Block body error.
#[display(fmt = "Error working with block body: {_0}")] #[snafu(display("Error working with block body: {source}"), context(false))]
Block(BlockError), Block {
/// Error source
source: BlockError,
},
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
@@ -40,98 +66,146 @@ impl std::error::Error for Error {}
impl From<scale_decode::visitor::DecodeError> for Error { impl From<scale_decode::visitor::DecodeError> for Error {
fn from(value: scale_decode::visitor::DecodeError) -> Self { fn from(value: scale_decode::visitor::DecodeError) -> Self {
Error::Decode(value.into()) Error::Decode {
source: DisplayError(value.into()),
}
} }
} }
/// Block error /// Block error
#[derive(Clone, Debug, Display, Eq, PartialEq)] #[derive(Clone, Debug, Snafu, Eq, PartialEq)]
pub enum BlockError { pub enum BlockError {
/// Extrinsic type ID cannot be resolved with the provided metadata. /// Extrinsic type ID cannot be resolved with the provided metadata.
#[display( #[snafu(display(
fmt = "Extrinsic type ID cannot be resolved with the provided metadata. Make sure this is a valid metadata" "Extrinsic type ID cannot be resolved with the provided metadata. Make sure this is a valid metadata"
)] ))]
MissingType, MissingType,
/// Unsupported signature. /// Unsupported signature.
#[display(fmt = "Unsupported extrinsic version, only version 4 is supported currently")] #[snafu(display("Unsupported extrinsic version, only version 4 is supported currently"))]
/// The extrinsic has an unsupported version. /// The extrinsic has an unsupported version.
UnsupportedVersion(u8), UnsupportedVersion {
/// Version of the extrinsic
version: u8,
},
/// Decoding error. /// Decoding error.
#[display(fmt = "Cannot decode extrinsic: {_0}")] #[snafu(display("Cannot decode extrinsic: {source}"), context(false))]
DecodingError(codec::Error), DecodingError {
/// Decoding error source
#[snafu(source(from(codec::Error, DisplayError)))]
source: DisplayError<codec::Error>,
},
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl std::error::Error for BlockError {} impl std::error::Error for BlockError {}
/// Something went wrong trying to access details in the metadata. /// Something went wrong trying to access details in the metadata.
#[derive(Clone, Debug, PartialEq, Display)] #[derive(Clone, Debug, PartialEq, Snafu)]
#[non_exhaustive] #[non_exhaustive]
pub enum MetadataError { pub enum MetadataError {
/// The DispatchError type isn't available in the metadata /// The DispatchError type isn't available in the metadata
#[display(fmt = "The DispatchError type isn't available")] #[snafu(display("The DispatchError type isn't available"))]
DispatchErrorNotFound, DispatchErrorNotFound,
/// Type not found in metadata. /// Type not found in metadata.
#[display(fmt = "Type with ID {_0} not found")] #[snafu(display("Type with ID {type_id} not found"))]
TypeNotFound(u32), TypeNotFound {
/// Type id
type_id: u32,
},
/// Pallet not found (index). /// Pallet not found (index).
#[display(fmt = "Pallet with index {_0} not found")] #[snafu(display("Pallet with index {pallet_idx} not found"))]
PalletIndexNotFound(u8), PalletIndexNotFound {
/// Pallet index
pallet_idx: u8,
},
/// Pallet not found (name). /// Pallet not found (name).
#[display(fmt = "Pallet with name {_0} not found")] #[snafu(display("Pallet with name {name} not found"))]
PalletNameNotFound(String), PalletNameNotFound {
/// Pallet name
name: String,
},
/// Variant not found. /// Variant not found.
#[display(fmt = "Variant with index {_0} not found")] #[snafu(display("Variant with index {variant_idx} not found"))]
VariantIndexNotFound(u8), VariantIndexNotFound {
/// index of the variant being searched
variant_idx: u8,
},
/// Constant not found. /// Constant not found.
#[display(fmt = "Constant with name {_0} not found")] #[snafu(display("Constant with name {name} not found"))]
ConstantNameNotFound(String), ConstantNameNotFound {
/// Name of the constant
name: String,
},
/// Call not found. /// Call not found.
#[display(fmt = "Call with name {_0} not found")] #[snafu(display("Call with name {name} not found"))]
CallNameNotFound(String), CallNameNotFound {
/// Name of the call
name: String,
},
/// Runtime trait not found. /// Runtime trait not found.
#[display(fmt = "Runtime trait with name {_0} not found")] #[snafu(display("Runtime trait with name {name} not found"))]
RuntimeTraitNotFound(String), RuntimeTraitNotFound {
/// Name of the trait being searched
name: String,
},
/// Runtime method not found. /// Runtime method not found.
#[display(fmt = "Runtime method with name {_0} not found")] #[snafu(display("Runtime method with name {name} not found"))]
RuntimeMethodNotFound(String), RuntimeMethodNotFound {
/// Name of the method being searched
name: String,
},
/// Call type not found in metadata. /// Call type not found in metadata.
#[display(fmt = "Call type not found in pallet with index {_0}")] #[snafu(display("Call type not found in pallet with index {type_id}"))]
CallTypeNotFoundInPallet(u8), CallTypeNotFoundInPallet {
/// Type id of the call
type_id: u8,
},
/// Event type not found in metadata. /// Event type not found in metadata.
#[display(fmt = "Event type not found in pallet with index {_0}")] #[snafu(display("Event type not found in pallet with index {type_id}"))]
EventTypeNotFoundInPallet(u8), EventTypeNotFoundInPallet {
/// Type id
type_id: u8,
},
/// Storage details not found in metadata. /// Storage details not found in metadata.
#[display(fmt = "Storage details not found in pallet with name {_0}")] #[snafu(display("Storage details not found in pallet with name {name}"))]
StorageNotFoundInPallet(String), StorageNotFoundInPallet {
/// Pallet name
name: String,
},
/// Storage entry not found. /// Storage entry not found.
#[display(fmt = "Storage entry {_0} not found")] #[snafu(display("Storage entry {entry_name} not found"))]
StorageEntryNotFound(String), StorageEntryNotFound {
/// Name of the storage entry
entry_name: String,
},
/// The generated interface used is not compatible with the node. /// The generated interface used is not compatible with the node.
#[display(fmt = "The generated code is not compatible with the node")] #[snafu(display("The generated code is not compatible with the node"))]
IncompatibleCodegen, IncompatibleCodegen,
/// Custom value not found. /// Custom value not found.
#[display(fmt = "Custom value with name {_0} not found")] #[snafu(display("Custom value with name {name} not found"))]
CustomValueNameNotFound(String), CustomValueNameNotFound {
/// Custom name of the value
name: String,
},
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl std::error::Error for MetadataError {} impl std::error::Error for MetadataError {}
/// Something went wrong trying to encode or decode a storage address. /// Something went wrong trying to encode or decode a storage address.
#[derive(Clone, Debug, Display)] #[derive(Clone, Debug, Snafu)]
#[non_exhaustive] #[non_exhaustive]
pub enum StorageAddressError { pub enum StorageAddressError {
/// Storage lookup does not have the expected number of keys. /// Storage lookup does not have the expected number of keys.
#[display(fmt = "Storage lookup requires {expected} keys but more keys have been provided.")] #[snafu(display("Storage lookup requires {expected} keys but more keys have been provided."))]
TooManyKeys { TooManyKeys {
/// The number of keys provided in the storage address. /// The number of keys provided in the storage address.
expected: usize, expected: usize,
}, },
/// This storage entry in the metadata does not have the correct number of hashers to fields. /// This storage entry in the metadata does not have the correct number of hashers to fields.
#[display( #[snafu(display(
fmt = "Storage entry in metadata does not have the correct number of hashers to fields" "Storage entry in metadata does not have the correct number of hashers to fields"
)] ))]
WrongNumberOfHashers { WrongNumberOfHashers {
/// The number of hashers in the metadata for this storage entry. /// The number of hashers in the metadata for this storage entry.
hashers: usize, hashers: usize,
@@ -139,20 +213,20 @@ pub enum StorageAddressError {
fields: usize, fields: usize,
}, },
/// We weren't given enough bytes to decode the storage address/key. /// We weren't given enough bytes to decode the storage address/key.
#[display(fmt = "Not enough remaining bytes to decode the storage address/key")] #[snafu(display("Not enough remaining bytes to decode the storage address/key"))]
NotEnoughBytes, NotEnoughBytes,
/// We have leftover bytes after decoding the storage address. /// We have leftover bytes after decoding the storage address.
#[display(fmt = "We have leftover bytes after decoding the storage address")] #[snafu(display("We have leftover bytes after decoding the storage address"))]
TooManyBytes, TooManyBytes,
/// The bytes of a storage address are not the expected address for decoding the storage keys of the address. /// The bytes of a storage address are not the expected address for decoding the storage keys of the address.
#[display( #[snafu(display(
fmt = "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" "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, 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. /// 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.
#[display( #[snafu(display(
fmt = "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" "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 { HasherCannotReconstructKey {
/// Type id of the key's type. /// Type id of the key's type.
ty_id: u32, ty_id: u32,
@@ -166,12 +240,12 @@ impl std::error::Error for StorageAddressError {}
/// An error that can be emitted when trying to construct an instance of [`crate::config::ExtrinsicParams`], /// 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. /// encode data from the instance, or match on signed extensions.
#[derive(Display, Debug)] #[derive(Snafu, Debug)]
#[non_exhaustive] #[non_exhaustive]
pub enum ExtrinsicParamsError { pub enum ExtrinsicParamsError {
/// Cannot find a type id in the metadata. The context provides some additional /// 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). /// information about the source of the error (eg the signed extension name).
#[display(fmt = "Cannot find type id '{type_id} in the metadata (context: {context})")] #[snafu(display("Cannot find type id '{type_id} in the metadata (context: {context})"))]
MissingTypeId { MissingTypeId {
/// Type ID. /// Type ID.
type_id: u32, type_id: u32,
@@ -179,13 +253,20 @@ pub enum ExtrinsicParamsError {
context: &'static str, context: &'static str,
}, },
/// A signed extension in use on some chain was not provided. /// A signed extension in use on some chain was not provided.
#[display( #[snafu(display(
fmt = "The chain expects a signed extension with the name {_0}, but we did not provide one" "The chain expects a signed extension with the name {extension}, but we did not provide one"
)] ))]
UnknownSignedExtension(String), UnknownSignedExtension {
/// Extension name
extension: String,
},
/// Some custom error. /// Some custom error.
#[display(fmt = "Error constructing extrinsic parameters: {_0}")] #[snafu(display("Error constructing extrinsic parameters: {source}"))]
Custom(Box<dyn CustomError>), Custom {
/// Error source
#[snafu(source(from(Box<dyn CustomError>, DisplayError)))]
source: DisplayError<Box<dyn CustomError>>,
},
} }
/// Anything implementing this trait can be used in [`ExtrinsicParamsError::Custom`]. /// Anything implementing this trait can be used in [`ExtrinsicParamsError::Custom`].
@@ -211,6 +292,8 @@ impl From<core::convert::Infallible> for ExtrinsicParamsError {
impl From<Box<dyn CustomError>> for ExtrinsicParamsError { impl From<Box<dyn CustomError>> for ExtrinsicParamsError {
fn from(value: Box<dyn CustomError>) -> Self { fn from(value: Box<dyn CustomError>) -> Self {
ExtrinsicParamsError::Custom(value) ExtrinsicParamsError::Custom {
source: DisplayError(value),
}
} }
} }
+24
View File
@@ -0,0 +1,24 @@
use core::fmt::{self, Debug, Display};
#[derive(Clone, PartialEq, Eq)]
pub struct DisplayError<T>(pub T);
impl<T> Debug for DisplayError<T>
where
T: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T> Display for DisplayError<T>
where
T: Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl<T> snafu::Error for DisplayError<T> where T: Display + Debug {}
+5 -3
View File
@@ -258,9 +258,11 @@ impl<T: Config> EventDetails<T> {
// Get metadata for the event: // Get metadata for the event:
let event_pallet = metadata.pallet_by_index_err(pallet_index)?; let event_pallet = metadata.pallet_by_index_err(pallet_index)?;
let event_variant = event_pallet let event_variant = event_pallet.event_variant_by_index(variant_index).ok_or(
.event_variant_by_index(variant_index) MetadataError::VariantIndexNotFound {
.ok_or(MetadataError::VariantIndexNotFound(variant_index))?; variant_idx: variant_index,
},
)?;
tracing::debug!( tracing::debug!(
"Decoding Event '{}::{}'", "Decoding Event '{}::{}'",
event_pallet.name(), event_pallet.name(),
+2
View File
@@ -23,6 +23,8 @@
#![cfg_attr(not(feature = "std"), no_std)] #![cfg_attr(not(feature = "std"), no_std)]
pub extern crate alloc; pub extern crate alloc;
mod error_utils;
#[macro_use] #[macro_use]
mod macros; mod macros;
+10 -4
View File
@@ -27,7 +27,9 @@ impl Metadata {
name: &str, name: &str,
) -> Result<subxt_metadata::PalletMetadata, MetadataError> { ) -> Result<subxt_metadata::PalletMetadata, MetadataError> {
self.pallet_by_name(name) self.pallet_by_name(name)
.ok_or_else(|| MetadataError::PalletNameNotFound(name.to_owned())) .ok_or_else(|| MetadataError::PalletNameNotFound {
name: name.to_owned(),
})
} }
/// Identical to `metadata.pallet_by_index()`, but returns an error if the pallet is not found. /// Identical to `metadata.pallet_by_index()`, but returns an error if the pallet is not found.
@@ -36,7 +38,7 @@ impl Metadata {
index: u8, index: u8,
) -> Result<subxt_metadata::PalletMetadata, MetadataError> { ) -> Result<subxt_metadata::PalletMetadata, MetadataError> {
self.pallet_by_index(index) self.pallet_by_index(index)
.ok_or(MetadataError::PalletIndexNotFound(index)) .ok_or(MetadataError::PalletIndexNotFound { pallet_idx: index })
} }
/// Identical to `metadata.runtime_api_trait_by_name()`, but returns an error if the trait is not found. /// Identical to `metadata.runtime_api_trait_by_name()`, but returns an error if the trait is not found.
@@ -45,7 +47,9 @@ impl Metadata {
name: &str, name: &str,
) -> Result<subxt_metadata::RuntimeApiMetadata, MetadataError> { ) -> Result<subxt_metadata::RuntimeApiMetadata, MetadataError> {
self.runtime_api_trait_by_name(name) self.runtime_api_trait_by_name(name)
.ok_or_else(|| MetadataError::RuntimeTraitNotFound(name.to_owned())) .ok_or_else(|| MetadataError::RuntimeTraitNotFound {
name: name.to_owned(),
})
} }
/// Identical to `metadata.custom().get(name)`, but returns an error if the trait is not found. /// Identical to `metadata.custom().get(name)`, but returns an error if the trait is not found.
@@ -55,7 +59,9 @@ impl Metadata {
) -> Result<subxt_metadata::CustomValueMetadata, MetadataError> { ) -> Result<subxt_metadata::CustomValueMetadata, MetadataError> {
self.custom() self.custom()
.get(name) .get(name)
.ok_or_else(|| MetadataError::CustomValueNameNotFound(name.to_owned())) .ok_or_else(|| MetadataError::CustomValueNameNotFound {
name: name.to_owned(),
})
} }
} }
+3 -1
View File
@@ -90,7 +90,9 @@ pub fn decode_value<P: Payload>(
let api_method = metadata let api_method = metadata
.runtime_api_trait_by_name_err(payload.trait_name())? .runtime_api_trait_by_name_err(payload.trait_name())?
.method_by_name(payload.method_name()) .method_by_name(payload.method_name())
.ok_or_else(|| MetadataError::RuntimeMethodNotFound(payload.method_name().to_owned()))?; .ok_or_else(|| MetadataError::RuntimeMethodNotFound {
name: payload.method_name().to_owned(),
})?;
let val = <P::ReturnType as DecodeWithMetadata>::decode_with_metadata( let val = <P::ReturnType as DecodeWithMetadata>::decode_with_metadata(
&mut &bytes[..], &mut &bytes[..],
+3 -1
View File
@@ -105,7 +105,9 @@ impl<ArgsData: EncodeAsFields, ReturnTy: DecodeWithMetadata> Payload
let api_method = metadata let api_method = metadata
.runtime_api_trait_by_name_err(&self.trait_name)? .runtime_api_trait_by_name_err(&self.trait_name)?
.method_by_name(&self.method_name) .method_by_name(&self.method_name)
.ok_or_else(|| MetadataError::RuntimeMethodNotFound((*self.method_name).to_owned()))?; .ok_or_else(|| MetadataError::RuntimeMethodNotFound {
name: (*self.method_name).to_owned(),
})?;
let mut fields = api_method let mut fields = api_method
.inputs() .inputs()
.map(|input| scale_encode::Field::named(input.ty, &input.name)); .map(|input| scale_encode::Field::named(input.ty, &input.name));
+8 -4
View File
@@ -154,10 +154,14 @@ where
let pallet = metadata.pallet_by_name_err(self.pallet_name())?; let pallet = metadata.pallet_by_name_err(self.pallet_name())?;
let storage = pallet let storage = pallet
.storage() .storage()
.ok_or_else(|| MetadataError::StorageNotFoundInPallet(self.pallet_name().to_owned()))?; .ok_or_else(|| MetadataError::StorageNotFoundInPallet {
let entry = storage name: self.pallet_name().to_owned(),
.entry_by_name(self.entry_name()) })?;
.ok_or_else(|| MetadataError::StorageEntryNotFound(self.entry_name().to_owned()))?; let entry = storage.entry_by_name(self.entry_name()).ok_or_else(|| {
MetadataError::StorageEntryNotFound {
entry_name: self.entry_name().to_owned(),
}
})?;
let hashers = StorageHashers::new(entry.entry_type(), metadata.types())?; let hashers = StorageHashers::new(entry.entry_type(), metadata.types())?;
self.keys self.keys
+5 -2
View File
@@ -5,6 +5,7 @@
use super::utils::hash_bytes; use super::utils::hash_bytes;
use crate::{ use crate::{
error::{Error, MetadataError, StorageAddressError}, error::{Error, MetadataError, StorageAddressError},
error_utils::DisplayError,
utils::{Encoded, Static}, utils::{Encoded, Static},
}; };
use alloc::vec; use alloc::vec;
@@ -34,7 +35,7 @@ impl StorageHashers {
{ {
let ty = types let ty = types
.resolve(*key_ty) .resolve(*key_ty)
.ok_or(MetadataError::TypeNotFound(*key_ty))?; .ok_or(MetadataError::TypeNotFound { type_id: *key_ty })?;
if let TypeDef::Tuple(tuple) = &ty.type_def { if let TypeDef::Tuple(tuple) = &ty.type_def {
if hashers.len() == 1 { if hashers.len() == 1 {
@@ -306,7 +307,9 @@ fn consume_hash_returning_key_bytes<'a>(
types, types,
IgnoreVisitor::<PortableRegistry>::new(), IgnoreVisitor::<PortableRegistry>::new(),
) )
.map_err(|err| Error::Decode(err.into()))?; .map_err(|err| Error::Decode {
source: DisplayError(err.into()),
})?;
// Return the key bytes, having advanced the input cursor past them. // Return the key bytes, having advanced the input cursor past them.
let key_bytes = &before_key[..before_key.len() - bytes.len()]; let key_bytes = &before_key[..before_key.len() - bytes.len()];
+11 -6
View File
@@ -46,11 +46,16 @@ pub fn lookup_storage_entry_details<'a>(
metadata: &'a Metadata, metadata: &'a Metadata,
) -> Result<(PalletMetadata<'a>, &'a StorageEntryMetadata), Error> { ) -> Result<(PalletMetadata<'a>, &'a StorageEntryMetadata), Error> {
let pallet_metadata = metadata.pallet_by_name_err(pallet_name)?; let pallet_metadata = metadata.pallet_by_name_err(pallet_name)?;
let storage_metadata = pallet_metadata let storage_metadata =
.storage() pallet_metadata
.ok_or_else(|| MetadataError::StorageNotFoundInPallet(pallet_name.to_owned()))?; .storage()
let storage_entry = storage_metadata .ok_or_else(|| MetadataError::StorageNotFoundInPallet {
.entry_by_name(entry_name) name: pallet_name.to_owned(),
.ok_or_else(|| MetadataError::StorageEntryNotFound(entry_name.to_owned()))?; })?;
let storage_entry = storage_metadata.entry_by_name(entry_name).ok_or_else(|| {
MetadataError::StorageEntryNotFound {
entry_name: entry_name.to_owned(),
}
})?;
Ok((pallet_metadata, storage_entry)) Ok((pallet_metadata, storage_entry))
} }
+3 -1
View File
@@ -80,7 +80,9 @@ pub fn validate<Call: Payload>(call: &Call, metadata: &Metadata) -> Result<(), E
let expected_hash = metadata let expected_hash = metadata
.pallet_by_name_err(details.pallet_name)? .pallet_by_name_err(details.pallet_name)?
.call_hash(details.call_name) .call_hash(details.call_name)
.ok_or_else(|| MetadataError::CallNameNotFound(details.call_name.to_owned()))?; .ok_or_else(|| MetadataError::CallNameNotFound {
name: details.call_name.to_owned(),
})?;
if details.hash != expected_hash { if details.hash != expected_hash {
return Err(MetadataError::IncompatibleCodegen.into()); return Err(MetadataError::IncompatibleCodegen.into());
+3 -1
View File
@@ -141,7 +141,9 @@ impl<CallData: EncodeAsFields> Payload for DefaultPayload<CallData> {
let pallet = metadata.pallet_by_name_err(&self.pallet_name)?; let pallet = metadata.pallet_by_name_err(&self.pallet_name)?;
let call = pallet let call = pallet
.call_variant_by_name(&self.call_name) .call_variant_by_name(&self.call_name)
.ok_or_else(|| MetadataError::CallNameNotFound((*self.call_name).to_owned()))?; .ok_or_else(|| MetadataError::CallNameNotFound {
name: (*self.call_name).to_owned(),
})?;
let pallet_index = pallet.index(); let pallet_index = pallet.index();
let call_index = call.index; let call_index = call.index;
+6 -6
View File
@@ -11,8 +11,8 @@ use alloc::string::String;
use alloc::vec; use alloc::vec;
use alloc::vec::Vec; use alloc::vec::Vec;
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use derive_more::Display;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use snafu::Snafu;
/// A 32-byte cryptographic identifier. This is a simplified version of Substrate's /// A 32-byte cryptographic identifier. This is a simplified version of Substrate's
/// `sp_core::crypto::AccountId32`. To obtain more functionality, convert this into /// `sp_core::crypto::AccountId32`. To obtain more functionality, convert this into
@@ -105,16 +105,16 @@ impl AccountId32 {
} }
/// An error obtained from trying to interpret an SS58 encoded string into an AccountId32 /// An error obtained from trying to interpret an SS58 encoded string into an AccountId32
#[derive(Clone, Copy, Eq, PartialEq, Debug, Display)] #[derive(Clone, Copy, Eq, PartialEq, Debug, Snafu)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub enum FromSs58Error { pub enum FromSs58Error {
#[display(fmt = "Base 58 requirement is violated")] #[snafu(display("Base 58 requirement is violated"))]
BadBase58, BadBase58,
#[display(fmt = "Length is bad")] #[snafu(display("Length is bad"))]
BadLength, BadLength,
#[display(fmt = "Invalid checksum")] #[snafu(display("Invalid checksum"))]
InvalidChecksum, InvalidChecksum,
#[display(fmt = "Invalid SS58 prefix byte.")] #[snafu(display("Invalid SS58 prefix byte."))]
InvalidPrefix, InvalidPrefix,
} }