From 5d0d0695aed0be3193eb4f2ce31d669e5c7eb2f5 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Fri, 10 May 2024 08:58:52 +0500 Subject: [PATCH] move block creation out of fast forward --- Cargo.lock | 1 + core/Cargo.toml | 1 + core/src/commands/fast_forward.rs | 178 +--------------- .../inherents/custom_idps/mod.rs | 0 .../inherents/custom_idps/para_parachain.rs | 0 .../inherents/custom_idps/relay_parachains.rs | 0 .../inherents/custom_idps/timestamp.rs | 0 .../inherents/mod.rs | 0 .../inherents/pre_apply.rs | 0 .../inherents/providers.rs | 2 +- core/src/common/empty_block/mod.rs | 2 + core/src/common/empty_block/production.rs | 199 ++++++++++++++++++ core/src/common/empty_block_creation/mod.rs | 1 - core/src/common/mod.rs | 2 +- 14 files changed, 216 insertions(+), 170 deletions(-) rename core/src/common/{empty_block_creation => empty_block}/inherents/custom_idps/mod.rs (100%) rename core/src/common/{empty_block_creation => empty_block}/inherents/custom_idps/para_parachain.rs (100%) rename core/src/common/{empty_block_creation => empty_block}/inherents/custom_idps/relay_parachains.rs (100%) rename core/src/common/{empty_block_creation => empty_block}/inherents/custom_idps/timestamp.rs (100%) rename core/src/common/{empty_block_creation => empty_block}/inherents/mod.rs (100%) rename core/src/common/{empty_block_creation => empty_block}/inherents/pre_apply.rs (100%) rename core/src/common/{empty_block_creation => empty_block}/inherents/providers.rs (98%) create mode 100644 core/src/common/empty_block/mod.rs create mode 100644 core/src/common/empty_block/production.rs delete mode 100644 core/src/common/empty_block_creation/mod.rs diff --git a/Cargo.lock b/Cargo.lock index c1316eb2b5..79434739a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12623,6 +12623,7 @@ dependencies = [ "cumulus-primitives-core", "cumulus-primitives-parachain-inherent", "frame-remote-externalities", + "frame-support", "frame-try-runtime", "hex", "itertools 0.11.0", diff --git a/core/Cargo.toml b/core/Cargo.toml index d8f2a161ad..be573e9e30 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -30,6 +30,7 @@ zstd = { workspace = true } frame-remote-externalities = { workspace = true } frame-try-runtime = { workspace = true, features=["try-runtime"] } +frame-support = { workspace = true } sc-cli = { workspace = true } sc-executor = { workspace = true } diff --git a/core/src/commands/fast_forward.rs b/core/src/commands/fast_forward.rs index 69748eb5e4..99b980246d 100644 --- a/core/src/commands/fast_forward.rs +++ b/core/src/commands/fast_forward.rs @@ -31,9 +31,12 @@ use sp_state_machine::TestExternalities; use crate::{ common::{ - empty_block_creation::inherents::{ - pre_apply::pre_apply_inherents, - providers::{InherentProvider, ProviderVariant}, + empty_block::{ + inherents::{ + pre_apply::pre_apply_inherents, + providers::{InherentProvider, ProviderVariant}, + }, + production::execute_next_block, }, state::{ build_executor, state_machine_call, state_machine_call_with_proof, RuntimeChecks, State, @@ -74,134 +77,6 @@ pub struct Command { pub state: State, } -/// Call `method` with `data` and return the result. `externalities` will not change. -fn dry_call( - externalities: &TestExternalities>, - executor: &WasmExecutor, - method: &'static str, - data: &[u8], -) -> Result { - let (_, result) = state_machine_call::( - externalities, - executor, - method, - data, - full_extensions(executor.clone()), - )?; - - Ok(::decode(&mut &*result)?) -} - -/// Call `method` with `data` and actually save storage changes to `externalities`. -async fn call( - externalities: &mut TestExternalities>, - executor: &WasmExecutor, - method: &'static str, - data: &[u8], -) -> Result<()> { - let (mut changes, _) = state_machine_call::( - externalities, - executor, - method, - data, - full_extensions(executor.clone()), - )?; - - let storage_changes = - changes.drain_storage_changes(&externalities.backend, externalities.state_version)?; - - externalities.backend.apply_transaction( - storage_changes.transaction_storage_root, - storage_changes.transaction, - ); - - Ok(()) -} - -/// Produces next block containing only inherents. -async fn produce_next_block( - externalities: &mut TestExternalities>, - executor: &WasmExecutor, - parent_header: Block::Header, - chain: ProviderVariant, - previous_block_building_info: Option<(InherentData, Digest)>, -) -> Result<(Block, Option<(InherentData, Digest)>)> -where - Block: BlockT + DeserializeOwned, - Block::Header: DeserializeOwned, - ::Err: Debug, - NumberFor: FromStr, - as FromStr>::Err: Debug, -{ - let (inherent_data_provider, pre_digest) = - >::get_inherent_providers_and_pre_digest( - &chain, - previous_block_building_info, - parent_header.clone(), - externalities, - )?; - - pre_apply_inherents::(externalities); - let inherent_data = inherent_data_provider - .create_inherent_data() - .await - .map_err(|s| sc_cli::Error::Input(s.to_string()))?; - let digest = Digest { logs: pre_digest }; - - let header = Block::Header::new( - *parent_header.number() + One::one(), - Default::default(), - Default::default(), - parent_header.hash(), - digest.clone(), - ); - - call::( - externalities, - executor, - "Core_initialize_block", - &header.encode(), - ) - .await?; - - let extrinsics = dry_call::, Block, _>( - externalities, - executor, - "BlockBuilder_inherent_extrinsics", - &inherent_data.encode(), - )?; - - for xt in &extrinsics { - call::( - externalities, - executor, - "BlockBuilder_apply_extrinsic", - &xt.encode(), - ) - .await?; - } - - let header = dry_call::( - externalities, - executor, - "BlockBuilder_finalize_block", - &[0u8; 0], - )?; - - call::( - externalities, - executor, - "BlockBuilder_finalize_block", - &[0u8; 0], - ) - .await?; - - Ok(( - Block::new(header, extrinsics), - Some((inherent_data, digest)), - )) -} - pub async fn run(shared: SharedParams, command: Command) -> Result<()> where Block: BlockT + DeserializeOwned, @@ -242,50 +117,19 @@ where let mut parent_block_building_info = None; for _ in 1..=command.n_blocks { - // We are saving state before we overwrite it while producing new block. - let backend = inner_ext.as_backend(); - - log::info!( - "Producing new empty block at height {:?}", - *parent_header.number() + One::one() - ); - - let (next_block, new_block_building_info) = produce_next_block::( + let (next_block_building_info, next_header) = execute_next_block::( &mut inner_ext, &executor, - parent_header.clone(), command.provider_variant, parent_block_building_info, - ) - .await?; - - log::info!("Produced a new block: {:?}", next_block.header()); - - // And now we restore previous state. - inner_ext.backend = backend; - - pre_apply_inherents::(&mut inner_ext); - let state_root_check = true; - let signature_check = true; - let payload = ( - next_block.clone(), - state_root_check, - signature_check, + parent_header.clone(), + command.provider_variant, command.try_state.clone(), - ) - .encode(); - call::( - &mut inner_ext, - &executor, - "TryRuntime_execute_block", - &payload, ) .await?; - log::info!("Executed the new block"); - - parent_block_building_info = new_block_building_info; - parent_header = next_block.header().clone(); + parent_block_building_info = Some(next_block_building_info); + parent_header = next_header; } Ok(()) diff --git a/core/src/common/empty_block_creation/inherents/custom_idps/mod.rs b/core/src/common/empty_block/inherents/custom_idps/mod.rs similarity index 100% rename from core/src/common/empty_block_creation/inherents/custom_idps/mod.rs rename to core/src/common/empty_block/inherents/custom_idps/mod.rs diff --git a/core/src/common/empty_block_creation/inherents/custom_idps/para_parachain.rs b/core/src/common/empty_block/inherents/custom_idps/para_parachain.rs similarity index 100% rename from core/src/common/empty_block_creation/inherents/custom_idps/para_parachain.rs rename to core/src/common/empty_block/inherents/custom_idps/para_parachain.rs diff --git a/core/src/common/empty_block_creation/inherents/custom_idps/relay_parachains.rs b/core/src/common/empty_block/inherents/custom_idps/relay_parachains.rs similarity index 100% rename from core/src/common/empty_block_creation/inherents/custom_idps/relay_parachains.rs rename to core/src/common/empty_block/inherents/custom_idps/relay_parachains.rs diff --git a/core/src/common/empty_block_creation/inherents/custom_idps/timestamp.rs b/core/src/common/empty_block/inherents/custom_idps/timestamp.rs similarity index 100% rename from core/src/common/empty_block_creation/inherents/custom_idps/timestamp.rs rename to core/src/common/empty_block/inherents/custom_idps/timestamp.rs diff --git a/core/src/common/empty_block_creation/inherents/mod.rs b/core/src/common/empty_block/inherents/mod.rs similarity index 100% rename from core/src/common/empty_block_creation/inherents/mod.rs rename to core/src/common/empty_block/inherents/mod.rs diff --git a/core/src/common/empty_block_creation/inherents/pre_apply.rs b/core/src/common/empty_block/inherents/pre_apply.rs similarity index 100% rename from core/src/common/empty_block_creation/inherents/pre_apply.rs rename to core/src/common/empty_block/inherents/pre_apply.rs diff --git a/core/src/common/empty_block_creation/inherents/providers.rs b/core/src/common/empty_block/inherents/providers.rs similarity index 98% rename from core/src/common/empty_block_creation/inherents/providers.rs rename to core/src/common/empty_block/inherents/providers.rs index 09e4c786a6..024a20cf32 100644 --- a/core/src/common/empty_block_creation/inherents/providers.rs +++ b/core/src/common/empty_block/inherents/providers.rs @@ -35,7 +35,7 @@ use sp_std::prelude::*; use strum::IntoEnumIterator; use strum_macros::{Display, EnumIter}; -use crate::common::empty_block_creation::inherents::custom_idps; +use crate::common::empty_block::inherents::custom_idps; /// Trait for providing the inherent data and digest items for block construction. pub trait InherentProvider { diff --git a/core/src/common/empty_block/mod.rs b/core/src/common/empty_block/mod.rs new file mode 100644 index 0000000000..70ad158537 --- /dev/null +++ b/core/src/common/empty_block/mod.rs @@ -0,0 +1,2 @@ +pub mod inherents; +pub mod production; diff --git a/core/src/common/empty_block/production.rs b/core/src/common/empty_block/production.rs new file mode 100644 index 0000000000..ec94c7aa98 --- /dev/null +++ b/core/src/common/empty_block/production.rs @@ -0,0 +1,199 @@ +use std::str::FromStr; + +use parity_scale_codec::{Decode, Encode}; +use sc_cli::Result; +use sc_executor::{HostFunctions, WasmExecutor}; +use sp_core::H256; +use sp_inherents::InherentData; +use sp_runtime::{ + traits::{Block as BlockT, HashingFor, Header, NumberFor, One}, + DeserializeOwned, Digest, +}; +use sp_state_machine::TestExternalities; +use sp_std::fmt::Debug; + +use super::inherents::{pre_apply::pre_apply_inherents, providers::InherentProvider}; +use crate::{ + common::{empty_block::inherents::providers::ProviderVariant, state::state_machine_call}, + full_extensions, +}; + +pub async fn execute_next_block( + ext: &mut TestExternalities>, + executor: &WasmExecutor, + chain: ProviderVariant, + previous_block_building_info: Option<(InherentData, Digest)>, + parent_header: Block::Header, + provider_variant: ProviderVariant, + try_state: frame_try_runtime::TryStateSelect, +) -> Result<((InherentData, Digest), Block::Header)> +where + Block: BlockT + DeserializeOwned, + Block::Header: DeserializeOwned, + ::Err: Debug, + NumberFor: FromStr, + as FromStr>::Err: Debug, +{ + // We are saving state before we overwrite it while producing new block. + let backend = ext.as_backend(); + + log::info!( + "Producing new empty block at height {:?}", + *parent_header.number() + One::one() + ); + + let (next_block, new_block_building_info) = produce_next_block::( + ext, + &executor, + parent_header.clone(), + provider_variant, + previous_block_building_info, + ) + .await?; + + log::info!("Produced a new block: {:?}", next_block.header()); + + // And now we restore previous state. + ext.backend = backend; + + pre_apply_inherents::(ext); + let state_root_check = true; + let signature_check = true; + let payload = ( + next_block.clone(), + state_root_check, + signature_check, + try_state, + ) + .encode(); + call::(ext, &executor, "TryRuntime_execute_block", &payload).await?; + + log::info!("Executed the new block"); + + Ok((new_block_building_info, next_block.header().clone())) +} + +/// Produces next block containing only inherents. +pub async fn produce_next_block( + externalities: &mut TestExternalities>, + executor: &WasmExecutor, + parent_header: Block::Header, + chain: ProviderVariant, + previous_block_building_info: Option<(InherentData, Digest)>, +) -> Result<(Block, (InherentData, Digest))> +where + Block: BlockT + DeserializeOwned, + Block::Header: DeserializeOwned, + ::Err: Debug, + NumberFor: FromStr, + as FromStr>::Err: Debug, +{ + let (inherent_data_provider, pre_digest) = + >::get_inherent_providers_and_pre_digest( + &chain, + previous_block_building_info, + parent_header.clone(), + externalities, + )?; + + pre_apply_inherents::(externalities); + let inherent_data = inherent_data_provider + .create_inherent_data() + .await + .map_err(|s| sc_cli::Error::Input(s.to_string()))?; + let digest = Digest { logs: pre_digest }; + + let header = Block::Header::new( + *parent_header.number() + One::one(), + Default::default(), + Default::default(), + parent_header.hash(), + digest.clone(), + ); + + call::( + externalities, + executor, + "Core_initialize_block", + &header.encode(), + ) + .await?; + + let extrinsics = dry_call::, Block, _>( + externalities, + executor, + "BlockBuilder_inherent_extrinsics", + &inherent_data.encode(), + )?; + + for xt in &extrinsics { + call::( + externalities, + executor, + "BlockBuilder_apply_extrinsic", + &xt.encode(), + ) + .await?; + } + + let header = dry_call::( + externalities, + executor, + "BlockBuilder_finalize_block", + &[0u8; 0], + )?; + + call::( + externalities, + executor, + "BlockBuilder_finalize_block", + &[0u8; 0], + ) + .await?; + + Ok((Block::new(header, extrinsics), (inherent_data, digest))) +} + +/// Call `method` with `data` and actually save storage changes to `externalities`. +async fn call( + externalities: &mut TestExternalities>, + executor: &WasmExecutor, + method: &'static str, + data: &[u8], +) -> Result<()> { + let (mut changes, _) = state_machine_call::( + externalities, + executor, + method, + data, + full_extensions(executor.clone()), + )?; + + let storage_changes = + changes.drain_storage_changes(&externalities.backend, externalities.state_version)?; + + externalities.backend.apply_transaction( + storage_changes.transaction_storage_root, + storage_changes.transaction, + ); + + Ok(()) +} + +/// Call `method` with `data` and return the result. `externalities` will not change. +fn dry_call( + externalities: &TestExternalities>, + executor: &WasmExecutor, + method: &'static str, + data: &[u8], +) -> Result { + let (_, result) = state_machine_call::( + externalities, + executor, + method, + data, + full_extensions(executor.clone()), + )?; + + Ok(::decode(&mut &*result)?) +} diff --git a/core/src/common/empty_block_creation/mod.rs b/core/src/common/empty_block_creation/mod.rs deleted file mode 100644 index d4561d921d..0000000000 --- a/core/src/common/empty_block_creation/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod inherents; diff --git a/core/src/common/mod.rs b/core/src/common/mod.rs index 5085ea1846..98bea196ae 100644 --- a/core/src/common/mod.rs +++ b/core/src/common/mod.rs @@ -1,4 +1,4 @@ -pub mod empty_block_creation; +pub mod empty_block; pub mod misc_logging; pub mod parse; pub mod shared_parameters;