diff --git a/crates/blockifier_reexecution/resources/raw_rpc_json_objects/transactions.json b/crates/blockifier_reexecution/resources/raw_rpc_json_objects/transactions.json index fbdfc3e4aa..f29c46ae04 100644 --- a/crates/blockifier_reexecution/resources/raw_rpc_json_objects/transactions.json +++ b/crates/blockifier_reexecution/resources/raw_rpc_json_objects/transactions.json @@ -69,5 +69,119 @@ "transaction_hash": "0xa7c7db686c7f756ceb7ca85a759caef879d425d156da83d6a836f86851983", "type": "INVOKE", "version": "0x3" + }, + "deploy_account_v1": { + "transaction_hash": "0x2a2e13cd94f911ea18c20a81e853314e37de58d49d13aa3a92370accd4338e8", + "type": "DEPLOY_ACCOUNT", + "version": "0x1", + "nonce": "0x0", + "max_fee": "0xb8deede8a5b", + "contract_address_salt": "0x2a810d00f7f876923cbde32f4395ebb4617dfd1f9a166af5bd038d796192cf3", + "class_hash": "0x13bfe114fb1cf405bfc3a7f8dbe2d91db146c17521d40dcf57e16d6b59fa8e6", + "constructor_calldata": [ + "0x2a810d00f7f876923cbde32f4395ebb4617dfd1f9a166af5bd038d796192cf3" + ], + "signature": [ + "0x6911f752999d2437a273d281855c321160f8d07df2a165b48522bc4fecbe798", + "0x2a51b2b55391d0d37ffa181d2bc694452a1922797ecd50192debf0dd41fa655", + "0x816dd0297efc55dc1e7559020a3a825e81ef734b558f03c83325d4da7e6253", + "0x2", + "0xeb594bf23d46d2ad1b755a0569532bda", + "0x676276ce46184eb3ef4eb15eacaa4c9", + "0x2e010f8bae599837e2be85fc727445e8", + "0xb5d30c808becca115c58dbcbc570ef1", + "0x0", + "0x0", + "0x0", + "0x0", + "0x534e5f4d41494e", + "0x208a971688739dc3e4ae79d2e953702ee176dd33b96ff2f3fd0bbe7b937e77d", + "0x23d05847f819ad713e5d05f3bcc7cd61476a1be915fcc743d2dd3217e666ca" + ] + }, + "deploy_account_v3": { + "transaction_hash": "0x4422b1300d2a55fb0138f8a97819d6dc04fe1d57e332b657ce8167e6572c958", + "type": "DEPLOY_ACCOUNT", + "version": "0x3", + "nonce": "0x0", + "contract_address_salt": "0x7a83b056935d1b135d0a41d4c38f1efa149834829fdf216a43e21ca7e1901e8", + "class_hash": "0x29927c8af6bccf3f6fda035981e765a7bdbf18a2dc0d630494f8758aa908e2b", + "constructor_calldata": [ + "0x7a83b056935d1b135d0a41d4c38f1efa149834829fdf216a43e21ca7e1901e8", + "0x0" + ], + "signature": [ + "0x6be7f4707ff4427bbfbb8d55c89366a7957dc8e992c93a6170bc59a8849dcc", + "0x4c821cf2ac5413f45ea651513c620fd8b30ecdb2a3ba505c087771a1c94c0a7" + ], + "resource_bounds": { + "l1_gas": { + "max_amount": "0x18", + "max_price_per_unit": "0x5e95b9f35336" + }, + "l2_gas": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "nonce_data_availability_mode": "L1", + "fee_data_availability_mode": "L1" + }, + "declare_v1": { + "transaction_hash": "0x4e9239ebc8512a508f21620cf570e9d938f31190770224d0f6d33ab93fefaf4", + "type": "DECLARE", + "version": "0x1", + "nonce": "0x5a", + "max_fee": "0xb1a2bc2ec50000", + "class_hash": "0x58e505d461c0cff95e868e634d37467170816e6bb9540fffd264b4bddb8c914", + "sender_address": "0x2e2226d64eb35c27f72beb528221884046b2ee1ef96b659aeb1351c4daad971", + "signature": [ + "0x238cc6ec87d76f27e6607ce14639be4140fe174a5dc20ed755fec0e902dfa0", + "0x1228cc33553d503043c885c2316e33ec4375990c5c95234fefea1b844a5a8a8" + ] + }, + "declare_v2": { + "transaction_hash": "0x409d159fbcab271ffc1693b08d9198f4bbff7e344e1624dadc2d9a67a960226", + "type": "DECLARE", + "version": "0x2", + "nonce": "0x15", + "max_fee": "0x9187da08b6a5", + "class_hash": "0x3d311ba322e1f900d669586b191a2a82c50f6cb850563a8e1c01c7bac9be7b0", + "sender_address": "0x42f636eba44ebcd94a9b92dac2f9560d3c654b395771f678429ca610d92570d", + "signature": [ + "0x286b65fa170a79f279a48f0c6f7fd08417dc459accab3d421aea6ac7e2a2594", + "0x5c560af73dd5c58969e2555382251806ffdfd0dd27825185ea46823eb101979" + ], + "compiled_class_hash": "0x1f3b8bd3cb7f4736fd5294cc005740b4721279bd79254e9c49c3ed23c462c63" + }, + "declare_v3": { + "transaction_hash": "0x3ab43c0913f95b901b49ed1aa6009b31ebe0ad7ba62da49fc6de7f3854b496f", + "type": "DECLARE", + "version": "0x3", + "nonce": "0x14c", + "class_hash": "0x5c321464adb6f82da223a5ebab47e84ff39bc6845cad1966eceb3b7603e71b1", + "sender_address": "0x1b23aa51d5569b9441d60ff575bf735345123304c4c3a303ee91670dccb4ac9", + "signature": [ + "0x67e32d3a23a66930ee5f14459cfeccc871fb2517ab4747e8b764348821d0422", + "0x47c9f401a824b34e91ba416f8a8721515fca00be3d09f970cdbd86e3c9ad149" + ], + "compiled_class_hash": "0x495579d0129be95d8fe95667e1df7790e9737784fb7fd9541814425018bd806", + "resource_bounds": { + "l1_gas": { + "max_amount": "0xb3d3", + "max_price_per_unit": "0xd7bdb9e5f316" + }, + "l2_gas": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "account_deployment_data": [], + "nonce_data_availability_mode": "L1", + "fee_data_availability_mode": "L1" } } \ No newline at end of file diff --git a/crates/blockifier_reexecution/src/state_reader/raw_rpc_json_test.rs b/crates/blockifier_reexecution/src/state_reader/raw_rpc_json_test.rs index ba67dffaef..268315d220 100644 --- a/crates/blockifier_reexecution/src/state_reader/raw_rpc_json_test.rs +++ b/crates/blockifier_reexecution/src/state_reader/raw_rpc_json_test.rs @@ -4,7 +4,12 @@ use pretty_assertions::assert_eq; use rstest::{fixture, rstest}; use starknet_api::block::BlockNumber; use starknet_api::test_utils::read_json_file; -use starknet_api::transaction::{InvokeTransaction, Transaction}; +use starknet_api::transaction::{ + DeclareTransaction, + DeployAccountTransaction, + InvokeTransaction, + Transaction, +}; use starknet_core::types::ContractClass; use starknet_gateway::rpc_objects::BlockHeader; @@ -65,3 +70,52 @@ fn deserialize_invoke_txs() { assert_matches!(invoke_tx_v3, Transaction::Invoke(InvokeTransaction::V3(..))); } + +#[rstest] +fn deserialize_deploy_account_txs( + #[values("deploy_account_v1", "deploy_account_v3")] deploy_account_version: &str, +) { + let deploy_account = deserialize_transaction_json_to_starknet_api_tx( + read_json_file("raw_rpc_json_objects/transactions.json")[deploy_account_version].clone(), + ) + .unwrap_or_else(|_| panic!("Failed to deserialize {deploy_account_version} tx")); + + match deploy_account_version { + "deploy_account_v1" => { + assert_matches!( + deploy_account, + Transaction::DeployAccount(DeployAccountTransaction::V1(..)) + ) + } + "deploy_account_v3" => { + assert_matches!( + deploy_account, + Transaction::DeployAccount(DeployAccountTransaction::V3(..)) + ) + } + _ => panic!("Unknown scenario '{deploy_account_version}'"), + } +} + +#[rstest] +fn deserialize_declare_txs( + #[values("declare_v1", "declare_v2", "declare_v3")] declare_version: &str, +) { + let declare_tx = deserialize_transaction_json_to_starknet_api_tx( + read_json_file("raw_rpc_json_objects/transactions.json")[declare_version].clone(), + ) + .unwrap_or_else(|_| panic!("Failed to deserialize {declare_version} tx")); + + match declare_version { + "declare_v1" => { + assert_matches!(declare_tx, Transaction::Declare(DeclareTransaction::V1(..))) + } + "declare_v2" => { + assert_matches!(declare_tx, Transaction::Declare(DeclareTransaction::V2(..))) + } + "declare_v3" => { + assert_matches!(declare_tx, Transaction::Declare(DeclareTransaction::V3(..))) + } + _ => panic!("Unknown scenario '{declare_version}'"), + } +} diff --git a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs index fb2565a5d4..51ef7a5129 100644 --- a/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs +++ b/crates/blockifier_reexecution/src/state_reader/rpc_https_test.rs @@ -6,7 +6,12 @@ use starknet_api::block::{BlockNumber, StarknetVersion}; use starknet_api::class_hash; use starknet_api::core::ClassHash; use starknet_api::test_utils::read_json_file; -use starknet_api::transaction::Transaction; +use starknet_api::transaction::{ + DeclareTransaction, + DeployAccountTransaction, + Transaction, + TransactionVersion, +}; use starknet_core::types::ContractClass::{Legacy, Sierra}; use crate::state_reader::compile::legacy_to_contract_class_v0; @@ -20,6 +25,26 @@ const EXAMPLE_BLOCK_NUMBER: u64 = 700000; const EXAMPLE_CONTACT_CLASS_HASH: &str = "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e"; +const EXAMPLE_DEPLOY_ACCOUNT_V1_BLOCK_NUMBER: u64 = 837408; +const EXAMPLE_DEPLOY_ACCOUNT_V1_TX_HASH: &str = + "0x02a2e13cd94f911ea18c20a81e853314e37de58d49d13aa3a92370accd4338e8"; + +const EXAMPLE_DEPLOY_ACCOUNT_V3_BLOCK_NUMBER: u64 = 837792; +const EXAMPLE_DEPLOY_ACCOUNT_V3_TX_HASH: &str = + "0x04422b1300d2a55fb0138f8a97819d6dc04fe1d57e332b657ce8167e6572c958"; + +const EXAMPLE_DECLARE_V1_BLOCK_NUMBER: u64 = 837461; +const EXAMPLE_DECLARE_V1_TX_HASH: &str = + "0x04e9239ebc8512a508f21620cf570e9d938f31190770224d0f6d33ab93fefaf4"; + +const EXAMPLE_DECLARE_V2_BLOCK_NUMBER: u64 = 822636; +const EXAMPLE_DECLARE_V2_TX_HASH: &str = + "0x0409d159fbcab271ffc1693b08d9198f4bbff7e344e1624dadc2d9a67a960226"; + +const EXAMPLE_DECLARE_V3_BLOCK_NUMBER: u64 = 825013; +const EXAMPLE_DECLARE_V3_TX_HASH: &str = + "0x03ab43c0913f95b901b49ed1aa6009b31ebe0ad7ba62da49fc6de7f3854b496f"; + #[fixture] pub fn test_block_number() -> BlockNumber { BlockNumber(EXAMPLE_BLOCK_NUMBER) @@ -95,11 +120,62 @@ pub fn test_get_tx_hashes(test_state_reader: TestStateReader, test_block_number: } #[rstest] -pub fn test_get_tx_by_hash(test_state_reader: TestStateReader) { +pub fn test_get_invoke_tx_by_hash(test_state_reader: TestStateReader) { let actual_tx = test_state_reader.get_tx_by_hash(EXAMPLE_INVOKE_TX_HASH).unwrap(); assert_matches!(actual_tx, Transaction::Invoke(..)); } +#[rstest] +#[case( + EXAMPLE_DEPLOY_ACCOUNT_V1_BLOCK_NUMBER, + EXAMPLE_DEPLOY_ACCOUNT_V1_TX_HASH, + TransactionVersion::ONE +)] +#[case( + EXAMPLE_DEPLOY_ACCOUNT_V3_BLOCK_NUMBER, + EXAMPLE_DEPLOY_ACCOUNT_V3_TX_HASH, + TransactionVersion::THREE +)] +pub fn test_get_deploy_account_tx_by_hash( + #[case] block_number: u64, + #[case] tx_hash: &str, + #[case] version: TransactionVersion, +) { + // Create StateReader with block number that contain the deploy account tx. + let state_reader = TestStateReader::new_for_testing(BlockNumber(block_number)); + let actual_tx = state_reader.get_tx_by_hash(tx_hash).unwrap(); + if version == TransactionVersion::ONE { + assert_matches!(actual_tx, Transaction::DeployAccount(DeployAccountTransaction::V1(..))) + } else if version == TransactionVersion::THREE { + assert_matches!(actual_tx, Transaction::DeployAccount(DeployAccountTransaction::V3(..))) + } else { + panic!("Invalid version") + } +} + +#[rstest] +#[case(EXAMPLE_DECLARE_V1_BLOCK_NUMBER, EXAMPLE_DECLARE_V1_TX_HASH, TransactionVersion::ONE)] +#[case(EXAMPLE_DECLARE_V2_BLOCK_NUMBER, EXAMPLE_DECLARE_V2_TX_HASH, TransactionVersion::TWO)] +#[case(EXAMPLE_DECLARE_V3_BLOCK_NUMBER, EXAMPLE_DECLARE_V3_TX_HASH, TransactionVersion::THREE)] +pub fn test_get_declare_tx_by_hash( + #[case] block_number: u64, + #[case] tx_hash: &str, + #[case] expected_version: TransactionVersion, +) { + // Create StateReader with block number that contain the declare tx. + let state_reader = TestStateReader::new_for_testing(BlockNumber(block_number)); + let actual_tx = state_reader.get_tx_by_hash(tx_hash).unwrap(); + if expected_version == TransactionVersion::ONE { + assert_matches!(actual_tx, Transaction::Declare(DeclareTransaction::V1(..))) + } else if expected_version == TransactionVersion::TWO { + assert_matches!(actual_tx, Transaction::Declare(DeclareTransaction::V2(..))) + } else if expected_version == TransactionVersion::THREE { + assert_matches!(actual_tx, Transaction::Declare(DeclareTransaction::V3(..))) + } else { + panic!("Invalid expected version") + } +} + #[rstest] pub fn test_get_statediff_rpc(test_state_reader: TestStateReader) { assert!(test_state_reader.get_state_diff().is_ok()); diff --git a/crates/blockifier_reexecution/src/state_reader/serde_utils.rs b/crates/blockifier_reexecution/src/state_reader/serde_utils.rs index 9e02fc90f7..568da2b3b1 100644 --- a/crates/blockifier_reexecution/src/state_reader/serde_utils.rs +++ b/crates/blockifier_reexecution/src/state_reader/serde_utils.rs @@ -10,6 +10,25 @@ use starknet_api::transaction::{ use crate::state_reader::test_state_reader::ReexecutionResult; +/// In old transaction, the resource bounds names are lowercase. +/// need to convert to uppercase for deserialization to work. +pub fn upper_case_resource_bounds_names(raw_transaction: &mut Value) { + let resource_bounds = raw_transaction + .get_mut("resource_bounds") + .expect("tx should contain resource_bounds field") + .as_object_mut() + .expect("resource_bounds should be an object"); + + if let Some(l1_gas_value) = resource_bounds.remove("l1_gas") { + resource_bounds.insert("L1_GAS".to_string(), l1_gas_value); + + let l2_gas_value = resource_bounds + .remove("l2_gas") + .expect("If tx contains l1_gas, it should contain l2_gas"); + resource_bounds.insert("L2_GAS".to_string(), l2_gas_value); + } +} + pub fn deserialize_transaction_json_to_starknet_api_tx( mut raw_transaction: Value, ) -> serde_json::Result { @@ -24,31 +43,20 @@ pub fn deserialize_transaction_json_to_starknet_api_tx( Ok(Transaction::Invoke(InvokeTransaction::V1(serde_json::from_value(raw_transaction)?))) } ("INVOKE", "0x3") => { - let resource_bounds = raw_transaction - .get_mut("resource_bounds") - .expect("Invoke v3 tx should contain resource_bounds field") - .as_object_mut() - .expect("resource_bounds should be an object"); - // In old invoke v3 transaction, the resource bounds names are lowercase. - // need to convert to uppercase for deserialization to work. - if let Some(l1_gas_value) = resource_bounds.remove("l1_gas") { - resource_bounds.insert("L1_GAS".to_string(), l1_gas_value); - - let l2_gas_value = resource_bounds - .remove("l2_gas") - .expect("If invoke v3 tx contains l1_gas, it should contain l2_gas"); - resource_bounds.insert("L2_GAS".to_string(), l2_gas_value); - } - + upper_case_resource_bounds_names(&mut raw_transaction); Ok(Transaction::Invoke(InvokeTransaction::V3(serde_json::from_value(raw_transaction)?))) } ("DEPLOY_ACCOUNT", "0x1") => Ok(Transaction::DeployAccount(DeployAccountTransaction::V1( serde_json::from_value(raw_transaction)?, ))), - ("DEPLOY_ACCOUNT", "0x3") => Ok(Transaction::DeployAccount(DeployAccountTransaction::V3( - serde_json::from_value(raw_transaction)?, - ))), + ("DEPLOY_ACCOUNT", "0x3") => { + // In old deploy account v3 transaction, the resource bounds names are lowercase. + upper_case_resource_bounds_names(&mut raw_transaction); + Ok(Transaction::DeployAccount(DeployAccountTransaction::V3(serde_json::from_value( + raw_transaction, + )?))) + } ("DECLARE", "0x0") => Ok(Transaction::Declare(DeclareTransaction::V0( serde_json::from_value(raw_transaction)?, ))), @@ -58,9 +66,13 @@ pub fn deserialize_transaction_json_to_starknet_api_tx( ("DECLARE", "0x2") => Ok(Transaction::Declare(DeclareTransaction::V2( serde_json::from_value(raw_transaction)?, ))), - ("DECLARE", "0x3") => Ok(Transaction::Declare(DeclareTransaction::V3( - serde_json::from_value(raw_transaction)?, - ))), + ("DECLARE", "0x3") => { + // In old declare v3 transaction, the resource bounds names are lowercase. + upper_case_resource_bounds_names(&mut raw_transaction); + Ok(Transaction::Declare(DeclareTransaction::V3(serde_json::from_value( + raw_transaction, + )?))) + } ("L1_HANDLER", _) => Ok(Transaction::L1Handler(serde_json::from_value(raw_transaction)?)), (tx_type, tx_version) => Err(serde::de::Error::custom(format!( "unimplemented transaction type: {tx_type} version: {tx_version}"