diff --git a/crates/blockifier/src/execution/native/syscall_handler.rs b/crates/blockifier/src/execution/native/syscall_handler.rs index 682f08b986..38b3ee485c 100644 --- a/crates/blockifier/src/execution/native/syscall_handler.rs +++ b/crates/blockifier/src/execution/native/syscall_handler.rs @@ -10,9 +10,9 @@ use cairo_native::starknet::{ StarknetSyscallHandler, SyscallResult, TxInfo, + TxV2Info, U256, }; -use cairo_native::starknet_stub::encode_str_as_felts; use cairo_vm::vm::runners::cairo_runner::ExecutionResources; use starknet_api::core::EthAddress; use starknet_api::state::StorageKey; @@ -28,8 +28,14 @@ use crate::execution::call_info::{ }; use crate::execution::common_hints::ExecutionMode; use crate::execution::entry_point::{CallEntryPoint, EntryPointExecutionContext}; +use crate::execution::native::utils::{ + calculate_resource_bounds, + default_tx_v2_info, + encode_str_as_felts, +}; use crate::execution::syscalls::hint_processor::{SyscallExecutionError, OUT_OF_GAS_ERROR}; use crate::state::state_api::State; +use crate::transaction::objects::TransactionInfo; pub struct NativeSyscallHandler<'state> { // Input for execution. @@ -175,6 +181,36 @@ impl<'state> NativeSyscallHandler<'state> { } } } + + fn get_tx_info_v2(&self) -> SyscallResult { + let tx_info = &self.context.tx_context.tx_info; + let native_tx_info = TxV2Info { + version: tx_info.version().0, + account_contract_address: Felt::from(tx_info.sender_address()), + max_fee: tx_info.max_fee().0, + signature: tx_info.signature().0, + transaction_hash: tx_info.transaction_hash().0, + chain_id: Felt::from_hex( + &self.context.tx_context.block_context.chain_info.chain_id.as_hex(), + ) + .expect("Failed to convert the chain_id to hex."), + nonce: tx_info.nonce().0, + ..default_tx_v2_info() + }; + + match tx_info { + TransactionInfo::Deprecated(_) => Ok(native_tx_info), + TransactionInfo::Current(context) => Ok(TxV2Info { + resource_bounds: calculate_resource_bounds(context)?, + tip: context.tip.0.into(), + paymaster_data: context.paymaster_data.0.clone(), + nonce_data_availability_mode: context.nonce_data_availability_mode.into(), + fee_data_availability_mode: context.fee_data_availability_mode.into(), + account_deployment_data: context.account_deployment_data.0.clone(), + ..native_tx_info + }), + } + } } impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { @@ -203,9 +239,20 @@ impl<'state> StarknetSyscallHandler for &mut NativeSyscallHandler<'state> { fn get_execution_info_v2( &mut self, - _remaining_gas: &mut u128, + remaining_gas: &mut u128, ) -> SyscallResult { - todo!("Implement get_execution_info_v2 syscall."); + self.pre_execute_syscall( + remaining_gas, + self.context.gas_costs().get_execution_info_gas_cost, + )?; + + Ok(ExecutionInfoV2 { + block_info: self.get_block_info(), + tx_info: self.get_tx_info_v2()?, + caller_address: Felt::from(self.call.caller_address), + contract_address: Felt::from(self.call.storage_address), + entry_point_selector: self.call.entry_point_selector.0, + }) } fn deploy( diff --git a/crates/blockifier/src/execution/native/utils.rs b/crates/blockifier/src/execution/native/utils.rs index 87f53f4795..11ed9c5609 100644 --- a/crates/blockifier/src/execution/native/utils.rs +++ b/crates/blockifier/src/execution/native/utils.rs @@ -1,7 +1,11 @@ use cairo_lang_starknet_classes::contract_class::ContractEntryPoint; +use cairo_native::starknet::{ResourceBounds, SyscallResult, TxV2Info}; use starknet_api::core::EntryPointSelector; +use starknet_api::transaction::fields::{Resource, ValidResourceBounds}; use starknet_types_core::felt::Felt; +use crate::transaction::objects::CurrentTransactionInfo; + pub fn contract_entrypoint_to_entrypoint_selector( entrypoint: &ContractEntryPoint, ) -> EntryPointSelector { @@ -20,3 +24,61 @@ pub fn encode_str_as_felts(msg: &str) -> Vec { } encoding } + +pub fn default_tx_v2_info() -> TxV2Info { + TxV2Info { + version: Default::default(), + account_contract_address: Default::default(), + max_fee: 0, + signature: vec![], + transaction_hash: Default::default(), + chain_id: Default::default(), + nonce: Default::default(), + resource_bounds: vec![], + tip: 0, + paymaster_data: vec![], + nonce_data_availability_mode: 0, + fee_data_availability_mode: 0, + account_deployment_data: vec![], + } +} + +pub fn calculate_resource_bounds( + tx_info: &CurrentTransactionInfo, +) -> SyscallResult> { + Ok(match tx_info.resource_bounds { + ValidResourceBounds::L1Gas(l1_bounds) => { + vec![ + ResourceBounds { + resource: Felt::from_hex(Resource::L1Gas.to_hex()).unwrap(), + max_amount: l1_bounds.max_amount.0, + max_price_per_unit: l1_bounds.max_price_per_unit.0, + }, + ResourceBounds { + resource: Felt::from_hex(Resource::L2Gas.to_hex()).unwrap(), + max_amount: 0, + max_price_per_unit: 0, + }, + ] + } + ValidResourceBounds::AllResources(all_bounds) => { + vec![ + ResourceBounds { + resource: Felt::from_hex(Resource::L1Gas.to_hex()).unwrap(), + max_amount: all_bounds.l1_gas.max_amount.0, + max_price_per_unit: all_bounds.l1_gas.max_price_per_unit.0, + }, + ResourceBounds { + resource: Felt::from_hex(Resource::L1DataGas.to_hex()).unwrap(), + max_amount: all_bounds.l1_data_gas.max_amount.0, + max_price_per_unit: all_bounds.l1_data_gas.max_price_per_unit.0, + }, + ResourceBounds { + resource: Felt::from_hex(Resource::L2Gas.to_hex()).unwrap(), + max_amount: all_bounds.l2_gas.max_amount.0, + max_price_per_unit: all_bounds.l2_gas.max_price_per_unit.0, + }, + ] + } + }) +} diff --git a/crates/blockifier/src/execution/syscalls/syscall_tests/get_execution_info.rs b/crates/blockifier/src/execution/syscalls/syscall_tests/get_execution_info.rs index f0feb210f0..a12a0d7d9e 100644 --- a/crates/blockifier/src/execution/syscalls/syscall_tests/get_execution_info.rs +++ b/crates/blockifier/src/execution/syscalls/syscall_tests/get_execution_info.rs @@ -62,6 +62,46 @@ use crate::transaction::objects::{ "Native [V1]: Execute execution mode: block info should be as usual. Transaction V1." ) )] +#[cfg_attr( + feature = "cairo_native", + test_case( + FeatureContract::TestContract(CairoVersion::Native), + ExecutionMode::Validate, + TransactionVersion::ONE, + false; + "Native: Validate execution mode: block info fields should be zeroed. Transaction V1." + ) +)] +#[cfg_attr( + feature = "cairo_native", + test_case( + FeatureContract::TestContract(CairoVersion::Native), + ExecutionMode::Execute, + TransactionVersion::ONE, + false; + "Native: Execute execution mode: block info should be as usual. Transaction V1." + ) +)] +#[cfg_attr( + feature = "cairo_native", + test_case( + FeatureContract::TestContract(CairoVersion::Native), + ExecutionMode::Validate, + TransactionVersion::THREE, + false; + "Native: Validate execution mode: block info fields should be zeroed. Transaction V3." + ) +)] +#[cfg_attr( + feature = "cairo_native", + test_case( + FeatureContract::TestContract(CairoVersion::Native), + ExecutionMode::Execute, + TransactionVersion::THREE, + false; + "Native: Execute execution mode: block info should be as usual. Transaction V3." + ) +)] #[test_case( FeatureContract::TestContract(CairoVersion::Cairo1), ExecutionMode::Validate, diff --git a/crates/starknet_api/src/data_availability.rs b/crates/starknet_api/src/data_availability.rs index 0fc3f94800..f8af2fffae 100644 --- a/crates/starknet_api/src/data_availability.rs +++ b/crates/starknet_api/src/data_availability.rs @@ -64,6 +64,15 @@ impl From for Felt { } } +impl From for u32 { + fn from(data_availability_mode: DataAvailabilityMode) -> u32 { + match data_availability_mode { + DataAvailabilityMode::L1 => 0, + DataAvailabilityMode::L2 => 1, + } + } +} + #[derive( Clone, Default, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, )]