Skip to content

Commit f5713fd

Browse files
blockifier: move logic inside felt_size_count
1 parent bbca19d commit f5713fd

File tree

4 files changed

+55
-26
lines changed

4 files changed

+55
-26
lines changed

crates/blockifier/src/execution/contract_class.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ use crate::abi::constants::{self};
4343
use crate::blockifier_versioned_constants::VersionedConstants;
4444
use crate::bouncer::vm_resources_to_sierra_gas;
4545
use crate::execution::call_info::BuiltinCounterMap;
46-
use crate::execution::casm_hash_estimation::EstimatedExecutionResources;
46+
use crate::execution::casm_hash_estimation::{
47+
CasmV2HashResourceEstimate,
48+
EstimatedExecutionResources,
49+
};
4750
use crate::execution::entry_point::{EntryPointExecutionContext, EntryPointTypeAndSelector};
4851
use crate::execution::errors::PreExecutionError;
4952
use crate::execution::execution_utils::{
@@ -82,6 +85,19 @@ impl FeltSizeCount {
8285
pub(crate) fn n_felts(&self) -> usize {
8386
self.small + self.large
8487
}
88+
89+
/// Returns the total number of `u32` words required to encode all felts
90+
/// according to encode_felts_to_u32s func.
91+
pub(crate) fn encoded_u32_len(&self) -> usize {
92+
self.large * Self::U32_WORDS_PER_LARGE_FELT + self.small * Self::U32_WORDS_PER_SMALL_FELT
93+
}
94+
95+
/// Returns the number of BLAKE opcodes required to hash the felts.
96+
/// Each BLAKE opcode processes one message block of [`U32_WORDS_PER_MESSAGE`] `u32`s
97+
/// (partial messages are padded).
98+
pub(crate) fn blake_opcode_count(&self) -> usize {
99+
self.encoded_u32_len().div_ceil(CasmV2HashResourceEstimate::U32_WORDS_PER_MESSAGE)
100+
}
85101
}
86102

87103
/// Counts felts in bytecode by size (small < 2^63, large >= 2^63).
@@ -102,6 +118,25 @@ impl From<&[BigUintAsHex]> for FeltSizeCount {
102118
}
103119
}
104120

121+
/// Counts felts in bytecode by size (small < 2^63, large >= 2^63).
122+
// TODO(AvivG): Remove this.
123+
impl From<&Vec<Felt>> for FeltSizeCount {
124+
fn from(felts: &Vec<Felt>) -> Self {
125+
// TODO(AvivG): use blake2s::SMALL_THRESHOLD.
126+
const SMALL_THRESHOLD: Felt = Felt::from_hex_unchecked("8000000000000000");
127+
128+
let (small, large) = felts.iter().fold((0, 0), |(small_count, large_count), x| {
129+
if *x < SMALL_THRESHOLD {
130+
(small_count + 1, large_count)
131+
} else {
132+
(small_count, large_count + 1)
133+
}
134+
});
135+
136+
FeltSizeCount { small, large }
137+
}
138+
}
139+
105140
#[derive(Clone, Debug, Eq, PartialEq)]
106141
pub enum NestedFeltCounts {
107142
Leaf(usize, FeltSizeCount), // (leaf length, felt size groups)

crates/blockifier/src/execution/contract_class_test.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ use std::collections::HashSet;
22
use std::sync::Arc;
33

44
use assert_matches::assert_matches;
5+
use blake2s::encode_felts_to_u32s;
56
use blockifier_test_utils::cairo_versions::{CairoVersion, RunnableCairo1};
67
use blockifier_test_utils::contracts::FeatureContract;
78
use cairo_lang_starknet_classes::NestedIntList;
89
use cairo_lang_utils::bigint::BigUintAsHex;
910
use rstest::rstest;
1011
use starknet_api::contract_class::compiled_class_hash::{HashVersion, HashableCompiledClass};
1112
use starknet_api::contract_class::ContractClass;
13+
use starknet_types_core::felt::Felt;
1214

1315
use crate::execution::contract_class::{
1416
CompiledClassV1,
@@ -136,3 +138,16 @@ fn test_create_bytecode_segment_felt_sizes(
136138
let result = NestedFeltCounts::new(&bytecode_segment_lengths, &bytecode);
137139
assert_eq!(result, expected_structure);
138140
}
141+
142+
#[rstest]
143+
#[case::boundary_small_felt(vec![Felt::from((1u64 << 63) - 1)])]
144+
#[case::boundary_at_2_63(vec![Felt::from(1u64 << 63)])]
145+
#[case::very_large_felt(vec![Felt::from_hex("0x800000000000011000000000000000000000000000000000000000000000000").unwrap()])]
146+
#[case::mixed_small_large(vec![Felt::from(42), Felt::from(1u64 << 63), Felt::from(1337)])]
147+
#[case::many_large(vec![Felt::from(1u64 << 63); 100])]
148+
fn test_encode_u32s_lengths(#[case] test_data: Vec<Felt>) {
149+
let actual_u32s = encode_felts_to_u32s(test_data.clone());
150+
let estimated_u32s_len = FeltSizeCount::from(&test_data).encoded_u32_len();
151+
152+
assert_eq!(actual_u32s.len(), estimated_u32s_len);
153+
}

crates/blockifier/src/execution/execution_utils.rs

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -397,18 +397,6 @@ mod blake_estimation {
397397
pub const STEPS_EMPTY_INPUT: usize = 170;
398398
}
399399

400-
/// Calculates the total number of u32s required to encode the given number of big and small felts.
401-
/// Big felts encode to 8 u32s each, small felts encode to 2 u32s each.
402-
fn total_u32s_from_felts(n_big_felts: usize, n_small_felts: usize) -> usize {
403-
let big_u32s = n_big_felts
404-
.checked_mul(FeltSizeCount::U32_WORDS_PER_LARGE_FELT)
405-
.expect("Overflow computing big felts u32s");
406-
let small_u32s = n_small_felts
407-
.checked_mul(FeltSizeCount::U32_WORDS_PER_SMALL_FELT)
408-
.expect("Overflow computing small felts u32s");
409-
big_u32s.checked_add(small_u32s).expect("Overflow computing total u32s")
410-
}
411-
412400
fn base_steps_for_blake_hash(n_u32s: usize) -> usize {
413401
let rem_u32s = n_u32s % CasmV2HashResourceEstimate::U32_WORDS_PER_MESSAGE;
414402
if rem_u32s == 0 {
@@ -437,7 +425,7 @@ fn felts_steps(n_big_felts: usize, n_small_felts: usize) -> usize {
437425
fn estimate_steps_of_encode_felt252_data_and_calc_blake_hash(
438426
felt_size_groups: &FeltSizeCount,
439427
) -> usize {
440-
let total_u32s = total_u32s_from_felts(felt_size_groups.large, felt_size_groups.small);
428+
let total_u32s = felt_size_groups.encoded_u32_len();
441429
if total_u32s == 0 {
442430
// The empty input case is a special case.
443431
return blake_estimation::STEPS_EMPTY_INPUT;
@@ -449,14 +437,6 @@ fn estimate_steps_of_encode_felt252_data_and_calc_blake_hash(
449437
base_steps.checked_add(felt_steps).expect("Overflow computing total Blake hash steps")
450438
}
451439

452-
/// Returns the number of BLAKE opcodes needed to hash the given felts.
453-
/// Each BLAKE opcode processes 16 u32s (partial messages are padded).
454-
fn count_blake_opcode(felt_size_groups: &FeltSizeCount) -> usize {
455-
// Count the total number of u32s to be hashed.
456-
let total_u32s = total_u32s_from_felts(felt_size_groups.large, felt_size_groups.small);
457-
total_u32s.div_ceil(CasmV2HashResourceEstimate::U32_WORDS_PER_MESSAGE)
458-
}
459-
460440
/// Estimates resource usage for `encode_felt252_data_and_calc_blake_hash` in the Starknet OS.
461441
///
462442
/// # Encoding Details
@@ -485,7 +465,7 @@ pub fn encode_and_blake_hash_resources(
485465

486466
EstimatedExecutionResources::V2Hash {
487467
resources,
488-
blake_count: count_blake_opcode(felt_size_groups),
468+
blake_count: felt_size_groups.blake_opcode_count(),
489469
}
490470
}
491471

crates/blockifier/src/execution/execution_utils_test.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use starknet_types_core::felt::Felt;
66
use crate::execution::contract_class::FeltSizeCount;
77
use crate::execution::execution_utils::blake_estimation::STEPS_EMPTY_INPUT;
88
use crate::execution::execution_utils::{
9-
count_blake_opcode,
109
encode_and_blake_hash_resources,
1110
estimate_steps_of_encode_felt252_data_and_calc_blake_hash,
1211
};
@@ -35,7 +34,7 @@ fn test_zero_inputs() {
3534
assert_eq!(steps, STEPS_EMPTY_INPUT, "Unexpected base step cost for zero inputs");
3635

3736
// No opcodes should be emitted.
38-
let opcodes = count_blake_opcode(&FeltSizeCount::default());
37+
let opcodes = FeltSizeCount::default().blake_opcode_count();
3938
assert_eq!(opcodes, 0, "Expected zero BLAKE opcodes for zero inputs");
4039

4140
// Should result in base cost only (no opcode cost).
@@ -47,7 +46,7 @@ fn test_zero_inputs() {
4746

4847
// TODO(AvivG): Add tests for:
4948
// - `estimate_steps_of_encode_felt252_data_and_calc_blake_hash` simple cases (felts input).
50-
// - `count_blake_opcode` simple cases (felts input).
49+
// - `blake_opcode_count` simple cases (felts input).
5150
// - `cost_of_encode_felt252_data_and_calc_blake_hash` simple cases (felts input) (including partial
5251
// remainder).
5352
// - `cost_of_encode_felt252_data_and_calc_blake_hash` compare against actual execution resources

0 commit comments

Comments
 (0)