Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.
Merged
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8eaa731
Add skip flags to transactions
mmsc2 Jun 28, 2023
b74cb99
implement functions in deploy
mmsc2 Jun 28, 2023
bcd932e
implement functions in deploy account
mmsc2 Jun 28, 2023
c33004d
implement functions in l1handler
mmsc2 Jun 28, 2023
e997cfd
avoid execution
mmsc2 Jun 28, 2023
e4e5f9e
support multiple transactions
SantiagoPittella Jun 28, 2023
648c839
Merge branch 'main' into multiple-transactions-simulation
juanbono Jun 28, 2023
cec32ff
Merge branch 'main' into multiple-transactions-simulation
juanbono Jun 28, 2023
b8d18f3
Add skip_fee_transfer flag
mmsc2 Jun 28, 2023
e4cd886
Merge branch 'main' into SimulateDeclareDeploy
mmsc2 Jun 28, 2023
9dd58cd
Fix broken test
mmsc2 Jun 28, 2023
c970d7d
test with multiple txs
SantiagoPittella Jun 29, 2023
2fbb967
Merge branch 'multiple-transactions-simulation' of github.com:lambdac…
SantiagoPittella Jun 29, 2023
0c813a1
remove simulate_Tx method, refactor create tx methods
SantiagoPittella Jun 29, 2023
56fd5b9
remove cached state imports
SantiagoPittella Jun 29, 2023
696f61d
add tests for invoke, declare, deploy and deploy_account
SantiagoPittella Jun 29, 2023
cd4c5f8
Add declare v2 simulation test
SantiagoPittella Jun 29, 2023
d58d465
Add l1 handler tx test
SantiagoPittella Jun 29, 2023
3573a4f
re arrange imports
SantiagoPittella Jun 29, 2023
099c347
remove clones
SantiagoPittella Jun 29, 2023
4752841
rmeove unwrap
SantiagoPittella Jun 30, 2023
34d3d8f
Merge branch 'main' into SimulateDeclareDeploy
SantiagoPittella Jun 30, 2023
37e4a2f
Merge branch 'main' into multiple-transactions-simulation
juanbono Jun 30, 2023
c64e485
Merge branch 'SimulateDeclareDeploy' into multiple-transactions-simul…
SantiagoPittella Jun 30, 2023
c0e3787
Merge branch 'main' into multiple-transactions-simulation
SantiagoPittella Jul 3, 2023
1d2a245
Re-add test
SantiagoPittella Jul 3, 2023
0fbc5ef
Merge branch 'main' into multiple-transactions-simulation
SantiagoPittella Jul 3, 2023
0c5b287
merge from main
juanbono Jul 3, 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
169 changes: 110 additions & 59 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,43 +47,55 @@ pub mod transaction;
pub mod utils;

pub fn simulate_transaction<S: StateReader>(
transaction: &Transaction,
transactions: &[Transaction],
state: S,
block_context: BlockContext,
remaining_gas: u128,
skip_validate: bool,
skip_execute: bool,
skip_fee_transfer: bool,
) -> Result<TransactionExecutionInfo, TransactionError> {
let mut cached_state = CachedState::new(state, None, Some(HashMap::new()));
let tx_for_simulation =
transaction.create_for_simulation(skip_validate, skip_execute, skip_fee_transfer);
tx_for_simulation.execute(&mut cached_state, &block_context, remaining_gas)
) -> Result<Vec<TransactionExecutionInfo>, TransactionError> {
let mut cache_state = CachedState::new(state, None, Some(HashMap::new()));
let mut result = Vec::with_capacity(transactions.len());
for transaction in transactions {
let tx_for_simulation =
transaction.create_for_simulation(skip_validate, skip_execute, skip_fee_transfer);
let tx_result =
tx_for_simulation.execute(&mut cache_state, &block_context, remaining_gas)?;
result.push(tx_result);
}

Ok(result)
}

/// Estimate the fee associated with transaction
pub fn estimate_fee<T>(
transaction: &Transaction,
transactions: &[Transaction],
state: T,
block_context: &BlockContext,
) -> Result<(u128, usize), TransactionError>
) -> Result<Vec<(u128, usize)>, TransactionError>
where
T: StateReader,
{
// This is used as a copy of the original state, we can update this cached state freely.
let mut cached_state = CachedState::<T>::new(state, None, None);

// Check if the contract is deployed.
cached_state.get_class_hash_at(&transaction.contract_address())?;

// execute the transaction with the fake state.
let transaction_result = transaction.execute(&mut cached_state, block_context, 1_000_000)?;
if let Some(gas_usage) = transaction_result.actual_resources.get("l1_gas_usage") {
let actual_fee = transaction_result.actual_fee;
Ok((actual_fee, *gas_usage))
} else {
Err(TransactionError::ResourcesError)
let mut result = Vec::with_capacity(transactions.len());
for transaction in transactions {
// Check if the contract is deployed.
cached_state.get_class_hash_at(&transaction.contract_address())?;
// execute the transaction with the fake state.

let transaction_result =
transaction.execute(&mut cached_state, block_context, 1_000_000)?;
if let Some(gas_usage) = transaction_result.actual_resources.get("l1_gas_usage") {
result.push((transaction_result.actual_fee, *gas_usage));
} else {
return Err(TransactionError::ResourcesError);
};
}

Ok(result)
}

pub fn call_contract<T: State + StateReader>(
Expand Down Expand Up @@ -292,8 +304,8 @@ mod test {
.unwrap();
let transaction = Transaction::InvokeFunction(invoke_function);

let estimated_fee = estimate_fee(&transaction, state, &block_context).unwrap();
assert_eq!(estimated_fee, (12, 0));
let estimated_fee = estimate_fee(&[transaction], state, &block_context).unwrap();
assert_eq!(estimated_fee[0], (12, 0));
}

#[test]
Expand Down Expand Up @@ -510,23 +522,54 @@ mod test {
]
.to_vec();

let invoke = InvokeFunction::new(
address,
entrypoint_selector,
1000000,
Felt252::one(),
calldata,
vec![],
StarknetChainId::TestNet.to_felt(),
Some(1.into()),
None,
)
.unwrap();
let invoke_1 = Transaction::InvokeFunction(
InvokeFunction::new(
address.clone(),
entrypoint_selector.clone(),
1000000,
Felt252::one(),
calldata.clone(),
vec![],
StarknetChainId::TestNet.to_felt(),
Some(1.into()),
None,
)
.unwrap(),
);

let invoke_2 = Transaction::InvokeFunction(
InvokeFunction::new(
address.clone(),
entrypoint_selector.clone(),
1000000,
Felt252::one(),
calldata.clone(),
vec![],
StarknetChainId::TestNet.to_felt(),
Some(2.into()),
None,
)
.unwrap(),
);

let invoke_3 = Transaction::InvokeFunction(
InvokeFunction::new(
address,
entrypoint_selector,
1000000,
Felt252::one(),
calldata,
vec![],
StarknetChainId::TestNet.to_felt(),
Some(3.into()),
None,
)
.unwrap(),
);
let block_context = BlockContext::default();

let context = simulate_transaction(
&Transaction::InvokeFunction(invoke),
&[invoke_1, invoke_2, invoke_3],
state_reader,
block_context,
1000,
Expand All @@ -536,9 +579,15 @@ mod test {
)
.unwrap();

assert!(context.validate_info.is_some());
assert!(context.call_info.is_none());
assert!(context.fee_transfer_info.is_none());
assert!(context[0].validate_info.is_some());
assert!(context[0].call_info.is_none());
assert!(context[0].fee_transfer_info.is_none());
assert!(context[1].validate_info.is_some());
assert!(context[1].call_info.is_none());
assert!(context[1].fee_transfer_info.is_none());
assert!(context[2].validate_info.is_some());
assert!(context[2].call_info.is_none());
assert!(context[2].fee_transfer_info.is_none());
Comment on lines +582 to +590
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe use a for?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

he performed loop unrolling (?)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blazing fast tests

}

#[test]
Expand Down Expand Up @@ -601,23 +650,25 @@ mod test {
]
.to_vec();

let invoke = InvokeFunction::new(
address,
entrypoint_selector,
1000000,
Felt252::one(),
calldata,
vec![],
StarknetChainId::TestNet.to_felt(),
Some(1.into()),
None,
)
.unwrap();
let invoke = Transaction::InvokeFunction(
InvokeFunction::new(
address,
entrypoint_selector,
1000000,
Felt252::one(),
calldata,
vec![],
StarknetChainId::TestNet.to_felt(),
Some(1.into()),
None,
)
.unwrap(),
);

let block_context = BlockContext::default();

let context = simulate_transaction(
&Transaction::InvokeFunction(invoke),
&[invoke],
state_reader,
block_context,
1000,
Expand All @@ -627,9 +678,9 @@ mod test {
)
.unwrap();

assert!(context.validate_info.is_none());
assert!(context.call_info.is_none());
assert!(context.fee_transfer_info.is_none());
assert!(context[0].validate_info.is_none());
assert!(context[0].call_info.is_none());
assert!(context[0].fee_transfer_info.is_none());
}

#[test]
Expand Down Expand Up @@ -659,7 +710,7 @@ mod test {
);

simulate_transaction(
&internal_deploy,
&[internal_deploy],
state,
block_context,
100_000_000,
Expand Down Expand Up @@ -695,7 +746,7 @@ mod test {
);

simulate_transaction(
&declare_tx,
&[declare_tx],
state,
block_context,
100_000_000,
Expand Down Expand Up @@ -756,7 +807,7 @@ mod test {
);

simulate_transaction(
&invoke_tx,
&[invoke_tx],
state,
block_context,
100_000_000,
Expand All @@ -779,7 +830,7 @@ mod test {
let block_context = Default::default();

// new consumes more execution time than raw struct instantiation
let deploy_account_tx = &Transaction::DeployAccount(
let deploy_account_tx = Transaction::DeployAccount(
DeployAccount::new(
*CLASS_HASH_BYTES,
0,
Expand All @@ -795,7 +846,7 @@ mod test {
);

simulate_transaction(
deploy_account_tx,
&[deploy_account_tx],
state,
block_context,
100_000_000,
Expand Down Expand Up @@ -835,7 +886,7 @@ mod test {
let declare_tx = Transaction::DeclareV2(Box::new(declarev2_tx()));

simulate_transaction(
&declare_tx,
&[declare_tx],
state,
block_context,
100_000_000,
Expand Down Expand Up @@ -904,7 +955,7 @@ mod test {
block_context.starknet_os_config.gas_price = 1;

simulate_transaction(
&l1_handler_tx,
&[l1_handler_tx],
state,
block_context,
100_000_000,
Expand Down