From a051468c7c868af4686619ba342ceac02df12ed6 Mon Sep 17 00:00:00 2001 From: Olivier Desenfans Date: Thu, 29 Aug 2024 15:31:41 +0200 Subject: [PATCH] Feature: support Sierra 1.6 (#328) * Feature: support Sierra 1.6 Problem: some contracts on Sepolia are built with Sierra 1.6, which is not supported by the version of the CASM compiler we use. But bumping the version of the compiler requires bumping cairo-vm and Blockifier as well. Solution: bump everything! We now use: * cairo-vm 1.0.1 * cairo-lang 2.7.1 * blockifier 0.8.0-rc.2 With this, we can now compile any contract on Sepolia. * Internal: remove deprecated `to_felt252` function This function is no longer required as felt types now all rely on starknet-types-core. * Internal: remove deprecated `felt_vm2api` function This function is no longer required as felt types now all rely on starknet-types-core. * Internal: remove deprecated `felt_api2vm` function This function is no longer required as felt types now all rely on starknet-types-core. * clippy * fmt * Feature: support blocks requiring Starknet v0.13.2 * Internal: remove deprecated `felt_to_vm` function This function is no longer required as felt types now all rely on starknet-types-core. * CI: add tests for DiffAssertValues resolution * CI: regression test for diff assert values in contract subcall * doc chain_id * fix review: expect(todo) * fix of the fix --- .github/workflows/prove_blocks.yml | 8 +- Cargo.toml | 14 +- crates/bin/prove_block/src/main.rs | 21 +- crates/bin/prove_block/src/rpc_utils.rs | 24 ++- crates/bin/prove_block/src/types.rs | 50 ++--- crates/bin/prove_block/src/utils.rs | 4 +- crates/rpc-replay/src/block_context.rs | 21 +- crates/rpc-replay/src/rpc_state_reader.rs | 47 ++--- crates/rpc-replay/src/transactions.rs | 34 ++-- crates/rpc-replay/src/utils.rs | 9 - crates/rpc-replay/tests/test_replay_block.rs | 4 +- .../src/casm_contract_class.rs | 2 +- crates/starknet-os-types/src/chain_id.rs | 21 ++ crates/starknet-os-types/src/hash.rs | 34 +--- crates/starknet-os/src/config.rs | 23 +-- .../execution/deprecated_syscall_handler.rs | 39 ++-- crates/starknet-os/src/execution/helper.rs | 11 +- .../src/execution/syscall_handler.rs | 13 +- .../src/execution/syscall_handler_utils.rs | 3 +- crates/starknet-os/src/hints/block_context.rs | 8 +- crates/starknet-os/src/hints/execution.rs | 7 +- crates/starknet-os/src/hints/mod.rs | 2 +- crates/starknet-os/src/hints/tests.rs | 11 +- crates/starknet-os/src/io/classes.rs | 8 +- .../business_logic/fact_state/state.rs | 88 ++++---- .../starknet-os/src/storage/storage_utils.rs | 7 +- crates/starknet-os/src/utils.rs | 46 +---- tests/integration/common/block_utils.rs | 31 ++- tests/integration/common/state.rs | 20 +- tests/integration/common/transaction_utils.rs | 188 +++++++++--------- tests/integration/declare_txn_tests.rs | 48 +++-- tests/integration/deploy_txn_tests.rs | 10 +- .../integration/deprecated_syscalls_tests.rs | 66 +++--- tests/integration/l1_handler_txn_tests.rs | 5 +- tests/integration/os.rs | 36 ++-- tests/integration/run_os.rs | 55 ++--- tests/integration/syscalls_tests.rs | 5 +- 37 files changed, 478 insertions(+), 545 deletions(-) diff --git a/.github/workflows/prove_blocks.yml b/.github/workflows/prove_blocks.yml index 1a9deeb1f..9d48dc4bd 100644 --- a/.github/workflows/prove_blocks.yml +++ b/.github/workflows/prove_blocks.yml @@ -47,4 +47,10 @@ jobs: bash scripts/setup-tests.sh - name: Prove Blocks - run: bash scripts/prove-blocks.sh -p ${{ secrets.PATHFINDER_RPC_URL }} -b 76793,76766,76775 + run: | + # These blocks verify the following issues: + # * 76793: the first block that we managed to prove, only has a few invoke txs + # * 76766 / 76775: additional basic blocks + # * 86507 / 124533: a failing assert that happened because we used the wrong VersionedConstants + # * 87019: diff assert values in contract subcall + bash scripts/prove-blocks.sh -p ${{ secrets.PATHFINDER_RPC_URL }} -b 76793,76766,76775,86507,87019,124533 diff --git a/Cargo.toml b/Cargo.toml index 514abce50..6ba31f41d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,13 +24,13 @@ assert_matches = "1.5.0" base64 = "0.21.3" bitvec = { version = "1.0.1", features = ["serde"] } # Point to the latest commit of branch msl/snos-0.6.0-rc.2 -blockifier = { git = "https://github.com/Moonsong-Labs/blockifier", rev = "983e3b1cdb6621c5e6fa600f47cd69bf9e287621", features = ["testing"] } -cairo-lang-starknet = { version = "2.6.3" } -cairo-lang-starknet-classes = { version = "2.6.3" } -cairo-lang-utils = { version = "2.6.3" } -cairo-lang-casm = { version = "2.6.3" } +blockifier = { git = "https://github.com/Moonsong-Labs/sequencer", rev = "01b97d9354faefa5f0cd520b5efbe73178213f7e", features = ["testing"] } +cairo-lang-starknet = { version = "=2.7.1" } +cairo-lang-starknet-classes = { version = "=2.7.1" } +cairo-lang-utils = { version = "=2.7.1" } +cairo-lang-casm = { version = "=2.7.1" } cairo-type-derive = { version = "0.1.0", path = "crates/cairo-type-derive" } -cairo-vm = { version = "=1.0.0-rc5", features = ["extensive_hints", "cairo-1-hints"] } +cairo-vm = { version = "=1.0.1", features = ["extensive_hints", "cairo-1-hints"] } clap = { version = "4.5.4", features = ["derive"] } env_logger = "0.11.3" flate2 = "1.0.32" @@ -58,7 +58,7 @@ serde_json = { version = "1.0.105", features = ["arbitrary_precision"] } serde_with = "3.3.0" serde_yaml = "0.9.25" starknet = "0.11.0" -starknet_api = { version = "=0.10", features = ["testing"] } +starknet_api = { git = "https://github.com/Moonsong-Labs/sequencer", rev = "01b97d9354faefa5f0cd520b5efbe73178213f7e", features = ["testing"] } starknet-core = "0.11.1" starknet-crypto = "0.6.2" starknet-os = { path = "crates/starknet-os" } diff --git a/crates/bin/prove_block/src/main.rs b/crates/bin/prove_block/src/main.rs index 276413c98..032ac4ea9 100644 --- a/crates/bin/prove_block/src/main.rs +++ b/crates/bin/prove_block/src/main.rs @@ -1,7 +1,7 @@ use std::collections::{HashMap, HashSet}; use std::error::Error; -use blockifier::state::cached_state::{CachedState, GlobalContractCache}; +use blockifier::state::cached_state::CachedState; use cairo_vm::types::layout_name::LayoutName; use cairo_vm::vm::errors::cairo_run_errors::CairoRunError::VmException; use cairo_vm::Felt252; @@ -24,13 +24,13 @@ use starknet_os::starknet::business_logic::fact_state::contract_state_objects::C use starknet_os::starknet::starknet_storage::CommitmentInfo; use starknet_os::starkware_utils::commitment_tree::base_types::Height; use starknet_os::starkware_utils::commitment_tree::patricia_tree::patricia_tree::PatriciaTree; -use starknet_os::utils::felt_api2vm; use starknet_os::{config, run_os}; +use starknet_os_types::chain_id::chain_id_from_felt; use starknet_os_types::sierra_contract_class::GenericSierraContractClass; use starknet_types_core::felt::Felt; use crate::reexecute::format_commitment_facts; -use crate::rpc_utils::PathfinderClassProof; +use crate::rpc_utils::{get_starknet_version, PathfinderClassProof}; use crate::state_utils::get_processed_state_update; use crate::types::starknet_rs_tx_to_internal_tx; @@ -113,7 +113,7 @@ async fn main() -> Result<(), Box> { reqwest::ClientBuilder::new().build().unwrap_or_else(|e| panic!("Could not build reqwest client: {e}")); // Step 1: build the block context - let chain_id = provider.chain_id().await?.to_string(); + let chain_id = chain_id_from_felt(provider.chain_id().await?); log::debug!("provider's chain_id: {}", chain_id); let block_with_txs = match provider.get_block_with_txs(block_id).await? { MaybePendingBlockWithTxs::Block(block_with_txs) => block_with_txs, @@ -122,6 +122,9 @@ async fn main() -> Result<(), Box> { } }; + let starknet_version = get_starknet_version(&block_with_txs); + log::debug!("Starknet version: {:?}", starknet_version); + // We only need to get the older block number and hash. No need to fetch all the txs let older_block = match provider .get_block_with_tx_hashes(BlockId::Number(block_number - STORED_BLOCK_HASH_BUFFER)) @@ -134,7 +137,7 @@ async fn main() -> Result<(), Box> { } }; - let block_context = build_block_context(chain_id.clone(), &block_with_txs); + let block_context = build_block_context(chain_id.clone(), &block_with_txs, starknet_version); let old_block_number = Felt252::from(older_block.block_number); let old_block_hash = older_block.block_hash; @@ -155,7 +158,7 @@ async fn main() -> Result<(), Box> { )); let blockifier_state_reader = AsyncRpcStateReader::new(provider_for_blockifier, BlockId::Number(block_number - 1)); - let mut blockifier_state = CachedState::new(blockifier_state_reader, GlobalContractCache::new(1024)); + let mut blockifier_state = CachedState::new(blockifier_state_reader); let tx_execution_infos = reexecute_transactions_with_blockifier( &mut blockifier_state, &block_context, @@ -189,9 +192,7 @@ async fn main() -> Result<(), Box> { let general_config = StarknetGeneralConfig { starknet_os_config: StarknetOsConfig { - // TODO: the string given by provider is in decimal, the OS expects hex - // chain_id: starknet_api::core::ChainId(chain_id.clone()), - chain_id: starknet_api::core::ChainId("SN_SEPOLIA".to_string()), + chain_id, fee_token_address: block_context.chain_info().fee_token_addresses.strk_fee_token_address, deprecated_fee_token_address: block_context.chain_info().fee_token_addresses.eth_fee_token_address, }, @@ -290,7 +291,7 @@ async fn main() -> Result<(), Box> { .visited_pcs .iter() .map(|(class_hash, visited_pcs)| { - (felt_api2vm(class_hash.0), visited_pcs.iter().copied().map(Felt252::from).collect::>()) + (class_hash.0, visited_pcs.iter().copied().map(Felt252::from).collect::>()) }) .collect(); diff --git a/crates/bin/prove_block/src/rpc_utils.rs b/crates/bin/prove_block/src/rpc_utils.rs index 7f45c3eb4..bfcb934e7 100644 --- a/crates/bin/prove_block/src/rpc_utils.rs +++ b/crates/bin/prove_block/src/rpc_utils.rs @@ -5,16 +5,15 @@ use cairo_vm::Felt252; use serde::de::DeserializeOwned; use serde::Deserialize; use serde_json::json; +use starknet::core::types::BlockWithTxs; use starknet_api::core::{ContractAddress, PatriciaKey}; -use starknet_api::hash::StarkHash; -use starknet_api::{contract_address, patricia_key}; +use starknet_api::{contract_address, felt, patricia_key}; use starknet_os::crypto::pedersen::PedersenHash; use starknet_os::crypto::poseidon::PoseidonHash; use starknet_os::starkware_utils::commitment_tree::base_types::{Length, NodePath}; use starknet_os::starkware_utils::commitment_tree::patricia_tree::nodes::{BinaryNodeFact, EdgeNodeFact}; use starknet_os::storage::dict_storage::DictStorage; use starknet_os::storage::storage::{Fact, HashFunctionType}; -use starknet_os::utils::{felt_api2vm, felt_vm2api}; use starknet_types_core::felt::Felt; use crate::utils::get_all_accessed_keys; @@ -137,7 +136,7 @@ pub(crate) async fn get_storage_proofs( ) -> Result, reqwest::Error> { let accessed_keys_by_address = { let mut keys = get_all_accessed_keys(tx_execution_infos); - keys.entry(contract_address!("0x1")).or_default().insert(felt_vm2api(old_block_number).try_into().unwrap()); + keys.entry(contract_address!("0x1")).or_default().insert(old_block_number.try_into().unwrap()); keys }; @@ -149,9 +148,9 @@ pub(crate) async fn get_storage_proofs( } for (contract_address, storage_keys) in accessed_keys_by_address { - let contract_address_felt = felt_api2vm(*contract_address.key()); + let contract_address_felt = *contract_address.key(); - let keys: Vec<_> = storage_keys.iter().map(|storage_key| felt_api2vm(*storage_key.key())).collect(); + let keys: Vec<_> = storage_keys.iter().map(|storage_key| *storage_key.key()).collect(); let storage_proof = if keys.is_empty() { pathfinder_get_proof(client, rpc_provider, block_number, contract_address_felt, &[]).await? @@ -299,3 +298,16 @@ pub(crate) fn verify_proof(key: Felt, commitment: Felt, pro Ok(()) } + +pub(crate) fn get_starknet_version(block_with_txs: &BlockWithTxs) -> blockifier::versioned_constants::StarknetVersion { + let starknet_version_str = &block_with_txs.starknet_version; + match starknet_version_str.as_ref() { + "0.13.0" => blockifier::versioned_constants::StarknetVersion::V0_13_0, + "0.13.1" => blockifier::versioned_constants::StarknetVersion::V0_13_1, + "0.13.1.1" => blockifier::versioned_constants::StarknetVersion::V0_13_1_1, + "0.13.2" => blockifier::versioned_constants::StarknetVersion::Latest, + other => { + unimplemented!("Unsupported Starknet version: {}", other) + } + } +} diff --git a/crates/bin/prove_block/src/types.rs b/crates/bin/prove_block/src/types.rs index 3a4ebae14..57734d988 100644 --- a/crates/bin/prove_block/src/types.rs +++ b/crates/bin/prove_block/src/types.rs @@ -7,17 +7,11 @@ use starknet::core::types::{ Transaction, }; use starknet_os::io::InternalTransaction; -use starknet_types_core::felt::Felt; // entry point for "__execute__" const EXECUTE_ENTRY_POINT_FELT: Felt252 = Felt252::from_hex_unchecked("0x15d40a3d6ca2ac30f4031e42be28da9b056fef9bb7357ac5e85627ee876e5ad"); -fn felt_to_vm(felt: Felt) -> Felt252 { - // Turns out that the types are the same between starknet-core and cairo-vm - felt -} - fn da_to_felt(data_availability_mode: DataAvailabilityMode) -> Felt252 { match data_availability_mode { DataAvailabilityMode::L1 => Felt252::ZERO, @@ -26,34 +20,28 @@ fn da_to_felt(data_availability_mode: DataAvailabilityMode) -> Felt252 { } fn invoke_tx_v0_to_internal_tx(tx: InvokeTransactionV0) -> InternalTransaction { - let signature: Vec<_> = tx.signature.into_iter().map(felt_to_vm).collect(); - let calldata: Vec<_> = tx.calldata.into_iter().map(felt_to_vm).collect(); - InternalTransaction { - hash_value: felt_to_vm(tx.transaction_hash), - max_fee: Some(felt_to_vm(tx.max_fee)), - signature: Some(signature), - contract_address: Some(felt_to_vm(tx.contract_address)), - entry_point_selector: Some(felt_to_vm(tx.entry_point_selector)), - calldata: Some(calldata), + hash_value: tx.transaction_hash, + max_fee: Some(tx.max_fee), + signature: Some(tx.signature), + contract_address: Some(tx.contract_address), + entry_point_selector: Some(tx.entry_point_selector), + calldata: Some(tx.calldata), version: Some(Felt252::ZERO), ..Default::default() } } fn invoke_tx_v1_to_internal_tx(tx: InvokeTransactionV1) -> InternalTransaction { - let signature: Vec<_> = tx.signature.into_iter().map(felt_to_vm).collect(); - let calldata: Vec<_> = tx.calldata.into_iter().map(felt_to_vm).collect(); - InternalTransaction { - hash_value: felt_to_vm(tx.transaction_hash), + hash_value: tx.transaction_hash, version: Some(Felt252::ONE), contract_address: Some(tx.sender_address), nonce: Some(tx.nonce), sender_address: Some(tx.sender_address), entry_point_selector: Some(EXECUTE_ENTRY_POINT_FELT), entry_point_type: Some("EXTERNAL".to_string()), - signature: Some(signature), - calldata: Some(calldata), + signature: Some(tx.signature), + calldata: Some(tx.calldata), r#type: "INVOKE_FUNCTION".to_string(), max_fee: Some(tx.max_fee), ..Default::default() @@ -61,27 +49,22 @@ fn invoke_tx_v1_to_internal_tx(tx: InvokeTransactionV1) -> InternalTransaction { } fn invoke_tx_v3_to_internal_tx(tx: InvokeTransactionV3) -> InternalTransaction { - let signature: Vec<_> = tx.signature.into_iter().map(felt_to_vm).collect(); - let calldata: Vec<_> = tx.calldata.into_iter().map(felt_to_vm).collect(); - let paymaster_data: Vec<_> = tx.paymaster_data.into_iter().map(felt_to_vm).collect(); - let account_deployment_data: Vec<_> = tx.account_deployment_data.into_iter().map(felt_to_vm).collect(); - InternalTransaction { - hash_value: felt_to_vm(tx.transaction_hash), - sender_address: Some(felt_to_vm(tx.sender_address)), - signature: Some(signature), - nonce: Some(felt_to_vm(tx.nonce)), + hash_value: tx.transaction_hash, + sender_address: Some(tx.sender_address), + signature: Some(tx.signature), + nonce: Some(tx.nonce), resource_bounds: Some(resource_bounds_core_to_api(&tx.resource_bounds)), tip: Some(Felt252::from(tx.tip)), - paymaster_data: Some(paymaster_data), - account_deployment_data: Some(account_deployment_data), + paymaster_data: Some(tx.paymaster_data), + account_deployment_data: Some(tx.account_deployment_data), nonce_data_availability_mode: Some(da_to_felt(tx.nonce_data_availability_mode)), fee_data_availability_mode: Some(da_to_felt(tx.fee_data_availability_mode)), version: Some(Felt252::TWO), contract_address: Some(tx.sender_address), entry_point_selector: Some(EXECUTE_ENTRY_POINT_FELT), entry_point_type: Some("EXTERNAL".to_string()), - calldata: Some(calldata), + calldata: Some(tx.calldata), ..Default::default() } } @@ -223,6 +206,7 @@ pub(crate) fn starknet_rs_tx_to_internal_tx(tx: Transaction) -> InternalTransact #[cfg(test)] mod tests { use starknet::core::types::{ResourceBounds, ResourceBoundsMapping}; + use starknet_types_core::felt::Felt; use super::*; diff --git a/crates/bin/prove_block/src/utils.rs b/crates/bin/prove_block/src/utils.rs index f776ca6ee..f2053721e 100644 --- a/crates/bin/prove_block/src/utils.rs +++ b/crates/bin/prove_block/src/utils.rs @@ -6,7 +6,6 @@ use cairo_vm::Felt252; use starknet::core::types::{ExecuteInvocation, FunctionInvocation, TransactionTrace, TransactionTraceWithHash}; use starknet_api::core::ContractAddress; use starknet_api::state::StorageKey; -use starknet_os::utils::felt_api2vm; /// Receives the transaction traces of a given block /// And extract the contracts addresses that where subcalled @@ -96,8 +95,7 @@ fn get_accessed_storage_keys(call_info: &CallInfo) -> HashMap = - call_info.accessed_storage_keys.iter().map(|x| felt_api2vm(*x.key()).to_hex_string()).collect(); + let storage_keys: Vec<_> = call_info.accessed_storage_keys.iter().map(|x| x.key().to_hex_string()).collect(); log::debug!("{}: {:?}", contract_address.to_string(), storage_keys); for inner_call in &call_info.inner_calls { diff --git a/crates/rpc-replay/src/block_context.rs b/crates/rpc-replay/src/block_context.rs index 96fb5671c..4c528f968 100644 --- a/crates/rpc-replay/src/block_context.rs +++ b/crates/rpc-replay/src/block_context.rs @@ -1,15 +1,19 @@ -use blockifier::block::{BlockInfo, GasPrices}; +use blockifier::blockifier::block::{BlockInfo, GasPrices}; +use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; use blockifier::versioned_constants::VersionedConstants; use starknet::core::types::BlockWithTxs; use starknet_api::block::{BlockNumber, BlockTimestamp}; -use starknet_api::core::{ContractAddress, PatriciaKey}; -use starknet_api::hash::StarkHash; -use starknet_api::{contract_address, patricia_key}; +use starknet_api::core::{ChainId, ContractAddress, PatriciaKey}; +use starknet_api::{contract_address, felt, patricia_key}; use crate::utils::felt_to_u128; -pub fn build_block_context(chain_id: String, block: &BlockWithTxs) -> BlockContext { +pub fn build_block_context( + chain_id: ChainId, + block: &BlockWithTxs, + starknet_version: blockifier::versioned_constants::StarknetVersion, +) -> BlockContext { let sequencer_address_hex = block.sequencer_address.to_hex_string(); let sequencer_address = contract_address!(sequencer_address_hex.as_str()); @@ -27,7 +31,7 @@ pub fn build_block_context(chain_id: String, block: &BlockWithTxs) -> BlockConte }; let chain_info = ChainInfo { - chain_id: starknet_api::core::ChainId(chain_id), + chain_id, // cf. https://docs.starknet.io/tools/important-addresses/ fee_token_addresses: FeeTokenAddresses { strk_fee_token_address: contract_address!( @@ -39,7 +43,8 @@ pub fn build_block_context(chain_id: String, block: &BlockWithTxs) -> BlockConte }, }; - let versioned_constants = VersionedConstants::latest_constants(); + let versioned_constants = VersionedConstants::get(starknet_version); + let bouncer_config = BouncerConfig::max(); - BlockContext::new_unchecked(&block_info, &chain_info, versioned_constants) + BlockContext::new(block_info, chain_info, versioned_constants.clone(), bouncer_config) } diff --git a/crates/rpc-replay/src/rpc_state_reader.rs b/crates/rpc-replay/src/rpc_state_reader.rs index a9b18030e..1c49783b4 100644 --- a/crates/rpc-replay/src/rpc_state_reader.rs +++ b/crates/rpc-replay/src/rpc_state_reader.rs @@ -1,17 +1,16 @@ use blockifier::execution::contract_class::ContractClass; use blockifier::state::errors::StateError; use blockifier::state::state_api::{StateReader, StateResult}; -use starknet::core::types::BlockId; +use starknet::core::types::{BlockId, Felt}; use starknet::providers::jsonrpc::JsonRpcTransport; use starknet::providers::{JsonRpcClient, Provider, ProviderError}; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; -use starknet_api::hash::StarkFelt; use starknet_api::state::StorageKey; use starknet_os_types::deprecated_compiled_class::GenericDeprecatedCompiledClass; use starknet_os_types::hash::GenericClassHash; use starknet_os_types::sierra_contract_class::GenericSierraContractClass; -use crate::utils::{execute_coroutine, felt_api2vm, felt_vm2api}; +use crate::utils::execute_coroutine; pub struct AsyncRpcStateReader where @@ -42,46 +41,39 @@ impl AsyncRpcStateReader where T: JsonRpcTransport + Sync + Send + 'static, { - pub async fn get_storage_at_async( - &self, - contract_address: ContractAddress, - key: StorageKey, - ) -> StateResult { + pub async fn get_storage_at_async(&self, contract_address: ContractAddress, key: StorageKey) -> StateResult { let storage_value = self .provider - .get_storage_at(felt_api2vm(*contract_address.key()), felt_api2vm(*key.0.key()), self.block_id) + .get_storage_at(*contract_address.key(), *key.0.key(), self.block_id) .await .map_err(provider_error_to_state_error)?; - Ok(felt_vm2api(storage_value)) + Ok(storage_value) } pub async fn get_nonce_at_async(&self, contract_address: ContractAddress) -> StateResult { let nonce = self .provider - .get_nonce(self.block_id, felt_api2vm(*contract_address.key())) + .get_nonce(self.block_id, *contract_address.key()) .await .map_err(provider_error_to_state_error)?; - Ok(Nonce(felt_vm2api(nonce))) + Ok(Nonce(nonce)) } pub async fn get_class_hash_at_async(&self, contract_address: ContractAddress) -> StateResult { let nonce = self .provider - .get_class_hash_at(self.block_id, felt_api2vm(*contract_address.key())) + .get_class_hash_at(self.block_id, *contract_address.key()) .await .map_err(provider_error_to_state_error)?; - Ok(ClassHash(felt_vm2api(nonce))) + Ok(ClassHash(nonce)) } pub async fn get_compiled_contract_class_async(&self, class_hash: ClassHash) -> StateResult { - let contract_class = self - .provider - .get_class(self.block_id, felt_api2vm(class_hash.0)) - .await - .map_err(provider_error_to_state_error)?; + let contract_class = + self.provider.get_class(self.block_id, class_hash.0).await.map_err(provider_error_to_state_error)?; let contract_class: ContractClass = match contract_class { starknet::core::types::ContractClass::Sierra(sierra_class) => { @@ -99,11 +91,8 @@ where } pub async fn get_compiled_class_hash_async(&self, class_hash: ClassHash) -> StateResult { - let contract_class = self - .provider - .get_class(self.block_id, felt_api2vm(class_hash.0)) - .await - .map_err(provider_error_to_state_error)?; + let contract_class = + self.provider.get_class(self.block_id, class_hash.0).await.map_err(provider_error_to_state_error)?; let class_hash: GenericClassHash = match contract_class { starknet::core::types::ContractClass::Sierra(sierra_class) => { @@ -125,24 +114,24 @@ impl StateReader for AsyncRpcStateReader where T: JsonRpcTransport + Sync + Send + 'static, { - fn get_storage_at(&mut self, contract_address: ContractAddress, key: StorageKey) -> StateResult { + fn get_storage_at(&self, contract_address: ContractAddress, key: StorageKey) -> StateResult { execute_coroutine(self.get_storage_at_async(contract_address, key)).map_err(to_state_err)? } - fn get_nonce_at(&mut self, contract_address: ContractAddress) -> StateResult { + fn get_nonce_at(&self, contract_address: ContractAddress) -> StateResult { execute_coroutine(self.get_nonce_at_async(contract_address)).map_err(to_state_err)? } - fn get_class_hash_at(&mut self, contract_address: ContractAddress) -> StateResult { + fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult { execute_coroutine(self.get_class_hash_at_async(contract_address)) .map_err(|e| StateError::StateReadError(e.to_string()))? } - fn get_compiled_contract_class(&mut self, class_hash: ClassHash) -> StateResult { + fn get_compiled_contract_class(&self, class_hash: ClassHash) -> StateResult { execute_coroutine(self.get_compiled_contract_class_async(class_hash)).map_err(to_state_err)? } - fn get_compiled_class_hash(&mut self, class_hash: ClassHash) -> StateResult { + fn get_compiled_class_hash(&self, class_hash: ClassHash) -> StateResult { execute_coroutine(self.get_compiled_class_hash_async(class_hash)).map_err(to_state_err)? } } diff --git a/crates/rpc-replay/src/transactions.rs b/crates/rpc-replay/src/transactions.rs index 63ee70d23..95a20f70c 100644 --- a/crates/rpc-replay/src/transactions.rs +++ b/crates/rpc-replay/src/transactions.rs @@ -7,8 +7,6 @@ use starknet::core::types::{InvokeTransaction, ResourceBoundsMapping, Transactio use starknet_api::core::PatriciaKey; use starknet_api::transaction::TransactionHash; -use crate::utils::felt_vm2api; - pub fn resource_bounds_core_to_api( resource_bounds: &ResourceBoundsMapping, ) -> starknet_api::transaction::ResourceBoundsMapping { @@ -47,51 +45,45 @@ pub fn starknet_rs_to_blockifier( Transaction::Invoke(tx) => { let (tx_hash, api_tx) = match tx { InvokeTransaction::V0(tx) => { - let _tx_hash = TransactionHash(felt_vm2api(tx.transaction_hash)); + let _tx_hash = TransactionHash(tx.transaction_hash); unimplemented!("starknet_rs_to_blockifier with InvokeTransaction::V0"); } InvokeTransaction::V1(tx) => { - let tx_hash = TransactionHash(felt_vm2api(tx.transaction_hash)); + let tx_hash = TransactionHash(tx.transaction_hash); let api_tx = starknet_api::transaction::InvokeTransaction::V1( starknet_api::transaction::InvokeTransactionV1 { max_fee: starknet_api::transaction::Fee(tx.max_fee.to_biguint().try_into()?), signature: starknet_api::transaction::TransactionSignature( - tx.signature.clone().into_iter().map(felt_vm2api).collect(), + tx.signature.clone().into_iter().collect(), ), - nonce: starknet_api::core::Nonce(felt_vm2api(tx.nonce)), + nonce: starknet_api::core::Nonce(tx.nonce), sender_address: starknet_api::core::ContractAddress( - PatriciaKey::try_from(felt_vm2api(tx.sender_address)).unwrap(), + PatriciaKey::try_from(tx.sender_address).unwrap(), ), calldata: starknet_api::transaction::Calldata(Arc::new( - tx.calldata.clone().into_iter().map(felt_vm2api).collect(), + tx.calldata.clone().into_iter().collect(), )), }, ); (tx_hash, api_tx) } InvokeTransaction::V3(tx) => { - let tx_hash = TransactionHash(felt_vm2api(tx.transaction_hash)); + let tx_hash = TransactionHash(tx.transaction_hash); let api_tx = starknet_api::transaction::InvokeTransaction::V3( starknet_api::transaction::InvokeTransactionV3 { resource_bounds: resource_bounds_core_to_api(&tx.resource_bounds), tip: starknet_api::transaction::Tip(tx.tip), - signature: starknet_api::transaction::TransactionSignature( - tx.signature.iter().copied().map(felt_vm2api).collect(), - ), - nonce: starknet_api::core::Nonce(felt_vm2api(tx.nonce)), + signature: starknet_api::transaction::TransactionSignature(tx.signature.to_vec()), + nonce: starknet_api::core::Nonce(tx.nonce), sender_address: starknet_api::core::ContractAddress( - PatriciaKey::try_from(felt_vm2api(tx.sender_address)).unwrap(), + PatriciaKey::try_from(tx.sender_address).unwrap(), ), - calldata: starknet_api::transaction::Calldata(Arc::new( - tx.calldata.iter().copied().map(felt_vm2api).collect(), - )), + calldata: starknet_api::transaction::Calldata(Arc::new(tx.calldata.to_vec())), nonce_data_availability_mode: da_mode_core_to_api(tx.nonce_data_availability_mode), fee_data_availability_mode: da_mode_core_to_api(tx.fee_data_availability_mode), - paymaster_data: starknet_api::transaction::PaymasterData( - tx.paymaster_data.iter().copied().map(felt_vm2api).collect(), - ), + paymaster_data: starknet_api::transaction::PaymasterData(tx.paymaster_data.to_vec()), account_deployment_data: starknet_api::transaction::AccountDeploymentData( - tx.account_deployment_data.iter().copied().map(felt_vm2api).collect(), + tx.account_deployment_data.to_vec(), ), }, ); diff --git a/crates/rpc-replay/src/utils.rs b/crates/rpc-replay/src/utils.rs index 5c7056263..c7e659c07 100644 --- a/crates/rpc-replay/src/utils.rs +++ b/crates/rpc-replay/src/utils.rs @@ -1,5 +1,4 @@ use starknet::core::types::Felt; -use starknet_api::hash::StarkFelt; /// Executes a coroutine from a synchronous context. /// Fails if no Tokio runtime is present. @@ -11,14 +10,6 @@ where Ok(tokio::task::block_in_place(|| tokio_runtime_handle.block_on(coroutine))) } -pub fn felt_api2vm(felt: StarkFelt) -> Felt { - Felt::from_bytes_be_slice(felt.bytes()) -} - -pub fn felt_vm2api(felt: Felt) -> StarkFelt { - StarkFelt::new_unchecked(felt.to_bytes_be()) -} - pub fn felt_to_u128(felt: &Felt) -> u128 { let digits = felt.to_be_digits(); ((digits[2] as u128) << 64) + digits[3] as u128 diff --git a/crates/rpc-replay/tests/test_replay_block.rs b/crates/rpc-replay/tests/test_replay_block.rs index d9bbb42f2..40b5178ab 100644 --- a/crates/rpc-replay/tests/test_replay_block.rs +++ b/crates/rpc-replay/tests/test_replay_block.rs @@ -1,5 +1,6 @@ use blockifier::state::cached_state::CachedState; use blockifier::transaction::transactions::ExecutableTransaction as _; +use blockifier::versioned_constants::StarknetVersion; use rpc_replay::block_context::build_block_context; use rpc_replay::rpc_state_reader::AsyncRpcStateReader; use rpc_replay::transactions::starknet_rs_to_blockifier; @@ -7,6 +8,7 @@ use rstest::rstest; use starknet::core::types::{BlockId, BlockWithTxs}; use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::{JsonRpcClient, Url}; +use starknet_api::core::ChainId; #[rstest] #[ignore = "Requires a local Pathfinder node"] @@ -27,7 +29,7 @@ async fn test_replay_block() { let state_reader = AsyncRpcStateReader::new(provider, BlockId::Number(block_with_txs.block_number - 1)); let mut state = CachedState::from(state_reader); - let block_context = build_block_context("SN_SEPOLIA".to_string(), &block_with_txs); + let block_context = build_block_context(ChainId::Sepolia, &block_with_txs, StarknetVersion::V0_13_1); for tx in block_with_txs.transactions.iter() { let blockifier_tx = starknet_rs_to_blockifier(tx).unwrap(); diff --git a/crates/starknet-os-types/src/casm_contract_class.rs b/crates/starknet-os-types/src/casm_contract_class.rs index ef1e62626..cb3a4ec2c 100644 --- a/crates/starknet-os-types/src/casm_contract_class.rs +++ b/crates/starknet-os-types/src/casm_contract_class.rs @@ -95,7 +95,7 @@ impl GenericCasmContractClass { let compiled_class = self.get_cairo_lang_contract_class()?; let class_hash_felt = compiled_class.compiled_class_hash(); - Ok(GenericClassHash::from_bytes_be(class_hash_felt.to_be_bytes())) + Ok(GenericClassHash::from_bytes_be(class_hash_felt.to_bytes_be())) } pub fn class_hash(&self) -> Result { diff --git a/crates/starknet-os-types/src/chain_id.rs b/crates/starknet-os-types/src/chain_id.rs index 7a51e97ca..c08cd08a9 100644 --- a/crates/starknet-os-types/src/chain_id.rs +++ b/crates/starknet-os-types/src/chain_id.rs @@ -5,3 +5,24 @@ use starknet_types_core::felt::Felt; pub fn chain_id_to_felt(chain_id: &ChainId) -> Felt { Felt::from_bytes_be_slice(chain_id.to_string().as_bytes()) } + +/// Builds a ChainId from a felt. +/// This function reads the felt as ASCII bytes. Leading zeroes are skipped. +pub fn chain_id_from_felt(felt: Felt) -> ChainId { + // Skip leading zeroes + let chain_id_bytes: Vec<_> = felt.to_bytes_be().into_iter().skip_while(|byte| *byte == 0u8).collect(); + let chain_id_str = String::from_utf8_lossy(&chain_id_bytes); + ChainId::from(chain_id_str.into_owned()) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_chain_id_from_felt() { + let chain_id_felt = Felt::from_dec_str("393402133025997798000961").unwrap(); + let chain_id = chain_id_from_felt(chain_id_felt); + assert_eq!(chain_id, ChainId::Sepolia); + } +} diff --git a/crates/starknet-os-types/src/hash.rs b/crates/starknet-os-types/src/hash.rs index aacced374..b8a0eada2 100644 --- a/crates/starknet-os-types/src/hash.rs +++ b/crates/starknet-os-types/src/hash.rs @@ -3,8 +3,6 @@ use std::ops::Deref; use num_bigint::BigUint; use serde::{Deserialize, Serialize}; use starknet_api::core::{ClassHash, CompiledClassHash}; -use starknet_api::hash::{StarkFelt, StarkHash}; -use starknet_api::StarknetApiError; use starknet_types_core::felt::Felt; const EMPTY_HASH: [u8; 32] = [0; 32]; @@ -80,27 +78,15 @@ impl From for Hash { } } -impl TryFrom for StarkFelt { - type Error = StarknetApiError; - - fn try_from(hash: Hash) -> Result { - Self::new(hash.0) - } -} - -impl TryFrom for CompiledClassHash { - type Error = StarknetApiError; - - fn try_from(hash: Hash) -> Result { - Ok(Self(hash.try_into()?)) +impl From for CompiledClassHash { + fn from(hash: Hash) -> Self { + Self(hash.into()) } } -impl TryFrom for ClassHash { - type Error = StarknetApiError; - - fn try_from(hash: Hash) -> Result { - Ok(Self(hash.try_into()?)) +impl From for ClassHash { + fn from(hash: Hash) -> Self { + Self(hash.into()) } } @@ -119,22 +105,20 @@ impl GenericClassHash { impl From for GenericClassHash { fn from(class_hash: ClassHash) -> Self { - let hash = Hash::from_bytes_be_slice(class_hash.0.bytes()); + let hash = Hash(class_hash.0.to_bytes_be()); Self(hash) } } impl From for ClassHash { fn from(class_hash: GenericClassHash) -> Self { - let stark_hash = StarkHash::new_unchecked(class_hash.0.0); - ClassHash(stark_hash) + class_hash.0.into() } } impl From for CompiledClassHash { fn from(class_hash: GenericClassHash) -> Self { - let stark_hash = StarkHash::new_unchecked(class_hash.0.0); - CompiledClassHash(stark_hash) + class_hash.0.into() } } diff --git a/crates/starknet-os/src/config.rs b/crates/starknet-os/src/config.rs index 54d05d02e..aca727c6c 100644 --- a/crates/starknet-os/src/config.rs +++ b/crates/starknet-os/src/config.rs @@ -1,7 +1,8 @@ use std::fs::File; use std::path::PathBuf; -use blockifier::block::{BlockInfo, GasPrices}; +use blockifier::blockifier::block::{BlockInfo, GasPrices}; +use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; use blockifier::transaction::objects::FeeType; use blockifier::versioned_constants::VersionedConstants; @@ -10,9 +11,7 @@ use serde::{Deserialize, Serialize}; use serde_with::serde_as; use starknet_api::block::{BlockNumber, BlockTimestamp}; use starknet_api::core::{ChainId, ContractAddress, PatriciaKey}; -use starknet_api::hash::{pedersen_hash_array, StarkFelt, StarkHash}; -use starknet_api::{contract_address, patricia_key}; -use starknet_crypto::FieldElement; +use starknet_api::{contract_address, felt, patricia_key}; use crate::error::SnOsError; use crate::utils::ChainIdNum; @@ -54,16 +53,6 @@ pub struct StarknetOsConfig { pub deprecated_fee_token_address: ContractAddress, } -impl StarknetOsConfig { - pub fn hash(&self) -> StarkHash { - pedersen_hash_array(&[ - StarkFelt::from(FieldElement::from_byte_slice_be(STARKNET_OS_CONFIG_HASH_VERSION.as_bytes()).unwrap()), - StarkFelt::from(u128::from_str_radix(&self.chain_id.0, 16).unwrap()), - *self.fee_token_address.0.key(), - ]) - } -} - #[derive(Debug, Serialize, Clone, Deserialize, PartialEq)] pub struct GasPriceBounds { pub min_wei_l1_gas_price: u128, @@ -91,7 +80,7 @@ impl Default for StarknetGeneralConfig { fn default() -> Self { Self { starknet_os_config: StarknetOsConfig { - chain_id: ChainId("SN_GOERLI".to_string()), + chain_id: ChainId::Sepolia, fee_token_address: contract_address!(DEFAULT_FEE_TOKEN_ADDR), deprecated_fee_token_address: contract_address!(DEFAULT_DEPRECATED_FEE_TOKEN_ADDR), }, @@ -152,7 +141,9 @@ impl StarknetGeneralConfig { }, }; - BlockContext::new_unchecked(&block_info, &chain_info, &versioned_constants) + let bouncer_config = BouncerConfig::max(); + + BlockContext::new(block_info, chain_info, versioned_constants, bouncer_config) } } diff --git a/crates/starknet-os/src/execution/deprecated_syscall_handler.rs b/crates/starknet-os/src/execution/deprecated_syscall_handler.rs index 965cae89d..9e1c78624 100644 --- a/crates/starknet-os/src/execution/deprecated_syscall_handler.rs +++ b/crates/starknet-os/src/execution/deprecated_syscall_handler.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use blockifier::block::BlockInfo; +use blockifier::blockifier::block::BlockInfo; use cairo_vm::types::relocatable::{MaybeRelocatable, Relocatable}; use cairo_vm::vm::errors::hint_errors::HintError; use cairo_vm::vm::vm_core::VirtualMachine; @@ -15,7 +15,6 @@ use crate::cairo_types::syscalls::{ TxInfo, }; use crate::starknet::starknet_storage::PerContractStorage; -use crate::utils::felt_api2vm; /// DeprecatedSyscallHandler implementation for execution of system calls in the StarkNet OS #[derive(Debug)] @@ -81,15 +80,7 @@ where // the result array. vm.insert_value((syscall_ptr + retdata_size_offset)?, result.retdata.0.len())?; let new_segment = vm.add_temporary_segment(); - let retdata = result - .retdata - .0 - .iter() - .map(|sf| { - let felt = felt_api2vm(*sf); - MaybeRelocatable::Int(felt) - }) - .collect(); + let retdata: Vec<_> = result.retdata.0.iter().map(|felt| MaybeRelocatable::Int(*felt)).collect(); vm.load_data(new_segment, &retdata)?; vm.insert_value((syscall_ptr + retdata_offset)?, new_segment)?; @@ -173,7 +164,6 @@ where let exec_helper = sys_hand.exec_wrapper.execution_helper.read().await; let caller_address = exec_helper.call_info.as_ref().expect("A call should have some call info").call.caller_address.0.key(); - let caller_address = felt_api2vm(*caller_address); // TODO: create proper struct for this (similar to GetCallerAddress and friends) // TODO: abstract this similar to pythonic _write_syscall_response() @@ -194,7 +184,7 @@ where exec_helper.call_info.as_ref().map(|info| info.call.storage_address).ok_or(HintError::SyscallError( "Missing storage address from call info".to_string().into_boxed_str(), ))?; - let contract_address_felt = felt_api2vm(*contract_address.0.key()); + let contract_address_felt = *contract_address.0.key(); let response_offset = GetContractAddress::response_offset() + GetContractAddressResponse::contract_address_offset(); @@ -209,7 +199,7 @@ where ) -> Result<(), HintError> { let syscall_handler = self.deprecated_syscall_handler.read().await; - let sequencer_address = felt_api2vm(*syscall_handler.block_info.sequencer_address.0.key()); + let sequencer_address = *syscall_handler.block_info.sequencer_address.0.key(); let response_offset = GetSequencerAddress::response_offset() + GetSequencerAddressResponse::sequencer_address_offset(); @@ -273,17 +263,12 @@ where HintError::SyscallError("No more storage reads available to replay".to_string().into_boxed_str()), )?; - vm.insert_value((syscall_ptr + 2usize).unwrap(), value).unwrap(); + vm.insert_value((syscall_ptr + 2usize)?, value)?; Ok(()) } pub async fn storage_write(&self, _syscall_ptr: Relocatable) -> Result<(), HintError> { - let sys_hand = self.deprecated_syscall_handler.write().await; - - let _ = sys_hand.exec_wrapper.execution_helper.write().await.execute_code_read_iter.next().ok_or( - HintError::SyscallError("No more storage writes available to replay".to_string().into_boxed_str()), - )?; - + // Nothing to do Ok(()) } @@ -302,7 +287,8 @@ where mod test { use std::borrow::Cow; - use blockifier::block::{BlockInfo, GasPrices}; + use blockifier::blockifier::block::{BlockInfo, GasPrices}; + use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; use blockifier::execution::call_info::Retdata; use blockifier::execution::entry_point_execution::CallResult; @@ -314,8 +300,7 @@ mod test { use rstest::{fixture, rstest}; use starknet_api::block::{BlockNumber, BlockTimestamp}; use starknet_api::core::{ChainId, ContractAddress, PatriciaKey}; - use starknet_api::hash::{StarkFelt, StarkHash}; - use starknet_api::{contract_address, patricia_key}; + use starknet_api::{contract_address, felt, patricia_key}; use crate::config::STORED_BLOCK_HASH_BUFFER; use crate::crypto::pedersen::PedersenHash; @@ -328,7 +313,7 @@ mod test { #[fixture] fn block_context() -> BlockContext { let chain_info = ChainInfo { - chain_id: ChainId("SN_GOERLI".to_string()), + chain_id: ChainId::Sepolia, fee_token_addresses: FeeTokenAddresses { strk_fee_token_address: contract_address!("0x1"), eth_fee_token_address: contract_address!("0x2"), @@ -348,7 +333,7 @@ mod test { use_kzg_da: false, }; - BlockContext::new_unchecked(&block_info, &chain_info, VersionedConstants::latest_constants()) + BlockContext::new(block_info, chain_info, VersionedConstants::latest_constants().clone(), BouncerConfig::max()) } #[fixture] @@ -380,7 +365,7 @@ mod test { // segment and insert its size somewhere in syscall_ptr. let call_results = vec![CallResult { failed: false, - retdata: Retdata(vec![StarkFelt::THREE, StarkFelt::TWO, StarkFelt::ONE]), + retdata: Retdata(vec![Felt252::THREE, Felt252::TWO, Felt252::ONE]), gas_consumed: 1, }]; exec_helper.execution_helper.write().await.result_iter = call_results.into_iter(); diff --git a/crates/starknet-os/src/execution/helper.rs b/crates/starknet-os/src/execution/helper.rs index 9129ab2c7..c66c669db 100644 --- a/crates/starknet-os/src/execution/helper.rs +++ b/crates/starknet-os/src/execution/helper.rs @@ -150,7 +150,7 @@ where .iter() .filter_map(|call| { if matches!(call.call.entry_point_type, EntryPointType::Constructor) { - Some(Felt252::from_bytes_be_slice(call.call.storage_address.0.key().bytes())) + Some(Felt252::from(call.call.storage_address)) } else { None } @@ -171,13 +171,7 @@ where .into_iter(); // unpack storage reads - eh_ref.execute_code_read_iter = call_info - .storage_read_values - .iter() - .map(|felt| Felt252::from_bytes_be_slice(felt.bytes())) - .collect::>() - .into_iter(); - + eh_ref.execute_code_read_iter = call_info.storage_read_values.clone().into_iter(); eh_ref.call_info = Some(call_info); } pub async fn exit_call(&mut self) { @@ -224,6 +218,7 @@ where let mut commitments = HashMap::new(); for (key, storage) in storage_by_address.iter_mut() { + log::debug!("Computing commitment for contract address {}", key.to_hex_string()); let commitment_info = storage.compute_commitment().await?; commitments.insert(*key, commitment_info); } diff --git a/crates/starknet-os/src/execution/syscall_handler.rs b/crates/starknet-os/src/execution/syscall_handler.rs index 6e92d40c0..b08367bae 100644 --- a/crates/starknet-os/src/execution/syscall_handler.rs +++ b/crates/starknet-os/src/execution/syscall_handler.rs @@ -22,7 +22,6 @@ use crate::execution::syscall_handler_utils::{ ReadOnlySegment, SyscallExecutionError, SyscallHandler, SyscallResult, SyscallSelector, WriteResponseResult, }; use crate::starknet::starknet_storage::PerContractStorage; -use crate::utils::felt_api2vm; /// DeprecatedSyscallHandler implementation for execution of system calls in the StarkNet OS #[derive(Debug)] @@ -162,14 +161,14 @@ impl SyscallHandler for CallContractHandler { *remaining_gas -= result.gas_consumed; - let retdata = result.retdata.0.iter().map(|sf| felt_api2vm(*sf)).collect(); + let retdata = result.retdata.0; if result.failed { return Err(SyscallExecutionError::SyscallError { error_data: retdata }); } let start_ptr = vm.add_temporary_segment(); - vm.load_data(start_ptr, &retdata.iter().map(MaybeRelocatable::from).collect())?; + vm.load_data(start_ptr, &retdata.iter().map(MaybeRelocatable::from).collect::>())?; Ok(ReadOnlySegment { start_ptr, length: retdata.len() }) } @@ -216,14 +215,14 @@ impl SyscallHandler for DeployHandler { *remaining_gas -= result.gas_consumed; - let retdata = result.retdata.0.iter().map(|sf| felt_api2vm(*sf)).collect(); + let retdata = result.retdata.0; if result.failed { return Err(SyscallExecutionError::SyscallError { error_data: retdata }); } let start_ptr = vm.add_temporary_segment(); - vm.load_data(start_ptr, &retdata.iter().map(MaybeRelocatable::from).collect())?; + vm.load_data(start_ptr, &retdata.iter().map(MaybeRelocatable::from).collect::>())?; let constructor_retdata = ReadOnlySegment { start_ptr, length: retdata.len() }; @@ -377,14 +376,14 @@ impl SyscallHandler for LibraryCallHandler { *remaining_gas -= result.gas_consumed; - let retdata = result.retdata.0.iter().map(|sf| felt_api2vm(*sf)).collect(); + let retdata = result.retdata.0; if result.failed { return Err(SyscallExecutionError::SyscallError { error_data: retdata }); } let start_ptr = vm.add_temporary_segment(); - vm.load_data(start_ptr, &retdata.iter().map(MaybeRelocatable::from).collect())?; + vm.load_data(start_ptr, &retdata.iter().map(MaybeRelocatable::from).collect::>())?; Ok(ReadOnlySegment { start_ptr, length: retdata.len() }) } diff --git a/crates/starknet-os/src/execution/syscall_handler_utils.rs b/crates/starknet-os/src/execution/syscall_handler_utils.rs index 9e8ffa149..503bf137d 100644 --- a/crates/starknet-os/src/execution/syscall_handler_utils.rs +++ b/crates/starknet-os/src/execution/syscall_handler_utils.rs @@ -261,7 +261,8 @@ fn write_failure( // Write the error data to a new memory segment. let revert_reason_start = vm.add_memory_segment(); - let revert_reason_end = vm.load_data(revert_reason_start, &error_data.into_iter().map(Into::into).collect())?; + let revert_reason_end = + vm.load_data(revert_reason_start, &error_data.into_iter().map(Into::into).collect::>())?; // Write the start and end pointers of the error data. write_maybe_relocatable(vm, ptr, revert_reason_start)?; diff --git a/crates/starknet-os/src/hints/block_context.rs b/crates/starknet-os/src/hints/block_context.rs index 87e71834d..1d8653adc 100644 --- a/crates/starknet-os/src/hints/block_context.rs +++ b/crates/starknet-os/src/hints/block_context.rs @@ -24,7 +24,7 @@ use crate::hints::vars; use crate::io::classes::write_class; use crate::io::input::StarknetOsInput; use crate::starknet::core::os::contract_class::compiled_class_hash_objects::BytecodeSegmentStructureImpl; -use crate::utils::{custom_hint_error, felt_api2vm, get_constant}; +use crate::utils::{custom_hint_error, get_constant}; pub const LOAD_CLASS_FACTS: &str = indoc! {r#" ids.compiled_class_facts = segments.add() @@ -234,7 +234,7 @@ pub fn fee_token_address( let os_input = exec_scopes.get::(vars::scopes::OS_INPUT)?; let fee_token_address = *os_input.general_config.starknet_os_config.fee_token_address.0.key(); log::debug!("fee_token_address: {}", fee_token_address); - insert_value_into_ap(vm, felt_api2vm(fee_token_address)) + insert_value_into_ap(vm, fee_token_address) } pub const DEPRECATED_FEE_TOKEN_ADDRESS: &str = @@ -249,7 +249,7 @@ pub fn deprecated_fee_token_address( let os_input = exec_scopes.get::(vars::scopes::OS_INPUT)?; let deprecated_fee_token_address = *os_input.general_config.starknet_os_config.deprecated_fee_token_address.0.key(); log::debug!("deprecated_fee_token_address: {}", deprecated_fee_token_address); - insert_value_into_ap(vm, felt_api2vm(deprecated_fee_token_address)) + insert_value_into_ap(vm, deprecated_fee_token_address) } pub const SEQUENCER_ADDRESS: &str = "memory[ap] = to_felt_or_relocatable(syscall_handler.block_info.sequencer_address)"; @@ -261,7 +261,7 @@ pub fn sequencer_address( _constants: &HashMap, ) -> Result<(), HintError> { let block_context = exec_scopes.get_ref::(vars::scopes::BLOCK_CONTEXT)?; - insert_value_into_ap(vm, felt_api2vm(*block_context.block_info().sequencer_address.0.key())) + insert_value_into_ap(vm, *block_context.block_info().sequencer_address.0.key()) } pub const GET_BLOCK_MAPPING: &str = indoc! {r#" diff --git a/crates/starknet-os/src/hints/execution.rs b/crates/starknet-os/src/hints/execution.rs index df92d0abc..d12142c0b 100644 --- a/crates/starknet-os/src/hints/execution.rs +++ b/crates/starknet-os/src/hints/execution.rs @@ -138,7 +138,8 @@ pub fn prepare_constructor_execution( ap_tracking, )?; - let constructor_calldata = tx.constructor_calldata.unwrap_or_default().iter().map(|felt| felt.into()).collect(); + let constructor_calldata = + tx.constructor_calldata.unwrap_or_default().iter().map(|felt| felt.into()).collect::>(); let constructor_calldata_base = vm.add_memory_segment(); vm.load_data(constructor_calldata_base, &constructor_calldata)?; insert_value_from_var_name(vars::ids::CONSTRUCTOR_CALLDATA, constructor_calldata_base, vm, ids_data, ap_tracking) @@ -586,7 +587,7 @@ pub fn tx_calldata( ) -> Result<(), HintError> { let tx = exec_scopes.get::(vars::scopes::TX)?; let calldata = - tx.calldata.ok_or(custom_hint_error("tx.calldata is None"))?.iter().map(|felt| felt.into()).collect(); + tx.calldata.ok_or(custom_hint_error("tx.calldata is None"))?.iter().map(|felt| felt.into()).collect::>(); let calldata_base = vm.add_memory_segment(); vm.load_data(calldata_base, &calldata)?; insert_value_into_ap(vm, calldata_base) @@ -849,7 +850,7 @@ pub fn gen_signature_arg( let tx = exec_scopes.get::(vars::scopes::TX)?; let signature = tx.signature.ok_or(custom_hint_error("tx.signature is None"))?; let signature_start_base = vm.add_memory_segment(); - let signature = signature.iter().map(|f| MaybeRelocatable::Int(*f)).collect(); + let signature = signature.iter().map(|f| MaybeRelocatable::Int(*f)).collect::>(); vm.load_data(signature_start_base, &signature)?; insert_value_from_var_name(vars::ids::SIGNATURE_START, signature_start_base, vm, ids_data, ap_tracking)?; diff --git a/crates/starknet-os/src/hints/mod.rs b/crates/starknet-os/src/hints/mod.rs index 72f767181..275ee8683 100644 --- a/crates/starknet-os/src/hints/mod.rs +++ b/crates/starknet-os/src/hints/mod.rs @@ -567,7 +567,7 @@ where .tx_execution_info .as_ref() .ok_or(HintError::CustomHint("ExecutionHelper should have tx_execution_info".to_owned().into_boxed_str())) - .map(|tx_execution_info| tx_execution_info.actual_fee) + .map(|tx_execution_info| tx_execution_info.transaction_receipt.fee) })??; insert_value_into_ap(vm, Felt252::from(actual_fee.0)) diff --git a/crates/starknet-os/src/hints/tests.rs b/crates/starknet-os/src/hints/tests.rs index 87546aca4..0906d1dbb 100644 --- a/crates/starknet-os/src/hints/tests.rs +++ b/crates/starknet-os/src/hints/tests.rs @@ -1,6 +1,7 @@ #[cfg(test)] pub mod tests { use blockifier::context::BlockContext; + use blockifier::fee::actual_cost::TransactionReceipt; use blockifier::transaction::objects::TransactionExecutionInfo; use cairo_vm::serde::deserialize_program::ApTracking; use cairo_vm::types::exec_scope::ExecutionScopes; @@ -60,11 +61,13 @@ pub mod tests { validate_call_info: None, execute_call_info: None, fee_transfer_call_info: None, - actual_fee: Fee(1234), - da_gas: Default::default(), - actual_resources: Default::default(), revert_error: None, - bouncer_resources: Default::default(), + transaction_receipt: TransactionReceipt { + fee: Fee(1234), + gas: Default::default(), + da_gas: Default::default(), + resources: Default::default(), + }, } } diff --git a/crates/starknet-os/src/io/classes.rs b/crates/starknet-os/src/io/classes.rs index 7c3e2bd90..ee7dd1d56 100644 --- a/crates/starknet-os/src/io/classes.rs +++ b/crates/starknet-os/src/io/classes.rs @@ -14,7 +14,7 @@ use crate::starknet::core::os::contract_class::compiled_class_hash_objects::{ BytecodeLeaf, BytecodeSegment, BytecodeSegmentStructureImpl, BytecodeSegmentedNode, }; use crate::starkware_utils::commitment_tree::base_types::Length; -use crate::utils::{custom_hint_error, felt_api2vm}; +use crate::utils::custom_hint_error; /// Returns the serialization of a contract as a list of field elements. pub fn get_deprecated_contract_class_struct( @@ -26,7 +26,7 @@ pub fn get_deprecated_contract_class_struct( let mut externals: Vec = Vec::new(); for elem in deprecated_class.entry_points_by_type.get(&EntryPointType::External).unwrap().iter() { - externals.push(MaybeRelocatable::from(felt_api2vm(elem.selector.0))); + externals.push(MaybeRelocatable::from(elem.selector.0)); externals.push(MaybeRelocatable::from(Felt252::from(elem.offset.0))); } vm.insert_value((class_base + 1)?, Felt252::from(externals.len() / 2))?; @@ -37,7 +37,7 @@ pub fn get_deprecated_contract_class_struct( let mut l1_handlers: Vec = Vec::new(); for elem in deprecated_class.entry_points_by_type.get(&EntryPointType::L1Handler).unwrap().iter() { - l1_handlers.push(MaybeRelocatable::from(felt_api2vm(elem.selector.0))); + l1_handlers.push(MaybeRelocatable::from(elem.selector.0)); l1_handlers.push(MaybeRelocatable::from(Felt252::from(elem.offset.0))); } vm.insert_value((class_base + 3)?, Felt252::from(l1_handlers.len() / 2))?; @@ -48,7 +48,7 @@ pub fn get_deprecated_contract_class_struct( let mut constructors: Vec = Vec::new(); for elem in deprecated_class.entry_points_by_type.get(&EntryPointType::Constructor).unwrap().iter() { - constructors.push(MaybeRelocatable::from(felt_api2vm(elem.selector.0))); + constructors.push(MaybeRelocatable::from(elem.selector.0)); constructors.push(MaybeRelocatable::from(Felt252::from(elem.offset.0))); } vm.insert_value((class_base + 5)?, Felt252::from(constructors.len() / 2))?; diff --git a/crates/starknet-os/src/starknet/business_logic/fact_state/state.rs b/crates/starknet-os/src/starknet/business_logic/fact_state/state.rs index 360d4b8f3..28d428c69 100644 --- a/crates/starknet-os/src/starknet/business_logic/fact_state/state.rs +++ b/crates/starknet-os/src/starknet/business_logic/fact_state/state.rs @@ -8,9 +8,7 @@ use blockifier::state::state_api::{StateReader, StateResult}; use cairo_vm::types::errors::math_errors::MathError; use cairo_vm::Felt252; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, Nonce}; -use starknet_api::hash::StarkFelt; use starknet_api::state::StorageKey; -use starknet_crypto::FieldElement; use starknet_os_types::casm_contract_class::GenericCasmContractClass; use starknet_os_types::deprecated_compiled_class::GenericDeprecatedCompiledClass; use starknet_os_types::hash::Hash; @@ -28,9 +26,10 @@ use crate::starknet::starknet_storage::StorageLeaf; use crate::starkware_utils::commitment_tree::base_types::{Height, TreeIndex}; use crate::starkware_utils::commitment_tree::binary_fact_tree::BinaryFactTree; use crate::starkware_utils::commitment_tree::errors::TreeError; +use crate::starkware_utils::commitment_tree::leaf_fact::LeafFact; use crate::starkware_utils::commitment_tree::patricia_tree::patricia_tree::PatriciaTree; use crate::storage::storage::{DbObject, FactFetchingContext, HashFunctionType, Storage, StorageError}; -use crate::utils::{execute_coroutine, felt_api2vm, felt_vm2api}; +use crate::utils::execute_coroutine; /// A class representing a combination of the onchain and offchain state. #[derive(Debug)] @@ -166,7 +165,7 @@ where ) -> Result { let empty_state = Self::empty(ffc).await?; - let mut storage_updates: HashMap> = HashMap::new(); + let mut storage_updates: HashMap> = HashMap::new(); for ((address, key), value) in blockifier_state.storage_view { storage_updates.entry(address).or_default().insert(key, value); } @@ -205,33 +204,23 @@ where address_to_class_hash: HashMap, address_to_nonce: HashMap, class_hash_to_compiled_class_hash: HashMap, - storage_updates: HashMap>, + storage_updates: HashMap>, ) -> Result { - let address_to_class_hash: HashMap<_, _> = address_to_class_hash - .into_iter() - .map(|(address, class_hash)| (felt_api2vm(*address.0.key()), felt_api2vm(class_hash.0))) - .collect(); + let address_to_class_hash: HashMap<_, _> = + address_to_class_hash.into_iter().map(|(address, class_hash)| (*address.0.key(), class_hash.0)).collect(); - let address_to_nonce: HashMap<_, _> = address_to_nonce - .into_iter() - .map(|(address, nonce)| (felt_api2vm(*address.0.key()), felt_api2vm(nonce.0))) - .collect(); + let address_to_nonce: HashMap<_, _> = + address_to_nonce.into_iter().map(|(address, nonce)| (*address.0.key(), nonce.0)).collect(); let class_hash_to_compiled_class_hash: HashMap<_, _> = class_hash_to_compiled_class_hash .into_iter() - .map(|(class_hash, compiled_class_hash)| (felt_api2vm(class_hash.0), felt_api2vm(compiled_class_hash.0))) + .map(|(class_hash, compiled_class_hash)| (class_hash.0, compiled_class_hash.0)) .collect(); let storage_updates: HashMap<_, HashMap<_, _>> = storage_updates .into_iter() .map(|(address, contract_storage_updates)| { - ( - felt_api2vm(*address.0.key()), - contract_storage_updates - .into_iter() - .map(|(k, v)| (felt_api2vm(*k.0.key()), felt_api2vm(v))) - .collect(), - ) + (*address.0.key(), contract_storage_updates.into_iter().map(|(k, v)| (*k.0.key(), v)).collect()) }) .collect(); @@ -325,7 +314,7 @@ where } async fn get_contract_state_async(&self, contract_address: ContractAddress) -> StateResult { - let contract_address: TreeIndex = felt_api2vm(*contract_address.0.key()).to_biguint(); + let contract_address: TreeIndex = contract_address.0.key().to_biguint(); let mut ffc = self.ffc.clone(); @@ -350,7 +339,7 @@ where } async fn get_compiled_class_hash_async(&self, class_hash: ClassHash) -> StateResult { - let class_hash_as_index: TreeIndex = felt_api2vm(class_hash.0).to_biguint(); + let class_hash_as_index: TreeIndex = class_hash.0.to_biguint(); log::debug!("class_hash_as_index: {:?}", class_hash_as_index); log::debug!("have contract_class_tree? {:?}", self.contract_classes.is_some()); @@ -361,6 +350,7 @@ where log::debug!("Should get something from get_leaf()..."); + // TODO: `get_leaf()` should not return an option let contract_class_leaf = >::get_leaf( contract_class_tree, @@ -370,6 +360,11 @@ where .await? .ok_or(StateError::UndeclaredClassHash(class_hash))?; + // Return an error if we get an empty leaf + if >::is_empty(&contract_class_leaf) { + return Err(StateError::UndeclaredClassHash(class_hash))?; + } + contract_class_leaf.compiled_class_hash } // The tree is not initialized; may happen if the reader is based on an old state @@ -377,34 +372,34 @@ where None => Felt252::ZERO, }; - Ok(CompiledClassHash(felt_vm2api(compiled_class_hash))) + Ok(CompiledClassHash(compiled_class_hash)) } async fn get_deprecated_compiled_class( - &mut self, + &self, compiled_class_hash: CompiledClassHash, ) -> Result, StorageError> { let storage = self.ffc.acquire_storage().await; - DeprecatedCompiledClassFact::get(storage.deref(), compiled_class_hash.0.bytes()) + DeprecatedCompiledClassFact::get(storage.deref(), &compiled_class_hash.0.to_bytes_be()) .await .map(|option| option.map(|fact| fact.contract_definition)) } async fn get_compiled_class( - &mut self, + &self, compiled_class_hash: CompiledClassHash, ) -> Result, StorageError> { let storage = self.ffc.acquire_storage().await; - CompiledClassFact::get(storage.deref(), compiled_class_hash.0.bytes()) + CompiledClassFact::get(storage.deref(), &compiled_class_hash.0.to_bytes_be()) .await .map(|option| option.map(|fact| fact.compiled_class)) } /// Returns the contract class of the given class hash. async fn get_compiled_contract_class_async( - &mut self, + &self, compiled_class_hash: CompiledClassHash, ) -> StateResult { log::debug!("SharedState as StateReader: get_compiled_contract_class {:?}", compiled_class_hash); @@ -430,22 +425,20 @@ where Err(StateError::UndeclaredClassHash(ClassHash(compiled_class_hash.0))) } - async fn get_storage_at_async( - &mut self, - contract_address: ContractAddress, - key: StorageKey, - ) -> StateResult { - let storage_key: TreeIndex = felt_api2vm(*key.0.key()).to_biguint(); + async fn get_storage_at_async(&self, contract_address: ContractAddress, key: StorageKey) -> StateResult { + let storage_key: TreeIndex = key.0.key().to_biguint(); + + let mut ffc = self.ffc.clone(); let contract_state = self.get_contract_state_async(contract_address).await?; let storage_items: HashMap = - contract_state.storage_commitment_tree.get_leaves(&mut self.ffc, &[storage_key.clone()], &mut None).await?; + contract_state.storage_commitment_tree.get_leaves(&mut ffc, &[storage_key.clone()], &mut None).await?; let state = storage_items .get(&storage_key) .ok_or(StateError::StateReadError(format!("get_storage_at_async: {:?}", storage_key)))?; - Ok(felt_vm2api(state.value)) + Ok(state.value) } } @@ -457,7 +450,7 @@ where /// Returns the storage value under the given key in the given contract instance (represented by /// its address). /// Default: 0 for an uninitialized contract address. - fn get_storage_at(&mut self, contract_address: ContractAddress, key: StorageKey) -> StateResult { + fn get_storage_at(&self, contract_address: ContractAddress, key: StorageKey) -> StateResult { log::debug!("SharedState as StateReader: get_storage_at {:?} / {:?}", contract_address, key); let value = execute_coroutine(self.get_storage_at_async(contract_address, key)).unwrap(); // TODO: unwrap log::debug!(" -> {:?}", value); @@ -466,40 +459,37 @@ where /// Returns the nonce of the given contract instance. /// Default: 0 for an uninitialized contract address. - fn get_nonce_at(&mut self, contract_address: ContractAddress) -> StateResult { + fn get_nonce_at(&self, contract_address: ContractAddress) -> StateResult { log::debug!("SharedState as StateReader: get_nonce_at {:?}", contract_address); let contract_state = self.get_contract_state(contract_address)?; - let nonce = Nonce(felt_vm2api(contract_state.nonce)); + let nonce = Nonce(contract_state.nonce); log::debug!(" -> {:?}", nonce); Ok(nonce) } /// Returns the class hash of the contract class at the given contract instance. /// Default: 0 (uninitialized class hash) for an uninitialized contract address. - fn get_class_hash_at(&mut self, contract_address: ContractAddress) -> StateResult { + fn get_class_hash_at(&self, contract_address: ContractAddress) -> StateResult { log::debug!("SharedState as StateReader: get_class_hash_at {:?}", contract_address); let contract_state = self.get_contract_state(contract_address)?; // TODO: this can be simplified once hashes are stored as [u8; 32]. Until then, this is fine. - let felt = FieldElement::from_byte_slice_be(&contract_state.contract_hash) - .expect("Conversion to felt should not fail"); + let felt = Felt252::from_bytes_be_slice(&contract_state.contract_hash); log::debug!(" -> {:?}", felt); - Ok(ClassHash(StarkFelt::from(felt))) + Ok(ClassHash(felt)) } /// Returns the contract class of the given class hash. - fn get_compiled_contract_class(&mut self, class_hash: ClassHash) -> StateResult { + fn get_compiled_contract_class(&self, class_hash: ClassHash) -> StateResult { execute_coroutine(async { - let compiled_class_hash = self.get_compiled_class_hash_async(class_hash).await.unwrap(); + let compiled_class_hash = self.get_compiled_class_hash_async(class_hash).await?; self.get_compiled_contract_class_async(compiled_class_hash).await }) .unwrap() // TODO: unwrap } /// Returns the compiled class hash of the given class hash. - fn get_compiled_class_hash(&mut self, class_hash: ClassHash) -> StateResult { + fn get_compiled_class_hash(&self, class_hash: ClassHash) -> StateResult { log::debug!("SharedState as StateReader: get_compiled_class_hash {:?}", class_hash); execute_coroutine(self.get_compiled_class_hash_async(class_hash)).unwrap() // TODO: unwrap } - - // TODO: do we care about `fn get_free_token_balance()`? } diff --git a/crates/starknet-os/src/storage/storage_utils.rs b/crates/starknet-os/src/storage/storage_utils.rs index 5ba77101a..43b34aad9 100644 --- a/crates/starknet-os/src/storage/storage_utils.rs +++ b/crates/starknet-os/src/storage/storage_utils.rs @@ -1,5 +1,4 @@ use blockifier::state::cached_state::CachedState; -use blockifier::state::state_api::State; use cairo_vm::Felt252; use starknet_os_types::hash::Hash; @@ -63,12 +62,16 @@ where } } +// TODO: move this function to where it is used, this should not be a public function of +// the starknet-os library pub async fn unpack_blockifier_state_async( mut blockifier_state: CachedState>, ) -> Result<(SharedState, SharedState), TreeError> { let final_state = { let state = blockifier_state.state.clone(); - state.apply_commitment_state_diff(blockifier_state.to_state_diff()).await? + state + .apply_commitment_state_diff(blockifier_state.to_state_diff().expect("failed to build state diff").into()) + .await? }; let initial_state = blockifier_state.state; diff --git a/crates/starknet-os/src/utils.rs b/crates/starknet-os/src/utils.rs index 606a044f0..65937282e 100644 --- a/crates/starknet-os/src/utils.rs +++ b/crates/starknet-os/src/utils.rs @@ -3,22 +3,13 @@ use std::collections::HashMap; use cairo_vm::types::exec_scope::ExecutionScopes; use cairo_vm::vm::errors::hint_errors::HintError; use cairo_vm::Felt252; -use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer}; +use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; use serde_json::Number; use serde_with::{DeserializeAs, SerializeAs}; use starknet_api::core::ChainId; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; +use starknet_os_types::chain_id::chain_id_to_felt; use tokio::task; -pub fn felt_vm2api(felt: Felt252) -> StarkFelt { - stark_felt!(felt.to_hex_string().as_str()) -} - -pub fn felt_api2vm(felt: StarkFelt) -> Felt252 { - Felt252::from_hex(&felt.to_string()).expect("Couldn't parse bytes") -} - pub(crate) struct Felt252Str; impl<'de> DeserializeAs<'de, Felt252> for Felt252Str { @@ -96,8 +87,10 @@ impl<'de> DeserializeAs<'de, ChainId> for ChainIdNum { where D: Deserializer<'de>, { - let felt_num = u128::deserialize(deserializer)?; - Ok(ChainId(format!("{felt_num:x}"))) + let bytes = u128::deserialize(deserializer)?.to_be_bytes(); + let chain_id_str = String::from_utf8_lossy(&bytes); + + Ok(ChainId::from(chain_id_str.into_owned())) } } @@ -106,7 +99,8 @@ impl SerializeAs for ChainIdNum { where S: Serializer, { - serializer.serialize_u128(u128::from_str_radix(&value.0, 16).map_err(ser::Error::custom)?) + let chain_id_felt = chain_id_to_felt(value); + chain_id_felt.serialize(serializer) } } @@ -159,7 +153,6 @@ pub(crate) fn custom_hint_error>(error: S) -> HintError { #[cfg(test)] mod tests { - use bitvec::prelude::*; use serde_with::serde_as; use super::*; @@ -171,30 +164,9 @@ mod tests { chain_id: ChainId, } - #[test] - fn felt_conversions() { - let vm_felt = Felt252::from_hex("0xDEADBEEF").unwrap(); - let api_felt = stark_felt!("DEADBEEF"); - - assert_eq!(vm_felt, felt_api2vm(api_felt)); - assert_eq!(api_felt, felt_vm2api(vm_felt)); - - let mut bv = bitvec![u8, Msb0; 0; 219]; - bv.extend_from_bitslice(0xDEADBEEF_u32.view_bits::()); - } - #[test] fn chain_id_num_ok() { - let c = ChainIdOnly { chain_id: ChainId("534e5f474f45524c49".to_string()) }; - - serde_json::to_string(&c).unwrap(); - } - - #[test] - #[should_panic] - fn chain_id_num_fail() { - let c = ChainIdOnly { chain_id: ChainId("SN_GOERLI".to_string()) }; - + let c = ChainIdOnly { chain_id: ChainId::Sepolia }; serde_json::to_string(&c).unwrap(); } } diff --git a/tests/integration/common/block_utils.rs b/tests/integration/common/block_utils.rs index bfbb03d60..9bcda9549 100644 --- a/tests/integration/common/block_utils.rs +++ b/tests/integration/common/block_utils.rs @@ -2,13 +2,12 @@ use std::collections::{HashMap, HashSet}; use blockifier::context::BlockContext; use blockifier::execution::contract_class::ContractClass::{V0, V1}; -use blockifier::state::cached_state::CachedState; -use blockifier::state::state_api::{State, StateReader}; +use blockifier::state::cached_state::{CachedState, CommitmentStateDiff}; +use blockifier::state::state_api::StateReader; use blockifier::transaction::objects::TransactionExecutionInfo; use cairo_vm::Felt252; use num_bigint::BigUint; use starknet_api::core::{ClassHash, ContractAddress, PatriciaKey}; -use starknet_api::hash::StarkHash; use starknet_os::config::{StarknetGeneralConfig, StarknetOsConfig, STORED_BLOCK_HASH_BUFFER}; use starknet_os::crypto::pedersen::PedersenHash; use starknet_os::crypto::poseidon::PoseidonHash; @@ -22,12 +21,9 @@ use starknet_os::starknet::starknet_storage::{CommitmentInfo, OsSingleStarknetSt use starknet_os::starkware_utils::commitment_tree::base_types::{Height, TreeIndex}; use starknet_os::storage::storage::Storage; use starknet_os::storage::storage_utils::build_starknet_storage_async; -use starknet_os::utils::{felt_api2vm, felt_vm2api}; use starknet_os_types::casm_contract_class::GenericCasmContractClass; use starknet_os_types::deprecated_compiled_class::GenericDeprecatedCompiledClass; -use crate::common::transaction_utils::to_felt252; - pub async fn os_hints( block_context: &BlockContext, mut blockifier_state: CachedState>, @@ -48,18 +44,19 @@ where .map(|address_biguint| { // TODO: biguint is exacerbating the type conversion problem, ideas...? let address: ContractAddress = - ContractAddress(PatriciaKey::try_from(felt_vm2api(Felt252::from(address_biguint))).unwrap()); + ContractAddress(PatriciaKey::try_from(Felt252::from(address_biguint)).unwrap()); let contract_state = blockifier_state.state.get_contract_state(address).unwrap(); - (to_felt252(address.0.key()), contract_state) + (*address.0.key(), contract_state) }) .collect(); // provide an empty ContractState for any newly deployed contract - let state_diff = blockifier_state.to_state_diff(); + let state_diff = + CommitmentStateDiff::from(blockifier_state.to_state_diff().expect("unable to generate state diff")); let deployed_addresses = state_diff.address_to_class_hash; for (address, _class_hash) in &deployed_addresses { contracts.insert( - to_felt252(address.0.key()), + *address.0.key(), ContractState::empty(Height(251), &mut blockifier_state.state.ffc).await.unwrap(), ); } @@ -69,11 +66,11 @@ where let mut class_hash_to_compiled_class_hash: HashMap = state_diff .class_hash_to_compiled_class_hash .iter() - .map(|(class_hash, _compiled_class_hash)| (felt_api2vm(class_hash.0), Felt252::ZERO)) + .map(|(class_hash, _compiled_class_hash)| (class_hash.0, Felt252::ZERO)) .collect(); for c in contracts.keys() { - let address = ContractAddress::try_from(StarkHash::new(c.to_bytes_be()).unwrap()).unwrap(); + let address = ContractAddress(PatriciaKey::try_from(*c).unwrap()); let class_hash = blockifier_state.get_class_hash_at(address).unwrap(); let blockifier_class = blockifier_state.get_compiled_contract_class(class_hash).unwrap(); match blockifier_class { @@ -83,7 +80,7 @@ where compiled_classes.get(&class_hash).unwrap_or_else(|| panic!("No class given for {:?}", class_hash)); let compiled_class_hash = compiled_class.class_hash().expect("Failed to compute class hash"); let compiled_class_hash = Felt252::from(compiled_class_hash); - class_hash_to_compiled_class_hash.insert(to_felt252(&class_hash.0), compiled_class_hash); + class_hash_to_compiled_class_hash.insert(class_hash.0, compiled_class_hash); compiled_class_hash_to_compiled_class.insert(compiled_class_hash, compiled_class.clone()); } @@ -125,7 +122,7 @@ where let general_config = StarknetGeneralConfig { starknet_os_config: StarknetOsConfig { - chain_id: default_general_config.starknet_os_config.chain_id, + chain_id: block_context.chain_info().chain_id.clone(), fee_token_address: block_context.chain_info().fee_token_addresses.strk_fee_token_address, deprecated_fee_token_address: block_context.chain_info().fee_token_addresses.eth_fee_token_address, }, @@ -140,7 +137,7 @@ where .visited_pcs .iter() .map(|(class_hash, visited_pcs)| { - let class_hash_felt = felt_api2vm(class_hash.0); + let class_hash_felt = class_hash.0; let compiled_class_hash_felt = class_hash_to_compiled_class_hash.get(&class_hash_felt).unwrap(); (*compiled_class_hash_felt, visited_pcs.iter().copied().map(Felt252::from).collect::>()) }) @@ -169,7 +166,7 @@ where .class_hash_to_compiled_class_hash .keys() .chain(compiled_classes.keys()) - .map(|class_hash| BigUint::from_bytes_be(class_hash.0.bytes())) + .map(|class_hash| class_hash.to_biguint()) .collect(); let contract_class_commitment_info = @@ -183,7 +180,7 @@ where .unwrap_or_else(|e| panic!("Could not create contract class commitment info: {:?}", e)); let deprecated_compiled_classes: HashMap<_, _> = - deprecated_compiled_classes.into_iter().map(|(k, v)| (felt_api2vm(k.0), v)).collect(); + deprecated_compiled_classes.into_iter().map(|(k, v)| (k.0, v)).collect(); let os_input = StarknetOsInput { contract_state_commitment_info, diff --git a/tests/integration/common/state.rs b/tests/integration/common/state.rs index df355bfc7..95043cc65 100644 --- a/tests/integration/common/state.rs +++ b/tests/integration/common/state.rs @@ -10,8 +10,6 @@ use rand::rngs::StdRng; use rand::{Rng, SeedableRng}; use rstest::fixture; use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress}; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; use starknet_os::crypto::pedersen::PedersenHash; use starknet_os::starknet::business_logic::fact_state::state::SharedState; use starknet_os::starknet::business_logic::utils::{write_class_facts, write_deprecated_compiled_class_fact}; @@ -272,7 +270,7 @@ impl<'a> StarknetStateBuilder<'a> { for (name, contract) in cairo0_contracts { let deprecated_compiled_class = contract.deprecated_compiled_class; let class_hash = write_deprecated_compiled_class_fact(deprecated_compiled_class.clone(), ffc).await?; - let class_hash = ClassHash::try_from(class_hash).expect("Class hash is not in prime field"); + let class_hash = ClassHash::from(class_hash); Self::add_cairo0_contract_to_state(class_hash, deprecated_compiled_class.clone(), dict_state_reader); @@ -299,7 +297,7 @@ impl<'a> StarknetStateBuilder<'a> { let deprecated_compiled_class = contract.contract.deprecated_compiled_class; let class_hash = write_deprecated_compiled_class_fact(deprecated_compiled_class.clone(), ffc).await?; - let class_hash = ClassHash::try_from(class_hash).expect("Class hash is not in prime field"); + let class_hash = ClassHash::from(class_hash); // Add entries in the dict state Self::add_cairo0_contract_to_state(class_hash, deprecated_compiled_class.clone(), dict_state_reader); @@ -345,9 +343,8 @@ impl<'a> StarknetStateBuilder<'a> { let (contract_class_hash, compiled_class_hash) = write_class_facts(contract_class.clone().into(), compiled_contract_class.clone(), ffc).await?; - let class_hash = ClassHash::try_from(contract_class_hash).expect("Class hash is not in prime field"); - let compiled_class_hash = - CompiledClassHash::try_from(compiled_class_hash).expect("Compiled class hash is not in prime field"); + let class_hash = ClassHash::from(contract_class_hash); + let compiled_class_hash = CompiledClassHash::from(compiled_class_hash); Self::add_cairo1_contract_to_state( class_hash, @@ -385,9 +382,8 @@ impl<'a> StarknetStateBuilder<'a> { let (contract_class_hash, compiled_class_hash) = write_class_facts(contract_class.clone().into(), compiled_contract_class.clone(), ffc).await?; - let class_hash = ClassHash::try_from(contract_class_hash).expect("Class hash is not in prime field"); - let compiled_class_hash = - CompiledClassHash::try_from(compiled_class_hash).expect("Compiled class hash is not in prime field"); + let class_hash = ClassHash::from(contract_class_hash); + let compiled_class_hash = CompiledClassHash::from(compiled_class_hash); // Add entries in the dict state Self::add_cairo1_contract_to_state( @@ -445,8 +441,8 @@ impl<'a> StarknetStateBuilder<'a> { ) { let storage_view = &mut dict_state_reader.storage_view; let balance_key = get_fee_token_var_address(account_address); - storage_view.insert((fee_config.eth_fee_token_address, balance_key), stark_felt!(balance.eth)); - storage_view.insert((fee_config.strk_fee_token_address, balance_key), stark_felt!(balance.strk)); + storage_view.insert((fee_config.eth_fee_token_address, balance_key), balance.eth.into()); + storage_view.insert((fee_config.strk_fee_token_address, balance_key), balance.strk.into()); } /// Converts the dict state reader and FFC into a shared state object. diff --git a/tests/integration/common/transaction_utils.rs b/tests/integration/common/transaction_utils.rs index 1b49ad16e..e17ce3078 100644 --- a/tests/integration/common/transaction_utils.rs +++ b/tests/integration/common/transaction_utils.rs @@ -15,14 +15,13 @@ use cairo_vm::Felt252; use num_bigint::BigUint; use rstest::rstest; use starknet_api::core::{calculate_contract_address, ChainId, ClassHash, ContractAddress, PatriciaKey}; -use starknet_api::hash::{StarkFelt, StarkHash}; use starknet_api::state::StorageKey; use starknet_api::transaction::{ DeclareTransactionV0V1, DeclareTransactionV2, DeclareTransactionV3, DeployAccountTransactionV1, DeployAccountTransactionV3, InvokeTransactionV0, InvokeTransactionV1, InvokeTransactionV3, Resource, - ResourceBoundsMapping, + ResourceBoundsMapping, TransactionHash, }; -use starknet_api::{contract_address, patricia_key, stark_felt}; +use starknet_api::{contract_address, felt, patricia_key}; use starknet_crypto::{pedersen_hash, FieldElement}; use starknet_os::config::{BLOCK_HASH_CONTRACT_ADDRESS, STORED_BLOCK_HASH_BUFFER}; use starknet_os::crypto::pedersen::PedersenHash; @@ -37,7 +36,6 @@ use starknet_os::starknet::business_logic::fact_state::state::SharedState; use starknet_os::starknet::core::os::transaction_hash::{L1_GAS, L2_GAS}; use starknet_os::starknet::starknet_storage::OsSingleStarknetStorage; use starknet_os::storage::storage::Storage; -use starknet_os::utils::felt_api2vm; use starknet_os::{config, run_os}; use starknet_os_types::casm_contract_class::GenericCasmContractClass; use starknet_os_types::chain_id::chain_id_to_felt; @@ -45,10 +43,6 @@ use starknet_os_types::deprecated_compiled_class::GenericDeprecatedCompiledClass use crate::common::block_utils::os_hints; -pub fn to_felt252(stark_felt: &StarkFelt) -> Felt252 { - Felt252::from_bytes_be_slice(stark_felt.bytes()) -} - const DECLARE_PREFIX: &[u8] = b"declare"; const DEPLOY_ACCOUNT_PREFIX: &[u8] = b"deploy_account"; const INVOKE_PREFIX: &[u8] = b"invoke"; @@ -424,17 +418,17 @@ fn account_tx_to_internal_tx(account_tx: &AccountTransaction, chain_id: &ChainId } } fn to_internal_l1_handler_tx(l1_tx: &L1HandlerTransaction, chain_id: &ChainId) -> InternalTransaction { - let contract_address = felt_api2vm(*l1_tx.tx.contract_address.0); - let entry_point_selector = felt_api2vm(l1_tx.tx.entry_point_selector.0); + let contract_address = *l1_tx.tx.contract_address.0; + let entry_point_selector = l1_tx.tx.entry_point_selector.0; let txinfo = l1_tx.create_tx_info(); let signature = match txinfo { TransactionInfo::Deprecated(tx) => tx.common_fields.signature, TransactionInfo::Current(tx) => tx.common_fields.signature, }; - let signature = signature.0.iter().map(to_felt252).collect(); - let calldata: Vec<_> = l1_tx.tx.calldata.0.iter().map(to_felt252).collect(); + let signature = signature.0.to_vec(); + let calldata: Vec<_> = l1_tx.tx.calldata.0.iter().copied().collect(); let chain_id_felt = chain_id_to_felt(chain_id); - let nonce = felt_api2vm(l1_tx.tx.nonce.0); + let nonce = l1_tx.tx.nonce.0; let fee = Felt252::ZERO; let hash_value = l1_tx_compute_hash(contract_address, entry_point_selector, &calldata, fee, chain_id_felt, nonce); @@ -463,15 +457,15 @@ pub fn to_internal_declare_v1_tx( let sender_address; let class_hash; let max_fee = tx.max_fee.0.into(); - let signature = tx.signature.0.iter().map(to_felt252).collect(); + let signature = tx.signature.0.to_vec(); let chain_id_felt = chain_id_to_felt(chain_id); - let nonce = felt_api2vm(tx.nonce.0); + let nonce = tx.nonce.0; match account_tx.create_tx_info() { TransactionInfo::Current(_) => unreachable!("v1 transactions can only contain a `Deprecated` variant"), TransactionInfo::Deprecated(context) => { - sender_address = felt_api2vm(*context.common_fields.sender_address.0.key()); - class_hash = felt_api2vm(tx.class_hash.0); + sender_address = *context.common_fields.sender_address.0.key(); + class_hash = tx.class_hash.0; hash_value = tx_hash_declare_v1(sender_address, max_fee, class_hash, chain_id_felt, nonce); } @@ -500,29 +494,27 @@ fn to_internal_deploy_v1_tx( TransactionInfo::Current(_) => unreachable!("TxV1 can only have deprecated variant"), TransactionInfo::Deprecated(context) => context.common_fields.sender_address, }; - let sender_address_felt = felt_api2vm(*sender_address.key()); - - let contract_address = felt_api2vm( - *calculate_contract_address( - tx.contract_address_salt, - tx.class_hash, - &tx.constructor_calldata, - contract_address!("0x0"), - ) - .unwrap() - .key(), - ); + let sender_address_felt = *sender_address.key(); + + let contract_address = *calculate_contract_address( + tx.contract_address_salt, + tx.class_hash, + &tx.constructor_calldata, + contract_address!("0x0"), + ) + .unwrap() + .key(); let max_fee: Felt252 = tx.max_fee.0.into(); - let signature = Some(tx.signature.0.iter().map(to_felt252).collect()); + let signature = Some(tx.signature.0.to_vec()); let entry_point_selector = Some(Felt252::ZERO); let chain_id_felt = chain_id_to_felt(chain_id); - let nonce = felt_api2vm(tx.nonce.0); + let nonce = tx.nonce.0; - let class_hash = felt_api2vm(tx.class_hash.0); + let class_hash = tx.class_hash.0; - let constructor_calldata: Vec<_> = tx.constructor_calldata.0.iter().map(to_felt252).collect(); - let contract_address_salt = felt_api2vm(tx.contract_address_salt.0); + let constructor_calldata: Vec<_> = tx.constructor_calldata.0.iter().copied().collect(); + let contract_address_salt = tx.contract_address_salt.0; let hash_value = tx_hash_deploy_account_v1( contract_address, @@ -561,24 +553,18 @@ pub fn to_internal_declare_v2_tx( let sender_address; let class_hash; let max_fee = tx.max_fee.0.into(); - let signature = tx.signature.0.iter().map(to_felt252).collect(); - let nonce = felt_api2vm(tx.nonce.0); + let signature = tx.signature.0.to_vec(); + let nonce = tx.nonce.0; let chain_id_felt = chain_id_to_felt(chain_id); match account_tx.create_tx_info() { TransactionInfo::Current(_) => panic!("Not implemented"), TransactionInfo::Deprecated(context) => { - sender_address = felt_api2vm(*context.common_fields.sender_address.0.key()); - class_hash = felt_api2vm(tx.class_hash.0); - - hash_value = tx_hash_declare_v2( - sender_address, - max_fee, - class_hash, - felt_api2vm(tx.compiled_class_hash.0), - chain_id_felt, - nonce, - ); + sender_address = *context.common_fields.sender_address.0.key(); + class_hash = tx.class_hash.0; + + hash_value = + tx_hash_declare_v2(sender_address, max_fee, class_hash, tx.compiled_class_hash.0, chain_id_felt, nonce); } } @@ -590,7 +576,7 @@ pub fn to_internal_declare_v2_tx( entry_point_type: Some("EXTERNAL".to_string()), signature: Some(signature), class_hash: Some(class_hash), - compiled_class_hash: Some(felt_api2vm(tx.compiled_class_hash.0)), + compiled_class_hash: Some(tx.compiled_class_hash.0), r#type: "DECLARE".to_string(), max_fee: Some(max_fee), ..Default::default() @@ -599,21 +585,21 @@ pub fn to_internal_declare_v2_tx( /// Convert a DeclareTransactionV2 to a SNOS InternalTransaction pub fn to_internal_declare_v3_tx(tx: &DeclareTransactionV3, chain_id: &ChainId) -> InternalTransaction { - let signature = Some(tx.signature.0.iter().map(to_felt252).collect()); - let entry_point_selector = to_felt252(&selector_from_name("__execute__").0); - let sender_address = to_felt252(tx.sender_address.0.key()); - let nonce = felt_api2vm(tx.nonce.0); + let signature = Some(tx.signature.0.to_vec()); + let entry_point_selector = selector_from_name("__execute__").0; + let sender_address = *tx.sender_address.0.key(); + let nonce = tx.nonce.0; let chain_id_felt = chain_id_to_felt(chain_id); - let tip = felt_api2vm(tx.tip.0.into()); + let tip = tx.tip.0.into(); let nonce_data_availability_mode = Felt252::from(tx.nonce_data_availability_mode as u64); let fee_data_availability_mode = Felt252::from(tx.fee_data_availability_mode as u64); let resource_bounds = &tx.resource_bounds; - let paymaster_data: Vec = tx.paymaster_data.0.iter().map(to_felt252).collect(); - let account_deployment_data: Vec = tx.account_deployment_data.0.iter().map(to_felt252).collect(); - let class_hash = felt_api2vm(tx.class_hash.0); - let compiled_class_hash = felt_api2vm(tx.compiled_class_hash.0); + let paymaster_data: Vec = tx.paymaster_data.0.to_vec(); + let account_deployment_data: Vec = tx.account_deployment_data.0.to_vec(); + let class_hash = tx.class_hash.0; + let compiled_class_hash = tx.compiled_class_hash.0; let hash_value = tx_hash_declare_v3( nonce, sender_address, @@ -652,10 +638,10 @@ pub fn to_internal_declare_v3_tx(tx: &DeclareTransactionV3, chain_id: &ChainId) /// Convert a InvokeTransactionV0 to a SNOS InternalTransaction pub fn to_internal_invoke_v0_tx(tx: &InvokeTransactionV0, chain_id: &ChainId) -> InternalTransaction { let max_fee = tx.max_fee.0.into(); - let signature = Some(tx.signature.0.iter().map(to_felt252).collect()); - let entry_point_selector = to_felt252(&tx.entry_point_selector.0); - let calldata: Vec<_> = tx.calldata.0.iter().map(to_felt252).collect(); - let contract_address = to_felt252(tx.contract_address.0.key()); + let signature = Some(tx.signature.0.to_vec()); + let entry_point_selector = tx.entry_point_selector.0; + let calldata: Vec<_> = tx.calldata.0.iter().copied().collect(); + let contract_address = *tx.contract_address.0.key(); let chain_id_felt = chain_id_to_felt(chain_id); let hash_value = tx_hash_invoke_v0(contract_address, entry_point_selector, calldata.clone(), max_fee, chain_id_felt); @@ -679,11 +665,11 @@ pub fn to_internal_invoke_v0_tx(tx: &InvokeTransactionV0, chain_id: &ChainId) -> /// Convert a InvokeTransactionV1 to a SNOS InternalTransaction pub fn to_internal_invoke_v1_tx(tx: &InvokeTransactionV1, chain_id: &ChainId) -> InternalTransaction { let max_fee = tx.max_fee.0.into(); - let signature = Some(tx.signature.0.iter().map(to_felt252).collect()); - let entry_point_selector = Some(to_felt252(&selector_from_name("__execute__").0)); - let calldata = Some(tx.calldata.0.iter().map(to_felt252).collect()); - let contract_address = to_felt252(tx.sender_address.0.key()); - let nonce = felt_api2vm(tx.nonce.0); + let signature = Some(tx.signature.0.to_vec()); + let entry_point_selector = Some(selector_from_name("__execute__").0); + let calldata = Some(tx.calldata.0.iter().copied().collect()); + let contract_address = *tx.sender_address.0.key(); + let nonce = tx.nonce.0; let chain_id_felt = chain_id_to_felt(chain_id); let hash_value = tx_hash_invoke_v1(contract_address, calldata.clone().unwrap(), max_fee, chain_id_felt, nonce); @@ -705,20 +691,20 @@ pub fn to_internal_invoke_v1_tx(tx: &InvokeTransactionV1, chain_id: &ChainId) -> /// Convert a InvokeTransactionV3 to a SNOS InternalTransaction pub fn to_internal_invoke_v3_tx(tx: &InvokeTransactionV3, chain_id: &ChainId) -> InternalTransaction { - let signature = Some(tx.signature.0.iter().map(to_felt252).collect()); - let entry_point_selector = to_felt252(&selector_from_name("__execute__").0); - let calldata: Vec<_> = tx.calldata.0.iter().map(to_felt252).collect(); - let sender_address = to_felt252(tx.sender_address.0.key()); - let nonce = felt_api2vm(tx.nonce.0); + let signature = Some(tx.signature.0.to_vec()); + let entry_point_selector = selector_from_name("__execute__").0; + let calldata: Vec<_> = tx.calldata.0.iter().copied().collect(); + let sender_address = *tx.sender_address.0.key(); + let nonce = tx.nonce.0; let chain_id_felt = chain_id_to_felt(chain_id); - let tip = felt_api2vm(tx.tip.0.into()); + let tip = tx.tip.0.into(); let nonce_data_availability_mode = Felt252::from(tx.nonce_data_availability_mode as u64); let fee_data_availability_mode = Felt252::from(tx.fee_data_availability_mode as u64); let resource_bounds = &tx.resource_bounds; - let paymaster_data: Vec = tx.paymaster_data.0.iter().map(to_felt252).collect(); - let account_deployment_data: Vec = tx.account_deployment_data.0.iter().map(to_felt252).collect(); + let paymaster_data: Vec = tx.paymaster_data.0.to_vec(); + let account_deployment_data: Vec = tx.account_deployment_data.0.to_vec(); let hash_value = tx_hash_invoke_v3( nonce, sender_address, @@ -762,21 +748,21 @@ pub fn to_internal_deploy_v3_tx( AccountTransaction::DeployAccount(a) => a.contract_address, _ => unreachable!(), }; - let signature = Some(tx.signature.0.iter().map(to_felt252).collect()); + let signature = Some(tx.signature.0.to_vec()); let entry_point_selector = Some(Felt252::ZERO); - let calldata: Vec<_> = tx.constructor_calldata.0.iter().map(to_felt252).collect(); + let calldata: Vec<_> = tx.constructor_calldata.0.iter().copied().collect(); - let nonce = felt_api2vm(tx.nonce.0); + let nonce = tx.nonce.0; let chain_id_felt = chain_id_to_felt(chain_id); - let tip = felt_api2vm(tx.tip.0.into()); + let tip = tx.tip.0.into(); let nonce_data_availability_mode = Felt252::from(tx.nonce_data_availability_mode as u64); let fee_data_availability_mode = Felt252::from(tx.fee_data_availability_mode as u64); let resource_bounds = &tx.resource_bounds; - let paymaster_data: Vec = tx.paymaster_data.0.iter().map(to_felt252).collect(); - let contract_address_salt = felt_api2vm(tx.contract_address_salt.0); - let class_hash = to_felt252(&tx.class_hash.0); + let paymaster_data: Vec = tx.paymaster_data.0.to_vec(); + let contract_address_salt = tx.contract_address_salt.0; + let class_hash = tx.class_hash.0; let contract_address = calculate_contract_address( tx.contract_address_salt, @@ -785,11 +771,11 @@ pub fn to_internal_deploy_v3_tx( ContractAddress::from(0_u8), ) .unwrap(); - let contract_address = felt_api2vm(*contract_address.0); + let contract_address_felt = *contract_address.0.key(); let hash_value = tx_hash_deploy_v3( nonce, - contract_address, + contract_address_felt, chain_id_felt, nonce_data_availability_mode, fee_data_availability_mode, @@ -805,8 +791,8 @@ pub fn to_internal_deploy_v3_tx( hash_value, version: Some(Felt252::THREE), nonce: Some(nonce), - sender_address: Some(to_felt252(&sender_address.0)), - contract_address: Some(contract_address), + sender_address: Some(*sender_address.0), + contract_address: Some(contract_address_felt), entry_point_selector, entry_point_type: Some("CONSTRUCTOR".to_string()), r#type: "DEPLOY_ACCOUNT".to_string(), @@ -824,6 +810,18 @@ pub fn to_internal_deploy_v3_tx( } } +/// Retrieves the transaction hash from a Blockifier `Transaction` object. +fn get_tx_hash(tx: &Transaction) -> TransactionHash { + match tx { + Transaction::AccountTransaction(account_tx) => match account_tx { + AccountTransaction::Declare(declare_tx) => declare_tx.tx_hash, + AccountTransaction::DeployAccount(deploy_tx) => deploy_tx.tx_hash, + AccountTransaction::Invoke(invoke_tx) => invoke_tx.tx_hash, + }, + Transaction::L1HandlerTransaction(l1_handler_tx) => l1_handler_tx.tx_hash, + } +} + async fn execute_txs( mut state: CachedState>, block_context: &BlockContext, @@ -836,23 +834,33 @@ where { let upper_bound_block_number = block_context.block_info().block_number.0 - STORED_BLOCK_HASH_BUFFER; let block_number = StorageKey::from(upper_bound_block_number); - let block_hash = stark_felt!(66_u64); + let block_hash = felt!(66_u64); - let block_hash_contract_address = ContractAddress::try_from(stark_felt!(BLOCK_HASH_CONTRACT_ADDRESS)).unwrap(); + let block_hash_contract_address = ContractAddress::try_from(felt!(BLOCK_HASH_CONTRACT_ADDRESS)).unwrap(); state.set_storage_at(block_hash_contract_address, block_number, block_hash).unwrap(); let internal_txs: Vec<_> = txs.iter().map(|tx| to_internal_tx(tx, &block_context.chain_info().chain_id)).collect(); + let n_txs = internal_txs.len(); + let execution_infos = txs .into_iter() - .map(|tx| { + .enumerate() + .map(|(index, tx)| { + let tx_hash = get_tx_hash(&tx).to_hex_string(); let tx_result = tx.execute(&mut state, block_context, true, true); match tx_result { Err(e) => { - panic!("Transaction failed in blockifier: {}", e); + panic!("Transaction {} ({}/{}) failed in blockifier: {}", tx_hash, index + 1, n_txs, e); } Ok(info) => { if info.is_reverted() { - log::error!("Transaction reverted: {:?}", info.revert_error); + log::error!( + "Transaction {} ({}/{}) reverted: {:?}", + tx_hash, + index + 1, + n_txs, + info.revert_error + ); log::warn!("TransactionExecutionInfo: {:?}", info); panic!("A transaction reverted during execution: {:?}", info); } diff --git a/tests/integration/declare_txn_tests.rs b/tests/integration/declare_txn_tests.rs index 896aa9f60..5a55ce200 100644 --- a/tests/integration/declare_txn_tests.rs +++ b/tests/integration/declare_txn_tests.rs @@ -1,17 +1,17 @@ use blockifier::context::BlockContext; use blockifier::declare_tx_args; use blockifier::execution::contract_class::ClassInfo; -use blockifier::test_utils::NonceManager; +use blockifier::test_utils::{NonceManager, BALANCE}; use blockifier::transaction::test_utils::{calculate_class_info_for_testing, max_fee}; -use rstest::rstest; +use rstest::{fixture, rstest}; use starknet_api::core::CompiledClassHash; use starknet_api::transaction::{Fee, Resource, ResourceBounds, ResourceBoundsMapping, TransactionVersion}; use starknet_os::crypto::poseidon::PoseidonHash; use starknet_os::starknet::business_logic::utils::write_class_facts; use crate::common::block_context; -use crate::common::blockifier_contracts::load_cairo1_feature_contract; -use crate::common::state::{initial_state_cairo0, initial_state_cairo1, StarknetTestState}; +use crate::common::blockifier_contracts::{load_cairo0_feature_contract, load_cairo1_feature_contract}; +use crate::common::state::{init_logging, initial_state_cairo1, StarknetStateBuilder, StarknetTestState}; use crate::common::transaction_utils::execute_txs_and_run_os; // Copied from the non-public Blockifier fn @@ -52,8 +52,8 @@ async fn declare_v3_cairo1_account( let sender_address = account_contract.address; let contract_class = casm_class.to_blockifier_contract_class().unwrap(); - let class_hash = starknet_api::core::ClassHash::try_from(contract_class_hash).unwrap(); - let compiled_class_hash = CompiledClassHash::try_from(compiled_class_hash).unwrap(); + let class_hash = starknet_api::core::ClassHash::from(contract_class_hash); + let compiled_class_hash = CompiledClassHash::from(compiled_class_hash); let class_info = ClassInfo::new(&contract_class.into(), sierra_class.sierra_program.len(), 0).unwrap(); @@ -111,8 +111,8 @@ async fn declare_cairo1_account( let sender_address = account_contract.address; let contract_class = casm_class.to_blockifier_contract_class().unwrap(); - let class_hash = starknet_api::core::ClassHash::try_from(contract_class_hash).unwrap(); - let compiled_class_hash = CompiledClassHash::try_from(compiled_class_hash).unwrap(); + let class_hash = starknet_api::core::ClassHash::from(contract_class_hash); + let compiled_class_hash = CompiledClassHash::from(compiled_class_hash); let class_info = ClassInfo::new(&contract_class.into(), sierra_class.sierra_program.len(), 0).unwrap(); @@ -140,26 +140,38 @@ async fn declare_cairo1_account( .expect("OS run failed"); } +#[fixture] +async fn initial_state_declare_cairo0( + block_context: BlockContext, + #[from(init_logging)] _logging: (), +) -> StarknetTestState { + let account_with_dummy_validate = load_cairo0_feature_contract("account_with_dummy_validate"); + + StarknetStateBuilder::new(&block_context) + .deploy_cairo0_contract(account_with_dummy_validate.0, account_with_dummy_validate.1) + .set_default_balance(BALANCE, BALANCE) + .build() + .await +} + #[rstest] // We need to use the multi_thread runtime to use task::block_in_place for sync -> async calls. #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn declare_v1_cairo0_account( - #[future] initial_state_cairo0: StarknetTestState, + #[future] initial_state_declare_cairo0: StarknetTestState, block_context: BlockContext, max_fee: Fee, ) { - let initial_state = initial_state_cairo0.await; - - let mut nonce_manager = NonceManager::default(); - + let initial_state = initial_state_declare_cairo0.await; let sender_address = initial_state.deployed_cairo0_contracts.get("account_with_dummy_validate").unwrap().address; - let test_contract = initial_state.deployed_cairo0_contracts.get("test_contract").unwrap(); - let tx_version = TransactionVersion::ONE; + let (_, test_contract) = load_cairo0_feature_contract("test_contract"); + let class_hash = test_contract.class_hash().unwrap(); - let class_hash = test_contract.declaration.class_hash; + let mut nonce_manager = NonceManager::default(); + let tx_version = TransactionVersion::ONE; - let blockifier_class = test_contract.declaration.class.get_blockifier_contract_class().unwrap().clone(); + let blockifier_class = test_contract.to_blockifier_contract_class().unwrap(); let class_info = calculate_class_info_for_testing(blockifier_class.into()); let declare_tx = blockifier::test_utils::declare::declare_tx( @@ -168,7 +180,7 @@ async fn declare_v1_cairo0_account( sender_address, version: tx_version, nonce: nonce_manager.next(sender_address), - class_hash: class_hash, + class_hash: class_hash.into(), }, class_info, ); diff --git a/tests/integration/deploy_txn_tests.rs b/tests/integration/deploy_txn_tests.rs index 2aa70bcf3..fdaed6d00 100644 --- a/tests/integration/deploy_txn_tests.rs +++ b/tests/integration/deploy_txn_tests.rs @@ -4,11 +4,11 @@ use blockifier::test_utils::deploy_account::deploy_account_tx; use blockifier::test_utils::{NonceManager, BALANCE}; use blockifier::transaction::account_transaction::AccountTransaction; use blockifier::transaction::test_utils::max_fee; +use cairo_vm::Felt252; use rstest::{fixture, rstest}; use starknet_api::core::{calculate_contract_address, ClassHash, ContractAddress, PatriciaKey}; -use starknet_api::hash::{StarkFelt, StarkHash}; use starknet_api::transaction::{Calldata, ContractAddressSalt, Fee, TransactionVersion}; -use starknet_api::{class_hash, contract_address, patricia_key, stark_felt}; +use starknet_api::{class_hash, contract_address, felt, patricia_key}; use crate::common::block_context; use crate::common::blockifier_contracts::{load_cairo0_feature_contract, load_cairo1_feature_contract}; @@ -19,7 +19,7 @@ use crate::common::transaction_utils::execute_txs_and_run_os; struct DeployArgs { contract_address_salt: ContractAddressSalt, class_hash: ClassHash, - constructor_calldata: Vec, + constructor_calldata: Vec, deployer_address: ContractAddress, } @@ -44,7 +44,7 @@ pub async fn initial_state_for_deploy_v1( let deploy_args = DeployArgs { contract_address_salt: ContractAddressSalt::default(), class_hash, - constructor_calldata: vec![stark_felt!(0u128), stark_felt!(101u128)], + constructor_calldata: vec![felt!(0u128), felt!(101u128)], // The deployer address is always be 0 for deploy v1 deployer_address: contract_address!("0x0"), }; @@ -127,7 +127,7 @@ pub async fn initial_state_for_deploy_v3( let deploy_args = DeployArgs { contract_address_salt: ContractAddressSalt::default(), class_hash, - constructor_calldata: vec![stark_felt!(0u128), stark_felt!(101u128)], + constructor_calldata: vec![felt!(0u128), felt!(101u128)], // The deployer address is always be 0 for deploy v1 deployer_address: contract_address!("0x0"), }; diff --git a/tests/integration/deprecated_syscalls_tests.rs b/tests/integration/deprecated_syscalls_tests.rs index 9fc1f36cf..77a750848 100644 --- a/tests/integration/deprecated_syscalls_tests.rs +++ b/tests/integration/deprecated_syscalls_tests.rs @@ -5,6 +5,7 @@ //! Each test in this file calls a single entrypoint and returns to test syscalls individually. use std::collections::HashMap; +use std::str::FromStr; use blockifier::abi::abi_utils::selector_from_name; use blockifier::context::BlockContext; @@ -18,11 +19,9 @@ use blockifier::transaction::transaction_execution::Transaction; use cairo_vm::Felt252; use num_traits::ToPrimitive; use rstest::rstest; -use starknet_api::core::{calculate_contract_address, ChainId}; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; +use starknet_api::core::calculate_contract_address; +use starknet_api::felt; use starknet_api::transaction::{Calldata, ContractAddressSalt, Fee, TransactionHash, TransactionVersion}; -use starknet_os::utils::{felt_api2vm, felt_vm2api}; use starknet_os_types::chain_id::chain_id_to_felt; use crate::common::block_context; @@ -53,7 +52,7 @@ async fn test_syscall_library_call_cairo0( let test_contract_class_hash = test_contract.declaration.class_hash; let selector_felt = selector_from_name("return_result"); - let return_result_calldata = vec![stark_felt!(1u128), stark_felt!(42u128)]; + let return_result_calldata = vec![felt!(1u128), felt!(42u128)]; let entrypoint_args = &[vec![test_contract_class_hash.0], vec![selector_felt.0], return_result_calldata].concat(); @@ -95,7 +94,7 @@ async fn test_syscall_get_block_number_cairo0( let sender_address = initial_state.deployed_cairo0_contracts.get("account_with_dummy_validate").unwrap().address; let contract_address = initial_state.deployed_cairo0_contracts.get("test_contract").unwrap().address; - let expected_block_number = stark_felt!(block_context.block_info().block_number.0); + let expected_block_number = felt!(block_context.block_info().block_number.0); let tx_version = TransactionVersion::ZERO; let mut nonce_manager = NonceManager::default(); @@ -135,7 +134,7 @@ async fn test_syscall_get_block_timestamp_cairo0( let sender_address = initial_state.deployed_cairo0_contracts.get("account_with_dummy_validate").unwrap().address; let contract_address = initial_state.deployed_cairo0_contracts.get("test_contract").unwrap().address; - let expected_block_timestamp = stark_felt!(block_context.block_info().block_timestamp.0); + let expected_block_timestamp = felt!(block_context.block_info().block_timestamp.0); let tx_version = TransactionVersion::ZERO; let mut nonce_manager = NonceManager::default(); @@ -177,7 +176,7 @@ async fn test_syscall_get_tx_info_cairo0( let tx_version = TransactionVersion::ZERO; - let expected_chain_id = felt_vm2api(chain_id_to_felt(&ChainId("SN_GOERLI".to_string()))); + let expected_chain_id = chain_id_to_felt(&block_context.chain_info().chain_id); let mut nonce_manager = NonceManager::default(); let nonce = nonce_manager.next(sender_address); @@ -185,9 +184,8 @@ async fn test_syscall_get_tx_info_cairo0( // Note: we use `test_get_tx_info_no_tx_hash_check()` instead of `test_get_tx_info()` // because it is pretty much impossible to generate a tx whose hash is equal to the expected // hash that must be set in the calldata. - let tx_hash = TransactionHash( - StarkFelt::try_from("0x8704f5e69650b81810a420373c21885aa6e75a8c46e34095e12a2a5231815f").unwrap(), - ); + let tx_hash = + TransactionHash(Felt252::from_str("0x8704f5e69650b81810a420373c21885aa6e75a8c46e34095e12a2a5231815f").unwrap()); let tx = { let mut invoke_tx = invoke_tx(invoke_tx_args! { max_fee, @@ -195,7 +193,7 @@ async fn test_syscall_get_tx_info_cairo0( calldata: create_calldata(contract_address, "test_get_tx_info_no_tx_hash_check", &[ tx_version.0, // expected version *sender_address.key(), // expected contract address - stark_felt!(max_fee.0), // expected max fee + felt!(max_fee.0), // expected max fee expected_chain_id, // expected chain ID nonce.0, // expected nonce ]), @@ -224,19 +222,16 @@ async fn test_syscall_get_tx_info_cairo0( let contract_changes_by_address: HashMap<_, _> = os_output.contracts.iter().map(|change| (change.addr, change)).collect(); let test_contract_changes = contract_changes_by_address - .get(&felt_api2vm(*contract_address.0.key())) + .get(contract_address.0.key()) .expect("The test contract should appear as modified in the OS output"); // Values based on the code of `test_contract.cairo`. // Note that if the nonce is 0 it will not appear as a change, so check for that. let expected_storage_changes = { - let mut changes = HashMap::from([ - (Felt252::from(300), felt_api2vm(tx_hash.0)), - (Felt252::from(311), felt_api2vm(expected_chain_id)), - ]); + let mut changes = HashMap::from([(Felt252::from(300), tx_hash.0), (Felt252::from(311), expected_chain_id)]); - if nonce.0 != StarkFelt::ZERO { - changes.insert(Felt252::from(322), felt_api2vm(nonce.0)); + if nonce.0 != Felt252::ZERO { + changes.insert(Felt252::from(322), nonce.0); } changes }; @@ -344,12 +339,12 @@ async fn test_syscall_deploy_cairo0( let class_hash = test_contract.declaration.class_hash; let contract_address_salt = ContractAddressSalt::default(); - let constructor_args = vec![StarkFelt::from(100u64), StarkFelt::from(200u64)]; + let constructor_args = vec![Felt252::from(100u64), Felt252::from(200u64)]; let test_deploy_args = &[ vec![class_hash.0, contract_address_salt.0], - vec![StarkFelt::from(constructor_args.len() as u64)], + vec![Felt252::from(constructor_args.len() as u64)], constructor_args.clone(), - vec![StarkFelt::ZERO], + vec![Felt252::ZERO], ] .concat(); @@ -385,7 +380,7 @@ async fn test_syscall_deploy_cairo0( // Check that the new contract address appears in the OS output let contract_changes_by_address: HashMap<_, _> = os_output.contracts.iter().map(|change| (change.addr, change)).collect(); - assert!(contract_changes_by_address.contains_key(&felt_api2vm(*expected_contract_address.key()))); + assert!(contract_changes_by_address.contains_key(expected_contract_address.key())); // Check other output fields assert_eq!(os_output.block_number.to_u64().unwrap(), block_context.block_info().block_number.0); @@ -453,15 +448,15 @@ async fn test_syscall_get_contract_address_cairo0( let class_hash = test_contract.declaration.class_hash; let contract_address_salt = ContractAddressSalt::default(); - let constructor_args = vec![StarkFelt::from(100u64), StarkFelt::from(200u64)]; + let constructor_args = vec![Felt252::from(100u64), Felt252::from(200u64)]; // Build the args required for calling test_contract_address. Check the Cairo code for // more details. let test_contract_address_args = &[ vec![contract_address_salt.0, class_hash.0], - vec![StarkFelt::from(constructor_args.len() as u64)], + vec![Felt252::from(constructor_args.len() as u64)], constructor_args.clone(), - vec![StarkFelt::ZERO], // deployer_address + vec![Felt252::ZERO], // deployer_address ] .concat(); @@ -508,12 +503,12 @@ async fn test_syscall_emit_event_cairo0( let contract_address = test_contract.address; let tx_version = TransactionVersion::ZERO; - let keys = vec![stark_felt!(2019_u16), stark_felt!(2020_u16)]; - let data = vec![stark_felt!(2021_u16), stark_felt!(2022_u16), stark_felt!(2023_u16)]; + let keys = vec![felt!(2019_u16), felt!(2020_u16)]; + let data = vec![felt!(2021_u16), felt!(2022_u16), felt!(2023_u16)]; let entrypoint_args = &[ - vec![stark_felt!(u128::try_from(keys.len()).unwrap())], + vec![felt!(u128::try_from(keys.len()).unwrap())], keys, - vec![stark_felt!(u128::try_from(data.len()).unwrap())], + vec![felt!(u128::try_from(data.len()).unwrap())], data, ] .concat(); @@ -561,7 +556,7 @@ async fn test_syscall_send_message_to_l1_cairo0( const PAYLOAD_2: u64 = 34; let tx_version = TransactionVersion::ZERO; - let to_address = stark_felt!(ADDRESS); + let to_address = felt!(ADDRESS); let entrypoint_args = &[vec![to_address]].concat(); @@ -586,12 +581,7 @@ async fn test_syscall_send_message_to_l1_cairo0( .expect("OS run failed"); let output = os_output.messages_to_l1; - let expected: [Felt252; 5] = [ - felt_api2vm(*contract_address.0.key()), - ADDRESS.into(), - PAYLOAD_SIZE.into(), - PAYLOAD_1.into(), - PAYLOAD_2.into(), - ]; + let expected: [Felt252; 5] = + [*contract_address.0.key(), ADDRESS.into(), PAYLOAD_SIZE.into(), PAYLOAD_1.into(), PAYLOAD_2.into()]; assert_eq!(&*output, expected); } diff --git a/tests/integration/l1_handler_txn_tests.rs b/tests/integration/l1_handler_txn_tests.rs index fcf300d04..95352a894 100644 --- a/tests/integration/l1_handler_txn_tests.rs +++ b/tests/integration/l1_handler_txn_tests.rs @@ -7,8 +7,7 @@ use blockifier::transaction::transactions::L1HandlerTransaction; use futures::Future; use rstest::{fixture, rstest}; use starknet_api::core::{ContractAddress, EntryPointSelector}; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; +use starknet_api::felt; use starknet_api::transaction::{Calldata, Fee, TransactionVersion}; use crate::common::state::{init_logging, initial_state_cairo0, initial_state_syscalls, StarknetTestState}; @@ -49,7 +48,7 @@ async fn l1_handler( let tx_version = TransactionVersion::ZERO; - let calldata_args = vec![stark_felt!(1234_u16), stark_felt!(42_u16)]; + let calldata_args = vec![felt!(1234_u16), felt!(42_u16)]; let l1_tx = L1HandlerTransaction { paid_fee_on_l1: max_fee, tx: starknet_api::transaction::L1HandlerTransaction { diff --git a/tests/integration/os.rs b/tests/integration/os.rs index 09fd5cbf7..c88707abd 100644 --- a/tests/integration/os.rs +++ b/tests/integration/os.rs @@ -3,9 +3,9 @@ use blockifier::invoke_tx_args; use blockifier::test_utils::{create_calldata, NonceManager}; use blockifier::transaction::test_utils; use blockifier::transaction::test_utils::max_fee; +use cairo_vm::Felt252; use rstest::rstest; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; +use starknet_api::felt; use starknet_api::transaction::{Fee, TransactionVersion}; use starknet_os::config::STORED_BLOCK_HASH_BUFFER; @@ -35,7 +35,7 @@ async fn return_result_cairo0_account( calldata: create_calldata( contract_address, "return_result", - &[stark_felt!(123_u8)], + &[felt!(123_u8)], ), version: tx_version, nonce: nonce_manager.next(sender_address), @@ -75,7 +75,7 @@ async fn return_result_cairo1_account( calldata: create_calldata( contract_address, "return_result", - &[stark_felt!(2_u8)], + &[felt!(2_u8)], ), version: tx_version, nonce: nonce_manager.next(sender_address), @@ -111,12 +111,12 @@ async fn syscalls_cairo1( let contract_address = initial_state.deployed_cairo1_contracts.get("test_contract").unwrap().address; // test_emit_event - let keys = vec![stark_felt!(2019_u16), stark_felt!(2020_u16)]; - let data = vec![stark_felt!(2021_u16), stark_felt!(2022_u16), stark_felt!(2023_u16)]; + let keys = vec![felt!(2019_u16), felt!(2020_u16)]; + let data = vec![felt!(2021_u16), felt!(2022_u16), felt!(2023_u16)]; let entrypoint_args = &[ - vec![stark_felt!(u128::try_from(keys.len()).unwrap())], + vec![felt!(u128::try_from(keys.len()).unwrap())], keys, - vec![stark_felt!(u128::try_from(data.len()).unwrap())], + vec![felt!(u128::try_from(data.len()).unwrap())], data, ] .concat(); @@ -133,7 +133,7 @@ async fn syscalls_cairo1( let test_storage_read_write_tx = test_utils::account_invoke_tx(invoke_tx_args! { max_fee, sender_address: sender_address, - calldata: create_calldata(contract_address, "test_storage_read_write", &[StarkFelt::TWO, StarkFelt::ONE]), + calldata: create_calldata(contract_address, "test_storage_read_write", &[Felt252::TWO, Felt252::ONE]), version: tx_version, nonce: nonce_manager.next(sender_address), }); @@ -142,15 +142,15 @@ async fn syscalls_cairo1( let test_get_block_hash_tx = test_utils::account_invoke_tx(invoke_tx_args! { max_fee, sender_address: sender_address, - calldata: create_calldata(contract_address, "test_get_block_hash", &[stark_felt!(block_context.block_info().block_number.0 - STORED_BLOCK_HASH_BUFFER)]), + calldata: create_calldata(contract_address, "test_get_block_hash", &[felt!(block_context.block_info().block_number.0 - STORED_BLOCK_HASH_BUFFER)]), version: tx_version, nonce: nonce_manager.next(sender_address), }); // test_send_message_to_l1 - let to_address = stark_felt!(1234_u16); - let payload = vec![stark_felt!(2019_u16), stark_felt!(2020_u16), stark_felt!(2021_u16)]; - let entrypoint_args = &[vec![to_address, stark_felt!(payload.len() as u64)], payload].concat(); + let to_address = felt!(1234_u16); + let payload = vec![felt!(2019_u16), felt!(2020_u16), felt!(2021_u16)]; + let entrypoint_args = &[vec![to_address, felt!(payload.len() as u64)], payload].concat(); let test_send_message_to_l1_tx = test_utils::account_invoke_tx(invoke_tx_args! { max_fee, @@ -165,11 +165,11 @@ async fn syscalls_cairo1( initial_state.deployed_cairo1_contracts.get("test_contract").unwrap().declaration.class_hash.0; let entrypoint_args = &[ test_contract_class_hash, // class hash - stark_felt!(255_u8), // contract_address_salt - stark_felt!(2_u8), // calldata length - stark_felt!(3_u8), // calldata: arg1 - stark_felt!(3_u8), // calldata: arg2 - stark_felt!(0_u8), // deploy_from_zero + felt!(255_u8), // contract_address_salt + felt!(2_u8), // calldata length + felt!(3_u8), // calldata: arg1 + felt!(3_u8), // calldata: arg2 + felt!(0_u8), // deploy_from_zero ]; let test_deploy_tx = test_utils::account_invoke_tx(invoke_tx_args! { diff --git a/tests/integration/run_os.rs b/tests/integration/run_os.rs index 1aa46eebb..265a889fa 100644 --- a/tests/integration/run_os.rs +++ b/tests/integration/run_os.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use std::sync::Arc; use blockifier::abi::abi_utils::selector_from_name; -use blockifier::block::BlockInfo; +use blockifier::blockifier::block::BlockInfo; +use blockifier::bouncer::BouncerConfig; use blockifier::context::{BlockContext, ChainInfo, FeeTokenAddresses}; use blockifier::state::cached_state::CachedState; use blockifier::test_utils::declare::declare_tx; @@ -16,10 +17,10 @@ use blockifier::transaction::transaction_execution::Transaction; use blockifier::transaction::transactions::{ExecutableTransaction, L1HandlerTransaction}; use blockifier::versioned_constants::VersionedConstants; use blockifier::{declare_tx_args, deploy_account_tx_args, invoke_tx_args}; +use cairo_vm::Felt252; use rstest::{fixture, rstest}; use starknet_api::core::{calculate_contract_address, ChainId, ContractAddress, EntryPointSelector}; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; +use starknet_api::felt; use starknet_api::transaction::{ Calldata, ContractAddressSalt, Fee, TransactionHash, TransactionSignature, TransactionVersion, }; @@ -29,7 +30,6 @@ use starknet_os::io::output::StarknetOsOutput; use starknet_os::starknet::business_logic::fact_state::state::SharedState; use starknet_os::storage::dict_storage::DictStorage; use starknet_os::storage::storage_utils::unpack_blockifier_state_async; -use starknet_os::utils::felt_api2vm; use crate::common::block_context; use crate::common::blockifier_contracts::load_cairo0_feature_contract; @@ -139,7 +139,7 @@ async fn prepare_extensive_os_test_params( let test_contract = cairo0_contracts.get("test_contract_run_os").unwrap(); for (salt, calldata) in salts.into_iter().zip(calldatas.into_iter()) { - let constructor_calldata: Vec<_> = calldata.iter().map(|&felt| stark_felt!(felt)).collect(); + let constructor_calldata: Vec<_> = calldata.iter().map(|&felt| felt!(felt)).collect(); deployed_txs_addresses.push( add_declare_and_deploy_contract_txs( "test_contract_run_os", @@ -298,7 +298,7 @@ async fn prepare_extensive_os_test_params( ], )); - let calldata_args = vec![stark_felt!(85_u16), stark_felt!(2_u16)]; + let calldata_args = vec![felt!(85_u16), felt!(2_u16)]; let l1_tx = L1HandlerTransaction { paid_fee_on_l1: max_fee(), tx: starknet_api::transaction::L1HandlerTransaction { @@ -331,23 +331,25 @@ async fn prepare_extensive_os_test_params( let inner_invoke_tx = { let tx_args = invoke_tx_args! { sender_address: deploy_account_address, + version: TransactionVersion::ONE, calldata: create_calldata(test_contract1_address, "test_call_contract", &[ delegate_proxy_address.into(), selector_from_name("test_get_tx_info").0, 1u128.into(), - (*deploy_account_address.0), + *deploy_account_address.0, ]), nonce: nonce_manager.next(deploy_account_address), signature: TransactionSignature(vec![100u128.into()]), max_fee: Fee(0x10000000000000000000000000u128), // 2**100 }; let mut tx = invoke_tx(tx_args); - tx.tx_hash = TransactionHash(stark_felt!("0x19c90daecc4e3ed29743b0331024b3014b9f2c4620ee7ec441b4a7ec330583")); + tx.tx_hash = TransactionHash(felt!("0x538ed2ab8c30b384fda9cc92736a2212a0082444cce35135cdff5700885b156")); tx }; - txs.push(Transaction::AccountTransaction(AccountTransaction::Invoke(inner_invoke_tx))); + let tx = Transaction::AccountTransaction(AccountTransaction::Invoke(inner_invoke_tx)); + txs.push(tx); let test_contract2 = cairo0_contracts.get("test_contract2").unwrap(); @@ -410,7 +412,10 @@ async fn prepare_extensive_os_test_params( fn build_block_context(chain_id: ChainId, fee_token_address: ContractAddress) -> BlockContext { let block_info = BlockInfo::create_for_testing(); - let versioned_constants = VersionedConstants::create_for_account_testing(); + let mut versioned_constants = VersionedConstants::create_for_account_testing(); + // Recent versions of Blockifier disable redeclaration of Cairo0 classes. We do that quite + // a bit in the test so the easy way out is to disable this feature. + versioned_constants.disable_cairo0_redeclaration = false; let chain_info = ChainInfo { chain_id, @@ -420,7 +425,9 @@ fn build_block_context(chain_id: ChainId, fee_token_address: ContractAddress) -> }, }; - BlockContext::new_unchecked(&block_info, &chain_info, &versioned_constants) + let bouncer_config = BouncerConfig::max(); + + BlockContext::new(block_info, chain_info, versioned_constants, bouncer_config) } #[allow(clippy::too_many_arguments)] @@ -431,8 +438,8 @@ fn add_declare_and_deploy_contract_txs( deploy_account_address: &ContractAddress, nonce_manager: &mut NonceManager, txs: &mut Vec, - salt: StarkFelt, - constructor_calldata: Vec, + salt: Felt252, + constructor_calldata: Vec, ) -> Result { let contract = cairo0_contracts.get(contract).ok_or("Contract not found")?; @@ -455,7 +462,7 @@ fn add_declare_and_deploy_contract_txs( contract.class_hash.0, // Class hash. salt, // Salt. ]; - ctor_calldata.push(stark_felt!(constructor_calldata.len() as u128)); // Constructor calldata length. + ctor_calldata.push(felt!(constructor_calldata.len() as u128)); // Constructor calldata length. ctor_calldata.extend(constructor_calldata.iter()); let invoke_tx = account_invoke_tx(invoke_tx_args! { sender_address: *deploy_account_address, @@ -516,19 +523,19 @@ fn validate_os_output(os_output: &StarknetOsOutput, tx_contracts: &[ContractAddr let output_messages_to_l1 = &os_output.messages_to_l1; let expected_messages_to_l1 = [ - felt_api2vm(*tx_contracts[0].0.key()), // from address - 85.into(), // to address - 2.into(), // PAYLOAD_SIZE - 12.into(), // PAYLOAD_1 - 34.into(), // PAYLOAD_1 + *tx_contracts[0].0.key(), // from address + 85.into(), // to address + 2.into(), // PAYLOAD_SIZE + 12.into(), // PAYLOAD_1 + 34.into(), // PAYLOAD_1 ]; assert_eq!(output_messages_to_l1, &expected_messages_to_l1); let expected_messages_to_l2 = [ - 85.into(), // from address - felt_api2vm(*tx_contracts[3].0.key()), // the delegate_proxy_address - 0.into(), // Nonce - felt_api2vm(selector_from_name("deposit").0), + 85.into(), // from address + *tx_contracts[3].0.key(), // the delegate_proxy_address + 0.into(), // Nonce + selector_from_name("deposit").0, 1u64.into(), // PAYLOAD_SIZE 2u64.into(), // PAYLOAD_1 ]; @@ -566,7 +573,7 @@ pub async fn initial_state_full_itests( async fn run_os_tests(#[future] initial_state_full_itests: StarknetTestState) { let initial_state = initial_state_full_itests.await; - let chain_id = ChainId("SN_GOERLI".to_string()); + let chain_id = ChainId::Sepolia; let mut nonce_manager = NonceManager::default(); let dummy_token = initial_state.declared_cairo0_contracts.get("token_for_testing").unwrap(); diff --git a/tests/integration/syscalls_tests.rs b/tests/integration/syscalls_tests.rs index 0cbbf54b5..9203e7a5d 100644 --- a/tests/integration/syscalls_tests.rs +++ b/tests/integration/syscalls_tests.rs @@ -6,8 +6,7 @@ use blockifier::transaction::test_utils; use blockifier::transaction::test_utils::max_fee; use blockifier::transaction::transaction_execution::Transaction; use rstest::rstest; -use starknet_api::hash::StarkFelt; -use starknet_api::stark_felt; +use starknet_api::felt; use starknet_api::transaction::{Fee, TransactionVersion}; use crate::common::block_context; @@ -38,7 +37,7 @@ async fn test_syscall_library_call_cairo1( let test_contract_class_hash = test_contract.declaration.class_hash; let selector_felt = selector_from_name("recurse"); - let return_result_calldata = vec![stark_felt!(1u128), stark_felt!(42u128)]; + let return_result_calldata = vec![felt!(1u128), felt!(42u128)]; let entrypoint_args = &[vec![test_contract_class_hash.0], vec![selector_felt.0], return_result_calldata].concat();