mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 15:41:02 +00:00
TryDecodeEntireState check for storage types and pallets (#1805)
### This PR is a port of this [PR for substrate](https://github.com/paritytech/substrate/pull/13013) by @kianenigma Add infrastructure needed to have a Pallet::decode_entire_state(), which makes sure all "typed" storage items defined in the pallet are decode-able. This is not enforced in any way at the moment. Teams who wish to integrate/use this in the try-runtime feature flag should add frame_support::storage::migration::EnsureStateDecodes as the LAST ITEM of the runtime's custom migrations, and pass it to frame-executive. This will make it usable in try-runtime on-runtime-upgrade. This now catches cases like https://github.com/paritytech/polkadot-sdk/pull/1969: ```pre ERROR runtime::executive] failed to decode the value at key: Failed to decode value at key: 0x94eadf0156a8ad5156507773d0471e4ab8ebad86f546c7e0b135a4212aace339. Storage info StorageInfo { pallet_name: Ok("ParaScheduler"), storage_name: Ok("AvailabilityCores"), prefix: Err(Utf8Error { valid_up_to: 0, error_len: Some(1) }), max_values: Some(1), max_size: None }. Raw value: Some("0x0c010101010101") ``` ... or:  Closes #241 --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Liam Aharon <liam.aharon@hotmail.com>
This commit is contained in:
@@ -127,11 +127,12 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
let trait_use_gen = &def.trait_use_generics(event.attr_span);
|
||||
let type_impl_gen = &def.type_impl_generics(event.attr_span);
|
||||
let type_use_gen = &def.type_use_generics(event.attr_span);
|
||||
let pallet_ident = &def.pallet_struct.pallet;
|
||||
|
||||
let PalletEventDepositAttr { fn_vis, fn_span, .. } = deposit_event;
|
||||
|
||||
quote::quote_spanned!(*fn_span =>
|
||||
impl<#type_impl_gen> Pallet<#type_use_gen> #completed_where_clause {
|
||||
impl<#type_impl_gen> #pallet_ident<#type_use_gen> #completed_where_clause {
|
||||
#fn_vis fn deposit_event(event: Event<#event_use_gen>) {
|
||||
let event = <
|
||||
<T as Config #trait_use_gen>::RuntimeEvent as
|
||||
|
||||
@@ -822,12 +822,69 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
)
|
||||
});
|
||||
|
||||
// aggregated where clause of all storage types and the whole pallet.
|
||||
let mut where_clauses = vec![&def.config.where_clause];
|
||||
where_clauses.extend(def.storages.iter().map(|storage| &storage.where_clause));
|
||||
let completed_where_clause = super::merge_where_clauses(&where_clauses);
|
||||
let type_impl_gen = &def.type_impl_generics(proc_macro2::Span::call_site());
|
||||
let type_use_gen = &def.type_use_generics(proc_macro2::Span::call_site());
|
||||
|
||||
let try_decode_entire_state = {
|
||||
let mut storage_names = def
|
||||
.storages
|
||||
.iter()
|
||||
.filter_map(|storage| {
|
||||
if storage.cfg_attrs.is_empty() {
|
||||
let ident = &storage.ident;
|
||||
let gen = &def.type_use_generics(storage.attr_span);
|
||||
Some(quote::quote_spanned!(storage.attr_span => #ident<#gen> ))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
storage_names.sort_by_cached_key(|ident| ident.to_string());
|
||||
|
||||
quote::quote!(
|
||||
#[cfg(feature = "try-runtime")]
|
||||
impl<#type_impl_gen> #frame_support::traits::TryDecodeEntireStorage
|
||||
for #pallet_ident<#type_use_gen> #completed_where_clause
|
||||
{
|
||||
fn try_decode_entire_state() -> Result<usize, #frame_support::__private::sp_std::vec::Vec<#frame_support::traits::TryDecodeEntireStorageError>> {
|
||||
let pallet_name = <<T as #frame_system::Config>::PalletInfo as frame_support::traits::PalletInfo>
|
||||
::name::<#pallet_ident<#type_use_gen>>()
|
||||
.expect("Every active pallet has a name in the runtime; qed");
|
||||
|
||||
#frame_support::__private::log::debug!(target: "runtime::try-decode-state", "trying to decode pallet: {pallet_name}");
|
||||
|
||||
// NOTE: for now, we have to exclude storage items that are feature gated.
|
||||
let mut errors = #frame_support::__private::sp_std::vec::Vec::new();
|
||||
let mut decoded = 0usize;
|
||||
|
||||
#(
|
||||
#frame_support::__private::log::debug!(target: "runtime::try-decode-state", "trying to decode storage: \
|
||||
{pallet_name}::{}", stringify!(#storage_names));
|
||||
|
||||
match <#storage_names as #frame_support::traits::TryDecodeEntireStorage>::try_decode_entire_state() {
|
||||
Ok(count) => {
|
||||
decoded += count;
|
||||
},
|
||||
Err(err) => {
|
||||
errors.extend(err);
|
||||
},
|
||||
}
|
||||
)*
|
||||
|
||||
if errors.is_empty() {
|
||||
Ok(decoded)
|
||||
} else {
|
||||
Err(errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
quote::quote!(
|
||||
impl<#type_impl_gen> #pallet_ident<#type_use_gen>
|
||||
#completed_where_clause
|
||||
@@ -853,5 +910,7 @@ pub fn expand_storages(def: &mut Def) -> proc_macro2::TokenStream {
|
||||
#( #getters )*
|
||||
#( #prefix_structs )*
|
||||
#( #on_empty_structs )*
|
||||
|
||||
#try_decode_entire_state
|
||||
)
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ pub enum QueryKind {
|
||||
/// `type MyStorage = StorageValue<MyStorageP, u32>`
|
||||
/// The keys and values types are parsed in order to get metadata
|
||||
pub struct StorageDef {
|
||||
/// The index of error item in pallet module.
|
||||
/// The index of storage item in pallet module.
|
||||
pub index: usize,
|
||||
/// Visibility of the storage type.
|
||||
pub vis: syn::Visibility,
|
||||
|
||||
Reference in New Issue
Block a user