diff --git a/crates/apollo_gateway/src/gateway.rs b/crates/apollo_gateway/src/gateway.rs index b12df75aa9b..50b688765a2 100644 --- a/crates/apollo_gateway/src/gateway.rs +++ b/crates/apollo_gateway/src/gateway.rs @@ -32,7 +32,7 @@ use starknet_api::rpc_transaction::{ RpcDeclareTransaction, RpcTransaction, }; -use tracing::{debug, warn, Span}; +use tracing::{debug, warn}; use crate::errors::{ mempool_client_result_to_deprecated_gw_result, @@ -157,30 +157,10 @@ impl Gateway { .await .inspect_err(|e| metric_counters.record_add_tx_failure(e))?; - let curr_span = Span::current(); - let mempool_client = self.mempool_client.clone(); - let nonce = tokio::task::spawn_blocking(move || { - curr_span.in_scope(|| { - stateful_transaction_validator.extract_state_nonce_and_run_validations( - &executable_tx, - mempool_client, - tokio::runtime::Handle::current(), - ) - }) - }) - .await - .map_err(|e| { - // Handle panics in the spawned thread (see tokio::task::JoinHandle). - let err = StarknetError { - code: StarknetErrorCode::UnknownErrorCode( - "StarknetErrorCode.InternalError".to_string(), - ), - message: format!("Validation task failed to complete: {e}"), - }; - metric_counters.record_add_tx_failure(&err); - err - })? - .inspect_err(|e| metric_counters.record_add_tx_failure(e))?; + let nonce = stateful_transaction_validator + .extract_state_nonce_and_run_validations(&executable_tx, self.mempool_client.clone()) + .await + .inspect_err(|e| metric_counters.record_add_tx_failure(e))?; let gateway_output = create_gateway_output(&internal_tx); diff --git a/crates/apollo_gateway/src/gateway_test.rs b/crates/apollo_gateway/src/gateway_test.rs index 0c8e24acf67..974dbac776f 100644 --- a/crates/apollo_gateway/src/gateway_test.rs +++ b/crates/apollo_gateway/src/gateway_test.rs @@ -557,7 +557,7 @@ async fn add_tx_returns_error_when_extract_state_nonce_and_run_validations_fails mock_stateful_transaction_validator .expect_extract_state_nonce_and_run_validations() - .return_once(|_, _, _| Err(expected_error)); + .return_once(|_, _| Err(expected_error)); mock_stateful_transaction_validator_factory .expect_instantiate_validator() diff --git a/crates/apollo_gateway/src/stateful_transaction_validator.rs b/crates/apollo_gateway/src/stateful_transaction_validator.rs index e519e51727a..51b43481459 100644 --- a/crates/apollo_gateway/src/stateful_transaction_validator.rs +++ b/crates/apollo_gateway/src/stateful_transaction_validator.rs @@ -11,10 +11,7 @@ use apollo_mempool_types::communication::SharedMempoolClient; use apollo_mempool_types::mempool_types::ValidationArgs; use apollo_proc_macros::sequencer_latency_histogram; use async_trait::async_trait; -use blockifier::blockifier::stateful_validator::{ - StatefulValidator, - StatefulValidatorTrait as BlockifierStatefulValidatorTrait, -}; +use blockifier::blockifier::stateful_validator::{StatefulValidator, StatefulValidatorTrait}; use blockifier::blockifier_versioned_constants::VersionedConstants; use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo}; @@ -32,7 +29,7 @@ use starknet_api::executable_transaction::{ }; use starknet_api::transaction::fields::ValidResourceBounds; use starknet_types_core::felt::Felt; -use tracing::debug; +use tracing::{debug, Span}; use crate::errors::{mempool_client_err_to_deprecated_gw_err, StatefulTransactionValidatorResult}; use crate::gateway_fixed_block_state_reader::GatewayFixedBlockStateReader; @@ -87,115 +84,96 @@ impl StatefulTransactionValidatorFactoryTrait for StatefulTransactionValidatorFa self.contract_class_manager.clone(), Some(GATEWAY_CLASS_CACHE_METRICS), ); - - let state = CachedState::new(state_reader_and_contract_manager); - let mut versioned_constants = VersionedConstants::get_versioned_constants( - self.config.versioned_constants_overrides.clone(), - ); - // The validation of a transaction is not affected by the casm hash migration. - versioned_constants.enable_casm_hash_migration = false; - - let mut block_info = gateway_fixed_block_state_reader.get_block_info().await?; - block_info.block_number = block_info.block_number.unchecked_next(); - let block_context = BlockContext::new( - block_info, + Ok(Box::new(StatefulTransactionValidator::new( + self.config.clone(), self.chain_info.clone(), - versioned_constants, - BouncerConfig::max(), - ); - - let blockifier_stateful_tx_validator = - BlockifierStatefulValidator::create(state, block_context); - Ok(Box::new(StatefulTransactionValidator { - config: self.config.clone(), - blockifier_stateful_tx_validator, + state_reader_and_contract_manager, gateway_fixed_block_state_reader, - })) + ))) } } #[cfg_attr(test, mockall::automock)] +#[async_trait] pub trait StatefulTransactionValidatorTrait: Send { - fn extract_state_nonce_and_run_validations( + async fn extract_state_nonce_and_run_validations( &mut self, executable_tx: &ExecutableTransaction, mempool_client: SharedMempoolClient, - runtime: tokio::runtime::Handle, ) -> StatefulTransactionValidatorResult; } -pub struct StatefulTransactionValidator { +pub struct StatefulTransactionValidator { config: StatefulTransactionValidatorConfig, - blockifier_stateful_tx_validator: B, + chain_info: ChainInfo, + // Consumed when running the CPU-heavy blockifier validation. + // TODO(Itamar): The whole `StatefulTransactionValidator` is never used after + // `state_reader_and_contract_manager` is taken. Make it non-optional and discard the + // instance after use. + state_reader_and_contract_manager: + Option>>, gateway_fixed_block_state_reader: Box, } -impl StatefulTransactionValidatorTrait - for StatefulTransactionValidator -{ - fn extract_state_nonce_and_run_validations( +#[async_trait] +impl StatefulTransactionValidatorTrait for StatefulTransactionValidator { + async fn extract_state_nonce_and_run_validations( &mut self, executable_tx: &ExecutableTransaction, mempool_client: SharedMempoolClient, - runtime: tokio::runtime::Handle, ) -> StatefulTransactionValidatorResult { - let address = executable_tx.contract_address(); - let account_nonce = runtime - .block_on(self.gateway_fixed_block_state_reader.get_nonce(address)) - .map_err(|e| { - // TODO(noamsp): Fix this. Need to map the errors better. - StarknetError::internal_with_signature_logging( - format!("Failed to get nonce for sender address {address}"), - &executable_tx.signature(), - e, - ) - })?; - self.run_transaction_validations(executable_tx, account_nonce, mempool_client, runtime)?; + let account_nonce = self.extract_nonce(executable_tx).await?; + let skip_validate = + self.run_pre_validation_checks(executable_tx, account_nonce, mempool_client).await?; + self.run_validate_entry_point(executable_tx, skip_validate).await?; Ok(account_nonce) } } -impl StatefulTransactionValidator { - fn run_transaction_validations( +impl StatefulTransactionValidator { + fn new( + config: StatefulTransactionValidatorConfig, + chain_info: ChainInfo, + state_reader_and_contract_manager: StateReaderAndContractManager< + Box, + >, + gateway_fixed_block_state_reader: Box, + ) -> Self { + Self { + config, + chain_info, + state_reader_and_contract_manager: Some(state_reader_and_contract_manager), + gateway_fixed_block_state_reader, + } + } + + fn take_state_reader_and_contract_manager( &mut self, - executable_tx: &ExecutableTransaction, - account_nonce: Nonce, - mempool_client: SharedMempoolClient, - runtime: tokio::runtime::Handle, - ) -> StatefulTransactionValidatorResult<()> { - self.validate_state_preconditions(executable_tx, account_nonce)?; - runtime.block_on(validate_by_mempool( - executable_tx, - account_nonce, - mempool_client.clone(), - ))?; - self.run_validate_entry_point(executable_tx, account_nonce, mempool_client, runtime)?; - Ok(()) + ) -> StateReaderAndContractManager> { + self.state_reader_and_contract_manager.take().expect("Validator was already consumed") } - fn validate_state_preconditions( + async fn validate_state_preconditions( &self, executable_tx: &ExecutableTransaction, account_nonce: Nonce, ) -> StatefulTransactionValidatorResult<()> { - self.validate_resource_bounds(executable_tx)?; + self.validate_resource_bounds(executable_tx).await?; self.validate_nonce(executable_tx, account_nonce)?; Ok(()) } - fn validate_resource_bounds( + async fn validate_resource_bounds( &self, executable_tx: &ExecutableTransaction, ) -> StatefulTransactionValidatorResult<()> { // Skip this validation during the systems bootstrap phase. if self.config.validate_resource_bounds { // TODO(Arni): getnext_l2_gas_price from the block header. - // TODO(Itamar): Replace usage of `blockifier_stateful_tx_validator.block_info()` with - // the GW fixed-block provider and then remove `block_info()` from - // blockifier::{StatefulValidatorTrait, StatefulValidator}. let previous_block_l2_gas_price = self - .blockifier_stateful_tx_validator - .block_info() + .gateway_fixed_block_state_reader + .get_block_info() + .await? .gas_prices .strk_gas_prices .l2_gas_price; @@ -265,15 +243,11 @@ impl StatefulTransactionValidator { } #[sequencer_latency_histogram(GATEWAY_VALIDATE_TX_LATENCY, true)] - fn run_validate_entry_point( + async fn run_validate_entry_point( &mut self, executable_tx: &ExecutableTransaction, - account_nonce: Nonce, - mempool_client: SharedMempoolClient, - runtime: tokio::runtime::Handle, + skip_validate: bool, ) -> StatefulTransactionValidatorResult<()> { - let skip_validate = - skip_stateful_validations(executable_tx, account_nonce, mempool_client, runtime)?; let only_query = false; let charge_fee = enforce_fee(executable_tx, only_query); let strict_nonce_check = false; @@ -281,7 +255,42 @@ impl StatefulTransactionValidator { ExecutionFlags { only_query, charge_fee, validate: !skip_validate, strict_nonce_check }; let account_tx = AccountTransaction { tx: executable_tx.clone(), execution_flags }; - self.blockifier_stateful_tx_validator.validate(account_tx).map_err(|e| StarknetError { + + // Build block context here. + let mut versioned_constants = VersionedConstants::get_versioned_constants( + self.config.versioned_constants_overrides.clone(), + ); + // The validation of a transaction is not affected by the casm hash migration. + versioned_constants.enable_casm_hash_migration = false; + + let mut block_info = self.gateway_fixed_block_state_reader.get_block_info().await?; + block_info.block_number = block_info.block_number.unchecked_next(); + let block_context = BlockContext::new( + block_info, + self.chain_info.clone(), + versioned_constants, + BouncerConfig::max(), + ); + + // Move state into the blocking task and run CPU-heavy validation. + let state_reader_and_contract_manager = self.take_state_reader_and_contract_manager(); + + let cur_span = Span::current(); + tokio::task::spawn_blocking(move || { + cur_span.in_scope(|| { + let state = CachedState::new(state_reader_and_contract_manager); + let mut blockifier = BlockifierStatefulValidator::create(state, block_context); + blockifier.validate(account_tx) + }) + }) + .await + .map_err(|e| StarknetError { + code: StarknetErrorCode::UnknownErrorCode( + "StarknetErrorCode.InternalError".to_string(), + ), + message: format!("Blocking task join error when running the validate entry point: {e}"), + })? + .map_err(|e| StarknetError { code: StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::ValidateFailure), message: e.to_string(), })?; @@ -321,6 +330,35 @@ impl StatefulTransactionValidator { } Ok(()) } + + async fn extract_nonce( + &self, + executable_tx: &ExecutableTransaction, + ) -> StatefulTransactionValidatorResult { + let address = executable_tx.contract_address(); + let account_nonce = + self.gateway_fixed_block_state_reader.get_nonce(address).await.map_err(|e| { + StarknetError::internal_with_signature_logging( + format!("Failed to get nonce for sender address {address}"), + &executable_tx.signature(), + e, + ) + })?; + Ok(account_nonce) + } + + async fn run_pre_validation_checks( + &self, + executable_tx: &ExecutableTransaction, + account_nonce: Nonce, + mempool_client: SharedMempoolClient, + ) -> StatefulTransactionValidatorResult { + self.validate_state_preconditions(executable_tx, account_nonce).await?; + validate_by_mempool(executable_tx, account_nonce, mempool_client.clone()).await?; + let skip_validate = + skip_stateful_validations(executable_tx, account_nonce, mempool_client.clone()).await?; + Ok(skip_validate) + } } /// Perform transaction validation by the mempool. @@ -339,11 +377,10 @@ async fn validate_by_mempool( /// Check if validation of an invoke transaction should be skipped due to deploy_account not being /// processed yet. This feature is used to improve UX for users sending deploy_account + invoke at /// once. -fn skip_stateful_validations( +async fn skip_stateful_validations( tx: &ExecutableTransaction, account_nonce: Nonce, mempool_client: SharedMempoolClient, - runtime: tokio::runtime::Handle, ) -> StatefulTransactionValidatorResult { if let ExecutableTransaction::Invoke(ExecutableInvokeTransaction { tx, .. }) = tx { // check if the transaction nonce is 1, meaning it is post deploy_account, and the @@ -355,8 +392,9 @@ fn skip_stateful_validations( // to check if the account exists in the mempool since it means that either it has a // deploy_account transaction or transactions with future nonces that passed // validations. - return runtime - .block_on(mempool_client.account_tx_in_pool_or_recent_block(tx.sender_address())) + return mempool_client + .account_tx_in_pool_or_recent_block(tx.sender_address()) + .await .map_err(|err| mempool_client_err_to_deprecated_gw_err(&tx.signature(), err)) .inspect(|exists| { if *exists { diff --git a/crates/apollo_gateway/src/stateful_transaction_validator_test.rs b/crates/apollo_gateway/src/stateful_transaction_validator_test.rs index b6c9d41b987..d9071e7f7cb 100644 --- a/crates/apollo_gateway/src/stateful_transaction_validator_test.rs +++ b/crates/apollo_gateway/src/stateful_transaction_validator_test.rs @@ -8,35 +8,21 @@ use apollo_gateway_types::deprecated_gateway_error::{ }; use apollo_mempool_types::communication::MockMempoolClient; use blockifier::blockifier::config::ContractClassManagerConfig; -use blockifier::blockifier::stateful_validator::{ - MockStatefulValidatorTrait as MockBlockifierStatefulValidatorTrait, - StatefulValidatorError as BlockifierStatefulValidatorError, -}; use blockifier::context::ChainInfo; use blockifier::state::contract_class_manager::ContractClassManager; use blockifier::test_utils::contracts::FeatureContractTrait; -use blockifier::transaction::errors::{TransactionFeeError, TransactionPreValidationError}; use blockifier::transaction::test_utils::calculate_class_info_for_testing; use blockifier_test_utils::cairo_versions::{CairoVersion, RunnableCairo1}; use blockifier_test_utils::contracts::FeatureContract; -use mempool_test_utils::starknet_api_test_utils::executable_invoke_tx as create_executable_invoke_tx; -use num_bigint::BigUint; use pretty_assertions::assert_eq; use rstest::rstest; use starknet_api::block::{BlockInfo, GasPrice, GasPriceVector, GasPrices, NonzeroGasPrice}; use starknet_api::core::Nonce; use starknet_api::executable_transaction::AccountTransaction; -use starknet_api::execution_resources::GasAmount; use starknet_api::test_utils::declare::executable_declare_tx; use starknet_api::test_utils::deploy_account::executable_deploy_account_tx; use starknet_api::test_utils::invoke::executable_invoke_tx; -use starknet_api::test_utils::{VALID_L1_GAS_MAX_AMOUNT, VALID_L1_GAS_MAX_PRICE_PER_UNIT}; -use starknet_api::transaction::fields::{ - AllResourceBounds, - Resource, - ResourceBounds, - ValidResourceBounds, -}; +use starknet_api::transaction::fields::{AllResourceBounds, ResourceBounds, ValidResourceBounds}; use starknet_api::{declare_tx_args, deploy_account_tx_args, invoke_tx_args, nonce}; use crate::gateway_fixed_block_state_reader::MockGatewayFixedBlockStateReader; @@ -50,7 +36,6 @@ use crate::stateful_transaction_validator::{ #[tokio::test] async fn test_get_nonce_fail_on_extract_state_nonce_and_run_validations() { - let mock_blockifier_validator = MockBlockifierStatefulValidatorTrait::new(); let mut mock_gateway_fixed_block = MockGatewayFixedBlockStateReader::new(); mock_gateway_fixed_block.expect_get_nonce().return_once(|_| { Err(StarknetError { @@ -62,23 +47,17 @@ async fn test_get_nonce_fail_on_extract_state_nonce_and_run_validations() { }); let mempool_client = Arc::new(MockMempoolClient::new()); - let runtime = tokio::runtime::Handle::current(); let mut stateful_validator = StatefulTransactionValidator { config: StatefulTransactionValidatorConfig::default(), - blockifier_stateful_tx_validator: mock_blockifier_validator, + chain_info: ChainInfo::create_for_testing(), + state_reader_and_contract_manager: None, gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block), }; let executable_tx = executable_invoke_tx(invoke_tx_args!()); - let result = tokio::task::spawn_blocking(move || { - stateful_validator.extract_state_nonce_and_run_validations( - &executable_tx, - mempool_client, - runtime, - ) - }) - .await - .unwrap(); + let result = stateful_validator + .extract_state_nonce_and_run_validations(&executable_tx, mempool_client) + .await; assert_eq!( result, Err(StarknetError { @@ -90,73 +69,6 @@ async fn test_get_nonce_fail_on_extract_state_nonce_and_run_validations() { ); } -// TODO(Arni): consider testing declare and deploy account. -#[rstest] -#[case::valid_tx(create_executable_invoke_tx(CairoVersion::Cairo1(RunnableCairo1::Casm)), true)] -#[case::invalid_tx(create_executable_invoke_tx(CairoVersion::Cairo1(RunnableCairo1::Casm)), false)] -#[tokio::test] -async fn test_extract_state_nonce_and_run_validations( - #[case] executable_tx: AccountTransaction, - #[case] expect_ok: bool, -) { - let account_nonce = nonce!(0); - - let expected_result = if expect_ok { - Ok(account_nonce) - } else { - Err(BlockifierStatefulValidatorError::TransactionPreValidationError( - TransactionPreValidationError::TransactionFeeError(Box::new( - TransactionFeeError::GasBoundsExceedBalance { - resource: Resource::L1DataGas, - max_amount: GasAmount(VALID_L1_GAS_MAX_AMOUNT), - max_price: GasPrice(VALID_L1_GAS_MAX_PRICE_PER_UNIT), - balance: BigUint::ZERO, - }, - )), - )) - }; - let expected_result_as_stateful_transaction_result = expected_result - .as_ref() - .map(|validate_result| *validate_result) - .map_err(|blockifier_error| StarknetError { - code: StarknetErrorCode::KnownErrorCode(KnownStarknetErrorCode::ValidateFailure), - message: format!("{blockifier_error}"), - }); - - let mut mock_blockifier_validator = MockBlockifierStatefulValidatorTrait::new(); - mock_blockifier_validator.expect_validate().return_once(|_| expected_result.map(|_| ())); - mock_blockifier_validator.expect_block_info().return_const(BlockInfo::default()); - - let mut mock_mempool_client = MockMempoolClient::new(); - mock_mempool_client.expect_account_tx_in_pool_or_recent_block().returning(|_| { - // The mempool does not have any transactions from the sender. - Ok(false) - }); - mock_mempool_client.expect_validate_tx().returning(|_| Ok(())); - let mempool_client = Arc::new(mock_mempool_client); - let runtime = tokio::runtime::Handle::current(); - - let mut mock_gateway_fixed_block = MockGatewayFixedBlockStateReader::new(); - mock_gateway_fixed_block.expect_get_nonce().return_once(move |_| Ok(account_nonce)); - - let mut stateful_validator = StatefulTransactionValidator { - config: StatefulTransactionValidatorConfig::default(), - blockifier_stateful_tx_validator: mock_blockifier_validator, - gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block), - }; - - let result = tokio::task::spawn_blocking(move || { - stateful_validator.extract_state_nonce_and_run_validations( - &executable_tx, - mempool_client, - runtime, - ) - }) - .await - .unwrap(); - assert_eq!(result, expected_result_as_stateful_transaction_result); -} - #[rstest] #[tokio::test] async fn test_instantiate_validator() { @@ -221,38 +133,31 @@ async fn test_skip_validate( #[case] contains_tx: bool, #[case] should_validate: bool, ) { - let mut mock_blockifier_validator = MockBlockifierStatefulValidatorTrait::new(); - mock_blockifier_validator - .expect_validate() - .withf(move |tx| tx.execution_flags.validate == should_validate) - .returning(|_| Ok(())); - mock_blockifier_validator.expect_block_info().return_const(BlockInfo::default()); - let mut mock_mempool_client = MockMempoolClient::new(); mock_mempool_client .expect_account_tx_in_pool_or_recent_block() .returning(move |_| Ok(contains_tx)); + mock_mempool_client.expect_validate_tx().returning(|_| Ok(())); let mempool_client = Arc::new(mock_mempool_client); - let runtime = tokio::runtime::Handle::current(); - + // Configure gateway state reader to return the provided sender/account nonce. let mut mock_gateway_fixed_block = MockGatewayFixedBlockStateReader::new(); mock_gateway_fixed_block.expect_get_nonce().return_once(move |_| Ok(sender_nonce)); - let mut stateful_validator = StatefulTransactionValidator { - config: StatefulTransactionValidatorConfig::default(), - blockifier_stateful_tx_validator: mock_blockifier_validator, + let stateful_validator = StatefulTransactionValidator { + config: StatefulTransactionValidatorConfig { + validate_resource_bounds: false, + ..Default::default() + }, + chain_info: ChainInfo::create_for_testing(), + state_reader_and_contract_manager: None, gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block), }; - tokio::task::spawn_blocking(move || { - let _ = stateful_validator.extract_state_nonce_and_run_validations( - &executable_tx, - mempool_client, - runtime, - ); - }) - .await - .unwrap(); + let skip_validate = stateful_validator + .run_pre_validation_checks(&executable_tx, sender_nonce, mempool_client) + .await + .unwrap(); + assert_eq!(skip_validate, !should_validate); } #[rstest] @@ -320,49 +225,38 @@ async fn validate_resource_bounds( #[case] tx_gas_price_per_unit: GasPrice, #[case] expected_result: Result<(), StarknetError>, ) { - let account_nonce = nonce!(0); let resource_bounds = ValidResourceBounds::AllResources(AllResourceBounds { l2_gas: ResourceBounds { max_price_per_unit: tx_gas_price_per_unit, ..Default::default() }, ..Default::default() }); let executable_tx = executable_invoke_tx(invoke_tx_args!(resource_bounds)); - let mut mock_blockifier_validator = MockBlockifierStatefulValidatorTrait::new(); - mock_blockifier_validator.expect_validate().return_once(|_| Ok(())); - mock_blockifier_validator.expect_block_info().return_const(BlockInfo { - gas_prices: GasPrices { - strk_gas_prices: GasPriceVector { - l2_gas_price: prev_l2_gas_price, + let mut mock_gateway_fixed_block = MockGatewayFixedBlockStateReader::new(); + mock_gateway_fixed_block.expect_get_block_info().return_once(move || { + Ok(BlockInfo { + gas_prices: GasPrices { + strk_gas_prices: GasPriceVector { + l2_gas_price: prev_l2_gas_price, + ..Default::default() + }, ..Default::default() }, ..Default::default() - }, - ..Default::default() + }) }); - let mock_gateway_fixed_block = MockGatewayFixedBlockStateReader::new(); - let mut stateful_validator = StatefulTransactionValidator { + let stateful_validator = StatefulTransactionValidator { config: StatefulTransactionValidatorConfig { validate_resource_bounds: true, min_gas_price_percentage, ..Default::default() }, - blockifier_stateful_tx_validator: mock_blockifier_validator, + chain_info: ChainInfo::create_for_testing(), + state_reader_and_contract_manager: None, gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block), }; - let result = tokio::task::spawn_blocking(move || { - let mut mempool_client = MockMempoolClient::new(); - mempool_client.expect_validate_tx().returning(|_| Ok(())); - stateful_validator.run_transaction_validations( - &executable_tx, - account_nonce, - Arc::new(mempool_client), - tokio::runtime::Handle::current(), - ) - }) - .await - .unwrap(); + let result = stateful_validator.validate_resource_bounds(&executable_tx).await; assert_eq!(result, expected_result); } @@ -392,7 +286,7 @@ async fn test_is_valid_nonce( nonce: tx_nonce, resource_bounds: ValidResourceBounds::create_for_testing(), )); - run_transaction_validation_test( + run_pre_validation_checks_test( executable_tx, account_nonce, max_allowed_nonce_gap, @@ -424,7 +318,7 @@ async fn test_reject_future_declares( FeatureContract::Empty(CairoVersion::Cairo1(RunnableCairo1::Casm)).get_class(), ), ); - run_transaction_validation_test(executable_tx, nonce!(account_nonce), 0, expected_result_code) + run_pre_validation_checks_test(executable_tx, nonce!(account_nonce), 0, expected_result_code) .await; } @@ -451,40 +345,35 @@ async fn test_deploy_account_nonce_validation( resource_bounds: ValidResourceBounds::create_for_testing(), )); - run_transaction_validation_test(executable_tx, nonce!(account_nonce), 0, expected_result_code) + run_pre_validation_checks_test(executable_tx, nonce!(account_nonce), 0, expected_result_code) .await; } -async fn run_transaction_validation_test( +async fn run_pre_validation_checks_test( executable_tx: AccountTransaction, account_nonce: Nonce, max_allowed_nonce_gap: u32, expected_result_code: Result<(), StarknetErrorCode>, ) { - let mut mock_blockifier_validator = MockBlockifierStatefulValidatorTrait::new(); - mock_blockifier_validator.expect_validate().return_once(|_| Ok(())); - mock_blockifier_validator.expect_block_info().return_const(BlockInfo::default()); - let mut mock_gateway_fixed_block = MockGatewayFixedBlockStateReader::new(); mock_gateway_fixed_block.expect_get_nonce().return_once(move |_| Ok(account_nonce)); - let mut stateful_validator = StatefulTransactionValidator { - config: StatefulTransactionValidatorConfig { max_allowed_nonce_gap, ..Default::default() }, - blockifier_stateful_tx_validator: mock_blockifier_validator, + let stateful_validator = StatefulTransactionValidator { + config: StatefulTransactionValidatorConfig { + max_allowed_nonce_gap, + validate_resource_bounds: false, + ..Default::default() + }, + chain_info: ChainInfo::create_for_testing(), + state_reader_and_contract_manager: None, gateway_fixed_block_state_reader: Box::new(mock_gateway_fixed_block), }; - let result = tokio::task::spawn_blocking(move || { - let mut mempool_client = MockMempoolClient::new(); - mempool_client.expect_validate_tx().returning(|_| Ok(())); - stateful_validator.run_transaction_validations( - &executable_tx, - account_nonce, - Arc::new(mempool_client), - tokio::runtime::Handle::current(), - ) - }) - .await - .unwrap() - .map_err(|err| err.code); + let mut mempool_client = MockMempoolClient::new(); + mempool_client.expect_validate_tx().returning(|_| Ok(())); + let result = stateful_validator + .run_pre_validation_checks(&executable_tx, account_nonce, Arc::new(mempool_client)) + .await + .map(|_| ()) + .map_err(|err| err.code); assert_eq!(result, expected_result_code); }