Fix order of hook execution (#10043)

* fix order

* Update frame/support/procedural/src/construct_runtime/mod.rs

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>

* format

* more accurate description

* format

* better explicit types

* fix tests

* address feedback

* add a type to ease non breaking implementation

* add comment about constraint

* fix test

* add test for generated types

Co-authored-by: Alexander Popiak <alexander.popiak@parity.io>
This commit is contained in:
Guillaume Thiolliere
2021-12-01 09:59:09 +09:00
committed by GitHub
parent d58aeb040a
commit db28ba9dfd
6 changed files with 236 additions and 94 deletions
@@ -304,35 +304,82 @@ fn decl_all_pallets<'a>(
types.extend(type_decl);
names.push(&pallet_declaration.name);
}
// Make nested tuple structure like (((Babe, Consensus), Grandpa), ...)
// Make nested tuple structure like:
// `((FirstPallet, (SecondPallet, ( ... , LastPallet) ... ))))`
// But ignore the system pallet.
let all_pallets = names
let all_pallets_without_system = names
.iter()
.filter(|n| **n != SYSTEM_PALLET_NAME)
.rev()
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
// Make nested tuple structure like:
// `((FirstPallet, (SecondPallet, ( ... , LastPallet) ... ))))`
let all_pallets_with_system = names
.iter()
.rev()
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
// Make nested tuple structure like:
// `((LastPallet, (SecondLastPallet, ( ... , FirstPallet) ... ))))`
// But ignore the system pallet.
let all_pallets_without_system_reversed = names
.iter()
.filter(|n| **n != SYSTEM_PALLET_NAME)
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
let all_pallets_with_system = names
// Make nested tuple structure like:
// `((LastPallet, (SecondLastPallet, ( ... , FirstPallet) ... ))))`
let all_pallets_with_system_reversed = names
.iter()
.fold(TokenStream2::default(), |combined, name| quote!((#name, #combined)));
let system_pallet = match names.iter().find(|n| **n == SYSTEM_PALLET_NAME) {
Some(name) => name,
None =>
return syn::Error::new(
proc_macro2::Span::call_site(),
"`System` pallet declaration is missing. \
Please add this line: `System: frame_system::{Pallet, Call, Storage, Config, Event<T>},`",
)
.into_compile_error(),
};
quote!(
#types
/// All pallets included in the runtime as a nested tuple of types.
/// Excludes the System pallet.
pub type AllPallets = ( #all_pallets );
#[deprecated(note = "The type definition has changed from representing all pallets \
excluding system, in reversed order to become the representation of all pallets \
including system pallet in regular order. For this reason it is encouraged to use \
explicitly one of `AllPalletsWithSystem`, `AllPalletsWithoutSystem`, \
`AllPalletsWithSystemReversed`, `AllPalletsWithoutSystemReversed`. \
Note that the type `frame_executive::Executive` expects one of `AllPalletsWithSystem` \
, `AllPalletsWithSystemReversed`, `AllPalletsReversedWithSystemFirst`. More details in \
https://github.com/paritytech/substrate/pull/10043")]
pub type AllPallets = AllPalletsWithSystem;
/// All pallets included in the runtime as a nested tuple of types.
pub type AllPalletsWithSystem = ( #all_pallets_with_system );
/// All modules included in the runtime as a nested tuple of types.
/// All pallets included in the runtime as a nested tuple of types.
/// Excludes the System pallet.
#[deprecated(note = "use `AllPallets` instead")]
#[allow(dead_code)]
pub type AllModules = ( #all_pallets );
/// All modules included in the runtime as a nested tuple of types.
#[deprecated(note = "use `AllPalletsWithSystem` instead")]
#[allow(dead_code)]
pub type AllModulesWithSystem = ( #all_pallets_with_system );
pub type AllPalletsWithoutSystem = ( #all_pallets_without_system );
/// All pallets included in the runtime as a nested tuple of types in reversed order.
/// Excludes the System pallet.
pub type AllPalletsWithoutSystemReversed = ( #all_pallets_without_system_reversed );
/// All pallets included in the runtime as a nested tuple of types in reversed order.
pub type AllPalletsWithSystemReversed = ( #all_pallets_with_system_reversed );
/// All pallets included in the runtime as a nested tuple of types in reversed order.
/// With the system pallet first.
pub type AllPalletsReversedWithSystemFirst = (
#system_pallet,
AllPalletsWithoutSystemReversed
);
)
}
+116 -6
View File
@@ -453,9 +453,21 @@ pub mod pallet2 {
pub struct Pallet<T>(_);
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> where
T::AccountId: From<SomeType1> + SomeAssociation1
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T>
where
T::AccountId: From<SomeType1> + SomeAssociation1,
{
fn on_initialize(_: BlockNumberFor<T>) -> Weight {
Self::deposit_event(Event::Something(11));
0
}
fn on_finalize(_: BlockNumberFor<T>) {
Self::deposit_event(Event::Something(21));
}
fn on_runtime_upgrade() -> Weight {
Self::deposit_event(Event::Something(31));
0
}
}
#[pallet::call]
@@ -469,6 +481,7 @@ pub mod pallet2 {
CountedStorageMap<Hasher = Twox64Concat, Key = u8, Value = u32>;
#[pallet::event]
#[pallet::generate_deposit(fn deposit_event)]
pub enum Event {
/// Something
Something(u32),
@@ -963,10 +976,10 @@ fn pallet_hooks_expand() {
TestExternalities::default().execute_with(|| {
frame_system::Pallet::<Runtime>::set_block_number(1);
assert_eq!(AllPallets::on_initialize(1), 10);
AllPallets::on_finalize(1);
assert_eq!(AllPalletsWithoutSystem::on_initialize(1), 10);
AllPalletsWithoutSystem::on_finalize(1);
assert_eq!(AllPallets::on_runtime_upgrade(), 30);
assert_eq!(AllPalletsWithoutSystem::on_runtime_upgrade(), 30);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[0].event,
@@ -974,10 +987,62 @@ fn pallet_hooks_expand() {
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[1].event,
Event::Example(pallet::Event::Something(20)),
Event::Example2(pallet2::Event::Something(11)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[2].event,
Event::Example(pallet::Event::Something(20)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[3].event,
Event::Example2(pallet2::Event::Something(21)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[4].event,
Event::Example(pallet::Event::Something(30)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[5].event,
Event::Example2(pallet2::Event::Something(31)),
);
})
}
#[test]
fn all_pallets_type_reversed_order_is_correct() {
TestExternalities::default().execute_with(|| {
frame_system::Pallet::<Runtime>::set_block_number(1);
#[allow(deprecated)]
{
assert_eq!(AllPalletsWithoutSystemReversed::on_initialize(1), 10);
AllPalletsWithoutSystemReversed::on_finalize(1);
assert_eq!(AllPalletsWithoutSystemReversed::on_runtime_upgrade(), 30);
}
assert_eq!(
frame_system::Pallet::<Runtime>::events()[0].event,
Event::Example2(pallet2::Event::Something(11)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[1].event,
Event::Example(pallet::Event::Something(10)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[2].event,
Event::Example2(pallet2::Event::Something(21)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[3].event,
Event::Example(pallet::Event::Something(20)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[4].event,
Event::Example2(pallet2::Event::Something(31)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[5].event,
Event::Example(pallet::Event::Something(30)),
);
})
@@ -1499,3 +1564,48 @@ fn test_storage_info() {
],
);
}
#[test]
fn assert_type_all_pallets_reversed_with_system_first_is_correct() {
// Just ensure the 2 types are same.
fn _a(_t: AllPalletsReversedWithSystemFirst) {}
fn _b(t: (System, (Example4, (Example2, (Example,))))) {
_a(t)
}
}
#[test]
fn assert_type_all_pallets_with_system_is_correct() {
// Just ensure the 2 types are same.
fn _a(_t: AllPalletsWithSystem) {}
fn _b(t: (System, (Example, (Example2, (Example4,))))) {
_a(t)
}
}
#[test]
fn assert_type_all_pallets_without_system_is_correct() {
// Just ensure the 2 types are same.
fn _a(_t: AllPalletsWithoutSystem) {}
fn _b(t: (Example, (Example2, (Example4,)))) {
_a(t)
}
}
#[test]
fn assert_type_all_pallets_with_system_reversed_is_correct() {
// Just ensure the 2 types are same.
fn _a(_t: AllPalletsWithSystemReversed) {}
fn _b(t: (Example4, (Example2, (Example, (System,))))) {
_a(t)
}
}
#[test]
fn assert_type_all_pallets_without_system_reversed_is_correct() {
// Just ensure the 2 types are same.
fn _a(_t: AllPalletsWithoutSystemReversed) {}
fn _b(t: (Example4, (Example2, (Example,)))) {
_a(t)
}
}
@@ -551,35 +551,34 @@ fn pallet_hooks_expand() {
TestExternalities::default().execute_with(|| {
frame_system::Pallet::<Runtime>::set_block_number(1);
assert_eq!(AllPallets::on_initialize(1), 21);
AllPallets::on_finalize(1);
assert_eq!(AllPalletsWithoutSystem::on_initialize(1), 21);
AllPalletsWithoutSystem::on_finalize(1);
assert_eq!(AllPallets::on_runtime_upgrade(), 61);
assert_eq!(AllPalletsWithoutSystem::on_runtime_upgrade(), 61);
// The order is indeed reversed due to https://github.com/paritytech/substrate/issues/6280
assert_eq!(
frame_system::Pallet::<Runtime>::events()[0].event,
Event::Instance1Example(pallet::Event::Something(11)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[1].event,
Event::Example(pallet::Event::Something(10)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[2].event,
Event::Instance1Example(pallet::Event::Something(21)),
frame_system::Pallet::<Runtime>::events()[1].event,
Event::Instance1Example(pallet::Event::Something(11)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[3].event,
frame_system::Pallet::<Runtime>::events()[2].event,
Event::Example(pallet::Event::Something(20)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[3].event,
Event::Instance1Example(pallet::Event::Something(21)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[4].event,
Event::Instance1Example(pallet::Event::Something(31)),
Event::Example(pallet::Event::Something(30)),
);
assert_eq!(
frame_system::Pallet::<Runtime>::events()[5].event,
Event::Example(pallet::Event::Something(30)),
Event::Instance1Example(pallet::Event::Something(31)),
);
})
}