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