diff --git a/crates/blockifier/src/blockifier/transaction_executor_test.rs b/crates/blockifier/src/blockifier/transaction_executor_test.rs index 0816316998..377fb47f9f 100644 --- a/crates/blockifier/src/blockifier/transaction_executor_test.rs +++ b/crates/blockifier/src/blockifier/transaction_executor_test.rs @@ -30,7 +30,7 @@ use crate::test_utils::{ BALANCE, DEFAULT_STRK_L1_GAS_PRICE, }; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use crate::transaction::errors::TransactionExecutionError; use crate::transaction::test_utils::{ block_context, @@ -131,7 +131,8 @@ fn test_declare( }, calculate_class_info_for_testing(declared_contract.get_class()), ); - let tx = AccountTransaction { tx: declare_tx, only_query: false }.into(); + let execution_flags = ExecutionFlags::default(); + let tx = AccountTransaction { tx: declare_tx, execution_flags }.into(); tx_executor_test_body(state, block_context, tx, expected_bouncer_weights); } @@ -152,7 +153,7 @@ fn test_deploy_account( }, &mut NonceManager::default(), ); - let tx = AccountTransaction { tx: deploy_account_tx, only_query: false }.into(); + let tx = AccountTransaction { tx: deploy_account_tx, execution_flags: ExecutionFlags::default() }.into(); let expected_bouncer_weights = BouncerWeights { state_diff_size: 3, message_segment_length: 0, diff --git a/crates/blockifier/src/concurrency/versioned_state_test.rs b/crates/blockifier/src/concurrency/versioned_state_test.rs index 48a0a95065..c83d19762a 100644 --- a/crates/blockifier/src/concurrency/versioned_state_test.rs +++ b/crates/blockifier/src/concurrency/versioned_state_test.rs @@ -44,10 +44,10 @@ use crate::test_utils::deploy_account::deploy_account_tx; use crate::test_utils::dict_state_reader::DictStateReader; use crate::test_utils::initial_test_state::test_state; use crate::test_utils::{CairoVersion, BALANCE, DEFAULT_STRK_L1_GAS_PRICE}; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use crate::transaction::objects::HasRelatedFeeType; use crate::transaction::test_utils::{default_all_resource_bounds, l1_resource_bounds}; -use crate::transaction::transactions::ExecutableTransaction; +use crate::transaction::transactions::{enforce_fee, ExecutableTransaction}; #[fixture] pub fn safe_versioned_state( @@ -236,8 +236,9 @@ fn test_run_parallel_txs(default_all_resource_bounds: ValidResourceBounds) { }, &mut NonceManager::default(), ); - let deploy_account_tx_1 = AccountTransaction { tx, only_query: false }; - let enforce_fee = deploy_account_tx_1.enforce_fee(); + let enforce_fee = enforce_fee(&tx, false); + let execution_flags = ExecutionFlags { charge_fee: enforce_fee, ..ExecutionFlags::default() }; + let deploy_account_tx_1 = AccountTransaction { tx, execution_flags: execution_flags.clone() }; let class_hash = grindy_account.get_class_hash(); let ctor_storage_arg = felt!(1_u8); @@ -251,8 +252,9 @@ fn test_run_parallel_txs(default_all_resource_bounds: ValidResourceBounds) { let nonce_manager = &mut NonceManager::default(); let delpoy_account_tx_2 = AccountTransaction { tx: deploy_account_tx(deploy_tx_args, nonce_manager), - only_query: false, + execution_flags, }; + let account_address = delpoy_account_tx_2.sender_address(); let tx_context = block_context.to_tx_context(&delpoy_account_tx_2); let fee_type = tx_context.tx_info.fee_type(); diff --git a/crates/blockifier/src/concurrency/worker_logic_test.rs b/crates/blockifier/src/concurrency/worker_logic_test.rs index 4370e43d17..ee64bb8210 100644 --- a/crates/blockifier/src/concurrency/worker_logic_test.rs +++ b/crates/blockifier/src/concurrency/worker_logic_test.rs @@ -32,7 +32,7 @@ use crate::test_utils::{ BALANCE, TEST_ERC20_CONTRACT_ADDRESS2, }; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use crate::transaction::objects::HasRelatedFeeType; use crate::transaction::test_utils::{ account_invoke_tx, @@ -561,7 +561,8 @@ fn test_deploy_before_declare( }, test_class_info.clone(), ); - let declare_tx = AccountTransaction { tx, only_query: false }; + let execution_flags = ExecutionFlags::default(); + let declare_tx = AccountTransaction { tx, execution_flags }; // Deploy test contract. let invoke_tx = account_invoke_tx(invoke_tx_args! { diff --git a/crates/blockifier/src/test_utils/transfers_generator.rs b/crates/blockifier/src/test_utils/transfers_generator.rs index 213215ca10..6833e78a20 100644 --- a/crates/blockifier/src/test_utils/transfers_generator.rs +++ b/crates/blockifier/src/test_utils/transfers_generator.rs @@ -18,9 +18,9 @@ use crate::test_utils::dict_state_reader::DictStateReader; use crate::test_utils::initial_test_state::test_state; use crate::test_utils::invoke::invoke_tx; use crate::test_utils::{CairoVersion, BALANCE, MAX_FEE}; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use crate::transaction::transaction_execution::Transaction; - +use crate::transaction::transactions::enforce_fee; const N_ACCOUNTS: u16 = 10000; const N_TXS: usize = 1000; const RANDOMIZATION_SEED: u64 = 0; @@ -145,7 +145,13 @@ impl TransfersGenerator { self.sender_index = (self.sender_index + 1) % self.account_addresses.len(); let tx = self.generate_transfer(sender_address, recipient_address); - let account_tx = AccountTransaction { tx, only_query: false }; + let only_query = false; + let execution_flags = ExecutionFlags { + charge_fee: enforce_fee(&tx, only_query), + only_query, + ..ExecutionFlags::default() + }; + let account_tx = AccountTransaction { tx, execution_flags }; txs.push(Transaction::Account(account_tx)); } let results = self.executor.execute_txs(&txs); diff --git a/crates/blockifier/src/transaction/account_transaction.rs b/crates/blockifier/src/transaction/account_transaction.rs index 3d87f93c85..a0151dbdc3 100644 --- a/crates/blockifier/src/transaction/account_transaction.rs +++ b/crates/blockifier/src/transaction/account_transaction.rs @@ -61,7 +61,7 @@ use crate::transaction::transaction_types::TransactionType; use crate::transaction::transactions::{ Executable, ExecutableTransaction, - ExecutionFlags, + ExecutionFlags as TransactionExecutionFlags, ValidatableTransaction, }; @@ -77,11 +77,24 @@ mod flavors_test; #[path = "post_execution_test.rs"] mod post_execution_test; +#[derive(Clone, Debug, derive_more::From)] +pub struct ExecutionFlags { + pub only_query: bool, + pub charge_fee: bool, + pub validate: bool, +} + +impl Default for ExecutionFlags { + fn default() -> Self { + Self { only_query: false, charge_fee: true, validate: true } + } +} + /// Represents a paid Starknet transaction. #[derive(Clone, Debug, derive_more::From)] pub struct AccountTransaction { pub tx: Transaction, - pub only_query: bool, + pub execution_flags: ExecutionFlags, } // TODO(AvivG): create additional macro that returns a reference. macro_rules! implement_tx_getter_calls { @@ -708,7 +721,7 @@ impl ExecutableTransaction for AccountTransaction { &self, state: &mut TransactionalState<'_, U>, block_context: &BlockContext, - execution_flags: ExecutionFlags, + execution_flags: TransactionExecutionFlags, ) -> TransactionExecutionResult { let tx_context = Arc::new(block_context.to_tx_context(self)); self.verify_tx_version(tx_context.tx_info.version())?; @@ -768,7 +781,7 @@ impl ExecutableTransaction for AccountTransaction { impl TransactionInfoCreator for AccountTransaction { fn create_tx_info(&self) -> TransactionInfo { - self.tx.create_tx_info(self.only_query) + self.tx.create_tx_info(self.execution_flags.only_query) } } diff --git a/crates/blockifier/src/transaction/account_transactions_test.rs b/crates/blockifier/src/transaction/account_transactions_test.rs index a016105508..14380cff44 100644 --- a/crates/blockifier/src/transaction/account_transactions_test.rs +++ b/crates/blockifier/src/transaction/account_transactions_test.rs @@ -84,7 +84,10 @@ use crate::test_utils::{ DEFAULT_STRK_L2_GAS_PRICE, MAX_FEE, }; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{ + AccountTransaction, + ExecutionFlags as AccountExecutionFlags, +}; use crate::transaction::objects::{HasRelatedFeeType, TransactionInfoCreator}; use crate::transaction::test_utils::{ account_invoke_tx, @@ -105,7 +108,7 @@ use crate::transaction::test_utils::{ INVALID, }; use crate::transaction::transaction_types::TransactionType; -use crate::transaction::transactions::{ExecutableTransaction, ExecutionFlags}; +use crate::transaction::transactions::{enforce_fee, ExecutableTransaction, ExecutionFlags}; use crate::utils::u64_from_usize; #[rstest] @@ -213,7 +216,11 @@ fn test_fee_enforcement( }, &mut NonceManager::default(), ); - let deploy_account_tx = AccountTransaction { tx, only_query: false }; + let only_query = false; + let charge_fee = enforce_fee(&tx, only_query); + let execution_flags = + AccountExecutionFlags { only_query, charge_fee, ..AccountExecutionFlags::default() }; + let deploy_account_tx = AccountTransaction { tx, execution_flags }; let enforce_fee = deploy_account_tx.enforce_fee(); assert_ne!(zero_bounds, enforce_fee); @@ -462,7 +469,8 @@ fn test_max_fee_limit_validate( }, class_info, ); - let account_tx = AccountTransaction { tx, only_query: false }; + let execution_flags = AccountExecutionFlags::default(); + let account_tx = AccountTransaction { tx, execution_flags }; account_tx.execute(&mut state, &block_context, true, true).unwrap(); // Deploy grindy account with a lot of grind in the constructor. @@ -785,7 +793,7 @@ fn test_fail_declare(block_context: BlockContext, max_fee: Fee) { }; let declare_account_tx = AccountTransaction { tx: ApiExecutableTransaction::Declare(executable_declare), - only_query: false, + execution_flags: AccountExecutionFlags::default(), }; // Fail execution, assert nonce and balance are unchanged. diff --git a/crates/blockifier/src/transaction/test_utils.rs b/crates/blockifier/src/transaction/test_utils.rs index 07ff2ba797..7f0c84c7a1 100644 --- a/crates/blockifier/src/transaction/test_utils.rs +++ b/crates/blockifier/src/transaction/test_utils.rs @@ -21,6 +21,7 @@ use starknet_api::{calldata, declare_tx_args, deploy_account_tx_args, felt, invo use starknet_types_core::felt::Felt; use strum::IntoEnumIterator; +use super::account_transaction::ExecutionFlags; use crate::context::{BlockContext, ChainInfo}; use crate::state::cached_state::CachedState; use crate::state::state_api::State; @@ -115,7 +116,7 @@ pub fn deploy_and_fund_account( // Deploy an account contract. let deploy_account_tx = AccountTransaction { tx: deploy_account_tx(deploy_tx_args, nonce_manager), - only_query: false, + execution_flags: ExecutionFlags::default(), }; let account_address = deploy_account_tx.sender_address(); @@ -165,6 +166,9 @@ pub struct FaultyAccountTxCreatorArgs { pub validate_constructor: bool, // Should be used with tx_type Declare. pub declared_contract: Option, + pub validate: bool, + pub only_query: bool, + pub charge_fee: bool, } impl Default for FaultyAccountTxCreatorArgs { @@ -181,6 +185,9 @@ impl Default for FaultyAccountTxCreatorArgs { max_fee: Fee::default(), resource_bounds: ValidResourceBounds::create_for_testing_no_fee_enforcement(), declared_contract: None, + validate: true, + only_query: false, + charge_fee: true, } } } @@ -217,6 +224,9 @@ pub fn create_account_tx_for_validate_test( max_fee, resource_bounds, declared_contract, + validate, + only_query, + charge_fee, } = faulty_account_tx_creator_args; // The first felt of the signature is used to set the scenario. If the scenario is @@ -226,7 +236,7 @@ pub fn create_account_tx_for_validate_test( signature_vector.extend(additional_data); } let signature = TransactionSignature(signature_vector); - + let execution_flags = ExecutionFlags { validate, charge_fee, only_query }; match tx_type { TransactionType::Declare => { let declared_contract = match declared_contract { @@ -251,7 +261,7 @@ pub fn create_account_tx_for_validate_test( }, class_info, ); - AccountTransaction { tx, only_query: false } + AccountTransaction { tx, execution_flags } } TransactionType::DeployAccount => { // We do not use the sender address here because the transaction generates the actual @@ -272,7 +282,7 @@ pub fn create_account_tx_for_validate_test( }, nonce_manager, ); - AccountTransaction { tx, only_query: false } + AccountTransaction { tx, execution_flags } } TransactionType::InvokeFunction => { let execute_calldata = create_calldata(sender_address, "foo", &[]); @@ -285,7 +295,7 @@ pub fn create_account_tx_for_validate_test( version: tx_version, nonce: nonce_manager.next(sender_address), }); - AccountTransaction { tx, only_query: false } + AccountTransaction { tx, execution_flags } } _ => panic!("{tx_type:?} is not an account transaction."), } @@ -294,7 +304,8 @@ pub fn create_account_tx_for_validate_test( // TODO(AvivG): Consider removing this function. pub fn account_invoke_tx(invoke_args: InvokeTxArgs) -> AccountTransaction { let only_query = invoke_args.only_query; - AccountTransaction { tx: invoke_tx(invoke_args), only_query } + let execution_flags = ExecutionFlags { only_query, ..ExecutionFlags::default() }; + AccountTransaction { tx: invoke_tx(invoke_args), execution_flags } } pub fn run_invoke_tx( diff --git a/crates/blockifier/src/transaction/transaction_execution.rs b/crates/blockifier/src/transaction/transaction_execution.rs index d305e0bdb8..103db62607 100644 --- a/crates/blockifier/src/transaction/transaction_execution.rs +++ b/crates/blockifier/src/transaction/transaction_execution.rs @@ -19,7 +19,10 @@ use crate::execution::entry_point::EntryPointExecutionContext; use crate::fee::receipt::TransactionReceipt; use crate::state::cached_state::TransactionalState; use crate::state::state_api::UpdatableState; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{ + AccountTransaction, + ExecutionFlags as AccountExecutionFlags, +}; use crate::transaction::errors::TransactionFeeError; use crate::transaction::objects::{ TransactionExecutionInfo, @@ -40,7 +43,10 @@ impl From for Transaction { fn from(value: starknet_api::executable_transaction::Transaction) -> Self { match value { starknet_api::executable_transaction::Transaction::Account(tx) => { - Transaction::Account(AccountTransaction { tx, only_query: false }) + Transaction::Account(AccountTransaction { + tx, + execution_flags: AccountExecutionFlags::default(), + }) } starknet_api::executable_transaction::Transaction::L1Handler(tx) => { Transaction::L1Handler(tx) @@ -119,7 +125,15 @@ impl Transaction { } _ => unimplemented!(), }; - Ok(AccountTransaction { tx: executable_tx, only_query }.into()) + Ok(AccountTransaction { + tx: executable_tx, + execution_flags: AccountExecutionFlags { + only_query, + charge_fee: false, + validate: false, + }, + } + .into()) } } diff --git a/crates/blockifier/src/transaction/transactions_test.rs b/crates/blockifier/src/transaction/transactions_test.rs index a5d8511b2a..649176a62f 100644 --- a/crates/blockifier/src/transaction/transactions_test.rs +++ b/crates/blockifier/src/transaction/transactions_test.rs @@ -116,7 +116,7 @@ use crate::test_utils::{ MAX_FEE, TEST_SEQUENCER_ADDRESS, }; -use crate::transaction::account_transaction::AccountTransaction; +use crate::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use crate::transaction::errors::{ TransactionExecutionError, TransactionFeeError, @@ -454,7 +454,8 @@ fn test_invoke_tx( calldata: Calldata(Arc::clone(&calldata.0)), resource_bounds, }); - let invoke_tx = AccountTransaction { tx, only_query: false }; + let execution_flags = ExecutionFlags::default(); + let invoke_tx = AccountTransaction { tx, execution_flags }; // Extract invoke transaction fields for testing, as it is consumed when creating an account // transaction. @@ -976,7 +977,7 @@ fn test_max_fee_exceeds_balance( }, &mut NonceManager::default(), ), - only_query: false, + execution_flags: ExecutionFlags::default(), }; assert_resource_bounds_exceed_balance_failure(state, block_context, invalid_tx); @@ -1011,7 +1012,7 @@ fn test_max_fee_exceeds_balance( }, class_info, ), - only_query: false, + execution_flags: ExecutionFlags::default(), }; assert_resource_bounds_exceed_balance_failure(state, block_context, invalid_tx); }; @@ -1527,7 +1528,7 @@ fn test_declare_tx( }, class_info.clone(), ); - let account_tx = AccountTransaction { tx, only_query: false }; + let account_tx = AccountTransaction { tx, execution_flags: ExecutionFlags::default() }; // Check state before transaction application. assert_matches!( @@ -1649,7 +1650,7 @@ fn test_declare_tx( }, class_info.clone(), ); - let account_tx2 = AccountTransaction { tx: tx2, only_query: false }; + let account_tx2 = AccountTransaction { tx: tx2, execution_flags: ExecutionFlags::default() }; let result = account_tx2.execute(state, block_context, true, true); assert_matches!( result.unwrap_err(), @@ -1684,7 +1685,10 @@ fn test_declare_tx_v0(default_l1_resource_bounds: ValidResourceBounds) { }, class_info.clone(), ); - let account_tx = AccountTransaction { tx, only_query: false }; + let account_tx = AccountTransaction { + tx, + execution_flags: ExecutionFlags { charge_fee: false, ..ExecutionFlags::default() }, + }; let actual_execution_info = account_tx.execute(state, block_context, false, true).unwrap(); // fee not charged for declare v0. @@ -1713,7 +1717,7 @@ fn test_deploy_account_tx( }, &mut nonce_manager, ), - only_query: false, + execution_flags: ExecutionFlags::default(), }; // Extract deploy account transaction fields for testing, as it is consumed when creating an @@ -1873,7 +1877,7 @@ fn test_deploy_account_tx( }, &mut nonce_manager, ), - only_query: false, + execution_flags: ExecutionFlags::default(), }; let error = deploy_account.execute(state, block_context, true, true).unwrap_err(); assert_matches!( @@ -1906,7 +1910,7 @@ fn test_fail_deploy_account_undeclared_class_hash( }, &mut nonce_manager, ), - only_query: false, + execution_flags: ExecutionFlags::default(), }; let tx_context = block_context.to_tx_context(&deploy_account); let fee_type = tx_context.tx_info.fee_type(); @@ -2253,7 +2257,8 @@ fn test_only_query_flag( sender_address, only_query, }); - let invoke_tx = AccountTransaction { tx, only_query }; + let execution_flags = ExecutionFlags { only_query, ..Default::default() }; + let invoke_tx = AccountTransaction { tx, execution_flags }; let tx_execution_info = invoke_tx.execute(state, block_context, true, true).unwrap(); assert_eq!(tx_execution_info.revert_error, None); diff --git a/crates/native_blockifier/src/py_transaction.rs b/crates/native_blockifier/src/py_transaction.rs index 65b89e81a1..7843f22a2f 100644 --- a/crates/native_blockifier/src/py_transaction.rs +++ b/crates/native_blockifier/src/py_transaction.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use blockifier::transaction::account_transaction::AccountTransaction; +use blockifier::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use blockifier::transaction::transaction_execution::Transaction; use blockifier::transaction::transaction_types::TransactionType; use pyo3::exceptions::PyValueError; @@ -142,15 +142,15 @@ pub fn py_tx( let non_optional_py_class_info: PyClassInfo = optional_py_class_info .expect("A class info must be passed in a Declare transaction."); let tx = ExecutableTransaction::Declare(py_declare(tx, non_optional_py_class_info)?); - AccountTransaction { tx, only_query: false }.into() + AccountTransaction { tx, execution_flags: ExecutionFlags::default() }.into() } TransactionType::DeployAccount => { let tx = ExecutableTransaction::DeployAccount(py_deploy_account(tx)?); - AccountTransaction { tx, only_query: false }.into() + AccountTransaction { tx, execution_flags: ExecutionFlags::default() }.into() } TransactionType::InvokeFunction => { let tx = ExecutableTransaction::Invoke(py_invoke_function(tx)?); - AccountTransaction { tx, only_query: false }.into() + AccountTransaction { tx, execution_flags: ExecutionFlags::default() }.into() } TransactionType::L1Handler => py_l1_handler(tx)?.into(), }) diff --git a/crates/starknet_batcher/src/block_builder.rs b/crates/starknet_batcher/src/block_builder.rs index b900f35d9c..39d961b677 100644 --- a/crates/starknet_batcher/src/block_builder.rs +++ b/crates/starknet_batcher/src/block_builder.rs @@ -15,7 +15,7 @@ use blockifier::execution::contract_class::RunnableCompiledClass; use blockifier::state::cached_state::CommitmentStateDiff; use blockifier::state::errors::StateError; use blockifier::state::global_cache::GlobalContractCache; -use blockifier::transaction::account_transaction::AccountTransaction; +use blockifier::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use blockifier::transaction::objects::TransactionExecutionInfo; use blockifier::transaction::transaction_execution::Transaction as BlockifierTransaction; use blockifier::versioned_constants::{VersionedConstants, VersionedConstantsOverrides}; @@ -167,7 +167,7 @@ impl BlockBuilderTrait for BlockBuilder { BlockifierTransaction::Account(AccountTransaction { // TODO(yair): Avoid this clone. tx: account_tx.clone(), - only_query: false, + execution_flags: ExecutionFlags::default(), }) } Transaction::L1Handler(l1_handler_tx) => { diff --git a/crates/starknet_gateway/src/stateful_transaction_validator.rs b/crates/starknet_gateway/src/stateful_transaction_validator.rs index 0674b8cd4b..6e0549e50d 100644 --- a/crates/starknet_gateway/src/stateful_transaction_validator.rs +++ b/crates/starknet_gateway/src/stateful_transaction_validator.rs @@ -5,7 +5,7 @@ use blockifier::blockifier::stateful_validator::{ use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo}; use blockifier::state::cached_state::CachedState; -use blockifier::transaction::account_transaction::AccountTransaction; +use blockifier::transaction::account_transaction::{AccountTransaction, ExecutionFlags}; use blockifier::versioned_constants::VersionedConstants; #[cfg(test)] use mockall::automock; @@ -75,7 +75,10 @@ impl StatefulTransactionValidator { mut validator: V, ) -> StatefulTransactionValidatorResult<()> { let skip_validate = skip_stateful_validations(executable_tx, account_nonce); - let account_tx = AccountTransaction { tx: executable_tx.clone(), only_query: false }; + let account_tx = AccountTransaction { + tx: executable_tx.clone(), + execution_flags: ExecutionFlags::default(), + }; validator .validate(account_tx, skip_validate) .map_err(|err| GatewaySpecError::ValidationFailure { data: err.to_string() })?;