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_runtime_upgrade() -> Weight { ... }
    fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError> { ... }
    fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> { ... }
    fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> { ... }
    fn offchain_worker(_n: BlockNumber) { ... }
    fn integrity_test() { ... }
}
Expand description

The pallet hooks trait. This is merely an umbrella trait for:

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 --> BeforeExtrinsics BeforeExtrinsics --> Extrinsics Extrinsics --> AfterExtrinsics subgraph Optional OnRuntimeUpgrade end subgraph BeforeExtrinsics OnInitialize end subgraph Extrinsics direction TB Inherent1 Inherent2 Extrinsic1 Extrinsic2 Inherent1 --> Inherent2 Inherent2 --> Extrinsic1 Extrinsic1 --> Extrinsic2 end subgraph AfterExtrinsics OnIdle OnFinalize OnIdle --> OnFinalize end
  • OnRuntimeUpgrade is only executed before everything else if a code
  • OnRuntimeUpgrade is mandatorily at the beginning of the block body (extrinsics) being processed. change is detected.
  • Extrinsics start with inherents, and continue with other signed or unsigned extrinsics.
  • OnIdle optionally comes after extrinsics. OnFinalize mandatorily comes after OnIdle.

OffchainWorker is not part of this flow, as it is not really part of the consensus/main block import path, and is called optionally, and in other circumstances. See crate::traits::misc::OffchainWorker for more information.

To learn more about the execution of hooks see frame-executive as this component is is charge of dispatching extrinsics and placing the hooks in the correct order.

Provided Methods§

source

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.

source

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.

source

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.

source

fn on_runtime_upgrade() -> Weight

Hook executed when a code change (aka. a “runtime upgrade”) is detected by FRAME.

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.

Vert similar to Hooks::on_initialize, any code in this block is mandatory and MUST execute. Use with care.

Implementation Note: Versioning
  1. An implementation of this should typically follow a pattern where the version of the pallet is checked against the onchain version, and a decision is made about what needs to be done. This is helpful to prevent accidental repetitive execution of this hook, which can be catastrophic.

Alternatively, migrations::VersionedRuntimeUpgrade can be used to assist with this.

Implementation Note: Runtime Level Migration

Additional “upgrade hooks” can be created by pallets by a manual implementation of Hooks::on_runtime_upgrade which can be passed on to Executive at the top level runtime.

source

fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError>

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 should not alter any storage.

source

fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError>

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 meant to be executed on-chain but is meant to be used by testing tools.

source

fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError>

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.

source

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 wasm runtime.

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.

source

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.

Implementors§