diff --git a/crates/starknet_os/resources/circuit_registry_canonical_small.json b/crates/starknet_os/resources/circuit_registry_canonical_small.json new file mode 100644 index 00000000000..ab2d5df7ef2 --- /dev/null +++ b/crates/starknet_os/resources/circuit_registry_canonical_small.json @@ -0,0 +1,71 @@ +{ + "cairo_prover_params": { + "channel_hash": "blake2s", + "channel_salt": 0, + "fri_config": { + "pow_bits": 16, + "log_blowup_factor": 1, + "log_last_layer_degree_bound": 0, + "n_queries": 70, + "fold_step": 1 + }, + "preprocessed_trace": "canonical_small", + "store_polynomials_coefficients": false, + "include_all_preprocessed_columns": true, + "opt_n_id_to_big_components": 16, + "lifting_size_policy": "at_least_preprocessed" + }, + "circuit_proof_configs": { + "default": { + "fri_config": { + "pow_bits": 26, + "log_blowup_factor": 1, + "log_last_layer_degree_bound": 0, + "n_queries": 70, + "fold_step": 4 + }, + "component_log_sizes": { + "eq": 20, + "qm31_ops": 23, + "m31_to_u32": 21, + "triple_xor": 20, + "blake_g_gate": 23 + } + } + }, + "leaf_verifiers": [ + { + "config": "default", + "trace_log_size": 20, + "circuit_hash": [ + "0xd2d85a42", + "0x79697b22", + "0x3a41a061", + "0x011cb393", + "0x7a040ec9", + "0x4508f4ca", + "0x42239409", + "0x60f3baea" + ] + } + ], + "multiverifiers": [ + { + "config": "default", + "input_configs": [ + "default", + "default" + ], + "circuit_hash": [ + "0xa5989715", + "0x2377c07a", + "0xc6d1e844", + "0x54f0a04d", + "0x8be65a7d", + "0xfd73c261", + "0x9078e728", + "0x973f680f" + ] + } + ] +} diff --git a/crates/starknet_os/src/proof_fact_fold_test.rs b/crates/starknet_os/src/proof_fact_fold_test.rs index 4850a11f616..ba3ba37029c 100644 --- a/crates/starknet_os/src/proof_fact_fold_test.rs +++ b/crates/starknet_os/src/proof_fact_fold_test.rs @@ -4,6 +4,8 @@ use apollo_starknet_os_program::test_programs::PROOF_FACT_FOLD_BYTES; use cairo_vm::types::builtin_name::BuiltinName; use cairo_vm::types::layout_name::LayoutName; use cairo_vm::types::relocatable::MaybeRelocatable; +use cairo_vm::vm::runners::cairo_runner::ExecutionResources; +use expect_test::expect; use rstest::rstest; use starknet_types_core::felt::Felt; @@ -89,6 +91,27 @@ fn run_cairo_processed_proof_output_digest(proof_facts: &[Felt]) -> Vec { ) } +fn run_cairo_processed_proof_output_digest_resources(proof_facts: &[Felt]) -> ExecutionResources { + let expected_return_values = vec![EndpointArg::Pointer(PointerArg::Array(vec![ + MaybeRelocatable::from(Felt::ZERO); + BLAKE2S_DIGEST_N_WORDS + ]))]; + let (_, _, cairo_runner) = initialize_and_run_cairo_0_entry_point( + &entrypoint_runner_config(), + PROOF_FACT_FOLD_BYTES, + "compute_processed_proof_output_digest", + &[EndpointArg::from(Felt::from(proof_facts.len())), felt_array_arg(proof_facts)], + &[ImplicitArg::Builtin(BuiltinName::range_check)], + &expected_return_values, + HashMap::new(), + None, + ) + .unwrap_or_else(|error| { + panic!("Failed to run compute_processed_proof_output_digest: {error:?}") + }); + cairo_runner.get_execution_resources().unwrap().filter_unused_builtins() +} + fn synthetic_proof_facts(transaction_index: u64) -> Vec { vec![ Felt::from_hex("0x50524f4f4631").unwrap(), @@ -241,3 +264,58 @@ fn test_cairo_pack_output_digest_matches_rust() { }; assert_eq!((*cairo_low, *cairo_high), (expected_low, expected_high)); } + +fn registry_circuit_hashes( + registry: &serde_json::Value, + verifier_list_key: &str, +) -> Vec { + registry[verifier_list_key] + .as_array() + .unwrap_or_else(|| panic!("The registry must list {verifier_list_key}.")) + .iter() + .map(|verifier_entry| { + let circuit_hash_words: Vec = verifier_entry["circuit_hash"] + .as_array() + .expect("A circuit hash must be an array of words.") + .iter() + .map(|circuit_hash_word| { + let word_hex = + circuit_hash_word.as_str().expect("A circuit hash word must be a string."); + u32::from_str_radix(word_hex.trim_start_matches("0x"), 16) + .expect("A circuit hash word must be a hex u32.") + }) + .collect(); + circuit_hash_words.try_into().expect("A circuit hash must have exactly 8 words.") + }) + .collect() +} + +#[test] +fn test_circuit_hash_constants_match_vendored_registry() { + let registry: serde_json::Value = + serde_json::from_str(include_str!("../resources/circuit_registry_canonical_small.json")) + .expect("The vendored circuit registry must be valid JSON."); + assert_eq!( + registry_circuit_hashes(®istry, "leaf_verifiers"), + vec![LEAF_VERIFIER_CIRCUIT_HASH] + ); + assert_eq!( + registry_circuit_hashes(®istry, "multiverifiers"), + vec![MULTIVERIFIER_CIRCUIT_HASH] + ); +} + +#[test] +fn test_processed_proof_output_digest_execution_resources() { + let execution_resources = + run_cairo_processed_proof_output_digest_resources(&synthetic_proof_facts(0)); + expect!["852 steps, 13 range checks"].assert_eq(&format!( + "{} steps, {} range checks", + execution_resources.n_steps, + execution_resources + .builtin_instance_counter + .get(&BuiltinName::range_check) + .copied() + .unwrap_or(0) + )); +}