Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(cairo_native): test papyrus state reader get compiled class #2949

Merged
merged 1 commit into from
Jan 12, 2025
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions crates/blockifier/src/blockifier/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ impl Default for ContractClassManagerConfig {
}
}

impl ContractClassManagerConfig {
#[cfg(any(test, feature = "testing", feature = "native_blockifier"))]
pub fn create_for_testing(run_cairo_native: bool, wait_on_native_compilation: bool) -> Self {
let cairo_native_run_config = CairoNativeRunConfig {
run_cairo_native,
wait_on_native_compilation,
..Default::default()
};
Self { cairo_native_run_config, ..Default::default() }
}
}

impl SerializeConfig for ContractClassManagerConfig {
fn dump(&self) -> BTreeMap<ParamPath, SerializedParam> {
let mut dump = BTreeMap::from_iter([ser_param(
Expand Down
6 changes: 5 additions & 1 deletion crates/blockifier/src/state/contract_class_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ use crate::execution::native::contract_class::NativeCompiledClassV1;
#[cfg(feature = "cairo_native")]
use crate::state::global_cache::CachedCairoNative;
use crate::state::global_cache::{CachedCasm, ContractCaches};

pub const DEFAULT_COMPILATION_REQUEST_CHANNEL_SIZE: usize = 1000;

/// Represents a request to compile a sierra contract class to a native compiled class.
Expand Down Expand Up @@ -158,6 +157,11 @@ impl ContractClassManager {
self.contract_caches.set_casm(class_hash, compiled_class);
}

#[cfg(all(feature = "cairo_native", feature = "testing"))]
pub fn set_native(&self, class_hash: ClassHash, compiled_class: NativeCompiledClassV1) {
self.contract_caches.set_native(class_hash, CachedCairoNative::Compiled(compiled_class));
}

#[cfg(feature = "cairo_native")]
pub fn run_cairo_native(&self) -> bool {
self.cairo_native_run_config.run_cairo_native
Expand Down
1 change: 1 addition & 0 deletions crates/papyrus_state_reader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ assert_matches.workspace = true
blockifier = { workspace = true, features = ["testing"] }
indexmap.workspace = true
papyrus_storage = { workspace = true, features = ["testing"] }
rstest.workspace = true
143 changes: 141 additions & 2 deletions crates/papyrus_state_reader/src/papyrus_state_test.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
use core::panic;

use assert_matches::assert_matches;
use blockifier::blockifier::config::ContractClassManagerConfig;
use blockifier::execution::call_info::CallExecution;
use blockifier::execution::contract_class::RunnableCompiledClass;
use blockifier::execution::entry_point::CallEntryPoint;
use blockifier::retdata;
use blockifier::state::cached_state::CachedState;
use blockifier::state::contract_class_manager::ContractClassManager;
use blockifier::state::state_api::StateReader;
use blockifier::test_utils::contracts::FeatureContract;
use blockifier::test_utils::{trivial_external_entry_point_new, CairoVersion};
use blockifier::test_utils::{trivial_external_entry_point_new, CairoVersion, RunnableCairo1};
use indexmap::IndexMap;
use papyrus_storage::class::ClassStorageWriter;
use papyrus_storage::compiled_class::CasmStorageWriter;
use papyrus_storage::state::StateStorageWriter;
use rstest::rstest;
use starknet_api::abi::abi_utils::selector_from_name;
use starknet_api::block::BlockNumber;
use starknet_api::contract_class::ContractClass;
use starknet_api::state::{StateDiff, StorageKey};
use starknet_api::state::{StateDiff, StorageKey, ThinStateDiff};
use starknet_api::{calldata, felt};

use crate::papyrus_state::PapyrusReader;
Expand Down Expand Up @@ -76,3 +81,137 @@ fn test_entry_point_with_papyrus_state() -> papyrus_storage::StorageResult<()> {

Ok(())
}

fn build_papyrus_state_reader_and_declare_contract(
contract: FeatureContract,
contract_manager_config: ContractClassManagerConfig,
) -> PapyrusReader {
let class_hash = contract.get_class_hash();
let ((storage_reader, mut storage_writer), _) = papyrus_storage::test_utils::get_test_storage();
let test_compiled_class_hash = contract.get_compiled_class_hash();
let block_number = BlockNumber::default();

// Hack to declare the contract in the storage.
match contract.get_class() {
ContractClass::V1((casm_class, _)) => {
let thin_state_diff = ThinStateDiff {
declared_classes: IndexMap::from([(class_hash, test_compiled_class_hash)]),
..Default::default()
};
storage_writer
.begin_rw_txn()
.unwrap()
.append_state_diff(block_number, thin_state_diff)
.unwrap()
.append_classes(block_number, &[(class_hash, &contract.get_sierra())], &[])
.unwrap()
.append_casm(&class_hash, &casm_class)
.unwrap()
.commit()
.unwrap();
}

ContractClass::V0(deprecated_contract_class) => {
let thin_state_diff = ThinStateDiff {
deprecated_declared_classes: vec![class_hash],
..Default::default()
};
storage_writer
.begin_rw_txn()
.unwrap()
.append_state_diff(block_number, thin_state_diff)
.unwrap()
.append_classes(block_number, &[], &[(class_hash, &deprecated_contract_class)])
.unwrap()
.commit()
.unwrap();
}
}

PapyrusReader::new(
storage_reader,
BlockNumber(1),
ContractClassManager::start(contract_manager_config),
)
}

#[rstest]
#[case::dont_run_cairo_native(false, false)]
#[cfg_attr(feature = "cairo_native", case::run_cairo_native_without_waiting(true, false))]
#[cfg_attr(feature = "cairo_native", case::run_cairo_native_and_wait(true, true))]
fn test_get_compiled_class_without_native_in_cache(
#[values(CairoVersion::Cairo0, CairoVersion::Cairo1(RunnableCairo1::Casm))]
cairo_version: CairoVersion,
#[case] run_cairo_native: bool,
#[case] wait_on_native_compilation: bool,
) {
// Sanity checks.
if !run_cairo_native {
assert!(!wait_on_native_compilation);
}
#[cfg(not(feature = "cairo_native"))]
assert!(!run_cairo_native);

// We store the sierra with the casm only when the casm is cairo1 and the native flag is enabled
let cached_with_sierra = run_cairo_native && matches!(cairo_version, CairoVersion::Cairo1(_));
let test_contract = FeatureContract::TestContract(cairo_version);
let test_class_hash = test_contract.get_class_hash();
let contract_manager_config = ContractClassManagerConfig::create_for_testing(
run_cairo_native,
wait_on_native_compilation,
);

let papyrus_reader =
build_papyrus_state_reader_and_declare_contract(test_contract, contract_manager_config);
#[cfg(feature = "cairo_native")]
assert!(papyrus_reader.contract_class_manager.get_native(&test_class_hash).is_none());

let compiled_class = papyrus_reader.get_compiled_class(test_class_hash).unwrap();

if cached_with_sierra {
// TODO: Test that a compilation request was sent.
if wait_on_native_compilation {
#[cfg(feature = "cairo_native")]
assert_matches!(
compiled_class,
RunnableCompiledClass::V1Native(_),
"We should have waited to the native class."
);
} else {
assert_matches!(
compiled_class,
RunnableCompiledClass::V1(_),
"We do not wait for native, return the cairo1 casm."
);
}
} else {
assert_eq!(
compiled_class,
test_contract.get_runnable_class(),
"`get_compiled_class` should return the casm"
);
}
}

#[cfg(feature = "cairo_native")]
#[test]
fn test_get_compiled_class_when_native_is_cached() {
let ((storage_reader, _), _) = papyrus_storage::test_utils::get_test_storage();
let test_contract = FeatureContract::TestContract(CairoVersion::Cairo1(RunnableCairo1::Native));
let test_class_hash = test_contract.get_class_hash();
let contract_manager_config = ContractClassManagerConfig::create_for_testing(true, true);
let papyrus_reader = PapyrusReader::new(
storage_reader,
BlockNumber::default(),
ContractClassManager::start(contract_manager_config),
);
if let RunnableCompiledClass::V1Native(native_compiled_class) =
test_contract.get_runnable_class()
{
papyrus_reader.contract_class_manager.set_native(test_class_hash, native_compiled_class);
} else {
panic!("Expected NativeCompiledClassV1");
}
let compiled_class = papyrus_reader.get_compiled_class(test_class_hash).unwrap();
assert_matches!(compiled_class, RunnableCompiledClass::V1Native(_));
}
Loading