From 32dc9248e1b2e99557c59089b2f15bdd83446fab Mon Sep 17 00:00:00 2001
From: AvivYossef-starkware
<141143145+AvivYossef-starkware@users.noreply.github.com>
Date: Tue, 1 Oct 2024 18:46:30 +0300
Subject: [PATCH] build: blockifier regression test serde rpc tx to starknet
api tx (#1021)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This change is [](https://reviewable.io/reviews/starkware-libs/sequencer/1021)
---
.../raw_rpc_json_objects/transactions.json | 73 +++++++++++++++++++
.../src/state_reader/raw_rpc_json_test.rs | 20 +++++
.../src/state_reader/rpc_https_test.rs | 20 ++++-
.../src/state_reader/test_state_reader.rs | 26 ++++++-
.../src/state_reader/utils.rs | 65 +++++++++++++++++
5 files changed, 200 insertions(+), 4 deletions(-)
create mode 100644 crates/blockifier_regression_test/resources/raw_rpc_json_objects/transactions.json
diff --git a/crates/blockifier_regression_test/resources/raw_rpc_json_objects/transactions.json b/crates/blockifier_regression_test/resources/raw_rpc_json_objects/transactions.json
new file mode 100644
index 0000000000..fbdfc3e4aa
--- /dev/null
+++ b/crates/blockifier_regression_test/resources/raw_rpc_json_objects/transactions.json
@@ -0,0 +1,73 @@
+{
+ "invoke_v1": {
+ "calldata": [
+ "0x1",
+ "0x422d33a3638dcc4c62e72e1d6942cd31eb643ef596ccac2351e0e21f6cd4bf4",
+ "0xcaffbd1bd76bd7f24a3fa1d69d1b2588a86d1f9d2359b13f6a84b7e1cbd126",
+ "0x5",
+ "0x5265736f6c766552616e646f6d4576656e74",
+ "0x3",
+ "0x0",
+ "0x1",
+ "0x10c3"
+ ],
+ "max_fee": "0x65f2d0057b2",
+ "nonce": "0x4d8",
+ "sender_address": "0x4e6989d518d5eb7e516dc5673f855fe7c5cfece1880a1047d6a8e8465be0d69",
+ "signature": [
+ "0x59b7462ea9566750ab7d7d08acbb6d339bfda921b053f1f8a5fd6b96c3656f9",
+ "0x2f11c36d10a03f21be918a5feeeb9922c11a2713fecd51f5e6bac5167856ecb"
+ ],
+ "transaction_hash": "0x47165a9a9c97e8829a4778f2a4b6fae4366aefc35b51d484bf04c458168351b",
+ "type": "INVOKE",
+ "version": "0x1"
+ },
+ "invoke_v3": {
+ "account_deployment_data": [],
+ "calldata": [
+ "0x2",
+ "0x4878d1148318a31829523ee9c6a5ee563af6cd87f90a30809e5b0d27db8a9b",
+ "0xa72371689866be053cc37a071de4216af73c9ffff96319b2576f7bf1e15290",
+ "0x4",
+ "0x2cb8f1439c83d9856179cbeae626e676bbb9b68e0bdda5423aa1988018acebe",
+ "0xba43b7400",
+ "0x2750a0009",
+ "0x422d33a3638dcc4c62e72e1d6942cd31eb643ef596ccac2351e0e21f6cd4bf4",
+ "0x422d33a3638dcc4c62e72e1d6942cd31eb643ef596ccac2351e0e21f6cd4bf4",
+ "0xcaffbd1bd76bd7f24a3fa1d69d1b2588a86d1f9d2359b13f6a84b7e1cbd126",
+ "0x6",
+ "0x41636365707444656c6976657279",
+ "0x4",
+ "0x9",
+ "0x2750a",
+ "0x1",
+ "0xcf"
+ ],
+ "fee_data_availability_mode": "L1",
+ "nonce": "0x1412",
+ "nonce_data_availability_mode": "L1",
+ "paymaster_data": [],
+ "resource_bounds": {
+ "l1_gas": {
+ "max_amount": "0x368",
+ "max_price_per_unit": "0x13bca990eeea"
+ },
+ "l2_gas": {
+ "max_amount": "0x0",
+ "max_price_per_unit": "0x0"
+ }
+ },
+ "sender_address": "0x614872dd2f3324f3e9a047d0cfaab9e9573bbdfa6081877f49f7108116b8ae0",
+ "signature": [
+ "0x1",
+ "0x0",
+ "0x61050eb8efaa6db97248c8c987c1a9df82527c26c204681396108cbd5babaf8",
+ "0x358bc995a221c3aa96cf2a1e6b5b8959b6d626b6fe89381d627f378dc39402a",
+ "0xf247079c5e0c5be56f4c0f37452304dc63b4b883b89d5a66e3202a855515ef"
+ ],
+ "tip": "0x0",
+ "transaction_hash": "0xa7c7db686c7f756ceb7ca85a759caef879d425d156da83d6a836f86851983",
+ "type": "INVOKE",
+ "version": "0x3"
+ }
+}
\ No newline at end of file
diff --git a/crates/blockifier_regression_test/src/state_reader/raw_rpc_json_test.rs b/crates/blockifier_regression_test/src/state_reader/raw_rpc_json_test.rs
index 8b799cc99d..96b6dcfce3 100644
--- a/crates/blockifier_regression_test/src/state_reader/raw_rpc_json_test.rs
+++ b/crates/blockifier_regression_test/src/state_reader/raw_rpc_json_test.rs
@@ -1,12 +1,15 @@
+use assert_matches::assert_matches;
use blockifier::blockifier::block::BlockInfo;
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_core::types::ContractClass;
use starknet_gateway::rpc_objects::BlockHeader;
use crate::state_reader::compile::legacy_to_contract_class_v0;
+use crate::state_reader::utils::deserialize_transaction_json_to_starknet_api_tx;
#[fixture]
fn block_header() -> BlockHeader {
@@ -45,3 +48,20 @@ fn test_compile_deprecated_contract_class(deprecated_contract_class: ContractCla
_ => panic!("Expected a legacy contract class"),
}
}
+
+#[test]
+fn deserialize_invoke_txs() {
+ let invoke_tx_v1 = deserialize_transaction_json_to_starknet_api_tx(
+ read_json_file("raw_rpc_json_objects/transactions.json")["invoke_v1"].clone(),
+ )
+ .expect("Failed to deserialize invoke v1 tx");
+
+ assert_matches!(invoke_tx_v1, Transaction::Invoke(InvokeTransaction::V1(..)));
+
+ let invoke_tx_v3 = deserialize_transaction_json_to_starknet_api_tx(
+ read_json_file("raw_rpc_json_objects/transactions.json")["invoke_v3"].clone(),
+ )
+ .expect("Failed to deserialize invoke v3 tx");
+
+ assert_matches!(invoke_tx_v3, Transaction::Invoke(InvokeTransaction::V3(..)));
+}
diff --git a/crates/blockifier_regression_test/src/state_reader/rpc_https_test.rs b/crates/blockifier_regression_test/src/state_reader/rpc_https_test.rs
index 7bc7e60cb5..b0144724d7 100644
--- a/crates/blockifier_regression_test/src/state_reader/rpc_https_test.rs
+++ b/crates/blockifier_regression_test/src/state_reader/rpc_https_test.rs
@@ -6,15 +6,24 @@ use rstest::{fixture, rstest};
use starknet_api::block::BlockNumber;
use starknet_api::core::ClassHash;
use starknet_api::test_utils::read_json_file;
+use starknet_api::transaction::Transaction;
use starknet_api::{class_hash, felt};
use starknet_core::types::ContractClass::{Legacy, Sierra};
use crate::state_reader::compile::legacy_to_contract_class_v0;
use crate::state_reader::test_state_reader::TestStateReader;
+const EXAMPLE_INVOKE_TX_HASH: &str =
+ "0xa7c7db686c7f756ceb7ca85a759caef879d425d156da83d6a836f86851983";
+
+const EXAMPLE_BLOCK_NUMBER: u64 = 700000;
+
+const EXAMPLE_CONTACT_CLASS_HASH: &str =
+ "0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e";
+
#[fixture]
pub fn test_block_number() -> BlockNumber {
- BlockNumber(700000)
+ BlockNumber(EXAMPLE_BLOCK_NUMBER)
}
#[fixture]
@@ -38,8 +47,7 @@ pub fn test_get_starknet_version(test_state_reader: TestStateReader) {
#[rstest]
pub fn test_get_contract_class(test_state_reader: TestStateReader, test_block_number: BlockNumber) {
// An example of existing class hash in Mainnet.
- let class_hash =
- class_hash!("0x3131fa018d520a037686ce3efddeab8f28895662f019ca3ca18a626650f7d1e");
+ let class_hash = class_hash!(EXAMPLE_CONTACT_CLASS_HASH);
// Test getting the contract class using RPC request.
let deprecated_contract_class =
@@ -74,3 +82,9 @@ pub fn test_get_tx_hashes(test_state_reader: TestStateReader, test_block_number:
});
assert_eq!(actual_tx_hashes, expected_tx_hashes);
}
+
+#[rstest]
+pub fn test_get_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(..));
+}
diff --git a/crates/blockifier_regression_test/src/state_reader/test_state_reader.rs b/crates/blockifier_regression_test/src/state_reader/test_state_reader.rs
index 17c89b436e..2bb67ac64e 100644
--- a/crates/blockifier_regression_test/src/state_reader/test_state_reader.rs
+++ b/crates/blockifier_regression_test/src/state_reader/test_state_reader.rs
@@ -12,6 +12,7 @@ use serde_json::{json, to_value};
use starknet_api::block::{BlockNumber, GasPrice};
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce};
use starknet_api::state::StorageKey;
+use starknet_api::transaction::Transaction;
use starknet_core::types::ContractClass as StarknetContractClass;
use starknet_core::types::ContractClass::{Legacy, Sierra};
use starknet_gateway::config::RpcStateReaderConfig;
@@ -21,7 +22,11 @@ use starknet_gateway::rpc_state_reader::RpcStateReader;
use starknet_types_core::felt::Felt;
use crate::state_reader::compile::{legacy_to_contract_class_v0, sierra_to_contact_class_v1};
-use crate::state_reader::utils::{get_chain_info, get_rpc_state_reader_config};
+use crate::state_reader::utils::{
+ deserialize_transaction_json_to_starknet_api_tx,
+ get_chain_info,
+ get_rpc_state_reader_config,
+};
pub struct TestStateReader(RpcStateReader);
@@ -120,6 +125,15 @@ impl TestStateReader {
serde_json::from_value(raw_tx_hashes).map_err(serde_err_to_state_err)
}
+ pub fn get_tx_by_hash(&self, tx_hash: &str) -> StateResult {
+ let method = "starknet_getTransactionByHash";
+ let params = json!({
+ "transaction_hash": tx_hash,
+ });
+ deserialize_transaction_json_to_starknet_api_tx(self.0.send_rpc_request(method, params)?)
+ .map_err(serde_err_to_state_err)
+ }
+
pub fn get_contract_class(&self, class_hash: &ClassHash) -> StateResult {
let params = json!({
"block_id": self.0.block_id,
@@ -131,6 +145,16 @@ impl TestStateReader {
Ok(contract_class)
}
+ pub fn get_all_txs_in_block(&self) -> StateResult> {
+ // TODO(Aviv): Use batch request to get all txs in a block.
+ let txs: Vec<_> = self
+ .get_tx_hashes()?
+ .iter()
+ .map(|tx_hash| self.get_tx_by_hash(tx_hash))
+ .collect::>()?;
+ Ok(txs)
+ }
+
pub fn get_versioned_constants(&self) -> StateResult<&'static VersionedConstants> {
Ok(self.get_starknet_version()?.into())
}
diff --git a/crates/blockifier_regression_test/src/state_reader/utils.rs b/crates/blockifier_regression_test/src/state_reader/utils.rs
index 31b77b7eef..5f94c0b05a 100644
--- a/crates/blockifier_regression_test/src/state_reader/utils.rs
+++ b/crates/blockifier_regression_test/src/state_reader/utils.rs
@@ -1,6 +1,13 @@
use blockifier::context::{ChainInfo, FeeTokenAddresses};
use papyrus_execution::{ETH_FEE_CONTRACT_ADDRESS, STRK_FEE_CONTRACT_ADDRESS};
+use serde_json::Value;
use starknet_api::core::{ChainId, ContractAddress, PatriciaKey};
+use starknet_api::transaction::{
+ DeclareTransaction,
+ DeployAccountTransaction,
+ InvokeTransaction,
+ Transaction,
+};
use starknet_api::{contract_address, felt, patricia_key};
use starknet_gateway::config::RpcStateReaderConfig;
@@ -27,3 +34,61 @@ pub fn get_rpc_state_reader_config() -> RpcStateReaderConfig {
pub fn get_chain_info() -> ChainInfo {
ChainInfo { chain_id: ChainId::Mainnet, fee_token_addresses: get_fee_token_addresses() }
}
+
+pub fn deserialize_transaction_json_to_starknet_api_tx(
+ mut raw_transaction: Value,
+) -> serde_json::Result {
+ let tx_type: String = serde_json::from_value(raw_transaction["type"].clone())?;
+ let tx_version: String = serde_json::from_value(raw_transaction["version"].clone())?;
+
+ match (tx_type.as_str(), tx_version.as_str()) {
+ ("INVOKE", "0x0") => {
+ Ok(Transaction::Invoke(InvokeTransaction::V0(serde_json::from_value(raw_transaction)?)))
+ }
+ ("INVOKE", "0x1") => {
+ 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);
+ }
+
+ 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)?,
+ ))),
+ ("DECLARE", "0x0") => Ok(Transaction::Declare(DeclareTransaction::V0(
+ serde_json::from_value(raw_transaction)?,
+ ))),
+ ("DECLARE", "0x1") => Ok(Transaction::Declare(DeclareTransaction::V1(
+ serde_json::from_value(raw_transaction)?,
+ ))),
+ ("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)?,
+ ))),
+ ("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}"
+ ))),
+ }
+}