frame_support/traits/hooks.rs
1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Traits relating to pallet hooks.
19//!
20//! See [`Hooks`] as the main entry-point.
21
22#![deny(missing_docs)]
23
24use crate::weights::Weight;
25use impl_trait_for_tuples::impl_for_tuples;
26use sp_runtime::traits::AtLeast32BitUnsigned;
27use sp_weights::WeightMeter;
28
29#[cfg(feature = "try-runtime")]
30use alloc::vec::Vec;
31#[cfg(feature = "try-runtime")]
32use sp_runtime::TryRuntimeError;
33
34/// Provides a callback to execute logic before the all inherents.
35pub trait PreInherents {
36 /// Called before all inherents were applied but after `on_initialize`.
37 fn pre_inherents() {}
38}
39
40#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
41#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
42#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
43impl PreInherents for Tuple {
44 fn pre_inherents() {
45 for_tuples!( #( Tuple::pre_inherents(); )* );
46 }
47}
48
49/// Provides a callback to execute logic after the all inherents.
50pub trait PostInherents {
51 /// Called after all inherents were applied.
52 fn post_inherents() {}
53}
54
55#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
56#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
57#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
58impl PostInherents for Tuple {
59 fn post_inherents() {
60 for_tuples!( #( Tuple::post_inherents(); )* );
61 }
62}
63
64/// Provides a callback to execute logic before the all transactions.
65pub trait PostTransactions {
66 /// Called after all transactions were applied but before `on_finalize`.
67 fn post_transactions() {}
68}
69
70#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
71#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
72#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
73impl PostTransactions for Tuple {
74 fn post_transactions() {
75 for_tuples!( #( Tuple::post_transactions(); )* );
76 }
77}
78
79/// Periodically executes logic. Is not guaranteed to run within a specific timeframe and should
80/// only be used on logic that has no deadline.
81pub trait OnPoll<BlockNumber> {
82 /// Code to execute every now and then at the beginning of the block after inherent application.
83 ///
84 /// The remaining weight limit must be respected.
85 fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter) {}
86}
87
88#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
89#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
90#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
91impl<BlockNumber: Clone> OnPoll<BlockNumber> for Tuple {
92 fn on_poll(n: BlockNumber, weight: &mut WeightMeter) {
93 for_tuples!( #( Tuple::on_poll(n.clone(), weight); )* );
94 }
95}
96
97/// See [`Hooks::on_initialize`].
98pub trait OnInitialize<BlockNumber> {
99 /// See [`Hooks::on_initialize`].
100 fn on_initialize(_n: BlockNumber) -> Weight {
101 Weight::zero()
102 }
103}
104
105#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
106#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
107#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
108impl<BlockNumber: Clone> OnInitialize<BlockNumber> for Tuple {
109 fn on_initialize(n: BlockNumber) -> Weight {
110 let mut weight = Weight::zero();
111 for_tuples!( #( weight = weight.saturating_add(Tuple::on_initialize(n.clone())); )* );
112 weight
113 }
114}
115
116/// See [`Hooks::on_finalize`].
117#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
118#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
119#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
120pub trait OnFinalize<BlockNumber> {
121 /// See [`Hooks::on_finalize`].
122 fn on_finalize(_n: BlockNumber) {}
123}
124
125/// See [`Hooks::on_idle`].
126pub trait OnIdle<BlockNumber> {
127 /// See [`Hooks::on_idle`].
128 fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight {
129 Weight::zero()
130 }
131}
132
133#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
134#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
135#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
136impl<BlockNumber: Copy + AtLeast32BitUnsigned> OnIdle<BlockNumber> for Tuple {
137 fn on_idle(n: BlockNumber, remaining_weight: Weight) -> Weight {
138 let on_idle_functions: &[fn(BlockNumber, Weight) -> Weight] =
139 &[for_tuples!( #( Tuple::on_idle ),* )];
140 let mut weight = Weight::zero();
141 let len = on_idle_functions.len();
142 let start_index = n % (len as u32).into();
143 let start_index = start_index.try_into().ok().expect(
144 "`start_index % len` always fits into `usize`, because `len` can be in maximum `usize::MAX`; qed"
145 );
146 for on_idle_fn in on_idle_functions.iter().cycle().skip(start_index).take(len) {
147 let adjusted_remaining_weight = remaining_weight.saturating_sub(weight);
148 weight = weight.saturating_add(on_idle_fn(n, adjusted_remaining_weight));
149 }
150 weight
151 }
152}
153
154/// A trait that will be called at genesis.
155///
156/// Implementing this trait for a pallet let's you express operations that should
157/// happen at genesis. It will be called in an externalities provided environment and
158/// will set the genesis state after all pallets have written their genesis state.
159#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
160#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
161#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
162pub trait OnGenesis {
163 /// Something that should happen at genesis.
164 fn on_genesis() {}
165}
166
167/// Implemented by pallets, allows defining logic to run prior to any [`OnRuntimeUpgrade`] logic.
168///
169/// This hook is intended to be used internally in FRAME and not be exposed to FRAME developers.
170///
171/// It is defined as a separate trait from [`OnRuntimeUpgrade`] precisely to not pollute the public
172/// API.
173pub trait BeforeAllRuntimeMigrations {
174 /// Something that should happen before runtime migrations are executed.
175 fn before_all_runtime_migrations() -> Weight {
176 Weight::zero()
177 }
178}
179
180/// See [`Hooks::on_runtime_upgrade`].
181pub trait OnRuntimeUpgrade {
182 /// See [`Hooks::on_runtime_upgrade`].
183 fn on_runtime_upgrade() -> Weight {
184 Weight::zero()
185 }
186
187 /// The expected and default behavior of this method is to handle executing `pre_upgrade` ->
188 /// `on_runtime_upgrade` -> `post_upgrade` hooks for a migration.
189 ///
190 /// Internally, the default implementation
191 /// - Handles passing data from `pre_upgrade` to `post_upgrade`
192 /// - Ensure storage is not modified in `pre_upgrade` and `post_upgrade` hooks.
193 ///
194 /// Combining the `pre_upgrade` -> `on_runtime_upgrade` -> `post_upgrade` logic flow into a
195 /// single method call is helpful for scenarios like testing a tuple of migrations, where the
196 /// tuple contains order-dependent migrations.
197 #[cfg(feature = "try-runtime")]
198 fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, TryRuntimeError> {
199 let maybe_state = if checks {
200 let _guard = frame_support::StorageNoopGuard::default();
201 let state = Self::pre_upgrade()?;
202 Some(state)
203 } else {
204 None
205 };
206
207 let weight = Self::on_runtime_upgrade();
208
209 if let Some(state) = maybe_state {
210 let _guard = frame_support::StorageNoopGuard::default();
211 // we want to panic if any checks fail right here right now.
212 Self::post_upgrade(state)?
213 }
214
215 Ok(weight)
216 }
217
218 /// See [`Hooks::pre_upgrade`].
219 #[cfg(feature = "try-runtime")]
220 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
221 Ok(Vec::new())
222 }
223
224 /// See [`Hooks::post_upgrade`].
225 #[cfg(feature = "try-runtime")]
226 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
227 Ok(())
228 }
229}
230
231/// This trait is intended for use within `VersionedMigration` to execute storage migrations without
232/// automatic version checks. Implementations should ensure migration logic is safe and idempotent.
233pub trait UncheckedOnRuntimeUpgrade {
234 /// Called within `VersionedMigration` to execute the actual migration. It is also
235 /// expected that no version checks are performed within this function.
236 ///
237 /// See also [`Hooks::on_runtime_upgrade`].
238 fn on_runtime_upgrade() -> Weight {
239 Weight::zero()
240 }
241
242 /// See [`Hooks::pre_upgrade`].
243 #[cfg(feature = "try-runtime")]
244 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
245 Ok(Vec::new())
246 }
247
248 /// See [`Hooks::post_upgrade`].
249 #[cfg(feature = "try-runtime")]
250 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
251 Ok(())
252 }
253}
254
255#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
256#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
257#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
258impl BeforeAllRuntimeMigrations for Tuple {
259 /// Implements the default behavior of
260 /// [`BeforeAllRuntimeMigrations::before_all_runtime_migrations`] for tuples.
261 fn before_all_runtime_migrations() -> Weight {
262 let mut weight = Weight::zero();
263 for_tuples!( #( weight = weight.saturating_add(Tuple::before_all_runtime_migrations()); )* );
264 weight
265 }
266}
267
268#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
269#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
270#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
271impl OnRuntimeUpgrade for Tuple {
272 /// Implements the default behavior of [`OnRuntimeUpgrade::on_runtime_upgrade`] for tuples.
273 fn on_runtime_upgrade() -> Weight {
274 let mut weight = Weight::zero();
275 for_tuples!( #( weight = weight.saturating_add(Tuple::on_runtime_upgrade()); )* );
276 weight
277 }
278
279 /// Implements the default behavior of `try_on_runtime_upgrade` for tuples, logging any errors
280 /// that occur.
281 #[cfg(feature = "try-runtime")]
282 fn try_on_runtime_upgrade(checks: bool) -> Result<Weight, TryRuntimeError> {
283 let mut cumulative_weight = Weight::zero();
284
285 let mut errors = Vec::new();
286
287 for_tuples!(#(
288 match Tuple::try_on_runtime_upgrade(checks) {
289 Ok(weight) => { cumulative_weight.saturating_accrue(weight); },
290 Err(err) => { errors.push(err); },
291 }
292 )*);
293
294 if errors.len() == 1 {
295 return Err(errors[0])
296 } else if !errors.is_empty() {
297 log::error!(
298 target: "try-runtime",
299 "Detected multiple errors while executing `try_on_runtime_upgrade`:",
300 );
301
302 errors.iter().for_each(|err| {
303 log::error!(
304 target: "try-runtime",
305 "{:?}",
306 err
307 );
308 });
309
310 return Err("Detected multiple errors while executing `try_on_runtime_upgrade`, check the logs!".into())
311 }
312
313 Ok(cumulative_weight)
314 }
315
316 /// [`OnRuntimeUpgrade::pre_upgrade`] should not be used on a tuple.
317 ///
318 /// Instead, implementors should use [`OnRuntimeUpgrade::try_on_runtime_upgrade`] which
319 /// internally calls `pre_upgrade` -> `on_runtime_upgrade` -> `post_upgrade` for each tuple
320 /// member in sequence, enabling testing of order-dependent migrations.
321 #[cfg(feature = "try-runtime")]
322 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
323 Err("Usage of `pre_upgrade` with Tuples is not expected. Please use `try_on_runtime_upgrade` instead, which internally calls `pre_upgrade` -> `on_runtime_upgrade` -> `post_upgrade` for each tuple member.".into())
324 }
325
326 /// [`OnRuntimeUpgrade::post_upgrade`] should not be used on a tuple.
327 ///
328 /// Instead, implementors should use [`OnRuntimeUpgrade::try_on_runtime_upgrade`] which
329 /// internally calls `pre_upgrade` -> `on_runtime_upgrade` -> `post_upgrade` for each tuple
330 /// member in sequence, enabling testing of order-dependent migrations.
331 #[cfg(feature = "try-runtime")]
332 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
333 Err("Usage of `post_upgrade` with Tuples is not expected. Please use `try_on_runtime_upgrade` instead, which internally calls `pre_upgrade` -> `on_runtime_upgrade` -> `post_upgrade` for each tuple member.".into())
334 }
335}
336
337/// See [`Hooks::integrity_test`].
338#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
339#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
340#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
341pub trait IntegrityTest {
342 /// See [`Hooks::integrity_test`].
343 fn integrity_test() {}
344}
345
346#[cfg_attr(doc, aquamarine::aquamarine)]
347/// The pallet hooks trait. This is merely an umbrella trait for:
348///
349/// - [`OnInitialize`]
350/// - [`OnFinalize`]
351/// - [`OnRuntimeUpgrade`]
352/// - [`crate::traits::misc::OffchainWorker`]
353/// - [`OnIdle`]
354/// - [`IntegrityTest`]
355/// - [`OnPoll`]
356///
357/// ## Ordering
358///
359/// For all hooks, except [`OnIdle`] the order of execution is derived from how the pallets are
360/// ordered in [`crate::construct_runtime`].
361///
362/// ## Summary
363///
364/// In short, the following diagram shows the flow of hooks in a pallet
365///
366/// ```mermaid
367/// graph LR
368/// Optional --> Mandatory
369/// Mandatory --> ExtrinsicsMandatory
370/// ExtrinsicsMandatory --> Poll
371/// Poll --> Extrinsics
372/// Extrinsics --> AfterMandatory
373/// AfterMandatory --> onIdle
374///
375/// subgraph Optional
376/// OnRuntimeUpgrade
377/// end
378///
379/// subgraph Mandatory
380/// OnInitialize
381/// end
382///
383/// subgraph ExtrinsicsMandatory
384/// Inherent1 --> Inherent2
385/// end
386///
387/// subgraph Extrinsics
388/// direction TB
389/// Extrinsic1 --> Extrinsic2
390/// end
391///
392/// subgraph AfterMandatory
393/// OnFinalize
394/// end
395/// ```
396///
397/// * [`OnRuntimeUpgrade`](Hooks::OnRuntimeUpgrade) hooks are only executed when a code change is
398/// detected.
399/// * [`OnRuntimeUpgrade`](Hooks::OnRuntimeUpgrade) hooks are mandatorily executed at the very
400/// beginning of the block body, before any extrinsics are processed.
401/// * [`Inherents`](sp_inherents) are always executed before any other other signed or unsigned
402/// extrinsics.
403/// * [`OnIdle`](Hooks::OnIdle) hooks are executed after extrinsics if there is weight remaining in
404/// the block.
405/// * [`OnFinalize`](Hooks::OnFinalize) hooks are mandatorily executed after
406/// [`OnIdle`](Hooks::OnIdle).
407///
408/// > [`OffchainWorker`](crate::traits::misc::OffchainWorker) hooks are not part of this flow,
409/// > because they are not part of the consensus/main block building logic. See
410/// > [`OffchainWorker`](crate::traits::misc::OffchainWorker) for more information.
411///
412/// To learn more about the execution of hooks see the FRAME `Executive` pallet which is in charge
413/// of dispatching extrinsics and calling hooks in the correct order.
414pub trait Hooks<BlockNumber> {
415 /// Block initialization hook. This is called at the very beginning of block execution.
416 ///
417 /// Must return the non-negotiable weight of both itself and whatever [`Hooks::on_finalize`]
418 /// wishes to consume.
419 ///
420 /// ## Warning
421 ///
422 /// The weight returned by this is treated as `DispatchClass::Mandatory`, meaning that
423 /// it MUST BE EXECUTED. If this is not the case, consider using [`Hooks::on_idle`] instead.
424 ///
425 /// Try to keep any arbitrary execution __deterministic__ and within __minimal__ time
426 /// complexity. For example, do not execute any unbounded iterations.
427 ///
428 /// NOTE: This function is called BEFORE ANY extrinsic in a block is applied, including inherent
429 /// extrinsics. Hence for instance, if you runtime includes `pallet-timestamp`, the `timestamp`
430 /// is not yet up to date at this point.
431 fn on_initialize(_n: BlockNumber) -> Weight {
432 Weight::zero()
433 }
434
435 /// Block finalization hook. This is called at the very end of block execution.
436 ///
437 /// Note that this has nothing to do with finality in the "consensus" sense.
438 ///
439 /// Note that the non-negotiable weight for this has must have already been returned by
440 /// [`Hooks::on_initialize`]. It usage alone is not permitted.
441 ///
442 /// Similar to [`Hooks::on_initialize`] it should only be used when execution is absolutely
443 /// necessary. In other cases, consider using [`Hooks::on_idle`] instead.
444 fn on_finalize(_n: BlockNumber) {}
445
446 /// Hook to consume a block's idle time. This will run when the block is being finalized (before
447 /// [`Hooks::on_finalize`]).
448 ///
449 /// Given that all dispatchables are already executed and noted (and the weight for
450 /// [`Hooks::on_finalize`], which comes next, is also already accounted for via
451 /// `on_initialize`), this hook consumes anything that is leftover.
452 ///
453 /// Each pallet's `on_idle` is chosen to be the first to execute in a round-robin fashion
454 /// indexed by the block number.
455 ///
456 /// Return the weight used, the caller will use this to calculate the remaining weight and then
457 /// call the next pallet `on_idle` hook if there is still weight left.
458 ///
459 /// Any implementation should always respect `_remaining_weight` and never consume (and
460 /// therefore return) more than this amount.
461 fn on_idle(_n: BlockNumber, _remaining_weight: Weight) -> Weight {
462 Weight::zero()
463 }
464
465 /// A hook to run logic after inherent application.
466 ///
467 /// Is not guaranteed to execute in a block and should therefore only be used in no-deadline
468 /// scenarios.
469 ///
470 /// This is the non-mandatory version of [`Hooks::on_initialize`].
471 fn on_poll(_n: BlockNumber, _weight: &mut WeightMeter) {}
472
473 /// Hook executed when a code change (aka. a "runtime upgrade") is detected by the FRAME
474 /// `Executive` pallet.
475 ///
476 /// Be aware that this is called before [`Hooks::on_initialize`] of any pallet; therefore, a lot
477 /// of the critical storage items such as `block_number` in system pallet might have not been
478 /// set yet.
479 ///
480 /// Similar to [`Hooks::on_initialize`], any code in this block is mandatory and MUST execute.
481 /// It is strongly recommended to dry-run the execution of these hooks using
482 /// [try-runtime-cli](https://github.com/paritytech/try-runtime-cli) to ensure they will not
483 /// produce and overweight block which can brick your chain. Use with care!
484 ///
485 /// ## Implementation Note: Standalone Migrations
486 ///
487 /// Additional migrations can be created by directly implementing [`OnRuntimeUpgrade`] on
488 /// structs and passing them to `Executive`. Or alternatively, by implementing
489 /// [`UncheckedOnRuntimeUpgrade`], passing it to [`crate::migrations::VersionedMigration`],
490 /// which already implements [`OnRuntimeUpgrade`].
491 ///
492 /// ## Implementation Note: Pallet Versioning
493 ///
494 /// Implementations of this hook are typically wrapped in
495 /// [`crate::migrations::VersionedMigration`] to ensure the migration is executed exactly
496 /// once and only when it is supposed to.
497 ///
498 /// Alternatively, developers can manually implement version checks.
499 ///
500 /// Failure to adequately check storage versions can result in accidental repetitive execution
501 /// of the hook, which can be catastrophic.
502 ///
503 /// ## Implementation Note: Weight
504 ///
505 /// Typically, implementations of this method are simple enough that weights can be calculated
506 /// manually. However, if required, a benchmark can also be used.
507 fn on_runtime_upgrade() -> Weight {
508 Weight::zero()
509 }
510
511 /// Execute the sanity checks of this pallet, per block.
512 ///
513 /// It should focus on certain checks to ensure that the state is sensible. This is never
514 /// executed in a consensus code-path, therefore it can consume as much weight as it needs.
515 ///
516 /// This hook must not alter any storage.
517 #[cfg(feature = "try-runtime")]
518 fn try_state(_n: BlockNumber) -> Result<(), TryRuntimeError> {
519 Ok(())
520 }
521
522 /// Execute some pre-checks prior to a runtime upgrade.
523 ///
524 /// Return a `Vec<u8>` that can contain arbitrary encoded data (usually some pre-upgrade state),
525 /// which will be passed to `post_upgrade` after upgrading for post-check. An empty vector
526 /// should be returned if there is no such need.
527 ///
528 /// This hook is never executed on-chain but instead used by testing tools.
529 #[cfg(feature = "try-runtime")]
530 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
531 Ok(Vec::new())
532 }
533
534 /// Execute some post-checks after a runtime upgrade.
535 ///
536 /// The `state` parameter is the `Vec<u8>` returned by `pre_upgrade` before upgrading, which
537 /// can be used for post-check. NOTE: if `pre_upgrade` is not implemented an empty vector will
538 /// be passed in, in such case `post_upgrade` should ignore it.
539 ///
540 /// This hook is never meant to be executed on-chain but is meant to be used by testing tools.
541 #[cfg(feature = "try-runtime")]
542 fn post_upgrade(_state: Vec<u8>) -> Result<(), TryRuntimeError> {
543 Ok(())
544 }
545
546 /// Implementing this function on a pallet allows you to perform long-running tasks that are
547 /// dispatched as separate threads, and entirely independent of the main blockchain execution.
548 ///
549 /// This function can freely read from the state, but any change it makes to the state is
550 /// meaningless. Writes can be pushed back to the chain by submitting extrinsics from the
551 /// offchain worker to the transaction pool. See `pallet-example-offchain-worker` for more
552 /// details on this.
553 ///
554 /// Moreover, the code in this function has access to a wider range of host functions in
555 /// [`sp-io`], namely [`sp_io::offchain`]. This includes exotic operations such as HTTP calls
556 /// that are not really possible in the rest of the runtime code.
557 ///
558 /// The execution of this hook is entirely optional and is left at the discretion of the
559 /// node-side software and its configuration. In a normal substrate-cli, look for the CLI
560 /// flags related to offchain-workers to learn more.
561 fn offchain_worker(_n: BlockNumber) {}
562
563 /// Check the integrity of this pallet's configuration.
564 ///
565 /// Any code located in this hook is placed in an auto-generated test, and generated as a part
566 /// of [`crate::construct_runtime`]'s expansion. Look for a test case with a name along the
567 /// lines of: `__construct_runtime_integrity_test`.
568 ///
569 /// This hook is the location where the values/types provided to the `Config` trait
570 /// of the pallet can be tested for correctness. For example, if two `type Foo: Get<u32>` and
571 /// `type Bar: Get<u32>` where `Foo::get()` must always be greater than `Bar::get()`, such
572 /// checks can be asserted upon here.
573 ///
574 /// Note that this hook is executed in an externality environment, provided by
575 /// `sp_io::TestExternalities`. This makes it possible to access the storage.
576 fn integrity_test() {}
577}
578
579/// A trait to define the build function of a genesis config for both runtime and pallets.
580///
581/// Replaces deprecated [`GenesisBuild<T,I>`].
582pub trait BuildGenesisConfig: sp_runtime::traits::MaybeSerializeDeserialize {
583 /// The build function puts initial `GenesisConfig` keys/values pairs into the storage.
584 fn build(&self);
585}
586
587impl BuildGenesisConfig for () {
588 fn build(&self) {}
589}
590
591/// A trait to define the build function of a genesis config, T and I are placeholder for pallet
592/// trait and pallet instance.
593#[deprecated(
594 note = "GenesisBuild is planned to be removed in December 2023. Use BuildGenesisConfig instead of it."
595)]
596pub trait GenesisBuild<T, I = ()>: sp_runtime::traits::MaybeSerializeDeserialize {
597 /// The build function is called within an externalities allowing storage APIs.
598 /// Thus one can write to storage using regular pallet storages.
599 fn build(&self);
600
601 /// Build the storage using `build` inside default storage.
602 #[cfg(feature = "std")]
603 fn build_storage(&self) -> Result<sp_runtime::Storage, String> {
604 let mut storage = Default::default();
605 self.assimilate_storage(&mut storage)?;
606 Ok(storage)
607 }
608
609 /// Assimilate the storage for this module into pre-existing overlays.
610 #[cfg(feature = "std")]
611 fn assimilate_storage(&self, storage: &mut sp_runtime::Storage) -> Result<(), String> {
612 sp_state_machine::BasicExternalities::execute_with_storage(storage, || {
613 self.build();
614 Ok(())
615 })
616 }
617}
618
619/// A trait which is called when the timestamp is set in the runtime.
620#[cfg_attr(all(not(feature = "tuples-96"), not(feature = "tuples-128")), impl_for_tuples(64))]
621#[cfg_attr(all(feature = "tuples-96", not(feature = "tuples-128")), impl_for_tuples(96))]
622#[cfg_attr(feature = "tuples-128", impl_for_tuples(128))]
623pub trait OnTimestampSet<Moment> {
624 /// Called when the timestamp is set.
625 fn on_timestamp_set(moment: Moment);
626}
627
628#[cfg(test)]
629mod tests {
630 use super::*;
631 use crate::parameter_types;
632 use alloc::vec::Vec;
633 use sp_io::TestExternalities;
634
635 #[cfg(feature = "try-runtime")]
636 #[test]
637 fn on_runtime_upgrade_pre_post_executed_tuple() {
638 crate::parameter_types! {
639 pub static Pre: Vec<&'static str> = Default::default();
640 pub static Post: Vec<&'static str> = Default::default();
641 }
642
643 macro_rules! impl_test_type {
644 ($name:ident) => {
645 struct $name;
646 impl OnRuntimeUpgrade for $name {
647 fn on_runtime_upgrade() -> Weight {
648 Default::default()
649 }
650
651 #[cfg(feature = "try-runtime")]
652 fn pre_upgrade() -> Result<Vec<u8>, TryRuntimeError> {
653 Pre::mutate(|s| s.push(stringify!($name)));
654 Ok(Vec::new())
655 }
656
657 #[cfg(feature = "try-runtime")]
658 fn post_upgrade(_: Vec<u8>) -> Result<(), TryRuntimeError> {
659 Post::mutate(|s| s.push(stringify!($name)));
660 Ok(())
661 }
662 }
663 };
664 }
665
666 impl_test_type!(Foo);
667 impl_test_type!(Bar);
668 impl_test_type!(Baz);
669
670 TestExternalities::default().execute_with(|| {
671 // try_on_runtime_upgrade works
672 Foo::try_on_runtime_upgrade(true).unwrap();
673 assert_eq!(Pre::take(), vec!["Foo"]);
674 assert_eq!(Post::take(), vec!["Foo"]);
675
676 <(Foo, Bar, Baz)>::try_on_runtime_upgrade(true).unwrap();
677 assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
678 assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
679
680 <((Foo, Bar), Baz)>::try_on_runtime_upgrade(true).unwrap();
681 assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
682 assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
683
684 <(Foo, (Bar, Baz))>::try_on_runtime_upgrade(true).unwrap();
685 assert_eq!(Pre::take(), vec!["Foo", "Bar", "Baz"]);
686 assert_eq!(Post::take(), vec!["Foo", "Bar", "Baz"]);
687
688 // calling pre_upgrade and post_upgrade directly on tuple of pallets fails
689 assert!(<(Foo, (Bar, Baz))>::pre_upgrade().is_err());
690 assert!(<(Foo, (Bar, Baz))>::post_upgrade(vec![]).is_err());
691 });
692 }
693
694 #[test]
695 fn on_initialize_and_on_runtime_upgrade_weight_merge_works() {
696 struct Test;
697
698 impl OnInitialize<u8> for Test {
699 fn on_initialize(_n: u8) -> Weight {
700 Weight::from_parts(10, 0)
701 }
702 }
703 impl OnRuntimeUpgrade for Test {
704 fn on_runtime_upgrade() -> Weight {
705 Weight::from_parts(20, 0)
706 }
707 }
708
709 TestExternalities::default().execute_with(|| {
710 assert_eq!(<(Test, Test)>::on_initialize(0), Weight::from_parts(20, 0));
711 assert_eq!(<(Test, Test)>::on_runtime_upgrade(), Weight::from_parts(40, 0));
712 });
713 }
714
715 #[test]
716 fn on_idle_round_robin_works() {
717 parameter_types! {
718 static OnIdleInvocationOrder: Vec<&'static str> = Vec::new();
719 }
720
721 struct Test1;
722 struct Test2;
723 struct Test3;
724 type TestTuple = (Test1, Test2, Test3);
725 impl OnIdle<u32> for Test1 {
726 fn on_idle(_n: u32, _weight: Weight) -> Weight {
727 OnIdleInvocationOrder::mutate(|o| o.push("Test1"));
728 Weight::zero()
729 }
730 }
731 impl OnIdle<u32> for Test2 {
732 fn on_idle(_n: u32, _weight: Weight) -> Weight {
733 OnIdleInvocationOrder::mutate(|o| o.push("Test2"));
734 Weight::zero()
735 }
736 }
737 impl OnIdle<u32> for Test3 {
738 fn on_idle(_n: u32, _weight: Weight) -> Weight {
739 OnIdleInvocationOrder::mutate(|o| o.push("Test3"));
740 Weight::zero()
741 }
742 }
743
744 TestTuple::on_idle(0, Weight::zero());
745 assert_eq!(OnIdleInvocationOrder::get(), ["Test1", "Test2", "Test3"].to_vec());
746 OnIdleInvocationOrder::mutate(|o| o.clear());
747
748 TestTuple::on_idle(1, Weight::zero());
749 assert_eq!(OnIdleInvocationOrder::get(), ["Test2", "Test3", "Test1"].to_vec());
750 OnIdleInvocationOrder::mutate(|o| o.clear());
751
752 TestTuple::on_idle(2, Weight::zero());
753 assert_eq!(OnIdleInvocationOrder::get(), ["Test3", "Test1", "Test2"].to_vec());
754 OnIdleInvocationOrder::mutate(|o| o.clear());
755
756 TestTuple::on_idle(3, Weight::zero());
757 assert_eq!(OnIdleInvocationOrder::get(), ["Test1", "Test2", "Test3"].to_vec());
758 OnIdleInvocationOrder::mutate(|o| o.clear());
759
760 TestTuple::on_idle(4, Weight::zero());
761 assert_eq!(OnIdleInvocationOrder::get(), ["Test2", "Test3", "Test1"].to_vec());
762 OnIdleInvocationOrder::mutate(|o| o.clear());
763 }
764}