From 7f6a396f7712ebe2e4f40550cb683d769535d82d Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 13:07:44 +0200 Subject: [PATCH 01/41] Add after_inherents Signed-off-by: Oliver Tale-Yazdi --- bin/node/runtime/src/lib.rs | 4 + .../basic-authorship/src/basic_authorship.rs | 21 +++-- client/block-builder/src/lib.rs | 9 ++- client/proposer-metrics/src/lib.rs | 4 + frame/executive/src/lib.rs | 81 +++++++++++++------ .../src/construct_runtime/expand/inherent.rs | 20 ++--- frame/support/src/traits/misc.rs | 5 +- frame/system/benchmarking/src/lib.rs | 1 + primitives/block-builder/src/lib.rs | 7 +- primitives/runtime/src/lib.rs | 9 +++ test-utils/runtime/src/lib.rs | 6 +- 11 files changed, 120 insertions(+), 47 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7d16a1afa1f2d..010550af440d1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2111,6 +2111,10 @@ impl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult { data.check_extrinsics(&block) } + + fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + Executive::after_inherents() + } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index d1921b3413cbc..b961950cb920d 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -39,7 +39,7 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - Digest, Percent, SaturatedConversion, + BlockAfterInherentsMode, Digest, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -347,12 +347,14 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; - // TODO call `after_inherents` and check if we should apply extrinsincs here - // - let block_timer = time::Instant::now(); - let end_reason = - self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?; + let mode = block_builder.after_inherents()?; + let end_reason = match mode { + BlockAfterInherentsMode::ExtrinsicsAllowed => + self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, + BlockAfterInherentsMode::ExtrinsicsForbidden => EndProposingReason::ExtrinsicsForbidden, + }; + let (block, storage_changes, proof) = block_builder.build()?.into_inner(); let block_took = block_timer.elapsed(); @@ -544,7 +546,12 @@ where }); let extrinsics_summary = if extrinsics.is_empty() { - "no extrinsics".to_string() + if end_reason == EndProposingReason::ExtrinsicsForbidden { + "extrinsics forbidden" + } else { + "no extrinsics" + } + .to_string() } else { format!( "extrinsics ({}): [{}]", diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index f055d4688822a..5c05d453ba047 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::ExecutionContext; use sp_runtime::{ legacy, traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, - Digest, + BlockAfterInherentsMode, Digest, }; use sc_client_api::backend; @@ -198,6 +198,13 @@ where }) } + /// Called after inherents but before extrinsics have been applied. + pub fn after_inherents(&self) -> Result { + self.api + .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) + .map_err(Into::into) + } + /// Push onto the block's list of extrinsics. /// /// This will ensure the extrinsic can be validly executed (by executing it). diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index 012e8ca769a96..a9aa5a0e0e302 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -44,11 +44,14 @@ impl MetricsLink { } /// The reason why proposing a block ended. +#[derive(Clone, Copy, PartialEq, Eq)] pub enum EndProposingReason { NoMoreTransactions, HitDeadline, HitBlockSizeLimit, HitBlockWeightLimit, + /// No extrinsics are allowed in the block. + ExtrinsicsForbidden, } /// Authorship metrics. @@ -112,6 +115,7 @@ impl Metrics { EndProposingReason::NoMoreTransactions => "no_more_transactions", EndProposingReason::HitBlockSizeLimit => "hit_block_size_limit", EndProposingReason::HitBlockWeightLimit => "hit_block_weight_limit", + EndProposingReason::ExtrinsicsForbidden => "extrinsics_forbidden", }; self.end_proposing_reason.with_label_values(&[reason]).inc(); diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 31cbb0ee7ba0d..abcf2de146668 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -133,7 +133,7 @@ use sp_runtime::{ ValidateUnsigned, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, BlockAfterInherentsMode, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -293,7 +293,10 @@ where // post-extrinsics book-keeping >::note_finished_extrinsics(); - Self::idle_and_finalize_hook(*header.number()); + // TODO MBMs will only conditionally run this. + Self::on_idle_hook(*header.number()); + + Self::on_finalize_hook(*header.number()); // run the try-state checks of all pallets, ensuring they don't alter any state. let _guard = frame_support::StorageNoopGuard::default(); @@ -454,7 +457,8 @@ where } } - fn initial_checks(block: &Block) { + /// Returns the number of inherents in the block. + fn initial_checks(block: &Block) -> u32 { sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks"); let header = block.header(); @@ -467,8 +471,9 @@ where "Parent hash should be valid.", ); - if let Err(i) = System::ensure_inherents_are_first(block) { - panic!("Invalid inherent position for extrinsic at index {}", i); + match System::ensure_inherents_are_first(block) { + Ok(num_inherents) => num_inherents, + Err(i) => panic!("Invalid inherent position for extrinsic at index {}", i), } } @@ -477,53 +482,77 @@ where sp_io::init_tracing(); sp_tracing::within_span! { sp_tracing::info_span!("execute_block", ?block); - + // Execute `on_runtime_upgrade` and `on_initialize`. Self::initialize_block(block.header()); - // any initial checks - Self::initial_checks(&block); + // Check the block and panic if invalid. + let num_inherents = Self::initial_checks(&block) as usize; + let (header, applyables) = block.deconstruct(); - // execute extrinsics - let (header, extrinsics) = block.deconstruct(); - Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number()); + // Process inherents (if any). + Self::execute_applyables(applyables.iter().take(num_inherents)); + match Self::after_inherents() { + BlockAfterInherentsMode::ExtrinsicsForbidden => { + if num_inherents < applyables.len() { + panic!("Extrinsics are not allowed in this block"); + } + }, + BlockAfterInherentsMode::ExtrinsicsAllowed => { + Self::execute_applyables(applyables.iter().skip(num_inherents)); + }, + } + + // Dispatchable processing is done now. + >::note_finished_extrinsics(); + // TODO MBMs will only conditionally run this. + Self::on_idle_hook(*header.number()); + + Self::on_finalize_hook(*header.number()); // any final checks Self::final_checks(&header); } } - /// Execute given extrinsics and take care of post-extrinsics book-keeping. - fn execute_extrinsics_with_book_keeping( - extrinsics: Vec, - block_number: NumberFor, - ) { - extrinsics.into_iter().for_each(|e| { - if let Err(e) = Self::apply_extrinsic(e) { + /// Execute code after inherents but before extrinsic application. + /// + /// This is always called by the block builder. It returns whether extrinsics are allowed to be + /// included in the block or not. + pub fn after_inherents() -> BlockAfterInherentsMode { + // TODO MBMs and `poll` will add a condition. + // + // + BlockAfterInherentsMode::ExtrinsicsAllowed + } + + /// Execute given applyables. + fn execute_applyables<'a>(applyables: impl Iterator) { + applyables.into_iter().for_each(|e| { + if let Err(e) = Self::apply_extrinsic(e.clone()) { let err: &'static str = e.into(); panic!("{}", err) } }); - - // post-extrinsics book-keeping - >::note_finished_extrinsics(); - - Self::idle_and_finalize_hook(block_number); } /// Finalize the block - it is up the caller to ensure that all header fields are valid /// except state-root. + // Note: Only used by the block builder - not Executive itself. pub fn finalize_block() -> System::Header { sp_io::init_tracing(); sp_tracing::enter_span!(sp_tracing::Level::TRACE, "finalize_block"); >::note_finished_extrinsics(); let block_number = >::block_number(); - Self::idle_and_finalize_hook(block_number); + // TODO MBMs will only conditionally run this. + Self::on_idle_hook(block_number); + + Self::on_finalize_hook(block_number); >::finalize() } - fn idle_and_finalize_hook(block_number: NumberFor) { + fn on_idle_hook(block_number: NumberFor) { let weight = >::block_weight(); let max_weight = >::get().max_block; let remaining_weight = max_weight.saturating_sub(weight.total()); @@ -538,7 +567,9 @@ where DispatchClass::Mandatory, ); } + } + fn on_finalize_hook(block_number: NumberFor) { >::on_finalize(block_number); } diff --git a/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/frame/support/procedural/src/construct_runtime/expand/inherent.rs index 2f1cf75ab7ce9..c89269732e261 100644 --- a/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -178,12 +178,12 @@ pub fn expand_outer_inherent( } impl #scrate::traits::EnsureInherentsAreFirst<#block> for #runtime { - fn ensure_inherents_are_first(block: &#block) -> Result<(), u32> { + fn ensure_inherents_are_first(block: &#block) -> Result { use #scrate::inherent::ProvideInherent; use #scrate::traits::{IsSubType, ExtrinsicCall}; use #scrate::sp_runtime::traits::Block as _; - let mut first_signed_observed = false; + let mut first_extrinsic_index = None; for (i, xt) in block.extrinsics().iter().enumerate() { let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt) @@ -208,16 +208,18 @@ pub fn expand_outer_inherent( is_inherent }; - if !is_inherent { - first_signed_observed = true; - } - - if first_signed_observed && is_inherent { - return Err(i as u32) + if is_inherent { + if first_extrinsic_index.is_some() { + // There is an inherent after an extrinsic: + return Err(i as u32) + } + } else if first_extrinsic_index.is_none() { + // This is the first extrinsic: + first_extrinsic_index = Some(i as u32); } } - Ok(()) + Ok(first_extrinsic_index.unwrap_or(0)) } } } diff --git a/frame/support/src/traits/misc.rs b/frame/support/src/traits/misc.rs index a6f8c46d63951..27bdca7eef73b 100644 --- a/frame/support/src/traits/misc.rs +++ b/frame/support/src/traits/misc.rs @@ -880,8 +880,9 @@ pub trait GetBacking { pub trait EnsureInherentsAreFirst { /// Ensure the position of inherent is correct, i.e. they are before non-inherents. /// - /// On error return the index of the inherent with invalid position (counting from 0). - fn ensure_inherents_are_first(block: &Block) -> Result<(), u32>; + /// On error return the index of the inherent with invalid position (counting from 0). On + /// success it returns the number of inherents. + fn ensure_inherents_are_first(block: &Block) -> Result; } /// An extrinsic on which we can get access to call. diff --git a/frame/system/benchmarking/src/lib.rs b/frame/system/benchmarking/src/lib.rs index 1cd7b1bac6bd5..ccd3bacf62ec6 100644 --- a/frame/system/benchmarking/src/lib.rs +++ b/frame/system/benchmarking/src/lib.rs @@ -18,6 +18,7 @@ // Benchmarks for Utility Pallet #![cfg_attr(not(feature = "std"), no_std)] +#![cfg(feature = "runtime-benchmarks")] use codec::Encode; use frame_benchmarking::v1::{benchmarks, whitelisted_caller}; diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 29e04857f463e..e1b132b9be670 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,11 +20,11 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult, BlockAfterInherentsMode}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. - #[api_version(6)] + #[api_version(7)] pub trait BlockBuilder { /// Apply the given extrinsic. /// @@ -48,5 +48,8 @@ sp_api::decl_runtime_apis! { /// Check that the inherents are valid. The inherent data will vary from chain to chain. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; + + /// Called after inherents but before extrinsic application. + fn after_inherents() -> BlockAfterInherentsMode; } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index d29938d0a8610..4acc1669acebf 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -944,6 +944,15 @@ impl TransactionOutcome { } } +/// The mode of a block after inherents were applied. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] +pub enum BlockAfterInherentsMode { + /// No extrinsics should be pushed to the block - not even mandatory ones. + ExtrinsicsForbidden, + /// Can push extrinsics to the block. + ExtrinsicsAllowed, +} + #[cfg(test)] mod tests { use crate::traits::BlakeTwo256; diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 8d77439f16455..bacc4a2d4aa67 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -480,7 +480,7 @@ impl_runtime_apis! { fn initialize_block(header: &::Header) { log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); - Executive::initialize_block(header); + Executive::initialize_block(header) } } @@ -526,6 +526,10 @@ impl_runtime_apis! { fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { CheckInherentsResult::new() } + + fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + Executive::after_inherents() + } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { From 03f6b4ec3a383526b5a2fb5d4d0597be5e086c91 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 13:36:36 +0200 Subject: [PATCH 02/41] Fix template runtime Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 22fb01b62d0f0..f2dc1099fdbb4 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -392,6 +392,10 @@ impl_runtime_apis! { ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) } + + fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + Executive::after_inherents() + } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { From 6d04b2a69fde0d901e4d635751825d1a539a8395 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 14:07:58 +0200 Subject: [PATCH 03/41] Fix test Signed-off-by: Oliver Tale-Yazdi --- bin/node/runtime/src/lib.rs | 2 +- client/rpc/src/state/tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 010550af440d1..255af877151b3 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -143,7 +143,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 268, + spec_version: 269, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 2, diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 9e00a04abe386..57ddd215822b1 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -515,7 +515,7 @@ async fn should_return_runtime_version() { // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ - [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\ + [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",7],\ [\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\ [\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\ [\"0xed99c5acb25eedf5\",3]],\"transactionVersion\":1,\"stateVersion\":1}"; From 76fb1bc3ccb642e965670da2bef34c5648e8f040 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 16:10:44 +0200 Subject: [PATCH 04/41] Fix test Signed-off-by: Oliver Tale-Yazdi --- client/rpc-spec-v2/src/chain_head/tests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/rpc-spec-v2/src/chain_head/tests.rs b/client/rpc-spec-v2/src/chain_head/tests.rs index cb6e65f859133..755ae9220ae15 100644 --- a/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/client/rpc-spec-v2/src/chain_head/tests.rs @@ -187,7 +187,7 @@ async fn follow_with_runtime() { // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION let runtime_str = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ - [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",6],\ + [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",7],\ [\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\ [\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\ [\"0xed99c5acb25eedf5\",3]],\"transactionVersion\":1,\"stateVersion\":1}"; From 2f62b6a685a813be3df37900005b055279348ba6 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 16:12:55 +0200 Subject: [PATCH 05/41] Move executive tests to own file Signed-off-by: Oliver Tale-Yazdi --- frame/executive/src/lib.rs | 957 ---------------------------------- frame/executive/src/tests.rs | 975 +++++++++++++++++++++++++++++++++++ 2 files changed, 975 insertions(+), 957 deletions(-) create mode 100644 frame/executive/src/tests.rs diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index abcf2de146668..d6a251082e07c 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -701,960 +701,3 @@ where ) } } - -#[cfg(test)] -mod tests { - use super::*; - - use sp_core::H256; - use sp_runtime::{ - generic::{DigestItem, Era}, - testing::{Block, Digest, Header}, - traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, IdentityLookup}, - transaction_validity::{ - InvalidTransaction, TransactionValidityError, UnknownTransaction, ValidTransaction, - }, - DispatchError, - }; - - use frame_support::{ - assert_err, parameter_types, - traits::{fungible, ConstU32, ConstU64, ConstU8, Currency}, - weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee}, - }; - use frame_system::{ChainContext, LastRuntimeUpgradeInfo}; - use pallet_balances::Call as BalancesCall; - use pallet_transaction_payment::CurrencyAdapter; - - const TEST_KEY: &[u8] = b":test:key:"; - - #[frame_support::pallet(dev_mode)] - mod custom { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::hooks] - impl Hooks> for Pallet { - // module hooks. - // one with block number arg and one without - fn on_initialize(n: T::BlockNumber) -> Weight { - println!("on_initialize({})", n); - Weight::from_parts(175, 0) - } - - fn on_idle(n: T::BlockNumber, remaining_weight: Weight) -> Weight { - println!("on_idle{}, {})", n, remaining_weight); - Weight::from_parts(175, 0) - } - - fn on_finalize(n: T::BlockNumber) { - println!("on_finalize({})", n); - } - - fn on_runtime_upgrade() -> Weight { - sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); - Weight::from_parts(200, 0) - } - - fn offchain_worker(n: T::BlockNumber) { - assert_eq!(T::BlockNumber::from(1u32), n); - } - } - - #[pallet::call] - impl Pallet { - pub fn some_function(origin: OriginFor) -> DispatchResult { - // NOTE: does not make any different. - frame_system::ensure_signed(origin)?; - Ok(()) - } - - #[pallet::weight((200, DispatchClass::Operational))] - pub fn some_root_operation(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } - - pub fn some_unsigned_message(origin: OriginFor) -> DispatchResult { - frame_system::ensure_none(origin)?; - Ok(()) - } - - pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } - - pub fn unallowed_unsigned(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } - - #[pallet::weight((0, DispatchClass::Mandatory))] - pub fn inherent_call(origin: OriginFor) -> DispatchResult { - frame_system::ensure_none(origin)?; - Ok(()) - } - - pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { - let root = sp_io::storage::root(sp_runtime::StateVersion::V1); - sp_io::storage::set("storage_root".as_bytes(), &root); - Ok(()) - } - } - - #[pallet::inherent] - impl ProvideInherent for Pallet { - type Call = Call; - - type Error = sp_inherents::MakeFatalError<()>; - - const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234"; - - fn create_inherent(_data: &InherentData) -> Option { - None - } - - fn is_inherent(call: &Self::Call) -> bool { - *call == Call::::inherent_call {} - } - } - - #[pallet::validate_unsigned] - impl ValidateUnsigned for Pallet { - type Call = Call; - - // Inherent call is accepted for being dispatched - fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { - match call { - Call::allowed_unsigned { .. } => Ok(()), - Call::inherent_call { .. } => Ok(()), - _ => Err(UnknownTransaction::NoUnsignedValidator.into()), - } - } - - // Inherent call is not validated as unsigned - fn validate_unsigned( - _source: TransactionSource, - call: &Self::Call, - ) -> TransactionValidity { - match call { - Call::allowed_unsigned { .. } => Ok(Default::default()), - _ => UnknownTransaction::NoUnsignedValidator.into(), - } - } - } - } - - frame_support::construct_runtime!( - pub struct Runtime where - Block = TestBlock, - NodeBlock = TestBlock, - UncheckedExtrinsic = TestUncheckedExtrinsic - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, - Custom: custom::{Pallet, Call, ValidateUnsigned, Inherent}, - } - ); - - parameter_types! { - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::builder() - .base_block(Weight::from_parts(10, 0)) - .for_class(DispatchClass::all(), |weights| weights.base_extrinsic = Weight::from_parts(5, 0)) - .for_class(DispatchClass::non_mandatory(), |weights| weights.max_total = Weight::from_parts(1024, u64::MAX).into()) - .build_or_panic(); - pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 10, - write: 100, - }; - } - impl frame_system::Config for Runtime { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = BlockWeights; - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type RuntimeCall = RuntimeCall; - type BlockNumber = u64; - type Hash = sp_core::H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = RuntimeVersion; - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; - } - - type Balance = u64; - impl pallet_balances::Config for Runtime { - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU64<1>; - type AccountStore = System; - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<1>; - type RuntimeHoldReason = (); - type MaxHolds = ConstU32<1>; - } - - parameter_types! { - pub const TransactionByteFee: Balance = 0; - } - impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = IdentityFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = (); - } - impl custom::Config for Runtime {} - - pub struct RuntimeVersion; - impl frame_support::traits::Get for RuntimeVersion { - fn get() -> sp_version::RuntimeVersion { - RuntimeVersionTestValues::get().clone() - } - } - - parameter_types! { - pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = - Default::default(); - } - - type SignedExtra = ( - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - ); - type TestXt = sp_runtime::testing::TestXt; - type TestBlock = Block; - type TestUncheckedExtrinsic = TestXt; - - // Will contain `true` when the custom runtime logic was called. - const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; - - struct CustomOnRuntimeUpgrade; - impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { - fn on_runtime_upgrade() -> Weight { - sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); - sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); - System::deposit_event(frame_system::Event::CodeUpdated); - Weight::from_parts(100, 0) - } - } - - type Executive = super::Executive< - Runtime, - Block, - ChainContext, - Runtime, - AllPalletsWithSystem, - CustomOnRuntimeUpgrade, - >; - - fn extra(nonce: u64, fee: Balance) -> SignedExtra { - ( - frame_system::CheckEra::from(Era::Immortal), - frame_system::CheckNonce::from(nonce), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(fee), - ) - } - - fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { - Some((who, extra(nonce, fee))) - } - - fn call_transfer(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) - } - - #[test] - fn balance_transfer_dispatch_works() { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } - .assimilate_storage(&mut t) - .unwrap(); - let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); - let weight = xt.get_dispatch_info().weight + - ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - let fee: Balance = - ::WeightToFee::weight_to_fee(&weight); - let mut t = sp_io::TestExternalities::new(t); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - let r = Executive::apply_extrinsic(xt); - assert!(r.is_ok()); - assert_eq!(>::total_balance(&1), 142 - fee); - assert_eq!(>::total_balance(&2), 69); - }); - } - - fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } - .assimilate_storage(&mut t) - .unwrap(); - t.into() - } - - fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } - .assimilate_storage(&mut t) - .unwrap(); - (t, sp_runtime::StateVersion::V0).into() - } - - #[test] - fn block_import_works() { - block_import_works_inner( - new_test_ext_v0(1), - array_bytes::hex_n_into_unchecked( - "65e953676859e7a33245908af7ad3637d6861eb90416d433d485e95e2dd174a1", - ), - ); - block_import_works_inner( - new_test_ext(1), - array_bytes::hex_n_into_unchecked( - "5a19b3d6fdb7241836349fdcbe2d9df4d4f945b949d979e31ad50bff1cbcd1c2", - ), - ); - } - fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { - ext.execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root, - extrinsics_root: array_bytes::hex_n_into_unchecked( - "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", - ), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_state_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: [0u8; 32].into(), - extrinsics_root: array_bytes::hex_n_into_unchecked( - "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", - ), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - #[should_panic] - fn block_import_of_bad_extrinsic_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: array_bytes::hex_n_into_unchecked( - "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5", - ), - extrinsics_root: [0u8; 32].into(), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } - - #[test] - fn bad_extrinsic_not_inserted() { - let mut t = new_test_ext(1); - // bad nonce check! - let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - assert_err!( - Executive::apply_extrinsic(xt), - TransactionValidityError::Invalid(InvalidTransaction::Future) - ); - assert_eq!(>::extrinsic_index(), Some(0)); - }); - } - - #[test] - fn block_weight_limit_enforced() { - let mut t = new_test_ext(10000); - // given: TestXt uses the encoded len as fixed Len: - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let encoded = xt.encode(); - let encoded_len = encoded.len() as u64; - // on_initialize weight + base block execution weight - let block_weights = ::BlockWeights::get(); - let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; - let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; - let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - // Base block execution weight + `on_initialize` weight from the custom module. - assert_eq!(>::block_weight().total(), base_block_weight); - - for nonce in 0..=num_to_exhaust_block { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { - dest: 33, - value: 0, - }), - sign_extra(1, nonce.into(), 0), - ); - let res = Executive::apply_extrinsic(xt); - if nonce != num_to_exhaust_block { - assert!(res.is_ok()); - assert_eq!( - >::block_weight().total(), - //--------------------- on_initialize + block_execution + extrinsic_base weight - Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, - ); - assert_eq!( - >::extrinsic_index(), - Some(nonce as u32 + 1) - ); - } else { - assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); - } - } - }); - } - - #[test] - fn block_weight_and_size_is_stored_per_tx() { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let x1 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 1, 0), - ); - let x2 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 2, 0), - ); - let len = xt.clone().encode().len() as u32; - let mut t = new_test_ext(1); - t.execute_with(|| { - // Block execution weight + on_initialize weight from custom module - let base_block_weight = Weight::from_parts(175, 0) + - ::BlockWeights::get().base_block; - - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(>::block_weight().total(), base_block_weight); - assert_eq!(>::all_extrinsics_len(), 0); - - assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); - - // default weight for `TestXt` == encoded length. - let extrinsic_weight = Weight::from_parts(len as u64, 0) + - ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - assert_eq!( - >::block_weight().total(), - base_block_weight + 3u64 * extrinsic_weight, - ); - assert_eq!(>::all_extrinsics_len(), 3 * len); - - let _ = >::finalize(); - // All extrinsics length cleaned on `System::finalize` - assert_eq!(>::all_extrinsics_len(), 0); - - // New Block - Executive::initialize_block(&Header::new( - 2, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - // Block weight cleaned up on `System::initialize` - assert_eq!(>::block_weight().total(), base_block_weight); - }); - } - - #[test] - fn validate_unsigned() { - let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); - let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); - let mut t = new_test_ext(1); - - t.execute_with(|| { - assert_eq!( - Executive::validate_transaction( - TransactionSource::InBlock, - valid.clone(), - Default::default(), - ), - Ok(ValidTransaction::default()), - ); - assert_eq!( - Executive::validate_transaction( - TransactionSource::InBlock, - invalid.clone(), - Default::default(), - ), - Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)), - ); - assert_eq!(Executive::apply_extrinsic(valid), Ok(Err(DispatchError::BadOrigin))); - assert_eq!( - Executive::apply_extrinsic(invalid), - Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)) - ); - }); - } - - #[test] - fn can_not_pay_for_tx_fee_on_full_lock() { - let mut t = new_test_ext(1); - t.execute_with(|| { - as fungible::MutateFreeze>::set_freeze( - &(), - &1, - 110, - ) - .unwrap(); - let xt = TestXt::new( - RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), - sign_extra(1, 0, 0), - ); - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(Executive::apply_extrinsic(xt), Err(InvalidTransaction::Payment.into()),); - assert_eq!(>::total_balance(&1), 111); - }); - } - - #[test] - fn block_hooks_weight_is_stored() { - new_test_ext(1).execute_with(|| { - Executive::initialize_block(&Header::new_from_number(1)); - Executive::finalize_block(); - // NOTE: might need updates over time if new weights are introduced. - // For now it only accounts for the base block execution weight and - // the `on_initialize` weight defined in the custom test module. - assert_eq!( - >::block_weight().total(), - Weight::from_parts(175 + 175 + 10, 0) - ); - }) - } - - #[test] - fn runtime_upgraded_should_work() { - new_test_ext(1).execute_with(|| { - RuntimeVersionTestValues::mutate(|v| *v = Default::default()); - // It should be added at genesis - assert!(frame_system::LastRuntimeUpgrade::::exists()); - assert!(!Executive::runtime_upgraded()); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - assert!(Executive::runtime_upgraded()); - assert_eq!( - Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "".into() }), - frame_system::LastRuntimeUpgrade::::get(), - ); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { - spec_version: 1, - spec_name: "test".into(), - ..Default::default() - } - }); - assert!(Executive::runtime_upgraded()); - assert_eq!( - Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), - frame_system::LastRuntimeUpgrade::::get(), - ); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { - spec_version: 1, - spec_name: "test".into(), - impl_version: 2, - ..Default::default() - } - }); - assert!(!Executive::runtime_upgraded()); - - frame_system::LastRuntimeUpgrade::::take(); - assert!(Executive::runtime_upgraded()); - assert_eq!( - Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), - frame_system::LastRuntimeUpgrade::::get(), - ); - }) - } - - #[test] - fn last_runtime_upgrade_was_upgraded_works() { - let test_data = vec![ - (0, "", 1, "", true), - (1, "", 1, "", false), - (1, "", 1, "test", true), - (1, "", 0, "", false), - (1, "", 0, "test", true), - ]; - - for (spec_version, spec_name, c_spec_version, c_spec_name, result) in test_data { - let current = sp_version::RuntimeVersion { - spec_version: c_spec_version, - spec_name: c_spec_name.into(), - ..Default::default() - }; - - let last = LastRuntimeUpgradeInfo { - spec_version: spec_version.into(), - spec_name: spec_name.into(), - }; - - assert_eq!(result, last.was_upgraded(¤t)); - } - } - - #[test] - fn custom_runtime_upgrade_is_called_before_modules() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); - assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); - }); - } - - #[test] - fn event_from_runtime_upgrade_is_included() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - // set block number to non zero so events are not excluded - System::set_block_number(1); - - Executive::initialize_block(&Header::new( - 2, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - System::assert_last_event(frame_system::Event::::CodeUpdated.into()); - }); - } - - /// Regression test that ensures that the custom on runtime upgrade is called when executive is - /// used through the `ExecuteBlock` trait. - #[test] - fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - - let header = new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - // Reset to get the correct new genesis below. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() } - }); - - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - >>::execute_block(Block::new(header, vec![xt])); - - assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); - assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); - }); - } - - #[test] - fn all_weights_are_recorded_correctly() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called for maximum complexity - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - let block_number = 1; - - Executive::initialize_block(&Header::new( - block_number, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - // All weights that show up in the `initialize_block_impl` - let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); - let runtime_upgrade_weight = - ::on_runtime_upgrade(); - let on_initialize_weight = - >::on_initialize(block_number); - let base_block_weight = - ::BlockWeights::get().base_block; - - // Weights are recorded correctly - assert_eq!( - frame_system::Pallet::::block_weight().total(), - custom_runtime_upgrade_weight + - runtime_upgrade_weight + - on_initialize_weight + base_block_weight, - ); - }); - } - - #[test] - fn offchain_worker_works_as_expected() { - new_test_ext(1).execute_with(|| { - let parent_hash = sp_core::H256::from([69u8; 32]); - let mut digest = Digest::default(); - digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); - - let header = - Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); - - Executive::offchain_worker(&header); - - assert_eq!(digest, System::digest()); - assert_eq!(parent_hash, System::block_hash(0)); - assert_eq!(header.hash(), System::block_hash(1)); - }); - } - - #[test] - fn calculating_storage_root_twice_works() { - let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); - let xt = TestXt::new(call, sign_extra(1, 0, 0)); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt])); - }); - } - - #[test] - #[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] - fn invalid_inherent_position_fail() { - let xt1 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); - }); - } - - #[test] - fn valid_inherents_position_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); - }); - } - - #[test] - #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] - fn invalid_inherents_fail_block_execution() { - let xt1 = - TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new( - Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - ), - vec![xt1], - )); - }); - } - - // Inherents are created by the runtime and don't need to be validated. - #[test] - fn inherents_fail_validate_block() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - - new_test_ext(1).execute_with(|| { - assert_eq!( - Executive::validate_transaction(TransactionSource::External, xt1, H256::random()) - .unwrap_err(), - InvalidTransaction::MandatoryValidation.into() - ); - }) - } -} diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs new file mode 100644 index 0000000000000..e5ec1c41b0154 --- /dev/null +++ b/frame/executive/src/tests.rs @@ -0,0 +1,975 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Test the `frame-executive` crate. + +#[cfg(test)] +mod tests { + use super::*; + + use sp_core::H256; + use sp_runtime::{ + generic::{DigestItem, Era}, + testing::{Block, Digest, Header}, + traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, IdentityLookup}, + transaction_validity::{ + InvalidTransaction, TransactionValidityError, UnknownTransaction, ValidTransaction, + }, + DispatchError, + }; + + use frame_support::{ + assert_err, parameter_types, + traits::{fungible, ConstU32, ConstU64, ConstU8, Currency}, + weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee}, + }; + use frame_system::{ChainContext, LastRuntimeUpgradeInfo}; + use pallet_balances::Call as BalancesCall; + use pallet_transaction_payment::CurrencyAdapter; + + const TEST_KEY: &[u8] = b":test:key:"; + + #[frame_support::pallet(dev_mode)] + mod custom { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::hooks] + impl Hooks> for Pallet { + // module hooks. + // one with block number arg and one without + fn on_initialize(n: T::BlockNumber) -> Weight { + println!("on_initialize({})", n); + Weight::from_parts(175, 0) + } + + fn on_idle(n: T::BlockNumber, remaining_weight: Weight) -> Weight { + println!("on_idle{}, {})", n, remaining_weight); + Weight::from_parts(175, 0) + } + + fn on_finalize(n: T::BlockNumber) { + println!("on_finalize({})", n); + } + + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); + Weight::from_parts(200, 0) + } + + fn offchain_worker(n: T::BlockNumber) { + assert_eq!(T::BlockNumber::from(1u32), n); + } + } + + #[pallet::call] + impl Pallet { + pub fn some_function(origin: OriginFor) -> DispatchResult { + // NOTE: does not make any different. + frame_system::ensure_signed(origin)?; + Ok(()) + } + + #[pallet::weight((200, DispatchClass::Operational))] + pub fn some_root_operation(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + pub fn some_unsigned_message(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + Ok(()) + } + + pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + pub fn unallowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } + + #[pallet::weight((0, DispatchClass::Mandatory))] + pub fn inherent_call(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + Ok(()) + } + + pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { + let root = sp_io::storage::root(sp_runtime::StateVersion::V1); + sp_io::storage::set("storage_root".as_bytes(), &root); + Ok(()) + } + } + + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + + type Error = sp_inherents::MakeFatalError<()>; + + const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234"; + + fn create_inherent(_data: &InherentData) -> Option { + None + } + + fn is_inherent(call: &Self::Call) -> bool { + *call == Call::::inherent_call {} + } + } + + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; + + // Inherent call is accepted for being dispatched + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + match call { + Call::allowed_unsigned { .. } => Ok(()), + Call::inherent_call { .. } => Ok(()), + _ => Err(UnknownTransaction::NoUnsignedValidator.into()), + } + } + + // Inherent call is not validated as unsigned + fn validate_unsigned( + _source: TransactionSource, + call: &Self::Call, + ) -> TransactionValidity { + match call { + Call::allowed_unsigned { .. } => Ok(Default::default()), + _ => UnknownTransaction::NoUnsignedValidator.into(), + } + } + } + } + + frame_support::construct_runtime!( + pub struct Runtime where + Block = TestBlock, + NodeBlock = TestBlock, + UncheckedExtrinsic = TestUncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, + Custom: custom::{Pallet, Call, ValidateUnsigned, Inherent}, + } + ); + + parameter_types! { + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::builder() + .base_block(Weight::from_parts(10, 0)) + .for_class(DispatchClass::all(), |weights| weights.base_extrinsic = Weight::from_parts(5, 0)) + .for_class(DispatchClass::non_mandatory(), |weights| weights.max_total = Weight::from_parts(1024, u64::MAX).into()) + .build_or_panic(); + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 10, + write: 100, + }; + } + impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = BlockWeights; + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type RuntimeCall = RuntimeCall; + type BlockNumber = u64; + type Hash = sp_core::H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = RuntimeVersion; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + } + + type Balance = u64; + impl pallet_balances::Config for Runtime { + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<1>; + type RuntimeHoldReason = (); + type MaxHolds = ConstU32<1>; + } + + parameter_types! { + pub const TransactionByteFee: Balance = 0; + } + impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = (); + } + impl custom::Config for Runtime {} + + pub struct RuntimeVersion; + impl frame_support::traits::Get for RuntimeVersion { + fn get() -> sp_version::RuntimeVersion { + RuntimeVersionTestValues::get().clone() + } + } + + parameter_types! { + pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = + Default::default(); + } + + type SignedExtra = ( + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, + ); + type TestXt = sp_runtime::testing::TestXt; + type TestBlock = Block; + type TestUncheckedExtrinsic = TestXt; + + // Will contain `true` when the custom runtime logic was called. + const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; + + struct CustomOnRuntimeUpgrade; + impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); + sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); + System::deposit_event(frame_system::Event::CodeUpdated); + Weight::from_parts(100, 0) + } + } + + type Executive = super::Executive< + Runtime, + Block, + ChainContext, + Runtime, + AllPalletsWithSystem, + CustomOnRuntimeUpgrade, + >; + + fn extra(nonce: u64, fee: Balance) -> SignedExtra { + ( + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(fee), + ) + } + + fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { + Some((who, extra(nonce, fee))) + } + + fn call_transfer(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) + } + + #[test] + fn balance_transfer_dispatch_works() { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } + .assimilate_storage(&mut t) + .unwrap(); + let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); + let weight = xt.get_dispatch_info().weight + + ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let fee: Balance = + ::WeightToFee::weight_to_fee(&weight); + let mut t = sp_io::TestExternalities::new(t); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + let r = Executive::apply_extrinsic(xt); + assert!(r.is_ok()); + assert_eq!(>::total_balance(&1), 142 - fee); + assert_eq!(>::total_balance(&2), 69); + }); + } + + fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + t.into() + } + + fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + (t, sp_runtime::StateVersion::V0).into() + } + + #[test] + fn block_import_works() { + block_import_works_inner( + new_test_ext_v0(1), + array_bytes::hex_n_into_unchecked( + "65e953676859e7a33245908af7ad3637d6861eb90416d433d485e95e2dd174a1", + ), + ); + block_import_works_inner( + new_test_ext(1), + array_bytes::hex_n_into_unchecked( + "5a19b3d6fdb7241836349fdcbe2d9df4d4f945b949d979e31ad50bff1cbcd1c2", + ), + ); + } + fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { + ext.execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root, + extrinsics_root: array_bytes::hex_n_into_unchecked( + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + ), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_state_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: [0u8; 32].into(), + extrinsics_root: array_bytes::hex_n_into_unchecked( + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + ), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + #[should_panic] + fn block_import_of_bad_extrinsic_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: array_bytes::hex_n_into_unchecked( + "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5", + ), + extrinsics_root: [0u8; 32].into(), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], + }); + }); + } + + #[test] + fn bad_extrinsic_not_inserted() { + let mut t = new_test_ext(1); + // bad nonce check! + let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + assert_err!( + Executive::apply_extrinsic(xt), + TransactionValidityError::Invalid(InvalidTransaction::Future) + ); + assert_eq!(>::extrinsic_index(), Some(0)); + }); + } + + #[test] + fn block_weight_limit_enforced() { + let mut t = new_test_ext(10000); + // given: TestXt uses the encoded len as fixed Len: + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let encoded = xt.encode(); + let encoded_len = encoded.len() as u64; + // on_initialize weight + base block execution weight + let block_weights = ::BlockWeights::get(); + let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; + let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; + let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + // Base block execution weight + `on_initialize` weight from the custom module. + assert_eq!(>::block_weight().total(), base_block_weight); + + for nonce in 0..=num_to_exhaust_block { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { + dest: 33, + value: 0, + }), + sign_extra(1, nonce.into(), 0), + ); + let res = Executive::apply_extrinsic(xt); + if nonce != num_to_exhaust_block { + assert!(res.is_ok()); + assert_eq!( + >::block_weight().total(), + //--------------------- on_initialize + block_execution + extrinsic_base weight + Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, + ); + assert_eq!( + >::extrinsic_index(), + Some(nonce as u32 + 1) + ); + } else { + assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); + } + } + }); + } + + #[test] + fn block_weight_and_size_is_stored_per_tx() { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let x1 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 1, 0), + ); + let x2 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 2, 0), + ); + let len = xt.clone().encode().len() as u32; + let mut t = new_test_ext(1); + t.execute_with(|| { + // Block execution weight + on_initialize weight from custom module + let base_block_weight = Weight::from_parts(175, 0) + + ::BlockWeights::get().base_block; + + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(>::block_weight().total(), base_block_weight); + assert_eq!(>::all_extrinsics_len(), 0); + + assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); + + // default weight for `TestXt` == encoded length. + let extrinsic_weight = Weight::from_parts(len as u64, 0) + + ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + assert_eq!( + >::block_weight().total(), + base_block_weight + 3u64 * extrinsic_weight, + ); + assert_eq!(>::all_extrinsics_len(), 3 * len); + + let _ = >::finalize(); + // All extrinsics length cleaned on `System::finalize` + assert_eq!(>::all_extrinsics_len(), 0); + + // New Block + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + // Block weight cleaned up on `System::initialize` + assert_eq!(>::block_weight().total(), base_block_weight); + }); + } + + #[test] + fn validate_unsigned() { + let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); + let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); + let mut t = new_test_ext(1); + + t.execute_with(|| { + assert_eq!( + Executive::validate_transaction( + TransactionSource::InBlock, + valid.clone(), + Default::default(), + ), + Ok(ValidTransaction::default()), + ); + assert_eq!( + Executive::validate_transaction( + TransactionSource::InBlock, + invalid.clone(), + Default::default(), + ), + Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)), + ); + assert_eq!(Executive::apply_extrinsic(valid), Ok(Err(DispatchError::BadOrigin))); + assert_eq!( + Executive::apply_extrinsic(invalid), + Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)) + ); + }); + } + + #[test] + fn can_not_pay_for_tx_fee_on_full_lock() { + let mut t = new_test_ext(1); + t.execute_with(|| { + as fungible::MutateFreeze>::set_freeze( + &(), + &1, + 110, + ) + .unwrap(); + let xt = TestXt::new( + RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), + sign_extra(1, 0, 0), + ); + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(Executive::apply_extrinsic(xt), Err(InvalidTransaction::Payment.into()),); + assert_eq!(>::total_balance(&1), 111); + }); + } + + #[test] + fn block_hooks_weight_is_stored() { + new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + Executive::finalize_block(); + // NOTE: might need updates over time if new weights are introduced. + // For now it only accounts for the base block execution weight and + // the `on_initialize` weight defined in the custom test module. + assert_eq!( + >::block_weight().total(), + Weight::from_parts(175 + 175 + 10, 0) + ); + }) + } + + #[test] + fn runtime_upgraded_should_work() { + new_test_ext(1).execute_with(|| { + RuntimeVersionTestValues::mutate(|v| *v = Default::default()); + // It should be added at genesis + assert!(frame_system::LastRuntimeUpgrade::::exists()); + assert!(!Executive::runtime_upgraded()); + + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + assert!(Executive::runtime_upgraded()); + assert_eq!( + Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "".into() }), + frame_system::LastRuntimeUpgrade::::get(), + ); + + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { + spec_version: 1, + spec_name: "test".into(), + ..Default::default() + } + }); + assert!(Executive::runtime_upgraded()); + assert_eq!( + Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), + frame_system::LastRuntimeUpgrade::::get(), + ); + + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { + spec_version: 1, + spec_name: "test".into(), + impl_version: 2, + ..Default::default() + } + }); + assert!(!Executive::runtime_upgraded()); + + frame_system::LastRuntimeUpgrade::::take(); + assert!(Executive::runtime_upgraded()); + assert_eq!( + Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), + frame_system::LastRuntimeUpgrade::::get(), + ); + }) + } + + #[test] + fn last_runtime_upgrade_was_upgraded_works() { + let test_data = vec![ + (0, "", 1, "", true), + (1, "", 1, "", false), + (1, "", 1, "test", true), + (1, "", 0, "", false), + (1, "", 0, "test", true), + ]; + + for (spec_version, spec_name, c_spec_version, c_spec_name, result) in test_data { + let current = sp_version::RuntimeVersion { + spec_version: c_spec_version, + spec_name: c_spec_name.into(), + ..Default::default() + }; + + let last = LastRuntimeUpgradeInfo { + spec_version: spec_version.into(), + spec_name: spec_name.into(), + }; + + assert_eq!(result, last.was_upgraded(¤t)); + } + } + + #[test] + fn custom_runtime_upgrade_is_called_before_modules() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + }); + } + + #[test] + fn event_from_runtime_upgrade_is_included() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + // set block number to non zero so events are not excluded + System::set_block_number(1); + + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + System::assert_last_event(frame_system::Event::::CodeUpdated.into()); + }); + } + + /// Regression test that ensures that the custom on runtime upgrade is called when executive is + /// used through the `ExecuteBlock` trait. + #[test] + fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + + let header = new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + // Reset to get the correct new genesis below. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() } + }); + + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + >>::execute_block(Block::new(header, vec![xt])); + + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + }); + } + + #[test] + fn all_weights_are_recorded_correctly() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called for maximum complexity + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); + + let block_number = 1; + + Executive::initialize_block(&Header::new( + block_number, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + // All weights that show up in the `initialize_block_impl` + let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); + let runtime_upgrade_weight = + ::on_runtime_upgrade(); + let on_initialize_weight = + >::on_initialize(block_number); + let base_block_weight = + ::BlockWeights::get().base_block; + + // Weights are recorded correctly + assert_eq!( + frame_system::Pallet::::block_weight().total(), + custom_runtime_upgrade_weight + + runtime_upgrade_weight + + on_initialize_weight + base_block_weight, + ); + }); + } + + #[test] + fn offchain_worker_works_as_expected() { + new_test_ext(1).execute_with(|| { + let parent_hash = sp_core::H256::from([69u8; 32]); + let mut digest = Digest::default(); + digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); + + let header = + Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); + + Executive::offchain_worker(&header); + + assert_eq!(digest, System::digest()); + assert_eq!(parent_hash, System::block_hash(0)); + assert_eq!(header.hash(), System::block_hash(1)); + }); + } + + #[test] + fn calculating_storage_root_twice_works() { + let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); + let xt = TestXt::new(call, sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt])); + }); + } + + #[test] + #[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] + fn invalid_inherent_position_fail() { + let xt1 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); + } + + #[test] + fn valid_inherents_position_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); + } + + #[test] + #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] + fn invalid_inherents_fail_block_execution() { + let xt1 = + TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new( + Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + ), + vec![xt1], + )); + }); + } + + // Inherents are created by the runtime and don't need to be validated. + #[test] + fn inherents_fail_validate_block() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + + new_test_ext(1).execute_with(|| { + assert_eq!( + Executive::validate_transaction(TransactionSource::External, xt1, H256::random()) + .unwrap_err(), + InvalidTransaction::MandatoryValidation.into() + ); + }) + } +} From 5740d378ad6a3ad94a737596accbe243512e60f8 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 16:13:33 +0200 Subject: [PATCH 06/41] fmt Signed-off-by: Oliver Tale-Yazdi --- frame/executive/src/tests.rs | 1697 +++++++++++++++++----------------- 1 file changed, 848 insertions(+), 849 deletions(-) diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index e5ec1c41b0154..4f0ce633fe163 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -17,959 +17,958 @@ //! Test the `frame-executive` crate. -#[cfg(test)] -mod tests { - use super::*; - - use sp_core::H256; - use sp_runtime::{ - generic::{DigestItem, Era}, - testing::{Block, Digest, Header}, - traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, IdentityLookup}, - transaction_validity::{ - InvalidTransaction, TransactionValidityError, UnknownTransaction, ValidTransaction, - }, - DispatchError, - }; - - use frame_support::{ - assert_err, parameter_types, - traits::{fungible, ConstU32, ConstU64, ConstU8, Currency}, - weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee}, - }; - use frame_system::{ChainContext, LastRuntimeUpgradeInfo}; - use pallet_balances::Call as BalancesCall; - use pallet_transaction_payment::CurrencyAdapter; - - const TEST_KEY: &[u8] = b":test:key:"; - - #[frame_support::pallet(dev_mode)] - mod custom { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config {} - - #[pallet::hooks] - impl Hooks> for Pallet { - // module hooks. - // one with block number arg and one without - fn on_initialize(n: T::BlockNumber) -> Weight { - println!("on_initialize({})", n); - Weight::from_parts(175, 0) - } +#![cfg(test)] + +use super::*; + +use sp_core::H256; +use sp_runtime::{ + generic::{DigestItem, Era}, + testing::{Block, Digest, Header}, + traits::{BlakeTwo256, Block as BlockT, Header as HeaderT, IdentityLookup}, + transaction_validity::{ + InvalidTransaction, TransactionValidityError, UnknownTransaction, ValidTransaction, + }, + DispatchError, +}; + +use frame_support::{ + assert_err, parameter_types, + traits::{fungible, ConstU32, ConstU64, ConstU8, Currency}, + weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee}, +}; +use frame_system::{ChainContext, LastRuntimeUpgradeInfo}; +use pallet_balances::Call as BalancesCall; +use pallet_transaction_payment::CurrencyAdapter; + +const TEST_KEY: &[u8] = b":test:key:"; + +#[frame_support::pallet(dev_mode)] +mod custom { + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::hooks] + impl Hooks> for Pallet { + // module hooks. + // one with block number arg and one without + fn on_initialize(n: T::BlockNumber) -> Weight { + println!("on_initialize({})", n); + Weight::from_parts(175, 0) + } - fn on_idle(n: T::BlockNumber, remaining_weight: Weight) -> Weight { - println!("on_idle{}, {})", n, remaining_weight); - Weight::from_parts(175, 0) - } + fn on_idle(n: T::BlockNumber, remaining_weight: Weight) -> Weight { + println!("on_idle{}, {})", n, remaining_weight); + Weight::from_parts(175, 0) + } - fn on_finalize(n: T::BlockNumber) { - println!("on_finalize({})", n); - } + fn on_finalize(n: T::BlockNumber) { + println!("on_finalize({})", n); + } - fn on_runtime_upgrade() -> Weight { - sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); - Weight::from_parts(200, 0) - } + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(super::TEST_KEY, "module".as_bytes()); + Weight::from_parts(200, 0) + } - fn offchain_worker(n: T::BlockNumber) { - assert_eq!(T::BlockNumber::from(1u32), n); - } + fn offchain_worker(n: T::BlockNumber) { + assert_eq!(T::BlockNumber::from(1u32), n); } + } - #[pallet::call] - impl Pallet { - pub fn some_function(origin: OriginFor) -> DispatchResult { - // NOTE: does not make any different. - frame_system::ensure_signed(origin)?; - Ok(()) - } + #[pallet::call] + impl Pallet { + pub fn some_function(origin: OriginFor) -> DispatchResult { + // NOTE: does not make any different. + frame_system::ensure_signed(origin)?; + Ok(()) + } - #[pallet::weight((200, DispatchClass::Operational))] - pub fn some_root_operation(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } + #[pallet::weight((200, DispatchClass::Operational))] + pub fn some_root_operation(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } - pub fn some_unsigned_message(origin: OriginFor) -> DispatchResult { - frame_system::ensure_none(origin)?; - Ok(()) - } + pub fn some_unsigned_message(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + Ok(()) + } - pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } + pub fn allowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } - pub fn unallowed_unsigned(origin: OriginFor) -> DispatchResult { - frame_system::ensure_root(origin)?; - Ok(()) - } + pub fn unallowed_unsigned(origin: OriginFor) -> DispatchResult { + frame_system::ensure_root(origin)?; + Ok(()) + } - #[pallet::weight((0, DispatchClass::Mandatory))] - pub fn inherent_call(origin: OriginFor) -> DispatchResult { - frame_system::ensure_none(origin)?; - Ok(()) - } + #[pallet::weight((0, DispatchClass::Mandatory))] + pub fn inherent_call(origin: OriginFor) -> DispatchResult { + frame_system::ensure_none(origin)?; + Ok(()) + } - pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { - let root = sp_io::storage::root(sp_runtime::StateVersion::V1); - sp_io::storage::set("storage_root".as_bytes(), &root); - Ok(()) - } + pub fn calculate_storage_root(_origin: OriginFor) -> DispatchResult { + let root = sp_io::storage::root(sp_runtime::StateVersion::V1); + sp_io::storage::set("storage_root".as_bytes(), &root); + Ok(()) } + } - #[pallet::inherent] - impl ProvideInherent for Pallet { - type Call = Call; + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; - type Error = sp_inherents::MakeFatalError<()>; + type Error = sp_inherents::MakeFatalError<()>; - const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234"; + const INHERENT_IDENTIFIER: [u8; 8] = *b"test1234"; - fn create_inherent(_data: &InherentData) -> Option { - None - } + fn create_inherent(_data: &InherentData) -> Option { + None + } - fn is_inherent(call: &Self::Call) -> bool { - *call == Call::::inherent_call {} - } + fn is_inherent(call: &Self::Call) -> bool { + *call == Call::::inherent_call {} } + } - #[pallet::validate_unsigned] - impl ValidateUnsigned for Pallet { - type Call = Call; - - // Inherent call is accepted for being dispatched - fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { - match call { - Call::allowed_unsigned { .. } => Ok(()), - Call::inherent_call { .. } => Ok(()), - _ => Err(UnknownTransaction::NoUnsignedValidator.into()), - } - } + #[pallet::validate_unsigned] + impl ValidateUnsigned for Pallet { + type Call = Call; - // Inherent call is not validated as unsigned - fn validate_unsigned( - _source: TransactionSource, - call: &Self::Call, - ) -> TransactionValidity { - match call { - Call::allowed_unsigned { .. } => Ok(Default::default()), - _ => UnknownTransaction::NoUnsignedValidator.into(), - } + // Inherent call is accepted for being dispatched + fn pre_dispatch(call: &Self::Call) -> Result<(), TransactionValidityError> { + match call { + Call::allowed_unsigned { .. } => Ok(()), + Call::inherent_call { .. } => Ok(()), + _ => Err(UnknownTransaction::NoUnsignedValidator.into()), } } - } - frame_support::construct_runtime!( - pub struct Runtime where - Block = TestBlock, - NodeBlock = TestBlock, - UncheckedExtrinsic = TestUncheckedExtrinsic - { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, - Custom: custom::{Pallet, Call, ValidateUnsigned, Inherent}, + // Inherent call is not validated as unsigned + fn validate_unsigned( + _source: TransactionSource, + call: &Self::Call, + ) -> TransactionValidity { + match call { + Call::allowed_unsigned { .. } => Ok(Default::default()), + _ => UnknownTransaction::NoUnsignedValidator.into(), + } } - ); - - parameter_types! { - pub BlockWeights: frame_system::limits::BlockWeights = - frame_system::limits::BlockWeights::builder() - .base_block(Weight::from_parts(10, 0)) - .for_class(DispatchClass::all(), |weights| weights.base_extrinsic = Weight::from_parts(5, 0)) - .for_class(DispatchClass::non_mandatory(), |weights| weights.max_total = Weight::from_parts(1024, u64::MAX).into()) - .build_or_panic(); - pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { - read: 10, - write: 100, - }; - } - impl frame_system::Config for Runtime { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = BlockWeights; - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type Index = u64; - type RuntimeCall = RuntimeCall; - type BlockNumber = u64; - type Hash = sp_core::H256; - type Hashing = BlakeTwo256; - type AccountId = u64; - type Lookup = IdentityLookup; - type Header = Header; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = RuntimeVersion; - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); - type MaxConsumers = ConstU32<16>; } +} - type Balance = u64; - impl pallet_balances::Config for Runtime { - type Balance = Balance; - type RuntimeEvent = RuntimeEvent; - type DustRemoval = (); - type ExistentialDeposit = ConstU64<1>; - type AccountStore = System; - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); - type FreezeIdentifier = (); - type MaxFreezes = ConstU32<1>; - type RuntimeHoldReason = (); - type MaxHolds = ConstU32<1>; - } +frame_support::construct_runtime!( + pub struct Runtime where + Block = TestBlock, + NodeBlock = TestBlock, + UncheckedExtrinsic = TestUncheckedExtrinsic + { + System: frame_system::{Pallet, Call, Config, Storage, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event}, + Custom: custom::{Pallet, Call, ValidateUnsigned, Inherent}, + } +); + +parameter_types! { + pub BlockWeights: frame_system::limits::BlockWeights = + frame_system::limits::BlockWeights::builder() + .base_block(Weight::from_parts(10, 0)) + .for_class(DispatchClass::all(), |weights| weights.base_extrinsic = Weight::from_parts(5, 0)) + .for_class(DispatchClass::non_mandatory(), |weights| weights.max_total = Weight::from_parts(1024, u64::MAX).into()) + .build_or_panic(); + pub const DbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 10, + write: 100, + }; +} +impl frame_system::Config for Runtime { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = BlockWeights; + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type Index = u64; + type RuntimeCall = RuntimeCall; + type BlockNumber = u64; + type Hash = sp_core::H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = RuntimeVersion; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} - parameter_types! { - pub const TransactionByteFee: Balance = 0; - } - impl pallet_transaction_payment::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type OnChargeTransaction = CurrencyAdapter; - type OperationalFeeMultiplier = ConstU8<5>; - type WeightToFee = IdentityFee; - type LengthToFee = ConstantMultiplier; - type FeeMultiplierUpdate = (); - } - impl custom::Config for Runtime {} +type Balance = u64; +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); + type FreezeIdentifier = (); + type MaxFreezes = ConstU32<1>; + type RuntimeHoldReason = (); + type MaxHolds = ConstU32<1>; +} - pub struct RuntimeVersion; - impl frame_support::traits::Get for RuntimeVersion { - fn get() -> sp_version::RuntimeVersion { - RuntimeVersionTestValues::get().clone() - } - } +parameter_types! { + pub const TransactionByteFee: Balance = 0; +} +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = CurrencyAdapter; + type OperationalFeeMultiplier = ConstU8<5>; + type WeightToFee = IdentityFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = (); +} +impl custom::Config for Runtime {} - parameter_types! { - pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = - Default::default(); +pub struct RuntimeVersion; +impl frame_support::traits::Get for RuntimeVersion { + fn get() -> sp_version::RuntimeVersion { + RuntimeVersionTestValues::get().clone() } +} - type SignedExtra = ( - frame_system::CheckEra, - frame_system::CheckNonce, - frame_system::CheckWeight, - pallet_transaction_payment::ChargeTransactionPayment, - ); - type TestXt = sp_runtime::testing::TestXt; - type TestBlock = Block; - type TestUncheckedExtrinsic = TestXt; - - // Will contain `true` when the custom runtime logic was called. - const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; - - struct CustomOnRuntimeUpgrade; - impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { - fn on_runtime_upgrade() -> Weight { - sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); - sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); - System::deposit_event(frame_system::Event::CodeUpdated); - Weight::from_parts(100, 0) - } - } +parameter_types! { + pub static RuntimeVersionTestValues: sp_version::RuntimeVersion = + Default::default(); +} - type Executive = super::Executive< - Runtime, - Block, - ChainContext, - Runtime, - AllPalletsWithSystem, - CustomOnRuntimeUpgrade, - >; - - fn extra(nonce: u64, fee: Balance) -> SignedExtra { - ( - frame_system::CheckEra::from(Era::Immortal), - frame_system::CheckNonce::from(nonce), - frame_system::CheckWeight::new(), - pallet_transaction_payment::ChargeTransactionPayment::from(fee), - ) +type SignedExtra = ( + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); +type TestXt = sp_runtime::testing::TestXt; +type TestBlock = Block; +type TestUncheckedExtrinsic = TestXt; + +// Will contain `true` when the custom runtime logic was called. +const CUSTOM_ON_RUNTIME_KEY: &[u8] = b":custom:on_runtime"; + +struct CustomOnRuntimeUpgrade; +impl OnRuntimeUpgrade for CustomOnRuntimeUpgrade { + fn on_runtime_upgrade() -> Weight { + sp_io::storage::set(TEST_KEY, "custom_upgrade".as_bytes()); + sp_io::storage::set(CUSTOM_ON_RUNTIME_KEY, &true.encode()); + System::deposit_event(frame_system::Event::CodeUpdated); + Weight::from_parts(100, 0) } +} - fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { - Some((who, extra(nonce, fee))) - } +type Executive = super::Executive< + Runtime, + Block, + ChainContext, + Runtime, + AllPalletsWithSystem, + CustomOnRuntimeUpgrade, +>; + +fn extra(nonce: u64, fee: Balance) -> SignedExtra { + ( + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(nonce), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(fee), + ) +} - fn call_transfer(dest: u64, value: u64) -> RuntimeCall { - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) - } +fn sign_extra(who: u64, nonce: u64, fee: Balance) -> Option<(u64, SignedExtra)> { + Some((who, extra(nonce, fee))) +} - #[test] - fn balance_transfer_dispatch_works() { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } - .assimilate_storage(&mut t) - .unwrap(); - let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); - let weight = xt.get_dispatch_info().weight + - ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - let fee: Balance = - ::WeightToFee::weight_to_fee(&weight); - let mut t = sp_io::TestExternalities::new(t); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - let r = Executive::apply_extrinsic(xt); - assert!(r.is_ok()); - assert_eq!(>::total_balance(&1), 142 - fee); - assert_eq!(>::total_balance(&2), 69); - }); - } +fn call_transfer(dest: u64, value: u64) -> RuntimeCall { + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest, value }) +} - fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } - .assimilate_storage(&mut t) - .unwrap(); - t.into() - } +#[test] +fn balance_transfer_dispatch_works() { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 211)] } + .assimilate_storage(&mut t) + .unwrap(); + let xt = TestXt::new(call_transfer(2, 69), sign_extra(1, 0, 0)); + let weight = xt.get_dispatch_info().weight + + ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + let fee: Balance = + ::WeightToFee::weight_to_fee(&weight); + let mut t = sp_io::TestExternalities::new(t); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + let r = Executive::apply_extrinsic(xt); + assert!(r.is_ok()); + assert_eq!(>::total_balance(&1), 142 - fee); + assert_eq!(>::total_balance(&2), 69); + }); +} - fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } - .assimilate_storage(&mut t) - .unwrap(); - (t, sp_runtime::StateVersion::V0).into() - } +fn new_test_ext(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + t.into() +} - #[test] - fn block_import_works() { - block_import_works_inner( - new_test_ext_v0(1), - array_bytes::hex_n_into_unchecked( - "65e953676859e7a33245908af7ad3637d6861eb90416d433d485e95e2dd174a1", - ), - ); - block_import_works_inner( - new_test_ext(1), - array_bytes::hex_n_into_unchecked( - "5a19b3d6fdb7241836349fdcbe2d9df4d4f945b949d979e31ad50bff1cbcd1c2", - ), - ); - } - fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { - ext.execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root, - extrinsics_root: array_bytes::hex_n_into_unchecked( - "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", - ), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); - }); - } +fn new_test_ext_v0(balance_factor: Balance) -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + pallet_balances::GenesisConfig:: { balances: vec![(1, 111 * balance_factor)] } + .assimilate_storage(&mut t) + .unwrap(); + (t, sp_runtime::StateVersion::V0).into() +} - #[test] - #[should_panic] - fn block_import_of_bad_state_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: [0u8; 32].into(), - extrinsics_root: array_bytes::hex_n_into_unchecked( - "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", - ), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); +#[test] +fn block_import_works() { + block_import_works_inner( + new_test_ext_v0(1), + array_bytes::hex_n_into_unchecked( + "65e953676859e7a33245908af7ad3637d6861eb90416d433d485e95e2dd174a1", + ), + ); + block_import_works_inner( + new_test_ext(1), + array_bytes::hex_n_into_unchecked( + "5a19b3d6fdb7241836349fdcbe2d9df4d4f945b949d979e31ad50bff1cbcd1c2", + ), + ); +} +fn block_import_works_inner(mut ext: sp_io::TestExternalities, state_root: H256) { + ext.execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root, + extrinsics_root: array_bytes::hex_n_into_unchecked( + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + ), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], }); - } + }); +} - #[test] - #[should_panic] - fn block_import_of_bad_extrinsic_root_fails() { - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block { - header: Header { - parent_hash: [69u8; 32].into(), - number: 1, - state_root: array_bytes::hex_n_into_unchecked( - "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5", - ), - extrinsics_root: [0u8; 32].into(), - digest: Digest { logs: vec![] }, - }, - extrinsics: vec![], - }); +#[test] +#[should_panic] +fn block_import_of_bad_state_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: [0u8; 32].into(), + extrinsics_root: array_bytes::hex_n_into_unchecked( + "03170a2e7597b7b7e3d84c05391d139a62b157e78786d8c082f29dcf4c111314", + ), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], }); - } + }); +} - #[test] - fn bad_extrinsic_not_inserted() { - let mut t = new_test_ext(1); - // bad nonce check! - let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - assert_err!( - Executive::apply_extrinsic(xt), - TransactionValidityError::Invalid(InvalidTransaction::Future) - ); - assert_eq!(>::extrinsic_index(), Some(0)); +#[test] +#[should_panic] +fn block_import_of_bad_extrinsic_root_fails() { + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block { + header: Header { + parent_hash: [69u8; 32].into(), + number: 1, + state_root: array_bytes::hex_n_into_unchecked( + "75e7d8f360d375bbe91bcf8019c01ab6362448b4a89e3b329717eb9d910340e5", + ), + extrinsics_root: [0u8; 32].into(), + digest: Digest { logs: vec![] }, + }, + extrinsics: vec![], }); - } + }); +} - #[test] - fn block_weight_limit_enforced() { - let mut t = new_test_ext(10000); - // given: TestXt uses the encoded len as fixed Len: - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), +#[test] +fn bad_extrinsic_not_inserted() { + let mut t = new_test_ext(1); + // bad nonce check! + let xt = TestXt::new(call_transfer(33, 69), sign_extra(1, 30, 0)); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + assert_err!( + Executive::apply_extrinsic(xt), + TransactionValidityError::Invalid(InvalidTransaction::Future) ); - let encoded = xt.encode(); - let encoded_len = encoded.len() as u64; - // on_initialize weight + base block execution weight - let block_weights = ::BlockWeights::get(); - let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; - let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; - let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); - t.execute_with(|| { - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - // Base block execution weight + `on_initialize` weight from the custom module. - assert_eq!(>::block_weight().total(), base_block_weight); - - for nonce in 0..=num_to_exhaust_block { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { - dest: 33, - value: 0, - }), - sign_extra(1, nonce.into(), 0), + assert_eq!(>::extrinsic_index(), Some(0)); + }); +} + +#[test] +fn block_weight_limit_enforced() { + let mut t = new_test_ext(10000); + // given: TestXt uses the encoded len as fixed Len: + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let encoded = xt.encode(); + let encoded_len = encoded.len() as u64; + // on_initialize weight + base block execution weight + let block_weights = ::BlockWeights::get(); + let base_block_weight = Weight::from_parts(175, 0) + block_weights.base_block; + let limit = block_weights.get(DispatchClass::Normal).max_total.unwrap() - base_block_weight; + let num_to_exhaust_block = limit.ref_time() / (encoded_len + 5); + t.execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + // Base block execution weight + `on_initialize` weight from the custom module. + assert_eq!(>::block_weight().total(), base_block_weight); + + for nonce in 0..=num_to_exhaust_block { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { + dest: 33, + value: 0, + }), + sign_extra(1, nonce.into(), 0), + ); + let res = Executive::apply_extrinsic(xt); + if nonce != num_to_exhaust_block { + assert!(res.is_ok()); + assert_eq!( + >::block_weight().total(), + //--------------------- on_initialize + block_execution + extrinsic_base weight + Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, ); - let res = Executive::apply_extrinsic(xt); - if nonce != num_to_exhaust_block { - assert!(res.is_ok()); - assert_eq!( - >::block_weight().total(), - //--------------------- on_initialize + block_execution + extrinsic_base weight - Weight::from_parts((encoded_len + 5) * (nonce + 1), 0) + base_block_weight, - ); - assert_eq!( - >::extrinsic_index(), - Some(nonce as u32 + 1) - ); - } else { - assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); - } + assert_eq!( + >::extrinsic_index(), + Some(nonce as u32 + 1) + ); + } else { + assert_eq!(res, Err(InvalidTransaction::ExhaustsResources.into())); } - }); - } + } + }); +} - #[test] - fn block_weight_and_size_is_stored_per_tx() { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), +#[test] +fn block_weight_and_size_is_stored_per_tx() { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let x1 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 1, 0), + ); + let x2 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 2, 0), + ); + let len = xt.clone().encode().len() as u32; + let mut t = new_test_ext(1); + t.execute_with(|| { + // Block execution weight + on_initialize weight from custom module + let base_block_weight = Weight::from_parts(175, 0) + + ::BlockWeights::get().base_block; + + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(>::block_weight().total(), base_block_weight); + assert_eq!(>::all_extrinsics_len(), 0); + + assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); + assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); + + // default weight for `TestXt` == encoded length. + let extrinsic_weight = Weight::from_parts(len as u64, 0) + + ::BlockWeights::get() + .get(DispatchClass::Normal) + .base_extrinsic; + assert_eq!( + >::block_weight().total(), + base_block_weight + 3u64 * extrinsic_weight, ); - let x1 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 1, 0), + assert_eq!(>::all_extrinsics_len(), 3 * len); + + let _ = >::finalize(); + // All extrinsics length cleaned on `System::finalize` + assert_eq!(>::all_extrinsics_len(), 0); + + // New Block + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + // Block weight cleaned up on `System::initialize` + assert_eq!(>::block_weight().total(), base_block_weight); + }); +} + +#[test] +fn validate_unsigned() { + let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); + let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); + let mut t = new_test_ext(1); + + t.execute_with(|| { + assert_eq!( + Executive::validate_transaction( + TransactionSource::InBlock, + valid.clone(), + Default::default(), + ), + Ok(ValidTransaction::default()), ); - let x2 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 2, 0), + assert_eq!( + Executive::validate_transaction( + TransactionSource::InBlock, + invalid.clone(), + Default::default(), + ), + Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)), ); - let len = xt.clone().encode().len() as u32; - let mut t = new_test_ext(1); - t.execute_with(|| { - // Block execution weight + on_initialize weight from custom module - let base_block_weight = Weight::from_parts(175, 0) + - ::BlockWeights::get().base_block; - - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - assert_eq!(>::block_weight().total(), base_block_weight); - assert_eq!(>::all_extrinsics_len(), 0); - - assert!(Executive::apply_extrinsic(xt.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x1.clone()).unwrap().is_ok()); - assert!(Executive::apply_extrinsic(x2.clone()).unwrap().is_ok()); - - // default weight for `TestXt` == encoded length. - let extrinsic_weight = Weight::from_parts(len as u64, 0) + - ::BlockWeights::get() - .get(DispatchClass::Normal) - .base_extrinsic; - assert_eq!( - >::block_weight().total(), - base_block_weight + 3u64 * extrinsic_weight, - ); - assert_eq!(>::all_extrinsics_len(), 3 * len); + assert_eq!(Executive::apply_extrinsic(valid), Ok(Err(DispatchError::BadOrigin))); + assert_eq!( + Executive::apply_extrinsic(invalid), + Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)) + ); + }); +} - let _ = >::finalize(); - // All extrinsics length cleaned on `System::finalize` - assert_eq!(>::all_extrinsics_len(), 0); +#[test] +fn can_not_pay_for_tx_fee_on_full_lock() { + let mut t = new_test_ext(1); + t.execute_with(|| { + as fungible::MutateFreeze>::set_freeze( + &(), + &1, + 110, + ) + .unwrap(); + let xt = TestXt::new( + RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), + sign_extra(1, 0, 0), + ); + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(Executive::apply_extrinsic(xt), Err(InvalidTransaction::Payment.into()),); + assert_eq!(>::total_balance(&1), 111); + }); +} - // New Block - Executive::initialize_block(&Header::new( - 2, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); +#[test] +fn block_hooks_weight_is_stored() { + new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new_from_number(1)); + Executive::finalize_block(); + // NOTE: might need updates over time if new weights are introduced. + // For now it only accounts for the base block execution weight and + // the `on_initialize` weight defined in the custom test module. + assert_eq!( + >::block_weight().total(), + Weight::from_parts(175 + 175 + 10, 0) + ); + }) +} - // Block weight cleaned up on `System::initialize` - assert_eq!(>::block_weight().total(), base_block_weight); - }); - } +#[test] +fn runtime_upgraded_should_work() { + new_test_ext(1).execute_with(|| { + RuntimeVersionTestValues::mutate(|v| *v = Default::default()); + // It should be added at genesis + assert!(frame_system::LastRuntimeUpgrade::::exists()); + assert!(!Executive::runtime_upgraded()); - #[test] - fn validate_unsigned() { - let valid = TestXt::new(RuntimeCall::Custom(custom::Call::allowed_unsigned {}), None); - let invalid = TestXt::new(RuntimeCall::Custom(custom::Call::unallowed_unsigned {}), None); - let mut t = new_test_ext(1); - - t.execute_with(|| { - assert_eq!( - Executive::validate_transaction( - TransactionSource::InBlock, - valid.clone(), - Default::default(), - ), - Ok(ValidTransaction::default()), - ); - assert_eq!( - Executive::validate_transaction( - TransactionSource::InBlock, - invalid.clone(), - Default::default(), - ), - Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)), - ); - assert_eq!(Executive::apply_extrinsic(valid), Ok(Err(DispatchError::BadOrigin))); - assert_eq!( - Executive::apply_extrinsic(invalid), - Err(TransactionValidityError::Unknown(UnknownTransaction::NoUnsignedValidator)) - ); + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - } - - #[test] - fn can_not_pay_for_tx_fee_on_full_lock() { - let mut t = new_test_ext(1); - t.execute_with(|| { - as fungible::MutateFreeze>::set_freeze( - &(), - &1, - 110, - ) - .unwrap(); - let xt = TestXt::new( - RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), - sign_extra(1, 0, 0), - ); - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); + assert!(Executive::runtime_upgraded()); + assert_eq!( + Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "".into() }), + frame_system::LastRuntimeUpgrade::::get(), + ); - assert_eq!(Executive::apply_extrinsic(xt), Err(InvalidTransaction::Payment.into()),); - assert_eq!(>::total_balance(&1), 111); + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { + spec_version: 1, + spec_name: "test".into(), + ..Default::default() + } }); - } - - #[test] - fn block_hooks_weight_is_stored() { - new_test_ext(1).execute_with(|| { - Executive::initialize_block(&Header::new_from_number(1)); - Executive::finalize_block(); - // NOTE: might need updates over time if new weights are introduced. - // For now it only accounts for the base block execution weight and - // the `on_initialize` weight defined in the custom test module. - assert_eq!( - >::block_weight().total(), - Weight::from_parts(175 + 175 + 10, 0) - ); - }) - } - - #[test] - fn runtime_upgraded_should_work() { - new_test_ext(1).execute_with(|| { - RuntimeVersionTestValues::mutate(|v| *v = Default::default()); - // It should be added at genesis - assert!(frame_system::LastRuntimeUpgrade::::exists()); - assert!(!Executive::runtime_upgraded()); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - assert!(Executive::runtime_upgraded()); - assert_eq!( - Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "".into() }), - frame_system::LastRuntimeUpgrade::::get(), - ); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { - spec_version: 1, - spec_name: "test".into(), - ..Default::default() - } - }); - assert!(Executive::runtime_upgraded()); - assert_eq!( - Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), - frame_system::LastRuntimeUpgrade::::get(), - ); - - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { - spec_version: 1, - spec_name: "test".into(), - impl_version: 2, - ..Default::default() - } - }); - assert!(!Executive::runtime_upgraded()); - - frame_system::LastRuntimeUpgrade::::take(); - assert!(Executive::runtime_upgraded()); - assert_eq!( - Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), - frame_system::LastRuntimeUpgrade::::get(), - ); - }) - } + assert!(Executive::runtime_upgraded()); + assert_eq!( + Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), + frame_system::LastRuntimeUpgrade::::get(), + ); - #[test] - fn last_runtime_upgrade_was_upgraded_works() { - let test_data = vec![ - (0, "", 1, "", true), - (1, "", 1, "", false), - (1, "", 1, "test", true), - (1, "", 0, "", false), - (1, "", 0, "test", true), - ]; - - for (spec_version, spec_name, c_spec_version, c_spec_name, result) in test_data { - let current = sp_version::RuntimeVersion { - spec_version: c_spec_version, - spec_name: c_spec_name.into(), + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { + spec_version: 1, + spec_name: "test".into(), + impl_version: 2, ..Default::default() - }; - - let last = LastRuntimeUpgradeInfo { - spec_version: spec_version.into(), - spec_name: spec_name.into(), - }; + } + }); + assert!(!Executive::runtime_upgraded()); - assert_eq!(result, last.was_upgraded(¤t)); - } - } + frame_system::LastRuntimeUpgrade::::take(); + assert!(Executive::runtime_upgraded()); + assert_eq!( + Some(LastRuntimeUpgradeInfo { spec_version: 1.into(), spec_name: "test".into() }), + frame_system::LastRuntimeUpgrade::::get(), + ); + }) +} - #[test] - fn custom_runtime_upgrade_is_called_before_modules() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); +#[test] +fn last_runtime_upgrade_was_upgraded_works() { + let test_data = vec![ + (0, "", 1, "", true), + (1, "", 1, "", false), + (1, "", 1, "test", true), + (1, "", 0, "", false), + (1, "", 0, "test", true), + ]; + + for (spec_version, spec_name, c_spec_version, c_spec_name, result) in test_data { + let current = sp_version::RuntimeVersion { + spec_version: c_spec_version, + spec_name: c_spec_name.into(), + ..Default::default() + }; - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); + let last = LastRuntimeUpgradeInfo { + spec_version: spec_version.into(), + spec_name: spec_name.into(), + }; - assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); - assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); - }); + assert_eq!(result, last.was_upgraded(¤t)); } +} - #[test] - fn event_from_runtime_upgrade_is_included() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - // set block number to non zero so events are not excluded - System::set_block_number(1); +#[test] +fn custom_runtime_upgrade_is_called_before_modules() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } + }); - Executive::initialize_block(&Header::new( - 2, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + }); +} - System::assert_last_event(frame_system::Event::::CodeUpdated.into()); +#[test] +fn event_from_runtime_upgrade_is_included() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - } - /// Regression test that ensures that the custom on runtime upgrade is called when executive is - /// used through the `ExecuteBlock` trait. - #[test] - fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { - let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); + // set block number to non zero so events are not excluded + System::set_block_number(1); - let header = new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); - - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); + Executive::initialize_block(&Header::new( + 2, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); - Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + System::assert_last_event(frame_system::Event::::CodeUpdated.into()); + }); +} - Executive::finalize_block() - }); +/// Regression test that ensures that the custom on runtime upgrade is called when executive is +/// used through the `ExecuteBlock` trait. +#[test] +fn custom_runtime_upgrade_is_called_when_using_execute_block_trait() { + let xt = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); - // Reset to get the correct new genesis below. + let header = new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() } + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called. - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); - >>::execute_block(Block::new(header, vec![xt])); + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); - assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); - assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); - }); - } + Executive::finalize_block() + }); - #[test] - fn all_weights_are_recorded_correctly() { - new_test_ext(1).execute_with(|| { - // Make sure `on_runtime_upgrade` is called for maximum complexity - RuntimeVersionTestValues::mutate(|v| { - *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } - }); + // Reset to get the correct new genesis below. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 0, ..Default::default() } + }); - let block_number = 1; - - Executive::initialize_block(&Header::new( - block_number, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - - // All weights that show up in the `initialize_block_impl` - let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); - let runtime_upgrade_weight = - ::on_runtime_upgrade(); - let on_initialize_weight = - >::on_initialize(block_number); - let base_block_weight = - ::BlockWeights::get().base_block; - - // Weights are recorded correctly - assert_eq!( - frame_system::Pallet::::block_weight().total(), - custom_runtime_upgrade_weight + - runtime_upgrade_weight + - on_initialize_weight + base_block_weight, - ); + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called. + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - } - - #[test] - fn offchain_worker_works_as_expected() { - new_test_ext(1).execute_with(|| { - let parent_hash = sp_core::H256::from([69u8; 32]); - let mut digest = Digest::default(); - digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); - let header = - Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); + >>::execute_block(Block::new(header, vec![xt])); - Executive::offchain_worker(&header); + assert_eq!(&sp_io::storage::get(TEST_KEY).unwrap()[..], *b"module"); + assert_eq!(sp_io::storage::get(CUSTOM_ON_RUNTIME_KEY).unwrap(), true.encode()); + }); +} - assert_eq!(digest, System::digest()); - assert_eq!(parent_hash, System::block_hash(0)); - assert_eq!(header.hash(), System::block_hash(1)); +#[test] +fn all_weights_are_recorded_correctly() { + new_test_ext(1).execute_with(|| { + // Make sure `on_runtime_upgrade` is called for maximum complexity + RuntimeVersionTestValues::mutate(|v| { + *v = sp_version::RuntimeVersion { spec_version: 1, ..Default::default() } }); - } - - #[test] - fn calculating_storage_root_twice_works() { - let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); - let xt = TestXt::new(call, sign_extra(1, 0, 0)); - - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); - Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + let block_number = 1; + + Executive::initialize_block(&Header::new( + block_number, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + // All weights that show up in the `initialize_block_impl` + let custom_runtime_upgrade_weight = CustomOnRuntimeUpgrade::on_runtime_upgrade(); + let runtime_upgrade_weight = + ::on_runtime_upgrade(); + let on_initialize_weight = + >::on_initialize(block_number); + let base_block_weight = + ::BlockWeights::get().base_block; + + // Weights are recorded correctly + assert_eq!( + frame_system::Pallet::::block_weight().total(), + custom_runtime_upgrade_weight + + runtime_upgrade_weight + + on_initialize_weight + base_block_weight, + ); + }); +} - Executive::finalize_block() - }); +#[test] +fn offchain_worker_works_as_expected() { + new_test_ext(1).execute_with(|| { + let parent_hash = sp_core::H256::from([69u8; 32]); + let mut digest = Digest::default(); + digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt])); - }); - } + let header = + Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); - #[test] - #[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] - fn invalid_inherent_position_fail() { - let xt1 = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), - sign_extra(1, 0, 0), - ); - let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + Executive::offchain_worker(&header); - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - )); + assert_eq!(digest, System::digest()); + assert_eq!(parent_hash, System::block_hash(0)); + assert_eq!(header.hash(), System::block_hash(1)); + }); +} - Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); +#[test] +fn calculating_storage_root_twice_works() { + let call = RuntimeCall::Custom(custom::Call::calculate_storage_root {}); + let xt = TestXt::new(call, sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt])); + }); +} - Executive::finalize_block() - }); +#[test] +#[should_panic(expected = "Invalid inherent position for extrinsic at index 1")] +fn invalid_inherent_position_fail() { + let xt1 = TestXt::new( + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), + sign_extra(1, 0, 0), + ); + let xt2 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); - }); - } +#[test] +fn valid_inherents_position_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} - #[test] - fn valid_inherents_position_works() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); +#[test] +#[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] +fn invalid_inherents_fail_block_execution() { + let xt1 = + TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); - let header = new_test_ext(1).execute_with(|| { - // Let's build some fake block. - Executive::initialize_block(&Header::new( + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new( + Header::new( 1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default(), - )); - - Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); - - Executive::finalize_block() - }); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); - }); - } - - #[test] - #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] - fn invalid_inherents_fail_block_execution() { - let xt1 = - TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); - - new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new( - Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - ), - vec![xt1], - )); - }); - } + ), + vec![xt1], + )); + }); +} - // Inherents are created by the runtime and don't need to be validated. - #[test] - fn inherents_fail_validate_block() { - let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); +// Inherents are created by the runtime and don't need to be validated. +#[test] +fn inherents_fail_validate_block() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - new_test_ext(1).execute_with(|| { - assert_eq!( - Executive::validate_transaction(TransactionSource::External, xt1, H256::random()) - .unwrap_err(), - InvalidTransaction::MandatoryValidation.into() - ); - }) - } + new_test_ext(1).execute_with(|| { + assert_eq!( + Executive::validate_transaction(TransactionSource::External, xt1, H256::random()) + .unwrap_err(), + InvalidTransaction::MandatoryValidation.into() + ); + }) } From 911111d79211bfb0b9d0b5537712e31f990875cc Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 17:16:35 +0200 Subject: [PATCH 07/41] Add test Signed-off-by: Oliver Tale-Yazdi --- frame/executive/src/lib.rs | 13 ++++- frame/executive/src/tests.rs | 95 ++++++++++++++++++++++++------------ 2 files changed, 76 insertions(+), 32 deletions(-) diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index d6a251082e07c..b4832e07311fd 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -116,6 +116,9 @@ #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(test)] +mod tests; + use codec::{Codec, Encode}; use frame_support::{ dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo}, @@ -499,6 +502,7 @@ where } }, BlockAfterInherentsMode::ExtrinsicsAllowed => { + dbg!(num_inherents, applyables.len()); Self::execute_applyables(applyables.iter().skip(num_inherents)); }, } @@ -519,9 +523,14 @@ where /// This is always called by the block builder. It returns whether extrinsics are allowed to be /// included in the block or not. pub fn after_inherents() -> BlockAfterInherentsMode { - // TODO MBMs and `poll` will add a condition. + // TODO add a proper condition here, but now we need this for mocking in tests. + // // - // + #[cfg(all(feature = "std", test))] + if sp_io::storage::exists(&b":extrinsics_forbidden"[..]) { + return BlockAfterInherentsMode::ExtrinsicsForbidden + } + BlockAfterInherentsMode::ExtrinsicsAllowed } diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index 4f0ce633fe163..58825f9adc405 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -17,8 +17,6 @@ //! Test the `frame-executive` crate. -#![cfg(test)] - use super::*; use sp_core::H256; @@ -155,10 +153,7 @@ mod custom { } // Inherent call is not validated as unsigned - fn validate_unsigned( - _source: TransactionSource, - call: &Self::Call, - ) -> TransactionValidity { + fn validate_unsigned(_source: TransactionSource, call: &Self::Call) -> TransactionValidity { match call { Call::allowed_unsigned { .. } => Ok(Default::default()), _ => UnknownTransaction::NoUnsignedValidator.into(), @@ -474,10 +469,7 @@ fn block_weight_limit_enforced() { for nonce in 0..=num_to_exhaust_block { let xt = TestXt::new( - RuntimeCall::Balances(BalancesCall::transfer_allow_death { - dest: 33, - value: 0, - }), + RuntimeCall::Balances(BalancesCall::transfer_allow_death { dest: 33, value: 0 }), sign_extra(1, nonce.into(), 0), ); let res = Executive::apply_extrinsic(xt); @@ -599,12 +591,8 @@ fn validate_unsigned() { fn can_not_pay_for_tx_fee_on_full_lock() { let mut t = new_test_ext(1); t.execute_with(|| { - as fungible::MutateFreeze>::set_freeze( - &(), - &1, - 110, - ) - .unwrap(); + as fungible::MutateFreeze>::set_freeze(&(), &1, 110) + .unwrap(); let xt = TestXt::new( RuntimeCall::System(frame_system::Call::remark { remark: vec![1u8] }), sign_extra(1, 0, 0), @@ -827,15 +815,15 @@ fn all_weights_are_recorded_correctly() { ::on_runtime_upgrade(); let on_initialize_weight = >::on_initialize(block_number); - let base_block_weight = - ::BlockWeights::get().base_block; + let base_block_weight = ::BlockWeights::get().base_block; // Weights are recorded correctly assert_eq!( frame_system::Pallet::::block_weight().total(), custom_runtime_upgrade_weight + runtime_upgrade_weight + - on_initialize_weight + base_block_weight, + on_initialize_weight + + base_block_weight, ); }); } @@ -847,8 +835,7 @@ fn offchain_worker_works_as_expected() { let mut digest = Digest::default(); digest.push(DigestItem::Seal([1, 2, 3, 4], vec![5, 6, 7, 8])); - let header = - Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); + let header = Header::new(1, H256::default(), H256::default(), parent_hash, digest.clone()); Executive::offchain_worker(&header); @@ -942,18 +929,11 @@ fn valid_inherents_position_works() { #[test] #[should_panic(expected = "A call was labelled as mandatory, but resulted in an Error.")] fn invalid_inherents_fail_block_execution() { - let xt1 = - TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), sign_extra(1, 0, 0)); new_test_ext(1).execute_with(|| { Executive::execute_block(Block::new( - Header::new( - 1, - H256::default(), - H256::default(), - [69u8; 32].into(), - Digest::default(), - ), + Header::new(1, H256::default(), H256::default(), [69u8; 32].into(), Digest::default()), vec![xt1], )); }); @@ -972,3 +952,58 @@ fn inherents_fail_validate_block() { ); }) } + +/// Inherents still work while `after_initialize` forbids extrinsics. +#[test] +fn inherents_ok_while_exts_forbidden_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = xt1.clone(); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} + +/// Panics when a block contains extrinsics although `after_inherents` forbids them. +#[test] +#[should_panic = "Extrinsics are not allowed in this block"] +fn extrinsic_while_exts_forbidden_errors() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + // Tell `after_inherents` to forbid extrinsics: + sp_io::storage::set(&b":extrinsics_forbidden"[..], &[0u8; 0]); + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} From 93d21713808335fa1f6fb3e15bb69312f9a3c2cb Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 17:39:59 +0200 Subject: [PATCH 08/41] Fix try-runtime Signed-off-by: Oliver Tale-Yazdi --- frame/executive/src/lib.rs | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index b4832e07311fd..3e4296838ecb3 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -258,7 +258,7 @@ where ); Self::initialize_block(block.header()); - Self::initial_checks(&block); + let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); @@ -283,7 +283,8 @@ where Ok(r.map(|_| ()).map_err(|e| e.error)) }; - for e in extrinsics { + // Apply all inherents: + for e in extrinsics.iter().take(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { frame_support::log::error!( target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", @@ -293,6 +294,23 @@ where break } } + match Self::after_inherents() { + BlockAfterInherentsMode::ExtrinsicsAllowed => { + // Apply all extrinsics: + for e in extrinsics.iter().skip(num_inherents) { + if let Err(err) = try_apply_extrinsic(e.clone()) { + frame_support::log::error!( + target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", + e, + err, + ); + break + } + } + }, + BlockAfterInherentsMode::ExtrinsicsForbidden => (), + } + // Apply all extrinsics: // post-extrinsics book-keeping >::note_finished_extrinsics(); @@ -502,7 +520,6 @@ where } }, BlockAfterInherentsMode::ExtrinsicsAllowed => { - dbg!(num_inherents, applyables.len()); Self::execute_applyables(applyables.iter().skip(num_inherents)); }, } From b12af3a78192436f4099986e870282ce9873bfc8 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 22:26:03 +0200 Subject: [PATCH 09/41] Fix test? Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 2 + frame/executive/Cargo.toml | 14 ++- frame/executive/src/tests.rs | 101 ++++++++++++++++-- .../src/construct_runtime/expand/inherent.rs | 14 ++- primitives/runtime/src/testing.rs | 2 +- 5 files changed, 117 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37f18f2cd2d77..0016578bd29ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2759,6 +2759,8 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "scale-info", + "sp-api", + "sp-block-builder", "sp-core", "sp-inherents", "sp-io", diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 2532df31682f7..dd51d0b023de0 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -34,6 +34,8 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-version = { version = "22.0.0", path = "../../primitives/version" } +sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } +sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } [features] default = ["std"] @@ -46,8 +48,18 @@ std = [ "scale-info/std", "sp-core/std", "sp-io/std", + "sp-api/std", "sp-runtime/std", "sp-std/std", "sp-tracing/std", + "sp-block-builder/std", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-try-runtime/try-runtime", + "sp-runtime/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime?/try-runtime", + "pallet-balances/try-runtime", + "pallet-transaction-payment/try-runtime" ] -try-runtime = ["frame-support/try-runtime", "frame-try-runtime/try-runtime", "sp-runtime/try-runtime"] diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index 58825f9adc405..124079b437c90 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -31,7 +31,7 @@ use sp_runtime::{ }; use frame_support::{ - assert_err, parameter_types, + assert_err, assert_ok, parameter_types, traits::{fungible, ConstU32, ConstU64, ConstU8, Currency}, weights::{ConstantMultiplier, IdentityFee, RuntimeDbWeight, Weight, WeightToFee}, }; @@ -957,7 +957,6 @@ fn inherents_fail_validate_block() { #[test] fn inherents_ok_while_exts_forbidden_works() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); - let xt2 = xt1.clone(); let header = new_test_ext(1).execute_with(|| { Executive::initialize_block(&Header::new( @@ -969,13 +968,13 @@ fn inherents_ok_while_exts_forbidden_works() { )); Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); - Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); - + // This is not applied: Executive::finalize_block() }); new_test_ext(1).execute_with(|| { - Executive::execute_block(Block::new(header, vec![xt1, xt2])); + // Tell `after_inherents` to forbid extrinsics: + Executive::execute_block(Block::new(header, vec![xt1])); }); } @@ -1003,7 +1002,97 @@ fn extrinsic_while_exts_forbidden_errors() { new_test_ext(1).execute_with(|| { // Tell `after_inherents` to forbid extrinsics: - sp_io::storage::set(&b":extrinsics_forbidden"[..], &[0u8; 0]); + sp_io::storage::set(&b":extrinsics_forbidden"[..], &[]); Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } + +#[test] +#[cfg(feature = "try-runtime")] +fn try_execute_block_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + Executive::try_execute_block( + Block::new(header, vec![xt1, xt2]), + true, + true, + frame_try_runtime::TryStateSelect::All, + ) + .unwrap(); + }); +} + +#[test] +fn ensure_inherents_are_first_works() { + let in1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + // Header is not checked. + let header = new_test_ext(1).execute_with(|| Executive::finalize_block()); + + new_test_ext(1).execute_with(|| { + assert_ok!(Runtime::ensure_inherents_are_first(&Block::new(header.clone(), vec![]),), 0); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new(header.clone(), vec![xt2.clone()]),), + 0 + ); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new(header.clone(), vec![in1.clone()]),), + 1 + ); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![in1.clone(), xt2.clone()] + ),), + 1 + ); + assert_ok!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![in1.clone(), in1.clone(), xt2.clone()] + ),), + 2 + ); + + assert_eq!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![xt2.clone(), in1.clone()] + ),), + Err(1) + ); + assert_eq!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![xt2.clone(), xt2.clone(), in1.clone()] + ),), + Err(2) + ); + assert_eq!( + Runtime::ensure_inherents_are_first(&Block::new( + header.clone(), + vec![xt2.clone(), xt2.clone(), xt2.clone(), in1.clone()] + ),), + Err(3) + ); + }); +} diff --git a/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/frame/support/procedural/src/construct_runtime/expand/inherent.rs index c89269732e261..61bbf9204b26b 100644 --- a/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -183,7 +183,7 @@ pub fn expand_outer_inherent( use #scrate::traits::{IsSubType, ExtrinsicCall}; use #scrate::sp_runtime::traits::Block as _; - let mut first_extrinsic_index = None; + let mut num_inherents = 0usize; for (i, xt) in block.extrinsics().iter().enumerate() { let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt) @@ -209,17 +209,15 @@ pub fn expand_outer_inherent( }; if is_inherent { - if first_extrinsic_index.is_some() { - // There is an inherent after an extrinsic: - return Err(i as u32) + if num_inherents != i{ + return Err(i as u32); } - } else if first_extrinsic_index.is_none() { - // This is the first extrinsic: - first_extrinsic_index = Some(i as u32); + + num_inherents += 1; // Safe since we are in an `enumerate` loop. } } - Ok(first_extrinsic_index.unwrap_or(0)) + Ok(num_inherents as u32) } } } diff --git a/primitives/runtime/src/testing.rs b/primitives/runtime/src/testing.rs index 6d02e23094f90..6f89588213565 100644 --- a/primitives/runtime/src/testing.rs +++ b/primitives/runtime/src/testing.rs @@ -235,7 +235,7 @@ impl Deref for ExtrinsicWrapper { } /// Testing block -#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] +#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, scale_info::TypeInfo)] pub struct Block { /// Block header pub header: Header, From cead9983a8c794be610a214655912e431104d186 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 19 Jun 2023 22:36:28 +0200 Subject: [PATCH 10/41] Cleanup Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 2 -- frame/executive/Cargo.toml | 4 ---- primitives/runtime/src/testing.rs | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0016578bd29ca..37f18f2cd2d77 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2759,8 +2759,6 @@ dependencies = [ "pallet-transaction-payment", "parity-scale-codec", "scale-info", - "sp-api", - "sp-block-builder", "sp-core", "sp-inherents", "sp-io", diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index dd51d0b023de0..c5c5aaad6ea86 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -34,8 +34,6 @@ sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-inherents = { version = "4.0.0-dev", path = "../../primitives/inherents" } sp-io = { version = "23.0.0", path = "../../primitives/io" } sp-version = { version = "22.0.0", path = "../../primitives/version" } -sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } [features] default = ["std"] @@ -48,11 +46,9 @@ std = [ "scale-info/std", "sp-core/std", "sp-io/std", - "sp-api/std", "sp-runtime/std", "sp-std/std", "sp-tracing/std", - "sp-block-builder/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/primitives/runtime/src/testing.rs b/primitives/runtime/src/testing.rs index 6f89588213565..6d02e23094f90 100644 --- a/primitives/runtime/src/testing.rs +++ b/primitives/runtime/src/testing.rs @@ -235,7 +235,7 @@ impl Deref for ExtrinsicWrapper { } /// Testing block -#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode, scale_info::TypeInfo)] +#[derive(PartialEq, Eq, Clone, Serialize, Debug, Encode, Decode)] pub struct Block { /// Block header pub header: Header, From 94e4658833a846e9071cdd297980f7d8e3ea8c15 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 20 Jun 2023 12:26:09 +0200 Subject: [PATCH 11/41] Cleanup Signed-off-by: Oliver Tale-Yazdi --- frame/executive/src/lib.rs | 14 +++++++------- test-utils/runtime/src/lib.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 3e4296838ecb3..d9f29a10371ea 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -310,11 +310,10 @@ where }, BlockAfterInherentsMode::ExtrinsicsForbidden => (), } - // Apply all extrinsics: // post-extrinsics book-keeping >::note_finished_extrinsics(); - // TODO MBMs will only conditionally run this. + // TODO MBMs will conditionally run this. Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); @@ -478,7 +477,7 @@ where } } - /// Returns the number of inherents in the block. + /// Check the block and panic if invalid. Returns the number of inherents in it. fn initial_checks(block: &Block) -> u32 { sp_tracing::enter_span!(sp_tracing::Level::TRACE, "initial_checks"); let header = block.header(); @@ -506,7 +505,6 @@ where // Execute `on_runtime_upgrade` and `on_initialize`. Self::initialize_block(block.header()); - // Check the block and panic if invalid. let num_inherents = Self::initial_checks(&block) as usize; let (header, applyables) = block.deconstruct(); @@ -526,7 +524,7 @@ where // Dispatchable processing is done now. >::note_finished_extrinsics(); - // TODO MBMs will only conditionally run this. + // TODO MBMs will conditionally run this. Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); @@ -551,7 +549,7 @@ where BlockAfterInherentsMode::ExtrinsicsAllowed } - /// Execute given applyables. + /// Execute given applyables (extrinsics or intrinsics). fn execute_applyables<'a>(applyables: impl Iterator) { applyables.into_iter().for_each(|e| { if let Err(e) = Self::apply_extrinsic(e.clone()) { @@ -570,7 +568,7 @@ where >::note_finished_extrinsics(); let block_number = >::block_number(); - // TODO MBMs will only conditionally run this. + // TODO MBMs will conditionally run this. Self::on_idle_hook(block_number); Self::on_finalize_hook(block_number); @@ -578,6 +576,7 @@ where >::finalize() } + /// Run the `on_idle` hook of all pallet, but only if there is weight remaining. fn on_idle_hook(block_number: NumberFor) { let weight = >::block_weight(); let max_weight = >::get().max_block; @@ -595,6 +594,7 @@ where } } + /// Run the `on_finalize` hook of all pallet. fn on_finalize_hook(block_number: NumberFor) { >::on_finalize(block_number); } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index bacc4a2d4aa67..ff320f6848291 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -480,7 +480,7 @@ impl_runtime_apis! { fn initialize_block(header: &::Header) { log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); - Executive::initialize_block(header) + Executive::initialize_block(header); } } From 4ac155dbdeaa6ba4dede2f9d699d14bbf4899b77 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 21 Jun 2023 11:28:09 +0200 Subject: [PATCH 12/41] Consume weight instead of return Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 2 +- bin/node/runtime/src/lib.rs | 2 +- .../basic-authorship/src/basic_authorship.rs | 18 ++--- client/block-builder/src/lib.rs | 5 +- client/proposer-metrics/src/lib.rs | 3 - frame/executive/src/lib.rs | 80 ++++++++----------- frame/executive/src/tests.rs | 21 ++++- primitives/block-builder/src/lib.rs | 4 +- primitives/runtime/src/lib.rs | 9 --- test-utils/runtime/src/lib.rs | 2 +- 10 files changed, 65 insertions(+), 81 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index f2dc1099fdbb4..4d9bf082036fc 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -393,7 +393,7 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + fn after_inherents() { Executive::after_inherents() } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 255af877151b3..1c0f1236b3854 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2112,7 +2112,7 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + fn after_inherents() { Executive::after_inherents() } } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index b961950cb920d..30e63c583a2dd 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -39,7 +39,7 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - BlockAfterInherentsMode, Digest, Percent, SaturatedConversion, + Digest, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -348,12 +348,9 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); - let mode = block_builder.after_inherents()?; - let end_reason = match mode { - BlockAfterInherentsMode::ExtrinsicsAllowed => - self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, - BlockAfterInherentsMode::ExtrinsicsForbidden => EndProposingReason::ExtrinsicsForbidden, - }; + block_builder.after_inherents()?; + let end_reason = + self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); let block_took = block_timer.elapsed(); @@ -546,12 +543,7 @@ where }); let extrinsics_summary = if extrinsics.is_empty() { - if end_reason == EndProposingReason::ExtrinsicsForbidden { - "extrinsics forbidden" - } else { - "no extrinsics" - } - .to_string() + "no extrinsics".to_string() } else { format!( "extrinsics ({}): [{}]", diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 5c05d453ba047..32ea343dfd942 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::ExecutionContext; use sp_runtime::{ legacy, traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, - BlockAfterInherentsMode, Digest, + Digest, }; use sc_client_api::backend; @@ -199,7 +199,8 @@ where } /// Called after inherents but before extrinsics have been applied. - pub fn after_inherents(&self) -> Result { + pub fn after_inherents(&self) -> Result<(), Error> { + // FAIL-CI check version of the API self.api .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) .map_err(Into::into) diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index a9aa5a0e0e302..d8de141244c29 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -50,8 +50,6 @@ pub enum EndProposingReason { HitDeadline, HitBlockSizeLimit, HitBlockWeightLimit, - /// No extrinsics are allowed in the block. - ExtrinsicsForbidden, } /// Authorship metrics. @@ -115,7 +113,6 @@ impl Metrics { EndProposingReason::NoMoreTransactions => "no_more_transactions", EndProposingReason::HitBlockSizeLimit => "hit_block_size_limit", EndProposingReason::HitBlockWeightLimit => "hit_block_weight_limit", - EndProposingReason::ExtrinsicsForbidden => "extrinsics_forbidden", }; self.end_proposing_reason.with_label_values(&[reason]).inc(); diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index d9f29a10371ea..35b8ad788179f 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -136,7 +136,7 @@ use sp_runtime::{ ValidateUnsigned, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, BlockAfterInherentsMode, + ApplyExtrinsicResult, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -294,28 +294,23 @@ where break } } - match Self::after_inherents() { - BlockAfterInherentsMode::ExtrinsicsAllowed => { - // Apply all extrinsics: - for e in extrinsics.iter().skip(num_inherents) { - if let Err(err) = try_apply_extrinsic(e.clone()) { - frame_support::log::error!( - target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", - e, - err, - ); - break - } - } - }, - BlockAfterInherentsMode::ExtrinsicsForbidden => (), + Self::after_inherents(); + + // Apply all extrinsics: + for e in extrinsics.iter().skip(num_inherents) { + if let Err(err) = try_apply_extrinsic(e.clone()) { + frame_support::log::error!( + target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", + e, + err, + ); + break + } } // post-extrinsics book-keeping >::note_finished_extrinsics(); - // TODO MBMs will conditionally run this. Self::on_idle_hook(*header.number()); - Self::on_finalize_hook(*header.number()); // run the try-state checks of all pallets, ensuring they don't alter any state. @@ -508,25 +503,16 @@ where let num_inherents = Self::initial_checks(&block) as usize; let (header, applyables) = block.deconstruct(); - // Process inherents (if any). + // Process inherents. Self::execute_applyables(applyables.iter().take(num_inherents)); - - match Self::after_inherents() { - BlockAfterInherentsMode::ExtrinsicsForbidden => { - if num_inherents < applyables.len() { - panic!("Extrinsics are not allowed in this block"); - } - }, - BlockAfterInherentsMode::ExtrinsicsAllowed => { - Self::execute_applyables(applyables.iter().skip(num_inherents)); - }, - } + Self::after_inherents(); + // Process extrinsics. + Self::execute_applyables(applyables.iter().skip(num_inherents)); // Dispatchable processing is done now. >::note_finished_extrinsics(); - // TODO MBMs will conditionally run this. - Self::on_idle_hook(*header.number()); + Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); // any final checks Self::final_checks(&header); @@ -535,18 +521,19 @@ where /// Execute code after inherents but before extrinsic application. /// - /// This is always called by the block builder. It returns whether extrinsics are allowed to be - /// included in the block or not. - pub fn after_inherents() -> BlockAfterInherentsMode { - // TODO add a proper condition here, but now we need this for mocking in tests. + /// It may consume all remaining weight of the block. + pub fn after_inherents() { + // TODO run the MBMs and poll hooks here. // // + // TODO add a proper condition here, but now we need this for mocking in tests. #[cfg(all(feature = "std", test))] - if sp_io::storage::exists(&b":extrinsics_forbidden"[..]) { - return BlockAfterInherentsMode::ExtrinsicsForbidden + if sp_io::storage::exists(&b":after_inherents_max_weight"[..]) { + >::register_extra_weight_unchecked( + Self::remaining_weight(), + DispatchClass::Mandatory, + ); } - - BlockAfterInherentsMode::ExtrinsicsAllowed } /// Execute given applyables (extrinsics or intrinsics). @@ -568,9 +555,7 @@ where >::note_finished_extrinsics(); let block_number = >::block_number(); - // TODO MBMs will conditionally run this. Self::on_idle_hook(block_number); - Self::on_finalize_hook(block_number); >::finalize() @@ -578,9 +563,7 @@ where /// Run the `on_idle` hook of all pallet, but only if there is weight remaining. fn on_idle_hook(block_number: NumberFor) { - let weight = >::block_weight(); - let max_weight = >::get().max_block; - let remaining_weight = max_weight.saturating_sub(weight.total()); + let remaining_weight = Self::remaining_weight(); if remaining_weight.all_gt(Weight::zero()) { let used_weight = >::on_idle( @@ -726,4 +709,11 @@ where *header.number(), ) } + + /// Returns the remaining weight of the current block. + fn remaining_weight() -> Weight { + let used = >::block_weight(); + let max = >::get().max_block; + max.saturating_sub(used.total()) + } } diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index 124079b437c90..d20efc50b45fd 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -978,9 +978,9 @@ fn inherents_ok_while_exts_forbidden_works() { }); } -/// Panics when a block contains extrinsics although `after_inherents` forbids them. +/// Panics when a block contains extrinsics although `after_inherents` consumed all weight. #[test] -#[should_panic = "Extrinsics are not allowed in this block"] +#[should_panic = "Transaction would exhaust the block limits"] fn extrinsic_while_exts_forbidden_errors() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); @@ -1001,12 +1001,25 @@ fn extrinsic_while_exts_forbidden_errors() { }); new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to forbid extrinsics: - sp_io::storage::set(&b":extrinsics_forbidden"[..], &[]); + // Tell `after_inherents` to use all remaining weight: + sp_io::storage::set(&b":after_inherents_max_weight"[..], &[]); Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } +#[test] +fn after_inherents_uses_all_weight() { + new_test_ext(1).execute_with(|| { + // Tell `after_inherents` to use all remaining weight: + sp_io::storage::set(&b":after_inherents_max_weight"[..], &[]); + Executive::after_inherents(); + + let used = frame_system::Pallet::::block_weight().total(); + let max = BlockWeights::get().max_block; + assert_eq!(used, max); + }); +} + #[test] #[cfg(feature = "try-runtime")] fn try_execute_block_works() { diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index e1b132b9be670..b4ded30416a39 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult, BlockAfterInherentsMode}; +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. @@ -50,6 +50,6 @@ sp_api::decl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; /// Called after inherents but before extrinsic application. - fn after_inherents() -> BlockAfterInherentsMode; + fn after_inherents(); } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 4acc1669acebf..d29938d0a8610 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -944,15 +944,6 @@ impl TransactionOutcome { } } -/// The mode of a block after inherents were applied. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] -pub enum BlockAfterInherentsMode { - /// No extrinsics should be pushed to the block - not even mandatory ones. - ExtrinsicsForbidden, - /// Can push extrinsics to the block. - ExtrinsicsAllowed, -} - #[cfg(test)] mod tests { use crate::traits::BlakeTwo256; diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index ff320f6848291..70f202dbfdbb5 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -527,7 +527,7 @@ impl_runtime_apis! { CheckInherentsResult::new() } - fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + fn after_inherents() { Executive::after_inherents() } } From 627b57a01645c2c8430f82987ceae0f8ffbebad1 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 21 Jun 2023 11:46:01 +0200 Subject: [PATCH 13/41] Review Signed-off-by: Oliver Tale-Yazdi --- bin/node/runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 1c0f1236b3854..e3a800a91f258 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -143,7 +143,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 269, + spec_version: 268, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 2, From 99d37ee5011da80226350f3bbe3ebabd8b4a55de Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 21 Jun 2023 11:50:42 +0200 Subject: [PATCH 14/41] Check runtime API version Signed-off-by: Oliver Tale-Yazdi --- client/block-builder/src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 32ea343dfd942..e66f79d430829 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -200,10 +200,14 @@ where /// Called after inherents but before extrinsics have been applied. pub fn after_inherents(&self) -> Result<(), Error> { - // FAIL-CI check version of the API - self.api - .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) - .map_err(Into::into) + if self.version >= 7 { + self.api + .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) + .map_err(Into::into) + } else { + // Not yet available; this is fine. + Ok(()) + } } /// Push onto the block's list of extrinsics. From 3aca2c36f13134f9d8f1b4ff34c04a77e59d22cd Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 21 Jun 2023 12:18:56 +0200 Subject: [PATCH 15/41] Cleanup Signed-off-by: Oliver Tale-Yazdi --- client/proposer-metrics/src/lib.rs | 1 - frame/executive/src/lib.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index d8de141244c29..012e8ca769a96 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -44,7 +44,6 @@ impl MetricsLink { } /// The reason why proposing a block ended. -#[derive(Clone, Copy, PartialEq, Eq)] pub enum EndProposingReason { NoMoreTransactions, HitDeadline, diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 35b8ad788179f..e7760b9768115 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -509,12 +509,10 @@ where // Process extrinsics. Self::execute_applyables(applyables.iter().skip(num_inherents)); - // Dispatchable processing is done now. >::note_finished_extrinsics(); Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); - // any final checks Self::final_checks(&header); } } From 0aa91123692e210f6969bd4dcca5386b2ec9d7ca Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Fri, 23 Jun 2023 16:23:21 +0200 Subject: [PATCH 16/41] Revert "Consume weight instead of return" This reverts commit 4ac155dbdeaa6ba4dede2f9d699d14bbf4899b77. Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 2 +- bin/node/runtime/src/lib.rs | 2 +- .../basic-authorship/src/basic_authorship.rs | 18 +++-- client/block-builder/src/lib.rs | 6 +- client/proposer-metrics/src/lib.rs | 3 + frame/executive/src/lib.rs | 80 +++++++++++-------- frame/executive/src/tests.rs | 21 +---- primitives/block-builder/src/lib.rs | 4 +- primitives/runtime/src/lib.rs | 9 +++ test-utils/runtime/src/lib.rs | 2 +- 10 files changed, 82 insertions(+), 65 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 4d9bf082036fc..f2dc1099fdbb4 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -393,7 +393,7 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() { + fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { Executive::after_inherents() } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index e3a800a91f258..010550af440d1 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2112,7 +2112,7 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() { + fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { Executive::after_inherents() } } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 30e63c583a2dd..b961950cb920d 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -39,7 +39,7 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - Digest, Percent, SaturatedConversion, + BlockAfterInherentsMode, Digest, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -348,9 +348,12 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); - block_builder.after_inherents()?; - let end_reason = - self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?; + let mode = block_builder.after_inherents()?; + let end_reason = match mode { + BlockAfterInherentsMode::ExtrinsicsAllowed => + self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, + BlockAfterInherentsMode::ExtrinsicsForbidden => EndProposingReason::ExtrinsicsForbidden, + }; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); let block_took = block_timer.elapsed(); @@ -543,7 +546,12 @@ where }); let extrinsics_summary = if extrinsics.is_empty() { - "no extrinsics".to_string() + if end_reason == EndProposingReason::ExtrinsicsForbidden { + "extrinsics forbidden" + } else { + "no extrinsics" + } + .to_string() } else { format!( "extrinsics ({}): [{}]", diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index e66f79d430829..5384b4a347d65 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::ExecutionContext; use sp_runtime::{ legacy, traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, - Digest, + BlockAfterInherentsMode, Digest, }; use sc_client_api::backend; @@ -199,14 +199,14 @@ where } /// Called after inherents but before extrinsics have been applied. - pub fn after_inherents(&self) -> Result<(), Error> { + pub fn after_inherents(&self) -> Result { if self.version >= 7 { self.api .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) .map_err(Into::into) } else { // Not yet available; this is fine. - Ok(()) + Ok(BlockAfterInherentsMode::ExtrinsicsAllowed) } } diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index 012e8ca769a96..ad28ec4591ab6 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -49,6 +49,8 @@ pub enum EndProposingReason { HitDeadline, HitBlockSizeLimit, HitBlockWeightLimit, + /// No extrinsics are allowed in the block. + ExtrinsicsForbidden, } /// Authorship metrics. @@ -112,6 +114,7 @@ impl Metrics { EndProposingReason::NoMoreTransactions => "no_more_transactions", EndProposingReason::HitBlockSizeLimit => "hit_block_size_limit", EndProposingReason::HitBlockWeightLimit => "hit_block_weight_limit", + EndProposingReason::ExtrinsicsForbidden => "extrinsics_forbidden", }; self.end_proposing_reason.with_label_values(&[reason]).inc(); diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index e7760b9768115..374fe24db322b 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -136,7 +136,7 @@ use sp_runtime::{ ValidateUnsigned, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, + ApplyExtrinsicResult, BlockAfterInherentsMode, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -294,23 +294,28 @@ where break } } - Self::after_inherents(); - - // Apply all extrinsics: - for e in extrinsics.iter().skip(num_inherents) { - if let Err(err) = try_apply_extrinsic(e.clone()) { - frame_support::log::error!( - target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", - e, - err, - ); - break - } + match Self::after_inherents() { + BlockAfterInherentsMode::ExtrinsicsAllowed => { + // Apply all extrinsics: + for e in extrinsics.iter().skip(num_inherents) { + if let Err(err) = try_apply_extrinsic(e.clone()) { + frame_support::log::error!( + target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", + e, + err, + ); + break + } + } + }, + BlockAfterInherentsMode::ExtrinsicsForbidden => (), } // post-extrinsics book-keeping >::note_finished_extrinsics(); + // TODO MBMs will conditionally run this. Self::on_idle_hook(*header.number()); + Self::on_finalize_hook(*header.number()); // run the try-state checks of all pallets, ensuring they don't alter any state. @@ -503,15 +508,24 @@ where let num_inherents = Self::initial_checks(&block) as usize; let (header, applyables) = block.deconstruct(); - // Process inherents. + // Process inherents (if any). Self::execute_applyables(applyables.iter().take(num_inherents)); - Self::after_inherents(); - // Process extrinsics. - Self::execute_applyables(applyables.iter().skip(num_inherents)); - >::note_finished_extrinsics(); + match Self::after_inherents() { + BlockAfterInherentsMode::ExtrinsicsForbidden => { + if num_inherents < applyables.len() { + panic!("Extrinsics are not allowed in this block"); + } + }, + BlockAfterInherentsMode::ExtrinsicsAllowed => { + Self::execute_applyables(applyables.iter().skip(num_inherents)); + }, + } + >::note_finished_extrinsics(); + // TODO MBMs will conditionally run this. Self::on_idle_hook(*header.number()); + Self::on_finalize_hook(*header.number()); Self::final_checks(&header); } @@ -519,19 +533,18 @@ where /// Execute code after inherents but before extrinsic application. /// - /// It may consume all remaining weight of the block. - pub fn after_inherents() { - // TODO run the MBMs and poll hooks here. + /// This is always called by the block builder. It returns whether extrinsics are allowed to be + /// included in the block or not. + pub fn after_inherents() -> BlockAfterInherentsMode { + // TODO add a proper condition here, but now we need this for mocking in tests. // // - // TODO add a proper condition here, but now we need this for mocking in tests. #[cfg(all(feature = "std", test))] - if sp_io::storage::exists(&b":after_inherents_max_weight"[..]) { - >::register_extra_weight_unchecked( - Self::remaining_weight(), - DispatchClass::Mandatory, - ); + if sp_io::storage::exists(&b":extrinsics_forbidden"[..]) { + return BlockAfterInherentsMode::ExtrinsicsForbidden } + + BlockAfterInherentsMode::ExtrinsicsAllowed } /// Execute given applyables (extrinsics or intrinsics). @@ -553,7 +566,9 @@ where >::note_finished_extrinsics(); let block_number = >::block_number(); + // TODO MBMs will conditionally run this. Self::on_idle_hook(block_number); + Self::on_finalize_hook(block_number); >::finalize() @@ -561,7 +576,9 @@ where /// Run the `on_idle` hook of all pallet, but only if there is weight remaining. fn on_idle_hook(block_number: NumberFor) { - let remaining_weight = Self::remaining_weight(); + let weight = >::block_weight(); + let max_weight = >::get().max_block; + let remaining_weight = max_weight.saturating_sub(weight.total()); if remaining_weight.all_gt(Weight::zero()) { let used_weight = >::on_idle( @@ -707,11 +724,4 @@ where *header.number(), ) } - - /// Returns the remaining weight of the current block. - fn remaining_weight() -> Weight { - let used = >::block_weight(); - let max = >::get().max_block; - max.saturating_sub(used.total()) - } } diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index d20efc50b45fd..124079b437c90 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -978,9 +978,9 @@ fn inherents_ok_while_exts_forbidden_works() { }); } -/// Panics when a block contains extrinsics although `after_inherents` consumed all weight. +/// Panics when a block contains extrinsics although `after_inherents` forbids them. #[test] -#[should_panic = "Transaction would exhaust the block limits"] +#[should_panic = "Extrinsics are not allowed in this block"] fn extrinsic_while_exts_forbidden_errors() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); @@ -1001,25 +1001,12 @@ fn extrinsic_while_exts_forbidden_errors() { }); new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to use all remaining weight: - sp_io::storage::set(&b":after_inherents_max_weight"[..], &[]); + // Tell `after_inherents` to forbid extrinsics: + sp_io::storage::set(&b":extrinsics_forbidden"[..], &[]); Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } -#[test] -fn after_inherents_uses_all_weight() { - new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to use all remaining weight: - sp_io::storage::set(&b":after_inherents_max_weight"[..], &[]); - Executive::after_inherents(); - - let used = frame_system::Pallet::::block_weight().total(); - let max = BlockWeights::get().max_block; - assert_eq!(used, max); - }); -} - #[test] #[cfg(feature = "try-runtime")] fn try_execute_block_works() { diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index b4ded30416a39..e1b132b9be670 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult, BlockAfterInherentsMode}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. @@ -50,6 +50,6 @@ sp_api::decl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; /// Called after inherents but before extrinsic application. - fn after_inherents(); + fn after_inherents() -> BlockAfterInherentsMode; } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index d29938d0a8610..4acc1669acebf 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -944,6 +944,15 @@ impl TransactionOutcome { } } +/// The mode of a block after inherents were applied. +#[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] +pub enum BlockAfterInherentsMode { + /// No extrinsics should be pushed to the block - not even mandatory ones. + ExtrinsicsForbidden, + /// Can push extrinsics to the block. + ExtrinsicsAllowed, +} + #[cfg(test)] mod tests { use crate::traits::BlakeTwo256; diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 70f202dbfdbb5..ff320f6848291 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -527,7 +527,7 @@ impl_runtime_apis! { CheckInherentsResult::new() } - fn after_inherents() { + fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { Executive::after_inherents() } } From f29b46f8f541f815f08b270814f3c4934a2c2f53 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 4 Jul 2023 16:08:50 +0200 Subject: [PATCH 17/41] Return ExecutiveMode from initialize_block Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 1 + bin/node-template/runtime/src/lib.rs | 4 +- bin/node/runtime/src/lib.rs | 4 +- .../basic-authorship/src/basic_authorship.rs | 18 +-- client/block-builder/src/lib.rs | 20 ++- client/consensus/babe/src/lib.rs | 8 +- client/transaction-pool/Cargo.toml | 1 + frame/executive/src/lib.rs | 150 +++++++++++------- frame/executive/src/tests.rs | 40 ++++- frame/support/test/tests/runtime_metadata.rs | 2 +- primitives/api/src/lib.rs | 6 +- primitives/api/test/tests/decl_and_impl.rs | 2 +- .../ui/impl_incorrect_method_signature.rs | 2 +- .../api/test/tests/ui/impl_missing_version.rs | 2 +- .../test/tests/ui/missing_versioned_method.rs | 2 +- .../missing_versioned_method_multiple_vers.rs | 2 +- .../ui/positive_cases/custom_where_bound.rs | 2 +- .../tests/ui/positive_cases/default_impls.rs | 2 +- ...ype_reference_in_impl_runtime_apis_call.rs | 2 +- primitives/block-builder/src/lib.rs | 4 +- primitives/runtime/src/lib.rs | 35 +++- .../runtime/src/transaction_validity.rs | 3 + test-utils/runtime/src/lib.rs | 6 +- 23 files changed, 205 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37f18f2cd2d77..15d27eabfaf8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10276,6 +10276,7 @@ dependencies = [ "sc-utils", "serde", "sp-api", + "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-core", diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index f2dc1099fdbb4..f6c6c60df4dab 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -354,7 +354,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { Executive::initialize_block(header) } } @@ -393,7 +393,7 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + fn after_inherents() { Executive::after_inherents() } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 010550af440d1..91dd0c5a5c5f0 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2076,7 +2076,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { Executive::initialize_block(header) } } @@ -2112,7 +2112,7 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + fn after_inherents() { Executive::after_inherents() } } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index b961950cb920d..d5b5135bccabe 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -39,7 +39,7 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - BlockAfterInherentsMode, Digest, Percent, SaturatedConversion, + Digest, Percent, RuntimeExecutiveMode, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -345,14 +345,15 @@ where let mut block_builder = self.client.new_block_at(self.parent_hash, inherent_digests, PR::ENABLED)?; + // The executive mode does not influence the execution of inherents: self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); - let mode = block_builder.after_inherents()?; - let end_reason = match mode { - BlockAfterInherentsMode::ExtrinsicsAllowed => + block_builder.after_inherents()?; + let end_reason = match block_builder.executive_mode { + RuntimeExecutiveMode::Normal => self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, - BlockAfterInherentsMode::ExtrinsicsForbidden => EndProposingReason::ExtrinsicsForbidden, + RuntimeExecutiveMode::Minimal => EndProposingReason::ExtrinsicsForbidden, }; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); @@ -546,12 +547,7 @@ where }); let extrinsics_summary = if extrinsics.is_empty() { - if end_reason == EndProposingReason::ExtrinsicsForbidden { - "extrinsics forbidden" - } else { - "no extrinsics" - } - .to_string() + "no extrinsics".to_string() } else { format!( "extrinsics ({}): [{}]", diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 5384b4a347d65..aa92c209a2519 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::ExecutionContext; use sp_runtime::{ legacy, traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, - BlockAfterInherentsMode, Digest, + Digest, RuntimeExecutiveMode, }; use sc_client_api::backend; @@ -139,6 +139,8 @@ pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { backend: &'a B, /// The estimated size of the block header. estimated_header_size: usize, + /// The executive mode of the block that is currently being built. + pub executive_mode: RuntimeExecutiveMode, } impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B> @@ -178,7 +180,7 @@ where api.record_proof(); } - api.initialize_block_with_context( + let executive_mode = api.initialize_block_with_context( parent_hash, ExecutionContext::BlockConstruction, &header, @@ -195,19 +197,15 @@ where version, backend, estimated_header_size, + executive_mode, }) } /// Called after inherents but before extrinsics have been applied. - pub fn after_inherents(&self) -> Result { - if self.version >= 7 { - self.api - .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) - .map_err(Into::into) - } else { - // Not yet available; this is fine. - Ok(BlockAfterInherentsMode::ExtrinsicsAllowed) - } + pub fn after_inherents(&self) -> Result<(), Error> { + self.api + .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) + .map_err(Into::into) } /// Push onto the block's list of extrinsics. diff --git a/client/consensus/babe/src/lib.rs b/client/consensus/babe/src/lib.rs index 219b52294952a..64ff00bb58c35 100644 --- a/client/consensus/babe/src/lib.rs +++ b/client/consensus/babe/src/lib.rs @@ -1152,10 +1152,10 @@ where // Verification for imported blocks is skipped in two cases: // 1. When importing blocks below the last finalized block during network initial // synchronization. - // 2. When importing whole state we don't calculate epoch descriptor, but rather - // read it from the state after import. We also skip all verifications - // because there's no parent state and we trust the sync module to verify - // that the state is correct and finalized. + // 2. When importing whole state we don't calculate epoch descriptor, but rather read it + // from the state after import. We also skip all verifications because there's no + // parent state and we trust the sync module to verify that the state is correct and + // finalized. return Ok(block) } diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 83bb8bdbd5040..d0cf253f30cc2 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -27,6 +27,7 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } +sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" } diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 374fe24db322b..fe64c3628d1fb 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -121,6 +121,7 @@ mod tests; use codec::{Codec, Encode}; use frame_support::{ + defensive, dispatch::{DispatchClass, DispatchInfo, GetDispatchInfo, PostDispatchInfo}, pallet_prelude::InvalidTransaction, traits::{ @@ -129,6 +130,7 @@ use frame_support::{ }, weights::Weight, }; +use sp_core::Get; use sp_runtime::{ generic::Digest, traits::{ @@ -136,7 +138,7 @@ use sp_runtime::{ ValidateUnsigned, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, BlockAfterInherentsMode, + ApplyExtrinsicResult, RuntimeExecutiveMode, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -168,6 +170,7 @@ pub struct Executive< UnsignedValidator, AllPalletsWithSystem, OnRuntimeUpgrade = (), + RuntimeExecutiveModeQuery = (), >( PhantomData<( System, @@ -176,6 +179,7 @@ pub struct Executive< UnsignedValidator, AllPalletsWithSystem, OnRuntimeUpgrade, + RuntimeExecutiveModeQuery, )>, ); @@ -190,9 +194,17 @@ impl< + OnFinalize + OffchainWorker, COnRuntimeUpgrade: OnRuntimeUpgrade, + RuntimeExecutiveModeQuery: Get, > ExecuteBlock - for Executive -where + for Executive< + System, + Block, + Context, + UnsignedValidator, + AllPalletsWithSystem, + COnRuntimeUpgrade, + RuntimeExecutiveModeQuery, + > where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, CallOf: @@ -208,6 +220,7 @@ where UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade, + RuntimeExecutiveModeQuery, >::execute_block(block); } } @@ -225,8 +238,17 @@ impl< + OffchainWorker + frame_support::traits::TryState, COnRuntimeUpgrade: OnRuntimeUpgrade, - > Executive -where + RuntimeExecutiveModeQuery: Get, + > + Executive< + System, + Block, + Context, + UnsignedValidator, + AllPalletsWithSystem, + COnRuntimeUpgrade, + RuntimeExecutiveModeQuery, + > where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, CallOf: @@ -257,7 +279,7 @@ where select, ); - Self::initialize_block(block.header()); + let mode = Self::initialize_block(block.header()); let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); @@ -287,33 +309,32 @@ where for e in extrinsics.iter().take(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { frame_support::log::error!( - target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", + target: LOG_TARGET, "extrinsic {:?} failed due to {:?}. Aborting the rest of the block execution.", e, err, ); break } } - match Self::after_inherents() { - BlockAfterInherentsMode::ExtrinsicsAllowed => { - // Apply all extrinsics: - for e in extrinsics.iter().skip(num_inherents) { - if let Err(err) = try_apply_extrinsic(e.clone()) { - frame_support::log::error!( - target: LOG_TARGET, "executing transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", - e, - err, - ); - break - } + + Self::after_inherents(); + if mode == RuntimeExecutiveMode::Normal { + // Apply transactions: + for e in extrinsics.iter().skip(num_inherents) { + if let Err(err) = try_apply_extrinsic(e.clone()) { + frame_support::log::error!( + target: LOG_TARGET, "extrinsics {:?} failed due to {:?}. Aborting the rest of the block execution.", + e, + err, + ); + break } - }, - BlockAfterInherentsMode::ExtrinsicsForbidden => (), + } } // post-extrinsics book-keeping >::note_finished_extrinsics(); - // TODO MBMs will conditionally run this. + // TODO MBMs will skip this. Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); @@ -401,8 +422,17 @@ impl< + OnFinalize + OffchainWorker, COnRuntimeUpgrade: OnRuntimeUpgrade, - > Executive -where + RuntimeExecutiveModeQuery: Get, + > + Executive< + System, + Block, + Context, + UnsignedValidator, + AllPalletsWithSystem, + COnRuntimeUpgrade, + RuntimeExecutiveModeQuery, + > where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, CallOf: @@ -416,11 +446,13 @@ where } /// Start the execution of a particular block. - pub fn initialize_block(header: &System::Header) { + pub fn initialize_block(header: &System::Header) -> RuntimeExecutiveMode { sp_io::init_tracing(); sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block"); let digests = Self::extract_pre_digest(header); Self::initialize_block_impl(header.number(), header.parent_hash(), &digests); + + RuntimeExecutiveModeQuery::get() } fn extract_pre_digest(header: &System::Header) -> Digest { @@ -503,27 +535,24 @@ where sp_tracing::within_span! { sp_tracing::info_span!("execute_block", ?block); // Execute `on_runtime_upgrade` and `on_initialize`. - Self::initialize_block(block.header()); - - let num_inherents = Self::initial_checks(&block) as usize; - let (header, applyables) = block.deconstruct(); + let mode = Self::initialize_block(block.header()); + let inherents = Self::initial_checks(&block) as usize; + let (header, extrinsics) = block.deconstruct(); // Process inherents (if any). - Self::execute_applyables(applyables.iter().take(num_inherents)); - - match Self::after_inherents() { - BlockAfterInherentsMode::ExtrinsicsForbidden => { - if num_inherents < applyables.len() { - panic!("Extrinsics are not allowed in this block"); - } - }, - BlockAfterInherentsMode::ExtrinsicsAllowed => { - Self::execute_applyables(applyables.iter().skip(num_inherents)); - }, + Self::apply_extrinsics(extrinsics.iter().take(inherents), mode); + Self::after_inherents(); + if mode == RuntimeExecutiveMode::Minimal { + if inherents < extrinsics.len() { + // Note: It would be possible to not explicitly panic here since the state-root check should already catch any mismatch, but this makes it easier to debug. + panic!("Only inherents are allowed in 'Minimal' blocks"); + } } + // Process transactions (if any). + Self::apply_extrinsics(extrinsics.iter().skip(inherents), mode); >::note_finished_extrinsics(); - // TODO MBMs will conditionally run this. + // TODO MBMs will skip this. Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); @@ -532,25 +561,19 @@ where } /// Execute code after inherents but before extrinsic application. - /// - /// This is always called by the block builder. It returns whether extrinsics are allowed to be - /// included in the block or not. - pub fn after_inherents() -> BlockAfterInherentsMode { - // TODO add a proper condition here, but now we need this for mocking in tests. + pub fn after_inherents() { + // TODO run either MBMs or `poll` depending on the mode: // // - #[cfg(all(feature = "std", test))] - if sp_io::storage::exists(&b":extrinsics_forbidden"[..]) { - return BlockAfterInherentsMode::ExtrinsicsForbidden - } - - BlockAfterInherentsMode::ExtrinsicsAllowed } - /// Execute given applyables (extrinsics or intrinsics). - fn execute_applyables<'a>(applyables: impl Iterator) { - applyables.into_iter().for_each(|e| { - if let Err(e) = Self::apply_extrinsic(e.clone()) { + /// Execute given extrinsics. + fn apply_extrinsics<'a>( + extrinsics: impl Iterator, + mode: RuntimeExecutiveMode, + ) { + extrinsics.into_iter().for_each(|e| { + if let Err(e) = Self::apply_extrinsic_in_mode(e.clone(), mode) { let err: &'static str = e.into(); panic!("{}", err) } @@ -602,6 +625,14 @@ where /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt /// hashes. pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult { + Self::apply_extrinsic_in_mode(uxt, RuntimeExecutiveMode::Normal) + } + + /// Same as `apply_extrinsic` but gets the `mode` directly passed in. + pub fn apply_extrinsic_in_mode( + uxt: Block::Extrinsic, + mode: RuntimeExecutiveMode, + ) -> ApplyExtrinsicResult { sp_io::init_tracing(); let encoded = uxt.encode(); let encoded_len = encoded.len(); @@ -625,9 +656,14 @@ where // // The entire block should be discarded if an inherent fails to apply. Otherwise // it may open an attack vector. - if r.is_err() && dispatch_info.class == DispatchClass::Mandatory { + let mandatory = dispatch_info.class == DispatchClass::Mandatory; + if r.is_err() && mandatory { return Err(InvalidTransaction::BadMandatory.into()) } + if mode == RuntimeExecutiveMode::Minimal && !mandatory { + defensive!("Only 'Mandatory' extrinsics should be present in a 'Minimal' block"); + return Err(InvalidTransaction::NotMandatory.into()) + } >::note_applied_extrinsic(&r, dispatch_info); diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index 124079b437c90..5fb6b79608be5 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -286,8 +286,14 @@ type Executive = super::Executive< Runtime, AllPalletsWithSystem, CustomOnRuntimeUpgrade, + MockedMode, >; +frame_support::parameter_types! { + /// Provides the runtime-mode to frame-executive. + pub static MockedMode: RuntimeExecutiveMode = RuntimeExecutiveMode::Normal; +} + fn extra(nonce: u64, fee: Balance) -> SignedExtra { ( frame_system::CheckEra::from(Era::Immortal), @@ -978,9 +984,9 @@ fn inherents_ok_while_exts_forbidden_works() { }); } -/// Panics when a block contains extrinsics although `after_inherents` forbids them. +/// Refuses to import blocks with transactions during MBMs. #[test] -#[should_panic = "Extrinsics are not allowed in this block"] +#[should_panic = "Only inherents are allowed in 'Minimal' blocks"] fn extrinsic_while_exts_forbidden_errors() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); @@ -1002,7 +1008,34 @@ fn extrinsic_while_exts_forbidden_errors() { new_test_ext(1).execute_with(|| { // Tell `after_inherents` to forbid extrinsics: - sp_io::storage::set(&b":extrinsics_forbidden"[..], &[]); + MockedMode::set(RuntimeExecutiveMode::Minimal); + Executive::execute_block(Block::new(header, vec![xt1, xt2])); + }); +} + +/// Same as above but imports. +#[test] +fn extrinsic_while_exts_allowed_works() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + // Tell `after_inherents` to forbid extrinsics: Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } @@ -1040,6 +1073,7 @@ fn try_execute_block_works() { }); } +/// Check that `ensure_inherents_are_first` reports the correct indices. #[test] fn ensure_inherents_are_first_works() { let in1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index 70ca307d4428c..8598c129ed69d 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -107,7 +107,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 1a286a927e6e8..b9e4c8ba4aa0b 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -93,7 +93,7 @@ pub use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Hash as HashT, HashFor, Header as HeaderT, NumberFor}, transaction_validity::TransactionValidity, - RuntimeString, TransactionOutcome, + RuntimeExecutiveMode, RuntimeString, TransactionOutcome, }; #[doc(hidden)] #[cfg(feature = "std")] @@ -715,7 +715,7 @@ pub fn deserialize_runtime_api_info(bytes: [u8; RUNTIME_API_INFO_SIZE]) -> ([u8; decl_runtime_apis! { /// The `Core` runtime api that every Substrate runtime needs to implement. #[core_trait] - #[api_version(4)] + #[api_version(5)] pub trait Core { /// Returns the version of the runtime. fn version() -> RuntimeVersion; @@ -723,7 +723,7 @@ decl_runtime_apis! { fn execute_block(block: Block); /// Initialize a block with the given header. #[renamed("initialise_block", 2)] - fn initialize_block(header: &::Header); + fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; } /// The `Metadata` api trait that returns metadata for the runtime. diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 274f80bd1b465..25b7ad81b49fc 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -89,7 +89,7 @@ impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs index 32501be7855c6..96c7c32dc79e7 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs @@ -23,7 +23,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/impl_missing_version.rs b/primitives/api/test/tests/ui/impl_missing_version.rs index 8fd40a400922f..bad30ac23920e 100644 --- a/primitives/api/test/tests/ui/impl_missing_version.rs +++ b/primitives/api/test/tests/ui/impl_missing_version.rs @@ -28,7 +28,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method.rs b/primitives/api/test/tests/ui/missing_versioned_method.rs index 919cef055fe62..44c03ea842023 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method.rs @@ -27,7 +27,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs index 036bba417f57d..c659ed9be4355 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs @@ -30,7 +30,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs index b572a3bc30d5d..c4031ed683753 100644 --- a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs +++ b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs @@ -34,7 +34,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/positive_cases/default_impls.rs b/primitives/api/test/tests/ui/positive_cases/default_impls.rs index 58192feb9ecac..deffb43481999 100644 --- a/primitives/api/test/tests/ui/positive_cases/default_impls.rs +++ b/primitives/api/test/tests/ui/positive_cases/default_impls.rs @@ -29,7 +29,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs index 14a8fa4d4e0b1..40d846946538f 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -25,7 +25,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) { + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { unimplemented!() } } diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index e1b132b9be670..b4ded30416a39 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult, BlockAfterInherentsMode}; +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. @@ -50,6 +50,6 @@ sp_api::decl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; /// Called after inherents but before extrinsic application. - fn after_inherents() -> BlockAfterInherentsMode; + fn after_inherents(); } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index 4acc1669acebf..bbd8a7a78f187 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -944,13 +944,36 @@ impl TransactionOutcome { } } -/// The mode of a block after inherents were applied. +/// Confines the logic that can be executed in a block. +/// +/// The runtime may refuse to import blocks that violate these requirements. #[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] -pub enum BlockAfterInherentsMode { - /// No extrinsics should be pushed to the block - not even mandatory ones. - ExtrinsicsForbidden, - /// Can push extrinsics to the block. - ExtrinsicsAllowed, +pub enum RuntimeExecutiveMode { + /// All logic is allowed to run. + /// + /// For example: + /// - Extrinsics with dispatch class `Normal`. + /// - `on_idle` hook. + Normal, + /// Only _really necessary_ logic is allowed to run. + /// + /// Explicitly forbidden are: + /// - Extrinsics with dispatch classes `Normal` and `Operational`. + /// - `on_idle` and `poll` hooks. + /// + /// Explicitly allowed are: + /// - Mandatory inherents and extrinsics (i.e. via OCW). + /// - `on_initialize` and `on_finalize` hooks. + /// - Storage migrations. + /// + /// Everything in between is to be judged by the runtime. + Minimal, +} + +impl Default for RuntimeExecutiveMode { + fn default() -> Self { + Self::Normal + } } #[cfg(test)] diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index 836948493823c..8f18522333d0d 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -82,6 +82,8 @@ pub enum InvalidTransaction { MandatoryValidation, /// The sending address is disabled or known to be invalid. BadSigner, + /// Only mandatory logic is allowed but it was attempted to execute non-mandatory logic. + NotMandatory, } impl InvalidTransaction { @@ -113,6 +115,7 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", + InvalidTransaction::NotMandatory => "Only mandatory logic is allowed", } } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index ff320f6848291..9c73a58f771e8 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -478,9 +478,9 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) { + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); - Executive::initialize_block(header); + Executive::initialize_block(header) } } @@ -527,7 +527,7 @@ impl_runtime_apis! { CheckInherentsResult::new() } - fn after_inherents() -> sp_runtime::BlockAfterInherentsMode { + fn after_inherents() { Executive::after_inherents() } } From e9b15c7600d3c23d53f737712656559f5062e97e Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 4 Jul 2023 18:46:01 +0200 Subject: [PATCH 18/41] Fix tests Signed-off-by: Oliver Tale-Yazdi --- client/rpc-spec-v2/src/chain_head/tests.rs | 2 +- client/rpc/src/state/tests.rs | 2 +- frame/executive/src/lib.rs | 32 ++++++++------- frame/executive/src/tests.rs | 39 ++++++++++++++++++- frame/support/test/tests/runtime_metadata.rs | 2 +- .../proc-macro/src/mock_impl_runtime_apis.rs | 4 +- 6 files changed, 61 insertions(+), 20 deletions(-) diff --git a/client/rpc-spec-v2/src/chain_head/tests.rs b/client/rpc-spec-v2/src/chain_head/tests.rs index 755ae9220ae15..c4baf60bf8a0d 100644 --- a/client/rpc-spec-v2/src/chain_head/tests.rs +++ b/client/rpc-spec-v2/src/chain_head/tests.rs @@ -186,7 +186,7 @@ async fn follow_with_runtime() { // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION let runtime_str = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ - \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ + \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",5],\ [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",7],\ [\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\ [\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\ diff --git a/client/rpc/src/state/tests.rs b/client/rpc/src/state/tests.rs index 57ddd215822b1..7af067592b1f6 100644 --- a/client/rpc/src/state/tests.rs +++ b/client/rpc/src/state/tests.rs @@ -514,7 +514,7 @@ async fn should_return_runtime_version() { // it is basically json-encoded substrate_test_runtime_client::runtime::VERSION let result = "{\"specName\":\"test\",\"implName\":\"parity-test\",\"authoringVersion\":1,\ - \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",4],\ + \"specVersion\":2,\"implVersion\":2,\"apis\":[[\"0xdf6acb689907609b\",5],\ [\"0x37e397fc7c91f5e4\",2],[\"0xd2bc9897eed08f15\",3],[\"0x40fe3ad401f8959a\",7],\ [\"0xbc9d89904f5b923f\",1],[\"0xc6e9a76309f39b09\",2],[\"0xdd718d5cc53262d4\",1],\ [\"0xcbca25e39f142387\",2],[\"0xf78b278be53f454c\",2],[\"0xab3c0572291feb8b\",1],\ diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index fe64c3628d1fb..eeeb4b10a3412 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -305,7 +305,7 @@ impl< Ok(r.map(|_| ()).map_err(|e| e.error)) }; - // Apply all inherents: + // Apply inherents: for e in extrinsics.iter().take(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { frame_support::log::error!( @@ -318,17 +318,20 @@ impl< } Self::after_inherents(); - if mode == RuntimeExecutiveMode::Normal { - // Apply transactions: - for e in extrinsics.iter().skip(num_inherents) { - if let Err(err) = try_apply_extrinsic(e.clone()) { - frame_support::log::error!( - target: LOG_TARGET, "extrinsics {:?} failed due to {:?}. Aborting the rest of the block execution.", - e, - err, - ); - break - } + if mode == RuntimeExecutiveMode::Minimal { + if num_inherents < extrinsics.len() { + return Err(InvalidTransaction::NotMandatory.into()) + } + } + // Apply transactions: + for e in extrinsics.iter().skip(num_inherents) { + if let Err(err) = try_apply_extrinsic(e.clone()) { + frame_support::log::error!( + target: LOG_TARGET, "extrinsics {:?} failed due to {:?}. Aborting the rest of the block execution.", + e, + err, + ); + break } } @@ -544,7 +547,8 @@ impl< Self::after_inherents(); if mode == RuntimeExecutiveMode::Minimal { if inherents < extrinsics.len() { - // Note: It would be possible to not explicitly panic here since the state-root check should already catch any mismatch, but this makes it easier to debug. + // Note: It would be possible to not explicitly panic here since the state-root + // check should already catch any mismatch, but this makes it easier to debug. panic!("Only inherents are allowed in 'Minimal' blocks"); } } @@ -589,7 +593,7 @@ impl< >::note_finished_extrinsics(); let block_number = >::block_number(); - // TODO MBMs will conditionally run this. + // TODO MBMs will conditionally skip this. Self::on_idle_hook(block_number); Self::on_finalize_hook(block_number); diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index 5fb6b79608be5..ee462a7ba0d6a 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -1073,13 +1073,50 @@ fn try_execute_block_works() { }); } +/// Same as `extrinsic_while_exts_forbidden_errors` but using the try-runtime function. +#[test] +#[cfg(feature = "try-runtime")] +#[should_panic = "Only inherents are allowed in 'Minimal' blocks"] +fn try_execute_ext_forbidden_errors() { + let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); + let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); + + let header = new_test_ext(1).execute_with(|| { + // Let's build some fake block. + Executive::initialize_block(&Header::new( + 1, + H256::default(), + H256::default(), + [69u8; 32].into(), + Digest::default(), + )); + + Executive::apply_extrinsic(xt1.clone()).unwrap().unwrap(); + Executive::apply_extrinsic(xt2.clone()).unwrap().unwrap(); + + Executive::finalize_block() + }); + + new_test_ext(1).execute_with(|| { + // Tell `after_inherents` to forbid extrinsics: + MockedMode::set(RuntimeExecutiveMode::Minimal); + Executive::try_execute_block( + Block::new(header, vec![xt1, xt2]), + true, + true, + frame_try_runtime::TryStateSelect::All, + ) + .unwrap(); + }); +} + /// Check that `ensure_inherents_are_first` reports the correct indices. #[test] fn ensure_inherents_are_first_works() { let in1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); - // Header is not checked. + // Mocked empty header: let header = new_test_ext(1).execute_with(|| Executive::finalize_block()); new_test_ext(1).execute_with(|| { diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index 8598c129ed69d..d9e04bdebda66 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -206,7 +206,7 @@ fn runtime_metadata() { name: "header", ty: meta_type::<&::Header>(), }], - output: meta_type::<()>(), + output: meta_type::(), docs: maybe_docs(vec![" Initialize a block with the given header."]), }, ], diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index be8c8ca0f8527..0229c51c5f92b 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -170,7 +170,7 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result::Hash, _: &<#block_type as #crate_::BlockT>::Header, - ) -> std::result::Result<(), #crate_::ApiError> { + ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") } @@ -179,7 +179,7 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result::Hash, _: #crate_::ExecutionContext, _: &<#block_type as #crate_::BlockT>::Header, - ) -> std::result::Result<(), #crate_::ApiError> { + ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") } } From b9bfdd7317361cb80fd0bc523a9068e7de2f08c6 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 4 Jul 2023 19:03:56 +0200 Subject: [PATCH 19/41] Cleanup Signed-off-by: Oliver Tale-Yazdi --- client/basic-authorship/src/basic_authorship.rs | 2 +- client/proposer-metrics/src/lib.rs | 6 +++--- frame/executive/src/lib.rs | 6 +++--- test-utils/runtime/src/lib.rs | 6 ++++++ 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index d5b5135bccabe..9bd0a7b8f0c56 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -353,7 +353,7 @@ where let end_reason = match block_builder.executive_mode { RuntimeExecutiveMode::Normal => self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, - RuntimeExecutiveMode::Minimal => EndProposingReason::ExtrinsicsForbidden, + RuntimeExecutiveMode::Minimal => EndProposingReason::TransactionsForbidden, }; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); diff --git a/client/proposer-metrics/src/lib.rs b/client/proposer-metrics/src/lib.rs index ad28ec4591ab6..aeb9d8d05b61e 100644 --- a/client/proposer-metrics/src/lib.rs +++ b/client/proposer-metrics/src/lib.rs @@ -49,8 +49,8 @@ pub enum EndProposingReason { HitDeadline, HitBlockSizeLimit, HitBlockWeightLimit, - /// No extrinsics are allowed in the block. - ExtrinsicsForbidden, + /// No transactions are allowed in the block. + TransactionsForbidden, } /// Authorship metrics. @@ -114,7 +114,7 @@ impl Metrics { EndProposingReason::NoMoreTransactions => "no_more_transactions", EndProposingReason::HitBlockSizeLimit => "hit_block_size_limit", EndProposingReason::HitBlockWeightLimit => "hit_block_weight_limit", - EndProposingReason::ExtrinsicsForbidden => "extrinsics_forbidden", + EndProposingReason::TransactionsForbidden => "transactions_forbidden", }; self.end_proposing_reason.with_label_values(&[reason]).inc(); diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index ca05f5c4b029d..c2fbb9e591075 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -583,7 +583,7 @@ impl< mode: RuntimeExecutiveMode, ) { extrinsics.into_iter().for_each(|e| { - if let Err(e) = Self::apply_extrinsic_in_mode(e.clone(), mode) { + if let Err(e) = Self::apply_extrinsic_with_mode(e.clone(), mode) { let err: &'static str = e.into(); panic!("{}", err) } @@ -635,11 +635,11 @@ impl< /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt /// hashes. pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult { - Self::apply_extrinsic_in_mode(uxt, RuntimeExecutiveMode::Normal) + Self::apply_extrinsic_with_mode(uxt, RuntimeExecutiveModeQuery::get()) } /// Same as `apply_extrinsic` but gets the `mode` directly passed in. - pub fn apply_extrinsic_in_mode( + pub fn apply_extrinsic_with_mode( uxt: Block::Extrinsic, mode: RuntimeExecutiveMode, ) -> ApplyExtrinsicResult { diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index c4f0b9057ad8a..384f2762cea60 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -228,8 +228,14 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, + (), // no migrations + MockedRuntimeExecutiveMode, >; +parameter_types! { + pub storage MockedRuntimeExecutiveMode: sp_runtime::RuntimeExecutiveMode = Default::default(); +} + #[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct CheckSubstrateCall; From ce2b00ccfcd43a1dfa482fd5e09384ff76757a73 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 15:23:07 +0200 Subject: [PATCH 20/41] Fixup Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 4 ++-- bin/node/runtime/src/lib.rs | 4 ++-- .../basic-authorship/src/basic_authorship.rs | 8 +++---- client/block-builder/src/lib.rs | 8 +++++-- frame/executive/src/lib.rs | 22 +++++++++---------- frame/executive/src/tests.rs | 2 +- .../src/construct_runtime/expand/inherent.rs | 2 +- primitives/block-builder/src/lib.rs | 4 ++-- .../runtime/src/transaction_validity.rs | 4 ++-- test-utils/runtime/src/lib.rs | 4 ++-- 10 files changed, 33 insertions(+), 29 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index f6c6c60df4dab..d575dc77e6317 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -393,8 +393,8 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() { - Executive::after_inherents() + fn after_inherents(mode: sp_runtime::RuntimeExecutiveMode) { + Executive::after_inherents(mode) } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 7fa7025867654..5dd1f2f937b5e 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2121,8 +2121,8 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents() { - Executive::after_inherents() + fn after_inherents(mode: sp_runtime::RuntimeExecutiveMode) { + Executive::after_inherents(mode) } } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 9bd0a7b8f0c56..0dec692a3bc87 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -349,10 +349,10 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); - block_builder.after_inherents()?; + block_builder.after_inherents(block_builder.executive_mode)?; let end_reason = match block_builder.executive_mode { RuntimeExecutiveMode::Normal => - self.apply_extrinsics(&mut block_builder, deadline, block_size_limit).await?, + self.apply_transactions(&mut block_builder, deadline, block_size_limit).await?, RuntimeExecutiveMode::Minimal => EndProposingReason::TransactionsForbidden, }; @@ -404,8 +404,8 @@ where Ok(()) } - /// Apply as many extrinsics as possible to the block. - async fn apply_extrinsics( + /// Apply as many transactions as possible to the block. + async fn apply_transactions( &self, block_builder: &mut sc_block_builder::BlockBuilder<'_, Block, C, B>, deadline: time::Instant, diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index aa92c209a2519..1400cd5fac04e 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -202,9 +202,13 @@ where } /// Called after inherents but before extrinsics have been applied. - pub fn after_inherents(&self) -> Result<(), Error> { + pub fn after_inherents(&self, mode: RuntimeExecutiveMode) -> Result<(), Error> { self.api - .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) + .after_inherents_with_context( + self.parent_hash, + ExecutionContext::BlockConstruction, + mode, + ) .map_err(Into::into) } diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index c2fbb9e591075..8e8a719dd5d3b 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -309,7 +309,7 @@ impl< for e in extrinsics.iter().take(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { frame_support::log::error!( - target: LOG_TARGET, "extrinsic {:?} failed due to {:?}. Aborting the rest of the block execution.", + target: LOG_TARGET, "inherent {:?} failed due to {:?}. Aborting the rest of the block execution.", e, err, ); @@ -317,17 +317,17 @@ impl< } } - Self::after_inherents(); + Self::after_inherents(mode); if mode == RuntimeExecutiveMode::Minimal { if num_inherents < extrinsics.len() { - return Err(InvalidTransaction::NotMandatory.into()) + return Err(InvalidTransaction::NonMandatory.into()) } } // Apply transactions: for e in extrinsics.iter().skip(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { frame_support::log::error!( - target: LOG_TARGET, "extrinsics {:?} failed due to {:?}. Aborting the rest of the block execution.", + target: LOG_TARGET, "transaction {:?} failed due to {:?}. Aborting the rest of the block execution.", e, err, ); @@ -545,21 +545,21 @@ impl< sp_tracing::info_span!("execute_block", ?block); // Execute `on_runtime_upgrade` and `on_initialize`. let mode = Self::initialize_block(block.header()); - let inherents = Self::initial_checks(&block) as usize; + let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); // Process inherents (if any). - Self::apply_extrinsics(extrinsics.iter().take(inherents), mode); - Self::after_inherents(); + Self::apply_extrinsics(extrinsics.iter().take(num_inherents), mode); + Self::after_inherents(mode); if mode == RuntimeExecutiveMode::Minimal { - if inherents < extrinsics.len() { + if num_inherents < extrinsics.len() { // Note: It would be possible to not explicitly panic here since the state-root // check should already catch any mismatch, but this makes it easier to debug. panic!("Only inherents are allowed in 'Minimal' blocks"); } } // Process transactions (if any). - Self::apply_extrinsics(extrinsics.iter().skip(inherents), mode); + Self::apply_extrinsics(extrinsics.iter().skip(num_inherents), mode); >::note_finished_extrinsics(); // TODO MBMs will skip this. @@ -571,7 +571,7 @@ impl< } /// Execute code after inherents but before extrinsic application. - pub fn after_inherents() { + pub fn after_inherents(_mode: RuntimeExecutiveMode) { // TODO run either MBMs or `poll` depending on the mode: // // @@ -672,7 +672,7 @@ impl< } if mode == RuntimeExecutiveMode::Minimal && !mandatory { defensive!("Only 'Mandatory' extrinsics should be present in a 'Minimal' block"); - return Err(InvalidTransaction::NotMandatory.into()) + return Err(InvalidTransaction::NonMandatory.into()) } >::note_applied_extrinsic(&r, dispatch_info); diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index ee462a7ba0d6a..0c24e23f1d135 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -1076,7 +1076,7 @@ fn try_execute_block_works() { /// Same as `extrinsic_while_exts_forbidden_errors` but using the try-runtime function. #[test] #[cfg(feature = "try-runtime")] -#[should_panic = "Only inherents are allowed in 'Minimal' blocks"] +#[should_panic = "Non-mandatory extrinsic was applied in a mandatory-only block"] fn try_execute_ext_forbidden_errors() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); diff --git a/frame/support/procedural/src/construct_runtime/expand/inherent.rs b/frame/support/procedural/src/construct_runtime/expand/inherent.rs index 61bbf9204b26b..1da8dba0ac2f3 100644 --- a/frame/support/procedural/src/construct_runtime/expand/inherent.rs +++ b/frame/support/procedural/src/construct_runtime/expand/inherent.rs @@ -209,7 +209,7 @@ pub fn expand_outer_inherent( }; if is_inherent { - if num_inherents != i{ + if num_inherents != i { return Err(i as u32); } diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index b4ded30416a39..8d011b360af20 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult, RuntimeExecutiveMode}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. @@ -50,6 +50,6 @@ sp_api::decl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; /// Called after inherents but before extrinsic application. - fn after_inherents(); + fn after_inherents(mode: RuntimeExecutiveMode); } } diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index 8f18522333d0d..1dce4b86734a2 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -83,7 +83,7 @@ pub enum InvalidTransaction { /// The sending address is disabled or known to be invalid. BadSigner, /// Only mandatory logic is allowed but it was attempted to execute non-mandatory logic. - NotMandatory, + NonMandatory, } impl InvalidTransaction { @@ -115,7 +115,7 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", - InvalidTransaction::NotMandatory => "Only mandatory logic is allowed", + InvalidTransaction::NonMandatory => "Non-mandatory extrinsic was applied in a mandatory-only block", } } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 384f2762cea60..e67f49216689c 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -535,8 +535,8 @@ impl_runtime_apis! { CheckInherentsResult::new() } - fn after_inherents() { - Executive::after_inherents() + fn after_inherents(mode: sp_runtime::RuntimeExecutiveMode) { + Executive::after_inherents(mode) } } From a54f5fd3075e2d600b7ef5f7cd4c95ffb50e0d21 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 17:14:07 +0200 Subject: [PATCH 21/41] Move initialize_block to the block builder Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 8 ++++---- bin/node/executor/tests/basic.rs | 10 +++++++--- bin/node/runtime/src/lib.rs | 8 ++++---- client/block-builder/src/lib.rs | 4 +--- client/consensus/aura/src/lib.rs | 11 ++++++----- client/consensus/aura/src/standalone.rs | 5 +++-- client/transaction-pool/Cargo.toml | 1 + client/transaction-pool/src/api.rs | 9 ++++----- client/transaction-pool/src/lib.rs | 6 ++++-- frame/support/test/tests/runtime_metadata.rs | 13 ------------- .../proc-macro/src/mock_impl_runtime_apis.rs | 17 ----------------- primitives/api/src/lib.rs | 3 --- primitives/api/test/tests/decl_and_impl.rs | 3 --- primitives/api/test/tests/runtime_calls.rs | 3 ++- primitives/block-builder/src/lib.rs | 3 +++ primitives/runtime/src/transaction_validity.rs | 3 ++- test-utils/runtime/src/lib.rs | 10 +++++----- 17 files changed, 46 insertions(+), 71 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index d575dc77e6317..9c2a6e5964261 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -353,10 +353,6 @@ impl_runtime_apis! { fn execute_block(block: Block) { Executive::execute_block(block); } - - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { - Executive::initialize_block(header) - } } impl sp_api::Metadata for Runtime { @@ -378,6 +374,10 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + Executive::initialize_block(header) + } + fn finalize_block() -> ::Header { Executive::finalize_block() } diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index d301aa06f90b0..0fa45e626c6f6 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -219,9 +219,13 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() { t.insert(>::hashed_key().to_vec(), 69u128.encode()); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = - executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) - .0; + let r = executor_call( + &mut t, + "BlockBuilder_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + ) + .0; assert!(r.is_ok()); let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true) .0 diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 5dd1f2f937b5e..9852d64f1c18b 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2084,10 +2084,6 @@ impl_runtime_apis! { fn execute_block(block: Block) { Executive::execute_block(block); } - - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { - Executive::initialize_block(header) - } } impl sp_api::Metadata for Runtime { @@ -2109,6 +2105,10 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + Executive::initialize_block(header) + } + fn finalize_block() -> ::Header { Executive::finalize_block() } diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 1400cd5fac04e..3ba057483d4f6 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -28,9 +28,7 @@ use codec::Encode; -use sp_api::{ - ApiExt, ApiRef, Core, ProvideRuntimeApi, StorageChanges, StorageProof, TransactionOutcome, -}; +use sp_api::{ApiExt, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof, TransactionOutcome}; use sp_blockchain::{ApplyExtrinsicFailed, Error}; use sp_core::ExecutionContext; use sp_runtime::{ diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 1dc364283d5b6..82ac48356f1d3 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -36,6 +36,7 @@ use futures::prelude::*; use codec::{Codec, Decode, Encode}; +use sc_block_builder::BlockBuilderApi; use sc_client_api::{backend::AuxStore, BlockOf}; use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, StateAction}; use sc_consensus_slots::{ @@ -43,7 +44,7 @@ use sc_consensus_slots::{ SlotInfo, StorageChanges, }; use sc_telemetry::TelemetryHandle; -use sp_api::{Core, ProvideRuntimeApi}; +use sp_api::ProvideRuntimeApi; use sp_application_crypto::AppPublic; use sp_blockchain::HeaderBackend; use sp_consensus::{BlockOrigin, Environment, Error as ConsensusError, Proposer, SelectChain}; @@ -177,7 +178,7 @@ where P::Signature: TryFrom> + Hash + Member + Encode + Decode, B: BlockT, C: ProvideRuntimeApi + BlockOf + AuxStore + HeaderBackend + Send + Sync, - C::Api: AuraApi>, + C::Api: AuraApi> + BlockBuilderApi, SC: SelectChain, I: BlockImport> + Send + Sync + 'static, PF: Environment + Send + Sync + 'static, @@ -278,7 +279,7 @@ pub fn build_aura_worker( where B: BlockT, C: ProvideRuntimeApi + BlockOf + AuxStore + HeaderBackend + Send + Sync, - C::Api: AuraApi>, + C::Api: AuraApi> + BlockBuilderApi, PF: Environment + Send + Sync + 'static, PF::Proposer: Proposer>, P: Pair + Send + Sync, @@ -329,7 +330,7 @@ impl sc_consensus_slots::SimpleSlotWorker where B: BlockT, C: ProvideRuntimeApi + BlockOf + HeaderBackend + Sync, - C::Api: AuraApi>, + C::Api: AuraApi> + BlockBuilderApi, E: Environment + Send + Sync, E::Proposer: Proposer>, I: BlockImport> + Send + Sync + 'static, @@ -518,7 +519,7 @@ where A: Codec + Debug, B: BlockT, C: ProvideRuntimeApi, - C::Api: AuraApi, + C::Api: AuraApi + BlockBuilderApi, { let runtime_api = client.runtime_api(); diff --git a/client/consensus/aura/src/standalone.rs b/client/consensus/aura/src/standalone.rs index 0f9b8668d4478..1f98572fcaf07 100644 --- a/client/consensus/aura/src/standalone.rs +++ b/client/consensus/aura/src/standalone.rs @@ -24,8 +24,9 @@ use log::trace; use codec::Codec; +use sc_block_builder::BlockBuilderApi; use sc_client_api::{backend::AuxStore, UsageProvider}; -use sp_api::{Core, ProvideRuntimeApi}; +use sp_api::ProvideRuntimeApi; use sp_application_crypto::{AppCrypto, AppPublic}; use sp_blockchain::Result as CResult; use sp_consensus::Error as ConsensusError; @@ -201,7 +202,7 @@ where A: Codec + Debug, B: BlockT, C: ProvideRuntimeApi, - C::Api: AuraApi, + C::Api: AuraApi + BlockBuilderApi, { let runtime_api = client.runtime_api(); diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 9ddbb80cf46d3..60c1971dbd749 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -24,6 +24,7 @@ serde = { version = "1.0.163", features = ["derive"] } thiserror = "1.0.30" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-client-api = { version = "4.0.0-dev", path = "../api" } +sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index f9d79ee429e6c..aaaf529be8d47 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -29,6 +29,7 @@ use futures::{ use std::{marker::PhantomData, pin::Pin, sync::Arc}; use prometheus_endpoint::Registry as PrometheusRegistry; +use sc_block_builder::BlockBuilderApi; use sc_client_api::{blockchain::HeaderBackend, BlockBackend}; use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_blockchain::{HeaderMetadata, TreeRoute}; @@ -119,7 +120,7 @@ where + HeaderBackend + HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: TaggedTransactionQueue, + Client::Api: TaggedTransactionQueue + sc_block_builder::BlockBuilderApi, { type Block = Block; type Error = error::Error; @@ -221,7 +222,7 @@ where + HeaderBackend + HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: TaggedTransactionQueue, + Client::Api: TaggedTransactionQueue + BlockBuilderApi, { sp_tracing::within_span!(sp_tracing::Level::TRACE, "validate_transaction"; { @@ -239,8 +240,6 @@ where )) }?; - use sp_api::Core; - sp_tracing::within_span!( sp_tracing::Level::TRACE, "runtime::validate_transaction"; { @@ -286,7 +285,7 @@ where + HeaderBackend + HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: TaggedTransactionQueue, + Client::Api: TaggedTransactionQueue + sc_block_builder::BlockBuilderApi, { /// Validates a transaction by calling into the runtime, same as /// `validate_transaction` but blocks the current thread when performing diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 1b438bd7e4f2f..4b310138e0a76 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -373,7 +373,8 @@ where + Send + Sync + 'static, - Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue, + Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sc_block_builder::BlockBuilderApi, { /// Create new basic transaction pool for a full node with the provided api. pub fn new_full( @@ -415,7 +416,8 @@ where + sp_runtime::traits::BlockIdTo + sp_blockchain::HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue, + Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sc_block_builder::BlockBuilderApi, { type Block = Block; type Hash = graph::ExtrinsicHash>; diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index d9e04bdebda66..24a9e4f6cb873 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -22,7 +22,6 @@ use frame_support::{ traits::ConstU32, }; use scale_info::{form::MetaForm, meta_type}; -use sp_runtime::traits::Block as BlockT; pub type BlockNumber = u64; pub type Index = u64; @@ -107,9 +106,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } @@ -200,15 +196,6 @@ fn runtime_metadata() { output: meta_type::<()>(), docs: maybe_docs(vec![" Execute the given block."]), }, - RuntimeApiMethodMetadataIR { - name: "initialize_block", - inputs: vec![RuntimeApiMethodParamMetadataIR:: { - name: "header", - ty: meta_type::<&::Header>(), - }], - output: meta_type::(), - docs: maybe_docs(vec![" Initialize a block with the given header."]), - }, ], docs: maybe_docs(vec![ " The `Core` runtime api that every Substrate runtime needs to implement.", diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index 0229c51c5f92b..b91c23c5b88bf 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -165,23 +165,6 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result std::result::Result<(), #crate_::ApiError> { unimplemented!("`Core::execute_block` not implemented for runtime api mocks") } - - fn initialize_block( - &self, - _: <#block_type as #crate_::BlockT>::Hash, - _: &<#block_type as #crate_::BlockT>::Header, - ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { - unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") - } - - fn initialize_block_with_context( - &self, - _: <#block_type as #crate_::BlockT>::Hash, - _: #crate_::ExecutionContext, - _: &<#block_type as #crate_::BlockT>::Header, - ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { - unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") - } } )) } diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 63ad38474b28d..857c7f8ef86fe 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -722,9 +722,6 @@ decl_runtime_apis! { fn version() -> RuntimeVersion; /// Execute the given block. fn execute_block(block: Block); - /// Initialize a block with the given header. - #[renamed("initialise_block", 2)] - fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; } /// The `Metadata` api trait that returns metadata for the runtime. diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 25b7ad81b49fc..3728a2b0f82b9 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -89,9 +89,6 @@ impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 344c2d31eb0a6..ebcf7d027a583 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -17,7 +17,8 @@ use std::panic::UnwindSafe; -use sp_api::{ApiExt, Core, ProvideRuntimeApi}; +use sc_block_builder::BlockBuilderApi; +use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_runtime::{ traits::{HashFor, Header as HeaderT}, TransactionOutcome, diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 8d011b360af20..6a54c7d0e378d 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -37,6 +37,9 @@ sp_api::decl_runtime_apis! { extrinsic: ::Extrinsic, ) -> sp_runtime::legacy::byte_sized_error::ApplyExtrinsicResult; + /// Initialize a block with the given header. + fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; + /// Finish the current block. #[renamed("finalise_block", 3)] fn finalize_block() -> ::Header; diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index 1dce4b86734a2..9f1599387ba2e 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -115,7 +115,8 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", - InvalidTransaction::NonMandatory => "Non-mandatory extrinsic was applied in a mandatory-only block", + InvalidTransaction::NonMandatory => + "Non-mandatory extrinsic was applied in a mandatory-only block", } } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index e67f49216689c..b3cea943e6a8a 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -485,11 +485,6 @@ impl_runtime_apis! { log::trace!(target: LOG_TARGET, "execute_block: {block:#?}"); Executive::execute_block(block); } - - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { - log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); - Executive::initialize_block(header) - } } impl sp_api::Metadata for Runtime { @@ -522,6 +517,11 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); + Executive::initialize_block(header) + } + fn finalize_block() -> ::Header { log::trace!(target: LOG_TARGET, "finalize_block"); Executive::finalize_block() From a01f247b55c4b4713bf7bad53707969445e6fb49 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 17:38:28 +0200 Subject: [PATCH 22/41] Fix test Signed-off-by: Oliver Tale-Yazdi --- bin/node/executor/benches/bench.rs | 2 +- bin/node/executor/tests/basic.rs | 34 +++++++++++++------ bin/node/executor/tests/common.rs | 4 ++- bin/node/executor/tests/fees.rs | 10 ++++-- client/service/test/src/client/mod.rs | 2 +- .../cli/src/commands/fast_forward.rs | 3 +- 6 files changed, 37 insertions(+), 18 deletions(-) diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index 6b082744e49f5..1d674566526bc 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -115,7 +115,7 @@ fn construct_block( .call( ext, &runtime_code, - "Core_initialize_block", + "BlockBuilder_initialize_block", &header.encode(), true, CallContext::Offchain, diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index 0fa45e626c6f6..d1402ab6a8f93 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -193,9 +193,13 @@ fn panic_execution_with_foreign_code_gives_error() { t.insert(>::hashed_key().to_vec(), 69_u128.encode()); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = - executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) - .0; + let r = executor_call( + &mut t, + "BlockBuilder_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + ) + .0; assert!(r.is_ok()); let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true) .0 @@ -260,9 +264,13 @@ fn successful_execution_with_native_equivalent_code_gives_ok() { ); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = - executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) - .0; + let r = executor_call( + &mut t, + "BlockBuilder_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + ) + .0; assert!(r.is_ok()); let fees = t.execute_with(|| transfer_fee(&xt())); @@ -302,9 +310,13 @@ fn successful_execution_with_foreign_code_gives_ok() { ); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = - executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) - .0; + let r = executor_call( + &mut t, + "BlockBuilder_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + ) + .0; assert!(r.is_ok()); let fees = t.execute_with(|| transfer_fee(&xt())); @@ -781,7 +793,7 @@ fn panic_execution_gives_error() { let r = executor_call( &mut t, - "Core_initialize_block", + "BlockBuilder_initialize_block", &vec![].and(&from_block_number(1u32)), false, ) @@ -822,7 +834,7 @@ fn successful_execution_gives_ok() { let r = executor_call( &mut t, - "Core_initialize_block", + "BlockBuilder_initialize_block", &vec![].and(&from_block_number(1u32)), false, ) diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 6ce9ea3a01090..7b2b9c2ce0412 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -168,7 +168,9 @@ pub fn construct_block( }; // execute the block to get the real header. - executor_call(env, "Core_initialize_block", &header.encode(), true).0.unwrap(); + executor_call(env, "BlockBuilder_initialize_block", &header.encode(), true) + .0 + .unwrap(); for extrinsic in extrinsics.iter() { // Try to apply the `extrinsic`. It should be valid, in the sense that it passes diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs index 970d790a87d3b..95658b63083cd 100644 --- a/bin/node/executor/tests/fees.rs +++ b/bin/node/executor/tests/fees.rs @@ -151,9 +151,13 @@ fn transaction_fee_is_correct() { function: RuntimeCall::Balances(default_transfer_call()), }); - let r = - executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) - .0; + let r = executor_call( + &mut t, + "BlockBuilder_initialize_block", + &vec![].and(&from_block_number(1u32)), + true, + ) + .0; assert!(r.is_ok()); let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt.clone()), true).0; diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 9c490a47a3b14..02035f5738d93 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -88,7 +88,7 @@ fn construct_block( backend, &mut overlay, &new_native_or_wasm_executor(), - "Core_initialize_block", + "BlockBuilder_initialize_block", &header.encode(), Default::default(), &runtime_code, diff --git a/utils/frame/try-runtime/cli/src/commands/fast_forward.rs b/utils/frame/try-runtime/cli/src/commands/fast_forward.rs index ea3ae532ca74d..85d2b74c59b2e 100644 --- a/utils/frame/try-runtime/cli/src/commands/fast_forward.rs +++ b/utils/frame/try-runtime/cli/src/commands/fast_forward.rs @@ -174,7 +174,8 @@ async fn next_empty_block< ); let mut extrinsics = >::new(); - run::(externalities, executor, "Core_initialize_block", &header.encode()).await?; + run::(externalities, executor, "BlockBuilder_initialize_block", &header.encode()) + .await?; if let Some(ref inherent_data) = maybe_inherent_data { extrinsics = dry_run::, Block, _>( From b50a78b3aaf11aaddcc67e2fc1c8876903f154d2 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 18:13:57 +0200 Subject: [PATCH 23/41] Fix test Signed-off-by: Oliver Tale-Yazdi --- primitives/api/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 857c7f8ef86fe..bc8b575aa2157 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -288,7 +288,6 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// # unimplemented!() /// # } /// # fn execute_block(_block: Block) {} -/// # fn initialize_block(_header: &::Header) {} /// # } /// /// impl self::Balance for Runtime { From 8f7751cf400c3fc61d4f54e32d3ec8f2b77b6a75 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 19:59:25 +0200 Subject: [PATCH 24/41] Fix imports Signed-off-by: Oliver Tale-Yazdi --- primitives/api/test/tests/decl_and_impl.rs | 2 +- .../api/test/tests/ui/impl_incorrect_method_signature.rs | 4 ---- primitives/api/test/tests/ui/impl_missing_version.rs | 4 ---- primitives/api/test/tests/ui/missing_versioned_method.rs | 4 ---- .../test/tests/ui/missing_versioned_method_multiple_vers.rs | 4 ---- .../api/test/tests/ui/positive_cases/custom_where_bound.rs | 4 ---- primitives/api/test/tests/ui/positive_cases/default_impls.rs | 4 ---- .../test/tests/ui/type_reference_in_impl_runtime_apis_call.rs | 4 ---- 8 files changed, 1 insertion(+), 29 deletions(-) diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 3728a2b0f82b9..e83f4ba78369a 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -15,10 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use sp_runtime::traits::Block as BlockT; use sp_api::{ decl_runtime_apis, impl_runtime_apis, mock_impl_runtime_apis, ApiError, ApiExt, RuntimeApiInfo, }; -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::{Block, Hash}; diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs index 96c7c32dc79e7..0ccd79a0a4bb8 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs @@ -1,4 +1,3 @@ -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real @@ -23,9 +22,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/ui/impl_missing_version.rs b/primitives/api/test/tests/ui/impl_missing_version.rs index bad30ac23920e..6bc549e86b6b1 100644 --- a/primitives/api/test/tests/ui/impl_missing_version.rs +++ b/primitives/api/test/tests/ui/impl_missing_version.rs @@ -1,4 +1,3 @@ -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -28,9 +27,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method.rs b/primitives/api/test/tests/ui/missing_versioned_method.rs index 44c03ea842023..6f59d514b3ae7 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method.rs @@ -1,4 +1,3 @@ -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -27,9 +26,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs index c659ed9be4355..054718aa26e24 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs @@ -1,4 +1,3 @@ -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -30,9 +29,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs index c4031ed683753..fa96470338040 100644 --- a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs +++ b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs @@ -1,6 +1,5 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -34,9 +33,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/ui/positive_cases/default_impls.rs b/primitives/api/test/tests/ui/positive_cases/default_impls.rs index deffb43481999..678d49fd18ae9 100644 --- a/primitives/api/test/tests/ui/positive_cases/default_impls.rs +++ b/primitives/api/test/tests/ui/positive_cases/default_impls.rs @@ -1,4 +1,3 @@ -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -29,9 +28,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs index 40d846946538f..14d62dea4071d 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -1,4 +1,3 @@ -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::Block; /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real @@ -25,9 +24,6 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { - unimplemented!() - } } } From baa9a39d69e762351db7eda0b63c86c14ab98eba Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 20:11:49 +0200 Subject: [PATCH 25/41] Update UI tests Signed-off-by: Oliver Tale-Yazdi --- primitives/api/test/tests/decl_and_impl.rs | 2 +- .../ui/impl_incorrect_method_signature.stderr | 30 +++++++++---------- .../test/tests/ui/impl_missing_version.stderr | 6 ++-- .../tests/ui/missing_versioned_method.stderr | 6 ++-- ...sing_versioned_method_multiple_vers.stderr | 6 ++-- ...reference_in_impl_runtime_apis_call.stderr | 28 ++++++++--------- 6 files changed, 39 insertions(+), 39 deletions(-) diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index e83f4ba78369a..3728a2b0f82b9 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -15,10 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use sp_runtime::traits::Block as BlockT; use sp_api::{ decl_runtime_apis, impl_runtime_apis, mock_impl_runtime_apis, ApiError, ApiExt, RuntimeApiInfo, }; +use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::{Block, Hash}; diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr index 2324be85be4f8..9d183b3673f85 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr @@ -1,35 +1,35 @@ error[E0053]: method `test` has an incompatible type for trait - --> tests/ui/impl_incorrect_method_signature.rs:16:17 + --> tests/ui/impl_incorrect_method_signature.rs:15:17 | -16 | fn test(data: String) {} +15 | fn test(data: String) {} | ^^^^^^ | | - | expected `u64`, found `std::string::String` + | expected `u64`, found `String` | help: change the parameter type to match the trait: `u64` | note: type in trait - --> tests/ui/impl_incorrect_method_signature.rs:10:17 + --> tests/ui/impl_incorrect_method_signature.rs:9:17 | -10 | fn test(data: u64); +9 | fn test(data: u64); | ^^^ = note: expected signature `fn(u64)` - found signature `fn(std::string::String)` + found signature `fn(String)` error[E0308]: mismatched types - --> tests/ui/impl_incorrect_method_signature.rs:16:11 + --> tests/ui/impl_incorrect_method_signature.rs:15:11 | -14 | / sp_api::impl_runtime_apis! { -15 | | impl self::Api for Runtime { -16 | | fn test(data: String) {} +13 | / sp_api::impl_runtime_apis! { +14 | | impl self::Api for Runtime { +15 | | fn test(data: String) {} | | ^^^^ expected `u64`, found `String` -17 | | } +16 | | } ... | -29 | | } -30 | | } +25 | | } +26 | | } | |_- arguments to this function are incorrect | note: associated function defined here - --> tests/ui/impl_incorrect_method_signature.rs:10:6 + --> tests/ui/impl_incorrect_method_signature.rs:9:6 | -10 | fn test(data: u64); +9 | fn test(data: u64); | ^^^^ diff --git a/primitives/api/test/tests/ui/impl_missing_version.stderr b/primitives/api/test/tests/ui/impl_missing_version.stderr index 770543aa8875d..4ca0997392ba5 100644 --- a/primitives/api/test/tests/ui/impl_missing_version.stderr +++ b/primitives/api/test/tests/ui/impl_missing_version.stderr @@ -1,8 +1,8 @@ error[E0405]: cannot find trait `ApiV4` in module `self::runtime_decl_for_api` - --> tests/ui/impl_missing_version.rs:18:13 + --> tests/ui/impl_missing_version.rs:17:13 | -8 | pub trait Api { +7 | pub trait Api { | ------------- similarly named trait `ApiV2` defined here ... -18 | impl self::Api for Runtime { +17 | impl self::Api for Runtime { | ^^^ help: a trait with a similar name exists: `ApiV2` diff --git a/primitives/api/test/tests/ui/missing_versioned_method.stderr b/primitives/api/test/tests/ui/missing_versioned_method.stderr index b88d903212df1..25255a67fbd4b 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method.stderr +++ b/primitives/api/test/tests/ui/missing_versioned_method.stderr @@ -1,8 +1,8 @@ error[E0046]: not all trait items implemented, missing: `test3` - --> tests/ui/missing_versioned_method.rs:18:2 + --> tests/ui/missing_versioned_method.rs:17:2 | -12 | fn test3(); +11 | fn test3(); | ----------- `test3` from trait ... -18 | impl self::Api for Runtime { +17 | impl self::Api for Runtime { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `test3` in implementation diff --git a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr index 4afa6856a5814..7c3785f48c2ce 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr +++ b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr @@ -1,8 +1,8 @@ error[E0046]: not all trait items implemented, missing: `test3` - --> tests/ui/missing_versioned_method_multiple_vers.rs:20:2 + --> tests/ui/missing_versioned_method_multiple_vers.rs:19:2 | -12 | fn test3(); +11 | fn test3(); | ----------- `test3` from trait ... -20 | impl self::Api for Runtime { +19 | impl self::Api for Runtime { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `test3` in implementation diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index e9d550f3a3bcf..72044dc94341d 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -1,39 +1,39 @@ error[E0053]: method `test` has an incompatible type for trait - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:16:17 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:15:17 | -16 | fn test(data: &u64) { +15 | fn test(data: &u64) { | ^^^^ | | | expected `u64`, found `&u64` | help: change the parameter type to match the trait: `u64` | note: type in trait - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:10:17 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:9:17 | -10 | fn test(data: u64); +9 | fn test(data: u64); | ^^^ = note: expected signature `fn(u64)` found signature `fn(&u64)` error[E0308]: mismatched types - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:16:11 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:15:11 | -14 | / sp_api::impl_runtime_apis! { -15 | | impl self::Api for Runtime { -16 | | fn test(data: &u64) { +13 | / sp_api::impl_runtime_apis! { +14 | | impl self::Api for Runtime { +15 | | fn test(data: &u64) { | | ^^^^^^^ expected `u64`, found `&u64` -17 | | unimplemented!() +16 | | unimplemented!() ... | -31 | | } -32 | | } +27 | | } +28 | | } | |_- arguments to this function are incorrect | note: associated function defined here - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:10:6 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:9:6 | -10 | fn test(data: u64); +9 | fn test(data: u64); | ^^^^ help: consider removing the borrow | -16 | fn test(data: &u64) { +15 | fn test(data: &u64) { | From 2c6f7646111c6eab778155588f27799518bad3df Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 21:03:39 +0200 Subject: [PATCH 26/41] Check runtime API Signed-off-by: Oliver Tale-Yazdi --- client/block-builder/src/lib.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 3ba057483d4f6..a62bd852601c8 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -201,13 +201,17 @@ where /// Called after inherents but before extrinsics have been applied. pub fn after_inherents(&self, mode: RuntimeExecutiveMode) -> Result<(), Error> { - self.api - .after_inherents_with_context( - self.parent_hash, - ExecutionContext::BlockConstruction, - mode, - ) - .map_err(Into::into) + if self.version >= 7 { + self.api + .after_inherents_with_context( + self.parent_hash, + ExecutionContext::BlockConstruction, + mode, + ) + .map_err(Into::into) + } else { + Ok(()) + } } /// Push onto the block's list of extrinsics. From 706bcd9250c6867803e8d150c6da464e184c4eb8 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 22:32:15 +0200 Subject: [PATCH 27/41] Revert "Update UI tests" This reverts commit baa9a39d69e762351db7eda0b63c86c14ab98eba. Revert "Fix test" This reverts commit b50a78b3aaf11aaddcc67e2fc1c8876903f154d2. Revert "Fix test" This reverts commit a01f247b55c4b4713bf7bad53707969445e6fb49. Revert "Move initialize_block to the block builder" This reverts commit a54f5fd3075e2d600b7ef5f7cd4c95ffb50e0d21. --- bin/node-template/runtime/src/lib.rs | 8 ++-- bin/node/executor/benches/bench.rs | 2 +- bin/node/executor/tests/basic.rs | 44 ++++++------------- bin/node/executor/tests/common.rs | 4 +- bin/node/executor/tests/fees.rs | 10 ++--- bin/node/runtime/src/lib.rs | 8 ++-- client/block-builder/src/lib.rs | 4 +- client/consensus/aura/src/lib.rs | 11 +++-- client/consensus/aura/src/standalone.rs | 5 +-- client/service/test/src/client/mod.rs | 2 +- client/transaction-pool/Cargo.toml | 1 - client/transaction-pool/src/api.rs | 9 ++-- client/transaction-pool/src/lib.rs | 6 +-- frame/support/test/tests/runtime_metadata.rs | 13 ++++++ .../proc-macro/src/mock_impl_runtime_apis.rs | 17 +++++++ primitives/api/src/lib.rs | 4 ++ primitives/api/test/tests/decl_and_impl.rs | 5 ++- primitives/api/test/tests/runtime_calls.rs | 3 +- .../ui/impl_incorrect_method_signature.stderr | 30 ++++++------- .../test/tests/ui/impl_missing_version.stderr | 6 +-- .../tests/ui/missing_versioned_method.stderr | 6 +-- ...sing_versioned_method_multiple_vers.stderr | 6 +-- ...reference_in_impl_runtime_apis_call.stderr | 28 ++++++------ primitives/block-builder/src/lib.rs | 3 -- .../runtime/src/transaction_validity.rs | 3 +- test-utils/runtime/src/lib.rs | 10 ++--- .../cli/src/commands/fast_forward.rs | 3 +- 27 files changed, 129 insertions(+), 122 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 9c2a6e5964261..d575dc77e6317 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -353,6 +353,10 @@ impl_runtime_apis! { fn execute_block(block: Block) { Executive::execute_block(block); } + + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + Executive::initialize_block(header) + } } impl sp_api::Metadata for Runtime { @@ -374,10 +378,6 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { - Executive::initialize_block(header) - } - fn finalize_block() -> ::Header { Executive::finalize_block() } diff --git a/bin/node/executor/benches/bench.rs b/bin/node/executor/benches/bench.rs index 1d674566526bc..6b082744e49f5 100644 --- a/bin/node/executor/benches/bench.rs +++ b/bin/node/executor/benches/bench.rs @@ -115,7 +115,7 @@ fn construct_block( .call( ext, &runtime_code, - "BlockBuilder_initialize_block", + "Core_initialize_block", &header.encode(), true, CallContext::Offchain, diff --git a/bin/node/executor/tests/basic.rs b/bin/node/executor/tests/basic.rs index d1402ab6a8f93..d301aa06f90b0 100644 --- a/bin/node/executor/tests/basic.rs +++ b/bin/node/executor/tests/basic.rs @@ -193,13 +193,9 @@ fn panic_execution_with_foreign_code_gives_error() { t.insert(>::hashed_key().to_vec(), 69_u128.encode()); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = executor_call( - &mut t, - "BlockBuilder_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - ) - .0; + let r = + executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) + .0; assert!(r.is_ok()); let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true) .0 @@ -223,13 +219,9 @@ fn bad_extrinsic_with_native_equivalent_code_gives_error() { t.insert(>::hashed_key().to_vec(), 69u128.encode()); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = executor_call( - &mut t, - "BlockBuilder_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - ) - .0; + let r = + executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) + .0; assert!(r.is_ok()); let v = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt()), true) .0 @@ -264,13 +256,9 @@ fn successful_execution_with_native_equivalent_code_gives_ok() { ); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = executor_call( - &mut t, - "BlockBuilder_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - ) - .0; + let r = + executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) + .0; assert!(r.is_ok()); let fees = t.execute_with(|| transfer_fee(&xt())); @@ -310,13 +298,9 @@ fn successful_execution_with_foreign_code_gives_ok() { ); t.insert(>::hashed_key_for(0), vec![0u8; 32]); - let r = executor_call( - &mut t, - "BlockBuilder_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - ) - .0; + let r = + executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) + .0; assert!(r.is_ok()); let fees = t.execute_with(|| transfer_fee(&xt())); @@ -793,7 +777,7 @@ fn panic_execution_gives_error() { let r = executor_call( &mut t, - "BlockBuilder_initialize_block", + "Core_initialize_block", &vec![].and(&from_block_number(1u32)), false, ) @@ -834,7 +818,7 @@ fn successful_execution_gives_ok() { let r = executor_call( &mut t, - "BlockBuilder_initialize_block", + "Core_initialize_block", &vec![].and(&from_block_number(1u32)), false, ) diff --git a/bin/node/executor/tests/common.rs b/bin/node/executor/tests/common.rs index 7b2b9c2ce0412..6ce9ea3a01090 100644 --- a/bin/node/executor/tests/common.rs +++ b/bin/node/executor/tests/common.rs @@ -168,9 +168,7 @@ pub fn construct_block( }; // execute the block to get the real header. - executor_call(env, "BlockBuilder_initialize_block", &header.encode(), true) - .0 - .unwrap(); + executor_call(env, "Core_initialize_block", &header.encode(), true).0.unwrap(); for extrinsic in extrinsics.iter() { // Try to apply the `extrinsic`. It should be valid, in the sense that it passes diff --git a/bin/node/executor/tests/fees.rs b/bin/node/executor/tests/fees.rs index 95658b63083cd..970d790a87d3b 100644 --- a/bin/node/executor/tests/fees.rs +++ b/bin/node/executor/tests/fees.rs @@ -151,13 +151,9 @@ fn transaction_fee_is_correct() { function: RuntimeCall::Balances(default_transfer_call()), }); - let r = executor_call( - &mut t, - "BlockBuilder_initialize_block", - &vec![].and(&from_block_number(1u32)), - true, - ) - .0; + let r = + executor_call(&mut t, "Core_initialize_block", &vec![].and(&from_block_number(1u32)), true) + .0; assert!(r.is_ok()); let r = executor_call(&mut t, "BlockBuilder_apply_extrinsic", &vec![].and(&xt.clone()), true).0; diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9852d64f1c18b..5dd1f2f937b5e 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2084,6 +2084,10 @@ impl_runtime_apis! { fn execute_block(block: Block) { Executive::execute_block(block); } + + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + Executive::initialize_block(header) + } } impl sp_api::Metadata for Runtime { @@ -2105,10 +2109,6 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { - Executive::initialize_block(header) - } - fn finalize_block() -> ::Header { Executive::finalize_block() } diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index a62bd852601c8..0ba2aa39cf2f4 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -28,7 +28,9 @@ use codec::Encode; -use sp_api::{ApiExt, ApiRef, ProvideRuntimeApi, StorageChanges, StorageProof, TransactionOutcome}; +use sp_api::{ + ApiExt, ApiRef, Core, ProvideRuntimeApi, StorageChanges, StorageProof, TransactionOutcome, +}; use sp_blockchain::{ApplyExtrinsicFailed, Error}; use sp_core::ExecutionContext; use sp_runtime::{ diff --git a/client/consensus/aura/src/lib.rs b/client/consensus/aura/src/lib.rs index 82ac48356f1d3..1dc364283d5b6 100644 --- a/client/consensus/aura/src/lib.rs +++ b/client/consensus/aura/src/lib.rs @@ -36,7 +36,6 @@ use futures::prelude::*; use codec::{Codec, Decode, Encode}; -use sc_block_builder::BlockBuilderApi; use sc_client_api::{backend::AuxStore, BlockOf}; use sc_consensus::{BlockImport, BlockImportParams, ForkChoiceStrategy, StateAction}; use sc_consensus_slots::{ @@ -44,7 +43,7 @@ use sc_consensus_slots::{ SlotInfo, StorageChanges, }; use sc_telemetry::TelemetryHandle; -use sp_api::ProvideRuntimeApi; +use sp_api::{Core, ProvideRuntimeApi}; use sp_application_crypto::AppPublic; use sp_blockchain::HeaderBackend; use sp_consensus::{BlockOrigin, Environment, Error as ConsensusError, Proposer, SelectChain}; @@ -178,7 +177,7 @@ where P::Signature: TryFrom> + Hash + Member + Encode + Decode, B: BlockT, C: ProvideRuntimeApi + BlockOf + AuxStore + HeaderBackend + Send + Sync, - C::Api: AuraApi> + BlockBuilderApi, + C::Api: AuraApi>, SC: SelectChain, I: BlockImport> + Send + Sync + 'static, PF: Environment + Send + Sync + 'static, @@ -279,7 +278,7 @@ pub fn build_aura_worker( where B: BlockT, C: ProvideRuntimeApi + BlockOf + AuxStore + HeaderBackend + Send + Sync, - C::Api: AuraApi> + BlockBuilderApi, + C::Api: AuraApi>, PF: Environment + Send + Sync + 'static, PF::Proposer: Proposer>, P: Pair + Send + Sync, @@ -330,7 +329,7 @@ impl sc_consensus_slots::SimpleSlotWorker where B: BlockT, C: ProvideRuntimeApi + BlockOf + HeaderBackend + Sync, - C::Api: AuraApi> + BlockBuilderApi, + C::Api: AuraApi>, E: Environment + Send + Sync, E::Proposer: Proposer>, I: BlockImport> + Send + Sync + 'static, @@ -519,7 +518,7 @@ where A: Codec + Debug, B: BlockT, C: ProvideRuntimeApi, - C::Api: AuraApi + BlockBuilderApi, + C::Api: AuraApi, { let runtime_api = client.runtime_api(); diff --git a/client/consensus/aura/src/standalone.rs b/client/consensus/aura/src/standalone.rs index 1f98572fcaf07..0f9b8668d4478 100644 --- a/client/consensus/aura/src/standalone.rs +++ b/client/consensus/aura/src/standalone.rs @@ -24,9 +24,8 @@ use log::trace; use codec::Codec; -use sc_block_builder::BlockBuilderApi; use sc_client_api::{backend::AuxStore, UsageProvider}; -use sp_api::ProvideRuntimeApi; +use sp_api::{Core, ProvideRuntimeApi}; use sp_application_crypto::{AppCrypto, AppPublic}; use sp_blockchain::Result as CResult; use sp_consensus::Error as ConsensusError; @@ -202,7 +201,7 @@ where A: Codec + Debug, B: BlockT, C: ProvideRuntimeApi, - C::Api: AuraApi + BlockBuilderApi, + C::Api: AuraApi, { let runtime_api = client.runtime_api(); diff --git a/client/service/test/src/client/mod.rs b/client/service/test/src/client/mod.rs index 02035f5738d93..9c490a47a3b14 100644 --- a/client/service/test/src/client/mod.rs +++ b/client/service/test/src/client/mod.rs @@ -88,7 +88,7 @@ fn construct_block( backend, &mut overlay, &new_native_or_wasm_executor(), - "BlockBuilder_initialize_block", + "Core_initialize_block", &header.encode(), Default::default(), &runtime_code, diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 60c1971dbd749..9ddbb80cf46d3 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -24,7 +24,6 @@ serde = { version = "1.0.163", features = ["derive"] } thiserror = "1.0.30" prometheus-endpoint = { package = "substrate-prometheus-endpoint", version = "0.10.0-dev", path = "../../utils/prometheus" } sc-client-api = { version = "4.0.0-dev", path = "../api" } -sc-block-builder = { version = "0.10.0-dev", path = "../block-builder" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index aaaf529be8d47..f9d79ee429e6c 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -29,7 +29,6 @@ use futures::{ use std::{marker::PhantomData, pin::Pin, sync::Arc}; use prometheus_endpoint::Registry as PrometheusRegistry; -use sc_block_builder::BlockBuilderApi; use sc_client_api::{blockchain::HeaderBackend, BlockBackend}; use sp_api::{ApiExt, ProvideRuntimeApi}; use sp_blockchain::{HeaderMetadata, TreeRoute}; @@ -120,7 +119,7 @@ where + HeaderBackend + HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: TaggedTransactionQueue + sc_block_builder::BlockBuilderApi, + Client::Api: TaggedTransactionQueue, { type Block = Block; type Error = error::Error; @@ -222,7 +221,7 @@ where + HeaderBackend + HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: TaggedTransactionQueue + BlockBuilderApi, + Client::Api: TaggedTransactionQueue, { sp_tracing::within_span!(sp_tracing::Level::TRACE, "validate_transaction"; { @@ -240,6 +239,8 @@ where )) }?; + use sp_api::Core; + sp_tracing::within_span!( sp_tracing::Level::TRACE, "runtime::validate_transaction"; { @@ -285,7 +286,7 @@ where + HeaderBackend + HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: TaggedTransactionQueue + sc_block_builder::BlockBuilderApi, + Client::Api: TaggedTransactionQueue, { /// Validates a transaction by calling into the runtime, same as /// `validate_transaction` but blocks the current thread when performing diff --git a/client/transaction-pool/src/lib.rs b/client/transaction-pool/src/lib.rs index 4b310138e0a76..1b438bd7e4f2f 100644 --- a/client/transaction-pool/src/lib.rs +++ b/client/transaction-pool/src/lib.rs @@ -373,8 +373,7 @@ where + Send + Sync + 'static, - Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sc_block_builder::BlockBuilderApi, + Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue, { /// Create new basic transaction pool for a full node with the provided api. pub fn new_full( @@ -416,8 +415,7 @@ where + sp_runtime::traits::BlockIdTo + sp_blockchain::HeaderMetadata, Client: Send + Sync + 'static, - Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue - + sc_block_builder::BlockBuilderApi, + Client::Api: sp_transaction_pool::runtime_api::TaggedTransactionQueue, { type Block = Block; type Hash = graph::ExtrinsicHash>; diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index 24a9e4f6cb873..d9e04bdebda66 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -22,6 +22,7 @@ use frame_support::{ traits::ConstU32, }; use scale_info::{form::MetaForm, meta_type}; +use sp_runtime::traits::Block as BlockT; pub type BlockNumber = u64; pub type Index = u64; @@ -106,6 +107,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { + unimplemented!() + } } } @@ -196,6 +200,15 @@ fn runtime_metadata() { output: meta_type::<()>(), docs: maybe_docs(vec![" Execute the given block."]), }, + RuntimeApiMethodMetadataIR { + name: "initialize_block", + inputs: vec![RuntimeApiMethodParamMetadataIR:: { + name: "header", + ty: meta_type::<&::Header>(), + }], + output: meta_type::(), + docs: maybe_docs(vec![" Initialize a block with the given header."]), + }, ], docs: maybe_docs(vec![ " The `Core` runtime api that every Substrate runtime needs to implement.", diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index b91c23c5b88bf..0229c51c5f92b 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -165,6 +165,23 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result std::result::Result<(), #crate_::ApiError> { unimplemented!("`Core::execute_block` not implemented for runtime api mocks") } + + fn initialize_block( + &self, + _: <#block_type as #crate_::BlockT>::Hash, + _: &<#block_type as #crate_::BlockT>::Header, + ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { + unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") + } + + fn initialize_block_with_context( + &self, + _: <#block_type as #crate_::BlockT>::Hash, + _: #crate_::ExecutionContext, + _: &<#block_type as #crate_::BlockT>::Header, + ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { + unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") + } } )) } diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index bc8b575aa2157..63ad38474b28d 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -288,6 +288,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// # unimplemented!() /// # } /// # fn execute_block(_block: Block) {} +/// # fn initialize_block(_header: &::Header) {} /// # } /// /// impl self::Balance for Runtime { @@ -721,6 +722,9 @@ decl_runtime_apis! { fn version() -> RuntimeVersion; /// Execute the given block. fn execute_block(block: Block); + /// Initialize a block with the given header. + #[renamed("initialise_block", 2)] + fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; } /// The `Metadata` api trait that returns metadata for the runtime. diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 3728a2b0f82b9..a085ef192bd90 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -15,10 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use sp_runtime::traits::Block as BlockT; use sp_api::{ decl_runtime_apis, impl_runtime_apis, mock_impl_runtime_apis, ApiError, ApiExt, RuntimeApiInfo, }; -use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::{Block, Hash}; @@ -89,6 +89,9 @@ impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index ebcf7d027a583..344c2d31eb0a6 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -17,8 +17,7 @@ use std::panic::UnwindSafe; -use sc_block_builder::BlockBuilderApi; -use sp_api::{ApiExt, ProvideRuntimeApi}; +use sp_api::{ApiExt, Core, ProvideRuntimeApi}; use sp_runtime::{ traits::{HashFor, Header as HeaderT}, TransactionOutcome, diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr index 9d183b3673f85..2324be85be4f8 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.stderr @@ -1,35 +1,35 @@ error[E0053]: method `test` has an incompatible type for trait - --> tests/ui/impl_incorrect_method_signature.rs:15:17 + --> tests/ui/impl_incorrect_method_signature.rs:16:17 | -15 | fn test(data: String) {} +16 | fn test(data: String) {} | ^^^^^^ | | - | expected `u64`, found `String` + | expected `u64`, found `std::string::String` | help: change the parameter type to match the trait: `u64` | note: type in trait - --> tests/ui/impl_incorrect_method_signature.rs:9:17 + --> tests/ui/impl_incorrect_method_signature.rs:10:17 | -9 | fn test(data: u64); +10 | fn test(data: u64); | ^^^ = note: expected signature `fn(u64)` - found signature `fn(String)` + found signature `fn(std::string::String)` error[E0308]: mismatched types - --> tests/ui/impl_incorrect_method_signature.rs:15:11 + --> tests/ui/impl_incorrect_method_signature.rs:16:11 | -13 | / sp_api::impl_runtime_apis! { -14 | | impl self::Api for Runtime { -15 | | fn test(data: String) {} +14 | / sp_api::impl_runtime_apis! { +15 | | impl self::Api for Runtime { +16 | | fn test(data: String) {} | | ^^^^ expected `u64`, found `String` -16 | | } +17 | | } ... | -25 | | } -26 | | } +29 | | } +30 | | } | |_- arguments to this function are incorrect | note: associated function defined here - --> tests/ui/impl_incorrect_method_signature.rs:9:6 + --> tests/ui/impl_incorrect_method_signature.rs:10:6 | -9 | fn test(data: u64); +10 | fn test(data: u64); | ^^^^ diff --git a/primitives/api/test/tests/ui/impl_missing_version.stderr b/primitives/api/test/tests/ui/impl_missing_version.stderr index 4ca0997392ba5..770543aa8875d 100644 --- a/primitives/api/test/tests/ui/impl_missing_version.stderr +++ b/primitives/api/test/tests/ui/impl_missing_version.stderr @@ -1,8 +1,8 @@ error[E0405]: cannot find trait `ApiV4` in module `self::runtime_decl_for_api` - --> tests/ui/impl_missing_version.rs:17:13 + --> tests/ui/impl_missing_version.rs:18:13 | -7 | pub trait Api { +8 | pub trait Api { | ------------- similarly named trait `ApiV2` defined here ... -17 | impl self::Api for Runtime { +18 | impl self::Api for Runtime { | ^^^ help: a trait with a similar name exists: `ApiV2` diff --git a/primitives/api/test/tests/ui/missing_versioned_method.stderr b/primitives/api/test/tests/ui/missing_versioned_method.stderr index 25255a67fbd4b..b88d903212df1 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method.stderr +++ b/primitives/api/test/tests/ui/missing_versioned_method.stderr @@ -1,8 +1,8 @@ error[E0046]: not all trait items implemented, missing: `test3` - --> tests/ui/missing_versioned_method.rs:17:2 + --> tests/ui/missing_versioned_method.rs:18:2 | -11 | fn test3(); +12 | fn test3(); | ----------- `test3` from trait ... -17 | impl self::Api for Runtime { +18 | impl self::Api for Runtime { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `test3` in implementation diff --git a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr index 7c3785f48c2ce..4afa6856a5814 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr +++ b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.stderr @@ -1,8 +1,8 @@ error[E0046]: not all trait items implemented, missing: `test3` - --> tests/ui/missing_versioned_method_multiple_vers.rs:19:2 + --> tests/ui/missing_versioned_method_multiple_vers.rs:20:2 | -11 | fn test3(); +12 | fn test3(); | ----------- `test3` from trait ... -19 | impl self::Api for Runtime { +20 | impl self::Api for Runtime { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `test3` in implementation diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr index 72044dc94341d..e9d550f3a3bcf 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.stderr @@ -1,39 +1,39 @@ error[E0053]: method `test` has an incompatible type for trait - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:15:17 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:16:17 | -15 | fn test(data: &u64) { +16 | fn test(data: &u64) { | ^^^^ | | | expected `u64`, found `&u64` | help: change the parameter type to match the trait: `u64` | note: type in trait - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:9:17 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:10:17 | -9 | fn test(data: u64); +10 | fn test(data: u64); | ^^^ = note: expected signature `fn(u64)` found signature `fn(&u64)` error[E0308]: mismatched types - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:15:11 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:16:11 | -13 | / sp_api::impl_runtime_apis! { -14 | | impl self::Api for Runtime { -15 | | fn test(data: &u64) { +14 | / sp_api::impl_runtime_apis! { +15 | | impl self::Api for Runtime { +16 | | fn test(data: &u64) { | | ^^^^^^^ expected `u64`, found `&u64` -16 | | unimplemented!() +17 | | unimplemented!() ... | -27 | | } -28 | | } +31 | | } +32 | | } | |_- arguments to this function are incorrect | note: associated function defined here - --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:9:6 + --> tests/ui/type_reference_in_impl_runtime_apis_call.rs:10:6 | -9 | fn test(data: u64); +10 | fn test(data: u64); | ^^^^ help: consider removing the borrow | -15 | fn test(data: &u64) { +16 | fn test(data: &u64) { | diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 6a54c7d0e378d..8d011b360af20 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -37,9 +37,6 @@ sp_api::decl_runtime_apis! { extrinsic: ::Extrinsic, ) -> sp_runtime::legacy::byte_sized_error::ApplyExtrinsicResult; - /// Initialize a block with the given header. - fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; - /// Finish the current block. #[renamed("finalise_block", 3)] fn finalize_block() -> ::Header; diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index 9f1599387ba2e..1dce4b86734a2 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -115,8 +115,7 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", - InvalidTransaction::NonMandatory => - "Non-mandatory extrinsic was applied in a mandatory-only block", + InvalidTransaction::NonMandatory => "Non-mandatory extrinsic was applied in a mandatory-only block", } } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index b3cea943e6a8a..e67f49216689c 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -485,6 +485,11 @@ impl_runtime_apis! { log::trace!(target: LOG_TARGET, "execute_block: {block:#?}"); Executive::execute_block(block); } + + fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); + Executive::initialize_block(header) + } } impl sp_api::Metadata for Runtime { @@ -517,11 +522,6 @@ impl_runtime_apis! { Executive::apply_extrinsic(extrinsic) } - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { - log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); - Executive::initialize_block(header) - } - fn finalize_block() -> ::Header { log::trace!(target: LOG_TARGET, "finalize_block"); Executive::finalize_block() diff --git a/utils/frame/try-runtime/cli/src/commands/fast_forward.rs b/utils/frame/try-runtime/cli/src/commands/fast_forward.rs index 85d2b74c59b2e..ea3ae532ca74d 100644 --- a/utils/frame/try-runtime/cli/src/commands/fast_forward.rs +++ b/utils/frame/try-runtime/cli/src/commands/fast_forward.rs @@ -174,8 +174,7 @@ async fn next_empty_block< ); let mut extrinsics = >::new(); - run::(externalities, executor, "BlockBuilder_initialize_block", &header.encode()) - .await?; + run::(externalities, executor, "Core_initialize_block", &header.encode()).await?; if let Some(ref inherent_data) = maybe_inherent_data { extrinsics = dry_run::, Block, _>( From 835941c65168027f241bc487acadd65197c08f59 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Wed, 5 Jul 2023 23:06:12 +0200 Subject: [PATCH 28/41] Fix doc tests Signed-off-by: Oliver Tale-Yazdi --- primitives/api/src/lib.rs | 6 ++++-- primitives/api/test/tests/decl_and_impl.rs | 2 +- primitives/runtime/src/transaction_validity.rs | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 63ad38474b28d..7b2d9e64786a7 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -261,7 +261,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// ```rust /// use sp_version::create_runtime_str; /// # -/// # use sp_runtime::traits::Block as BlockT; +/// # use sp_runtime::{RuntimeExecutiveMode, traits::Block as BlockT}; /// # use sp_test_primitives::Block; /// # /// # /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro @@ -288,7 +288,9 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// # unimplemented!() /// # } /// # fn execute_block(_block: Block) {} -/// # fn initialize_block(_header: &::Header) {} +/// # fn initialize_block(_header: &::Header) -> RuntimeExecutiveMode { +/// # unimplemented!() +/// # } /// # } /// /// impl self::Balance for Runtime { diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index a085ef192bd90..25b7ad81b49fc 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -15,10 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use sp_runtime::traits::Block as BlockT; use sp_api::{ decl_runtime_apis, impl_runtime_apis, mock_impl_runtime_apis, ApiError, ApiExt, RuntimeApiInfo, }; +use sp_runtime::traits::Block as BlockT; use substrate_test_runtime_client::runtime::{Block, Hash}; diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index 1dce4b86734a2..9f1599387ba2e 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -115,7 +115,8 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", - InvalidTransaction::NonMandatory => "Non-mandatory extrinsic was applied in a mandatory-only block", + InvalidTransaction::NonMandatory => + "Non-mandatory extrinsic was applied in a mandatory-only block", } } } From 708ede6bc8c9eec4a0653dee78f33498c4d8e014 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 6 Jul 2023 12:28:07 +0200 Subject: [PATCH 29/41] Fix UI tests Signed-off-by: Oliver Tale-Yazdi --- .../api/test/tests/ui/impl_incorrect_method_signature.rs | 4 ++++ primitives/api/test/tests/ui/impl_missing_version.rs | 4 ++++ primitives/api/test/tests/ui/missing_versioned_method.rs | 4 ++++ .../test/tests/ui/missing_versioned_method_multiple_vers.rs | 4 ++++ .../api/test/tests/ui/positive_cases/custom_where_bound.rs | 4 ++++ primitives/api/test/tests/ui/positive_cases/default_impls.rs | 4 ++++ .../test/tests/ui/type_reference_in_impl_runtime_apis_call.rs | 4 ++++ 7 files changed, 28 insertions(+) diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs index 0ccd79a0a4bb8..014fd37666756 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs @@ -1,3 +1,4 @@ +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real @@ -22,6 +23,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/ui/impl_missing_version.rs b/primitives/api/test/tests/ui/impl_missing_version.rs index 6bc549e86b6b1..17c563f7dc0ba 100644 --- a/primitives/api/test/tests/ui/impl_missing_version.rs +++ b/primitives/api/test/tests/ui/impl_missing_version.rs @@ -1,3 +1,4 @@ +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -27,6 +28,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method.rs b/primitives/api/test/tests/ui/missing_versioned_method.rs index 6f59d514b3ae7..e2ef0beb2da16 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method.rs @@ -1,3 +1,4 @@ +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -26,6 +27,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs index 054718aa26e24..db7d30f08a3a1 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs @@ -1,3 +1,4 @@ +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -29,6 +30,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs index fa96470338040..c2e1672aa202b 100644 --- a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs +++ b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs @@ -1,5 +1,6 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -33,6 +34,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/ui/positive_cases/default_impls.rs b/primitives/api/test/tests/ui/positive_cases/default_impls.rs index 678d49fd18ae9..a42a3db0596e5 100644 --- a/primitives/api/test/tests/ui/positive_cases/default_impls.rs +++ b/primitives/api/test/tests/ui/positive_cases/default_impls.rs @@ -1,3 +1,4 @@ +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -28,6 +29,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs index 14d62dea4071d..064eb3f931b98 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -1,3 +1,4 @@ +use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; use substrate_test_runtime_client::runtime::Block; /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real @@ -24,6 +25,9 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } + fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + unimplemented!() + } } } From b7869da4f788e0916530daacf672275cfa80a353 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 6 Jul 2023 15:30:02 +0200 Subject: [PATCH 30/41] Also version initialize_block Signed-off-by: Oliver Tale-Yazdi --- client/block-builder/src/lib.rs | 27 +++++++++++++------- frame/support/test/tests/runtime_metadata.rs | 2 +- primitives/api/src/lib.rs | 3 +++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 0ba2aa39cf2f4..efbfa58bd3f73 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -175,20 +175,29 @@ where let estimated_header_size = header.encoded_size(); let mut api = api.runtime_api(); + let version = api + .api_version::>(parent_hash)? + .ok_or_else(|| Error::VersionInvalid("BlockBuilderApi".to_string()))?; if record_proof.yes() { api.record_proof(); } - let executive_mode = api.initialize_block_with_context( - parent_hash, - ExecutionContext::BlockConstruction, - &header, - )?; - - let version = api - .api_version::>(parent_hash)? - .ok_or_else(|| Error::VersionInvalid("BlockBuilderApi".to_string()))?; + let executive_mode = if version >= 5 { + api.initialize_block_with_context( + parent_hash, + ExecutionContext::BlockConstruction, + &header, + )? + } else { + #[allow(deprecated)] + api.initialize_block_before_version_5_with_context( + parent_hash, + ExecutionContext::BlockConstruction, + &header, + )?; + RuntimeExecutiveMode::Normal + }; Ok(Self { parent_hash, diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index d9e04bdebda66..64acb0f58b8d8 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -207,7 +207,7 @@ fn runtime_metadata() { ty: meta_type::<&::Header>(), }], output: meta_type::(), - docs: maybe_docs(vec![" Initialize a block with the given header."]), + docs: maybe_docs(vec![" Initialize a block with the given header and return the runtime executive mode."]), }, ], docs: maybe_docs(vec![ diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 7b2d9e64786a7..cb066bf28a4a0 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -725,6 +725,9 @@ decl_runtime_apis! { /// Execute the given block. fn execute_block(block: Block); /// Initialize a block with the given header. + #[changed_in(5)] + fn initialize_block(header: &::Header); + /// Initialize a block with the given header and return the runtime executive mode. #[renamed("initialise_block", 2)] fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; } From 2ce81ebf77bd491ec08db8b3fee37e5d794faecb Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 6 Jul 2023 17:37:10 +0200 Subject: [PATCH 31/41] Cleanup Signed-off-by: Oliver Tale-Yazdi --- client/basic-authorship/src/basic_authorship.rs | 1 - frame/executive/src/lib.rs | 16 ++++++---------- primitives/api/src/lib.rs | 2 +- primitives/runtime/src/lib.rs | 4 ++-- test-utils/runtime/src/lib.rs | 6 ------ 5 files changed, 9 insertions(+), 20 deletions(-) diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 0dec692a3bc87..7c468066a6fc5 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -345,7 +345,6 @@ where let mut block_builder = self.client.new_block_at(self.parent_hash, inherent_digests, PR::ENABLED)?; - // The executive mode does not influence the execution of inherents: self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 8e8a719dd5d3b..24f45c8bf9369 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -318,10 +318,8 @@ impl< } Self::after_inherents(mode); - if mode == RuntimeExecutiveMode::Minimal { - if num_inherents < extrinsics.len() { - return Err(InvalidTransaction::NonMandatory.into()) - } + if mode == RuntimeExecutiveMode::Minimal && extrinsics.len() > num_inherents { + return Err(InvalidTransaction::NonMandatory.into()) } // Apply transactions: for e in extrinsics.iter().skip(num_inherents) { @@ -551,12 +549,10 @@ impl< // Process inherents (if any). Self::apply_extrinsics(extrinsics.iter().take(num_inherents), mode); Self::after_inherents(mode); - if mode == RuntimeExecutiveMode::Minimal { - if num_inherents < extrinsics.len() { - // Note: It would be possible to not explicitly panic here since the state-root - // check should already catch any mismatch, but this makes it easier to debug. - panic!("Only inherents are allowed in 'Minimal' blocks"); - } + if mode == RuntimeExecutiveMode::Minimal && extrinsics.len() > num_inherents { + // Note: It would be possible to not explicitly panic here since the state-root + // check should already catch any mismatch, but this makes it easier to debug. + panic!("Only inherents are allowed in 'Minimal' blocks"); } // Process transactions (if any). Self::apply_extrinsics(extrinsics.iter().skip(num_inherents), mode); diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index cb066bf28a4a0..36ab000e0c0cb 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -726,9 +726,9 @@ decl_runtime_apis! { fn execute_block(block: Block); /// Initialize a block with the given header. #[changed_in(5)] + #[renamed("initialise_block", 2)] fn initialize_block(header: &::Header); /// Initialize a block with the given header and return the runtime executive mode. - #[renamed("initialise_block", 2)] fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index bbd8a7a78f187..fbec3a57c6a16 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -955,14 +955,14 @@ pub enum RuntimeExecutiveMode { /// - Extrinsics with dispatch class `Normal`. /// - `on_idle` hook. Normal, - /// Only _really necessary_ logic is allowed to run. + /// Only _necessary_ logic is allowed to run. /// /// Explicitly forbidden are: /// - Extrinsics with dispatch classes `Normal` and `Operational`. /// - `on_idle` and `poll` hooks. /// /// Explicitly allowed are: - /// - Mandatory inherents and extrinsics (i.e. via OCW). + /// - Mandatory extrinsics (i.e. via OCW). /// - `on_initialize` and `on_finalize` hooks. /// - Storage migrations. /// diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index e67f49216689c..75ce8686b84f0 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -228,14 +228,8 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - (), // no migrations - MockedRuntimeExecutiveMode, >; -parameter_types! { - pub storage MockedRuntimeExecutiveMode: sp_runtime::RuntimeExecutiveMode = Default::default(); -} - #[derive(Copy, Clone, PartialEq, Eq, Encode, Decode, RuntimeDebug, TypeInfo)] pub struct CheckSubstrateCall; From 83bbe6fe9aa7bea1d24728b3718e549233dcd0ab Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jul 2023 18:37:52 +0200 Subject: [PATCH 32/41] Update client/block-builder/src/lib.rs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bastian Köcher --- client/block-builder/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index efbfa58bd3f73..d859862f05600 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -140,7 +140,7 @@ pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { /// The estimated size of the block header. estimated_header_size: usize, /// The executive mode of the block that is currently being built. - pub executive_mode: RuntimeExecutiveMode, + executive_mode: RuntimeExecutiveMode, } impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B> From 66b1091657d6024d5aeecb68b75ab7f61bc7d60a Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jul 2023 19:19:47 +0200 Subject: [PATCH 33/41] Review fixes Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 4 ++-- bin/node/runtime/src/lib.rs | 4 ++-- .../basic-authorship/src/basic_authorship.rs | 6 ++--- client/block-builder/src/lib.rs | 12 ++++------ frame/executive/src/lib.rs | 21 +++++++++--------- frame/executive/src/tests.rs | 22 +++++++++---------- primitives/block-builder/src/lib.rs | 4 ++-- primitives/runtime/src/lib.rs | 6 ++--- .../runtime/src/transaction_validity.rs | 8 +++---- test-utils/runtime/src/lib.rs | 4 ++-- 10 files changed, 43 insertions(+), 48 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index d575dc77e6317..f6c6c60df4dab 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -393,8 +393,8 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents(mode: sp_runtime::RuntimeExecutiveMode) { - Executive::after_inherents(mode) + fn after_inherents() { + Executive::after_inherents() } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 5dd1f2f937b5e..7fa7025867654 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2121,8 +2121,8 @@ impl_runtime_apis! { data.check_extrinsics(&block) } - fn after_inherents(mode: sp_runtime::RuntimeExecutiveMode) { - Executive::after_inherents(mode) + fn after_inherents() { + Executive::after_inherents() } } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 7c468066a6fc5..8c314e77baa08 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -348,11 +348,11 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); - block_builder.after_inherents(block_builder.executive_mode)?; + block_builder.after_inherents()?; let end_reason = match block_builder.executive_mode { - RuntimeExecutiveMode::Normal => + RuntimeExecutiveMode::AllExtrinsics => self.apply_transactions(&mut block_builder, deadline, block_size_limit).await?, - RuntimeExecutiveMode::Minimal => EndProposingReason::TransactionsForbidden, + RuntimeExecutiveMode::OnlyInherents => EndProposingReason::TransactionsForbidden, }; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index d859862f05600..54a0014b2f433 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -140,7 +140,7 @@ pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { /// The estimated size of the block header. estimated_header_size: usize, /// The executive mode of the block that is currently being built. - executive_mode: RuntimeExecutiveMode, + pub executive_mode: RuntimeExecutiveMode, } impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B> @@ -196,7 +196,7 @@ where ExecutionContext::BlockConstruction, &header, )?; - RuntimeExecutiveMode::Normal + RuntimeExecutiveMode::AllExtrinsics }; Ok(Self { @@ -211,14 +211,10 @@ where } /// Called after inherents but before extrinsics have been applied. - pub fn after_inherents(&self, mode: RuntimeExecutiveMode) -> Result<(), Error> { + pub fn after_inherents(&self) -> Result<(), Error> { if self.version >= 7 { self.api - .after_inherents_with_context( - self.parent_hash, - ExecutionContext::BlockConstruction, - mode, - ) + .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) .map_err(Into::into) } else { Ok(()) diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 24f45c8bf9369..529b79844c44c 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -317,9 +317,9 @@ impl< } } - Self::after_inherents(mode); - if mode == RuntimeExecutiveMode::Minimal && extrinsics.len() > num_inherents { - return Err(InvalidTransaction::NonMandatory.into()) + Self::after_inherents(); + if mode == RuntimeExecutiveMode::OnlyInherents && extrinsics.len() > num_inherents { + return Err(InvalidTransaction::NotInherent.into()) } // Apply transactions: for e in extrinsics.iter().skip(num_inherents) { @@ -548,11 +548,11 @@ impl< // Process inherents (if any). Self::apply_extrinsics(extrinsics.iter().take(num_inherents), mode); - Self::after_inherents(mode); - if mode == RuntimeExecutiveMode::Minimal && extrinsics.len() > num_inherents { + Self::after_inherents(); + if mode == RuntimeExecutiveMode::OnlyInherents && extrinsics.len() > num_inherents { // Note: It would be possible to not explicitly panic here since the state-root // check should already catch any mismatch, but this makes it easier to debug. - panic!("Only inherents are allowed in 'Minimal' blocks"); + panic!("Only inherents are allowed in this blocks"); } // Process transactions (if any). Self::apply_extrinsics(extrinsics.iter().skip(num_inherents), mode); @@ -567,7 +567,7 @@ impl< } /// Execute code after inherents but before extrinsic application. - pub fn after_inherents(_mode: RuntimeExecutiveMode) { + pub fn after_inherents() { // TODO run either MBMs or `poll` depending on the mode: // // @@ -666,9 +666,10 @@ impl< if r.is_err() && mandatory { return Err(InvalidTransaction::BadMandatory.into()) } - if mode == RuntimeExecutiveMode::Minimal && !mandatory { - defensive!("Only 'Mandatory' extrinsics should be present in a 'Minimal' block"); - return Err(InvalidTransaction::NonMandatory.into()) + if mode == RuntimeExecutiveMode::OnlyInherents && !mandatory { + // Note: The block builder should never try to do this. + defensive!("Only inherents should be present in this block"); + return Err(InvalidTransaction::NotInherent.into()) } >::note_applied_extrinsic(&r, dispatch_info); diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index 0c24e23f1d135..cd430fca95d1f 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -291,7 +291,7 @@ type Executive = super::Executive< frame_support::parameter_types! { /// Provides the runtime-mode to frame-executive. - pub static MockedMode: RuntimeExecutiveMode = RuntimeExecutiveMode::Normal; + pub static MockedMode: RuntimeExecutiveMode = RuntimeExecutiveMode::AllExtrinsics; } fn extra(nonce: u64, fee: Balance) -> SignedExtra { @@ -984,10 +984,10 @@ fn inherents_ok_while_exts_forbidden_works() { }); } -/// Refuses to import blocks with transactions during MBMs. +/// Refuses to import blocks with transactions during `OnlyInherents` mode. #[test] -#[should_panic = "Only inherents are allowed in 'Minimal' blocks"] -fn extrinsic_while_exts_forbidden_errors() { +#[should_panic = "Only inherents are allowed in this blocks"] +fn transactions_in_only_inherents_block_errors() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); @@ -1007,15 +1007,14 @@ fn extrinsic_while_exts_forbidden_errors() { }); new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to forbid extrinsics: - MockedMode::set(RuntimeExecutiveMode::Minimal); + MockedMode::set(RuntimeExecutiveMode::OnlyInherents); Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } -/// Same as above but imports. +/// Same as above but no error. #[test] -fn extrinsic_while_exts_allowed_works() { +fn transactions_in_normal_block_works() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); @@ -1076,8 +1075,8 @@ fn try_execute_block_works() { /// Same as `extrinsic_while_exts_forbidden_errors` but using the try-runtime function. #[test] #[cfg(feature = "try-runtime")] -#[should_panic = "Non-mandatory extrinsic was applied in a mandatory-only block"] -fn try_execute_ext_forbidden_errors() { +#[should_panic = "Non-inherent extrinsic was supplied in a block that only allows inherent extrinsics"] +fn try_execute_tx_forbidden_errors() { let xt1 = TestXt::new(RuntimeCall::Custom(custom::Call::inherent_call {}), None); let xt2 = TestXt::new(call_transfer(33, 0), sign_extra(1, 0, 0)); @@ -1098,8 +1097,7 @@ fn try_execute_ext_forbidden_errors() { }); new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to forbid extrinsics: - MockedMode::set(RuntimeExecutiveMode::Minimal); + MockedMode::set(RuntimeExecutiveMode::OnlyInherents); Executive::try_execute_block( Block::new(header, vec![xt1, xt2]), true, diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 8d011b360af20..b4ded30416a39 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -20,7 +20,7 @@ #![cfg_attr(not(feature = "std"), no_std)] use sp_inherents::{CheckInherentsResult, InherentData}; -use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. @@ -50,6 +50,6 @@ sp_api::decl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; /// Called after inherents but before extrinsic application. - fn after_inherents(mode: RuntimeExecutiveMode); + fn after_inherents(); } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index fbec3a57c6a16..a1970dabf80aa 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -954,7 +954,7 @@ pub enum RuntimeExecutiveMode { /// For example: /// - Extrinsics with dispatch class `Normal`. /// - `on_idle` hook. - Normal, + AllExtrinsics, /// Only _necessary_ logic is allowed to run. /// /// Explicitly forbidden are: @@ -967,12 +967,12 @@ pub enum RuntimeExecutiveMode { /// - Storage migrations. /// /// Everything in between is to be judged by the runtime. - Minimal, + OnlyInherents, } impl Default for RuntimeExecutiveMode { fn default() -> Self { - Self::Normal + Self::AllExtrinsics } } diff --git a/primitives/runtime/src/transaction_validity.rs b/primitives/runtime/src/transaction_validity.rs index 9f1599387ba2e..a4c146619b042 100644 --- a/primitives/runtime/src/transaction_validity.rs +++ b/primitives/runtime/src/transaction_validity.rs @@ -82,8 +82,8 @@ pub enum InvalidTransaction { MandatoryValidation, /// The sending address is disabled or known to be invalid. BadSigner, - /// Only mandatory logic is allowed but it was attempted to execute non-mandatory logic. - NonMandatory, + /// Only inherents are allowed in this block but a non-inherent was present. + NotInherent, } impl InvalidTransaction { @@ -115,8 +115,8 @@ impl From for &'static str { "Transaction dispatch is mandatory; transactions must not be validated.", InvalidTransaction::Custom(_) => "InvalidTransaction custom error", InvalidTransaction::BadSigner => "Invalid signing address", - InvalidTransaction::NonMandatory => - "Non-mandatory extrinsic was applied in a mandatory-only block", + InvalidTransaction::NotInherent => + "Non-inherent extrinsic was supplied in a block that only allows inherent extrinsics", } } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 75ce8686b84f0..c4f0b9057ad8a 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -529,8 +529,8 @@ impl_runtime_apis! { CheckInherentsResult::new() } - fn after_inherents(mode: sp_runtime::RuntimeExecutiveMode) { - Executive::after_inherents(mode) + fn after_inherents() { + Executive::after_inherents() } } From 1c1f71c97fb85b56f6905dffcd370ab3fb2414dd Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jul 2023 19:43:48 +0200 Subject: [PATCH 34/41] Remove unused dep Signed-off-by: Oliver Tale-Yazdi --- Cargo.lock | 1 - client/transaction-pool/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a900920643504..19cc8cd781a71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10271,7 +10271,6 @@ dependencies = [ "sc-utils", "serde", "sp-api", - "sp-block-builder", "sp-blockchain", "sp-consensus", "sp-core", diff --git a/client/transaction-pool/Cargo.toml b/client/transaction-pool/Cargo.toml index 9ddbb80cf46d3..6f02b1cbad243 100644 --- a/client/transaction-pool/Cargo.toml +++ b/client/transaction-pool/Cargo.toml @@ -27,7 +27,6 @@ sc-client-api = { version = "4.0.0-dev", path = "../api" } sc-transaction-pool-api = { version = "4.0.0-dev", path = "./api" } sc-utils = { version = "4.0.0-dev", path = "../utils" } sp-api = { version = "4.0.0-dev", path = "../../primitives/api" } -sp-block-builder = { version = "4.0.0-dev", path = "../../primitives/block-builder" } sp-blockchain = { version = "4.0.0-dev", path = "../../primitives/blockchain" } sp-core = { version = "21.0.0", path = "../../primitives/core" } sp-runtime = { version = "24.0.0", path = "../../primitives/runtime" } From e9e60ef21f1ba73e76b8e0823644dbcd116d26bf Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 11 Jul 2023 20:13:19 +0200 Subject: [PATCH 35/41] Adapt to set_call_context Signed-off-by: Oliver Tale-Yazdi --- client/block-builder/src/lib.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 2f62ff3e537c4..1351f48418b8e 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -184,20 +184,12 @@ where } api.set_call_context(CallContext::Onchain); - + let executive_mode = if version >= 5 { - api.initialize_block_with_context( - parent_hash, - ExecutionContext::BlockConstruction, - &header, - )? + api.initialize_block(parent_hash, &header)? } else { #[allow(deprecated)] - api.initialize_block_before_version_5_with_context( - parent_hash, - ExecutionContext::BlockConstruction, - &header, - )?; + api.initialize_block_before_version_5(parent_hash, &header)?; RuntimeExecutiveMode::AllExtrinsics }; @@ -215,9 +207,7 @@ where /// Called after inherents but before extrinsics have been applied. pub fn after_inherents(&self) -> Result<(), Error> { if self.version >= 7 { - self.api - .after_inherents_with_context(self.parent_hash, ExecutionContext::BlockConstruction) - .map_err(Into::into) + self.api.after_inherents(self.parent_hash).map_err(Into::into) } else { Ok(()) } From a36bcc6fb1dd2b4dfca7b9dbb9effae345dc98ae Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Thu, 20 Jul 2023 16:29:29 +0200 Subject: [PATCH 36/41] Review fixes and renames Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 2 +- bin/node/runtime/src/lib.rs | 2 +- .../basic-authorship/src/basic_authorship.rs | 6 +-- client/block-builder/src/lib.rs | 6 +-- client/transaction-pool/src/api.rs | 3 +- frame/executive/src/lib.rs | 52 ++++++++++--------- frame/executive/src/tests.rs | 6 +-- frame/support/test/tests/runtime_metadata.rs | 4 +- .../proc-macro/src/mock_impl_runtime_apis.rs | 2 +- primitives/api/src/lib.rs | 8 +-- primitives/api/test/tests/decl_and_impl.rs | 2 +- primitives/api/test/tests/runtime_calls.rs | 24 ++++++++- .../ui/impl_incorrect_method_signature.rs | 4 +- .../api/test/tests/ui/impl_missing_version.rs | 4 +- .../test/tests/ui/missing_versioned_method.rs | 4 +- .../missing_versioned_method_multiple_vers.rs | 4 +- .../ui/positive_cases/custom_where_bound.rs | 4 +- .../tests/ui/positive_cases/default_impls.rs | 4 +- ...ype_reference_in_impl_runtime_apis_call.rs | 4 +- primitives/runtime/src/lib.rs | 8 ++- test-utils/runtime/src/lib.rs | 2 +- 21 files changed, 90 insertions(+), 65 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index f6c6c60df4dab..7c48f7ce71ec7 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -354,7 +354,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index a25ec008b508e..c9ddd313d6543 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2085,7 +2085,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { Executive::initialize_block(header) } } diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 8c314e77baa08..71c8efaa40552 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -39,7 +39,7 @@ use sp_core::traits::SpawnNamed; use sp_inherents::InherentData; use sp_runtime::{ traits::{BlakeTwo256, Block as BlockT, Hash as HashT, Header as HeaderT}, - Digest, Percent, RuntimeExecutiveMode, SaturatedConversion, + Digest, ExtrinsicInclusionMode, Percent, SaturatedConversion, }; use std::{marker::PhantomData, pin::Pin, sync::Arc, time}; @@ -350,9 +350,9 @@ where let block_timer = time::Instant::now(); block_builder.after_inherents()?; let end_reason = match block_builder.executive_mode { - RuntimeExecutiveMode::AllExtrinsics => + ExtrinsicInclusionMode::AllExtrinsics => self.apply_transactions(&mut block_builder, deadline, block_size_limit).await?, - RuntimeExecutiveMode::OnlyInherents => EndProposingReason::TransactionsForbidden, + ExtrinsicInclusionMode::OnlyInherents => EndProposingReason::TransactionsForbidden, }; let (block, storage_changes, proof) = block_builder.build()?.into_inner(); diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 1351f48418b8e..76060c4c152b0 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -36,7 +36,7 @@ use sp_core::traits::CallContext; use sp_runtime::{ legacy, traits::{Block as BlockT, Hash, HashFor, Header as HeaderT, NumberFor, One}, - Digest, RuntimeExecutiveMode, + Digest, ExtrinsicInclusionMode, }; use sc_client_api::backend; @@ -140,7 +140,7 @@ pub struct BlockBuilder<'a, Block: BlockT, A: ProvideRuntimeApi, B> { /// The estimated size of the block header. estimated_header_size: usize, /// The executive mode of the block that is currently being built. - pub executive_mode: RuntimeExecutiveMode, + pub executive_mode: ExtrinsicInclusionMode, } impl<'a, Block, A, B> BlockBuilder<'a, Block, A, B> @@ -190,7 +190,7 @@ where } else { #[allow(deprecated)] api.initialize_block_before_version_5(parent_hash, &header)?; - RuntimeExecutiveMode::AllExtrinsics + ExtrinsicInclusionMode::AllExtrinsics }; Ok(Self { diff --git a/client/transaction-pool/src/api.rs b/client/transaction-pool/src/api.rs index f9d79ee429e6c..be3135d12af54 100644 --- a/client/transaction-pool/src/api.rs +++ b/client/transaction-pool/src/api.rs @@ -255,7 +255,8 @@ where )?; // The old versions require us to call `initialize_block` before. - runtime_api.initialize_block(block_hash, &sp_runtime::traits::Header::new( + #[allow(deprecated)] + runtime_api.initialize_block_before_version_5(block_hash, &sp_runtime::traits::Header::new( block_number + sp_runtime::traits::One::one(), Default::default(), Default::default(), diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 529b79844c44c..f2a88b3afa7f3 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -138,7 +138,7 @@ use sp_runtime::{ ValidateUnsigned, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, RuntimeExecutiveMode, + ApplyExtrinsicResult, ExtrinsicInclusionMode, }; use sp_std::{marker::PhantomData, prelude::*}; @@ -163,6 +163,8 @@ pub type OriginOf = as Dispatchable>::RuntimeOrigin; /// used to call hooks e.g. `on_initialize`. /// - `OnRuntimeUpgrade`: Custom logic that should be called after a runtime upgrade. Modules are /// already called by `AllPalletsWithSystem`. It will be called before all modules will be called. +/// - `ExtrinsicInclusionModeQuery`: Provides the [`ExtrinsicInclusionMode`] with which a block +/// should be executed. Defaults to [`ExtrinsicInclusionMode::default()`]. pub struct Executive< System, Block, @@ -170,7 +172,7 @@ pub struct Executive< UnsignedValidator, AllPalletsWithSystem, OnRuntimeUpgrade = (), - RuntimeExecutiveModeQuery = (), + ExtrinsicInclusionModeQuery = (), >( PhantomData<( System, @@ -179,7 +181,7 @@ pub struct Executive< UnsignedValidator, AllPalletsWithSystem, OnRuntimeUpgrade, - RuntimeExecutiveModeQuery, + ExtrinsicInclusionModeQuery, )>, ); @@ -194,7 +196,7 @@ impl< + OnFinalize + OffchainWorker, COnRuntimeUpgrade: OnRuntimeUpgrade, - RuntimeExecutiveModeQuery: Get, + ExtrinsicInclusionModeQuery: Get, > ExecuteBlock for Executive< System, @@ -203,7 +205,7 @@ impl< UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade, - RuntimeExecutiveModeQuery, + ExtrinsicInclusionModeQuery, > where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, @@ -220,7 +222,7 @@ impl< UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade, - RuntimeExecutiveModeQuery, + ExtrinsicInclusionModeQuery, >::execute_block(block); } } @@ -238,7 +240,7 @@ impl< + OffchainWorker + frame_support::traits::TryState, COnRuntimeUpgrade: OnRuntimeUpgrade, - RuntimeExecutiveModeQuery: Get, + ExtrinsicInclusionModeQuery: Get, > Executive< System, @@ -247,7 +249,7 @@ impl< UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade, - RuntimeExecutiveModeQuery, + ExtrinsicInclusionModeQuery, > where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, @@ -281,9 +283,12 @@ impl< let mode = Self::initialize_block(block.header()); let num_inherents = Self::initial_checks(&block) as usize; - let (header, extrinsics) = block.deconstruct(); + if mode == ExtrinsicInclusionMode::OnlyInherents && extrinsics.len() > num_inherents { + return Err(InvalidTransaction::NotInherent.into()) + } + let try_apply_extrinsic = |uxt: Block::Extrinsic| -> ApplyExtrinsicResult { sp_io::init_tracing(); let encoded = uxt.encode(); @@ -318,9 +323,7 @@ impl< } Self::after_inherents(); - if mode == RuntimeExecutiveMode::OnlyInherents && extrinsics.len() > num_inherents { - return Err(InvalidTransaction::NotInherent.into()) - } + // Apply transactions: for e in extrinsics.iter().skip(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { @@ -429,7 +432,7 @@ impl< + OnFinalize + OffchainWorker, COnRuntimeUpgrade: OnRuntimeUpgrade, - RuntimeExecutiveModeQuery: Get, + ExtrinsicInclusionModeQuery: Get, > Executive< System, @@ -438,7 +441,7 @@ impl< UnsignedValidator, AllPalletsWithSystem, COnRuntimeUpgrade, - RuntimeExecutiveModeQuery, + ExtrinsicInclusionModeQuery, > where Block::Extrinsic: Checkable + Codec, CheckedOf: Applyable + GetDispatchInfo, @@ -453,13 +456,13 @@ impl< } /// Start the execution of a particular block. - pub fn initialize_block(header: &System::Header) -> RuntimeExecutiveMode { + pub fn initialize_block(header: &System::Header) -> ExtrinsicInclusionMode { sp_io::init_tracing(); sp_tracing::enter_span!(sp_tracing::Level::TRACE, "init_block"); let digests = Self::extract_pre_digest(header); Self::initialize_block_impl(header.number(), header.parent_hash(), &digests); - RuntimeExecutiveModeQuery::get() + ExtrinsicInclusionModeQuery::get() } fn extract_pre_digest(header: &System::Header) -> Digest { @@ -546,14 +549,15 @@ impl< let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); - // Process inherents (if any). - Self::apply_extrinsics(extrinsics.iter().take(num_inherents), mode); - Self::after_inherents(); - if mode == RuntimeExecutiveMode::OnlyInherents && extrinsics.len() > num_inherents { + if mode == ExtrinsicInclusionMode::OnlyInherents && extrinsics.len() > num_inherents { // Note: It would be possible to not explicitly panic here since the state-root // check should already catch any mismatch, but this makes it easier to debug. panic!("Only inherents are allowed in this blocks"); } + + // Process inherents (if any). + Self::apply_extrinsics(extrinsics.iter().take(num_inherents), mode); + Self::after_inherents(); // Process transactions (if any). Self::apply_extrinsics(extrinsics.iter().skip(num_inherents), mode); @@ -576,7 +580,7 @@ impl< /// Execute given extrinsics. fn apply_extrinsics<'a>( extrinsics: impl Iterator, - mode: RuntimeExecutiveMode, + mode: ExtrinsicInclusionMode, ) { extrinsics.into_iter().for_each(|e| { if let Err(e) = Self::apply_extrinsic_with_mode(e.clone(), mode) { @@ -631,13 +635,13 @@ impl< /// This doesn't attempt to validate anything regarding the block, but it builds a list of uxt /// hashes. pub fn apply_extrinsic(uxt: Block::Extrinsic) -> ApplyExtrinsicResult { - Self::apply_extrinsic_with_mode(uxt, RuntimeExecutiveModeQuery::get()) + Self::apply_extrinsic_with_mode(uxt, ExtrinsicInclusionModeQuery::get()) } /// Same as `apply_extrinsic` but gets the `mode` directly passed in. pub fn apply_extrinsic_with_mode( uxt: Block::Extrinsic, - mode: RuntimeExecutiveMode, + mode: ExtrinsicInclusionMode, ) -> ApplyExtrinsicResult { sp_io::init_tracing(); let encoded = uxt.encode(); @@ -666,7 +670,7 @@ impl< if r.is_err() && mandatory { return Err(InvalidTransaction::BadMandatory.into()) } - if mode == RuntimeExecutiveMode::OnlyInherents && !mandatory { + if mode == ExtrinsicInclusionMode::OnlyInherents && !mandatory { // Note: The block builder should never try to do this. defensive!("Only inherents should be present in this block"); return Err(InvalidTransaction::NotInherent.into()) diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index cd430fca95d1f..46a149b9442fb 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -291,7 +291,7 @@ type Executive = super::Executive< frame_support::parameter_types! { /// Provides the runtime-mode to frame-executive. - pub static MockedMode: RuntimeExecutiveMode = RuntimeExecutiveMode::AllExtrinsics; + pub static MockedMode: ExtrinsicInclusionMode = ExtrinsicInclusionMode::AllExtrinsics; } fn extra(nonce: u64, fee: Balance) -> SignedExtra { @@ -1007,7 +1007,7 @@ fn transactions_in_only_inherents_block_errors() { }); new_test_ext(1).execute_with(|| { - MockedMode::set(RuntimeExecutiveMode::OnlyInherents); + MockedMode::set(ExtrinsicInclusionMode::OnlyInherents); Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } @@ -1097,7 +1097,7 @@ fn try_execute_tx_forbidden_errors() { }); new_test_ext(1).execute_with(|| { - MockedMode::set(RuntimeExecutiveMode::OnlyInherents); + MockedMode::set(ExtrinsicInclusionMode::OnlyInherents); Executive::try_execute_block( Block::new(header, vec![xt1, xt2]), true, diff --git a/frame/support/test/tests/runtime_metadata.rs b/frame/support/test/tests/runtime_metadata.rs index 64acb0f58b8d8..3e3c5881cac7b 100644 --- a/frame/support/test/tests/runtime_metadata.rs +++ b/frame/support/test/tests/runtime_metadata.rs @@ -107,7 +107,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } @@ -206,7 +206,7 @@ fn runtime_metadata() { name: "header", ty: meta_type::<&::Header>(), }], - output: meta_type::(), + output: meta_type::(), docs: maybe_docs(vec![" Initialize a block with the given header and return the runtime executive mode."]), }, ], diff --git a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs index 52b5d4e4a50ee..9af6548cb9a73 100644 --- a/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs +++ b/primitives/api/proc-macro/src/mock_impl_runtime_apis.rs @@ -160,7 +160,7 @@ fn implement_common_api_traits(block_type: TypePath, self_ty: Type) -> Result::Hash, _: &<#block_type as #crate_::BlockT>::Header, - ) -> std::result::Result<#crate_::RuntimeExecutiveMode, #crate_::ApiError> { + ) -> std::result::Result<#crate_::ExtrinsicInclusionMode, #crate_::ApiError> { unimplemented!("`Core::initialize_block` not implemented for runtime api mocks") } } diff --git a/primitives/api/src/lib.rs b/primitives/api/src/lib.rs index 167d5e3922191..d5e0b34f850e1 100644 --- a/primitives/api/src/lib.rs +++ b/primitives/api/src/lib.rs @@ -100,7 +100,7 @@ pub use sp_runtime::{ generic::BlockId, traits::{Block as BlockT, Hash as HashT, HashFor, Header as HeaderT, NumberFor}, transaction_validity::TransactionValidity, - RuntimeExecutiveMode, RuntimeString, TransactionOutcome, + ExtrinsicInclusionMode, RuntimeString, TransactionOutcome, }; #[doc(hidden)] #[cfg(feature = "std")] @@ -267,7 +267,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// ```rust /// use sp_version::create_runtime_str; /// # -/// # use sp_runtime::{RuntimeExecutiveMode, traits::Block as BlockT}; +/// # use sp_runtime::{ExtrinsicInclusionMode, traits::Block as BlockT}; /// # use sp_test_primitives::Block; /// # /// # /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro @@ -294,7 +294,7 @@ pub use sp_api_proc_macro::decl_runtime_apis; /// # unimplemented!() /// # } /// # fn execute_block(_block: Block) {} -/// # fn initialize_block(_header: &::Header) -> RuntimeExecutiveMode { +/// # fn initialize_block(_header: &::Header) -> ExtrinsicInclusionMode { /// # unimplemented!() /// # } /// # } @@ -752,7 +752,7 @@ decl_runtime_apis! { #[renamed("initialise_block", 2)] fn initialize_block(header: &::Header); /// Initialize a block with the given header and return the runtime executive mode. - fn initialize_block(header: &::Header) -> RuntimeExecutiveMode; + fn initialize_block(header: &::Header) -> ExtrinsicInclusionMode; } /// The `Metadata` api trait that returns metadata for the runtime. diff --git a/primitives/api/test/tests/decl_and_impl.rs b/primitives/api/test/tests/decl_and_impl.rs index 25b7ad81b49fc..49cc66b91f518 100644 --- a/primitives/api/test/tests/decl_and_impl.rs +++ b/primitives/api/test/tests/decl_and_impl.rs @@ -89,7 +89,7 @@ impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> sp_runtime::RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> sp_runtime::ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/runtime_calls.rs b/primitives/api/test/tests/runtime_calls.rs index 92118c16cdddc..156f7e366f599 100644 --- a/primitives/api/test/tests/runtime_calls.rs +++ b/primitives/api/test/tests/runtime_calls.rs @@ -66,7 +66,7 @@ fn initialize_block_works() { let client = TestClientBuilder::new().build(); let runtime_api = client.runtime_api(); let best_hash = client.chain_info().best_hash; - runtime_api + let mode = runtime_api .initialize_block( best_hash, &Header::new( @@ -79,6 +79,28 @@ fn initialize_block_works() { ) .unwrap(); assert_eq!(runtime_api.get_block_number(best_hash).unwrap(), 1); + assert_eq!(mode, sp_api::ExtrinsicInclusionMode::AllExtrinsics); +} + +#[test] +fn initialize_block_before_version_5_works() { + let client = TestClientBuilder::new().build(); + let runtime_api = client.runtime_api(); + let best_hash = client.chain_info().best_hash; + #[allow(deprecated)] + let () = runtime_api + .initialize_block_before_version_5( + best_hash, + &Header::new( + 1, + Default::default(), + Default::default(), + Default::default(), + Default::default(), + ), + ) + .unwrap(); + assert_eq!(runtime_api.get_block_number(best_hash).unwrap(), 1); } #[test] diff --git a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs index 014fd37666756..da28ff3c1543b 100644 --- a/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs +++ b/primitives/api/test/tests/ui/impl_incorrect_method_signature.rs @@ -1,4 +1,4 @@ -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real @@ -23,7 +23,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/impl_missing_version.rs b/primitives/api/test/tests/ui/impl_missing_version.rs index 17c563f7dc0ba..84494000c53b2 100644 --- a/primitives/api/test/tests/ui/impl_missing_version.rs +++ b/primitives/api/test/tests/ui/impl_missing_version.rs @@ -1,4 +1,4 @@ -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -28,7 +28,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method.rs b/primitives/api/test/tests/ui/missing_versioned_method.rs index e2ef0beb2da16..580ec6ff9cfac 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method.rs @@ -1,4 +1,4 @@ -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -27,7 +27,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs index db7d30f08a3a1..4c036008e9737 100644 --- a/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs +++ b/primitives/api/test/tests/ui/missing_versioned_method_multiple_vers.rs @@ -1,4 +1,4 @@ -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -30,7 +30,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs index c2e1672aa202b..304dc897c7a7d 100644 --- a/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs +++ b/primitives/api/test/tests/ui/positive_cases/custom_where_bound.rs @@ -1,6 +1,6 @@ use codec::{Decode, Encode}; use scale_info::TypeInfo; -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -34,7 +34,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/positive_cases/default_impls.rs b/primitives/api/test/tests/ui/positive_cases/default_impls.rs index a42a3db0596e5..5ee8f7d1aa92a 100644 --- a/primitives/api/test/tests/ui/positive_cases/default_impls.rs +++ b/primitives/api/test/tests/ui/positive_cases/default_impls.rs @@ -1,4 +1,4 @@ -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; struct Runtime {} @@ -29,7 +29,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs index 064eb3f931b98..87a5a78a061c1 100644 --- a/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs +++ b/primitives/api/test/tests/ui/type_reference_in_impl_runtime_apis_call.rs @@ -1,4 +1,4 @@ -use sp_runtime::{traits::Block as BlockT, RuntimeExecutiveMode}; +use sp_runtime::{traits::Block as BlockT, ExtrinsicInclusionMode}; use substrate_test_runtime_client::runtime::Block; /// The declaration of the `Runtime` type is done by the `construct_runtime!` macro in a real @@ -25,7 +25,7 @@ sp_api::impl_runtime_apis! { fn execute_block(_: Block) { unimplemented!() } - fn initialize_block(_: &::Header) -> RuntimeExecutiveMode { + fn initialize_block(_: &::Header) -> ExtrinsicInclusionMode { unimplemented!() } } diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index a1970dabf80aa..6c8d526abfc1f 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -944,11 +944,9 @@ impl TransactionOutcome { } } -/// Confines the logic that can be executed in a block. -/// -/// The runtime may refuse to import blocks that violate these requirements. +/// Confines the kind of extrinsics that can be included in a block. #[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] -pub enum RuntimeExecutiveMode { +pub enum ExtrinsicInclusionMode { /// All logic is allowed to run. /// /// For example: @@ -970,7 +968,7 @@ pub enum RuntimeExecutiveMode { OnlyInherents, } -impl Default for RuntimeExecutiveMode { +impl Default for ExtrinsicInclusionMode { fn default() -> Self { Self::AllExtrinsics } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index 744d2178db9d9..daaec03dc5b9d 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -480,7 +480,7 @@ impl_runtime_apis! { Executive::execute_block(block); } - fn initialize_block(header: &::Header) -> sp_runtime::RuntimeExecutiveMode { + fn initialize_block(header: &::Header) -> sp_runtime::ExtrinsicInclusionMode { log::trace!(target: LOG_TARGET, "initialize_block: {header:#?}"); Executive::initialize_block(header) } From da4c138311dd858b7316ef0d4fa4281f324d1c9e Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Sat, 22 Jul 2023 15:42:12 +0200 Subject: [PATCH 37/41] Review Signed-off-by: Oliver Tale-Yazdi --- frame/executive/src/lib.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 4529f3eb76310..9b9d561ecb430 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -286,6 +286,7 @@ impl< let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); + // Check if there are any forbidden non-inherents in the block. if mode == ExtrinsicInclusionMode::OnlyInherents && extrinsics.len() > num_inherents { return Err(InvalidTransaction::NotInherent.into()) } @@ -553,6 +554,7 @@ impl< let num_inherents = Self::initial_checks(&block) as usize; let (header, extrinsics) = block.deconstruct(); + // Check if there are any forbidden non-inherents in the block. if mode == ExtrinsicInclusionMode::OnlyInherents && extrinsics.len() > num_inherents { // Note: It would be possible to not explicitly panic here since the state-root // check should already catch any mismatch, but this makes it easier to debug. @@ -643,7 +645,9 @@ impl< } /// Same as `apply_extrinsic` but gets the `mode` directly passed in. - pub fn apply_extrinsic_with_mode( + /// + /// This can be used for caching purposes where the `mode` is already known. + fn apply_extrinsic_with_mode( uxt: Block::Extrinsic, mode: ExtrinsicInclusionMode, ) -> ApplyExtrinsicResult { From d04928c26e41a676e711fb08f80c8a94a74afc3b Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Sat, 22 Jul 2023 15:48:05 +0200 Subject: [PATCH 38/41] Comment Signed-off-by: Oliver Tale-Yazdi --- primitives/block-builder/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index b4ded30416a39..9ac134ad0d9f0 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -49,7 +49,7 @@ sp_api::decl_runtime_apis! { /// Check that the inherents are valid. The inherent data will vary from chain to chain. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; - /// Called after inherents but before extrinsic application. + /// Called after inherents but before transaction application. fn after_inherents(); } } From 7369e42d5a805557e2a255db196d8157cf329bef Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Tue, 25 Jul 2023 16:46:19 +0200 Subject: [PATCH 39/41] Fix docs Signed-off-by: Oliver Tale-Yazdi --- primitives/runtime/src/lib.rs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/primitives/runtime/src/lib.rs b/primitives/runtime/src/lib.rs index fd9bc2f5d84a8..9b3c8acba116c 100644 --- a/primitives/runtime/src/lib.rs +++ b/primitives/runtime/src/lib.rs @@ -975,24 +975,9 @@ impl TransactionOutcome { /// Confines the kind of extrinsics that can be included in a block. #[derive(Debug, PartialEq, Eq, Clone, Copy, Encode, Decode, TypeInfo)] pub enum ExtrinsicInclusionMode { - /// All logic is allowed to run. - /// - /// For example: - /// - Extrinsics with dispatch class `Normal`. - /// - `on_idle` hook. + /// All extrinsics are allowed to be included in this block. AllExtrinsics, - /// Only _necessary_ logic is allowed to run. - /// - /// Explicitly forbidden are: - /// - Extrinsics with dispatch classes `Normal` and `Operational`. - /// - `on_idle` and `poll` hooks. - /// - /// Explicitly allowed are: - /// - Mandatory extrinsics (i.e. via OCW). - /// - `on_initialize` and `on_finalize` hooks. - /// - Storage migrations. - /// - /// Everything in between is to be judged by the runtime. + /// Inherents are allowed to be included. OnlyInherents, } From 585373a4a61089676b37dd118a9a194af0724a14 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 7 Aug 2023 12:07:39 +0200 Subject: [PATCH 40/41] Remove after_inherents Signed-off-by: Oliver Tale-Yazdi --- bin/node-template/runtime/src/lib.rs | 4 ---- bin/node/runtime/src/lib.rs | 4 ---- client/basic-authorship/src/basic_authorship.rs | 1 - client/block-builder/src/lib.rs | 9 --------- frame/executive/src/lib.rs | 16 +++------------- frame/executive/src/tests.rs | 4 ++-- primitives/block-builder/src/lib.rs | 5 +---- test-utils/runtime/src/lib.rs | 4 ---- 8 files changed, 6 insertions(+), 41 deletions(-) diff --git a/bin/node-template/runtime/src/lib.rs b/bin/node-template/runtime/src/lib.rs index 9405a2c86d94d..ddcc9d97df79e 100644 --- a/bin/node-template/runtime/src/lib.rs +++ b/bin/node-template/runtime/src/lib.rs @@ -386,10 +386,6 @@ impl_runtime_apis! { ) -> sp_inherents::CheckInherentsResult { data.check_extrinsics(&block) } - - fn after_inherents() { - Executive::after_inherents() - } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 17a22dc570477..a252f10df0a56 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -2118,10 +2118,6 @@ impl_runtime_apis! { fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult { data.check_extrinsics(&block) } - - fn after_inherents() { - Executive::after_inherents() - } } impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { diff --git a/client/basic-authorship/src/basic_authorship.rs b/client/basic-authorship/src/basic_authorship.rs index 71c8efaa40552..00b23164119d3 100644 --- a/client/basic-authorship/src/basic_authorship.rs +++ b/client/basic-authorship/src/basic_authorship.rs @@ -348,7 +348,6 @@ where self.apply_inherents(&mut block_builder, inherent_data)?; let block_timer = time::Instant::now(); - block_builder.after_inherents()?; let end_reason = match block_builder.executive_mode { ExtrinsicInclusionMode::AllExtrinsics => self.apply_transactions(&mut block_builder, deadline, block_size_limit).await?, diff --git a/client/block-builder/src/lib.rs b/client/block-builder/src/lib.rs index 76060c4c152b0..369dd14727503 100644 --- a/client/block-builder/src/lib.rs +++ b/client/block-builder/src/lib.rs @@ -204,15 +204,6 @@ where }) } - /// Called after inherents but before extrinsics have been applied. - pub fn after_inherents(&self) -> Result<(), Error> { - if self.version >= 7 { - self.api.after_inherents(self.parent_hash).map_err(Into::into) - } else { - Ok(()) - } - } - /// Push onto the block's list of extrinsics. /// /// This will ensure the extrinsic can be validly executed (by executing it). diff --git a/frame/executive/src/lib.rs b/frame/executive/src/lib.rs index 9b9d561ecb430..c93fe993e15dc 100644 --- a/frame/executive/src/lib.rs +++ b/frame/executive/src/lib.rs @@ -324,8 +324,6 @@ impl< } } - Self::after_inherents(); - // Apply transactions: for e in extrinsics.iter().skip(num_inherents) { if let Err(err) = try_apply_extrinsic(e.clone()) { @@ -340,7 +338,7 @@ impl< // post-extrinsics book-keeping >::note_finished_extrinsics(); - // TODO MBMs will skip this. + // TODO MBMs will run here depending on `ExtrinsicInclusionModeQuery::get()`. Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); @@ -563,12 +561,11 @@ impl< // Process inherents (if any). Self::apply_extrinsics(extrinsics.iter().take(num_inherents), mode); - Self::after_inherents(); // Process transactions (if any). Self::apply_extrinsics(extrinsics.iter().skip(num_inherents), mode); >::note_finished_extrinsics(); - // TODO MBMs will skip this. + // TODO MBMs will run here depending on `ExtrinsicInclusionModeQuery::get()`. Self::on_idle_hook(*header.number()); Self::on_finalize_hook(*header.number()); @@ -576,13 +573,6 @@ impl< } } - /// Execute code after inherents but before extrinsic application. - pub fn after_inherents() { - // TODO run either MBMs or `poll` depending on the mode: - // - // - } - /// Execute given extrinsics. fn apply_extrinsics<'a>( extrinsics: impl Iterator, @@ -605,7 +595,7 @@ impl< >::note_finished_extrinsics(); let block_number = >::block_number(); - // TODO MBMs will conditionally skip this. + // TODO MBMs will run here depending on `ExtrinsicInclusionModeQuery::get()`. Self::on_idle_hook(block_number); Self::on_finalize_hook(block_number); diff --git a/frame/executive/src/tests.rs b/frame/executive/src/tests.rs index cdba7a8c4a85f..6418bdbb3a722 100644 --- a/frame/executive/src/tests.rs +++ b/frame/executive/src/tests.rs @@ -974,7 +974,7 @@ fn inherents_ok_while_exts_forbidden_works() { }); new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to forbid extrinsics: + // Tell `initialize_block` to forbid extrinsics: Executive::execute_block(Block::new(header, vec![xt1])); }); } @@ -1029,7 +1029,7 @@ fn transactions_in_normal_block_works() { }); new_test_ext(1).execute_with(|| { - // Tell `after_inherents` to forbid extrinsics: + // Tell `initialize_block` to forbid extrinsics: Executive::execute_block(Block::new(header, vec![xt1, xt2])); }); } diff --git a/primitives/block-builder/src/lib.rs b/primitives/block-builder/src/lib.rs index 9ac134ad0d9f0..29e04857f463e 100644 --- a/primitives/block-builder/src/lib.rs +++ b/primitives/block-builder/src/lib.rs @@ -24,7 +24,7 @@ use sp_runtime::{traits::Block as BlockT, ApplyExtrinsicResult}; sp_api::decl_runtime_apis! { /// The `BlockBuilder` api trait that provides the required functionality for building a block. - #[api_version(7)] + #[api_version(6)] pub trait BlockBuilder { /// Apply the given extrinsic. /// @@ -48,8 +48,5 @@ sp_api::decl_runtime_apis! { /// Check that the inherents are valid. The inherent data will vary from chain to chain. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult; - - /// Called after inherents but before transaction application. - fn after_inherents(); } } diff --git a/test-utils/runtime/src/lib.rs b/test-utils/runtime/src/lib.rs index ccb736b8fdb0b..c7f2b61b1f04f 100644 --- a/test-utils/runtime/src/lib.rs +++ b/test-utils/runtime/src/lib.rs @@ -525,10 +525,6 @@ impl_runtime_apis! { fn check_inherents(_block: Block, _data: InherentData) -> CheckInherentsResult { CheckInherentsResult::new() } - - fn after_inherents() { - Executive::after_inherents() - } } impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { From 092925223f1f4157b381efb4e20ea6ab33325eb3 Mon Sep 17 00:00:00 2001 From: Oliver Tale-Yazdi Date: Mon, 7 Aug 2023 13:11:00 +0200 Subject: [PATCH 41/41] Fixup Signed-off-by: Oliver Tale-Yazdi --- frame/executive/Cargo.toml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/frame/executive/Cargo.toml b/frame/executive/Cargo.toml index 01229d8ff7d0b..fa466dd2041ea 100644 --- a/frame/executive/Cargo.toml +++ b/frame/executive/Cargo.toml @@ -62,12 +62,3 @@ try-runtime = [ "pallet-balances/try-runtime", "pallet-transaction-payment/try-runtime" ] -try-runtime = [ - "frame-support/try-runtime", - "frame-try-runtime/try-runtime", - "sp-runtime/try-runtime", - "frame-system/try-runtime", - "frame-try-runtime?/try-runtime", - "pallet-balances/try-runtime", - "pallet-transaction-payment/try-runtime" -]