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