Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Add the ability to execute DeployAccount transactions using the RpcState #1089

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c22eb56
Add test case
fmoletta Oct 18, 2023
855d516
Fix get_onchain_data_segment_length
fmoletta Oct 18, 2023
d163fdb
Debug setup
fmoletta Oct 18, 2023
1e7efff
Add StorageChangesCount struct
fmoletta Oct 18, 2023
cc55c5c
Merge branch 'fix-get_onchain_data_segment_length' into fix-count_act…
fmoletta Oct 19, 2023
ba8cf16
Merge branch 'fix-get_onchain_data_segment_length' into fix-count_act…
fmoletta Oct 19, 2023
0df3007
Use StorageChangesCount struct in state method
fmoletta Oct 19, 2023
fed2162
Fix implicated code
fmoletta Oct 19, 2023
413dfa1
Update doc
fmoletta Oct 19, 2023
d680546
Update test values
fmoletta Oct 19, 2023
6a2bd15
Rename method for consistency
fmoletta Oct 19, 2023
94804d2
Add note comment
fmoletta Oct 19, 2023
5ae787e
Remove hardcoded contract address
fmoletta Oct 19, 2023
e75750b
Remove txt files
fmoletta Oct 19, 2023
7ddad62
Remove dbg prints
fmoletta Oct 19, 2023
c70a509
Remove dbg prints
fmoletta Oct 19, 2023
14576a6
Format
fmoletta Oct 19, 2023
bc06dbd
Restore blockifier version
fmoletta Oct 19, 2023
11f9f00
Restore tests
fmoletta Oct 19, 2023
52fb298
Restore newlines
fmoletta Oct 19, 2023
b0673c4
Restore newlines
fmoletta Oct 19, 2023
c82c682
Remove txt file
fmoletta Oct 19, 2023
0a517fc
Merge branch 'main' of github.com:lambdaclass/starknet_in_rust into r…
fmoletta Oct 19, 2023
fd99568
Merge remote-tracking branch 'origin/fix-count_actual_storage_changes…
fmoletta Oct 19, 2023
3a0b7fe
fmt
fmoletta Oct 19, 2023
1bfa497
Merge branch 'fix-get_onchain_data_segment_length' into fix-count_act…
fmoletta Oct 19, 2023
f6295c9
Merge branch 'fix-count_actual_storage_changes' into rpc-state-reader…
fmoletta Oct 19, 2023
4584071
Fix bug in `From<StarknetRsContractClass> for CompiledClass` implemen…
fmoletta Oct 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions rpc_state_reader/src/rpc_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ impl RpcState {
contract_address.0.key().clone().to_string()
]),
)
.unwrap();
.unwrap_or_default();

ClassHash(hash)
}
Expand All @@ -431,7 +431,8 @@ impl RpcState {
contract_address.0.key().clone().to_string()
]),
)
.unwrap()
// When running deploy_account transactions, the nonce doesn't exist on the previous block so we return 0
.unwrap_or_default()
}

pub fn get_storage_at(
Expand All @@ -450,7 +451,7 @@ impl RpcState {
self.block.to_value().unwrap()
]),
)
.unwrap()
.unwrap_or_default()
}

/// Requests the given transaction to the Feeder Gateway API.
Expand Down
3 changes: 3 additions & 0 deletions rpc_state_reader/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ pub fn deserialize_transaction_json(
"unimplemented invoke version: {x}"
))),
},
"DEPLOY_ACCOUNT" => Ok(Transaction::DeployAccount(serde_json::from_value(
transaction,
)?)),
x => Err(serde::de::Error::custom(format!(
"unimplemented transaction type deserialization: {x}"
))),
Expand Down
34 changes: 31 additions & 3 deletions rpc_state_reader/tests/blockifier_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use blockifier::{
state_api::{StateReader, StateResult},
},
transaction::{
account_transaction::AccountTransaction, objects::TransactionExecutionInfo,
transactions::ExecutableTransaction,
account_transaction::AccountTransaction,
objects::TransactionExecutionInfo,
transactions::{DeployAccountTransaction, ExecutableTransaction},
},
};
use blockifier::{
Expand All @@ -27,7 +28,10 @@ use starknet::core::types::ContractClass as SNContractClass;
use starknet_api::{
block::BlockNumber,
contract_address,
core::{ClassHash, CompiledClassHash, ContractAddress, Nonce, PatriciaKey},
core::{
calculate_contract_address, ClassHash, CompiledClassHash, ContractAddress, Nonce,
PatriciaKey,
},
hash::{StarkFelt, StarkHash},
patricia_key, stark_felt,
state::StorageKey,
Expand Down Expand Up @@ -176,6 +180,20 @@ pub fn execute_tx(
let invoke = InvokeTransaction { tx, tx_hash };
AccountTransaction::Invoke(invoke)
}
SNTransaction::DeployAccount(tx) => {
let contract_address = calculate_contract_address(
tx.contract_address_salt,
tx.class_hash,
&tx.constructor_calldata,
ContractAddress::default(),
)
.unwrap();
AccountTransaction::DeployAccount(DeployAccountTransaction {
tx,
tx_hash,
contract_address,
})
}
_ => unimplemented!(),
};

Expand Down Expand Up @@ -286,6 +304,16 @@ fn blockifier_test_recent_tx() {
186551, // real block 186552
RpcChain::MainNet
)]
#[test_case(
"0x1cbc74e101a1533082a021ce53235cfd744899b0ff948d1949a64646e0f15c2",
885298, // real block 885299
RpcChain::TestNet
)]
#[test_case(
"0x5a5de1f42f6005f3511ea6099daed9bcbcf9de334ee714e8563977e25f71601",
281513, // real block 281514
RpcChain::MainNet
)]
fn blockifier_test_case_tx(hash: &str, block_number: u64, chain: RpcChain) {
let (tx_info, trace, receipt) = execute_tx(hash, chain, BlockNumber(block_number));

Expand Down
17 changes: 16 additions & 1 deletion rpc_state_reader/tests/sir_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use starknet_in_rust::{
state_cache::StorageEntry,
BlockInfo,
},
transaction::InvokeFunction,
transaction::{DeployAccount, InvokeFunction},
utils::{Address, ClassHash},
};

Expand Down Expand Up @@ -143,6 +143,11 @@ pub fn execute_tx_configurable(
SNTransaction::Invoke(tx) => InvokeFunction::from_invoke_transaction(tx, chain_id)
.unwrap()
.create_for_simulation(skip_validate, false, false, false, skip_nonce_check),
SNTransaction::DeployAccount(tx) => {
DeployAccount::from_sn_api_transaction(tx, chain_id.to_felt())
.unwrap()
.create_for_simulation(skip_validate, false, false, false)
}
_ => unimplemented!(),
};

Expand Down Expand Up @@ -277,6 +282,16 @@ fn test_get_gas_price() {
317092, // real block 317093
RpcChain::MainNet
)]
#[test_case(
"0x1cbc74e101a1533082a021ce53235cfd744899b0ff948d1949a64646e0f15c2",
885298, // real block 885299
RpcChain::TestNet
)]
#[test_case(
"0x5a5de1f42f6005f3511ea6099daed9bcbcf9de334ee714e8563977e25f71601",
281513, // real block 281514
RpcChain::MainNet
)]
fn starknet_in_rust_test_case_tx(hash: &str, block_number: u64, chain: RpcChain) {
let (tx_info, trace, receipt) = execute_tx(hash, chain, BlockNumber(block_number));

Expand Down
2 changes: 1 addition & 1 deletion src/definitions/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::collections::HashMap;

pub(crate) const L2_TO_L1_MSG_HEADER_SIZE: usize = 3;
pub(crate) const L1_TO_L2_MSG_HEADER_SIZE: usize = 5;
pub(crate) const DEPLOYMENT_INFO_SIZE: usize = 1;
pub(crate) const CLASS_UPDATE_SIZE: usize = 1;
pub(crate) const CONSUMED_MSG_TO_L2_N_TOPICS: usize = 3;
pub(crate) const LOG_MSG_TO_L1_N_TOPICS: usize = 2;
pub(crate) const N_DEFAULT_TOPICS: usize = 1; // Events have one default topic.
Expand Down
47 changes: 25 additions & 22 deletions src/execution/gas_usage.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::definitions::constants::*;
use crate::execution::L2toL1MessageInfo;
use crate::services::eth_definitions::eth_gas_constants::*;
use crate::state::state_api::StateChangesCount;

/// Estimates L1 gas usage by Starknet's update state and the verifier
///
Expand All @@ -19,16 +20,13 @@ use crate::services::eth_definitions::eth_gas_constants::*;
/// The estimation of L1 gas usage as a `usize` value.
pub fn calculate_tx_gas_usage(
l2_to_l1_messages: Vec<L2toL1MessageInfo>,
n_modified_contracts: usize,
n_storage_changes: usize,
state_changes: &StateChangesCount,
l1_handler_payload_size: Option<usize>,
n_deployments: usize,
) -> usize {
let residual_message_segment_length =
get_message_segment_lenght(&l2_to_l1_messages, l1_handler_payload_size);

let residual_onchain_data_segment_length =
get_onchain_data_segment_length(n_modified_contracts, n_storage_changes, n_deployments);
let residual_onchain_data_segment_length = get_onchain_data_segment_length(state_changes);

let n_l2_to_l1_messages = l2_to_l1_messages.len();
let n_l1_to_l2_messages = match l1_handler_payload_size {
Expand Down Expand Up @@ -95,22 +93,18 @@ pub fn get_message_segment_lenght(
}

/// Calculates the amount of `felt252` added to the output message's segment by the given operations.
///
/// # Parameters:
///
/// - `n_modified_contracts`: The number of contracts modified by the transaction.
/// - `n_storage_changes`: The number of storage changes made by the transaction.
/// - `n_deployments`: The number of contracts deployed by the transaction.
///
/// # Returns:
///
/// The on-chain data segment length
pub const fn get_onchain_data_segment_length(
n_modified_contracts: usize,
n_storage_changes: usize,
n_deployments: usize,
) -> usize {
n_modified_contracts * 2 + n_deployments * DEPLOYMENT_INFO_SIZE + n_storage_changes * 2
pub const fn get_onchain_data_segment_length(state_changes: &StateChangesCount) -> usize {
// For each newly modified contract:
// contract address (1 word).
// + 1 word with the following info: A flag indicating whether the class hash was updated, the
// number of entry updates, and the new nonce.
state_changes.n_modified_contracts * 2
// For each class updated (through a deploy or a class replacement).
+ state_changes.n_class_hash_updates * CLASS_UPDATE_SIZE
// For each modified storage cell: key, new value.
+ state_changes.n_storage_updates * 2
// For each compiled class updated (through declare): class_hash, compiled_class_hash
+ state_changes.n_compiled_class_hash_updates * 2
}

/// Calculates the cost of ConsumedMessageToL2 event emissions caused by an L1 handler with the given
Expand Down Expand Up @@ -261,7 +255,16 @@ mod test {
let message2 = L2toL1MessageInfo::new(ord_ev2, Address(1235.into()));

assert_eq!(
calculate_tx_gas_usage(vec![message1, message2], 2, 2, Some(2), 1),
calculate_tx_gas_usage(
vec![message1, message2],
&StateChangesCount {
n_storage_updates: 2,
n_class_hash_updates: 1,
n_compiled_class_hash_updates: 0,
n_modified_contracts: 2
},
Some(2)
),
76439
)
}
Expand Down
2 changes: 1 addition & 1 deletion src/services/api/contract_classes/compiled_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl From<StarknetRsContractClass> for CompiledClass {
)
})
.collect::<Vec<ContractEntryPoint>>();
entry_points_by_type.insert(EntryPointType::Constructor, l1_handler_entries);
entry_points_by_type.insert(EntryPointType::L1Handler, l1_handler_entries);

let v = serde_json::to_value(&_deprecated_contract_class.abi).unwrap();
let abi: Option<AbiType> = serde_json::from_value(v).unwrap();
Expand Down
39 changes: 26 additions & 13 deletions src/state/cached_state.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{
state_api::{State, StateReader},
state_api::{State, StateChangesCount, StateReader},
state_cache::{StateCache, StorageEntry},
};
use crate::{
Expand Down Expand Up @@ -283,10 +283,10 @@ impl<T: StateReader> State for CachedState<T> {
Ok(())
}

fn count_actual_storage_changes(
fn count_actual_state_changes(
&mut self,
fee_token_and_sender_address: Option<(&Address, &Address)>,
) -> Result<(usize, usize), StateError> {
) -> Result<StateChangesCount, StateError> {
self.update_initial_values_of_write_only_accesses()?;

let mut storage_updates = subtract_mappings(
Expand All @@ -296,17 +296,24 @@ impl<T: StateReader> State for CachedState<T> {

let storage_unique_updates = storage_updates.keys().map(|k| k.0.clone());

let class_hash_updates = subtract_mappings_keys(
let class_hash_updates: Vec<&Address> = subtract_mappings_keys(
&self.cache.class_hash_writes,
&self.cache.class_hash_initial_values,
)
.collect();
let n_class_hash_updates = class_hash_updates.len();

let compiled_class_hash_updates = subtract_mappings_keys(
&self.cache.compiled_class_hash_writes,
&self.cache.compiled_class_hash_initial_values,
);

let nonce_updates =
subtract_mappings_keys(&self.cache.nonce_writes, &self.cache.nonce_initial_values);

let mut modified_contracts: HashSet<Address> = HashSet::new();
modified_contracts.extend(storage_unique_updates);
modified_contracts.extend(class_hash_updates.cloned());
modified_contracts.extend(class_hash_updates.into_iter().cloned());
modified_contracts.extend(nonce_updates.cloned());

// Add fee transfer storage update before actually charging it, as it needs to be included in the
Expand All @@ -320,7 +327,12 @@ impl<T: StateReader> State for CachedState<T> {
modified_contracts.remove(fee_token_address);
}

Ok((modified_contracts.len(), storage_updates.len()))
Ok(StateChangesCount {
n_storage_updates: storage_updates.len(),
n_class_hash_updates,
n_compiled_class_hash_updates: compiled_class_hash_updates.count(),
n_modified_contracts: modified_contracts.len(),
})
}

/// Returns the class hash for a given contract address.
Expand Down Expand Up @@ -800,7 +812,7 @@ mod tests {

/// This test calculate the number of actual storage changes.
#[test]
fn count_actual_storage_changes_test() {
fn count_actual_state_changes_test() {
let state_reader = InMemoryStateReader::default();

let mut cached_state = CachedState::new(Arc::new(state_reader), HashMap::new());
Expand All @@ -822,14 +834,15 @@ mod tests {
let fee_token_address = Address(123.into());
let sender_address = Address(321.into());

let expected_changes = {
let n_storage_updates = 3 + 1; // + 1 fee transfer balance update
let n_modified_contracts = 2;

(n_modified_contracts, n_storage_updates)
let expected_changes = StateChangesCount {
n_storage_updates: 3 + 1, // + 1 fee transfer balance update,
n_class_hash_updates: 0,
n_compiled_class_hash_updates: 0,
n_modified_contracts: 2,
};

let changes = cached_state
.count_actual_storage_changes(Some((&fee_token_address, &sender_address)))
.count_actual_state_changes(Some((&fee_token_address, &sender_address)))
.unwrap();

assert_eq!(changes, expected_changes);
Expand Down
14 changes: 11 additions & 3 deletions src/state/state_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ pub trait StateReader {
) -> Result<CompiledClassHash, StateError>;
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct StateChangesCount {
pub n_storage_updates: usize,
pub n_class_hash_updates: usize,
pub n_compiled_class_hash_updates: usize,
pub n_modified_contracts: usize,
}

pub trait State {
fn set_contract_class(
&mut self,
Expand Down Expand Up @@ -63,11 +71,11 @@ pub trait State {

fn apply_state_update(&mut self, sate_updates: &StateDiff) -> Result<(), StateError>;

/// Counts the amount of modified contracts and the updates to the storage
fn count_actual_storage_changes(
/// Counts the amount of state changes
fn count_actual_state_changes(
&mut self,
fee_token_and_sender_address: Option<(&Address, &Address)>,
) -> Result<(usize, usize), StateError>;
) -> Result<StateChangesCount, StateError>;

/// Returns the class hash of the contract class at the given address.
/// Returns zero by default if the value is not present
Expand Down
4 changes: 2 additions & 2 deletions src/syscalls/native_syscall_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ impl<'a, S: StateReader> StarkNetSyscallHandler for NativeSyscallHandler<'a, S>
_gas: &mut u128,
) -> SyscallResult<cairo_vm::felt::Felt252> {
let value = match self.starknet_storage_state.read(&address.to_be_bytes()) {
Ok(value) => Ok(dbg!(value)),
Ok(value) => Ok(value),
Err(_e @ StateError::Io(_)) => todo!(),
Err(_) => Ok(dbg!(Felt252::zero())),
Err(_) => Ok(Felt252::zero()),
};
println!("Called `storage_read({address_domain}, {address}) = {value:?}` from MLIR.");
value
Expand Down
2 changes: 1 addition & 1 deletion src/transaction/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ impl Declare {
} else {
self.run_validate_entrypoint(state, &mut resources_manager, block_context)?
};
let changes = state.count_actual_storage_changes(Some((
let changes = state.count_actual_state_changes(Some((
&block_context.starknet_os_config.fee_token_address,
&self.sender_address,
)))?;
Expand Down
2 changes: 1 addition & 1 deletion src/transaction/declare_v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ impl DeclareV2 {
(info, gas)
};

let storage_changes = state.count_actual_storage_changes(Some((
let storage_changes = state.count_actual_state_changes(Some((
&block_context.starknet_os_config.fee_token_address,
&self.sender_address,
)))?;
Expand Down
Loading