From 179b851ffdcc0e4b1f344cd90f8de83e246db96f Mon Sep 17 00:00:00 2001 From: Yoni <78365039+Yoni-Starkware@users.noreply.github.com> Date: Sun, 5 May 2024 18:30:12 +0300 Subject: [PATCH] feat(execution,concurrency): add ConcurrencyConfig (#1861) --- crates/blockifier/src/blockifier.rs | 1 + crates/blockifier/src/blockifier/block.rs | 3 ++- .../blockifier/src/blockifier/block_test.rs | 5 ++++- crates/blockifier/src/blockifier/config.rs | 11 +++++++++++ .../src/blockifier/stateful_validator.rs | 8 +++++++- .../src/blockifier/transaction_executor.rs | 19 ++++++++++++++++++- .../blockifier/transaction_executor_test.rs | 17 ++++++++++++++--- .../src/py_block_executor.rs | 16 ++++++++++++++-- 8 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 crates/blockifier/src/blockifier/config.rs diff --git a/crates/blockifier/src/blockifier.rs b/crates/blockifier/src/blockifier.rs index e6760888f0..6bd74a63ec 100644 --- a/crates/blockifier/src/blockifier.rs +++ b/crates/blockifier/src/blockifier.rs @@ -1,3 +1,4 @@ pub mod block; +pub mod config; pub mod stateful_validator; pub mod transaction_executor; diff --git a/crates/blockifier/src/blockifier/block.rs b/crates/blockifier/src/blockifier/block.rs index c7bac7fb22..98ab8bf05b 100644 --- a/crates/blockifier/src/blockifier/block.rs +++ b/crates/blockifier/src/blockifier/block.rs @@ -62,6 +62,7 @@ pub fn pre_process_block( block_info: BlockInfo, chain_info: ChainInfo, versioned_constants: VersionedConstants, + concurrency_mode: bool, ) -> StateResult { let should_block_hash_be_provided = block_info.block_number >= BlockNumber(constants::STORED_BLOCK_HASH_BUFFER); @@ -80,7 +81,7 @@ pub fn pre_process_block( return Err(StateError::OldBlockHashNotProvided); } - Ok(BlockContext { block_info, chain_info, versioned_constants, concurrency_mode: false }) + Ok(BlockContext { block_info, chain_info, versioned_constants, concurrency_mode }) } pub struct BlockNumberHashPair { diff --git a/crates/blockifier/src/blockifier/block_test.rs b/crates/blockifier/src/blockifier/block_test.rs index 7a48565af5..bf93491f22 100644 --- a/crates/blockifier/src/blockifier/block_test.rs +++ b/crates/blockifier/src/blockifier/block_test.rs @@ -29,6 +29,7 @@ fn test_pre_process_block() { block_info, ChainInfo::default(), VersionedConstants::default(), + false, ) .unwrap(); @@ -48,7 +49,8 @@ fn test_pre_process_block() { None, block_info, ChainInfo::default(), - VersionedConstants::default() + VersionedConstants::default(), + false, ) .is_ok() ); @@ -61,6 +63,7 @@ fn test_pre_process_block() { block_info, ChainInfo::default(), VersionedConstants::default(), + false, ); assert_eq!( format!( diff --git a/crates/blockifier/src/blockifier/config.rs b/crates/blockifier/src/blockifier/config.rs new file mode 100644 index 0000000000..36e1d74a6f --- /dev/null +++ b/crates/blockifier/src/blockifier/config.rs @@ -0,0 +1,11 @@ +#[derive(Debug, Default, Clone)] +pub struct TransactionExecutorConfig { + pub concurrency_config: ConcurrencyConfig, +} + +#[derive(Debug, Default, Clone)] +pub struct ConcurrencyConfig { + pub enabled: bool, + pub n_workers: usize, + pub chunk_size: usize, +} diff --git a/crates/blockifier/src/blockifier/stateful_validator.rs b/crates/blockifier/src/blockifier/stateful_validator.rs index 69f190b714..d551ed29d0 100644 --- a/crates/blockifier/src/blockifier/stateful_validator.rs +++ b/crates/blockifier/src/blockifier/stateful_validator.rs @@ -3,6 +3,7 @@ use starknet_api::hash::StarkFelt; use starknet_api::transaction::TransactionHash; use thiserror::Error; +use crate::blockifier::config::TransactionExecutorConfig; use crate::blockifier::transaction_executor::{TransactionExecutor, TransactionExecutorError}; use crate::bouncer::BouncerConfig; use crate::context::{BlockContext, TransactionContext}; @@ -48,7 +49,12 @@ impl StatefulValidator { max_nonce_for_validation_skip: Nonce, bouncer_config: BouncerConfig, ) -> Self { - let tx_executor = TransactionExecutor::new(state, block_context, bouncer_config); + let tx_executor = TransactionExecutor::new( + state, + block_context, + bouncer_config, + TransactionExecutorConfig::default(), + ); Self { tx_executor, max_nonce_for_validation_skip } } diff --git a/crates/blockifier/src/blockifier/transaction_executor.rs b/crates/blockifier/src/blockifier/transaction_executor.rs index f1c50d22b3..ca0c9f8a73 100644 --- a/crates/blockifier/src/blockifier/transaction_executor.rs +++ b/crates/blockifier/src/blockifier/transaction_executor.rs @@ -4,6 +4,7 @@ use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use starknet_api::core::ClassHash; use thiserror::Error; +use crate::blockifier::config::TransactionExecutorConfig; use crate::bouncer::{Bouncer, BouncerConfig}; use crate::context::BlockContext; use crate::execution::call_info::CallInfo; @@ -38,6 +39,8 @@ pub type VisitedSegmentsMapping = Vec<(ClassHash, Vec)>; pub struct TransactionExecutor { pub block_context: BlockContext, pub bouncer: Bouncer, + // Note: this config must not affect the execution result (e.g. state diff and traces). + pub config: TransactionExecutorConfig, // State-related fields. pub state: CachedState, @@ -48,11 +51,13 @@ impl TransactionExecutor { state: CachedState, block_context: BlockContext, bouncer_config: BouncerConfig, + config: TransactionExecutorConfig, ) -> Self { log::debug!("Initializing Transaction Executor..."); // Note: the state might not be empty even at this point; it is the creator's // responsibility to tune the bouncer according to pre and post block process. - let tx_executor = Self { block_context, bouncer: Bouncer::new(bouncer_config), state }; + let tx_executor = + Self { block_context, bouncer: Bouncer::new(bouncer_config), config, state }; log::debug!("Initialized Transaction Executor."); tx_executor @@ -95,6 +100,18 @@ impl TransactionExecutor { &mut self, txs: &[Transaction], charge_fee: bool, + ) -> Vec> { + if !self.config.concurrency_config.enabled { + self.execute_chunk_sequentially(txs, charge_fee) + } else { + todo!() + } + } + + pub fn execute_chunk_sequentially( + &mut self, + txs: &[Transaction], + charge_fee: bool, ) -> Vec> { let mut results = Vec::new(); for tx in txs { diff --git a/crates/blockifier/src/blockifier/transaction_executor_test.rs b/crates/blockifier/src/blockifier/transaction_executor_test.rs index af8d446d73..f073b2c64f 100644 --- a/crates/blockifier/src/blockifier/transaction_executor_test.rs +++ b/crates/blockifier/src/blockifier/transaction_executor_test.rs @@ -5,6 +5,7 @@ use starknet_api::hash::StarkFelt; use starknet_api::stark_felt; use starknet_api::transaction::{Fee, TransactionVersion}; +use crate::blockifier::config::TransactionExecutorConfig; use crate::blockifier::transaction_executor::{TransactionExecutor, TransactionExecutorError}; use crate::bouncer::{Bouncer, BouncerConfig, BouncerWeights}; use crate::context::BlockContext; @@ -34,8 +35,12 @@ fn tx_executor_test_body( charge_fee: bool, expected_bouncer_weights: BouncerWeights, ) { - let mut tx_executor = - TransactionExecutor::new(state, block_context, BouncerConfig::create_for_testing()); + let mut tx_executor = TransactionExecutor::new( + state, + block_context, + BouncerConfig::create_for_testing(), + TransactionExecutorConfig::default(), + ); // TODO(Arni, 30/03/2024): Consider adding a test for the transaction execution info. If A test // should not be added, rename the test to `test_bouncer_info`. // TODO(Arni, 30/03/2024): Test all bouncer weights. @@ -258,6 +263,7 @@ fn test_bouncing( }, ..BouncerConfig::default() }, + TransactionExecutorConfig::default(), ); tx_executor.bouncer.set_accumulated_weights(initial_bouncer_weights); @@ -288,7 +294,12 @@ fn test_execute_chunk_bouncing(block_context: BlockContext) { }, ..BouncerConfig::default() }; - let mut tx_executor = TransactionExecutor::new(state, block_context, bouncer_config.clone()); + let mut tx_executor = TransactionExecutor::new( + state, + block_context, + bouncer_config.clone(), + TransactionExecutorConfig::default(), + ); let txs: Vec = [ emit_n_events_tx(1, account_address, contract_address, nonce!(0_u32)), diff --git a/crates/native_blockifier/src/py_block_executor.rs b/crates/native_blockifier/src/py_block_executor.rs index f70af82307..5e82c88005 100644 --- a/crates/native_blockifier/src/py_block_executor.rs +++ b/crates/native_blockifier/src/py_block_executor.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use blockifier::blockifier::block::{ pre_process_block as pre_process_block_blockifier, BlockInfo, BlockNumberHashPair, GasPrices, }; +use blockifier::blockifier::config::TransactionExecutorConfig; use blockifier::blockifier::transaction_executor::{TransactionExecutor, TransactionExecutorError}; use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; @@ -109,6 +110,7 @@ impl TypedTransactionExecutionInfo { #[pyclass] pub struct PyBlockExecutor { pub bouncer_config: BouncerConfig, + pub tx_executor_config: TransactionExecutorConfig, pub general_config: PyGeneralConfig, pub versioned_constants: VersionedConstants, pub tx_executor: Option>, @@ -140,6 +142,7 @@ impl PyBlockExecutor { Self { bouncer_config: bouncer_config.into(), + tx_executor_config: TransactionExecutorConfig::default(), general_config, versioned_constants, tx_executor: None, @@ -165,10 +168,15 @@ impl PyBlockExecutor { &self.general_config, &next_block_info, &self.versioned_constants, + self.tx_executor_config.concurrency_config.enabled, )?; - let tx_executor = - TransactionExecutor::new(state, block_context, self.bouncer_config.clone()); + let tx_executor = TransactionExecutor::new( + state, + block_context, + self.bouncer_config.clone(), + self.tx_executor_config.clone(), + ); self.tx_executor = Some(tx_executor); Ok(()) @@ -377,6 +385,7 @@ impl PyBlockExecutor { ..BouncerWeights::max(true) }, }, + tx_executor_config: TransactionExecutorConfig::default(), storage: Box::new(PapyrusStorage::new_for_testing( path, &general_config.starknet_os_config.chain_id, @@ -409,6 +418,7 @@ impl PyBlockExecutor { use blockifier::state::global_cache::GLOBAL_CONTRACT_CACHE_SIZE_FOR_TEST; Self { bouncer_config: BouncerConfig::max(), + tx_executor_config: TransactionExecutorConfig::default(), storage: Box::new(storage), general_config: PyGeneralConfig::default(), versioned_constants: VersionedConstants::latest_constants().clone(), @@ -518,6 +528,7 @@ fn pre_process_block( general_config: &PyGeneralConfig, block_info: &PyBlockInfo, versioned_constants: &VersionedConstants, + concurrency_mode: bool, ) -> NativeBlockifierResult { let old_block_number_and_hash = old_block_number_and_hash .map(|(block_number, block_hash)| BlockNumberHashPair::new(block_number, block_hash.0)); @@ -540,6 +551,7 @@ fn pre_process_block( block_info, chain_info, versioned_constants.clone(), + concurrency_mode, )?; Ok(block_context)