diff --git a/core/Cargo.toml b/core/Cargo.toml index be573e9e30..aff77b5cd4 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -13,6 +13,7 @@ targets = ["x86_64-unknown-linux-gnu"] [dependencies] # Crates.io +tokio = { workspace = true } async-trait = { workspace = true } array-bytes = { workspace = true } polkadot-primitives = { workspace = true } @@ -64,7 +65,6 @@ similar-asserts = "1.5.0" assert_cmd = { workspace = true } regex = { workspace = true } tempfile = { workspace = true } -tokio = { workspace = true } sc-service = { workspace = true } substrate-cli-test-utils = { workspace = true, features = ["try-runtime"] } diff --git a/core/src/commands/fast_forward.rs b/core/src/commands/fast_forward.rs index a418bda7db..27132ff65a 100644 --- a/core/src/commands/fast_forward.rs +++ b/core/src/commands/fast_forward.rs @@ -15,11 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{ - fmt::Debug, - str::FromStr, - sync::{Arc, Mutex}, -}; +use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration}; use parity_scale_codec::Encode; use sc_cli::Result; @@ -27,6 +23,7 @@ use sc_executor::sp_wasm_interface::HostFunctions; use serde::de::DeserializeOwned; use sp_core::H256; use sp_runtime::traits::NumberFor; +use tokio::sync::Mutex; use crate::{ common::{ @@ -43,11 +40,9 @@ pub struct Command { #[arg(long)] pub n_blocks: u64, - /// Which inherent provider variant to use. In most cases "smart" should be used, which - /// attempts to support all chains. - #[arg(long, default_value = "smart")] - #[clap(value_enum)] - pub provider_variant: ProviderVariant, + /// The chain blocktime in milliseconds. + #[arg(long, default_value = "6000")] + pub blocktime: u64, /// Which try-state targets to execute when running this command. /// @@ -108,6 +103,7 @@ where let inner_ext = Arc::new(Mutex::new(ext.inner_ext)); let mut parent_header = ext.header.clone(); let mut parent_block_building_info = None; + let provider_variant = ProviderVariant::Smart(Duration::from_millis(command.blocktime)); for _ in 1..=command.n_blocks { let (next_block_building_info, next_header) = mine_block::( @@ -115,7 +111,7 @@ where &executor, parent_block_building_info, parent_header.clone(), - command.provider_variant, + provider_variant, command.try_state.clone(), ) .await?; diff --git a/core/src/common/empty_block/inherents/custom_idps/para_parachain.rs b/core/src/common/empty_block/inherents/custom_idps/para_parachain.rs index 9e442a380c..8f4c7d1ff2 100644 --- a/core/src/common/empty_block/inherents/custom_idps/para_parachain.rs +++ b/core/src/common/empty_block/inherents/custom_idps/para_parachain.rs @@ -18,7 +18,7 @@ //! Inherent data provider for the [cumulus parachin inherents](https://github.com/paritytech/polkadot-sdk/blob/master/cumulus/primitives/parachain-inherent/src/lib.rs) //! for empty block production on top of an existing externalities. -use std::sync::{Arc, Mutex}; +use std::{ops::DerefMut, sync::Arc}; use parity_scale_codec::{Decode, Encode}; use polkadot_primitives::{BlockNumber, HeadData}; @@ -27,6 +27,7 @@ use sp_core::twox_128; use sp_inherents::InherentIdentifier; use sp_runtime::traits::{Block as BlockT, HashingFor, NumberFor}; use sp_state_machine::TestExternalities; +use tokio::sync::Mutex; /// Get the para id if it exists pub fn get_para_id(ext: &mut TestExternalities>) -> Option { @@ -61,7 +62,7 @@ pub struct InherentDataProvider { pub timestamp: sp_timestamp::Timestamp, pub blocktime_millis: u64, pub parent_header: B::Header, - pub ext: Arc>>>, + pub ext_mutex: Arc>>>, } #[async_trait::async_trait] @@ -70,9 +71,10 @@ impl sp_inherents::InherentDataProvider for InherentDataProvider { &self, inherent_data: &mut sp_inherents::InherentData, ) -> Result<(), sp_inherents::Error> { - let maybe_last_relay_chain_block_number = - get_last_relay_chain_block_number::(&mut self.ext.lock().unwrap()); - let maybe_para_id = get_para_id::(&mut self.ext.lock().unwrap()); + let mut ext_guard = self.ext_mutex.lock().await; + let ext = ext_guard.deref_mut(); + let maybe_last_relay_chain_block_number = get_last_relay_chain_block_number::(ext); + let maybe_para_id = get_para_id::(ext); let (last_relay_chain_block_number, para_id) = match (maybe_last_relay_chain_block_number, maybe_para_id) { (Some(last_relay_chain_block_number), Some(para_id)) => { diff --git a/core/src/common/empty_block/inherents/providers.rs b/core/src/common/empty_block/inherents/providers.rs index 7d99b9e284..b51a319018 100644 --- a/core/src/common/empty_block/inherents/providers.rs +++ b/core/src/common/empty_block/inherents/providers.rs @@ -17,12 +17,8 @@ //! Contains providers for inherents required for empty block production. -use std::{ - sync::{Arc, Mutex}, - time::Duration, -}; +use std::{sync::Arc, time::Duration}; -use clap::ValueEnum; use parity_scale_codec::Encode; use sp_consensus_aura::{Slot, SlotDuration, AURA_ENGINE_ID}; use sp_consensus_babe::{ @@ -37,6 +33,7 @@ use sp_runtime::{ use sp_state_machine::TestExternalities; use sp_std::prelude::*; use strum_macros::{Display, EnumIter}; +use tokio::sync::Mutex; use crate::common::empty_block::inherents::custom_idps; @@ -60,12 +57,13 @@ type InherentProviderResult = /// /// Currently only Smart is implemented. New implementations may be added if Smart is not suitable /// for some edge cases. -#[derive(Debug, Clone, clap::Parser, EnumIter, Display, Copy, ValueEnum)] -#[clap(rename_all = "snake_case")] +#[derive(Debug, Clone, EnumIter, Display, Copy)] pub enum ProviderVariant { /// Smart chain varient will automatically adjust provided inherents based on the given /// externalities. - Smart, + /// + /// The blocktime is provided in milliseconds. + Smart(core::time::Duration), } impl InherentProvider for ProviderVariant { @@ -78,9 +76,9 @@ impl InherentProvider for ProviderVariant { ext: Arc>>>, ) -> InherentProviderResult { match *self { - ProviderVariant::Smart => { - >::get_inherent_providers_and_pre_digest(&SmartInherentProvider { - blocktime: Duration::from_secs(6), + ProviderVariant::Smart(blocktime) => { + >::get_inherent_providers_and_pre_digest(&SmartInherentProvider { + blocktime, }, maybe_parent_info, parent_header, ext) } } @@ -108,24 +106,22 @@ impl InherentProvider for SmartInherentProvider { parent_header: B::Header, ext: Arc>>>, ) -> InherentProviderResult { - let blocktime_millis = self.blocktime.as_millis() as u64; - let timestamp_idp = custom_idps::timestamp::InherentDataProvider { - blocktime_millis, + blocktime_millis: self.blocktime.as_millis() as u64, maybe_parent_info, }; let para_parachain_idp = custom_idps::para_parachain::InherentDataProvider:: { - blocktime_millis, + blocktime_millis: self.blocktime.as_millis() as u64, parent_header: parent_header.clone(), timestamp: timestamp_idp.timestamp(), - ext, + ext_mutex: ext, }; let relay_parachain_data_idp = custom_idps::relay_parachains::InherentDataProvider::::new(parent_header); let slot = Slot::from_timestamp( timestamp_idp.timestamp(), - SlotDuration::from_millis(blocktime_millis), + SlotDuration::from_millis(self.blocktime.as_millis() as u64), ); let digest = vec![ DigestItem::PreRuntime( diff --git a/core/src/common/empty_block/production.rs b/core/src/common/empty_block/production.rs index 9fb7346737..9f24fd98ce 100644 --- a/core/src/common/empty_block/production.rs +++ b/core/src/common/empty_block/production.rs @@ -1,8 +1,4 @@ -use std::{ - ops::DerefMut, - str::FromStr, - sync::{Arc, Mutex}, -}; +use std::{ops::DerefMut, str::FromStr, sync::Arc}; use parity_scale_codec::{Decode, Encode}; use sc_cli::Result; @@ -15,6 +11,7 @@ use sp_runtime::{ }; use sp_state_machine::TestExternalities; use sp_std::fmt::Debug; +use tokio::sync::Mutex; use super::inherents::{pre_apply::pre_apply_inherents, providers::InherentProvider}; use crate::{ @@ -23,7 +20,7 @@ use crate::{ }; pub async fn mine_block( - ext: Arc>>>, + ext_mutex: Arc>>>, executor: &WasmExecutor, previous_block_building_info: Option<(InherentData, Digest)>, parent_header: Block::Header, @@ -38,7 +35,10 @@ where as FromStr>::Err: Debug, { // We are saving state before we overwrite it while producing new block. - let backend = ext.lock().unwrap().deref_mut().as_backend(); + let mut ext_guard = ext_mutex.lock().await; + let ext = ext_guard.deref_mut(); + let backend = ext.as_backend(); + drop(ext_guard); log::info!( "Producing new empty block at height {:?}", @@ -46,7 +46,7 @@ where ); let (next_block, new_block_building_info) = produce_next_block::( - ext.clone(), + ext_mutex.clone(), executor, parent_header.clone(), provider_variant, @@ -59,10 +59,13 @@ where array_bytes::bytes2hex("0x", next_block.header().hash()) ); + let mut ext_guard = ext_mutex.lock().await; + let ext = ext_guard.deref_mut(); + // And now we restore previous state. - ext.lock().unwrap().deref_mut().backend = backend; + ext.backend = backend; - pre_apply_inherents::(ext.lock().unwrap().deref_mut()); + pre_apply_inherents::(ext); let state_root_check = true; let signature_check = true; let payload = ( @@ -72,13 +75,7 @@ where try_state, ) .encode(); - call::( - ext.lock().unwrap().deref_mut(), - executor, - "TryRuntime_execute_block", - &payload, - ) - .await?; + call::(ext, executor, "TryRuntime_execute_block", &payload).await?; log::info!("Executed the new block"); @@ -87,7 +84,7 @@ where /// Produces next block containing only inherents. pub async fn produce_next_block( - externalities: Arc>>>, + ext_mutex: Arc>>>, executor: &WasmExecutor, parent_header: Block::Header, chain: ProviderVariant, @@ -105,10 +102,14 @@ where &chain, previous_block_building_info, parent_header.clone(), - externalities.clone(), + ext_mutex.clone(), )?; - pre_apply_inherents::(externalities.clone().lock().unwrap().deref_mut()); + let mut ext_guard = ext_mutex.lock().await; + let ext = ext_guard.deref_mut(); + + pre_apply_inherents::(ext); + drop(ext_guard); let inherent_data = inherent_data_provider .create_inherent_data() .await @@ -123,45 +124,32 @@ where digest.clone(), ); - call::( - externalities.lock().unwrap().deref_mut(), - executor, - "Core_initialize_block", - &header.encode(), - ) - .await?; + let mut ext_guard = ext_mutex.lock().await; + let ext = ext_guard.deref_mut(); + log::info!("d"); + call::(ext, executor, "Core_initialize_block", &header.encode()).await?; let extrinsics = dry_call::, Block, _>( - externalities.lock().unwrap().deref_mut(), + ext, executor, "BlockBuilder_inherent_extrinsics", &inherent_data.encode(), )?; for xt in &extrinsics { - call::( - externalities.lock().unwrap().deref_mut(), - executor, - "BlockBuilder_apply_extrinsic", - &xt.encode(), - ) - .await?; + call::(ext, executor, "BlockBuilder_apply_extrinsic", &xt.encode()).await?; } let header = dry_call::( - externalities.lock().unwrap().deref_mut(), + ext, executor, "BlockBuilder_finalize_block", &[0u8; 0], )?; - call::( - externalities.lock().unwrap().deref_mut(), - executor, - "BlockBuilder_finalize_block", - &[0u8; 0], - ) - .await?; + call::(ext, executor, "BlockBuilder_finalize_block", &[0u8; 0]).await?; + + drop(ext_guard); Ok((Block::new(header, extrinsics), (inherent_data, digest))) }