From 4b0018270b578a7219eed3bdabe810554e9ce72b Mon Sep 17 00:00:00 2001 From: Aviv Greenburg Date: Sun, 15 Sep 2024 16:11:44 +0300 Subject: [PATCH] chore(blockifier): have charge_fee flag represent enforce_fee return value --- .../src/blockifier/stateful_validator.rs | 3 +- .../src/blockifier/transaction_executor.rs | 6 ++- .../src/concurrency/versioned_state_test.rs | 7 +++- .../src/concurrency/worker_logic.rs | 9 ++++- .../src/execution/stack_trace_test.rs | 7 +++- crates/blockifier/src/fee/fee_checks.rs | 2 +- .../src/transaction/account_transaction.rs | 2 +- .../transaction/account_transactions_test.rs | 22 ++++++---- .../src/transaction/post_execution_test.rs | 3 +- .../blockifier/src/transaction/test_utils.rs | 8 +++- .../src/transaction/transactions_test.rs | 40 +++++++++++-------- 11 files changed, 72 insertions(+), 37 deletions(-) diff --git a/crates/blockifier/src/blockifier/stateful_validator.rs b/crates/blockifier/src/blockifier/stateful_validator.rs index 98e7286a17..b2286dadf4 100644 --- a/crates/blockifier/src/blockifier/stateful_validator.rs +++ b/crates/blockifier/src/blockifier/stateful_validator.rs @@ -19,6 +19,7 @@ use crate::state::errors::StateError; use crate::state::state_api::StateReader; use crate::transaction::account_transaction::AccountTransaction; use crate::transaction::errors::{TransactionExecutionError, TransactionPreValidationError}; +use crate::transaction::objects::TransactionInfoCreator; use crate::transaction::transaction_execution::Transaction; use crate::transaction::transactions::ValidatableTransaction; @@ -95,7 +96,7 @@ impl StatefulValidator { ) -> StatefulValidatorResult<()> { let strict_nonce_check = false; // Run pre-validation in charge fee mode to perform fee and balance related checks. - let charge_fee = true; + let charge_fee = tx.create_tx_info().enforce_fee(); tx.perform_pre_validation_stage( self.tx_executor.block_state.as_mut().expect(BLOCK_STATE_ACCESS_ERR), tx_context, diff --git a/crates/blockifier/src/blockifier/transaction_executor.rs b/crates/blockifier/src/blockifier/transaction_executor.rs index c9a9c9c569..ac2bcf5b52 100644 --- a/crates/blockifier/src/blockifier/transaction_executor.rs +++ b/crates/blockifier/src/blockifier/transaction_executor.rs @@ -22,7 +22,7 @@ use crate::state::cached_state::{CachedState, CommitmentStateDiff, Transactional use crate::state::errors::StateError; use crate::state::state_api::{StateReader, StateResult}; use crate::transaction::errors::TransactionExecutionError; -use crate::transaction::objects::TransactionExecutionInfo; +use crate::transaction::objects::{TransactionExecutionInfo, TransactionInfoCreator}; use crate::transaction::transaction_execution::Transaction; use crate::transaction::transactions::{ExecutableTransaction, ExecutionFlags}; @@ -104,9 +104,11 @@ impl TransactionExecutor { let mut transactional_state = TransactionalState::create_transactional( self.block_state.as_mut().expect(BLOCK_STATE_ACCESS_ERR), ); + let tx_charge_fee = tx.create_tx_info().enforce_fee(); + // Executing a single transaction cannot be done in a concurrent mode. let execution_flags = - ExecutionFlags { charge_fee: true, validate: true, concurrency_mode: false }; + ExecutionFlags { charge_fee: tx_charge_fee, validate: true, concurrency_mode: false }; let tx_execution_result = tx.execute_raw(&mut transactional_state, &self.block_context, execution_flags); match tx_execution_result { diff --git a/crates/blockifier/src/concurrency/versioned_state_test.rs b/crates/blockifier/src/concurrency/versioned_state_test.rs index 1093535a69..da3d13fbe3 100644 --- a/crates/blockifier/src/concurrency/versioned_state_test.rs +++ b/crates/blockifier/src/concurrency/versioned_state_test.rs @@ -269,14 +269,17 @@ fn test_run_parallel_txs(max_l1_resource_bounds: ValidResourceBounds) { let block_context_1 = block_context.clone(); let block_context_2 = block_context.clone(); + // Execute transactions thread::scope(|s| { s.spawn(move || { - let result = account_tx_1.execute(&mut state_1, &block_context_1, true, true); + let charge_fee_1 = account_tx_1.create_tx_info().enforce_fee(); + let result = account_tx_1.execute(&mut state_1, &block_context_1, charge_fee_1, true); assert_eq!(result.is_err(), enforce_fee); }); s.spawn(move || { - account_tx_2.execute(&mut state_2, &block_context_2, true, true).unwrap(); + let charge_fee_2 = account_tx_2.create_tx_info().enforce_fee(); + account_tx_2.execute(&mut state_2, &block_context_2, charge_fee_2, true).unwrap(); // Check that the constructor wrote ctor_arg to the storage. let storage_key = get_storage_var_address("ctor_arg", &[]); let deployed_contract_address = calculate_contract_address( diff --git a/crates/blockifier/src/concurrency/worker_logic.rs b/crates/blockifier/src/concurrency/worker_logic.rs index 425b810985..eb26f2a26e 100644 --- a/crates/blockifier/src/concurrency/worker_logic.rs +++ b/crates/blockifier/src/concurrency/worker_logic.rs @@ -22,7 +22,11 @@ use crate::state::cached_state::{ TransactionalState, }; use crate::state::state_api::{StateReader, UpdatableState}; -use crate::transaction::objects::{TransactionExecutionInfo, TransactionExecutionResult}; +use crate::transaction::objects::{ + TransactionExecutionInfo, + TransactionExecutionResult, + TransactionInfoCreator, +}; use crate::transaction::transaction_execution::Transaction; use crate::transaction::transactions::{ExecutableTransaction, ExecutionFlags}; @@ -128,10 +132,11 @@ impl<'a, S: StateReader> WorkerExecutor<'a, S> { fn execute_tx(&self, tx_index: TxIndex) { let mut tx_versioned_state = self.state.pin_version(tx_index); let tx = &self.chunk[tx_index]; + let tx_charge_fee = tx.create_tx_info().enforce_fee(); let mut transactional_state = TransactionalState::create_transactional(&mut tx_versioned_state); let execution_flags = - ExecutionFlags { charge_fee: true, validate: true, concurrency_mode: true }; + ExecutionFlags { charge_fee: tx_charge_fee, validate: true, concurrency_mode: true }; let execution_result = tx.execute_raw(&mut transactional_state, self.block_context, execution_flags); diff --git a/crates/blockifier/src/execution/stack_trace_test.rs b/crates/blockifier/src/execution/stack_trace_test.rs index 6befda1689..72f4d76f99 100644 --- a/crates/blockifier/src/execution/stack_trace_test.rs +++ b/crates/blockifier/src/execution/stack_trace_test.rs @@ -27,6 +27,7 @@ use crate::transaction::constants::{ VALIDATE_DEPLOY_ENTRY_POINT_NAME, VALIDATE_ENTRY_POINT_NAME, }; +use crate::transaction::objects::TransactionInfoCreator; use crate::transaction::test_utils::{ account_invoke_tx, block_context, @@ -620,7 +621,8 @@ Execution failed. Failure reason: 0x496e76616c6964207363656e6172696f ('Invalid s // Clean pc locations from the trace. let re = Regex::new(r"pc=0:[0-9]+").unwrap(); let cleaned_expected_error = &re.replace_all(&expected_error, "pc=0:*"); - let actual_error = account_tx.execute(state, block_context, true, true).unwrap_err(); + let charge_fee = account_tx.create_tx_info().enforce_fee(); + let actual_error = account_tx.execute(state, block_context, charge_fee, true).unwrap_err(); let actual_error_str = actual_error.to_string(); let cleaned_actual_error = &re.replace_all(&actual_error_str, "pc=0:*"); // Compare actual trace to the expected trace (sans pc locations). @@ -683,7 +685,8 @@ An ASSERT_EQ instruction failed: 1 != 0. }; // Compare expected and actual error. - let error = deploy_account_tx.execute(state, &block_context, true, true).unwrap_err(); + let charge_fee = deploy_account_tx.create_tx_info().enforce_fee(); + let error = deploy_account_tx.execute(state, &block_context, charge_fee, true).unwrap_err(); assert_eq!(error.to_string(), expected_error); } diff --git a/crates/blockifier/src/fee/fee_checks.rs b/crates/blockifier/src/fee/fee_checks.rs index 0a14d27b56..4dca651f79 100644 --- a/crates/blockifier/src/fee/fee_checks.rs +++ b/crates/blockifier/src/fee/fee_checks.rs @@ -234,7 +234,7 @@ impl PostExecutionReport { let TransactionReceipt { fee, .. } = tx_receipt; // If fee is not enforced, no need to check post-execution. - if !charge_fee || !tx_context.tx_info.enforce_fee() { + if !charge_fee { return Ok(Self(FeeCheckReport::success_report(*fee))); } diff --git a/crates/blockifier/src/transaction/account_transaction.rs b/crates/blockifier/src/transaction/account_transaction.rs index 4aa9e55a44..a7e67a0bd3 100644 --- a/crates/blockifier/src/transaction/account_transaction.rs +++ b/crates/blockifier/src/transaction/account_transaction.rs @@ -296,7 +296,7 @@ impl AccountTransaction { let tx_info = &tx_context.tx_info; Self::handle_nonce(state, tx_info, strict_nonce_check)?; - if charge_fee && tx_info.enforce_fee() { + if charge_fee { self.check_fee_bounds(tx_context)?; verify_can_pay_committed_bounds(state, tx_context)?; diff --git a/crates/blockifier/src/transaction/account_transactions_test.rs b/crates/blockifier/src/transaction/account_transactions_test.rs index 8438f79ec1..1ea3c1cd9f 100644 --- a/crates/blockifier/src/transaction/account_transactions_test.rs +++ b/crates/blockifier/src/transaction/account_transactions_test.rs @@ -177,9 +177,9 @@ fn test_fee_enforcement( ); let account_tx = AccountTransaction::DeployAccount(deploy_account_tx); - let enforce_fee = account_tx.create_tx_info().enforce_fee(); - let result = account_tx.execute(state, &block_context, true, true); - assert_eq!(result.is_err(), enforce_fee); + let charge_fee = account_tx.create_tx_info().enforce_fee(); + let result = account_tx.execute(state, &block_context, charge_fee, true); + assert_eq!(result.is_err(), charge_fee); } #[rstest] @@ -612,7 +612,9 @@ fn test_fail_deploy_account( let initial_balance = state.get_fee_token_balance(deploy_address, fee_token_address).unwrap(); - let error = deploy_account_tx.execute(state, &block_context, true, true).unwrap_err(); + let charge_fee = deploy_account_tx.create_tx_info().enforce_fee(); + + let error = deploy_account_tx.execute(state, &block_context, charge_fee, true).unwrap_err(); // Check the error is as expected. Assure the error message is not nonce or fee related. check_tx_execution_error_for_invalid_scenario!(cairo_version, error, false); @@ -938,9 +940,11 @@ fn test_max_fee_to_max_steps_conversion( nonce: nonce_manager.next(account_address), }); let tx_context1 = Arc::new(block_context.to_tx_context(&account_tx1)); - let execution_context1 = EntryPointExecutionContext::new_invoke(tx_context1, true); + let charge_fee1 = account_tx1.create_tx_info().enforce_fee(); + let execution_context1 = EntryPointExecutionContext::new_invoke(tx_context1, charge_fee1); let max_steps_limit1 = execution_context1.vm_run_resources.get_n_steps(); - let tx_execution_info1 = account_tx1.execute(&mut state, &block_context, true, true).unwrap(); + let tx_execution_info1 = + account_tx1.execute(&mut state, &block_context, charge_fee1, true).unwrap(); let n_steps1 = tx_execution_info1.receipt.resources.computation.vm_resources.n_steps; let gas_used_vector1 = tx_execution_info1.receipt.resources.to_gas_vector( &block_context.versioned_constants, @@ -958,9 +962,11 @@ fn test_max_fee_to_max_steps_conversion( nonce: nonce_manager.next(account_address), }); let tx_context2 = Arc::new(block_context.to_tx_context(&account_tx2)); - let execution_context2 = EntryPointExecutionContext::new_invoke(tx_context2, true); + let charge_fee2 = account_tx2.create_tx_info().enforce_fee(); + let execution_context2 = EntryPointExecutionContext::new_invoke(tx_context2, charge_fee2); let max_steps_limit2 = execution_context2.vm_run_resources.get_n_steps(); - let tx_execution_info2 = account_tx2.execute(&mut state, &block_context, true, true).unwrap(); + let tx_execution_info2 = + account_tx2.execute(&mut state, &block_context, charge_fee2, true).unwrap(); let n_steps2 = tx_execution_info2.receipt.resources.computation.vm_resources.n_steps; let gas_used_vector2 = tx_execution_info2.receipt.resources.to_gas_vector( &block_context.versioned_constants, diff --git a/crates/blockifier/src/transaction/post_execution_test.rs b/crates/blockifier/src/transaction/post_execution_test.rs index 960638d0f8..297fb38362 100644 --- a/crates/blockifier/src/transaction/post_execution_test.rs +++ b/crates/blockifier/src/transaction/post_execution_test.rs @@ -113,8 +113,9 @@ fn test_revert_on_overdraft( nonce: nonce_manager.next(account_address), }); let tx_info = approve_tx.create_tx_info(); + let charge_fee = tx_info.enforce_fee(); let approval_execution_info = - approve_tx.execute(&mut state, &block_context, true, true).unwrap(); + approve_tx.execute(&mut state, &block_context, charge_fee, true).unwrap(); assert!(!approval_execution_info.is_reverted()); // Transfer a valid amount of funds to compute the cost of a successful diff --git a/crates/blockifier/src/transaction/test_utils.rs b/crates/blockifier/src/transaction/test_utils.rs index bf40dcf832..cec0be9e48 100644 --- a/crates/blockifier/src/transaction/test_utils.rs +++ b/crates/blockifier/src/transaction/test_utils.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use rstest::fixture; use starknet_api::core::{ClassHash, ContractAddress, Nonce}; use starknet_api::test_utils::deploy_account::DeployAccountTxArgs; @@ -298,7 +300,11 @@ pub fn run_invoke_tx( block_context: &BlockContext, invoke_args: InvokeTxArgs, ) -> TransactionExecutionResult { - account_invoke_tx(invoke_args).execute(state, block_context, true, true) + let tx = account_invoke_tx(invoke_args.clone()); + let tx_context = Arc::new(block_context.to_tx_context(&tx)); + let charge_fee = tx_context.tx_info.enforce_fee(); + + account_invoke_tx(invoke_args).execute(state, block_context, charge_fee, true) } /// Creates a `ResourceBoundsMapping` with the given `max_amount` and `max_price` for L1 gas limits. diff --git a/crates/blockifier/src/transaction/transactions_test.rs b/crates/blockifier/src/transaction/transactions_test.rs index ab3c665571..4faa46286e 100644 --- a/crates/blockifier/src/transaction/transactions_test.rs +++ b/crates/blockifier/src/transaction/transactions_test.rs @@ -119,6 +119,7 @@ use crate::transaction::objects::{ HasRelatedFeeType, TransactionExecutionInfo, TransactionInfo, + TransactionInfoCreator, }; use crate::transaction::test_utils::{ account_invoke_tx, @@ -808,7 +809,8 @@ fn test_state_get_fee_token_balance( version: tx_version, nonce: Nonce::default(), }); - account_tx.execute(state, block_context, true, true).unwrap(); + let charge_fee = account_tx.create_tx_info().enforce_fee(); + account_tx.execute(state, block_context, charge_fee, true).unwrap(); // Get balance from state, and validate. let (low, high) = @@ -823,10 +825,13 @@ fn assert_failure_if_resource_bounds_exceed_balance( block_context: &BlockContext, invalid_tx: AccountTransaction, ) { - match block_context.to_tx_context(&invalid_tx).tx_info { + let tx_info = invalid_tx.create_tx_info(); + let charge_fee = tx_info.enforce_fee(); + + match tx_info { TransactionInfo::Deprecated(context) => { assert_matches!( - invalid_tx.execute(state, block_context, true, true).unwrap_err(), + invalid_tx.execute(state, block_context, charge_fee, true).unwrap_err(), TransactionExecutionError::TransactionPreValidationError( TransactionPreValidationError::TransactionFeeError( TransactionFeeError::MaxFeeExceedsBalance{ max_fee, .. })) @@ -836,7 +841,7 @@ fn assert_failure_if_resource_bounds_exceed_balance( TransactionInfo::Current(context) => { let l1_bounds = context.l1_resource_bounds(); assert_matches!( - invalid_tx.execute(state, block_context, true, true).unwrap_err(), + invalid_tx.execute(state, block_context, charge_fee, true).unwrap_err(), TransactionExecutionError::TransactionPreValidationError( TransactionPreValidationError::TransactionFeeError( TransactionFeeError::GasBoundsExceedBalance{resource, max_amount, max_price, .. })) @@ -1734,7 +1739,10 @@ fn test_validate_accounts_tx( additional_data: None, ..default_args }); - let error = account_tx.execute(state, block_context, true, true).unwrap_err(); + // All tx has default resource bounds, thus the default charge fee is the same for all. + let default_charge_fee = account_tx.create_tx_info().enforce_fee(); + + let error = account_tx.execute(state, block_context, default_charge_fee, true).unwrap_err(); check_tx_execution_error_for_invalid_scenario!(cairo_version, error, validate_constructor,); // Try to call another contract (forbidden). @@ -1747,7 +1755,7 @@ fn test_validate_accounts_tx( resource_bounds: ValidResourceBounds::create_for_testing(), ..default_args }); - let error = account_tx.execute(state, block_context, true, true).unwrap_err(); + let error = account_tx.execute(state, block_context, default_charge_fee, true).unwrap_err(); check_tx_execution_error_for_custom_hint!( &error, "Unauthorized syscall call_contract in execution mode Validate.", @@ -1763,7 +1771,7 @@ fn test_validate_accounts_tx( resource_bounds: ValidResourceBounds::create_for_testing(), ..default_args }); - let error = account_tx.execute(state, block_context, true, true).unwrap_err(); + let error = account_tx.execute(state, block_context, default_charge_fee, true).unwrap_err(); check_tx_execution_error_for_custom_hint!( &error, "Unauthorized syscall get_block_hash in execution mode Validate.", @@ -1778,7 +1786,7 @@ fn test_validate_accounts_tx( resource_bounds: ValidResourceBounds::create_for_testing(), ..default_args }); - let error = account_tx.execute(state, block_context, true, true).unwrap_err(); + let error = account_tx.execute(state, block_context, default_charge_fee, true).unwrap_err(); check_tx_execution_error_for_custom_hint!( &error, "Unauthorized syscall get_sequencer_address in execution mode Validate.", @@ -1802,7 +1810,7 @@ fn test_validate_accounts_tx( ..default_args }, ); - let result = account_tx.execute(state, block_context, true, true); + let result = account_tx.execute(state, block_context, default_charge_fee, true); assert!(result.is_ok(), "Execution failed: {:?}", result.unwrap_err()); if tx_type != TransactionType::DeployAccount { @@ -1819,7 +1827,7 @@ fn test_validate_accounts_tx( ..default_args }, ); - let result = account_tx.execute(state, block_context, true, true); + let result = account_tx.execute(state, block_context, default_charge_fee, true); assert!(result.is_ok(), "Execution failed: {:?}", result.unwrap_err()); } @@ -1839,7 +1847,7 @@ fn test_validate_accounts_tx( ..default_args }, ); - let result = account_tx.execute(state, block_context, true, true); + let result = account_tx.execute(state, block_context, default_charge_fee, true); assert!(result.is_ok(), "Execution failed: {:?}", result.unwrap_err()); // Call the syscall get_block_timestamp and assert the returned timestamp was modified @@ -1855,7 +1863,7 @@ fn test_validate_accounts_tx( ..default_args }, ); - let result = account_tx.execute(state, block_context, true, true); + let result = account_tx.execute(state, block_context, default_charge_fee, true); assert!(result.is_ok(), "Execution failed: {:?}", result.unwrap_err()); } @@ -1877,7 +1885,7 @@ fn test_validate_accounts_tx( ..default_args }, ); - let result = account_tx.execute(state, block_context, true, true); + let result = account_tx.execute(state, block_context, default_charge_fee, true); assert!(result.is_ok(), "Execution failed: {:?}", result.unwrap_err()); } } @@ -2021,8 +2029,8 @@ fn test_l1_handler(#[values(false, true)] use_kzg_da: bool) { let key = calldata.0[1]; let value = calldata.0[2]; let payload_size = tx.payload_size(); - - let actual_execution_info = tx.execute(state, block_context, true, true).unwrap(); + let charge_fee = tx.create_tx_info().enforce_fee(); + let actual_execution_info = tx.execute(state, block_context, charge_fee, true).unwrap(); // Build the expected call info. let accessed_storage_key = StorageKey::try_from(key).unwrap(); @@ -2146,7 +2154,7 @@ fn test_l1_handler(#[values(false, true)] use_kzg_da: bool) { // always uptade the storage instad. state.set_storage_at(contract_address, StorageKey::try_from(key).unwrap(), Felt::ZERO).unwrap(); let tx_no_fee = L1HandlerTransaction::create_for_testing(Fee(0), contract_address); - let error = tx_no_fee.execute(state, block_context, true, true).unwrap_err(); + let error = tx_no_fee.execute(state, block_context, charge_fee, true).unwrap_err(); // Today, we check that the paid_fee is positive, no matter what was the actual fee. let expected_actual_fee = expected_execution_info.receipt.resources.calculate_tx_fee(block_context, &FeeType::Eth);