From 52cfdf6ce588c2bfff8122dc96644ecf7677d7a5 Mon Sep 17 00:00:00 2001 From: Avi Cohen Date: Sun, 17 May 2026 15:57:52 +0300 Subject: [PATCH 1/5] blockifier,apollo_compile_to_native: adopt cairo_native::ContractExecutor + libfunc profiling Co-Authored-By: Claude Opus 4.7 (1M context) --- Cargo.lock | 107 +++++++++++++++++- Cargo.toml | 6 +- crates/apollo_compile_to_native/Cargo.toml | 6 + .../apollo_compile_to_native/src/compiler.rs | 25 ++++ crates/blockifier/Cargo.toml | 12 ++ crates/blockifier/src/execution/native.rs | 3 + .../src/execution/native/contract_class.rs | 33 +++++- .../execution/native/entry_point_execution.rs | 6 +- .../src/execution/native/profiling.rs | 68 +++++++++++ .../src/execution/native/run_dispatch.rs | 45 ++++++++ .../src/state/native_class_manager.rs | 13 ++- 11 files changed, 312 insertions(+), 12 deletions(-) create mode 100644 crates/blockifier/src/execution/native/profiling.rs create mode 100644 crates/blockifier/src/execution/native/run_dispatch.rs diff --git a/Cargo.lock b/Cargo.lock index 81c7ead2892..8d5ec5b85fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4696,6 +4696,35 @@ dependencies = [ "xshell", ] +[[package]] +name = "cairo-lang-test-plugin" +version = "2.17.0-rc.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c4d694701893b14eb6fe944e0d46b0f6f075450885c470a543210aba5481d32" +dependencies = [ + "anyhow", + "cairo-lang-compiler", + "cairo-lang-debug", + "cairo-lang-defs", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-parser", + "cairo-lang-semantic", + "cairo-lang-sierra", + "cairo-lang-sierra-generator", + "cairo-lang-starknet", + "cairo-lang-starknet-classes", + "cairo-lang-syntax", + "cairo-lang-utils", + "indoc 2.0.7", + "itertools 0.14.0", + "num-bigint", + "num-traits", + "salsa", + "serde", + "starknet-types-core", +] + [[package]] name = "cairo-lang-test-utils" version = "2.17.0-rc.4" @@ -4735,8 +4764,7 @@ dependencies = [ [[package]] name = "cairo-native" version = "0.9.0-rc.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe61376fbdfb4c121e4d5ca997fa6eee18b4891d8fe22226f60fe27983467339" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=74aab36c21aa3a87f918d910420efe4c0dbd9d02#74aab36c21aa3a87f918d910420efe4c0dbd9d02" dependencies = [ "aquamarine", "ark-ec", @@ -4754,6 +4782,7 @@ dependencies = [ "cairo-lang-starknet", "cairo-lang-starknet-classes", "cairo-lang-utils", + "cairo-starknet-syscalls", "educe 0.5.11", "itertools 0.14.0", "keccak", @@ -4771,6 +4800,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.9", + "sierra-emu", "starknet-curve 0.6.0", "starknet-types-core", "tempfile", @@ -4804,6 +4834,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "cairo-starknet-syscalls" +version = "0.9.0-rc.6" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=74aab36c21aa3a87f918d910420efe4c0dbd9d02#74aab36c21aa3a87f918d910420efe4c0dbd9d02" +dependencies = [ + "serde", + "starknet-types-core", +] + [[package]] name = "cairo-vm" version = "3.2.0" @@ -6014,6 +6053,7 @@ dependencies = [ "ff", "generic-array", "group", + "pem-rfc7468", "pkcs8", "rand_core 0.6.4", "sec1", @@ -7949,6 +7989,7 @@ dependencies = [ "once_cell", "serdect", "sha2 0.10.9", + "signature", ] [[package]] @@ -9705,6 +9746,18 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2 0.10.9", +] + [[package]] name = "page_size" version = "0.6.0" @@ -10178,6 +10231,15 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -11950,6 +12012,47 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "sierra-emu" +version = "0.9.0-rc.6" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=74aab36c21aa3a87f918d910420efe4c0dbd9d02#74aab36c21aa3a87f918d910420efe4c0dbd9d02" +dependencies = [ + "cairo-lang-compiler", + "cairo-lang-filesystem", + "cairo-lang-lowering", + "cairo-lang-runner", + "cairo-lang-sierra", + "cairo-lang-sierra-ap-change", + "cairo-lang-sierra-gas", + "cairo-lang-sierra-to-casm", + "cairo-lang-sierra-type-size", + "cairo-lang-starknet-classes", + "cairo-lang-test-plugin", + "cairo-lang-utils", + "cairo-starknet-syscalls", + "clap", + "generic-array", + "k256", + "keccak", + "num-bigint", + "num-integer", + "num-traits", + "p256", + "rand 0.9.2", + "rayon", + "sec1", + "serde", + "serde_json", + "sha2 0.10.9", + "smallvec", + "starknet-crypto 0.8.1", + "starknet-curve 0.6.0", + "starknet-types-core", + "thiserror 2.0.17", + "tracing", + "tracing-subscriber", +] + [[package]] name = "signal-hook-registry" version = "1.4.6" diff --git a/Cargo.toml b/Cargo.toml index 401a8e1110c..6e28292ceef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -259,7 +259,11 @@ cairo-lang-sierra = "2.17.0-rc.4" cairo-lang-sierra-to-casm = "2.17.0-rc.4" cairo-lang-starknet-classes = "2.17.0-rc.4" cairo-lang-utils = "2.17.0-rc.4" -cairo-native = "0.9.0-rc.6" +# TEMP: git dep pinned to the tip of the unreleased PR stack +# (starkware-libs/cairo_native#1610 → #1611 → #1612 → #1613) containing +# `ContractExecutor`, `EmuContractInfo`, `AotWithProgram`, and `run_with_profile`. +# Switch back to a crates.io version once those land in a published cairo-native release. +cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "74aab36c21aa3a87f918d910420efe4c0dbd9d02" } cairo-program-runner-lib = "1.1.0" cairo-vm = "3.2.0" camelpaste = "0.1.0" diff --git a/crates/apollo_compile_to_native/Cargo.toml b/crates/apollo_compile_to_native/Cargo.toml index ea3e4a4ec77..613badc1538 100644 --- a/crates/apollo_compile_to_native/Cargo.toml +++ b/crates/apollo_compile_to_native/Cargo.toml @@ -9,6 +9,12 @@ description = "A utility crate for compiling Sierra code into Cairo native." [lints] workspace = true +[features] +# Enables `SierraToNativeCompiler::compile_with_program`, which returns the +# AOT executor paired with the Sierra program required by cairo-native's +# libfunc profiler. +with-libfunc-profiling = ["cairo-native/with-libfunc-profiling"] + [dependencies] apollo_compilation_utils.workspace = true apollo_compile_to_native_types.workspace = true diff --git a/crates/apollo_compile_to_native/src/compiler.rs b/crates/apollo_compile_to_native/src/compiler.rs index d1b4c32b722..0a05a8c5bbb 100644 --- a/crates/apollo_compile_to_native/src/compiler.rs +++ b/crates/apollo_compile_to_native/src/compiler.rs @@ -1,4 +1,6 @@ use std::path::{Path, PathBuf}; +#[cfg(feature = "with-libfunc-profiling")] +use std::sync::Arc; use apollo_compilation_utils::compiler_utils::compile_with_args; use apollo_compilation_utils::errors::CompilationUtilError; @@ -7,6 +9,8 @@ use apollo_compilation_utils::resource_limits::ResourceLimits; use apollo_compile_to_native_types::SierraCompilationConfig; use cairo_lang_starknet_classes::contract_class::ContractClass; use cairo_native::executor::AotContractExecutor; +#[cfg(feature = "with-libfunc-profiling")] +use cairo_native::executor::AotWithProgram; use tempfile::NamedTempFile; use crate::constants::CAIRO_NATIVE_BINARY_NAME; @@ -54,6 +58,27 @@ impl SierraToNativeCompiler { .map_err(|e| CompilationUtilError::CompilationError(e.to_string()))? .unwrap()) } + + /// Like [`Self::compile`], but also returns the Sierra program so cairo-native's + /// libfunc profiler can resolve runtime libfunc IDs back to declarations. The + /// program is extracted from `contract_class` before compilation so the two are + /// guaranteed to correspond. + #[cfg(feature = "with-libfunc-profiling")] + pub fn compile_with_program( + &self, + contract_class: ContractClass, + ) -> Result { + let program = contract_class + .extract_sierra_program(false) + .map(|extracted| Arc::new(extracted.program)) + .map_err(|err| { + CompilationUtilError::UnexpectedError(format!( + "Failed to extract Sierra program for profiling: {err}" + )) + })?; + let executor = self.compile(contract_class)?; + Ok(AotWithProgram { executor, program }) + } } // Returns the OUT_DIR. This function is only operable at run time. diff --git a/crates/blockifier/Cargo.toml b/crates/blockifier/Cargo.toml index 18eb9ade6f7..592fdd65119 100644 --- a/crates/blockifier/Cargo.toml +++ b/crates/blockifier/Cargo.toml @@ -22,9 +22,21 @@ native_blockifier = [] node_api = [] only-native = ["cairo_native"] reexecution = ["transaction_serde"] +# Enables the sierra-emu execution path of `cairo_native::ContractExecutor`. Pulls in +# cairo-native's `sierra-emu` feature which compiles `SierraEmuSyscallBridge`. +sierra-emu = ["cairo-native/sierra-emu", "cairo_native"] testing = ["blockifier_test_utils", "rand", "rstest", "rstest_reuse", "starknet_api/testing"] tracing = [] transaction_serde = [] +# Enables libfunc-level profiling for native execution. Pulls in cairo-native's +# `with-libfunc-profiling` so `ContractExecutor::run_with_profile` is available, +# and apollo_compile_to_native's matching feature so `SierraToNativeCompiler` can +# pair the compiled executor with its Sierra program in one call. +with-libfunc-profiling = [ + "apollo_compile_to_native/with-libfunc-profiling", + "cairo-native/with-libfunc-profiling", + "cairo_native", +] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/blockifier/src/execution/native.rs b/crates/blockifier/src/execution/native.rs index 8b24ff59652..7fdd8ed3624 100644 --- a/crates/blockifier/src/execution/native.rs +++ b/crates/blockifier/src/execution/native.rs @@ -1,5 +1,8 @@ pub mod contract_class; pub mod entry_point_execution; +#[cfg(feature = "with-libfunc-profiling")] +pub mod profiling; +mod run_dispatch; pub mod syscall_handler; pub mod utils; diff --git a/crates/blockifier/src/execution/native/contract_class.rs b/crates/blockifier/src/execution/native/contract_class.rs index d7c6999fac9..c1c5bad93e1 100644 --- a/crates/blockifier/src/execution/native/contract_class.rs +++ b/crates/blockifier/src/execution/native/contract_class.rs @@ -2,7 +2,11 @@ use std::borrow::Cow; use std::ops::Deref; use std::sync::Arc; -use cairo_native::executor::AotContractExecutor; +#[cfg(feature = "with-libfunc-profiling")] +use cairo_native::executor::AotWithProgram; +#[cfg(feature = "sierra-emu")] +use cairo_native::executor::EmuContractInfo; +use cairo_native::executor::{AotContractExecutor, ContractExecutor}; use starknet_api::contract_class::compiled_class_hash::HashableCompiledClass; use starknet_api::core::EntryPointSelector; use starknet_types_core::felt::Felt; @@ -30,7 +34,28 @@ impl NativeCompiledClassV1 { /// executor must be derived from sierra_program which in turn must be derived from /// sierra_contract_class. pub fn new(executor: AotContractExecutor, casm: CompiledClassV1) -> NativeCompiledClassV1 { - let contract = NativeCompiledClassV1Inner::new(executor, casm); + let contract = NativeCompiledClassV1Inner::new(executor.into(), casm); + + Self(Arc::new(contract)) + } + + /// Initialize a compiled class backed by the sierra-emu interpreter instead of the AOT + /// executor. Used by benchmarking / replay tooling that wants to execute through the emu + /// VM while reusing the rest of the blockifier pipeline. + #[cfg(feature = "sierra-emu")] + pub fn new_from_emu(info: EmuContractInfo, casm: CompiledClassV1) -> NativeCompiledClassV1 { + let contract = NativeCompiledClassV1Inner::new(info.into(), casm); + + Self(Arc::new(contract)) + } + + /// Like [`Self::new`], but also stores the Sierra `Program` (via the cairo-native + /// [`AotWithProgram`] pairing) so [`cairo_native::ContractExecutor::run_with_profile`] + /// can resolve libfunc samples. Only callable when the `with-libfunc-profiling` + /// feature is enabled. + #[cfg(feature = "with-libfunc-profiling")] + pub fn new_with_program(info: AotWithProgram, casm: CompiledClassV1) -> NativeCompiledClassV1 { + let contract = NativeCompiledClassV1Inner::new(info.into(), casm); Self(Arc::new(contract)) } @@ -71,12 +96,12 @@ impl HashableCompiledClass for NativeCompiledCla #[derive(Debug)] pub struct NativeCompiledClassV1Inner { - pub executor: AotContractExecutor, + pub executor: ContractExecutor, casm: CompiledClassV1, } impl NativeCompiledClassV1Inner { - fn new(executor: AotContractExecutor, casm: CompiledClassV1) -> Self { + fn new(executor: ContractExecutor, casm: CompiledClassV1) -> Self { NativeCompiledClassV1Inner { executor, casm } } } diff --git a/crates/blockifier/src/execution/native/entry_point_execution.rs b/crates/blockifier/src/execution/native/entry_point_execution.rs index 2dbc2cc48d5..22f0a42f33a 100644 --- a/crates/blockifier/src/execution/native/entry_point_execution.rs +++ b/crates/blockifier/src/execution/native/entry_point_execution.rs @@ -18,6 +18,7 @@ use crate::execution::entry_point::{ }; use crate::execution::errors::{EntryPointExecutionError, PostExecutionError, PreExecutionError}; use crate::execution::native::contract_class::NativeCompiledClassV1; +use crate::execution::native::run_dispatch::run_native_executor; use crate::execution::native::syscall_handler::NativeSyscallHandler; use crate::state::state_api::State; use crate::transaction::objects::ExecutionResourcesTraits; @@ -59,11 +60,12 @@ pub fn execute_entry_point_call( .checked_sub(initial_budget) .ok_or(PreExecutionError::InsufficientEntryPointGas)?; - let execution_result = compiled_class.executor.run( + let execution_result = run_native_executor( + &compiled_class.executor, entry_point.selector.0, &syscall_handler.base.call.calldata.0.clone(), call_initial_gas, - Some(builtin_costs), + builtin_costs, &mut syscall_handler, ); diff --git a/crates/blockifier/src/execution/native/profiling.rs b/crates/blockifier/src/execution/native/profiling.rs new file mode 100644 index 00000000000..04cff2a213a --- /dev/null +++ b/crates/blockifier/src/execution/native/profiling.rs @@ -0,0 +1,68 @@ +//! Blockifier-side storage for libfunc profiles collected by +//! [`cairo_native::ContractExecutor::run_with_profile`]. +//! +//! cairo-native owns the profiling primitive; this module only provides the keying +//! (transaction hash / block number / class hash + selector) that's not visible from +//! cairo-native's layer. +//! +//! Intended for single-tenant benchmarking. The map grows without bound — drain it +//! externally between runs. + +use std::collections::HashMap; +use std::sync::{Arc, LazyLock, Mutex}; + +use cairo_native::executor::Program; +use cairo_native::metadata::profiler::Profile; +use starknet_types_core::felt::Felt; + +use crate::execution::native::syscall_handler::NativeSyscallHandler; + +pub struct EntrypointProfile { + pub class_hash: Felt, + pub selector: Felt, + pub profile: Profile, + pub program: Arc, +} + +pub struct TransactionProfile { + pub block_number: u64, + pub tx_hash: String, + pub entrypoint_profiles: Vec, +} + +type ProfilesByBlockTx = HashMap; + +pub static LIBFUNC_PROFILES_MAP: LazyLock> = + LazyLock::new(|| Mutex::new(HashMap::new())); + +/// Builds an `FnOnce(Profile, Arc)` that, when invoked, records the captured +/// profile in `LIBFUNC_PROFILES_MAP` keyed by the syscall handler's current transaction +/// hash. The program is supplied by cairo-native's +/// [`cairo_native::ContractExecutor::run_with_profile`] callback alongside the profile. +/// +/// All keying data is extracted up front so the closure doesn't re-borrow +/// `syscall_handler` — required because the closure outlives the call to +/// `ContractExecutor::run_with_profile`, which itself holds a `&mut` to the handler. +pub fn record_profile_for( + syscall_handler: &NativeSyscallHandler<'_>, + selector: Felt, +) -> impl FnOnce(Profile, Arc) + 'static { + let class_hash = *syscall_handler.base.call.class_hash; + let tx_hash = + syscall_handler.base.context.tx_context.tx_info.transaction_hash().to_hex_string(); + let block_number = + syscall_handler.base.context.tx_context.block_context.block_info.block_number.0; + + move |profile, program| { + let entry = EntrypointProfile { class_hash, selector, profile, program }; + let mut map = LIBFUNC_PROFILES_MAP.lock().unwrap(); + map.entry(tx_hash.clone()) + .or_insert_with(|| TransactionProfile { + block_number, + tx_hash: tx_hash.clone(), + entrypoint_profiles: Vec::new(), + }) + .entrypoint_profiles + .push(entry); + } +} diff --git a/crates/blockifier/src/execution/native/run_dispatch.rs b/crates/blockifier/src/execution/native/run_dispatch.rs new file mode 100644 index 00000000000..d3ddd4cfc81 --- /dev/null +++ b/crates/blockifier/src/execution/native/run_dispatch.rs @@ -0,0 +1,45 @@ +//! Dispatches a [`ContractExecutor`] entry-point call, transparently routing through +//! [`ContractExecutor::run_with_profile`] when libfunc profiling is enabled. +//! +//! Keeps the libfunc-profiling cfg-noise out of the main entry-point execution path. + +use cairo_native::error::Result; +use cairo_native::execution_result::ContractExecutionResult; +use cairo_native::executor::ContractExecutor; +use cairo_native::utils::BuiltinCosts; +use starknet_types_core::felt::Felt; + +use crate::execution::native::syscall_handler::NativeSyscallHandler; + +/// Runs an entry point on `executor`. Always available. +/// +/// When `with-libfunc-profiling` is enabled the call is routed through +/// [`ContractExecutor::run_with_profile`]; for the `AotWithProgram` variant cairo-native +/// invokes our callback with the captured profile and the program it was built from, which +/// we record into [`crate::execution::native::profiling::LIBFUNC_PROFILES_MAP`] keyed by +/// the current transaction hash. For other variants cairo-native falls through to +/// [`ContractExecutor::run`] and the callback is never invoked. +pub fn run_native_executor( + executor: &ContractExecutor, + selector: Felt, + calldata: &[Felt], + call_initial_gas: u64, + builtin_costs: BuiltinCosts, + syscall_handler: &mut NativeSyscallHandler<'_>, +) -> Result { + #[cfg(feature = "with-libfunc-profiling")] + { + let on_profile = + crate::execution::native::profiling::record_profile_for(syscall_handler, selector); + executor.run_with_profile( + selector, + calldata, + call_initial_gas, + Some(builtin_costs), + syscall_handler, + on_profile, + ) + } + #[cfg(not(feature = "with-libfunc-profiling"))] + executor.run(selector, calldata, call_initial_gas, Some(builtin_costs), syscall_handler) +} diff --git a/crates/blockifier/src/state/native_class_manager.rs b/crates/blockifier/src/state/native_class_manager.rs index 64cbf5ca90c..07defb94847 100644 --- a/crates/blockifier/src/state/native_class_manager.rs +++ b/crates/blockifier/src/state/native_class_manager.rs @@ -283,8 +283,16 @@ fn process_compilation_request( return Ok(()); } let sierra_for_compilation = into_contract_class_for_compilation(sierra.as_ref()); + let start = Instant::now(); - let compilation_result = compiler.compile(sierra_for_compilation); + #[cfg(feature = "with-libfunc-profiling")] + let compilation_result = compiler + .compile_with_program(sierra_for_compilation) + .map(|info| NativeCompiledClassV1::new_with_program(info, casm.clone())); + #[cfg(not(feature = "with-libfunc-profiling"))] + let compilation_result = compiler + .compile(sierra_for_compilation) + .map(|executor| NativeCompiledClassV1::new(executor, casm.clone())); let duration = start.elapsed(); log::info!( "Compiling to native contract with class hash: {:#066x}. Duration: {:.3} seconds", @@ -292,8 +300,7 @@ fn process_compilation_request( duration.as_secs_f32() ); match compilation_result { - Ok(executor) => { - let native_compiled_class = NativeCompiledClassV1::new(executor, casm); + Ok(native_compiled_class) => { class_cache.set( class_hash, CompiledClasses::V1Native(CachedCairoNative::Compiled(native_compiled_class)), From c8cca679a0de98f744cc1347dbc3a9c5dcd505ff Mon Sep 17 00:00:00 2001 From: Avi Cohen Date: Mon, 18 May 2026 18:01:12 +0300 Subject: [PATCH 2/5] workspace: declare cairo-native version on git dep for version sync test Cargo accepts both git+rev and a version field together; the field is a SemVer constraint on the package at the git rev. The rev's Cargo.toml already pins 0.9.0-rc.6, matching native_compiler_version.txt, so the constants test required_cairo_native_version_test parses the version and succeeds. Co-Authored-By: Claude Opus 4.7 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6e28292ceef..c46cbee0ea9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -263,7 +263,7 @@ cairo-lang-utils = "2.17.0-rc.4" # (starkware-libs/cairo_native#1610 → #1611 → #1612 → #1613) containing # `ContractExecutor`, `EmuContractInfo`, `AotWithProgram`, and `run_with_profile`. # Switch back to a crates.io version once those land in a published cairo-native release. -cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "74aab36c21aa3a87f918d910420efe4c0dbd9d02" } +cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "74aab36c21aa3a87f918d910420efe4c0dbd9d02", version = "0.9.0-rc.6" } cairo-program-runner-lib = "1.1.0" cairo-vm = "3.2.0" camelpaste = "0.1.0" From 88b68af923590e49a2ac47aa375a1d569a7f63a2 Mon Sep 17 00:00:00 2001 From: Avi Cohen Date: Tue, 19 May 2026 15:40:06 +0300 Subject: [PATCH 3/5] blockifier: address review feedback on native compilation path - Drop unused `NativeCompiledClassV1::new_from_emu`; it had no in-tree callers, and the sierra-emu construction path will be re-added when the benchmarking/replay tool that needs it lands. - Revert `process_compilation_request`'s `.map(...)` shape to a direct `match`, moving `casm` into `NativeCompiledClassV1::new(_with_program)` in the `Ok` arm at zero cost instead of cloning it. - Bump pinned cairo-native rev to pick up `cargo fmt` fix on starkware-libs/cairo_native#1613. Co-Authored-By: Claude Opus 4.7 (1M context) --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- .../src/execution/native/contract_class.rs | 12 ------------ .../blockifier/src/state/native_class_manager.rs | 14 +++++++------- 4 files changed, 11 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8d5ec5b85fc..b890ce151d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "cairo-native" version = "0.9.0-rc.6" -source = "git+https://github.com/starkware-libs/cairo_native.git?rev=74aab36c21aa3a87f918d910420efe4c0dbd9d02#74aab36c21aa3a87f918d910420efe4c0dbd9d02" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=d19f2ac5e6f01b07f2805cbea42d02b45d9f885f#d19f2ac5e6f01b07f2805cbea42d02b45d9f885f" dependencies = [ "aquamarine", "ark-ec", @@ -4837,7 +4837,7 @@ dependencies = [ [[package]] name = "cairo-starknet-syscalls" version = "0.9.0-rc.6" -source = "git+https://github.com/starkware-libs/cairo_native.git?rev=74aab36c21aa3a87f918d910420efe4c0dbd9d02#74aab36c21aa3a87f918d910420efe4c0dbd9d02" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=d19f2ac5e6f01b07f2805cbea42d02b45d9f885f#d19f2ac5e6f01b07f2805cbea42d02b45d9f885f" dependencies = [ "serde", "starknet-types-core", @@ -12015,7 +12015,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "sierra-emu" version = "0.9.0-rc.6" -source = "git+https://github.com/starkware-libs/cairo_native.git?rev=74aab36c21aa3a87f918d910420efe4c0dbd9d02#74aab36c21aa3a87f918d910420efe4c0dbd9d02" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=d19f2ac5e6f01b07f2805cbea42d02b45d9f885f#d19f2ac5e6f01b07f2805cbea42d02b45d9f885f" dependencies = [ "cairo-lang-compiler", "cairo-lang-filesystem", diff --git a/Cargo.toml b/Cargo.toml index c46cbee0ea9..9406d9378a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -263,7 +263,7 @@ cairo-lang-utils = "2.17.0-rc.4" # (starkware-libs/cairo_native#1610 → #1611 → #1612 → #1613) containing # `ContractExecutor`, `EmuContractInfo`, `AotWithProgram`, and `run_with_profile`. # Switch back to a crates.io version once those land in a published cairo-native release. -cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "74aab36c21aa3a87f918d910420efe4c0dbd9d02", version = "0.9.0-rc.6" } +cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "d19f2ac5e6f01b07f2805cbea42d02b45d9f885f", version = "0.9.0-rc.6" } cairo-program-runner-lib = "1.1.0" cairo-vm = "3.2.0" camelpaste = "0.1.0" diff --git a/crates/blockifier/src/execution/native/contract_class.rs b/crates/blockifier/src/execution/native/contract_class.rs index c1c5bad93e1..7dc2fb6bfda 100644 --- a/crates/blockifier/src/execution/native/contract_class.rs +++ b/crates/blockifier/src/execution/native/contract_class.rs @@ -4,8 +4,6 @@ use std::sync::Arc; #[cfg(feature = "with-libfunc-profiling")] use cairo_native::executor::AotWithProgram; -#[cfg(feature = "sierra-emu")] -use cairo_native::executor::EmuContractInfo; use cairo_native::executor::{AotContractExecutor, ContractExecutor}; use starknet_api::contract_class::compiled_class_hash::HashableCompiledClass; use starknet_api::core::EntryPointSelector; @@ -39,16 +37,6 @@ impl NativeCompiledClassV1 { Self(Arc::new(contract)) } - /// Initialize a compiled class backed by the sierra-emu interpreter instead of the AOT - /// executor. Used by benchmarking / replay tooling that wants to execute through the emu - /// VM while reusing the rest of the blockifier pipeline. - #[cfg(feature = "sierra-emu")] - pub fn new_from_emu(info: EmuContractInfo, casm: CompiledClassV1) -> NativeCompiledClassV1 { - let contract = NativeCompiledClassV1Inner::new(info.into(), casm); - - Self(Arc::new(contract)) - } - /// Like [`Self::new`], but also stores the Sierra `Program` (via the cairo-native /// [`AotWithProgram`] pairing) so [`cairo_native::ContractExecutor::run_with_profile`] /// can resolve libfunc samples. Only callable when the `with-libfunc-profiling` diff --git a/crates/blockifier/src/state/native_class_manager.rs b/crates/blockifier/src/state/native_class_manager.rs index 07defb94847..847ca6b8e31 100644 --- a/crates/blockifier/src/state/native_class_manager.rs +++ b/crates/blockifier/src/state/native_class_manager.rs @@ -286,13 +286,9 @@ fn process_compilation_request( let start = Instant::now(); #[cfg(feature = "with-libfunc-profiling")] - let compilation_result = compiler - .compile_with_program(sierra_for_compilation) - .map(|info| NativeCompiledClassV1::new_with_program(info, casm.clone())); + let compilation_result = compiler.compile_with_program(sierra_for_compilation); #[cfg(not(feature = "with-libfunc-profiling"))] - let compilation_result = compiler - .compile(sierra_for_compilation) - .map(|executor| NativeCompiledClassV1::new(executor, casm.clone())); + let compilation_result = compiler.compile(sierra_for_compilation); let duration = start.elapsed(); log::info!( "Compiling to native contract with class hash: {:#066x}. Duration: {:.3} seconds", @@ -300,7 +296,11 @@ fn process_compilation_request( duration.as_secs_f32() ); match compilation_result { - Ok(native_compiled_class) => { + Ok(compiled) => { + #[cfg(feature = "with-libfunc-profiling")] + let native_compiled_class = NativeCompiledClassV1::new_with_program(compiled, casm); + #[cfg(not(feature = "with-libfunc-profiling"))] + let native_compiled_class = NativeCompiledClassV1::new(compiled, casm); class_cache.set( class_hash, CompiledClasses::V1Native(CachedCairoNative::Compiled(native_compiled_class)), From 74e34ec8f7dd62a03c9938f5fe24f1d647df1ccc Mon Sep 17 00:00:00 2001 From: Avi Cohen Date: Wed, 20 May 2026 12:48:57 +0300 Subject: [PATCH 4/5] workspace: bump cairo-native rev to rebased libfunc-profiling-2 tip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cairo_native PRs #1610–#1612 were rebased onto a newer cairo_native main (now at 2463ca0). Rebase libfunc-profiling-2 (#1613) onto the new contract-executor-2 (#1612) and update the pinned rev accordingly. No content change in the libfunc-profiling-2 commit itself. Co-Authored-By: Claude Opus 4.7 (1M context) --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b890ce151d0..54dbf94ffb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4764,7 +4764,7 @@ dependencies = [ [[package]] name = "cairo-native" version = "0.9.0-rc.6" -source = "git+https://github.com/starkware-libs/cairo_native.git?rev=d19f2ac5e6f01b07f2805cbea42d02b45d9f885f#d19f2ac5e6f01b07f2805cbea42d02b45d9f885f" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=60e4055897f7f6b5149f17bc464780bb00861176#60e4055897f7f6b5149f17bc464780bb00861176" dependencies = [ "aquamarine", "ark-ec", @@ -4837,7 +4837,7 @@ dependencies = [ [[package]] name = "cairo-starknet-syscalls" version = "0.9.0-rc.6" -source = "git+https://github.com/starkware-libs/cairo_native.git?rev=d19f2ac5e6f01b07f2805cbea42d02b45d9f885f#d19f2ac5e6f01b07f2805cbea42d02b45d9f885f" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=60e4055897f7f6b5149f17bc464780bb00861176#60e4055897f7f6b5149f17bc464780bb00861176" dependencies = [ "serde", "starknet-types-core", @@ -12015,7 +12015,7 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "sierra-emu" version = "0.9.0-rc.6" -source = "git+https://github.com/starkware-libs/cairo_native.git?rev=d19f2ac5e6f01b07f2805cbea42d02b45d9f885f#d19f2ac5e6f01b07f2805cbea42d02b45d9f885f" +source = "git+https://github.com/starkware-libs/cairo_native.git?rev=60e4055897f7f6b5149f17bc464780bb00861176#60e4055897f7f6b5149f17bc464780bb00861176" dependencies = [ "cairo-lang-compiler", "cairo-lang-filesystem", diff --git a/Cargo.toml b/Cargo.toml index 9406d9378a6..cea7a49b607 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -263,7 +263,7 @@ cairo-lang-utils = "2.17.0-rc.4" # (starkware-libs/cairo_native#1610 → #1611 → #1612 → #1613) containing # `ContractExecutor`, `EmuContractInfo`, `AotWithProgram`, and `run_with_profile`. # Switch back to a crates.io version once those land in a published cairo-native release. -cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "d19f2ac5e6f01b07f2805cbea42d02b45d9f885f", version = "0.9.0-rc.6" } +cairo-native = { git = "https://github.com/starkware-libs/cairo_native.git", rev = "60e4055897f7f6b5149f17bc464780bb00861176", version = "0.9.0-rc.6" } cairo-program-runner-lib = "1.1.0" cairo-vm = "3.2.0" camelpaste = "0.1.0" From f72014c4fc9a2cd415a4bdc4363025711fae414d Mon Sep 17 00:00:00 2001 From: Avi Cohen Date: Wed, 20 May 2026 13:07:03 +0300 Subject: [PATCH 5/5] blockifier: re-add new_from_emu for out-of-tree benchmarking branch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `new_from_emu` was deleted in 88b68af9 after Cursor flagged it as unused. Restore it (with a doc comment naming the planned consumer) so the benchmarking / replay tooling — which will live as a feature branch and is not expected to merge here — can reach it without patching this file. No `#[expect(dead_code)]` needed: `dead_code` doesn't fire on `pub fn` in a library crate. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/execution/native/contract_class.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/crates/blockifier/src/execution/native/contract_class.rs b/crates/blockifier/src/execution/native/contract_class.rs index 7dc2fb6bfda..a61e865f7cd 100644 --- a/crates/blockifier/src/execution/native/contract_class.rs +++ b/crates/blockifier/src/execution/native/contract_class.rs @@ -4,6 +4,8 @@ use std::sync::Arc; #[cfg(feature = "with-libfunc-profiling")] use cairo_native::executor::AotWithProgram; +#[cfg(feature = "sierra-emu")] +use cairo_native::executor::EmuContractInfo; use cairo_native::executor::{AotContractExecutor, ContractExecutor}; use starknet_api::contract_class::compiled_class_hash::HashableCompiledClass; use starknet_api::core::EntryPointSelector; @@ -37,6 +39,17 @@ impl NativeCompiledClassV1 { Self(Arc::new(contract)) } + /// Initialize a compiled class backed by the sierra-emu interpreter instead of the AOT + /// executor. Intended for the out-of-tree benchmarking / replay feature branch — those + /// tools are not expected to merge into this repo and will consume this constructor + /// from a fork. `pub` so a fork can reach it without patching this file. + #[cfg(feature = "sierra-emu")] + pub fn new_from_emu(info: EmuContractInfo, casm: CompiledClassV1) -> NativeCompiledClassV1 { + let contract = NativeCompiledClassV1Inner::new(info.into(), casm); + + Self(Arc::new(contract)) + } + /// Like [`Self::new`], but also stores the Sierra `Program` (via the cairo-native /// [`AotWithProgram`] pairing) so [`cairo_native::ContractExecutor::run_with_profile`] /// can resolve libfunc samples. Only callable when the `with-libfunc-profiling`