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