diff --git a/crates/starknet_integration_tests/Cargo.toml b/crates/starknet_integration_tests/Cargo.toml index 64c4cdf8e3f..1384ad7530c 100644 --- a/crates/starknet_integration_tests/Cargo.toml +++ b/crates/starknet_integration_tests/Cargo.toml @@ -15,6 +15,7 @@ blockifier.workspace = true cairo-lang-starknet-classes.workspace = true futures.workspace = true indexmap.workspace = true +infra_utils.workspace = true mempool_test_utils.workspace = true papyrus_common.workspace = true papyrus_consensus.workspace = true @@ -44,7 +45,6 @@ tracing.workspace = true [dev-dependencies] futures.workspace = true -infra_utils.workspace = true itertools.workspace = true pretty_assertions.workspace = true rstest.workspace = true diff --git a/crates/starknet_integration_tests/src/end_to_end_integration.rs b/crates/starknet_integration_tests/src/end_to_end_integration.rs new file mode 100644 index 00000000000..60108da02c2 --- /dev/null +++ b/crates/starknet_integration_tests/src/end_to_end_integration.rs @@ -0,0 +1,104 @@ +use infra_utils::run_until::run_until; +use mempool_test_utils::starknet_api_test_utils::{AccountId, MultiAccountTransactionGenerator}; +use papyrus_execution::execution_utils::get_nonce_at; +use papyrus_storage::state::StateStorageReader; +use papyrus_storage::StorageReader; +use starknet_api::block::BlockNumber; +use starknet_api::core::{ContractAddress, Nonce}; +use starknet_api::state::StateNumber; +use starknet_sequencer_node::test_utils::compilation::spawn_run_node; +use starknet_types_core::felt::Felt; +use tracing::info; + +use crate::integration_test_setup::IntegrationTestSetup; +use crate::utils::send_account_txs; + +/// Reads the latest block number from the storage. +fn get_latest_block_number(storage_reader: &StorageReader) -> BlockNumber { + let txn = storage_reader.begin_ro_txn().unwrap(); + txn.get_state_marker() + .expect("There should always be a state marker") + .prev() + .expect("There should be a previous block in the storage, set by the test setup") +} + +/// Reads an account nonce after a block number from storage. +fn get_account_nonce(storage_reader: &StorageReader, contract_address: ContractAddress) -> Nonce { + let block_number = get_latest_block_number(storage_reader); + let txn = storage_reader.begin_ro_txn().unwrap(); + let state_number = StateNumber::unchecked_right_after_block(block_number); + get_nonce_at(&txn, state_number, None, contract_address) + .expect("Should always be Ok(Some(Nonce))") + .expect("Should always be Some(Nonce)") +} + +/// Sample a storage until sufficiently many blocks have been stored. Returns an error if after +/// the given number of attempts the target block number has not been reached. +async fn await_block( + interval: u64, + target_block_number: BlockNumber, + max_attempts: usize, + storage_reader: &StorageReader, +) -> Result { + let condition = |&latest_block_number: &BlockNumber| latest_block_number >= target_block_number; + let get_latest_block_number_closure = || async move { get_latest_block_number(storage_reader) }; + + run_until(interval, max_attempts, get_latest_block_number_closure, condition, None) + .await + .ok_or(()) +} + +pub async fn end_to_end_integration(mut tx_generator: MultiAccountTransactionGenerator) { + const EXPECTED_BLOCK_NUMBER: BlockNumber = BlockNumber(15); + + info!("Running integration test setup."); + + // Creating the storage for the test. + let integration_test_setup = IntegrationTestSetup::new_from_tx_generator(&tx_generator).await; + + info!("Running sequencer node."); + let node_run_handle = spawn_run_node(integration_test_setup.node_config_path).await; + + // Wait for the node to start. + match integration_test_setup.is_alive_test_client.await_alive(5000, 50).await { + Ok(_) => {} + Err(_) => panic!("Node is not alive."), + } + + info!("Running integration test simulator."); + + let send_rpc_tx_fn = + &mut |rpc_tx| integration_test_setup.add_tx_http_client.assert_add_tx_success(rpc_tx); + + const ACCOUNT_ID_0: AccountId = 0; + let n_txs = 50; + let sender_address = tx_generator.account_with_id(ACCOUNT_ID_0).sender_address(); + info!("Sending {n_txs} txs."); + let tx_hashes = send_account_txs(tx_generator, ACCOUNT_ID_0, n_txs, send_rpc_tx_fn).await; + + info!("Awaiting until {EXPECTED_BLOCK_NUMBER} blocks have been created."); + + let (batcher_storage_reader, _) = + papyrus_storage::open_storage(integration_test_setup.batcher_storage_config) + .expect("Failed to open batcher's storage"); + + match await_block(5000, EXPECTED_BLOCK_NUMBER, 15, &batcher_storage_reader).await { + Ok(_) => {} + Err(_) => panic!("Did not reach expected block number."), + } + + info!("Shutting the node down."); + node_run_handle.abort(); + let res = node_run_handle.await; + assert!( + res.expect_err("Node should have been stopped.").is_cancelled(), + "Node should have been stopped." + ); + + info!("Verifying tx sender account nonce."); + let expected_nonce_value = tx_hashes.len() + 1; + let expected_nonce = + Nonce(Felt::from_hex_unchecked(format!("0x{:X}", expected_nonce_value).as_str())); + let nonce = get_account_nonce(&batcher_storage_reader, sender_address); + assert_eq!(nonce, expected_nonce); +} diff --git a/crates/starknet_integration_tests/src/lib.rs b/crates/starknet_integration_tests/src/lib.rs index 76d06d00041..d2555c76bdd 100644 --- a/crates/starknet_integration_tests/src/lib.rs +++ b/crates/starknet_integration_tests/src/lib.rs @@ -1,4 +1,5 @@ pub mod config_utils; +pub mod end_to_end_integration; pub mod flow_test_setup; pub mod integration_test_setup; pub mod state_reader; diff --git a/crates/starknet_integration_tests/tests/end_to_end_integration_test.rs b/crates/starknet_integration_tests/tests/end_to_end_integration_test.rs index fdb2d8f082a..f36d95aae20 100644 --- a/crates/starknet_integration_tests/tests/end_to_end_integration_test.rs +++ b/crates/starknet_integration_tests/tests/end_to_end_integration_test.rs @@ -1,123 +1,23 @@ -use infra_utils::run_until::run_until; -use mempool_test_utils::starknet_api_test_utils::{AccountId, MultiAccountTransactionGenerator}; -use papyrus_execution::execution_utils::get_nonce_at; -use papyrus_storage::state::StateStorageReader; -use papyrus_storage::StorageReader; +use mempool_test_utils::starknet_api_test_utils::MultiAccountTransactionGenerator; use rstest::{fixture, rstest}; -use starknet_api::block::BlockNumber; -use starknet_api::core::{ContractAddress, Nonce}; -use starknet_api::state::StateNumber; -use starknet_integration_tests::integration_test_setup::IntegrationTestSetup; +use starknet_integration_tests::end_to_end_integration::end_to_end_integration; use starknet_integration_tests::utils::{ create_integration_test_tx_generator, run_integration_test, - send_account_txs, }; use starknet_sequencer_infra::trace_util::configure_tracing; -use starknet_sequencer_node::test_utils::compilation::spawn_run_node; -use starknet_types_core::felt::Felt; -use tracing::info; #[fixture] fn tx_generator() -> MultiAccountTransactionGenerator { create_integration_test_tx_generator() } -/// Reads the latest block number from the storage. -fn get_latest_block_number(storage_reader: &StorageReader) -> BlockNumber { - let txn = storage_reader.begin_ro_txn().unwrap(); - txn.get_state_marker() - .expect("There should always be a state marker") - .prev() - .expect("There should be a previous block in the storage, set by the test setup") -} - -/// Reads an account nonce after a block number from storage. -fn get_account_nonce(storage_reader: &StorageReader, contract_address: ContractAddress) -> Nonce { - let block_number = get_latest_block_number(storage_reader); - let txn = storage_reader.begin_ro_txn().unwrap(); - let state_number = StateNumber::unchecked_right_after_block(block_number); - get_nonce_at(&txn, state_number, None, contract_address) - .expect("Should always be Ok(Some(Nonce))") - .expect("Should always be Some(Nonce)") -} - -/// Sample a storage until sufficiently many blocks have been stored. Returns an error if after -/// the given number of attempts the target block number has not been reached. -async fn await_block( - interval: u64, - target_block_number: BlockNumber, - max_attempts: usize, - storage_reader: &StorageReader, -) -> Result { - let condition = |&latest_block_number: &BlockNumber| latest_block_number >= target_block_number; - let get_latest_block_number_closure = || async move { get_latest_block_number(storage_reader) }; - - run_until(interval, max_attempts, get_latest_block_number_closure, condition, None) - .await - .ok_or(()) -} - #[rstest] #[tokio::test] -async fn test_end_to_end_integration(mut tx_generator: MultiAccountTransactionGenerator) { +async fn test_end_to_end_integration(tx_generator: MultiAccountTransactionGenerator) { if !run_integration_test() { return; } - - const EXPECTED_BLOCK_NUMBER: BlockNumber = BlockNumber(15); - configure_tracing().await; - info!("Running integration test setup."); - - // Creating the storage for the test. - - let integration_test_setup = IntegrationTestSetup::new_from_tx_generator(&tx_generator).await; - - info!("Running sequencer node."); - let node_run_handle = spawn_run_node(integration_test_setup.node_config_path).await; - - // Wait for the node to start. - match integration_test_setup.is_alive_test_client.await_alive(5000, 50).await { - Ok(_) => {} - Err(_) => panic!("Node is not alive."), - } - - info!("Running integration test simulator."); - - let send_rpc_tx_fn = - &mut |rpc_tx| integration_test_setup.add_tx_http_client.assert_add_tx_success(rpc_tx); - - const ACCOUNT_ID_0: AccountId = 0; - - let n_txs = 50; - let sender_address = tx_generator.account_with_id(ACCOUNT_ID_0).sender_address(); - info!("Sending {n_txs} txs."); - let tx_hashes = send_account_txs(tx_generator, ACCOUNT_ID_0, n_txs, send_rpc_tx_fn).await; - - info!("Awaiting until {EXPECTED_BLOCK_NUMBER} blocks have been created."); - - let (batcher_storage_reader, _) = - papyrus_storage::open_storage(integration_test_setup.batcher_storage_config) - .expect("Failed to open batcher's storage"); - - match await_block(5000, EXPECTED_BLOCK_NUMBER, 15, &batcher_storage_reader).await { - Ok(_) => {} - Err(_) => panic!("Did not reach expected block number."), - } - - info!("Shutting the node down."); - node_run_handle.abort(); - let res = node_run_handle.await; - assert!( - res.expect_err("Node should have been stopped.").is_cancelled(), - "Node should have been stopped." - ); - - info!("Verifying tx sender account nonce."); - let expected_nonce_value = tx_hashes.len() + 1; - let expected_nonce = - Nonce(Felt::from_hex_unchecked(format!("0x{:X}", expected_nonce_value).as_str())); - let nonce = get_account_nonce(&batcher_storage_reader, sender_address); - assert_eq!(nonce, expected_nonce); + end_to_end_integration(tx_generator).await; }