diff --git a/crates/sequencing/papyrus_consensus_orchestrator/resources/central_declare_tx.json b/crates/sequencing/papyrus_consensus_orchestrator/resources/central_declare_tx.json new file mode 100644 index 0000000000..9ac7afb452 --- /dev/null +++ b/crates/sequencing/papyrus_consensus_orchestrator/resources/central_declare_tx.json @@ -0,0 +1,39 @@ +{ + "tx": { + "hash_value": "0x41e7d973115400a98a7775190c27d4e3b1fcd8cd40b7d27464f6c3f10b8b706", + "version": "0x3", + "signature": [], + "nonce": "0x0", + "sender_address": "0x12fd537", + "nonce_data_availability_mode": 0, + "fee_data_availability_mode": 0, + "resource_bounds": { + "L1_GAS": { + "max_amount": "0x1", + "max_price_per_unit": "0x1" + }, + "L2_GAS": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + }, + "L1_DATA": { + "max_amount": "0x0", + "max_price_per_unit": "0x0" + } + }, + "tip": "0x0", + "paymaster_data": [], + "class_hash": "0x3a59046762823dc87385eb5ac8a21f3f5bfe4274151c6eb633737656c209056", + "compiled_class_hash": "0x0", + "sierra_program_size": 8844, + "sierra_version": [ + "0x1", + "0x6", + "0x0" + ], + "abi_size": 11237, + "account_deployment_data": [], + "type": "DECLARE" + }, + "time_created": 1734601649 +} diff --git a/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects.rs b/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects.rs index 61b20e200a..69f9a3ae0b 100644 --- a/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects.rs +++ b/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects.rs @@ -1,6 +1,6 @@ use assert_matches::assert_matches; use indexmap::{indexmap, IndexMap}; -use serde::{Deserialize, Serialize}; +use serde::Serialize; use starknet_api::block::{ BlockInfo, BlockNumber, @@ -8,10 +8,12 @@ use starknet_api::block::{ NonzeroGasPrice, StarknetVersion, }; +use starknet_api::contract_class::SierraVersion; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; use starknet_api::data_availability::DataAvailabilityMode; use starknet_api::executable_transaction::{ AccountTransaction, + DeclareTransaction, DeployAccountTransaction, InvokeTransaction, Transaction, @@ -36,13 +38,13 @@ use starknet_types_core::felt::Felt; #[path = "central_objects_test.rs"] mod central_objects_test; -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] pub struct CentralResourcePrice { pub price_in_wei: NonzeroGasPrice, pub price_in_fri: NonzeroGasPrice, } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] pub struct CentralBlockInfo { pub block_number: BlockNumber, pub block_timestamp: BlockTimestamp, @@ -78,7 +80,7 @@ impl From<(BlockInfo, StarknetVersion)> for CentralBlockInfo { } } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] pub struct CentralStateDiff { pub address_to_class_hash: IndexMap, pub nonces: IndexMap>, @@ -104,7 +106,7 @@ impl From<(ThinStateDiff, BlockInfo, StarknetVersion)> for CentralStateDiff { } } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] pub struct CentralInvokeTransactionV3 { pub sender_address: ContractAddress, pub calldata: Calldata, @@ -139,14 +141,14 @@ impl From for CentralInvokeTransactionV3 { } } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] #[serde(tag = "version")] pub enum CentralInvokeTransaction { #[serde(rename = "0x3")] V3(CentralInvokeTransactionV3), } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] pub struct CentralDeployAccountTransactionV3 { pub resource_bounds: ValidResourceBounds, pub tip: Tip, @@ -181,20 +183,74 @@ impl From for CentralDeployAccountTransactionV3 { } } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] #[serde(tag = "version")] pub enum CentralDeployAccountTransaction { #[serde(rename = "0x3")] V3(CentralDeployAccountTransactionV3), } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +fn into_string_tuple(val: SierraVersion) -> (String, String, String) { + (format!("0x{:x}", val.major), format!("0x{:x}", val.minor), format!("0x{:x}", val.patch)) +} + +#[derive(Debug, PartialEq, Serialize)] +pub struct CentralDeclareTransactionV3 { + pub resource_bounds: ValidResourceBounds, + pub tip: Tip, + pub signature: TransactionSignature, + pub nonce: Nonce, + pub class_hash: ClassHash, + pub compiled_class_hash: CompiledClassHash, + pub sender_address: ContractAddress, + pub nonce_data_availability_mode: u32, + pub fee_data_availability_mode: u32, + pub paymaster_data: PaymasterData, + pub account_deployment_data: AccountDeploymentData, + pub sierra_program_size: usize, + pub abi_size: usize, + pub sierra_version: (String, String, String), + pub hash_value: TransactionHash, +} + +impl From for CentralDeclareTransactionV3 { + fn from(tx: DeclareTransaction) -> CentralDeclareTransactionV3 { + CentralDeclareTransactionV3 { + resource_bounds: tx.resource_bounds(), + tip: tx.tip(), + signature: tx.signature(), + nonce: tx.nonce(), + class_hash: tx.class_hash(), + compiled_class_hash: tx.compiled_class_hash(), + sender_address: tx.sender_address(), + nonce_data_availability_mode: tx.nonce_data_availability_mode().into(), + fee_data_availability_mode: tx.fee_data_availability_mode().into(), + paymaster_data: tx.paymaster_data(), + account_deployment_data: tx.account_deployment_data(), + sierra_program_size: tx.class_info.sierra_program_length, + abi_size: tx.class_info.abi_length, + sierra_version: into_string_tuple(tx.class_info.sierra_version), + hash_value: tx.tx_hash, + } + } +} + +#[derive(Debug, PartialEq, Serialize)] +#[serde(tag = "version")] +pub enum CentralDeclareTransaction { + #[serde(rename = "0x3")] + V3(CentralDeclareTransactionV3), +} + +#[derive(Debug, PartialEq, Serialize)] #[serde(tag = "type")] pub enum CentralTransaction { #[serde(rename = "INVOKE_FUNCTION")] Invoke(CentralInvokeTransaction), #[serde(rename = "DEPLOY_ACCOUNT")] DeployAccount(CentralDeployAccountTransaction), + #[serde(rename = "DECLARE")] + Declare(CentralDeclareTransaction), } impl From for CentralTransaction { @@ -208,13 +264,15 @@ impl From for CentralTransaction { deploy_tx.into(), )) } - Transaction::Account(_) => unimplemented!(), + Transaction::Account(AccountTransaction::Declare(declare_tx)) => { + CentralTransaction::Declare(CentralDeclareTransaction::V3(declare_tx.into())) + } Transaction::L1Handler(_) => unimplemented!(), } } } -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Debug, PartialEq, Serialize)] pub struct CentralTransactionWritten { pub tx: CentralTransaction, pub time_created: u64, diff --git a/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects_test.rs b/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects_test.rs index 8d269b4c01..449c2d805d 100644 --- a/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects_test.rs +++ b/crates/sequencing/papyrus_consensus_orchestrator/src/cende/central_objects_test.rs @@ -13,9 +13,14 @@ use starknet_api::block::{ NonzeroGasPrice, StarknetVersion, }; +use starknet_api::contract_class::{ClassInfo, ContractClass, SierraVersion}; use starknet_api::core::{ClassHash, CompiledClassHash, Nonce}; use starknet_api::data_availability::DataAvailabilityMode; -use starknet_api::executable_transaction::{DeployAccountTransaction, InvokeTransaction}; +use starknet_api::executable_transaction::{ + DeclareTransaction, + DeployAccountTransaction, + InvokeTransaction, +}; use starknet_api::execution_resources::GasAmount; use starknet_api::state::ThinStateDiff; use starknet_api::test_utils::read_json_file; @@ -26,10 +31,16 @@ use starknet_api::transaction::fields::{ ResourceBounds, ValidResourceBounds, }; -use starknet_api::transaction::{DeployAccountTransactionV3, InvokeTransactionV3, TransactionHash}; +use starknet_api::transaction::{ + DeclareTransactionV3, + DeployAccountTransactionV3, + InvokeTransactionV3, + TransactionHash, +}; use starknet_api::{contract_address, felt, storage_key}; use super::{ + CentralDeclareTransaction, CentralDeployAccountTransaction, CentralInvokeTransaction, CentralStateDiff, @@ -40,6 +51,7 @@ use super::{ pub const CENTRAL_STATE_DIFF_JSON_PATH: &str = "central_state_diff.json"; pub const CENTRAL_INVOKE_TX_JSON_PATH: &str = "central_invoke_tx.json"; pub const CENTRAL_DEPLOY_ACCOUNT_TX_JSON_PATH: &str = "central_deploy_account_tx.json"; +pub const CENTRAL_DECLARE_TX_JSON_PATH: &str = "central_declare_tx.json"; fn central_state_diff_json() -> Value { let state_diff = ThinStateDiff { @@ -157,10 +169,54 @@ fn central_deploy_account_tx_json() -> Value { serde_json::to_value(central_transaction_written).unwrap() } +fn central_declare_tx_json() -> Value { + let declare_tx = DeclareTransaction { + tx: starknet_api::transaction::DeclareTransaction::V3(DeclareTransactionV3 { + resource_bounds: ValidResourceBounds::AllResources(AllResourceBounds { + l1_gas: ResourceBounds { + max_amount: GasAmount(1), + max_price_per_unit: GasPrice(1), + }, + l2_gas: ResourceBounds::default(), + l1_data_gas: ResourceBounds::default(), + }), + sender_address: contract_address!("0x12fd537"), + signature: Default::default(), + nonce: Nonce(felt!("0x0")), + tip: Default::default(), + paymaster_data: Default::default(), + nonce_data_availability_mode: DataAvailabilityMode::L1, + fee_data_availability_mode: DataAvailabilityMode::L1, + account_deployment_data: Default::default(), + class_hash: ClassHash(felt!( + "0x3a59046762823dc87385eb5ac8a21f3f5bfe4274151c6eb633737656c209056" + )), + compiled_class_hash: CompiledClassHash(felt!("0x0")), + }), + tx_hash: TransactionHash(felt!( + "0x41e7d973115400a98a7775190c27d4e3b1fcd8cd40b7d27464f6c3f10b8b706" + )), + class_info: ClassInfo { + // The contract class is not used by the central object. + contract_class: ContractClass::V0(Default::default()), + sierra_program_length: 8844, + abi_length: 11237, + sierra_version: SierraVersion::new(1, 6, 0), + }, + }; + let central_transaction_written = CentralTransactionWritten { + tx: CentralTransaction::Declare(CentralDeclareTransaction::V3(declare_tx.into())), + time_created: 1734601649, + }; + + serde_json::to_value(central_transaction_written).unwrap() +} + #[rstest] #[case::state_diff(central_state_diff_json(), CENTRAL_STATE_DIFF_JSON_PATH)] #[case::invoke_tx(central_invoke_tx_json(), CENTRAL_INVOKE_TX_JSON_PATH)] #[case::deploy_account_tx(central_deploy_account_tx_json(), CENTRAL_DEPLOY_ACCOUNT_TX_JSON_PATH)] +#[case::declare_tx(central_declare_tx_json(), CENTRAL_DECLARE_TX_JSON_PATH)] fn serialize_central_objects(#[case] rust_json: Value, #[case] python_json_path: &str) { let python_json = read_json_file(python_json_path); diff --git a/crates/starknet_api/src/executable_transaction.rs b/crates/starknet_api/src/executable_transaction.rs index a3e0f96f33..9d862413a7 100644 --- a/crates/starknet_api/src/executable_transaction.rs +++ b/crates/starknet_api/src/executable_transaction.rs @@ -1,7 +1,14 @@ use serde::{Deserialize, Serialize}; use crate::contract_class::{ClassInfo, ContractClass}; -use crate::core::{calculate_contract_address, ChainId, ClassHash, ContractAddress, Nonce}; +use crate::core::{ + calculate_contract_address, + ChainId, + ClassHash, + CompiledClassHash, + ContractAddress, + Nonce, +}; use crate::data_availability::DataAvailabilityMode; use crate::rpc_transaction::{ RpcDeployAccountTransaction, @@ -152,7 +159,16 @@ impl DeclareTransaction { (nonce, Nonce), (sender_address, ContractAddress), (signature, TransactionSignature), - (version, TransactionVersion) + (version, TransactionVersion), + // compiled_class_hash is only supported in V2 and V3, otherwise the getter panics. + (compiled_class_hash, CompiledClassHash), + // The following fields are only supported in V3, otherwise the getter panics. + (tip, Tip), + (nonce_data_availability_mode, DataAvailabilityMode), + (fee_data_availability_mode, DataAvailabilityMode), + (paymaster_data, PaymasterData), + (account_deployment_data, AccountDeploymentData), + (resource_bounds, ValidResourceBounds) ); pub fn create(