Trait polkadot_sdk_frame::traits::Hooks
pub trait Hooks<BlockNumber> {
// Provided methods
fn on_initialize(_n: BlockNumber) -> Weight { ... }
fn on_finalize(_n: BlockNumber) { ... }
fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight { ... }
fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter) { ... }
fn on_runtime_upgrade() -> Weight { ... }
fn try_state(_n: BlockNumber) -> Result<(), DispatchError> { ... }
fn pre_upgrade() -> Result<Vec<u8>, DispatchError> { ... }
fn post_upgrade(_state: Vec<u8>) -> Result<(), DispatchError> { ... }
fn offchain_worker(_n: BlockNumber) { ... }
fn integrity_test() { ... }
}
Expand description
The pallet hooks trait. This is merely an umbrella trait for:
OnInitialize
OnFinalize
OnRuntimeUpgrade
crate::traits::misc::OffchainWorker
OnIdle
IntegrityTest
OnPoll
§Ordering
For all hooks, except OnIdle
the order of execution is derived from how the pallets are
ordered in crate::construct_runtime
.
§Summary
In short, the following diagram shows the flow of hooks in a pallet
graph LR
Optional --> Mandatory
Mandatory --> ExtrinsicsMandatory
ExtrinsicsMandatory --> Poll
Poll --> Extrinsics
Extrinsics --> AfterMandatory
AfterMandatory --> onIdle
subgraph Optional
OnRuntimeUpgrade
end
subgraph Mandatory
OnInitialize
end
subgraph ExtrinsicsMandatory
Inherent1 --> Inherent2
end
subgraph Extrinsics
direction TB
Extrinsic1 --> Extrinsic2
end
subgraph AfterMandatory
OnFinalize
end
OnRuntimeUpgrade
hooks are only executed when a code change is detected.OnRuntimeUpgrade
hooks are mandatorily executed at the very beginning of the block body, before any extrinsics are processed.Inherents
are always executed before any other other signed or unsigned extrinsics.OnIdle
hooks are executed after extrinsics if there is weight remaining in the block.OnFinalize
hooks are mandatorily executed afterOnIdle
.
OffchainWorker
hooks are not part of this flow, because they are not part of the consensus/main block building logic. SeeOffchainWorker
for more information.
To learn more about the execution of hooks see the FRAME Executive
pallet which is in charge
of dispatching extrinsics and calling hooks in the correct order.
Provided Methods§
fn on_initialize(_n: BlockNumber) -> Weight
fn on_initialize(_n: BlockNumber) -> Weight
Block initialization hook. This is called at the very beginning of block execution.
Must return the non-negotiable weight of both itself and whatever Hooks::on_finalize
wishes to consume.
§Warning
The weight returned by this is treated as DispatchClass::Mandatory
, meaning that
it MUST BE EXECUTED. If this is not the case, consider using Hooks::on_idle
instead.
Try to keep any arbitrary execution deterministic and within minimal time complexity. For example, do not execute any unbounded iterations.
NOTE: This function is called BEFORE ANY extrinsic in a block is applied, including inherent
extrinsics. Hence for instance, if you runtime includes pallet-timestamp
, the timestamp
is not yet up to date at this point.
fn on_finalize(_n: BlockNumber)
fn on_finalize(_n: BlockNumber)
Block finalization hook. This is called at the very end of block execution.
Note that this has nothing to do with finality in the “consensus” sense.
Note that the non-negotiable weight for this has must have already been returned by
Hooks::on_initialize
. It usage alone is not permitted.
Similar to Hooks::on_initialize
it should only be used when execution is absolutely
necessary. In other cases, consider using Hooks::on_idle
instead.
fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight
fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight
Hook to consume a block’s idle time. This will run when the block is being finalized (before
Hooks::on_finalize
).
Given that all dispatchables are already executed and noted (and the weight for
Hooks::on_finalize
, which comes next, is also already accounted for via
on_initialize
), this hook consumes anything that is leftover.
Each pallet’s on_idle
is chosen to be the first to execute in a round-robin fashion
indexed by the block number.
Return the weight used, the caller will use this to calculate the remaining weight and then
call the next pallet on_idle
hook if there is still weight left.
Any implementation should always respect _remaining_weight
and never consume (and
therefore return) more than this amount.
fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter)
fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter)
A hook to run logic after inherent application.
Is not guaranteed to execute in a block and should therefore only be used in no-deadline scenarios.
This is the non-mandatory version of Hooks::on_initialize
.
fn on_runtime_upgrade() -> Weight
fn on_runtime_upgrade() -> Weight
Hook executed when a code change (aka. a “runtime upgrade”) is detected by the FRAME
Executive
pallet.
Be aware that this is called before Hooks::on_initialize
of any pallet; therefore, a lot
of the critical storage items such as block_number
in system pallet might have not been
set yet.
Similar to Hooks::on_initialize
, any code in this block is mandatory and MUST execute.
It is strongly recommended to dry-run the execution of these hooks using
try-runtime-cli to ensure they will not
produce and overweight block which can brick your chain. Use with care!
§Implementation Note: Standalone Migrations
Additional migrations can be created by directly implementing OnRuntimeUpgrade
on
structs and passing them to Executive
. Or alternatively, by implementing
UncheckedOnRuntimeUpgrade
, passing it to [crate::migrations::VersionedMigration
],
which already implements OnRuntimeUpgrade
.
§Implementation Note: Pallet Versioning
Implementations of this hook are typically wrapped in
[crate::migrations::VersionedMigration
] to ensure the migration is executed exactly
once and only when it is supposed to.
Alternatively, developers can manually implement version checks.
Failure to adequately check storage versions can result in accidental repetitive execution of the hook, which can be catastrophic.
§Implementation Note: Weight
Typically, implementations of this method are simple enough that weights can be calculated manually. However, if required, a benchmark can also be used.
fn try_state(_n: BlockNumber) -> Result<(), DispatchError>
fn try_state(_n: BlockNumber) -> Result<(), DispatchError>
Execute the sanity checks of this pallet, per block.
It should focus on certain checks to ensure that the state is sensible. This is never executed in a consensus code-path, therefore it can consume as much weight as it needs.
This hook must not alter any storage.
fn pre_upgrade() -> Result<Vec<u8>, DispatchError>
fn pre_upgrade() -> Result<Vec<u8>, DispatchError>
Execute some pre-checks prior to a runtime upgrade.
Return a Vec<u8>
that can contain arbitrary encoded data (usually some pre-upgrade state),
which will be passed to post_upgrade
after upgrading for post-check. An empty vector
should be returned if there is no such need.
This hook is never executed on-chain but instead used by testing tools.
fn post_upgrade(_state: Vec<u8>) -> Result<(), DispatchError>
fn post_upgrade(_state: Vec<u8>) -> Result<(), DispatchError>
Execute some post-checks after a runtime upgrade.
The state
parameter is the Vec<u8>
returned by pre_upgrade
before upgrading, which
can be used for post-check. NOTE: if pre_upgrade
is not implemented an empty vector will
be passed in, in such case post_upgrade
should ignore it.
This hook is never meant to be executed on-chain but is meant to be used by testing tools.
fn offchain_worker(_n: BlockNumber)
fn offchain_worker(_n: BlockNumber)
Implementing this function on a pallet allows you to perform long-running tasks that are dispatched as separate threads, and entirely independent of the main blockchain execution.
This function can freely read from the state, but any change it makes to the state is
meaningless. Writes can be pushed back to the chain by submitting extrinsics from the
offchain worker to the transaction pool. See pallet-example-offchain-worker
for more
details on this.
Moreover, the code in this function has access to a wider range of host functions in
[sp-io
], namely [sp_io::offchain
]. This includes exotic operations such as HTTP calls
that are not really possible in the rest of the runtime code.
The execution of this hook is entirely optional and is left at the discretion of the node-side software and its configuration. In a normal substrate-cli, look for the CLI flags related to offchain-workers to learn more.
fn integrity_test()
fn integrity_test()
Check the integrity of this pallet’s configuration.
Any code located in this hook is placed in an auto-generated test, and generated as a part
of crate::construct_runtime
’s expansion. Look for a test case with a name along the
lines of: __construct_runtime_integrity_test
.
This hook is the location where the values/types provided to the Config
trait
of the pallet can be tested for correctness. For example, if two type Foo: Get<u32>
and
type Bar: Get<u32>
where Foo::get()
must always be greater than Bar::get()
, such
checks can be asserted upon here.
Note that this hook is executed in an externality environment, provided by
sp_io::TestExternalities
. This makes it possible to access the storage.