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