Skip to content

Commit 1664e0f

Browse files
starknet_os: os resources test - invoke tx constant factor
1 parent dfe2b69 commit 1664e0f

8 files changed

Lines changed: 156 additions & 24 deletions

File tree

crates/apollo_rpc/src/v0_8/execution_test.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,22 +173,22 @@ lazy_static! {
173173
// TODO(yair): verify this is the correct fee, got this value by printing the result of the
174174
// call.
175175
pub static ref EXPECTED_FEE_ESTIMATE: FeeEstimation = FeeEstimation {
176-
gas_consumed: felt!("0x682"),
176+
gas_consumed: felt!("0x683"),
177177
l1_gas_price: GAS_PRICE.price_in_wei,
178178
data_gas_consumed: Felt::ZERO,
179179
l1_data_gas_price: DATA_GAS_PRICE.price_in_wei,
180180
l2_gas_price: L2_GAS_PRICE.price_in_wei,
181-
overall_fee: Fee(166600000000000,),
181+
overall_fee: Fee(166700000000000,),
182182
unit: PriceUnit::Wei,
183183
};
184184

185185
pub static ref EXPECTED_FEE_ESTIMATE_SKIP_VALIDATE: FeeEstimation = FeeEstimation {
186-
gas_consumed: felt!("0x682"),
186+
gas_consumed: felt!("0x683"),
187187
l1_gas_price: GAS_PRICE.price_in_wei,
188188
data_gas_consumed: Felt::ZERO,
189189
l1_data_gas_price: DATA_GAS_PRICE.price_in_wei,
190190
l2_gas_price: L2_GAS_PRICE.price_in_wei,
191-
overall_fee: Fee(166600000000000,),
191+
overall_fee: Fee(166700000000000,),
192192
unit: PriceUnit::Wei,
193193
};
194194

crates/blockifier/resources/blockifier_versioned_constants_0_14_4.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -526,12 +526,12 @@
526526
},
527527
"InvokeFunction": {
528528
"constant": {
529-
"n_steps": 4348,
529+
"n_steps": 4779,
530530
"n_memory_holes": 0,
531531
"builtin_instance_counter": {
532-
"range_check_builtin": 90,
532+
"range_check_builtin": 110,
533533
"pedersen_builtin": 4,
534-
"poseidon_builtin": 12
534+
"poseidon_builtin": 11
535535
}
536536
},
537537
"calldata_factor": {

crates/blockifier/resources/versioned_constants_diff_regression/0.14.3_0.14.4.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,6 @@
2222
~ /os_resources/execute_syscalls/Secp256r1New/n_steps: 564
2323
~ /os_resources/execute_syscalls/SendMessageToL1/n_steps: 124
2424
~ /os_resources/execute_syscalls/Sha256ProcessBlock/n_steps: 1854
25+
~ /os_resources/execute_txs_inner/InvokeFunction/constant/builtin_instance_counter/poseidon_builtin: 11
26+
~ /os_resources/execute_txs_inner/InvokeFunction/constant/builtin_instance_counter/range_check_builtin: 110
27+
~ /os_resources/execute_txs_inner/InvokeFunction/constant/n_steps: 4779

crates/blockifier/src/transaction/account_transactions_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ fn test_infinite_recursion(
458458
resource_bounds: ValidResourceBounds,
459459
) {
460460
// Limit the number of execution steps (so we quickly hit the limit).
461-
block_context.versioned_constants.invoke_tx_max_n_steps = 4700;
461+
block_context.versioned_constants.invoke_tx_max_n_steps = 6000;
462462

463463
let TestInitData { mut state, account_address, contract_address, mut nonce_manager } =
464464
create_test_init_data(&block_context.chain_info, CairoVersion::Cairo0);
@@ -491,7 +491,7 @@ fn test_infinite_recursion(
491491
)
492492
.unwrap();
493493
if success {
494-
assert!(tx_execution_info.revert_error.is_none());
494+
assert_eq!(tx_execution_info.revert_error, None);
495495
} else {
496496
assert!(
497497
tx_execution_info

crates/blockifier/src/transaction/execution_flavors_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -690,10 +690,10 @@ fn test_simulate_validate_charge_fee_mid_execution(
690690

691691
// Second scenario: limit resources via sender bounds. Should revert if and only if step limit
692692
// is derived from sender bounds (`charge_fee` mode).
693-
let (gas_bound, fee_bound) = gas_and_fee(6543_u32.into(), validate, &fee_type);
693+
let (gas_bound, fee_bound) = gas_and_fee(6962_u32.into(), validate, &fee_type);
694694
// If `charge_fee` is true, execution is limited by sender bounds, so less resources will be
695695
// used. Otherwise, execution is limited by block bounds, so more resources will be used.
696-
let (limited_gas_used, limited_fee) = gas_and_fee(8195_u32.into(), validate, &fee_type);
696+
let (limited_gas_used, limited_fee) = gas_and_fee(8614_u32.into(), validate, &fee_type);
697697
let (unlimited_gas_used, unlimited_fee) = gas_and_fee(
698698
u64_from_usize(
699699
get_const_syscall_resources(SyscallSelector::CallContract).n_steps
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
32
1+
33

crates/central_systest_blobs/resources/preconfirmed_block.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@
2020
"timestamp": 1013,
2121
"transaction_receipts": [
2222
{
23-
"actual_fee": "0x106f19",
23+
"actual_fee": "0x11a799",
2424
"events": [
2525
{
2626
"data": [
2727
"0x3d3759cf036b96f8105f40dcf3fe0c209be3419154aa458d03336ad0443ce81",
2828
"0x1000",
29-
"0x106f19",
29+
"0x11a799",
3030
"0x0"
3131
],
3232
"from_address": "0x6c6a50ee425e9ff35846be376051b8cdbdc1aadc6c954209fe3fd247a571b33",
@@ -38,20 +38,20 @@
3838
"execution_resources": {
3939
"builtin_instance_counter": {
4040
"pedersen_builtin": 4,
41-
"poseidon_builtin": 15,
42-
"range_check_builtin": 90
41+
"poseidon_builtin": 14,
42+
"range_check_builtin": 110
4343
},
4444
"data_availability": {
4545
"l1_data_gas": 0,
4646
"l1_gas": 1652,
4747
"l2_gas": 0
4848
},
4949
"n_memory_holes": 0,
50-
"n_steps": 4381,
50+
"n_steps": 4812,
5151
"total_gas_consumed": {
5252
"l1_data_gas": 0,
5353
"l1_gas": 1652,
54-
"l2_gas": 1075365
54+
"l2_gas": 1155365
5555
}
5656
},
5757
"execution_status": "SUCCEEDED",
@@ -74,11 +74,11 @@
7474
"0x6c6a50ee425e9ff35846be376051b8cdbdc1aadc6c954209fe3fd247a571b33": [
7575
{
7676
"key": "0x2cbac7495ce24b399327e9282b09d029b1dd772b24b7e8dcd0467fedab5af58",
77-
"value": "0xfffffffffffffffffffffffff98c2f53"
77+
"value": "0xfffffffffffffffffffffffff9826b53"
7878
},
7979
{
8080
"key": "0x723973208639b7839ce298f7ffea61e3f9533872defd7abdb91023db4658812",
81-
"value": "0x673d0ac"
81+
"value": "0x67d94ac"
8282
}
8383
]
8484
}

crates/starknet_os_flow_tests/src/os_resources_test.rs

Lines changed: 133 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::collections::{HashMap, HashSet};
2-
use std::sync::LazyLock;
2+
use std::sync::{Arc, LazyLock};
33

44
use blockifier::blockifier_versioned_constants::{
5+
CallDataFactor,
56
RawStepGasCost,
67
RawVersionedConstants,
78
ResourcesParams,
@@ -21,9 +22,9 @@ use indexmap::IndexMap;
2122
use starknet_api::block::StarknetVersion;
2223
use starknet_api::contract_class::SierraVersion;
2324
use starknet_api::core::{ClassHash, ContractAddress, EthAddress};
24-
use starknet_api::executable_transaction::InvokeTransaction;
25+
use starknet_api::executable_transaction::{InvokeTransaction, TransactionType};
2526
use starknet_api::test_utils::invoke::invoke_tx;
26-
use starknet_api::transaction::fields::ContractAddressSalt;
27+
use starknet_api::transaction::fields::{Calldata, ContractAddressSalt};
2728
use starknet_api::transaction::{L2ToL1Payload, MessageToL1};
2829
use starknet_api::versioned_constants_logic::VersionedConstantsTrait;
2930
use starknet_api::{calldata, declare_tx_args, invoke_tx_args};
@@ -172,7 +173,7 @@ async fn setup_test_builder(raw_vc: Option<&RawVersionedConstants>) -> OsResourc
172173
);
173174
test_builder.add_fund_address_tx_with_default_amount(os_resources_contract_address);
174175

175-
// Declare and deploy an instance of the stable contract.
176+
// Declare and deploy an instance of the stable contract. Also, fund it.
176177
let stable_contract_sierra = &DEPLOYABLE_FOR_RESOURCE_MEASUREMENT_CONTRACT_SIERRA;
177178
let stable_contract_casm = &DEPLOYABLE_FOR_RESOURCE_MEASUREMENT_CONTRACT_CASM;
178179
let stable_contract_class_hash = stable_contract_sierra.calculate_class_hash();
@@ -198,6 +199,7 @@ async fn setup_test_builder(raw_vc: Option<&RawVersionedConstants>) -> OsResourc
198199
deploy_from_zero,
199200
);
200201
test_builder.add_invoke_tx(deploy_tx, None, None);
202+
test_builder.add_fund_address_tx_with_default_amount(stable_contract_address);
201203

202204
// Move on to the next block, so the measurement txs are in their own block.
203205
test_builder.move_to_next_block();
@@ -210,6 +212,13 @@ async fn setup_test_builder(raw_vc: Option<&RawVersionedConstants>) -> OsResourc
210212
}
211213
}
212214

215+
/// Utility method to create dummy calldata to a cairo Span argument.
216+
fn span_calldata(n_elements: usize) -> Calldata {
217+
let mut calldata = vec![Felt::from(n_elements)];
218+
calldata.extend(vec![Felt::ZERO; n_elements]);
219+
Calldata(Arc::new(calldata))
220+
}
221+
213222
/// Regression test for the list of syscalls called during the fee transfer phase of a transaction.
214223
#[tokio::test]
215224
async fn test_fee_transfer_syscalls() {
@@ -479,3 +488,123 @@ async fn test_os_resources_regression() {
479488
expect_file![VersionedConstants::json_path(&version).unwrap()]
480489
.assert_eq(&raw_vc.to_string_pretty());
481490
}
491+
492+
/// Measures the per-transaction-type overhead of `execute_transaction_inner` in the OS and
493+
/// compares it against the versioned constants.
494+
///
495+
/// Methodology:
496+
/// - Run a minimal transaction of the given type through the full OS.
497+
/// - Compute: overhead = OS trace resources − blockifier business-logic resources
498+
/// (execute_call_info + validate_call_info).
499+
/// - The remainder is the pure OS scaffolding cost stored under `execute_txs_inner`.
500+
#[tokio::test]
501+
async fn test_execute_txs_inner_resources() {
502+
let version = StarknetVersion::LATEST;
503+
let mut raw_vc: RawVersionedConstants =
504+
serde_json::from_str(VersionedConstants::json_str(&version).unwrap()).unwrap();
505+
// TODO(Dori): Declare, DeployAccount, L1Handler.
506+
const N_TXS: usize = 2;
507+
508+
// For linear factor measurements, it's not enough to just add one more calldata element; the
509+
// increase is not the same per element. The linear scale is on average.
510+
const INVOKE_SCALING_FACTOR: usize = 2;
511+
const INVOKE_EXTRA_ARGS: usize = 10;
512+
513+
let OsResourcesTestSetup { stable_contract_address, mut test_builder, .. } =
514+
setup_test_builder(Some(&raw_vc)).await;
515+
516+
// Invoke.
517+
let invoke_args = invoke_tx_args! {
518+
sender_address: stable_contract_address,
519+
calldata: calldata![Felt::ZERO],
520+
resource_bounds: *NON_TRIVIAL_RESOURCE_BOUNDS,
521+
nonce: test_builder.next_nonce(stable_contract_address),
522+
};
523+
test_builder.add_invoke_tx(
524+
InvokeTransaction::create(invoke_tx(invoke_args), &test_builder.chain_id()).unwrap(),
525+
None,
526+
None,
527+
);
528+
// Invoke: scale-factor more calldata elements.
529+
let invoke_args = invoke_tx_args! {
530+
sender_address: stable_contract_address,
531+
calldata: span_calldata(INVOKE_EXTRA_ARGS),
532+
resource_bounds: *NON_TRIVIAL_RESOURCE_BOUNDS,
533+
nonce: test_builder.next_nonce(stable_contract_address),
534+
};
535+
test_builder.add_invoke_tx(
536+
InvokeTransaction::create(invoke_tx(invoke_args), &test_builder.chain_id()).unwrap(),
537+
None,
538+
None,
539+
);
540+
541+
// Execute the business logic and extract the business logic resources for each tx.
542+
let test_runner = test_builder.build().await;
543+
let business_logic_resources: [ExecutionResources; N_TXS] = test_runner
544+
.os_hints
545+
.os_input
546+
.os_block_inputs
547+
.last()
548+
.unwrap()
549+
.tx_execution_infos
550+
.iter()
551+
.map(|exec_info| {
552+
let mut business_logic_resources =
553+
[exec_info.execute_call_info.as_ref(), exec_info.validate_call_info.as_ref()]
554+
.into_iter()
555+
.flatten()
556+
.map(|ci| ci.resources.vm_resources.clone())
557+
.fold(ExecutionResources::default(), |acc, resources| &acc + &resources);
558+
// TODO(Dori): Consider supporting memory-hole counting in the OsLogger. Until then, we
559+
// cannot subtract inner calls with positive memory-hole counts from the OsLogger
560+
// resources.
561+
business_logic_resources.n_memory_holes = 0;
562+
business_logic_resources
563+
})
564+
.collect::<Vec<_>>()
565+
.try_into()
566+
.unwrap();
567+
568+
// Run the OS part.
569+
let test_output = test_runner.run();
570+
test_output.perform_default_validations();
571+
572+
// Fetch the OS resources for each tx.
573+
let [invoke_first, invoke_second]: [ExecutionResources; N_TXS] = test_output
574+
.runner_output
575+
.txs_trace
576+
.iter()
577+
.rev()
578+
.take(N_TXS)
579+
.rev()
580+
.map(|trace| trace.get_resources().unwrap().clone())
581+
.zip(business_logic_resources)
582+
.map(|(os_resources, business_logic_resources)| {
583+
(&os_resources - &business_logic_resources).filter_unused_builtins()
584+
})
585+
.collect::<Vec<_>>()
586+
.try_into()
587+
.unwrap();
588+
589+
// Update the VC with the measurements.
590+
// For transaction types with linear factors, the first call has one linear element (calldata
591+
// length, of zero), so one linear cost must be subtracted from the first measurement to get the
592+
// base cost.
593+
let invoke_linear_factor = (&(&invoke_second - &invoke_first).filter_unused_builtins()
594+
* INVOKE_SCALING_FACTOR)
595+
.div_ceil(INVOKE_EXTRA_ARGS);
596+
raw_vc.os_resources.execute_txs_inner.extend([(
597+
TransactionType::InvokeFunction,
598+
VariableResourceParams::WithFactor(ResourcesParams {
599+
constant: (&invoke_first - &invoke_linear_factor).filter_unused_builtins(),
600+
calldata_factor: VariableCallDataFactor::Scaled(CallDataFactor {
601+
resources: invoke_linear_factor,
602+
scaling_factor: INVOKE_SCALING_FACTOR,
603+
}),
604+
}),
605+
)]);
606+
607+
// Verify computation.
608+
expect_file![VersionedConstants::json_path(&version).unwrap()]
609+
.assert_eq(&raw_vc.to_string_pretty());
610+
}

0 commit comments

Comments
 (0)