use crate::pallet::Def;
pub fn expand_hooks(def: &mut Def) -> proc_macro2::TokenStream {
let (where_clause, span, has_runtime_upgrade) = match def.hooks.as_ref() {
Some(hooks) => {
let where_clause = hooks.where_clause.clone();
let span = hooks.attr_span;
let has_runtime_upgrade = hooks.has_runtime_upgrade;
(where_clause, span, has_runtime_upgrade)
},
None => (def.config.where_clause.clone(), def.pallet_struct.attr_span, false),
};
let frame_support = &def.frame_support;
let type_impl_gen = &def.type_impl_generics(span);
let type_use_gen = &def.type_use_generics(span);
let pallet_ident = &def.pallet_struct.pallet;
let frame_system = &def.frame_system;
let pallet_name = quote::quote! {
<
<T as #frame_system::Config>::PalletInfo
as
#frame_support::traits::PalletInfo
>::name::<Self>().unwrap_or("<unknown pallet name>")
};
let initialize_on_chain_storage_version = if let Some(in_code_version) =
&def.pallet_struct.storage_version
{
quote::quote! {
#frame_support::__private::log::info!(
target: #frame_support::LOG_TARGET,
"🐥 New pallet {:?} detected in the runtime. Initializing the on-chain storage version to match the storage version defined in the pallet: {:?}",
#pallet_name,
#in_code_version
);
#in_code_version.put::<Self>();
}
} else {
quote::quote! {
let default_version = #frame_support::traits::StorageVersion::new(0);
#frame_support::__private::log::info!(
target: #frame_support::LOG_TARGET,
"🐥 New pallet {:?} detected in the runtime. The pallet has no defined storage version, so the on-chain version is being initialized to {:?}.",
#pallet_name,
default_version
);
default_version.put::<Self>();
}
};
let log_runtime_upgrade = if has_runtime_upgrade {
quote::quote! {
#frame_support::__private::log::info!(
target: #frame_support::LOG_TARGET,
"⚠️ {} declares internal migrations (which *might* execute). \
On-chain `{:?}` vs in-code storage version `{:?}`",
#pallet_name,
<Self as #frame_support::traits::GetStorageVersion>::on_chain_storage_version(),
<Self as #frame_support::traits::GetStorageVersion>::in_code_storage_version(),
);
}
} else {
quote::quote! {
#frame_support::__private::log::debug!(
target: #frame_support::LOG_TARGET,
"✅ no migration for {}",
#pallet_name,
);
}
};
let hooks_impl = if def.hooks.is_none() {
let frame_system = &def.frame_system;
quote::quote! {
impl<#type_impl_gen>
#frame_support::traits::Hooks<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause {}
}
} else {
proc_macro2::TokenStream::new()
};
let post_storage_version_check = if def.pallet_struct.storage_version.is_some() {
quote::quote! {
let on_chain_version = <Self as #frame_support::traits::GetStorageVersion>::on_chain_storage_version();
let in_code_version = <Self as #frame_support::traits::GetStorageVersion>::in_code_storage_version();
if on_chain_version != in_code_version {
#frame_support::__private::log::error!(
target: #frame_support::LOG_TARGET,
"{}: On chain storage version {:?} doesn't match in-code storage version {:?}.",
#pallet_name,
on_chain_version,
in_code_version,
);
return Err("On chain and in-code storage version do not match. Missing runtime upgrade?".into());
}
}
} else {
quote::quote! {
let on_chain_version = <Self as #frame_support::traits::GetStorageVersion>::on_chain_storage_version();
if on_chain_version != #frame_support::traits::StorageVersion::new(0) {
#frame_support::__private::log::error!(
target: #frame_support::LOG_TARGET,
"{}: On chain storage version {:?} is set to non zero, \
while the pallet is missing the `#[pallet::storage_version(VERSION)]` attribute.",
#pallet_name,
on_chain_version,
);
return Err("On chain storage version set, while the pallet doesn't \
have the `#[pallet::storage_version(VERSION)]` attribute.".into());
}
}
};
quote::quote_spanned!(span =>
#hooks_impl
impl<#type_impl_gen>
#frame_support::traits::OnFinalize<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause
{
fn on_finalize(n: #frame_system::pallet_prelude::BlockNumberFor::<T>) {
#frame_support::__private::sp_tracing::enter_span!(
#frame_support::__private::sp_tracing::trace_span!("on_finalize")
);
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::on_finalize(n)
}
}
impl<#type_impl_gen>
#frame_support::traits::OnIdle<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause
{
fn on_idle(
n: #frame_system::pallet_prelude::BlockNumberFor::<T>,
remaining_weight: #frame_support::weights::Weight
) -> #frame_support::weights::Weight {
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::on_idle(n, remaining_weight)
}
}
impl<#type_impl_gen>
#frame_support::traits::OnPoll<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause
{
fn on_poll(
n: #frame_system::pallet_prelude::BlockNumberFor::<T>,
weight: &mut #frame_support::weights::WeightMeter
) {
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::on_poll(n, weight);
}
}
impl<#type_impl_gen>
#frame_support::traits::OnInitialize<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause
{
fn on_initialize(
n: #frame_system::pallet_prelude::BlockNumberFor::<T>
) -> #frame_support::weights::Weight {
#frame_support::__private::sp_tracing::enter_span!(
#frame_support::__private::sp_tracing::trace_span!("on_initialize")
);
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::on_initialize(n)
}
}
impl<#type_impl_gen>
#frame_support::traits::BeforeAllRuntimeMigrations
for #pallet_ident<#type_use_gen> #where_clause
{
fn before_all_runtime_migrations() -> #frame_support::weights::Weight {
use #frame_support::traits::{Get, PalletInfoAccess};
use #frame_support::__private::hashing::twox_128;
use #frame_support::storage::unhashed::contains_prefixed_key;
#frame_support::__private::sp_tracing::enter_span!(
#frame_support::__private::sp_tracing::trace_span!("before_all")
);
let pallet_hashed_prefix = <Self as PalletInfoAccess>::name_hash();
let exists = contains_prefixed_key(&pallet_hashed_prefix);
if !exists {
#initialize_on_chain_storage_version
<T as #frame_system::Config>::DbWeight::get().reads_writes(1, 1)
} else {
<T as #frame_system::Config>::DbWeight::get().reads(1)
}
}
}
impl<#type_impl_gen>
#frame_support::traits::OnRuntimeUpgrade
for #pallet_ident<#type_use_gen> #where_clause
{
fn on_runtime_upgrade() -> #frame_support::weights::Weight {
#frame_support::__private::sp_tracing::enter_span!(
#frame_support::__private::sp_tracing::trace_span!("on_runtime_update")
);
#log_runtime_upgrade
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::on_runtime_upgrade()
}
#frame_support::try_runtime_enabled! {
fn pre_upgrade() -> Result<#frame_support::__private::Vec<u8>, #frame_support::sp_runtime::TryRuntimeError> {
<
Self
as
#frame_support::traits::Hooks<#frame_system::pallet_prelude::BlockNumberFor::<T>>
>::pre_upgrade()
}
fn post_upgrade(state: #frame_support::__private::Vec<u8>) -> Result<(), #frame_support::sp_runtime::TryRuntimeError> {
#post_storage_version_check
<
Self
as
#frame_support::traits::Hooks<#frame_system::pallet_prelude::BlockNumberFor::<T>>
>::post_upgrade(state)
}
}
}
impl<#type_impl_gen>
#frame_support::traits::OffchainWorker<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause
{
fn offchain_worker(n: #frame_system::pallet_prelude::BlockNumberFor::<T>) {
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::offchain_worker(n)
}
}
#frame_support::std_enabled! {
impl<#type_impl_gen>
#frame_support::traits::IntegrityTest
for #pallet_ident<#type_use_gen> #where_clause
{
fn integrity_test() {
#frame_support::__private::sp_io::TestExternalities::default().execute_with(|| {
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::integrity_test()
});
}
}
}
#frame_support::try_runtime_enabled! {
impl<#type_impl_gen>
#frame_support::traits::TryState<#frame_system::pallet_prelude::BlockNumberFor::<T>>
for #pallet_ident<#type_use_gen> #where_clause
{
fn try_state(
n: #frame_system::pallet_prelude::BlockNumberFor::<T>,
_s: #frame_support::traits::TryStateSelect
) -> Result<(), #frame_support::sp_runtime::TryRuntimeError> {
#frame_support::__private::log::info!(
target: #frame_support::LOG_TARGET,
"🩺 Running {:?} try-state checks",
#pallet_name,
);
<
Self as #frame_support::traits::Hooks<
#frame_system::pallet_prelude::BlockNumberFor::<T>
>
>::try_state(n).inspect_err(|err| {
#frame_support::__private::log::error!(
target: #frame_support::LOG_TARGET,
"❌ {:?} try_state checks failed: {:?}",
#pallet_name,
err
);
})
}
}
}
)
}