referrerpolicy=no-referrer-when-downgrade

frame_executive/
lib.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#![cfg_attr(not(feature = "std"), no_std)]
19
20//! # Executive Module
21//!
22//! The Executive module acts as the orchestration layer for the runtime. It dispatches incoming
23//! extrinsic calls to the respective modules in the runtime.
24//!
25//! ## Overview
26//!
27//! The executive module is not a typical pallet providing functionality around a specific feature.
28//! It is a cross-cutting framework component for the FRAME. It works in conjunction with the
29//! [FRAME System module](../frame_system/index.html) to perform these cross-cutting functions.
30//!
31//! The Executive module provides functions to:
32//!
33//! - Check transaction validity.
34//! - Initialize a block.
35//! - Apply extrinsics.
36//! - Execute a block.
37//! - Finalize a block.
38//! - Start an off-chain worker.
39//!
40//! The flow of their application in a block is explained in the [block flowchart](block_flowchart).
41//!
42//! ### Implementations
43//!
44//! The Executive module provides the following implementations:
45//!
46//! - `ExecuteBlock`: Trait that can be used to execute a block.
47//! - `Executive`: Type that can be used to make the FRAME available from the runtime.
48//!
49//! ## Usage
50//!
51//! The default Substrate node template declares the [`Executive`](./struct.Executive.html) type in
52//! its library.
53//!
54//! ### Example
55//!
56//! `Executive` type declaration from the node template.
57//!
58//! ```
59//! # use sp_runtime::generic;
60//! # use frame_executive as executive;
61//! # pub struct UncheckedExtrinsic {};
62//! # pub struct Header {};
63//! # type Context = frame_system::ChainContext<Runtime>;
64//! # pub type Block = generic::Block<Header, UncheckedExtrinsic>;
65//! # pub type Balances = u64;
66//! # pub type AllPalletsWithSystem = u64;
67//! # pub enum Runtime {};
68//! # use sp_runtime::transaction_validity::{
69//! #    TransactionValidity, UnknownTransaction, TransactionSource,
70//! # };
71//! /// Executive: handles dispatch to the various modules.
72//! pub type Executive = executive::Executive<Runtime, Block, Context, Runtime, AllPalletsWithSystem>;
73//! ```
74
75#[cfg(doc)]
76#[cfg_attr(doc, aquamarine::aquamarine)]
77/// # Block Execution
78///
79/// These are the steps of block execution as done by [`Executive::execute_block`]. A block is
80/// invalid if any of them fail.
81///
82/// ```mermaid
83/// flowchart TD
84///     Executive::execute_block --> on_runtime_upgrade
85///     on_runtime_upgrade --> System::initialize
86///     Executive::initialize_block --> System::initialize
87///     System::initialize --> on_initialize
88///     on_initialize --> PreInherents[System::PreInherents]
89///     PreInherents --> Inherents[Apply Inherents]
90///     Inherents --> PostInherents[System::PostInherents]
91///     PostInherents --> Check{MBM ongoing?}
92///     Check -->|No| poll
93///     Check -->|Yes| post_transactions_2[System::PostTransaction]
94///     post_transactions_2 --> Step[MBMs::step]
95///     Step --> on_finalize
96///     poll --> transactions[Apply Transactions]
97///     transactions --> post_transactions_1[System::PostTransaction]
98///     post_transactions_1 --> CheckIdle{Weight remaining?}
99///     CheckIdle -->|Yes| on_idle
100///     CheckIdle -->|No| on_finalize
101///     on_idle --> on_finalize
102/// ```
103pub mod block_flowchart {}
104
105#[cfg(test)]
106mod tests;
107
108extern crate alloc;
109
110use codec::{Codec, Encode};
111use core::marker::PhantomData;
112use frame_support::{
113	defensive_assert,
114	dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo},
115	migrations::MultiStepMigrator,
116	pallet_prelude::InvalidTransaction,
117	traits::{
118		BeforeAllRuntimeMigrations, ExecuteBlock, Get, IsInherent, OffchainWorker, OnFinalize,
119		OnIdle, OnInitialize, OnPoll, OnRuntimeUpgrade, PostInherents, PostTransactions,
120		PreInherents,
121	},
122	weights::{Weight, WeightMeter},
123	MAX_EXTRINSIC_DEPTH,
124};
125use frame_system::pallet_prelude::BlockNumberFor;
126use sp_runtime::{
127	generic::Digest,
128	traits::{
129		self, Applyable, CheckEqual, Checkable, Dispatchable, Header, LazyBlock, NumberFor, One,
130		Zero,
131	},
132	transaction_validity::{TransactionSource, TransactionValidity, TransactionValidityError},
133	ApplyExtrinsicResult, ExtrinsicInclusionMode,
134};
135
136#[allow(deprecated)]
137use sp_runtime::traits::ValidateUnsigned;
138
139#[cfg(feature = "try-runtime")]
140use ::{
141	frame_support::{
142		traits::{TryDecodeEntireStorage, TryDecodeEntireStorageError, TryState},
143		StorageNoopGuard,
144	},
145	frame_try_runtime::{TryStateSelect, UpgradeCheckSelect},
146	log,
147	sp_runtime::TryRuntimeError,
148};
149
150#[allow(dead_code)]
151const LOG_TARGET: &str = "runtime::executive";
152
153pub type CheckedOf<E, C> = <E as Checkable<C>>::Checked;
154pub type CallOf<E, C> = <CheckedOf<E, C> as Applyable>::Call;
155pub type OriginOf<E, C> = <CallOf<E, C> as Dispatchable>::RuntimeOrigin;
156
157/// Configuration for try-runtime upgrade checks.
158#[cfg(feature = "try-runtime")]
159#[derive(Debug, Clone)]
160pub struct TryRuntimeUpgradeConfig {
161	/// Whether to execute `pre/post_upgrade` and `try_state` hooks.
162	pub checks: UpgradeCheckSelect,
163	/// Which pallets' try_state hooks to execute.
164	pub try_state_select: TryStateSelect,
165}
166
167#[cfg(feature = "try-runtime")]
168impl TryRuntimeUpgradeConfig {
169	/// Create a new config with default settings (run all checks for all pallets).
170	pub fn new(checks: UpgradeCheckSelect) -> Self {
171		Self { checks, try_state_select: TryStateSelect::All }
172	}
173
174	/// Set which pallets' try_state hooks to execute.
175	pub fn with_try_state_select(mut self, try_state_select: TryStateSelect) -> Self {
176		self.try_state_select = try_state_select;
177		self
178	}
179}
180
181#[derive(PartialEq)]
182pub enum ExecutiveError {
183	UnableToDecodeExtrinsic,
184	InvalidInherentPosition(usize),
185	OnlyInherentsAllowed,
186	ApplyExtrinsic(TransactionValidityError),
187	Custom(&'static str),
188}
189
190impl core::fmt::Debug for ExecutiveError {
191	fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
192		match self {
193			ExecutiveError::UnableToDecodeExtrinsic => {
194				write!(fmt, "The extrinsic could not be decoded correctly")
195			},
196			ExecutiveError::InvalidInherentPosition(i) => {
197				write!(fmt, "Invalid inherent position for extrinsic at index {}", i)
198			},
199			ExecutiveError::OnlyInherentsAllowed => {
200				write!(fmt, "Only inherents are allowed in this block")
201			},
202			ExecutiveError::ApplyExtrinsic(e) => write!(
203				fmt,
204				"ExecuteBlockError applying extrinsic: {}",
205				Into::<&'static str>::into(*e)
206			),
207			ExecutiveError::Custom(err) => write!(fmt, "{err}"),
208		}
209	}
210}
211
212/// Main entry point for certain runtime actions as e.g. `execute_block`.
213///
214/// Generic parameters:
215/// - `System`: Something that implements `frame_system::Config`
216/// - `Block`: The block type of the runtime
217/// - `Context`: The context that is used when checking an extrinsic.
218/// - `UnsignedValidator`: The unsigned transaction validator of the runtime.
219/// - `AllPalletsWithSystem`: Tuple that contains all pallets including frame system pallet. Will be
220///   used to call hooks e.g. `on_initialize`.
221/// - [**DEPRECATED** `OnRuntimeUpgrade`]: This parameter is deprecated and will be removed after
222///   September 2026. Use type `SingleBlockMigrations` in frame_system::Config instead.
223#[allow(deprecated)]
224pub struct Executive<
225	System,
226	Block,
227	Context,
228	UnsignedValidator,
229	AllPalletsWithSystem,
230	OnRuntimeUpgrade = (),
231>(
232	PhantomData<(
233		System,
234		Block,
235		Context,
236		UnsignedValidator,
237		AllPalletsWithSystem,
238		OnRuntimeUpgrade,
239	)>,
240);
241
242/// TODO: The `OnRuntimeUpgrade` generic parameter in `Executive` is deprecated and will be
243/// removed in a future version. Once removed, this `#[allow(deprecated)]` attribute
244/// can be safely deleted.
245#[allow(deprecated)]
246impl<
247		System: frame_system::Config + IsInherent<Block::Extrinsic>,
248		Block: traits::Block<
249			Header = frame_system::pallet_prelude::HeaderFor<System>,
250			Hash = System::Hash,
251		>,
252		Context: Default,
253		UnsignedValidator,
254		AllPalletsWithSystem: OnRuntimeUpgrade
255			+ BeforeAllRuntimeMigrations
256			+ OnInitializeWithWeightRegistration<System>
257			+ OnIdle<BlockNumberFor<System>>
258			+ OnFinalize<BlockNumberFor<System>>
259			+ OffchainWorker<BlockNumberFor<System>>
260			+ OnPoll<BlockNumberFor<System>>,
261		COnRuntimeUpgrade: OnRuntimeUpgrade,
262	> ExecuteBlock<Block>
263	for Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
264where
265	Block::Extrinsic: Checkable<Context> + Codec,
266	CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
267	CallOf<Block::Extrinsic, Context>:
268		Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
269	OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
270	UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
271{
272	fn verify_and_remove_seal(_: &mut <Block as traits::Block>::LazyBlock) {
273		// Nothing to do here.
274	}
275
276	fn execute_verified_block(block: Block::LazyBlock) {
277		Executive::<
278			System,
279			Block,
280			Context,
281			UnsignedValidator,
282			AllPalletsWithSystem,
283			COnRuntimeUpgrade,
284		>::execute_block(block);
285	}
286}
287
288/// TODO: The `OnRuntimeUpgrade` generic parameter in `Executive` is deprecated and will be
289/// removed in a future version. Once removed, this `#[allow(deprecated)]` attribute
290/// can be safely deleted.
291#[allow(deprecated)]
292#[cfg(feature = "try-runtime")]
293impl<
294		System: frame_system::Config + IsInherent<Block::Extrinsic>,
295		Block: traits::Block<
296			Header = frame_system::pallet_prelude::HeaderFor<System>,
297			Hash = System::Hash,
298		>,
299		Context: Default,
300		UnsignedValidator,
301		AllPalletsWithSystem: OnRuntimeUpgrade
302			+ BeforeAllRuntimeMigrations
303			+ OnInitializeWithWeightRegistration<System>
304			+ OnIdle<BlockNumberFor<System>>
305			+ OnFinalize<BlockNumberFor<System>>
306			+ OffchainWorker<BlockNumberFor<System>>
307			+ OnPoll<BlockNumberFor<System>>
308			+ TryState<BlockNumberFor<System>>
309			+ TryDecodeEntireStorage,
310		COnRuntimeUpgrade: OnRuntimeUpgrade,
311	> Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
312where
313	Block::Extrinsic: Checkable<Context> + Codec,
314	CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
315	CallOf<Block::Extrinsic, Context>:
316		Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
317	OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
318	UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
319{
320	/// Execute given block, but don't as strict is the normal block execution.
321	///
322	/// Some checks can be disabled via:
323	///
324	/// - `state_root_check`
325	/// - `signature_check`
326	///
327	/// Should only be used for testing ONLY.
328	pub fn try_execute_block(
329		block: Block::LazyBlock,
330		state_root_check: bool,
331		signature_check: bool,
332		select: frame_try_runtime::TryStateSelect,
333	) -> Result<Weight, ExecutiveError> {
334		log::info!(
335			target: LOG_TARGET,
336			"try-runtime: executing block #{:?} / state root check: {:?} / signature check: {:?} / try-state-select: {:?}",
337			block.header().number(),
338			state_root_check,
339			signature_check,
340			select,
341		);
342
343		let mode = Self::initialize_block(block.header());
344		Self::initial_checks(block.header());
345
346		// Apply extrinsics:
347		let signature_check = if signature_check {
348			Block::Extrinsic::check
349		} else {
350			Block::Extrinsic::unchecked_into_checked_i_know_what_i_am_doing
351		};
352		Self::apply_extrinsics(mode, block.extrinsics(), |uxt, is_inherent| {
353			Self::do_apply_extrinsic(uxt, is_inherent, signature_check)
354		})?;
355
356		// In this case there were no transactions to trigger this state transition:
357		if !<frame_system::Pallet<System>>::inherents_applied() {
358			Self::inherents_applied();
359		}
360
361		// post-extrinsics book-keeping
362		<frame_system::Pallet<System>>::note_finished_extrinsics();
363		<System as frame_system::Config>::PostTransactions::post_transactions();
364
365		let header = block.header();
366		Self::on_idle_hook(*header.number());
367		Self::on_finalize_hook(*header.number());
368
369		// run the try-state checks of all pallets, ensuring they don't alter any state.
370		let _guard = frame_support::StorageNoopGuard::default();
371		<AllPalletsWithSystem as frame_support::traits::TryState<
372			BlockNumberFor<System>,
373		>>::try_state(*header.number(), select.clone())
374		.map_err(|e| {
375			log::error!(target: LOG_TARGET, "failure: {:?}", e);
376			ExecutiveError::Custom(e.into())
377		})?;
378		if select.any() {
379			let res = AllPalletsWithSystem::try_decode_entire_state();
380			Self::log_decode_result(res).map_err(|e| ExecutiveError::Custom(e.into()))?;
381		}
382		drop(_guard);
383
384		// do some of the checks that would normally happen in `final_checks`, but perhaps skip
385		// the state root check.
386		{
387			let new_header = <frame_system::Pallet<System>>::finalize();
388			let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
389			for (header_item, computed_item) in items_zip {
390				header_item.check_equal(computed_item);
391				assert!(header_item == computed_item, "Digest item must match that calculated.");
392			}
393
394			if state_root_check {
395				let storage_root = new_header.state_root();
396				header.state_root().check_equal(storage_root);
397				assert!(
398					header.state_root() == storage_root,
399					"Storage root must match that calculated."
400				);
401			}
402
403			assert!(
404				header.extrinsics_root() == new_header.extrinsics_root(),
405				"Transaction trie root must be valid.",
406			);
407		}
408
409		log::info!(
410			target: LOG_TARGET,
411			"try-runtime: Block #{:?} successfully executed",
412			header.number(),
413		);
414
415		Ok(frame_system::Pallet::<System>::block_weight().total())
416	}
417
418	/// Execute all Migrations of this runtime.
419	///
420	/// The `checks` param determines whether to execute `pre/post_upgrade` and `try_state` hooks.
421	///
422	/// [`frame_system::LastRuntimeUpgrade`] is set to the current runtime version after
423	/// migrations execute. This is important for idempotency checks, because some migrations use
424	/// this value to determine whether or not they should execute.
425	///
426	/// This function runs `try_state` hooks for all pallets. Use
427	/// [`Self::try_runtime_upgrade_with_config`] if you need more control over which pallets'
428	/// `try_state` hooks to execute.
429	pub fn try_runtime_upgrade(checks: UpgradeCheckSelect) -> Result<Weight, TryRuntimeError> {
430		Self::try_runtime_upgrade_with_config(TryRuntimeUpgradeConfig::new(checks))
431	}
432
433	/// Execute all Migrations of this runtime with custom configuration.
434	///
435	/// This function provides more granular control over runtime upgrade testing compared to
436	/// [`Self::try_runtime_upgrade`]. Use [`TryRuntimeUpgradeConfig`] to specify which checks
437	/// to run and which pallets' try_state hooks to execute.
438	///
439	/// [`frame_system::LastRuntimeUpgrade`] is set to the current runtime version after
440	/// migrations execute. This is important for idempotency checks, because some migrations use
441	/// this value to determine whether or not they should execute.
442	pub fn try_runtime_upgrade_with_config(
443		config: TryRuntimeUpgradeConfig,
444	) -> Result<Weight, TryRuntimeError> {
445		let checks = config.checks;
446		let try_state_select = config.try_state_select;
447		let before_all_weight =
448			<AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
449
450		let try_on_runtime_upgrade_weight =
451			<(
452				COnRuntimeUpgrade,
453				<System as frame_system::Config>::SingleBlockMigrations,
454				// We want to run the migrations before we call into the pallets as they may
455				// access any state that would then not be migrated.
456				AllPalletsWithSystem,
457			) as OnRuntimeUpgrade>::try_on_runtime_upgrade(checks.pre_and_post())?;
458
459		frame_system::LastRuntimeUpgrade::<System>::put(
460			frame_system::LastRuntimeUpgradeInfo::from(
461				<System::Version as frame_support::traits::Get<_>>::get(),
462			),
463		);
464
465		// Nothing should modify the state after the migrations ran:
466		let _guard = StorageNoopGuard::default();
467
468		// The state must be decodable:
469		if checks.any() {
470			let res = AllPalletsWithSystem::try_decode_entire_state();
471			Self::log_decode_result(res)?;
472		}
473
474		// Check all storage invariants:
475		if checks.try_state() {
476			AllPalletsWithSystem::try_state(
477				frame_system::Pallet::<System>::block_number(),
478				try_state_select,
479			)?;
480		}
481
482		Ok(before_all_weight.saturating_add(try_on_runtime_upgrade_weight))
483	}
484
485	/// Logs the result of trying to decode the entire state.
486	fn log_decode_result(
487		res: Result<usize, alloc::vec::Vec<TryDecodeEntireStorageError>>,
488	) -> Result<(), TryRuntimeError> {
489		match res {
490			Ok(bytes) => {
491				log::info!(
492					target: LOG_TARGET,
493					"✅ Entire runtime state decodes without error. {} bytes total.",
494					bytes
495				);
496
497				Ok(())
498			},
499			Err(errors) => {
500				log::error!(
501					target: LOG_TARGET,
502					"`try_decode_entire_state` failed with {} errors",
503					errors.len(),
504				);
505
506				for (i, err) in errors.iter().enumerate() {
507					// We log the short version to `error` and then the full debug info to `debug`:
508					log::error!(target: LOG_TARGET, "- {i}. error: {err}");
509					log::debug!(target: LOG_TARGET, "- {i}. error: {err:?}");
510				}
511
512				Err("`try_decode_entire_state` failed".into())
513			},
514		}
515	}
516}
517
518/// Extension trait for [`OnInitialize`].
519///
520/// It takes care to register the weight of each pallet directly after executing its
521/// `on_initialize`.
522///
523/// The trait is sealed.
524pub trait OnInitializeWithWeightRegistration<T: frame_system::Config> {
525	/// The actual logic that calls `on_initialize` and registers the weight.
526	fn on_initialize_with_weight_registration(_n: BlockNumberFor<T>) -> Weight;
527}
528
529frame_support::impl_for_tuples_attr! {
530	#[tuple_types_custom_trait_bound(OnInitialize<frame_system::pallet_prelude::BlockNumberFor<T>>)]
531	impl<T: frame_system::Config> OnInitializeWithWeightRegistration<T> for Tuple {
532		fn on_initialize_with_weight_registration(n: BlockNumberFor<T>) -> Weight {
533			let mut weight = Weight::zero();
534			for_tuples!( #(
535				let individual_weight = Tuple::on_initialize(n);
536
537				<frame_system::Pallet<T>>::register_extra_weight_unchecked(
538					individual_weight,
539					DispatchClass::Mandatory,
540				);
541
542				weight = weight.saturating_add(individual_weight);
543			)* );
544
545			weight
546		}
547	}
548}
549
550/// TODO: The `OnRuntimeUpgrade` generic parameter in `Executive` is deprecated and will be
551/// removed in a future version. Once removed, this `#[allow(deprecated)]` attribute
552/// can be safely deleted.
553#[allow(deprecated)]
554impl<
555		System: frame_system::Config + IsInherent<Block::Extrinsic>,
556		Block: traits::Block<
557			Header = frame_system::pallet_prelude::HeaderFor<System>,
558			Hash = System::Hash,
559		>,
560		Context: Default,
561		UnsignedValidator,
562		AllPalletsWithSystem: OnRuntimeUpgrade
563			+ BeforeAllRuntimeMigrations
564			+ OnInitializeWithWeightRegistration<System>
565			+ OnIdle<BlockNumberFor<System>>
566			+ OnFinalize<BlockNumberFor<System>>
567			+ OffchainWorker<BlockNumberFor<System>>
568			+ OnPoll<BlockNumberFor<System>>,
569		COnRuntimeUpgrade: OnRuntimeUpgrade,
570	> Executive<System, Block, Context, UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade>
571where
572	Block::Extrinsic: Checkable<Context> + Codec,
573	CheckedOf<Block::Extrinsic, Context>: Applyable + GetDispatchInfo,
574	CallOf<Block::Extrinsic, Context>:
575		Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo>,
576	OriginOf<Block::Extrinsic, Context>: From<Option<System::AccountId>>,
577	UnsignedValidator: ValidateUnsigned<Call = CallOf<Block::Extrinsic, Context>>,
578{
579	/// Execute all `OnRuntimeUpgrade` of this runtime, and return the aggregate weight.
580	pub fn execute_on_runtime_upgrade() -> Weight {
581		let before_all_weight =
582			<AllPalletsWithSystem as BeforeAllRuntimeMigrations>::before_all_runtime_migrations();
583
584		let runtime_upgrade_weight = <(
585			COnRuntimeUpgrade,
586			<System as frame_system::Config>::SingleBlockMigrations,
587			// We want to run the migrations before we call into the pallets as they may
588			// access any state that would then not be migrated.
589			AllPalletsWithSystem,
590		) as OnRuntimeUpgrade>::on_runtime_upgrade();
591
592		before_all_weight.saturating_add(runtime_upgrade_weight)
593	}
594
595	/// Start the execution of a particular block.
596	pub fn initialize_block(
597		header: &frame_system::pallet_prelude::HeaderFor<System>,
598	) -> ExtrinsicInclusionMode {
599		sp_io::init_tracing();
600		sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block");
601		let digests = Self::extract_pre_digest(header);
602		Self::initialize_block_impl(header.number(), header.parent_hash(), &digests);
603
604		Self::extrinsic_mode()
605	}
606
607	fn extrinsic_mode() -> ExtrinsicInclusionMode {
608		if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
609			ExtrinsicInclusionMode::OnlyInherents
610		} else {
611			ExtrinsicInclusionMode::AllExtrinsics
612		}
613	}
614
615	fn extract_pre_digest(header: &frame_system::pallet_prelude::HeaderFor<System>) -> Digest {
616		let mut digest = <Digest>::default();
617		header.digest().logs().iter().for_each(|d| {
618			if d.as_pre_runtime().is_some() {
619				digest.push(d.clone())
620			}
621		});
622		digest
623	}
624
625	fn initialize_block_impl(
626		block_number: &BlockNumberFor<System>,
627		parent_hash: &System::Hash,
628		digest: &Digest,
629	) {
630		// Reset events before apply runtime upgrade hook.
631		// This is required to preserve events from runtime upgrade hook.
632		// This means the format of all the event related storage must always be compatible.
633		<frame_system::Pallet<System>>::reset_events();
634
635		let mut weight = Weight::zero();
636		if Self::runtime_upgraded() {
637			weight = weight.saturating_add(Self::execute_on_runtime_upgrade());
638
639			frame_system::LastRuntimeUpgrade::<System>::put(
640				frame_system::LastRuntimeUpgradeInfo::from(
641					<System::Version as frame_support::traits::Get<_>>::get(),
642				),
643			);
644		}
645		<frame_system::Pallet<System>>::initialize(block_number, parent_hash, digest);
646
647		weight = System::BlockWeights::get().base_block.saturating_add(weight);
648		// Register the base block weight and optional `on_runtime_upgrade` weight.
649		<frame_system::Pallet<System>>::register_extra_weight_unchecked(
650			weight,
651			DispatchClass::Mandatory,
652		);
653
654		weight = weight
655			.saturating_add(<AllPalletsWithSystem as OnInitializeWithWeightRegistration<
656			System,
657		>>::on_initialize_with_weight_registration(*block_number));
658
659		log::debug!(
660			target: LOG_TARGET,
661			"[{block_number:?}]: Block initialization weight consumption: {weight:?}",
662		);
663
664		frame_system::Pallet::<System>::note_finished_initialize();
665		<System as frame_system::Config>::PreInherents::pre_inherents();
666	}
667
668	/// Returns if the runtime has been upgraded, based on [`frame_system::LastRuntimeUpgrade`].
669	fn runtime_upgraded() -> bool {
670		let last = frame_system::LastRuntimeUpgrade::<System>::get();
671		let current = <System::Version as frame_support::traits::Get<_>>::get();
672
673		last.map(|v| v.was_upgraded(&current)).unwrap_or(true)
674	}
675
676	fn initial_checks(header: &Block::Header) {
677		sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks");
678
679		// Check that `parent_hash` is correct.
680		let n = *header.number();
681		assert!(
682			n > BlockNumberFor::<System>::zero() &&
683				<frame_system::Pallet<System>>::block_hash(n - BlockNumberFor::<System>::one()) ==
684					*header.parent_hash(),
685			"Parent hash should be valid.",
686		);
687	}
688
689	/// Actually execute all transitions for `block`.
690	pub fn execute_block(block: Block::LazyBlock) {
691		sp_io::init_tracing();
692		sp_tracing::within_span! {
693			sp_tracing::info_span!("execute_block", ?block);
694			// Execute `on_runtime_upgrade` and `on_initialize`.
695			let mode = Self::initialize_block(block.header());
696			Self::initial_checks(block.header());
697
698			let extrinsics = block.extrinsics();
699			if let Err(e) = Self::apply_extrinsics(
700				mode,
701				extrinsics,
702				|uxt, is_inherent| {
703					Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
704				}
705			) {
706				panic!("{:?}", e)
707			}
708
709			// In this case there were no transactions to trigger this state transition:
710			if !<frame_system::Pallet<System>>::inherents_applied() {
711				Self::inherents_applied();
712			}
713
714			<frame_system::Pallet<System>>::note_finished_extrinsics();
715			<System as frame_system::Config>::PostTransactions::post_transactions();
716
717			let header = block.header();
718			Self::on_idle_hook(*header.number());
719			Self::on_finalize_hook(*header.number());
720			<frame_system::Pallet<System>>::maybe_apply_pending_code_upgrade();
721			Self::final_checks(&header);
722		}
723	}
724
725	/// Logic that runs directly after inherent application.
726	///
727	/// It advances the Multi-Block-Migrations or runs the `on_poll` hook.
728	pub fn inherents_applied() {
729		<frame_system::Pallet<System>>::note_inherents_applied();
730		<System as frame_system::Config>::PostInherents::post_inherents();
731
732		if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
733			let used_weight = <System as frame_system::Config>::MultiBlockMigrator::step();
734			<frame_system::Pallet<System>>::register_extra_weight_unchecked(
735				used_weight,
736				DispatchClass::Mandatory,
737			);
738		} else {
739			let block_number = <frame_system::Pallet<System>>::block_number();
740			Self::on_poll_hook(block_number);
741		}
742	}
743
744	/// Execute given extrinsics.
745	fn apply_extrinsics(
746		mode: ExtrinsicInclusionMode,
747		extrinsics: impl Iterator<Item = Result<Block::Extrinsic, codec::Error>>,
748		mut apply_extrinsic: impl FnMut(Block::Extrinsic, bool) -> ApplyExtrinsicResult,
749	) -> Result<(), ExecutiveError> {
750		let mut first_non_inherent_idx = 0;
751		for (idx, maybe_uxt) in extrinsics.into_iter().enumerate() {
752			let uxt = maybe_uxt.map_err(|_| ExecutiveError::UnableToDecodeExtrinsic)?;
753			let is_inherent = System::is_inherent(&uxt);
754			if is_inherent {
755				// Check if inherents are first
756				if first_non_inherent_idx != idx {
757					return Err(ExecutiveError::InvalidInherentPosition(idx));
758				}
759				first_non_inherent_idx += 1;
760			} else {
761				// Check if there are any forbidden non-inherents in the block.
762				if mode == ExtrinsicInclusionMode::OnlyInherents {
763					return Err(ExecutiveError::OnlyInherentsAllowed);
764				}
765			}
766
767			log::debug!(target: LOG_TARGET, "Executing transaction: {:?}", uxt);
768			if let Err(e) = apply_extrinsic(uxt, is_inherent) {
769				log::error!(
770					target: LOG_TARGET,
771					"Transaction({idx}) failed due to {e:?}. \
772					Aborting the rest of the block execution.",
773				);
774				return Err(ExecutiveError::ApplyExtrinsic(e.into()));
775			}
776		}
777
778		Ok(())
779	}
780
781	/// Finalize the block - it is up the caller to ensure that all header fields are valid
782	/// except state-root.
783	// Note: Only used by the block builder - not Executive itself.
784	pub fn finalize_block() -> frame_system::pallet_prelude::HeaderFor<System> {
785		sp_io::init_tracing();
786		sp_tracing::enter_span!(sp_tracing::Level::TRACE, "finalize_block");
787
788		// In this case there were no transactions to trigger this state transition:
789		if !<frame_system::Pallet<System>>::inherents_applied() {
790			Self::inherents_applied();
791		}
792
793		<frame_system::Pallet<System>>::note_finished_extrinsics();
794		<System as frame_system::Config>::PostTransactions::post_transactions();
795		let block_number = <frame_system::Pallet<System>>::block_number();
796		Self::on_idle_hook(block_number);
797		Self::on_finalize_hook(block_number);
798		<frame_system::Pallet<System>>::maybe_apply_pending_code_upgrade();
799		<frame_system::Pallet<System>>::finalize()
800	}
801
802	/// Run the `on_idle` hook of all pallet, but only if there is weight remaining and there are no
803	/// ongoing MBMs.
804	fn on_idle_hook(block_number: NumberFor<Block>) {
805		if <System as frame_system::Config>::MultiBlockMigrator::ongoing() {
806			return;
807		}
808
809		let weight = <frame_system::Pallet<System>>::block_weight();
810		let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
811		let remaining_weight = max_weight.saturating_sub(weight.total());
812
813		if remaining_weight.all_gt(Weight::zero()) {
814			let used_weight = <AllPalletsWithSystem as OnIdle<BlockNumberFor<System>>>::on_idle(
815				block_number,
816				remaining_weight,
817			);
818			<frame_system::Pallet<System>>::register_extra_weight_unchecked(
819				used_weight,
820				DispatchClass::Mandatory,
821			);
822		}
823	}
824
825	fn on_poll_hook(block_number: NumberFor<Block>) {
826		defensive_assert!(
827			!<System as frame_system::Config>::MultiBlockMigrator::ongoing(),
828			"on_poll should not be called during migrations"
829		);
830
831		let weight = <frame_system::Pallet<System>>::block_weight();
832		let max_weight = <System::BlockWeights as frame_support::traits::Get<_>>::get().max_block;
833		let remaining = max_weight.saturating_sub(weight.total());
834
835		if remaining.all_gt(Weight::zero()) {
836			let mut meter = WeightMeter::with_limit(remaining);
837			<AllPalletsWithSystem as OnPoll<BlockNumberFor<System>>>::on_poll(
838				block_number,
839				&mut meter,
840			);
841			<frame_system::Pallet<System>>::register_extra_weight_unchecked(
842				meter.consumed(),
843				DispatchClass::Mandatory,
844			);
845		}
846	}
847
848	/// Run the `on_finalize` hook of all pallet.
849	fn on_finalize_hook(block_number: NumberFor<Block>) {
850		<AllPalletsWithSystem as OnFinalize<BlockNumberFor<System>>>::on_finalize(block_number);
851	}
852
853	/// Apply extrinsic outside of the block execution function.
854	///
855	/// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt
856	/// hashes.
857	fn do_apply_extrinsic(
858		uxt: Block::Extrinsic,
859		is_inherent: bool,
860		check: impl FnOnce(
861			Block::Extrinsic,
862			&Context,
863		) -> Result<CheckedOf<Block::Extrinsic, Context>, TransactionValidityError>,
864	) -> ApplyExtrinsicResult {
865		sp_io::init_tracing();
866		let encoded = uxt.encode();
867		let encoded_len = encoded.len();
868		sp_tracing::enter_span!(sp_tracing::info_span!(
869			"apply_extrinsic",
870			ext=?sp_core::hexdisplay::HexDisplay::from(&encoded)
871		));
872
873		let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
874			MAX_EXTRINSIC_DEPTH,
875			&mut &encoded[..],
876		)
877		.map_err(|_| InvalidTransaction::Call)?;
878
879		// Verify that the signature is good.
880		let xt = check(uxt, &Context::default())?;
881
882		let dispatch_info = xt.get_dispatch_info();
883
884		if !is_inherent && !<frame_system::Pallet<System>>::inherents_applied() {
885			Self::inherents_applied();
886		}
887
888		// We don't need to make sure to `note_extrinsic` only after we know it's going to be
889		// executed to prevent it from leaking in storage since at this point, it will either
890		// execute or panic (and revert storage changes).
891		<frame_system::Pallet<System>>::note_extrinsic(encoded);
892
893		// AUDIT: Under no circumstances may this function panic from here onwards.
894
895		let r = Applyable::apply::<UnsignedValidator>(xt, &dispatch_info, encoded_len)?;
896
897		// Mandatory(inherents) are not allowed to fail.
898		//
899		// The entire block should be discarded if an inherent fails to apply. Otherwise
900		// it may open an attack vector.
901		if r.is_err() && dispatch_info.class == DispatchClass::Mandatory {
902			return Err(InvalidTransaction::BadMandatory.into());
903		}
904
905		<frame_system::Pallet<System>>::note_applied_extrinsic(&r, dispatch_info);
906
907		Ok(r.map(|_| ()).map_err(|e| e.error))
908	}
909
910	/// Apply extrinsic outside of the block execution function.
911	///
912	/// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt
913	/// hashes.
914	pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult {
915		let is_inherent = System::is_inherent(&uxt);
916		Self::do_apply_extrinsic(uxt, is_inherent, Block::Extrinsic::check)
917	}
918
919	fn final_checks(header: &frame_system::pallet_prelude::HeaderFor<System>) {
920		sp_tracing::enter_span!(sp_tracing::Level::TRACE, "final_checks");
921		// remove temporaries
922		let new_header = <frame_system::Pallet<System>>::finalize();
923
924		// check digest
925		assert_eq!(
926			header.digest().logs().len(),
927			new_header.digest().logs().len(),
928			"Number of digest items must match that calculated."
929		);
930		let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
931		for (header_item, computed_item) in items_zip {
932			header_item.check_equal(computed_item);
933			assert!(header_item == computed_item, "Digest item must match that calculated.");
934		}
935
936		// check storage root.
937		let storage_root = new_header.state_root();
938		header.state_root().check_equal(storage_root);
939		assert!(header.state_root() == storage_root, "Storage root must match that calculated.");
940
941		assert!(
942			header.extrinsics_root() == new_header.extrinsics_root(),
943			"Transaction trie root must be valid.",
944		);
945	}
946
947	/// Check a given signed transaction for validity. This doesn't execute any
948	/// side-effects; it merely checks whether the transaction would panic if it were included or
949	/// not.
950	///
951	/// Changes made to storage should be discarded.
952	pub fn validate_transaction(
953		source: TransactionSource,
954		uxt: Block::Extrinsic,
955		block_hash: Block::Hash,
956	) -> TransactionValidity {
957		sp_io::init_tracing();
958		use sp_tracing::{enter_span, within_span};
959
960		<frame_system::Pallet<System>>::initialize(
961			&(frame_system::Pallet::<System>::block_number() + One::one()),
962			&block_hash,
963			&Default::default(),
964		);
965
966		enter_span! { sp_tracing::Level::TRACE, "validate_transaction" };
967
968		let encoded = within_span! { sp_tracing::Level::TRACE, "using_encoded";
969			uxt.encode()
970		};
971
972		let uxt = <Block::Extrinsic as codec::DecodeLimit>::decode_all_with_depth_limit(
973			MAX_EXTRINSIC_DEPTH,
974			&mut &encoded[..],
975		)
976		.map_err(|_| InvalidTransaction::Call)?;
977
978		let xt = within_span! { sp_tracing::Level::TRACE, "check";
979			uxt.check(&Default::default())
980		}?;
981
982		let dispatch_info = within_span! { sp_tracing::Level::TRACE, "dispatch_info";
983			xt.get_dispatch_info()
984		};
985
986		if dispatch_info.class == DispatchClass::Mandatory {
987			return Err(InvalidTransaction::MandatoryValidation.into());
988		}
989
990		within_span! {
991			sp_tracing::Level::TRACE, "validate";
992			xt.validate::<UnsignedValidator>(source, &dispatch_info, encoded.len())
993		}
994	}
995
996	/// Start an offchain worker and generate extrinsics.
997	pub fn offchain_worker(header: &frame_system::pallet_prelude::HeaderFor<System>) {
998		sp_io::init_tracing();
999		// We need to keep events available for offchain workers,
1000		// hence we initialize the block manually.
1001		// OffchainWorker RuntimeApi should skip initialization.
1002		let digests = header.digest().clone();
1003
1004		// Let's deposit all the logs we are not yet aware of. These are the logs set by the `node`.
1005		let existing_digest = frame_system::Pallet::<System>::digest();
1006		for digest in digests.logs().iter().filter(|d| !existing_digest.logs.contains(d)) {
1007			frame_system::Pallet::<System>::deposit_log(digest.clone());
1008		}
1009
1010		// Initialize the intra block entropy, which is maybe used by offchain workers.
1011		frame_system::Pallet::<System>::initialize_intra_block_entropy(header.parent_hash());
1012
1013		// Frame system only inserts the parent hash into the block hashes as normally we don't know
1014		// the hash for the header before. However, here we are aware of the hash and we can add it
1015		// as well.
1016		frame_system::BlockHash::<System>::insert(header.number(), header.hash());
1017
1018		<AllPalletsWithSystem as OffchainWorker<BlockNumberFor<System>>>::offchain_worker(
1019			*header.number(),
1020		)
1021	}
1022}