mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-15 06:51:07 +00:00
use snafu in core
This commit is contained in:
+1
-1
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 }
|
||||||
))
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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
@@ -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),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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(),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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[..],
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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,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()];
|
||||||
|
|
||||||
|
|||||||
@@ -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
@@ -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());
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user