Skip to content

Commit b3de0fd

Browse files
blockifier: add test_proving_gas_minus_sierra_gas_equals_builtin_gas
0.13.6
1 parent 4700baa commit b3de0fd

File tree

1 file changed

+143
-1
lines changed

1 file changed

+143
-1
lines changed

crates/blockifier/src/bouncer_test.rs

Lines changed: 143 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ use std::collections::{HashMap, HashSet};
22

33
use assert_matches::assert_matches;
44
use cairo_vm::types::builtin_name::BuiltinName;
5+
use cairo_vm::vm::runners::cairo_runner::ExecutionResources;
56
use rstest::rstest;
7+
use starknet_api::core::ClassHash;
68
use starknet_api::execution_resources::GasAmount;
79
use starknet_api::transaction::fields::Fee;
810
use starknet_api::{class_hash, contract_address, storage_key};
911

1012
use super::BouncerConfig;
1113
use crate::blockifier::transaction_executor::TransactionExecutorError;
1214
use crate::bouncer::{
15+
get_tx_weights,
1316
verify_tx_weights_within_max_capacity,
1417
Bouncer,
1518
BouncerWeights,
@@ -18,9 +21,12 @@ use crate::bouncer::{
1821
use crate::context::BlockContext;
1922
use crate::execution::call_info::ExecutionSummary;
2023
use crate::fee::resources::{ComputationResources, TransactionResources};
21-
use crate::state::cached_state::{StateChangesKeys, TransactionalState};
24+
use crate::state::cached_state::{StateChangesKeys, StateMaps, TransactionalState};
25+
use crate::test_utils::contracts::FeatureContract;
2226
use crate::test_utils::initial_test_state::test_state;
27+
use crate::test_utils::{CairoVersion, RunnableCairo1};
2328
use crate::transaction::errors::TransactionExecutionError;
29+
use crate::utils::{add_maps, u64_from_usize};
2430

2531
#[test]
2632
fn test_block_weights_has_room() {
@@ -239,3 +245,139 @@ fn test_transaction_too_large_sierra_gas_based() {
239245
)
240246
) if *max_capacity == bouncer_config.block_max_capacity && *tx_size == expected_weights);
241247
}
248+
249+
/// Verifies that the difference between proving gas and Sierra gas
250+
/// is fully accounted for by the builtin gas delta (Stone vs Stwo).
251+
///
252+
/// Covers combinations of OS computation builtins and CASM hash computation builtins.
253+
#[rstest]
254+
#[case::no_os_no_casm(
255+
&[],
256+
ExecutionResources::default(),
257+
HashSet::new(),
258+
HashMap::new(),
259+
)]
260+
#[case::with_os_only(
261+
&[],
262+
ExecutionResources {
263+
builtin_instance_counter: HashMap::from([
264+
(BuiltinName::bitwise, 1),
265+
]),
266+
..Default::default()
267+
},
268+
HashSet::new(),
269+
HashMap::new(),
270+
)]
271+
#[case::with_casm_only(
272+
&[
273+
(FeatureContract::TestContract(CairoVersion::Cairo0), 1),
274+
(FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Casm)), 1),
275+
],
276+
ExecutionResources::default(),
277+
HashSet::from([
278+
FeatureContract::TestContract(CairoVersion::Cairo0).get_class_hash(),
279+
FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Casm)).get_class_hash(),
280+
]),
281+
// Builtins mapping computed by printing `additional_os_resources.builtin_instance_counter`
282+
// in `get_tx_weights` (bouncer_test.rs) for the above contracts.
283+
HashMap::from([
284+
(BuiltinName::poseidon, 11699),
285+
(BuiltinName::pedersen, 2205),
286+
]),
287+
)]
288+
#[case::with_os_and_casm(
289+
&[
290+
(FeatureContract::TestContract(CairoVersion::Cairo0), 1),
291+
(FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Casm)), 1),
292+
],
293+
ExecutionResources {
294+
builtin_instance_counter: HashMap::from([
295+
(BuiltinName::range_check, 1),
296+
(BuiltinName::bitwise, 2),
297+
]),
298+
..Default::default()
299+
},
300+
HashSet::from([
301+
FeatureContract::TestContract(CairoVersion::Cairo0).get_class_hash(),
302+
FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Casm)).get_class_hash(),
303+
]),
304+
HashMap::from([
305+
(BuiltinName::poseidon, 11699),
306+
(BuiltinName::pedersen, 2205),
307+
]),
308+
)]
309+
fn test_proving_gas_minus_sierra_gas_equals_builtin_gas(
310+
#[case] contract_instances: &[(FeatureContract, u16)],
311+
#[case] os_vm_resources: ExecutionResources,
312+
#[case] executed_class_hashes: HashSet<ClassHash>,
313+
#[case] casm_hash_computation_builtins: HashMap<BuiltinName, usize>,
314+
) {
315+
let block_context = BlockContext::create_for_account_testing();
316+
let state = test_state(&block_context.chain_info, Fee(0), contract_instances);
317+
318+
// Transaction builtin counters.
319+
let mut tx_builtin_counters =
320+
HashMap::from([(BuiltinName::range_check, 2), (BuiltinName::pedersen, 1)]);
321+
322+
let tx_resources = TransactionResources {
323+
computation: ComputationResources {
324+
sierra_gas: GasAmount(100),
325+
tx_vm_resources: ExecutionResources {
326+
builtin_instance_counter: tx_builtin_counters.clone(),
327+
..Default::default()
328+
},
329+
os_vm_resources: os_vm_resources.clone(),
330+
..Default::default()
331+
},
332+
..Default::default()
333+
};
334+
// If we simulate CASM hash computation, we assume storage entries were visited.
335+
let n_visited_storage_entries = if casm_hash_computation_builtins.is_empty() { 0 } else { 1 };
336+
337+
let result = get_tx_weights(
338+
&state,
339+
&executed_class_hashes,
340+
n_visited_storage_entries,
341+
&tx_resources,
342+
&StateMaps::default().keys(), // state changes keys
343+
&block_context.versioned_constants,
344+
&tx_builtin_counters,
345+
&block_context.bouncer_config.builtin_weights,
346+
)
347+
.unwrap();
348+
349+
// Combine TX + OS + CASM builtin usage.
350+
add_maps(&mut tx_builtin_counters, &os_vm_resources.builtin_instance_counter);
351+
add_maps(&mut tx_builtin_counters, &casm_hash_computation_builtins);
352+
353+
// Compute expected gas delta from builtin delta (Stwo - Stone).
354+
let expected_builtin_gas_delta = tx_builtin_counters
355+
.iter()
356+
.map(|(name, count)| {
357+
let swo_gas = block_context.bouncer_config.builtin_weights.builtin_weight(name);
358+
let stone_gas = block_context
359+
.versioned_constants
360+
.os_constants
361+
.gas_costs
362+
.builtins
363+
.get_builtin_gas_cost(name)
364+
.expect();
365+
366+
let stwo_total = swo_gas.checked_mul(*count).map(u64_from_usize).expect("overflow");
367+
let stone_total = u64_from_usize(*count).checked_mul(stone_gas).expect("overflow");
368+
369+
stwo_total.checked_sub(stone_total).expect("underflow")
370+
})
371+
// Sum the deltas.
372+
.try_fold(0u64, |acc, val| acc.checked_add(val))
373+
.expect("overflow in sum");
374+
375+
assert_eq!(
376+
result.proving_gas.0 - result.sierra_gas.0,
377+
expected_builtin_gas_delta,
378+
"Proving gas: {} - Sierra gas: {} ≠ builtins gap: {}",
379+
result.proving_gas.0,
380+
result.sierra_gas.0,
381+
expected_builtin_gas_delta
382+
);
383+
}

0 commit comments

Comments
 (0)