diff --git a/crates/central_systest_blobs/resources/blob_file_generation b/crates/central_systest_blobs/resources/blob_file_generation index 9d607966b72..3cacc0b93c9 100644 --- a/crates/central_systest_blobs/resources/blob_file_generation +++ b/crates/central_systest_blobs/resources/blob_file_generation @@ -1 +1 @@ -11 \ No newline at end of file +12 \ No newline at end of file diff --git a/crates/central_systest_blobs/resources/preconfirmed_block.json b/crates/central_systest_blobs/resources/preconfirmed_block.json index 1d1fe10fcb0..9815f198a00 100644 --- a/crates/central_systest_blobs/resources/preconfirmed_block.json +++ b/crates/central_systest_blobs/resources/preconfirmed_block.json @@ -1,5 +1,5 @@ { - "block_number": 6, + "block_number": 13, "pre_confirmed_block": { "l1_da_mode": "CALLDATA", "l1_data_gas_price": { @@ -17,16 +17,16 @@ "sequencer_address": "0x1000", "starknet_version": "0.14.3", "status": "PRE_CONFIRMED", - "timestamp": 1006, + "timestamp": 1013, "transaction_receipts": [ { - "actual_fee": "0x158bf1", + "actual_fee": "0xff313", "events": [ { "data": [ "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", "0x1000", - "0x158bf1", + "0xff313", "0x0" ], "from_address": "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83", @@ -38,58 +38,47 @@ "execution_resources": { "builtin_instance_counter": { "pedersen_builtin": 4, - "poseidon_builtin": 17, + "poseidon_builtin": 15, "range_check_builtin": 90 }, "data_availability": { "l1_data_gas": 0, - "l1_gas": 4095, + "l1_gas": 1652, "l2_gas": 0 }, "n_memory_holes": 0, - "n_steps": 4403, + "n_steps": 4381, "total_gas_consumed": { "l1_data_gas": 0, - "l1_gas": 4646, - "l2_gas": 1407435 + "l1_gas": 1652, + "l2_gas": 1043615 } }, "execution_status": "SUCCEEDED", "l2_to_l1_messages": [], - "transaction_hash": "0x69baeec4f5fd1665ef711e66f55b891ea8c8427d2cacb2eb39e3b66d320ae0d", + "transaction_hash": "0x4acc6e7cb93683ae3a42ed499788f2d0143e8c3357315e1ecaad4e65f6dd479", "transaction_index": 0 } ], "transaction_state_diffs": [ { "declared_classes": [], - "deployed_contracts": [ - { - "address": "0x4021329459ab2dacdd89c397996da9214211fa2abf2cda1bfb8f4cffe6db51f", - "class_hash": "0x4b0dc3014cc21eeeeba97610d8fb3eaf61c428c513a2e9bfcf1b7beb9cb99c0" - } - ], + "deployed_contracts": [], "migrated_compiled_classes": [], "nonces": { - "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955": "0x5" + "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955": "0xc" }, "old_declared_contracts": [], "replaced_classes": [], "storage_diffs": { - "0x4021329459ab2dacdd89c397996da9214211fa2abf2cda1bfb8f4cffe6db51f": [ - { - "key": "0x1275130f95dda36bcbb6e9d28796c1d7e10b6e9fd5ed083e0ede4b12f613528", - "value": "0x2" - } - ], "0x6bd1d71a2fb67a567618584ca31da288dbc2e1a8421e4045e05f52c19bfab83": [ { "key": "0x6fba6554adab51d0272b896b6f41768bd0491e5ad59c39fab38e65767974793", - "value": "0xffffffffffffffffffffffff92bbce2b" + "value": "0xffffffffffffffffffffffff924412b1" }, { "key": "0x723973208639b7839ce298f7ffea61e3f9533872defd7abdb91023db4658812", - "value": "0x6d4431d4" + "value": "0x6dbbed4e" } ] } @@ -100,18 +89,14 @@ "account_deployment_data": [], "calldata": [ "0x1", - "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", - "0x2730079d734ee55315f4f141eaed376bddd8c2133523d223a344c5604e0f7f8", - "0x6", - "0x4b0dc3014cc21eeeeba97610d8fb3eaf61c428c513a2e9bfcf1b7beb9cb99c0", - "0x0", + "0x3d275d3e01ff9dca442ca4aa77b00d6581ad890e3df054932a6851a5166e94d", + "0x4ea6d2b84c4aea3baab8c031143fcd1fdf95debad5f888784f8db17e1c17f4", "0x2", - "0x1", - "0x1", - "0x0" + "0x4021329459ab2dacdd89c397996da9214211fa2abf2cda1bfb8f4cffe6db51f", + "0x2000" ], "fee_data_availability_mode": 0, - "nonce": "0x4", + "nonce": "0xb", "nonce_data_availability_mode": 0, "paymaster_data": [], "proof_facts": [], @@ -131,11 +116,11 @@ }, "sender_address": "0xf99e7cdfbcce0bf14ce17e4c57fd2d12ad1bca5fc8e46a9fbafc36b59a9955", "signature": [ - "0x24b3b8fc254a82c56f7c592ebaf989fb2551228ac0f8d7fa2b0cb43ea94dc2a", - "0x70feac66dc56daf6857c6a34a4b547ca653a96fb3d674b180ce403684e8dbba" + "0x47fc4402ccfebfe5e1a8af95ee4de99932534b43d9161e7024847382c022926", + "0x71c9ccc594f6d54d88b649a51dc167c3df0423d4a3f95a0e1b85f2560e78588" ], "tip": "0x0", - "transaction_hash": "0x69baeec4f5fd1665ef711e66f55b891ea8c8427d2cacb2eb39e3b66d320ae0d", + "transaction_hash": "0x4acc6e7cb93683ae3a42ed499788f2d0143e8c3357315e1ecaad4e65f6dd479", "type": "INVOKE_FUNCTION", "version": "0x3" } diff --git a/crates/central_systest_blobs/src/cende_blob_regression_test.rs b/crates/central_systest_blobs/src/cende_blob_regression_test.rs index 97afa803fd5..c22dff48768 100644 --- a/crates/central_systest_blobs/src/cende_blob_regression_test.rs +++ b/crates/central_systest_blobs/src/cende_blob_regression_test.rs @@ -44,6 +44,7 @@ use google_cloud_storage::http::objects::get::GetObjectRequest; use google_cloud_storage::http::objects::upload::{Media, UploadObjectRequest, UploadType}; use google_cloud_storage::http::Error as GcsError; use mockall::predicate::eq; +use starknet_api::abi::abi_utils::selector_from_name; use starknet_api::block::{BlockHash, BlockHashAndNumber, BlockInfo, BlockNumber, BlockTimestamp}; use starknet_api::block_hash::block_hash_calculator::{ calculate_block_commitments, @@ -158,7 +159,11 @@ static NON_TRIVIAL_RESOURCE_BOUNDS: LazyLock = }, }); -type TxPair = (ExecutableAccountTx, InternalConsensusTransaction); +struct TxData { + executable: ExecutableAccountTx, + internal: InternalConsensusTransaction, + should_revert: bool, +} /// ID of the current blobs file. fn current_generation() -> usize { @@ -249,7 +254,7 @@ struct BlobFactory { blocks: Vec, // Transactions for the next block. - next_txs: Vec, + next_txs: Vec, // Context. nonce_manager: NonceManager, @@ -310,11 +315,18 @@ impl BlobFactory { .unwrap(); let mut transactions_with_receipts = Vec::new(); // Consume the transactions list (next block starts empty). - for (executable, internal) in std::mem::take(&mut self.next_txs).into_iter() { + for (tx_index, TxData { executable, internal, should_revert }) in + std::mem::take(&mut self.next_txs).into_iter().enumerate() + { let (execution_info, _state_changes) = executor .execute(&BlockifierTx::new_for_sequencing(ExecutableTx::Account(executable))) .unwrap(); - assert!(!execution_info.is_reverted(), "Got a reverted tx: {execution_info:?}"); + assert_eq!( + execution_info.is_reverted(), + should_revert, + "Transaction at index {tx_index} in block {block_number}: result does not match \ + expected (should_revert={should_revert}): {execution_info:?}" + ); transactions_with_receipts .push(InternalTransactionWithReceipt { transaction: internal, execution_info }); @@ -511,7 +523,11 @@ impl BlobFactory { .returning(move |_| Ok(Some(contract.get_class()))); // Return the transactions. - self.next_txs.push((executable.into(), internal_tx)); + self.next_txs.push(TxData { + executable: executable.into(), + internal: internal_tx, + should_revert: false, + }); } fn make_free_deploy_account_tx(&mut self, account: FeatureContract) -> ContractAddress { @@ -563,7 +579,11 @@ impl BlobFactory { tx: without_hash, tx_hash, }); - self.next_txs.push((executable.into(), internal)); + self.next_txs.push(TxData { + executable: executable.into(), + internal, + should_revert: false, + }); contract_address } @@ -573,6 +593,7 @@ impl BlobFactory { function_name: &str, calldata: &[Felt], with_fee_charge: bool, + should_revert: bool, ) { let nonce = self.nonce_manager.next(*OPERATOR_ADDRESS); let resource_bounds = if with_fee_charge { @@ -608,7 +629,7 @@ impl BlobFactory { tx: without_hash, tx_hash, }); - self.next_txs.push((executable.into(), internal)); + self.next_txs.push(TxData { executable: executable.into(), internal, should_revert }); } fn make_operator_deploy_tx( @@ -637,6 +658,7 @@ impl BlobFactory { "deploy_contract", &calldata, with_fee_charge, + false, // should not revert ); contract_address } @@ -664,7 +686,7 @@ impl BlobFactory { /// no commitment is computed. fn make_preconfirmed_block_from_remaining_txs( block_context: BlockContext, - txs: Vec, + txs: Vec, mut state: DictStateReader, ) -> CendeWritePreconfirmedBlock { let block_info = block_context.block_info().clone(); @@ -672,7 +694,9 @@ impl BlobFactory { let mut transaction_receipts = vec![]; let mut transaction_state_diffs = vec![]; - for (tx_index, (executable, internal)) in txs.into_iter().enumerate() { + for (tx_index, TxData { executable, internal, should_revert }) in + txs.into_iter().enumerate() + { let tx_hash = match &internal { InternalConsensusTransaction::RpcTransaction(tx) => tx.tx_hash, InternalConsensusTransaction::L1Handler(_) => { @@ -684,6 +708,12 @@ impl BlobFactory { let execution_info = BlockifierAccountTx::new_for_sequencing(executable) .execute(&mut tx_state, &block_context) .unwrap(); + assert_eq!( + execution_info.is_reverted(), + should_revert, + "Transaction at index {tx_index}: result does not match expected \ + (should_revert={should_revert}): {execution_info:?}" + ); let state_changes = tx_state.to_state_diff().unwrap(); @@ -829,19 +859,9 @@ async fn test_make_data() { let mut blob_factory = BlobFactory::new(); let chain_info = OsChainInfo::from(&blob_factory.chain_info).to_hex_map(); - // Create the list of transactions to be included in the blobs: - // 1. bootstrap declare of an ERC20 contract. - // 2. bootstrap declare of an account with real validate. - // 3. deploy account (with zero fees). - // 4. deploy ERC20 contract from the account (with zero fees), while minting some tokens to the - // sender account. - // (from this point - all txs include non-zero fees, and no more bootstrap declares) - // 5. declare the test contract. - // 6. deploy the test contract. - // 7. deploy another instance of the test contract. - // TODO(Dori): the rest of the txs. - // 8. invoke the test contract: something with a state change. - // 9. invoke the test contract: test syscalls. + // Create the list of transactions to be included in the blobs. + // Block closing point is arbitrary, although it is preferable not to close after the last tx + // (to ensure the preconfirmed block is not empty). let erc20_contract = FeatureContract::ERC20(CairoVersion::Cairo1(RunnableCairo1::Casm)); let account_with_real_validate = FeatureContract::AccountWithRealValidate(RunnableCairo1::Casm); let test_contract = FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Casm)); @@ -871,17 +891,79 @@ async fn test_make_data() { blob_factory.close_block().await; blob_factory.make_declare_tx(test_contract, Some(*OPERATOR_ADDRESS)); blob_factory.close_block().await; - let _test_contract_address_0 = blob_factory.make_operator_deploy_tx( + let test_contract_address_0 = blob_factory.make_operator_deploy_tx( test_contract, calldata![Felt::ZERO, Felt::ZERO], true, // charge fee ); blob_factory.close_block().await; - let _test_contract_address_1 = blob_factory.make_operator_deploy_tx( + let test_contract_address_1 = blob_factory.make_operator_deploy_tx( test_contract, calldata![Felt::ONE, Felt::ONE], true, // charge fee ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_0, + "test_increment", + &[Felt::ZERO; 3], + true, // charge fee + false, // should not revert + ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_1, + "test_storage_read_write", + &[Felt::ONE, Felt::TWO], + true, // charge fee + false, // should not revert + ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_1, + "test_storage_write", + &[Felt::THREE, Felt::ONE], + true, // charge fee + false, // should not revert + ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_0, + "write_and_revert", + &[Felt::from(7u8), Felt::ONE], + true, // charge fee + true, // should revert + ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_1, + "test_call_contract", + &[ + **test_contract_address_0, + selector_from_name("test_storage_read_write").0, + Felt::TWO, + Felt::from(0x1000), + Felt::from(0x1000), + ], + true, // charge fee + false, // should not revert + ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_1, + "write_1", + &[Felt::TWO], + true, // charge fee + false, // should not revert + ); + blob_factory.close_block().await; + blob_factory.make_operator_invoke_tx( + test_contract_address_0, + "catch_write_revert_panic", + &[**test_contract_address_1, Felt::from(0x2000)], + true, // charge fee + false, // should not revert (inner error is caught) + ); let (blobs, preconfirmed_block) = blob_factory.finalize().await; expect_file![CHAIN_INFO_PATH].assert_eq(&serde_json::to_string_pretty(&chain_info).unwrap());