Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
29 changes: 12 additions & 17 deletions crates/blockifier/src/execution/contract_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub trait HasSelector {
fn selector(&self) -> &EntryPointSelector;
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct FeltSizeCount {
// Number of felts below 2^63.
pub small: usize,
Expand Down Expand Up @@ -354,9 +354,7 @@ impl CompiledClassV1 {
/// This is an empiric measurement of several bytecode lengths, which constitutes as the
/// dominant factor in it.
fn estimate_casm_hash_computation_resources(&self) -> ExecutionResources {
// TODO(AvivG): Pass `NestedMultipleInt` directly to avoid redundant `NestedIntList`
// conversion.
estimate_casm_poseidon_hash_computation_resources(&self.bytecode_segment_lengths())
estimate_casm_poseidon_hash_computation_resources(&self.bytecode_segment_felt_sizes)
}

/// Estimate the VM gas required to perform a CompiledClassHash migration.
Expand All @@ -382,8 +380,7 @@ impl CompiledClassV1 {
);

let poseidon_hash_resources =
// TODO(AvivG): Pass `NestedMultipleInt` directly to avoid redundant `NestedIntList` conversion.
estimate_casm_poseidon_hash_computation_resources(&self.bytecode_segment_lengths());
estimate_casm_poseidon_hash_computation_resources(&self.bytecode_segment_felt_sizes);
let poseidon_hash_gas =
vm_resources_to_sierra_gas(&poseidon_hash_resources, versioned_constants);

Expand All @@ -400,9 +397,7 @@ impl CompiledClassV1 {
visited_pcs: &HashSet<usize>,
) -> Result<Vec<usize>, TransactionExecutionError> {
let mut reversed_visited_pcs: Vec<_> = visited_pcs.iter().cloned().sorted().rev().collect();
// TODO(AvivG): Pass `NestedMultipleInt` directly to avoid redundant `NestedIntList`
// conversion.
get_visited_segments(&self.bytecode_segment_lengths(), &mut reversed_visited_pcs, &mut 0)
get_visited_segments(&self.bytecode_segment_felt_sizes, &mut reversed_visited_pcs, &mut 0)
}

pub fn try_from_json_string(
Expand Down Expand Up @@ -455,20 +450,20 @@ impl HashableCompiledClass<EntryPointV1> for CompiledClassV1 {
/// class entry points.
/// Also, this function is not backward compatible.
pub fn estimate_casm_poseidon_hash_computation_resources(
bytecode_segment_lengths: &NestedIntList,
bytecode_segment_lengths: &NestedFeltCounts,
) -> ExecutionResources {
// The constants in this function were computed by running the Casm code on a few values
// of `bytecode_segment_lengths`.
match bytecode_segment_lengths {
NestedIntList::Leaf(length) => {
NestedFeltCounts::Leaf(length, _) => {
// The entire contract is a single segment (old Sierra contracts).
&ExecutionResources {
n_steps: 464,
n_memory_holes: 0,
builtin_instance_counter: HashMap::from([(BuiltinName::poseidon, 10)]),
} + &poseidon_hash_many_cost(*length)
}
NestedIntList::Node(segments) => {
NestedFeltCounts::Node(segments) => {
// The contract code is segmented by its functions.
let mut execution_resources = ExecutionResources {
n_steps: 482,
Expand All @@ -481,7 +476,7 @@ pub fn estimate_casm_poseidon_hash_computation_resources(
builtin_instance_counter: HashMap::from([(BuiltinName::poseidon, 1)]),
};
for segment in segments {
let NestedIntList::Leaf(length) = segment else {
let NestedFeltCounts::Leaf(length, _) = segment else {
panic!(
"Estimating hash cost is only supported for segmentation depth at most 1."
);
Expand Down Expand Up @@ -585,14 +580,14 @@ pub fn estimate_casm_blake_hash_computation_resources(
// Each visited segment must have its starting PC visited, and is represented by it.
// visited_pcs should be given in reversed order, and is consumed by the function.
fn get_visited_segments(
segment_lengths: &NestedIntList,
segment_lengths: &NestedFeltCounts,
visited_pcs: &mut Vec<usize>,
bytecode_offset: &mut usize,
) -> Result<Vec<usize>, TransactionExecutionError> {
let mut res = Vec::new();

match segment_lengths {
NestedIntList::Leaf(length) => {
NestedFeltCounts::Leaf(length, _) => {
let segment = *bytecode_offset..*bytecode_offset + length;
if visited_pcs.last().is_some_and(|pc| segment.contains(pc)) {
res.push(segment.start);
Expand All @@ -603,7 +598,7 @@ fn get_visited_segments(
}
*bytecode_offset += length;
}
NestedIntList::Node(segments) => {
NestedFeltCounts::Node(segments) => {
for segment in segments {
let segment_start = *bytecode_offset;
let next_visited_pc = visited_pcs.last().copied();
Expand Down Expand Up @@ -821,7 +816,7 @@ impl<EP: HasSelector> Index<EntryPointType> for EntryPointsByType<EP> {
impl NestedFeltCounts {
/// Builds a nested structure matching `layout`, consuming values from `bytecode`.
#[allow(unused)]
pub(crate) fn new(bytecode_segment_lengths: &NestedIntList, bytecode: &[BigUintAsHex]) -> Self {
pub fn new(bytecode_segment_lengths: &NestedIntList, bytecode: &[BigUintAsHex]) -> Self {
let (base_node, consumed_felts) = Self::new_inner(bytecode_segment_lengths, bytecode, 0);
assert_eq!(consumed_felts, bytecode.len());
base_node
Expand Down
2 changes: 1 addition & 1 deletion crates/blockifier/src/execution/contract_class_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ fn test_compiled_class_hash(
#[case::empty(
NestedIntList::Leaf(0),
vec![],
NestedFeltCounts::Leaf(0, FeltSizeCount { small: 0, large: 0 })
NestedFeltCounts::Leaf(0, FeltSizeCount::default())
)]
#[case::leaf(
NestedIntList::Leaf(3),
Expand Down
16 changes: 11 additions & 5 deletions crates/native_blockifier/src/py_testing_wrappers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use blockifier::execution::contract_class::estimate_casm_poseidon_hash_computation_resources;
use blockifier::execution::contract_class::{
estimate_casm_poseidon_hash_computation_resources,
FeltSizeCount,
NestedFeltCounts,
};
use blockifier::transaction::errors::{TransactionExecutionError, TransactionFeeError};
use cairo_lang_starknet_classes::NestedIntList;
use pyo3::{pyfunction, PyResult};

use crate::errors::NativeBlockifierResult;
Expand All @@ -20,7 +23,7 @@ pub fn raise_error_for_testing() -> NativeBlockifierResult<()> {
pub fn estimate_casm_hash_computation_resources_for_testing_single(
bytecode_segment_lengths: usize,
) -> PyResult<PyExecutionResources> {
let node = NestedIntList::Leaf(bytecode_segment_lengths);
let node = NestedFeltCounts::Leaf(bytecode_segment_lengths, FeltSizeCount::default());
Ok(estimate_casm_poseidon_hash_computation_resources(&node).into())
}

Expand All @@ -30,8 +33,11 @@ pub fn estimate_casm_hash_computation_resources_for_testing_single(
pub fn estimate_casm_hash_computation_resources_for_testing_list(
bytecode_segment_lengths: Vec<usize>,
) -> PyResult<PyExecutionResources> {
let node = NestedIntList::Node(
bytecode_segment_lengths.into_iter().map(NestedIntList::Leaf).collect(),
let node = NestedFeltCounts::Node(
bytecode_segment_lengths
.into_iter()
.map(|length| NestedFeltCounts::Leaf(length, FeltSizeCount::default()))
.collect(),
);
Ok(estimate_casm_poseidon_hash_computation_resources(&node).into())
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::collections::HashMap;

use apollo_starknet_os_program::test_programs::BLAKE_COMPILED_CLASS_HASH_BYTES;
use blockifier::execution::contract_class::estimate_casm_poseidon_hash_computation_resources;
use blockifier::execution::contract_class::{
estimate_casm_poseidon_hash_computation_resources,
NestedFeltCounts,
};
use blockifier::test_utils::contracts::FeatureContractTrait;
use blockifier_test_utils::cairo_versions::{CairoVersion, RunnableCairo1};
use blockifier_test_utils::contracts::FeatureContract;
Expand Down Expand Up @@ -308,9 +311,11 @@ fn test_compiled_class_hash_resources_estimation() {
run_compiled_class_hash_entry_point(&contract_class, true, &hash_version);

// Compare the actual execution resources with the estimation with some allowed margin.
let mut execution_resources_estimation = estimate_casm_poseidon_hash_computation_resources(
&contract_class.get_bytecode_segment_lengths(),
);
let mut execution_resources_estimation =
estimate_casm_poseidon_hash_computation_resources(&NestedFeltCounts::new(
&contract_class.get_bytecode_segment_lengths(),
&contract_class.bytecode,
));
let margin_n_steps =
execution_resources_estimation.n_steps.abs_diff(actual_execution_resources.n_steps);
assert!(
Expand Down
Loading