Skip to main content

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