Introduce Metadata type (#974)

* WIP new Metadata type

* Finish basic Metadata impl inc hashing and validation

* remove caching from metadata; can add that higher up

* remove caches

* update retain to use Metadata

* clippy fixes

* update codegen to use Metadata

* clippy

* WIP fixing subxt lib

* WIP fixing tests, rebuild artifacts, fix OrderedMap::retain

* get --all-targets compiling

* move DispatchError type lookup back to being optional

* cargo clippy

* fix docs

* re-use VariantIndex to get variants

* add docs and enforce docs on metadata crate

* fix docs

* add test and fix docs

* cargo fmt

* address review comments

* update lockfiles

* ExactSizeIter so we can ask for len() of things (and hopefully soon is_empty()
This commit is contained in:
James Wilson
2023-05-25 10:35:21 +01:00
committed by GitHub
parent f344d0dd4d
commit b9f5419095
64 changed files with 6818 additions and 5719 deletions
+30 -18
View File
@@ -10,7 +10,7 @@ use core::fmt::Debug;
use scale_decode::visitor::DecodeAsTypeResult;
use std::borrow::Cow;
use super::Error;
use super::{Error, MetadataError};
use crate::error::RootError;
/// An error dispatching a transaction.
@@ -145,20 +145,27 @@ impl std::fmt::Display for ModuleError {
return f.write_str("Unknown pallet error (pallet and error details cannot be retrieved)");
};
let pallet = details.pallet();
let error = details.error();
let pallet = details.pallet.name();
let error = &details.variant.name;
write!(f, "Pallet error {pallet}::{error}")
}
}
impl ModuleError {
/// Return more details about this error.
pub fn details(&self) -> Result<&crate::metadata::ErrorMetadata, super::Error> {
let error_details = self
pub fn details(&self) -> Result<ModuleErrorDetails, MetadataError> {
let pallet = self
.metadata
.error(self.raw.pallet_index, self.raw.error[0])?;
Ok(error_details)
.pallet_by_index(self.raw.pallet_index)
.ok_or(MetadataError::PalletIndexNotFound(self.raw.pallet_index))?;
let variant = pallet
.error_variant_by_index(self.raw.error[0])
.ok_or_else(|| MetadataError::VariantIndexNotFound(self.raw.error[0]))?;
Ok(ModuleErrorDetails { pallet, variant })
}
/// Return the underlying module error data that was decoded.
pub fn raw(&self) -> RawModuleError {
self.raw
@@ -167,10 +174,22 @@ impl ModuleError {
/// Attempts to decode the ModuleError into a value implementing the trait `RootError`
/// where the actual type of value is the generated top level enum `Error`.
pub fn as_root_error<E: RootError>(&self) -> Result<E, Error> {
E::root_error(&self.raw.error, self.details()?.pallet(), &self.metadata)
E::root_error(
&self.raw.error,
self.details()?.pallet.name(),
&self.metadata,
)
}
}
/// Details about the module error.
pub struct ModuleErrorDetails<'a> {
/// The pallet that the error came from
pub pallet: crate::metadata::types::PalletMetadata<'a>,
/// The variant representing the error
pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
}
/// The error details about a module error that has occurred.
///
/// **Note**: Structure used to obtain the underlying bytes of a ModuleError.
@@ -198,16 +217,9 @@ impl DispatchError {
metadata: Metadata,
) -> Result<Self, super::Error> {
let bytes = bytes.into();
let dispatch_error_ty_id = match metadata.dispatch_error_ty() {
Some(id) => id,
None => {
tracing::warn!(
"Can't decode error: sp_runtime::DispatchError was not found in Metadata"
);
return Err(super::Error::Unknown(bytes.into_owned()));
}
};
let dispatch_error_ty_id = metadata
.dispatch_error_ty()
.ok_or(MetadataError::DispatchErrorNotFound)?;
// The aim is to decode our bytes into roughly this shape. This is copied from
// `sp_runtime::DispatchError`; we need the variant names and any inner variant