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