Skip to content

Commit e5e710c

Browse files
starknet_os: os resources test - invoke tx constant factor
1 parent 572a3b1 commit e5e710c

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
@@ -21,3 +21,6 @@
2121
~ /os_resources/execute_syscalls/Secp256r1New/n_steps: 564
2222
~ /os_resources/execute_syscalls/SendMessageToL1/n_steps: 124
2323
~ /os_resources/execute_syscalls/Sha256ProcessBlock/n_steps: 1854
24+
~ /os_resources/execute_txs_inner/InvokeFunction/constant/builtin_instance_counter/poseidon_builtin: 11
25+
~ /os_resources/execute_txs_inner/InvokeFunction/constant/builtin_instance_counter/range_check_builtin: 110
26+
~ /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};
@@ -169,7 +170,7 @@ async fn setup_test_builder(raw_vc: Option<&RawVersionedConstants>) -> OsResourc
169170
);
170171
test_builder.add_fund_address_tx_with_default_amount(os_resources_contract_address);
171172

172-
// Declare and deploy an instance of the stable contract.
173+
// Declare and deploy an instance of the stable contract. Also, fund it.
173174
let stable_contract_sierra = &DEPLOYABLE_FOR_RESOURCE_MEASUREMENT_CONTRACT_SIERRA;
174175
let stable_contract_casm = &DEPLOYABLE_FOR_RESOURCE_MEASUREMENT_CONTRACT_CASM;
175176
let stable_contract_class_hash = stable_contract_sierra.calculate_class_hash();
@@ -195,6 +196,7 @@ async fn setup_test_builder(raw_vc: Option<&RawVersionedConstants>) -> OsResourc
195196
deploy_from_zero,
196197
);
197198
test_builder.add_invoke_tx(deploy_tx, None, None);
199+
test_builder.add_fund_address_tx_with_default_amount(stable_contract_address);
198200

199201
// Move on to the next block, so the measurement txs are in their own block.
200202
test_builder.move_to_next_block();
@@ -207,6 +209,13 @@ async fn setup_test_builder(raw_vc: Option<&RawVersionedConstants>) -> OsResourc
207209
}
208210
}
209211

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

0 commit comments

Comments
 (0)