Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Handle sp_runtime::ModuleError substrate updates #492

Merged
merged 15 commits into from
Mar 31, 2022
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 57 additions & 18 deletions codegen/src/api/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,31 +38,63 @@ pub fn generate_has_module_error_impl(
.ty()
.type_def();

// Slightly older versions of substrate have a `DispatchError::Module { index, error }`
// variant. Newer versions have something like a `DispatchError::Module (Details)` variant.
// We check to see which type of variant we're dealing with based on the metadata, and
// generate the correct code to handle either older or newer substrate versions.
let module_variant_is_struct = if let TypeDef::Variant(details) = dispatch_error_def {
// Different substrate versions will have a `DispatchError::Module` of the following form,
// ordered by versions:
//
// Case 1. DispatchError::Module { index: u8, error: u8 }
// Case 2. DispatchError::Module ( sp_runtime::ModuleError { index: u8, error: u8 } )
// Case 3. DispatchError::Module ( sp_runtime::ModuleError { index: u8, error: [u8; 4] } )
//
// To handle all cases and maintain backward compatibility, the type of the variant is inspected
// based on the metadata.
// If the variant has a named field (i.e, Case 1) the variable `module_variant_is_struct` is
// true. If the error is of form `u8`, then `module_legacy_err` is True.
//
// Note: Legacy errors are present in Case 1 and Case 2. Therefore, newer errors are possibly
// encountered in Case 3s, the unnamed field case.
let (module_variant_is_struct, module_legacy_err) = if let TypeDef::Variant(details) =
dispatch_error_def
{
let module_variant = details
.variants()
.iter()
.find(|variant| variant.name() == "Module")
.unwrap_or_else(|| {
abort_call_site!("DispatchError::Module variant expected in metadata")
});
let are_fields_named = module_variant
.fields()
.get(0)
.unwrap_or_else(|| {
abort_call_site!(
"DispatchError::Module expected to contain 1 or more fields"
)
})
.name()
.is_some();
are_fields_named

let module_field = module_variant.fields().get(0).unwrap_or_else(|| {
lexnv marked this conversation as resolved.
Show resolved Hide resolved
abort_call_site!("DispatchError::Module expected to contain 1 or more fields")
});
if module_field.name().is_none() {
let module_err = metadata
.types
.resolve(module_field.ty().id())
.unwrap_or_else(|| {
abort_call_site!("sp_runtime::ModuleError type expected in metadata")
});

if let TypeDef::Composite(composite) = module_err.type_def() {
let error_field = composite
.fields()
.iter()
.find(|field| field.name() == Some(&"error".to_string()))
.unwrap_or_else(|| {
abort_call_site!(
"sp_runtime::ModuleError expected to contain error field"
)
});
// Avoid further metadata inspection by relying on type name information
// (the name of the type of the field as it appears in the source code)
(false, error_field.type_name() == Some(&"u8".to_string()))
} else {
(false, true)
}
} else {
(true, true)
}
} else {
false
(false, true)
};

let trait_fn_body = if module_variant_is_struct {
Expand All @@ -74,9 +106,16 @@ pub fn generate_has_module_error_impl(
}
}
} else {
let error_conversion = if module_legacy_err {
quote! { module_error.error }
} else {
// Convert [u8; 4] errors to legacy format.
ascjones marked this conversation as resolved.
Show resolved Hide resolved
quote! { module_error.error[0] }
};

quote! {
if let Self::Module (module_error) = self {
Some((module_error.index, module_error.error))
Some((module_error.index, #error_conversion))
} else {
None
}
Expand Down