Skip to content
Open
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
10 changes: 9 additions & 1 deletion crates/blockifier/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,14 @@ native_blockifier = []
node_api = []
only-native = ["cairo_native"]
reexecution = ["transaction_serde"]
testing = ["blockifier_test_utils", "rand", "rstest", "rstest_reuse", "starknet_api/testing"]
testing = [
"blockifier_test_utils",
"expect-test",
"rand",
"rstest",
"rstest_reuse",
"starknet_api/testing",
]
tracing = []
transaction_serde = []

Expand Down Expand Up @@ -56,6 +63,7 @@ derive_more = { workspace = true, features = [
"from",
"into_iterator",
] }
expect-test = { workspace = true, optional = true }
indexmap.workspace = true
itertools.workspace = true
keccak.workspace = true
Expand Down
16 changes: 16 additions & 0 deletions crates/blockifier/src/execution/casm_hash_estimation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,22 @@ impl EstimateCasmHashResources for CasmV1HashResourceEstimate {
}
}

/// Expected values for the CASM V2 (Blake) hash estimation.
/// Separate module, gated by `testing` feature, to avoid depending on the expect-test crate in
/// production code. Values used in production are defined as constants in the
/// [CasmV2HashResourceEstimate] struct (same names, without the _EXPECT suffix).
#[cfg(any(test, feature = "testing"))]
pub mod expected {
use expect_test::{expect, Expect};

pub static STEPS_EMPTY_INPUT_EXPECT: Expect = expect!["169"];
pub static STEPS_PER_LARGE_FELT_EXPECT: Expect = expect!["45"];
pub static STEPS_PER_SMALL_FELT_EXPECT: Expect = expect!["15"];
pub static BASE_STEPS_FULL_MSG_EXPECT: Expect = expect!["216"];
pub static BASE_STEPS_PARTIAL_MSG_EXPECT: Expect = expect!["194"];
pub static STEPS_PER_2_U32_REMINDER_EXPECT: Expect = expect!["3"];
}

pub struct CasmV2HashResourceEstimate {}

impl CasmV2HashResourceEstimate {
Expand Down
34 changes: 34 additions & 0 deletions crates/blockifier/src/execution/casm_hash_estimation_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ use pretty_assertions::assert_eq;
use starknet_types_core::hash::Blake2Felt252;

use crate::execution::call_info::OpcodeName;
use crate::execution::casm_hash_estimation::expected::{
BASE_STEPS_FULL_MSG_EXPECT,
BASE_STEPS_PARTIAL_MSG_EXPECT,
STEPS_EMPTY_INPUT_EXPECT,
STEPS_PER_2_U32_REMINDER_EXPECT,
STEPS_PER_LARGE_FELT_EXPECT,
STEPS_PER_SMALL_FELT_EXPECT,
};
use crate::execution::casm_hash_estimation::{
CasmV2HashResourceEstimate,
EstimateCasmHashResources,
Expand All @@ -22,6 +30,32 @@ fn test_u32_constants() {
assert_eq!(large_u32s.len(), CasmV2HashResourceEstimate::U32_WORDS_PER_LARGE_FELT);
}

/// Assert consistency between the blake constants used in production and the expected values
/// reproduced and auto-fixed by tests.
#[test]
fn test_expected_constants() {
macro_rules! assert_eq_expect {
($expect:expr, $actual:ident) => {
assert_eq!(
$expect.data().parse::<usize>().unwrap(),
CasmV2HashResourceEstimate::$actual,
"Expect constant {} is not equal to constant CasmV2HashResourceEstimate::{} ({} \
!= {}). Fix the latter (manually) to match the former.",
stringify!($expect),
stringify!($actual),
$expect.data().parse::<usize>().unwrap(),
CasmV2HashResourceEstimate::$actual,
);
};
}
assert_eq_expect!(STEPS_EMPTY_INPUT_EXPECT, STEPS_EMPTY_INPUT);
assert_eq_expect!(STEPS_PER_LARGE_FELT_EXPECT, STEPS_PER_LARGE_FELT);
assert_eq_expect!(STEPS_PER_SMALL_FELT_EXPECT, STEPS_PER_SMALL_FELT);
assert_eq_expect!(BASE_STEPS_FULL_MSG_EXPECT, BASE_STEPS_FULL_MSG);
assert_eq_expect!(BASE_STEPS_PARTIAL_MSG_EXPECT, BASE_STEPS_PARTIAL_MSG);
assert_eq_expect!(STEPS_PER_2_U32_REMINDER_EXPECT, STEPS_PER_2_U32_REMINDER);
}

/// Test the edge case of hashing an empty array of felt values.
#[test]
fn test_zero_inputs() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
use std::collections::HashMap;

use blockifier::execution::casm_hash_estimation::expected::{
BASE_STEPS_FULL_MSG_EXPECT,
BASE_STEPS_PARTIAL_MSG_EXPECT,
STEPS_EMPTY_INPUT_EXPECT,
STEPS_PER_2_U32_REMINDER_EXPECT,
STEPS_PER_LARGE_FELT_EXPECT,
STEPS_PER_SMALL_FELT_EXPECT,
};
use blockifier::execution::casm_hash_estimation::{
CasmV2HashResourceEstimate,
EstimateCasmHashResources,
Expand Down Expand Up @@ -95,7 +103,7 @@ fn test_blake_step_constants() {

// Test empty input.
let steps_empty = cairo_encode_felt252_data_and_calc_blake_hash_steps(&[]);
assert_eq!(steps_empty, CasmV2HashResourceEstimate::STEPS_EMPTY_INPUT);
STEPS_EMPTY_INPUT_EXPECT.assert_eq(&steps_empty.to_string());

// Start with a baseline of one full word.
let one_message_large_felts = vec![large_felt; LARGE_FELTS_PER_MESSAGE];
Expand All @@ -111,7 +119,7 @@ fn test_blake_step_constants() {
.collect::<Vec<Felt>>(),
) - baseline_steps)
/ LARGE_FELTS_PER_MESSAGE;
assert_eq!(large_felt_overhead, CasmV2HashResourceEstimate::STEPS_PER_LARGE_FELT);
STEPS_PER_LARGE_FELT_EXPECT.assert_eq(&large_felt_overhead.to_string());

// Add another full word of small felts to compute the overhead per small felt.
let one_message_small_felts = vec![small_felt; SMALL_FELTS_PER_MESSAGE];
Expand All @@ -123,12 +131,12 @@ fn test_blake_step_constants() {
.collect::<Vec<Felt>>(),
) - baseline_steps)
/ SMALL_FELTS_PER_MESSAGE;
assert_eq!(small_felt_overhead, CasmV2HashResourceEstimate::STEPS_PER_SMALL_FELT);
STEPS_PER_SMALL_FELT_EXPECT.assert_eq(&small_felt_overhead.to_string());

// Compute the full-word overhead by subtracting the overhead of one word of large felts, from
// the result of exactly one word of large felts.
let full_word_overhead = baseline_steps - (large_felt_overhead * LARGE_FELTS_PER_MESSAGE);
assert_eq!(full_word_overhead, CasmV2HashResourceEstimate::BASE_STEPS_FULL_MSG);
BASE_STEPS_FULL_MSG_EXPECT.assert_eq(&full_word_overhead.to_string());

// Compute the two-word partial overhead by computing:
// X, one full message of large felts + one half-message of small felts.
Expand All @@ -153,7 +161,7 @@ fn test_blake_step_constants() {
let remainder = one_plus_half_message_plus_small_felt_steps
- one_plus_half_message_steps
- small_felt_overhead;
assert_eq!(remainder, CasmV2HashResourceEstimate::STEPS_PER_2_U32_REMINDER);
STEPS_PER_2_U32_REMINDER_EXPECT.assert_eq(&remainder.to_string());

// Reuse the above computation to deduce the constant overhead for the case where the input does
// not fit into an exact multiple of messages.
Expand All @@ -162,7 +170,7 @@ fn test_blake_step_constants() {
- (SMALL_FELTS_PER_MESSAGE / 2) * (small_felt_overhead + remainder)
// Overhead of first (full) message: two large felts.
- LARGE_FELTS_PER_MESSAGE * large_felt_overhead;
assert_eq!(partial_message_overhead, CasmV2HashResourceEstimate::BASE_STEPS_PARTIAL_MSG);
BASE_STEPS_PARTIAL_MSG_EXPECT.assert_eq(&partial_message_overhead.to_string());
Comment thread
cursor[bot] marked this conversation as resolved.
}

/// Test that compares Cairo and Rust implementations of
Expand Down
Loading