diff --git a/stwo_cairo_prover/Cargo.lock b/stwo_cairo_prover/Cargo.lock index 83cc01404..b74960af3 100644 --- a/stwo_cairo_prover/Cargo.lock +++ b/stwo_cairo_prover/Cargo.lock @@ -8,8 +8,9 @@ version = "0.1.0" dependencies = [ "clap", "log", + "serde", "serde_json", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=678d4a7)", "stwo_cairo_prover", "stwo_cairo_utils", "thiserror 2.0.11", @@ -695,6 +696,18 @@ dependencies = [ "bytes", ] +[[package]] +name = "faststr" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9154486833a83cb5d99de8c4d831314b8ae810dd4ef18d89ceb7a9c7c728dd74" +dependencies = [ + "bytes", + "rkyv", + "serde", + "simdutf8", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -968,6 +981,26 @@ dependencies = [ "adler2", ] +[[package]] +name = "munge" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64142d38c84badf60abf06ff9bd80ad2174306a5b11bd4706535090a30a419df" +dependencies = [ + "munge_macro", +] + +[[package]] +name = "munge_macro" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "nom" version = "7.1.3" @@ -1173,10 +1206,30 @@ dependencies = [ "serde", "starknet-ff", "stwo-cairo-serialize", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=678d4a7)", "stwo_cairo_utils", ] +[[package]] +name = "ptr_meta" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "quote" version = "1.0.38" @@ -1192,6 +1245,15 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "rancor" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947" +dependencies = [ + "ptr_meta", +] + [[package]] name = "rand" version = "0.8.5" @@ -1257,16 +1319,42 @@ version = "0.1.0" dependencies = [ "cairo-lang-casm", "serde_json", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=678d4a7)", "stwo_cairo_prover", ] +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "rend" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215" + [[package]] name = "rfc6979" version = "0.4.0" @@ -1277,6 +1365,35 @@ dependencies = [ "subtle", ] +[[package]] +name = "rkyv" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e147371c75553e1e2fcdb483944a8540b8438c31426279553b9a8182a9b7b65" +dependencies = [ + "bytes", + "hashbrown 0.15.2", + "indexmap", + "munge", + "ptr_meta", + "rancor", + "rend", + "rkyv_derive", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246b40ac189af6c675d124b802e8ef6d5246c53e17367ce9501f8f66a81abb7a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "rlp" version = "0.5.2" @@ -1326,7 +1443,7 @@ dependencies = [ "clap", "log", "serde_json", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=678d4a7)", "stwo_cairo_prover", "stwo_cairo_utils", "thiserror 2.0.11", @@ -1465,12 +1582,56 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "sonic-number" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8a74044c092f4f43ca7a6cfd62854cf9fb5ac8502b131347c990bf22bef1dfe" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "sonic-rs" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0275f9f2f07d47556fe60c2759da8bc4be6083b047b491b2d476aa0bfa558eb1" +dependencies = [ + "bumpalo", + "bytes", + "cfg-if", + "faststr", + "itoa", + "ref-cast", + "ryu", + "serde", + "simdutf8", + "sonic-number", + "sonic-simd", + "thiserror 2.0.11", +] + +[[package]] +name = "sonic-simd" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940a24e82c9a97483ef66cef06b92160a8fa5cd74042c57c10b24d99d169d2fc" +dependencies = [ + "cfg-if", +] + [[package]] name = "spin" version = "0.9.8" @@ -1594,7 +1755,7 @@ dependencies = [ "itertools 0.12.1", "rayon", "stwo-air-utils-derive", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=90b3e55)", ] [[package]] @@ -1614,7 +1775,7 @@ version = "0.1.0" dependencies = [ "starknet-ff", "stwo-cairo-serialize-derive", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=678d4a7)", ] [[package]] @@ -1629,7 +1790,7 @@ dependencies = [ [[package]] name = "stwo-prover" version = "0.1.1" -source = "git+https://github.com/starkware-libs/stwo?rev=90b3e55#90b3e55d29b3dd657878360d47be9b604dd24796" +source = "git+https://github.com/starkware-libs/stwo?rev=678d4a7#678d4a7c3d6ce5334447e211b5a8a4686154e6ef" dependencies = [ "blake2", "blake3", @@ -1648,6 +1809,27 @@ dependencies = [ "tracing", ] +[[package]] +name = "stwo-prover" +version = "0.1.1" +source = "git+https://github.com/starkware-libs/stwo?rev=90b3e55#90b3e55d29b3dd657878360d47be9b604dd24796" +dependencies = [ + "blake2", + "blake3", + "bytemuck", + "cfg-if", + "educe", + "hex", + "itertools 0.12.1", + "num-traits", + "rand", + "serde", + "starknet-crypto 0.6.2", + "starknet-ff", + "thiserror 1.0.69", + "tracing", +] + [[package]] name = "stwo_cairo_prover" version = "0.1.0" @@ -1665,11 +1847,12 @@ dependencies = [ "rayon", "serde", "serde_json", + "sonic-rs", "starknet-ff", "stwo-air-utils", "stwo-air-utils-derive", "stwo-cairo-serialize", - "stwo-prover", + "stwo-prover 0.1.1 (git+https://github.com/starkware-libs/stwo?rev=678d4a7)", "stwo_cairo_utils", "thiserror 2.0.11", "tracing", @@ -1806,6 +1989,21 @@ dependencies = [ "once_cell", ] +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml_datetime" version = "0.6.8" @@ -1922,6 +2120,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +[[package]] +name = "uuid" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3758f5e68192bb96cc8f9b7e2c2cfdabb435499a28499a42f8f984092adad4b" + [[package]] name = "valuable" version = "0.1.1" diff --git a/stwo_cairo_prover/Cargo.toml b/stwo_cairo_prover/Cargo.toml index ea76a63bc..5cfc63aa1 100644 --- a/stwo_cairo_prover/Cargo.toml +++ b/stwo_cairo_prover/Cargo.toml @@ -36,7 +36,7 @@ serde_json = "1.0.1" stwo_cairo_prover = { path = "crates/prover", version = "~0.1.0" } stwo_cairo_utils = { path = "crates/utils", version = "~0.1.0" } # TODO(ShaharS): take stwo version from the source repository. -stwo-prover = { git = "https://github.com/starkware-libs/stwo", rev = "90b3e55", features = [ +stwo-prover = { git = "https://github.com/starkware-libs/stwo", rev = "678d4a7", features = [ "parallel", ], default-features = false } thiserror = { version = "2.0.10", default-features = false } diff --git a/stwo_cairo_prover/crates/adapted_prover/Cargo.toml b/stwo_cairo_prover/crates/adapted_prover/Cargo.toml index b9be93d18..76bc17c0b 100644 --- a/stwo_cairo_prover/crates/adapted_prover/Cargo.toml +++ b/stwo_cairo_prover/crates/adapted_prover/Cargo.toml @@ -12,3 +12,4 @@ stwo_cairo_utils.workspace = true stwo-prover.workspace = true thiserror.workspace = true tracing.workspace = true +serde.workspace = true diff --git a/stwo_cairo_prover/crates/adapted_prover/src/main.rs b/stwo_cairo_prover/crates/adapted_prover/src/main.rs index e6718bb01..6bbffc6c8 100644 --- a/stwo_cairo_prover/crates/adapted_prover/src/main.rs +++ b/stwo_cairo_prover/crates/adapted_prover/src/main.rs @@ -2,14 +2,22 @@ use std::path::PathBuf; use std::process::ExitCode; use clap::Parser; +use serde::Serialize; use stwo_cairo_prover::cairo_air::{ - prove_cairo, verify_cairo, CairoVerificationError, ConfigBuilder, + prove_cairo, verify_cairo, CairoVerificationError, ChannelHash, ConfigBuilder, ProverConfig, + ProverParameters, }; use stwo_cairo_prover::input::vm_import::{adapt_vm_output, VmImportError}; use stwo_cairo_prover::input::ProverInput; use stwo_cairo_utils::binary_utils::run_binary; +use stwo_prover::core::backend::simd::SimdBackend; +use stwo_prover::core::backend::BackendForChannel; +use stwo_prover::core::channel::MerkleChannel; +use stwo_prover::core::fri::FriConfig; +use stwo_prover::core::pcs::PcsConfig; use stwo_prover::core::prover::ProvingError; use stwo_prover::core::vcs::blake2_merkle::Blake2sMerkleChannel; +use stwo_prover::core::vcs::poseidon252_merkle::Poseidon252MerkleChannel; use thiserror::Error; use tracing::{span, Level}; @@ -25,6 +33,9 @@ struct Args { pub_json: PathBuf, #[structopt(long = "priv_json")] priv_json: PathBuf, + /// The path to the JSON file containing the prover parameters (optional). + #[structopt(long = "params_json")] + params_json: Option, /// The output file path for the proof. #[structopt(long = "proof_path")] proof_path: PathBuf, @@ -57,6 +68,30 @@ fn main() -> ExitCode { run_binary(run, "adapted_stwo") } +/// Generates proof given the Cairo VM output and prover config/parameters. +/// Serializes the proof as JSON and write to the output path. +/// Verifies the proof in case the respective flag is set. +fn run_inner( + vm_output: ProverInput, + prover_config: ProverConfig, + pcs_config: PcsConfig, + verify: bool, + proof_path: PathBuf, +) -> Result<(), Error> +where + SimdBackend: BackendForChannel, + MC::H: Serialize, +{ + let proof = prove_cairo::(vm_output, prover_config, pcs_config)?; + std::fs::write(&proof_path, serde_json::to_string(&proof)?)?; + + if verify { + verify_cairo::(proof, pcs_config)?; + log::info!("Proof verified successfully"); + } + Ok(()) +} + fn run(args: impl Iterator) -> Result<(), Error> { let _span = span!(Level::INFO, "run").entered(); let args = Args::try_parse_from(args)?; @@ -73,15 +108,37 @@ fn run(args: impl Iterator) -> Result<(), Error> { vm_output.state_transitions.casm_states_by_opcode ); - // TODO(Ohad): Propagate hash from CLI args. - let proof = prove_cairo::(vm_output, prover_config)?; - - std::fs::write(args.proof_path, serde_json::to_string(&proof)?)?; + let params: ProverParameters = match args.params_json { + Some(path) => serde_json::from_str(&std::fs::read_to_string(path)?)?, + None => default_parameters(), + }; - if args.verify { - verify_cairo::(proof)?; - log::info!("Proof verified successfully"); - } + let run_inner_fn = match params.channel_hash { + ChannelHash::Blake2s => run_inner::, + ChannelHash::Poseidon252 => run_inner::, + }; + run_inner_fn( + vm_output, + prover_config, + params.pcs_config, + args.verify, + args.proof_path, + )?; Ok(()) } + +/// The default prover paramters (96 bits of security). +pub fn default_parameters() -> ProverParameters { + ProverParameters { + channel_hash: ChannelHash::Blake2s, + pcs_config: PcsConfig { + pow_bits: 26, + fri_config: FriConfig { + log_last_layer_degree_bound: 7, + log_blowup_factor: 1, + n_queries: 70, + }, + }, + } +} diff --git a/stwo_cairo_prover/crates/prover/Cargo.toml b/stwo_cairo_prover/crates/prover/Cargo.toml index ec3f63bed..3d86f3ee5 100644 --- a/stwo_cairo_prover/crates/prover/Cargo.toml +++ b/stwo_cairo_prover/crates/prover/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [features] slow-tests = [] +std = ["dep:sonic-rs"] [dependencies] air_structs_derive = { path = "../air_structs_derive" } @@ -23,6 +24,7 @@ rayon = { version = "1.10.0" } serde.workspace = true serde_json.workspace = true starknet-ff.workspace = true +sonic-rs = { version = "0.3.17", optional = true } stwo_cairo_utils = { path = "../utils" } stwo-cairo-serialize = { path = "../cairo-serialize" } stwo-prover.workspace = true diff --git a/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs b/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs index e3c6cf57a..68e9e2c49 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs @@ -26,11 +26,13 @@ use super::opcodes_air::{ OpcodesInteractionClaimGenerator, }; use super::preprocessed::preprocessed_trace_columns; -use crate::components::memory::{memory_address_to_id, memory_id_to_big}; -use crate::components::range_check_vector::{ - range_check_19, range_check_4_3, range_check_7_2_5, range_check_9_9, +use super::range_checks_air::{ + RangeChecksClaim, RangeChecksClaimGenerator, RangeChecksComponents, + RangeChecksInteractionClaim, RangeChecksInteractionClaimGenerator, + RangeChecksInteractionElements, }; -use crate::components::{range_check_11, verify_instruction}; +use crate::components::memory::{memory_address_to_id, memory_id_to_big}; +use crate::components::verify_instruction; use crate::felt::split_f252; use crate::input::ProverInput; use crate::relations; @@ -69,11 +71,7 @@ pub struct CairoClaim { pub builtins: BuiltinsClaim, pub memory_address_to_id: memory_address_to_id::Claim, pub memory_id_to_value: memory_id_to_big::Claim, - pub range_check_11: range_check_11::Claim, - pub range_check_19: range_check_19::Claim, - pub range_check9_9: range_check_9_9::Claim, - pub range_check7_2_5: range_check_7_2_5::Claim, - pub range_check4_3: range_check_4_3::Claim, + pub range_checks: RangeChecksClaim, // ... } @@ -85,11 +83,7 @@ impl CairoClaim { self.builtins.mix_into(channel); self.memory_address_to_id.mix_into(channel); self.memory_id_to_value.mix_into(channel); - self.range_check_11.mix_into(channel); - self.range_check_19.mix_into(channel); - self.range_check9_9.mix_into(channel); - self.range_check7_2_5.mix_into(channel); - self.range_check4_3.mix_into(channel); + self.range_checks.mix_into(channel); } pub fn log_sizes(&self) -> TreeVec> { @@ -99,11 +93,7 @@ impl CairoClaim { self.builtins.log_sizes(), self.memory_address_to_id.log_sizes(), self.memory_id_to_value.log_sizes(), - self.range_check_11.log_sizes(), - self.range_check_19.log_sizes(), - self.range_check9_9.log_sizes(), - self.range_check7_2_5.log_sizes(), - self.range_check4_3.log_sizes(), + self.range_checks.log_sizes(), ]; let mut log_sizes = TreeVec::concat_cols(log_sizes_list.into_iter()); @@ -173,11 +163,7 @@ pub struct CairoClaimGenerator { builtins: BuiltinsClaimGenerator, memory_address_to_id_trace_generator: memory_address_to_id::ClaimGenerator, memory_id_to_value_trace_generator: memory_id_to_big::ClaimGenerator, - range_check_11_trace_generator: range_check_11::ClaimGenerator, - range_check_19_trace_generator: range_check_19::ClaimGenerator, - range_check_9_9_trace_generator: range_check_9_9::ClaimGenerator, - range_check_7_2_5_trace_generator: range_check_7_2_5::ClaimGenerator, - range_check_4_3_trace_generator: range_check_4_3::ClaimGenerator, + range_checks_trace_generator: RangeChecksClaimGenerator, // ... } impl CairoClaimGenerator { @@ -192,11 +178,7 @@ impl CairoClaimGenerator { memory_address_to_id::ClaimGenerator::new(&input.memory); let memory_id_to_value_trace_generator = memory_id_to_big::ClaimGenerator::new(&input.memory); - let range_check_11_trace_generator = range_check_11::ClaimGenerator::new(); - let range_check_19_trace_generator = range_check_19::ClaimGenerator::new(); - let range_check_9_9_trace_generator = range_check_9_9::ClaimGenerator::new(); - let range_check_7_2_5_trace_generator = range_check_7_2_5::ClaimGenerator::new(); - let range_check_4_3_trace_generator = range_check_4_3::ClaimGenerator::new(); + let range_checks_trace_generator = RangeChecksClaimGenerator::new(); // Yield public memory. for addr in input @@ -233,11 +215,7 @@ impl CairoClaimGenerator { builtins, memory_address_to_id_trace_generator, memory_id_to_value_trace_generator, - range_check_11_trace_generator, - range_check_19_trace_generator, - range_check_9_9_trace_generator, - range_check_7_2_5_trace_generator, - range_check_4_3_trace_generator, + range_checks_trace_generator, } } @@ -253,9 +231,9 @@ impl CairoClaimGenerator { tree_builder, &self.memory_address_to_id_trace_generator, &self.memory_id_to_value_trace_generator, - &self.range_check_11_trace_generator, - &self.range_check_19_trace_generator, - &self.range_check_9_9_trace_generator, + &self.range_checks_trace_generator.rc_11_trace_generator, + &self.range_checks_trace_generator.rc_19_trace_generator, + &self.range_checks_trace_generator.rc_9_9_trace_generator, &self.verify_instruction_trace_generator, ); span.exit(); @@ -265,8 +243,8 @@ impl CairoClaimGenerator { tree_builder, &self.memory_address_to_id_trace_generator, &self.memory_id_to_value_trace_generator, - &self.range_check_4_3_trace_generator, - &self.range_check_7_2_5_trace_generator, + &self.range_checks_trace_generator.rc_4_3_trace_generator, + &self.range_checks_trace_generator.rc_7_2_5_trace_generator, ); let (builtins_claim, builtins_interaction_gen) = self.builtins.write_trace( tree_builder, @@ -276,24 +254,13 @@ impl CairoClaimGenerator { let (memory_address_to_id_claim, memory_address_to_id_interaction_gen) = self .memory_address_to_id_trace_generator .write_trace(tree_builder); - let (memory_id_to_value_claim, memory_id_to_value_interaction_gen) = self - .memory_id_to_value_trace_generator - .write_trace(tree_builder, &self.range_check_9_9_trace_generator); - let (range_check_11_claim, range_check_11_interaction_gen) = self - .range_check_11_trace_generator - .write_trace(tree_builder); - let (range_check_19_claim, range_check_19_interaction_gen) = self - .range_check_19_trace_generator - .write_trace(tree_builder); - let (range_check9_9_claim, range_check_9_9_interaction_gen) = self - .range_check_9_9_trace_generator - .write_trace(tree_builder); - let (range_check_7_2_5_claim, range_check_7_2_5_interaction_gen) = self - .range_check_7_2_5_trace_generator - .write_trace(tree_builder); - let (range_check_4_3_claim, range_check_4_3_interaction_gen) = self - .range_check_4_3_trace_generator - .write_trace(tree_builder); + let (memory_id_to_value_claim, memory_id_to_value_interaction_gen) = + self.memory_id_to_value_trace_generator.write_trace( + tree_builder, + &self.range_checks_trace_generator.rc_9_9_trace_generator, + ); + let (range_checks_claim, range_checks_interaction_gen) = + self.range_checks_trace_generator.write_trace(tree_builder); span.exit(); ( CairoClaim { @@ -303,11 +270,7 @@ impl CairoClaimGenerator { builtins: builtins_claim, memory_address_to_id: memory_address_to_id_claim, memory_id_to_value: memory_id_to_value_claim, - range_check_11: range_check_11_claim, - range_check_19: range_check_19_claim, - range_check9_9: range_check9_9_claim, - range_check7_2_5: range_check_7_2_5_claim, - range_check4_3: range_check_4_3_claim, + range_checks: range_checks_claim, }, CairoInteractionClaimGenerator { opcodes_interaction_gen, @@ -315,11 +278,7 @@ impl CairoClaimGenerator { builtins_interaction_gen, memory_address_to_id_interaction_gen, memory_id_to_value_interaction_gen, - range_check_11_interaction_gen, - range_check_19_interaction_gen, - range_check_9_9_interaction_gen, - range_check_7_2_5_interaction_gen, - range_check_4_3_interaction_gen, + range_checks_interaction_gen, }, ) } @@ -331,11 +290,7 @@ pub struct CairoInteractionClaimGenerator { builtins_interaction_gen: BuiltinsInteractionClaimGenerator, memory_address_to_id_interaction_gen: memory_address_to_id::InteractionClaimGenerator, memory_id_to_value_interaction_gen: memory_id_to_big::InteractionClaimGenerator, - range_check_11_interaction_gen: range_check_11::InteractionClaimGenerator, - range_check_19_interaction_gen: range_check_19::InteractionClaimGenerator, - range_check_9_9_interaction_gen: range_check_9_9::InteractionClaimGenerator, - range_check_7_2_5_interaction_gen: range_check_7_2_5::InteractionClaimGenerator, - range_check_4_3_interaction_gen: range_check_4_3::InteractionClaimGenerator, + range_checks_interaction_gen: RangeChecksInteractionClaimGenerator, // ... } impl CairoInteractionClaimGenerator { @@ -356,8 +311,8 @@ impl CairoInteractionClaimGenerator { tree_builder, &interaction_elements.memory_address_to_id, &interaction_elements.memory_id_to_value, - &interaction_elements.range_check_4_3, - &interaction_elements.range_check_7_2_5, + &interaction_elements.range_checks.rc_4_3, + &interaction_elements.range_checks.rc_7_2_5, &interaction_elements.verify_instruction, ); let builtins_interaction_claims = self @@ -371,24 +326,12 @@ impl CairoInteractionClaimGenerator { .write_interaction_trace( tree_builder, &interaction_elements.memory_id_to_value, - &interaction_elements.range_check_9_9, + &interaction_elements.range_checks.rc_9_9, ); - let range_check_11_interaction_claim = self - .range_check_11_interaction_gen - .write_interaction_trace(tree_builder, &interaction_elements.range_check_11); - let range_check_19_interaction_claim = self - .range_check_19_interaction_gen - .write_interaction_trace(tree_builder, &interaction_elements.range_check_19); - let range_check9_9_interaction_claim = self - .range_check_9_9_interaction_gen - .write_interaction_trace(tree_builder, &interaction_elements.range_check_9_9); - let range_check_7_2_5_interaction_claim = self - .range_check_7_2_5_interaction_gen - .write_interaction_trace(tree_builder, &interaction_elements.range_check_7_2_5); - let range_check_4_3_interaction_claim = self - .range_check_4_3_interaction_gen - .write_interaction_trace(tree_builder, &interaction_elements.range_check_4_3); + let range_checks_interaction_claim = self + .range_checks_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.range_checks); CairoInteractionClaim { opcodes: opcodes_interaction_claims, @@ -396,11 +339,7 @@ impl CairoInteractionClaimGenerator { builtins: builtins_interaction_claims, memory_address_to_id: memory_address_to_id_interaction_claim, memory_id_to_value: memory_id_to_value_interaction_claim, - range_check_11: range_check_11_interaction_claim, - range_check_19: range_check_19_interaction_claim, - range_check_9_9: range_check9_9_interaction_claim, - range_check_7_2_5: range_check_7_2_5_interaction_claim, - range_check_4_3: range_check_4_3_interaction_claim, + range_checks: range_checks_interaction_claim, } } } @@ -410,12 +349,7 @@ pub struct CairoInteractionElements { pub verify_instruction: relations::VerifyInstruction, pub memory_address_to_id: relations::MemoryAddressToId, pub memory_id_to_value: relations::MemoryIdToBig, - pub range_check_11: relations::RangeCheck_11, - pub range_check_19: relations::RangeCheck_19, - pub range_check_9_9: relations::RangeCheck_9_9, - pub range_check_7_2_5: relations::RangeCheck_7_2_5, - pub range_check_4_3: relations::RangeCheck_4_3, - // ... + pub range_checks: RangeChecksInteractionElements, } impl CairoInteractionElements { pub fn draw(channel: &mut impl Channel) -> CairoInteractionElements { @@ -424,11 +358,7 @@ impl CairoInteractionElements { verify_instruction: relations::VerifyInstruction::draw(channel), memory_address_to_id: relations::MemoryAddressToId::draw(channel), memory_id_to_value: relations::MemoryIdToBig::draw(channel), - range_check_11: relations::RangeCheck_11::draw(channel), - range_check_19: relations::RangeCheck_19::draw(channel), - range_check_9_9: relations::RangeCheck_9_9::draw(channel), - range_check_7_2_5: relations::RangeCheck_7_2_5::draw(channel), - range_check_4_3: relations::RangeCheck_4_3::draw(channel), + range_checks: RangeChecksInteractionElements::draw(channel), } } } @@ -440,11 +370,7 @@ pub struct CairoInteractionClaim { pub builtins: BuiltinsInteractionClaim, pub memory_address_to_id: memory_address_to_id::InteractionClaim, pub memory_id_to_value: memory_id_to_big::InteractionClaim, - pub range_check_11: range_check_11::InteractionClaim, - pub range_check_19: range_check_19::InteractionClaim, - pub range_check_9_9: range_check_9_9::InteractionClaim, - pub range_check_7_2_5: range_check_7_2_5::InteractionClaim, - pub range_check_4_3: range_check_4_3::InteractionClaim, + pub range_checks: RangeChecksInteractionClaim, } impl CairoInteractionClaim { pub fn mix_into(&self, channel: &mut impl Channel) { @@ -453,11 +379,7 @@ impl CairoInteractionClaim { self.builtins.mix_into(channel); self.memory_address_to_id.mix_into(channel); self.memory_id_to_value.mix_into(channel); - self.range_check_11.mix_into(channel); - self.range_check_19.mix_into(channel); - self.range_check_9_9.mix_into(channel); - self.range_check_7_2_5.mix_into(channel); - self.range_check_4_3.mix_into(channel); + self.range_checks.mix_into(channel); } } @@ -477,11 +399,7 @@ pub fn lookup_sum( sum += interaction_claim.memory_address_to_id.claimed_sum; sum += interaction_claim.memory_id_to_value.big_claimed_sum; sum += interaction_claim.memory_id_to_value.small_claimed_sum; - sum += interaction_claim.range_check_11.claimed_sum; - sum += interaction_claim.range_check_19.claimed_sum; - sum += interaction_claim.range_check_9_9.claimed_sum; - sum += interaction_claim.range_check_7_2_5.claimed_sum; - sum += interaction_claim.range_check_4_3.claimed_sum; + sum += interaction_claim.range_checks.sum(); sum } @@ -494,11 +412,7 @@ pub struct CairoComponents { memory_id_to_big::BigComponent, memory_id_to_big::SmallComponent, ), - range_check_11: range_check_11::Component, - range_check_19: range_check_19::Component, - range_check9_9: range_check_9_9::Component, - range_check7_2_5: range_check_7_2_5::Component, - range_check4_3: range_check_4_3::Component, + range_checks: RangeChecksComponents, // ... } impl CairoComponents { @@ -529,8 +443,11 @@ impl CairoComponents { .clone(), verify_instruction_lookup_elements: interaction_elements.verify_instruction.clone(), memory_id_to_big_lookup_elements: interaction_elements.memory_id_to_value.clone(), - range_check_4_3_lookup_elements: interaction_elements.range_check_4_3.clone(), - range_check_7_2_5_lookup_elements: interaction_elements.range_check_7_2_5.clone(), + range_check_4_3_lookup_elements: interaction_elements.range_checks.rc_4_3.clone(), + range_check_7_2_5_lookup_elements: interaction_elements + .range_checks + .rc_7_2_5 + .clone(), }, (interaction_claim.verify_instruction.claimed_sum, None), ); @@ -556,7 +473,7 @@ impl CairoComponents { memory_id_to_big::BigEval::new( cairo_claim.memory_id_to_value.clone(), interaction_elements.memory_id_to_value.clone(), - interaction_elements.range_check_9_9.clone(), + interaction_elements.range_checks.rc_9_9.clone(), ), ( interaction_claim.memory_id_to_value.clone().big_claimed_sum, @@ -568,7 +485,7 @@ impl CairoComponents { memory_id_to_big::SmallEval::new( cairo_claim.memory_id_to_value.clone(), interaction_elements.memory_id_to_value.clone(), - interaction_elements.range_check_9_9.clone(), + interaction_elements.range_checks.rc_9_9.clone(), ), ( interaction_claim @@ -578,30 +495,10 @@ impl CairoComponents { None, ), ); - let range_check_11_component = range_check_11::Component::new( - tree_span_provider, - range_check_11::Eval::new(interaction_elements.range_check_11.clone()), - (interaction_claim.range_check_11.claimed_sum, None), - ); - let range_check_19_component = range_check_19::Component::new( - tree_span_provider, - range_check_19::Eval::new(interaction_elements.range_check_19.clone()), - (interaction_claim.range_check_19.claimed_sum, None), - ); - let range_check9_9_component = range_check_9_9::Component::new( - tree_span_provider, - range_check_9_9::Eval::new(interaction_elements.range_check_9_9.clone()), - (interaction_claim.range_check_9_9.claimed_sum, None), - ); - let range_check_7_2_5_component = range_check_7_2_5::Component::new( + let range_checks_component = RangeChecksComponents::new( tree_span_provider, - range_check_7_2_5::Eval::new(interaction_elements.range_check_7_2_5.clone()), - (interaction_claim.range_check_7_2_5.claimed_sum, None), - ); - let range_check_4_3_component = range_check_4_3::Component::new( - tree_span_provider, - range_check_4_3::Eval::new(interaction_elements.range_check_4_3.clone()), - (interaction_claim.range_check_4_3.claimed_sum, None), + &interaction_elements.range_checks, + &interaction_claim.range_checks, ); Self { opcodes: opcode_components, @@ -612,11 +509,7 @@ impl CairoComponents { memory_id_to_value_component, small_memory_id_to_value_component, ), - range_check_11: range_check_11_component, - range_check_19: range_check_19_component, - range_check9_9: range_check9_9_component, - range_check7_2_5: range_check_7_2_5_component, - range_check4_3: range_check_4_3_component, + range_checks: range_checks_component, } } @@ -629,12 +522,8 @@ impl CairoComponents { &self.memory_address_to_id as &dyn ComponentProver, &self.memory_id_to_value.0 as &dyn ComponentProver, &self.memory_id_to_value.1 as &dyn ComponentProver, - &self.range_check_11 as &dyn ComponentProver, - &self.range_check_19 as &dyn ComponentProver, - &self.range_check9_9 as &dyn ComponentProver, - &self.range_check7_2_5 as &dyn ComponentProver, - &self.range_check4_3 as &dyn ComponentProver, - ] + ], + self.range_checks.provers() ) .collect() } @@ -672,31 +561,7 @@ impl std::fmt::Display for CairoComponents { "SmallMemoryIdToValue: {}", indented_component_display(&self.memory_id_to_value.1) )?; - writeln!( - f, - "RangeCheck19: {}", - indented_component_display(&self.range_check_11) - )?; - writeln!( - f, - "RangeCheck19: {}", - indented_component_display(&self.range_check_19) - )?; - writeln!( - f, - "RangeCheck9_9: {}", - indented_component_display(&self.range_check9_9) - )?; - writeln!( - f, - "RangeCheck7_2_5: {}", - indented_component_display(&self.range_check7_2_5) - )?; - writeln!( - f, - "RangeCheck4_3: {}", - indented_component_display(&self.range_check4_3) - )?; + writeln!(f, "RangeChecks: {}", self.range_checks)?; Ok(()) } } diff --git a/stwo_cairo_prover/crates/prover/src/cairo_air/mod.rs b/stwo_cairo_prover/crates/prover/src/cairo_air/mod.rs index 379b985d1..fa500b991 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/mod.rs @@ -3,17 +3,18 @@ pub mod builtins_air; mod debug_tools; pub mod opcodes_air; pub mod preprocessed; +pub mod range_checks_air; use air::{lookup_sum, CairoClaimGenerator, CairoComponents, CairoInteractionElements, CairoProof}; use debug_tools::track_cairo_relations; use num_traits::Zero; use preprocessed::preprocessed_trace_columns; +use serde::{Deserialize, Serialize}; use stwo_prover::constraint_framework::relation_tracker::RelationSummary; use stwo_prover::core::backend::simd::SimdBackend; use stwo_prover::core::backend::BackendForChannel; use stwo_prover::core::channel::MerkleChannel; use stwo_prover::core::fields::qm31::SecureField; -use stwo_prover::core::fri::FriConfig; use stwo_prover::core::pcs::{CommitmentSchemeProver, CommitmentSchemeVerifier, PcsConfig}; use stwo_prover::core::poly::circle::{CanonicCoset, PolyOps}; use stwo_prover::core::prover::{prove, verify, ProvingError, VerificationError}; @@ -31,29 +32,23 @@ pub fn prove_cairo( track_relations, display_components, }: ProverConfig, + pcs_config: PcsConfig, ) -> Result, ProvingError> where SimdBackend: BackendForChannel, { let _span = span!(Level::INFO, "prove_cairo").entered(); - // TODO(Ohad): Propogate config from CLI args. - let config = PcsConfig { - pow_bits: 0, - fri_config: FriConfig { - log_last_layer_degree_bound: 2, - log_blowup_factor: 1, - n_queries: 15, - }, - }; + let twiddles = SimdBackend::precompute_twiddles( - CanonicCoset::new(LOG_MAX_ROWS + config.fri_config.log_blowup_factor + 2) + CanonicCoset::new(LOG_MAX_ROWS + pcs_config.fri_config.log_blowup_factor + 2) .circle_domain() .half_coset, ); // Setup protocol. let channel = &mut MC::C::default(); - let mut commitment_scheme = CommitmentSchemeProver::::new(config, &twiddles); + let mut commitment_scheme = + CommitmentSchemeProver::::new(pcs_config, &twiddles); // Preprocessed trace. let mut tree_builder = commitment_scheme.tree_builder(); @@ -124,19 +119,12 @@ pub fn verify_cairo( interaction_claim, stark_proof, }: CairoProof, + pcs_config: PcsConfig, ) -> Result<(), CairoVerificationError> { - // Verify. - // TODO(Ohad): Propogate config from CLI args. - let config = PcsConfig { - pow_bits: 0, - fri_config: FriConfig { - log_last_layer_degree_bound: 2, - log_blowup_factor: 1, - n_queries: 15, - }, - }; + let _span = span!(Level::INFO, "verify_cairo").entered(); + let channel = &mut MC::C::default(); - let commitment_scheme_verifier = &mut CommitmentSchemeVerifier::::new(config); + let commitment_scheme_verifier = &mut CommitmentSchemeVerifier::::new(pcs_config); let log_sizes = claim.log_sizes(); @@ -206,6 +194,25 @@ impl ConfigBuilder { } } +#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] +pub struct ProverParameters { + pub channel_hash: ChannelHash, + pub pcs_config: PcsConfig, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum ChannelHash { + Blake2s, + Poseidon252, +} + +impl Default for ChannelHash { + fn default() -> Self { + Self::Blake2s + } +} + #[derive(Error, Debug)] pub enum CairoVerificationError { #[error("Invalid logup sum")] @@ -217,6 +224,7 @@ pub enum CairoVerificationError { #[cfg(test)] mod tests { use cairo_lang_casm::casm; + use stwo_prover::core::pcs::PcsConfig; use stwo_prover::core::vcs::blake2_merkle::Blake2sMerkleChannel; use super::ProverConfig; @@ -258,8 +266,10 @@ mod tests { #[test] fn test_basic_cairo_air() { - let cairo_proof = prove_cairo::(test_input(), test_cfg()).unwrap(); - verify_cairo::(cairo_proof).unwrap(); + let cairo_proof = + prove_cairo::(test_input(), test_cfg(), PcsConfig::default()) + .unwrap(); + verify_cairo::(cairo_proof, PcsConfig::default()).unwrap(); } #[cfg(feature = "slow-tests")] @@ -276,21 +286,29 @@ mod tests { #[test] fn generate_and_serialise_proof() { - let cairo_proof = - prove_cairo::(test_input(), test_cfg()).unwrap(); + let cairo_proof = prove_cairo::( + test_input(), + test_cfg(), + PcsConfig::default(), + ) + .unwrap(); let mut output = Vec::new(); CairoSerialize::serialize(&cairo_proof, &mut output); let proof_str = output.iter().map(|v| v.to_string()).join(","); let mut file = std::fs::File::create("proof.cairo").unwrap(); file.write_all(proof_str.as_bytes()).unwrap(); - verify_cairo::(cairo_proof).unwrap(); + verify_cairo::(cairo_proof, PcsConfig::default()).unwrap(); } #[test] fn test_full_cairo_air() { - let cairo_proof = - prove_cairo::(small_cairo_input(), test_cfg()).unwrap(); - verify_cairo::(cairo_proof).unwrap(); + let cairo_proof = prove_cairo::( + small_cairo_input(), + test_cfg(), + PcsConfig::default(), + ) + .unwrap(); + verify_cairo::(cairo_proof, PcsConfig::default()).unwrap(); } } } diff --git a/stwo_cairo_prover/crates/prover/src/cairo_air/opcodes_air.rs b/stwo_cairo_prover/crates/prover/src/cairo_air/opcodes_air.rs index 129782fc4..bef1963cf 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/opcodes_air.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/opcodes_air.rs @@ -1196,8 +1196,8 @@ impl OpcodesInteractionClaimGenerator { &interaction_elements.memory_address_to_id, &interaction_elements.memory_id_to_value, &interaction_elements.opcodes, - &interaction_elements.range_check_19, - &interaction_elements.range_check_9_9, + &interaction_elements.range_checks.rc_19, + &interaction_elements.range_checks.rc_9_9, &interaction_elements.verify_instruction, ) }) @@ -1315,7 +1315,7 @@ impl OpcodesInteractionClaimGenerator { &interaction_elements.memory_address_to_id, &interaction_elements.memory_id_to_value, &interaction_elements.opcodes, - &interaction_elements.range_check_19, + &interaction_elements.range_checks.rc_19, &interaction_elements.verify_instruction, ) }) @@ -1329,7 +1329,7 @@ impl OpcodesInteractionClaimGenerator { &interaction_elements.memory_address_to_id, &interaction_elements.memory_id_to_value, &interaction_elements.opcodes, - &interaction_elements.range_check_19, + &interaction_elements.range_checks.rc_19, &interaction_elements.verify_instruction, ) }) @@ -1733,9 +1733,13 @@ impl OpcodeComponents { .memory_id_to_value .clone(), opcodes_lookup_elements: interaction_elements.opcodes.clone(), - range_check_19_lookup_elements: interaction_elements.range_check_19.clone(), + range_check_19_lookup_elements: interaction_elements + .range_checks + .rc_19 + .clone(), range_check_9_9_lookup_elements: interaction_elements - .range_check_9_9 + .range_checks + .rc_9_9 .clone(), verify_instruction_lookup_elements: interaction_elements .verify_instruction @@ -1953,7 +1957,10 @@ impl OpcodeComponents { .memory_id_to_value .clone(), opcodes_lookup_elements: interaction_elements.opcodes.clone(), - range_check_19_lookup_elements: interaction_elements.range_check_19.clone(), + range_check_19_lookup_elements: interaction_elements + .range_checks + .rc_19 + .clone(), verify_instruction_lookup_elements: interaction_elements .verify_instruction .clone(), @@ -1978,7 +1985,10 @@ impl OpcodeComponents { .memory_id_to_value .clone(), opcodes_lookup_elements: interaction_elements.opcodes.clone(), - range_check_19_lookup_elements: interaction_elements.range_check_19.clone(), + range_check_19_lookup_elements: interaction_elements + .range_checks + .rc_19 + .clone(), verify_instruction_lookup_elements: interaction_elements .verify_instruction .clone(), diff --git a/stwo_cairo_prover/crates/prover/src/cairo_air/range_checks_air.rs b/stwo_cairo_prover/crates/prover/src/cairo_air/range_checks_air.rs new file mode 100644 index 000000000..682d76417 --- /dev/null +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/range_checks_air.rs @@ -0,0 +1,413 @@ +use num_traits::Zero; +use serde::{Deserialize, Serialize}; +use stwo_cairo_serialize::CairoSerialize; +use stwo_prover::constraint_framework::TraceLocationAllocator; +use stwo_prover::core::air::ComponentProver; +use stwo_prover::core::backend::simd::SimdBackend; +use stwo_prover::core::backend::BackendForChannel; +use stwo_prover::core::channel::{Channel, MerkleChannel}; +use stwo_prover::core::fields::qm31::{SecureField, QM31}; +use stwo_prover::core::pcs::{TreeBuilder, TreeVec}; + +use super::debug_tools::indented_component_display; +use crate::components::range_check_vector::{ + range_check_11, range_check_12, range_check_18, range_check_19, range_check_3_6, + range_check_3_6_6_3, range_check_4_3, range_check_7_2_5, range_check_9_9, +}; +use crate::relations; + +#[derive(Serialize, Deserialize, CairoSerialize)] +pub struct RangeChecksClaim { + pub rc_11: range_check_11::Claim, + pub rc_12: range_check_12::Claim, + pub rc_18: range_check_18::Claim, + pub rc_19: range_check_19::Claim, + pub rc_3_6: range_check_3_6::Claim, + pub rc_4_3: range_check_4_3::Claim, + pub rc_9_9: range_check_9_9::Claim, + pub rc_7_2_5: range_check_7_2_5::Claim, + pub rc_3_6_6_3: range_check_3_6_6_3::Claim, +} +impl RangeChecksClaim { + pub fn mix_into(&self, channel: &mut impl Channel) { + self.rc_11.mix_into(channel); + self.rc_12.mix_into(channel); + self.rc_18.mix_into(channel); + self.rc_19.mix_into(channel); + self.rc_3_6.mix_into(channel); + self.rc_4_3.mix_into(channel); + self.rc_9_9.mix_into(channel); + self.rc_7_2_5.mix_into(channel); + self.rc_3_6_6_3.mix_into(channel); + } + + pub fn log_sizes(&self) -> TreeVec> { + TreeVec::concat_cols( + vec![ + self.rc_11.log_sizes(), + self.rc_12.log_sizes(), + self.rc_18.log_sizes(), + self.rc_19.log_sizes(), + self.rc_3_6.log_sizes(), + self.rc_4_3.log_sizes(), + self.rc_9_9.log_sizes(), + self.rc_7_2_5.log_sizes(), + self.rc_3_6_6_3.log_sizes(), + ] + .into_iter(), + ) + } +} + +pub struct RangeChecksClaimGenerator { + pub rc_11_trace_generator: range_check_11::ClaimGenerator, + pub rc_12_trace_generator: range_check_12::ClaimGenerator, + pub rc_18_trace_generator: range_check_18::ClaimGenerator, + pub rc_19_trace_generator: range_check_19::ClaimGenerator, + pub rc_3_6_trace_generator: range_check_3_6::ClaimGenerator, + pub rc_4_3_trace_generator: range_check_4_3::ClaimGenerator, + pub rc_9_9_trace_generator: range_check_9_9::ClaimGenerator, + pub rc_7_2_5_trace_generator: range_check_7_2_5::ClaimGenerator, + pub rc_3_6_6_3_trace_generator: range_check_3_6_6_3::ClaimGenerator, +} +impl Default for RangeChecksClaimGenerator { + fn default() -> Self { + Self::new() + } +} + +impl RangeChecksClaimGenerator { + pub fn new() -> Self { + Self { + rc_11_trace_generator: range_check_11::ClaimGenerator::new(), + rc_12_trace_generator: range_check_12::ClaimGenerator::new(), + rc_18_trace_generator: range_check_18::ClaimGenerator::new(), + rc_19_trace_generator: range_check_19::ClaimGenerator::new(), + rc_3_6_trace_generator: range_check_3_6::ClaimGenerator::new(), + rc_4_3_trace_generator: range_check_4_3::ClaimGenerator::new(), + rc_9_9_trace_generator: range_check_9_9::ClaimGenerator::new(), + rc_7_2_5_trace_generator: range_check_7_2_5::ClaimGenerator::new(), + rc_3_6_6_3_trace_generator: range_check_3_6_6_3::ClaimGenerator::new(), + } + } + pub fn write_trace( + self, + tree_builder: &mut TreeBuilder<'_, '_, SimdBackend, MC>, + ) -> (RangeChecksClaim, RangeChecksInteractionClaimGenerator) + where + SimdBackend: BackendForChannel, + { + let (rc_11_claim, rc_11_interaction_gen) = + self.rc_11_trace_generator.write_trace(tree_builder); + let (rc_12_claim, rc_12_interaction_gen) = + self.rc_12_trace_generator.write_trace(tree_builder); + let (rc_18_claim, rc_18_interaction_gen) = + self.rc_18_trace_generator.write_trace(tree_builder); + let (rc_19_claim, rc_19_interaction_gen) = + self.rc_19_trace_generator.write_trace(tree_builder); + let (rc_3_6_claim, rc_3_6_interaction_gen) = + self.rc_3_6_trace_generator.write_trace(tree_builder); + let (rc_4_3_claim, rc_4_3_interaction_gen) = + self.rc_4_3_trace_generator.write_trace(tree_builder); + let (rc_9_9_claim, rc_9_9_interaction_gen) = + self.rc_9_9_trace_generator.write_trace(tree_builder); + let (rc_7_2_5_claim, rc_7_2_5_interaction_gen) = + self.rc_7_2_5_trace_generator.write_trace(tree_builder); + let (rc_3_6_6_3_claim, rc_3_6_6_3_interaction_gen) = + self.rc_3_6_6_3_trace_generator.write_trace(tree_builder); + ( + RangeChecksClaim { + rc_11: rc_11_claim, + rc_12: rc_12_claim, + rc_18: rc_18_claim, + rc_19: rc_19_claim, + rc_3_6: rc_3_6_claim, + rc_4_3: rc_4_3_claim, + rc_9_9: rc_9_9_claim, + rc_7_2_5: rc_7_2_5_claim, + rc_3_6_6_3: rc_3_6_6_3_claim, + }, + RangeChecksInteractionClaimGenerator { + rc_11_interaction_gen, + rc_12_interaction_gen, + rc_18_interaction_gen, + rc_19_interaction_gen, + rc_3_6_interaction_gen, + rc_4_3_interaction_gen, + rc_9_9_interaction_gen, + rc_7_2_5_interaction_gen, + rc_3_6_6_3_interaction_gen, + }, + ) + } +} + +#[derive(Serialize, Deserialize, CairoSerialize)] +pub struct RangeChecksInteractionClaim { + pub rc_11: range_check_11::InteractionClaim, + pub rc_12: range_check_12::InteractionClaim, + pub rc_18: range_check_18::InteractionClaim, + pub rc_19: range_check_19::InteractionClaim, + pub rc_3_6: range_check_3_6::InteractionClaim, + pub rc_4_3: range_check_4_3::InteractionClaim, + pub rc_9_9: range_check_9_9::InteractionClaim, + pub rc_7_2_5: range_check_7_2_5::InteractionClaim, + pub rc_3_6_6_3: range_check_3_6_6_3::InteractionClaim, +} +impl RangeChecksInteractionClaim { + pub fn mix_into(&self, channel: &mut impl Channel) { + self.rc_11.mix_into(channel); + self.rc_12.mix_into(channel); + self.rc_18.mix_into(channel); + self.rc_19.mix_into(channel); + self.rc_3_6.mix_into(channel); + self.rc_4_3.mix_into(channel); + self.rc_9_9.mix_into(channel); + self.rc_7_2_5.mix_into(channel); + self.rc_3_6_6_3.mix_into(channel); + } + + pub fn sum(&self) -> SecureField { + let mut sum = QM31::zero(); + sum += self.rc_11.claimed_sum; + sum += self.rc_12.claimed_sum; + sum += self.rc_18.claimed_sum; + sum += self.rc_19.claimed_sum; + sum += self.rc_3_6.claimed_sum; + sum += self.rc_4_3.claimed_sum; + sum += self.rc_9_9.claimed_sum; + sum += self.rc_7_2_5.claimed_sum; + sum += self.rc_3_6_6_3.claimed_sum; + sum + } +} + +pub struct RangeChecksInteractionClaimGenerator { + rc_11_interaction_gen: range_check_11::InteractionClaimGenerator, + rc_12_interaction_gen: range_check_12::InteractionClaimGenerator, + rc_18_interaction_gen: range_check_18::InteractionClaimGenerator, + rc_19_interaction_gen: range_check_19::InteractionClaimGenerator, + rc_3_6_interaction_gen: range_check_3_6::InteractionClaimGenerator, + rc_4_3_interaction_gen: range_check_4_3::InteractionClaimGenerator, + rc_9_9_interaction_gen: range_check_9_9::InteractionClaimGenerator, + rc_7_2_5_interaction_gen: range_check_7_2_5::InteractionClaimGenerator, + rc_3_6_6_3_interaction_gen: range_check_3_6_6_3::InteractionClaimGenerator, +} +impl RangeChecksInteractionClaimGenerator { + pub fn write_interaction_trace( + self, + tree_builder: &mut TreeBuilder<'_, '_, SimdBackend, MC>, + interaction_elements: &RangeChecksInteractionElements, + ) -> RangeChecksInteractionClaim + where + SimdBackend: BackendForChannel, + { + let rc_11_interaction_claim = self + .rc_11_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_11); + let rc_12_interaction_claim = self + .rc_12_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_12); + let rc_18_interaction_claim = self + .rc_18_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_18); + let rc_19_interaction_claim = self + .rc_19_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_19); + let rc_3_6_interaction_claim = self + .rc_3_6_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_3_6); + let rc_4_3_interaction_claim = self + .rc_4_3_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_4_3); + let rc_9_9_interaction_claim = self + .rc_9_9_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_9_9); + let rc_7_2_5_interaction_claim = self + .rc_7_2_5_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_7_2_5); + let rc_3_6_6_3_interaction_claim = self + .rc_3_6_6_3_interaction_gen + .write_interaction_trace(tree_builder, &interaction_elements.rc_3_6_6_3); + RangeChecksInteractionClaim { + rc_11: rc_11_interaction_claim, + rc_12: rc_12_interaction_claim, + rc_18: rc_18_interaction_claim, + rc_19: rc_19_interaction_claim, + rc_3_6: rc_3_6_interaction_claim, + rc_4_3: rc_4_3_interaction_claim, + rc_9_9: rc_9_9_interaction_claim, + rc_7_2_5: rc_7_2_5_interaction_claim, + rc_3_6_6_3: rc_3_6_6_3_interaction_claim, + } + } +} + +pub struct RangeChecksInteractionElements { + pub rc_11: relations::RangeCheck_11, + pub rc_12: relations::RangeCheck_12, + pub rc_18: relations::RangeCheck_18, + pub rc_19: relations::RangeCheck_19, + pub rc_3_6: relations::RangeCheck_3_6, + pub rc_4_3: relations::RangeCheck_4_3, + pub rc_9_9: relations::RangeCheck_9_9, + pub rc_7_2_5: relations::RangeCheck_7_2_5, + pub rc_3_6_6_3: relations::RangeCheck_3_6_6_3, + // ... +} +impl RangeChecksInteractionElements { + pub fn draw(channel: &mut impl Channel) -> RangeChecksInteractionElements { + RangeChecksInteractionElements { + rc_11: relations::RangeCheck_11::draw(channel), + rc_12: relations::RangeCheck_12::draw(channel), + rc_18: relations::RangeCheck_18::draw(channel), + rc_19: relations::RangeCheck_19::draw(channel), + rc_3_6: relations::RangeCheck_3_6::draw(channel), + rc_4_3: relations::RangeCheck_4_3::draw(channel), + rc_9_9: relations::RangeCheck_9_9::draw(channel), + rc_7_2_5: relations::RangeCheck_7_2_5::draw(channel), + rc_3_6_6_3: relations::RangeCheck_3_6_6_3::draw(channel), + } + } +} + +pub struct RangeChecksComponents { + rc_11: range_check_11::Component, + rc_12: range_check_12::Component, + rc_18: range_check_18::Component, + rc_19: range_check_19::Component, + rc_3_6: range_check_3_6::Component, + rc_4_3: range_check_4_3::Component, + rc_9_9: range_check_9_9::Component, + rc_7_2_5: range_check_7_2_5::Component, + rc_3_6_6_3: range_check_3_6_6_3::Component, +} +impl RangeChecksComponents { + pub fn new( + tree_span_provider: &mut TraceLocationAllocator, + interaction_elements: &RangeChecksInteractionElements, + interaction_claim: &RangeChecksInteractionClaim, + ) -> Self { + let rc_11_component = range_check_11::Component::new( + tree_span_provider, + range_check_11::Eval::new(interaction_elements.rc_11.clone()), + (interaction_claim.rc_11.claimed_sum, None), + ); + let rc_12_component = range_check_12::Component::new( + tree_span_provider, + range_check_12::Eval::new(interaction_elements.rc_12.clone()), + (interaction_claim.rc_12.claimed_sum, None), + ); + let rc_18_component = range_check_18::Component::new( + tree_span_provider, + range_check_18::Eval::new(interaction_elements.rc_18.clone()), + (interaction_claim.rc_18.claimed_sum, None), + ); + let rc_19_component = range_check_19::Component::new( + tree_span_provider, + range_check_19::Eval::new(interaction_elements.rc_19.clone()), + (interaction_claim.rc_19.claimed_sum, None), + ); + let rc_3_6_component = range_check_3_6::Component::new( + tree_span_provider, + range_check_3_6::Eval::new(interaction_elements.rc_3_6.clone()), + (interaction_claim.rc_3_6.claimed_sum, None), + ); + let rc_4_3_component = range_check_4_3::Component::new( + tree_span_provider, + range_check_4_3::Eval::new(interaction_elements.rc_4_3.clone()), + (interaction_claim.rc_4_3.claimed_sum, None), + ); + let rc_9_9_component = range_check_9_9::Component::new( + tree_span_provider, + range_check_9_9::Eval::new(interaction_elements.rc_9_9.clone()), + (interaction_claim.rc_9_9.claimed_sum, None), + ); + let rc_7_2_5_component = range_check_7_2_5::Component::new( + tree_span_provider, + range_check_7_2_5::Eval::new(interaction_elements.rc_7_2_5.clone()), + (interaction_claim.rc_7_2_5.claimed_sum, None), + ); + let rc_3_6_6_3_component = range_check_3_6_6_3::Component::new( + tree_span_provider, + range_check_3_6_6_3::Eval::new(interaction_elements.rc_3_6_6_3.clone()), + (interaction_claim.rc_3_6_6_3.claimed_sum, None), + ); + Self { + rc_11: rc_11_component, + rc_12: rc_12_component, + rc_18: rc_18_component, + rc_19: rc_19_component, + rc_3_6: rc_3_6_component, + rc_4_3: rc_4_3_component, + rc_9_9: rc_9_9_component, + rc_7_2_5: rc_7_2_5_component, + rc_3_6_6_3: rc_3_6_6_3_component, + } + } + + pub fn provers(&self) -> Vec<&dyn ComponentProver> { + vec![ + &self.rc_11 as &dyn ComponentProver, + &self.rc_12 as &dyn ComponentProver, + &self.rc_18 as &dyn ComponentProver, + &self.rc_19 as &dyn ComponentProver, + &self.rc_3_6 as &dyn ComponentProver, + &self.rc_4_3 as &dyn ComponentProver, + &self.rc_9_9 as &dyn ComponentProver, + &self.rc_7_2_5 as &dyn ComponentProver, + &self.rc_3_6_6_3 as &dyn ComponentProver, + ] + } +} + +impl std::fmt::Display for RangeChecksComponents { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!( + f, + "RangeCheck11: {}", + indented_component_display(&self.rc_11) + )?; + writeln!( + f, + "RangeCheck12: {}", + indented_component_display(&self.rc_12) + )?; + writeln!( + f, + "RangeCheck18: {}", + indented_component_display(&self.rc_18) + )?; + writeln!( + f, + "RangeCheck19: {}", + indented_component_display(&self.rc_19) + )?; + writeln!( + f, + "RangeCheck3_6: {}", + indented_component_display(&self.rc_3_6) + )?; + writeln!( + f, + "RangeCheck4_3: {}", + indented_component_display(&self.rc_4_3) + )?; + writeln!( + f, + "RangeCheck9_9: {}", + indented_component_display(&self.rc_9_9) + )?; + writeln!( + f, + "RangeCheck7_2_5: {}", + indented_component_display(&self.rc_7_2_5) + )?; + writeln!( + f, + "RangeCheck3_6_6_3: {}", + indented_component_display(&self.rc_3_6_6_3) + )?; + Ok(()) + } +} diff --git a/stwo_cairo_prover/crates/prover/src/components/mod.rs b/stwo_cairo_prover/crates/prover/src/components/mod.rs index 7cfe048f1..6b16d046c 100644 --- a/stwo_cairo_prover/crates/prover/src/components/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/components/mod.rs @@ -22,6 +22,7 @@ pub mod jump_opcode_rel; pub mod jump_opcode_rel_imm; pub mod memory; pub mod range_check_builtin_bits_128; +pub mod range_check_builtin_bits_96; pub mod range_check_vector; pub mod ret_opcode; pub mod utils; diff --git a/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/component.rs b/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/component.rs new file mode 100644 index 000000000..2ac96ebe6 --- /dev/null +++ b/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/component.rs @@ -0,0 +1,145 @@ +#![allow(non_camel_case_types)] +#![allow(unused_imports)] +use num_traits::{One, Zero}; +use serde::{Deserialize, Serialize}; +use stwo_cairo_serialize::CairoSerialize; +use stwo_prover::constraint_framework::logup::{LogupAtRow, LogupSums, LookupElements}; +use stwo_prover::constraint_framework::{ + EvalAtRow, FrameworkComponent, FrameworkEval, RelationEntry, +}; +use stwo_prover::core::backend::simd::m31::LOG_N_LANES; +use stwo_prover::core::channel::Channel; +use stwo_prover::core::fields::m31::M31; +use stwo_prover::core::fields::qm31::SecureField; +use stwo_prover::core::fields::secure_column::SECURE_EXTENSION_DEGREE; +use stwo_prover::core::pcs::TreeVec; + +use crate::cairo_air::preprocessed::{PreProcessedColumn, Seq}; +use crate::relations; + +pub struct Eval { + pub claim: Claim, + pub memory_address_to_id_lookup_elements: relations::MemoryAddressToId, + pub memory_id_to_big_lookup_elements: relations::MemoryIdToBig, + pub range_check_6_lookup_elements: relations::RangeCheck_6, +} + +#[derive(Copy, Clone, Serialize, Deserialize, CairoSerialize)] +pub struct Claim { + pub log_size: u32, + pub range_check96_builtin_segment_start: u32, +} +impl Claim { + pub fn new(log_size: u32, range_check96_builtin_segment_start: u32) -> Self { + Self { + log_size, + range_check96_builtin_segment_start, + } + } + + pub fn log_sizes(&self) -> TreeVec> { + let log_size = self.log_size; + let trace_log_sizes = vec![log_size; 12]; + let interaction_log_sizes = vec![log_size; SECURE_EXTENSION_DEGREE * 2]; + let preprocessed_log_sizes = vec![log_size]; + TreeVec::new(vec![ + preprocessed_log_sizes, + trace_log_sizes, + interaction_log_sizes, + ]) + } + + pub fn mix_into(&self, channel: &mut impl Channel) { + channel.mix_u64(self.log_size as u64); + channel.mix_u64(self.range_check96_builtin_segment_start as u64); + } +} + +#[derive(Copy, Clone, Serialize, Deserialize, CairoSerialize)] +pub struct InteractionClaim { + pub logup_sums: LogupSums, +} +impl InteractionClaim { + pub fn mix_into(&self, channel: &mut impl Channel) { + let (total_sum, claimed_sum) = self.logup_sums; + channel.mix_felts(&[total_sum]); + if let Some(claimed_sum) = claimed_sum { + channel.mix_felts(&[claimed_sum.0]); + channel.mix_u64(claimed_sum.1 as u64); + } + } +} + +pub type Component = FrameworkComponent; + +impl FrameworkEval for Eval { + fn log_size(&self) -> u32 { + self.claim.log_size + } + + fn max_constraint_log_degree_bound(&self) -> u32 { + self.log_size() + 1 + } + + #[allow(unused_parens)] + #[allow(clippy::double_parens)] + #[allow(non_snake_case)] + fn evaluate(&self, mut eval: E) -> E { + let seq = + eval.get_preprocessed_column(PreProcessedColumn::Seq(Seq::new(self.log_size())).id()); + let value_id_col0 = eval.next_trace_mask(); + let value_limb_0_col1 = eval.next_trace_mask(); + let value_limb_1_col2 = eval.next_trace_mask(); + let value_limb_2_col3 = eval.next_trace_mask(); + let value_limb_3_col4 = eval.next_trace_mask(); + let value_limb_4_col5 = eval.next_trace_mask(); + let value_limb_5_col6 = eval.next_trace_mask(); + let value_limb_6_col7 = eval.next_trace_mask(); + let value_limb_7_col8 = eval.next_trace_mask(); + let value_limb_8_col9 = eval.next_trace_mask(); + let value_limb_9_col10 = eval.next_trace_mask(); + let value_limb_10_col11 = eval.next_trace_mask(); + + // Read Positive Num Bits 96. + + eval.add_to_relation(RelationEntry::new( + &self.memory_address_to_id_lookup_elements, + E::EF::one(), + &[ + (E::F::from(M31::from(self.claim.range_check96_builtin_segment_start)) + + seq.clone()), + value_id_col0.clone(), + ], + )); + + // Range Check Last Limb Bits In Ms Limb 6. + + eval.add_to_relation(RelationEntry::new( + &self.range_check_6_lookup_elements, + E::EF::one(), + &[value_limb_10_col11.clone()], + )); + + eval.add_to_relation(RelationEntry::new( + &self.memory_id_to_big_lookup_elements, + E::EF::one(), + &[ + value_id_col0.clone(), + value_limb_0_col1.clone(), + value_limb_1_col2.clone(), + value_limb_2_col3.clone(), + value_limb_3_col4.clone(), + value_limb_4_col5.clone(), + value_limb_5_col6.clone(), + value_limb_6_col7.clone(), + value_limb_7_col8.clone(), + value_limb_8_col9.clone(), + value_limb_9_col10.clone(), + value_limb_10_col11.clone(), + ], + )); + + eval.finalize_logup_in_pairs(); + eval + } +} diff --git a/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/mod.rs b/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/mod.rs new file mode 100644 index 000000000..6a1bf6635 --- /dev/null +++ b/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/mod.rs @@ -0,0 +1,5 @@ +pub mod component; +pub mod prover; + +pub use component::{Claim, Component, Eval, InteractionClaim}; +pub use prover::{ClaimGenerator, InteractionClaimGenerator}; diff --git a/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/prover.rs b/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/prover.rs new file mode 100644 index 000000000..e88bb5581 --- /dev/null +++ b/stwo_cairo_prover/crates/prover/src/components/range_check_builtin_bits_96/prover.rs @@ -0,0 +1,265 @@ +#![allow(unused_parens)] +#![allow(unused_imports)] +use std::iter::zip; + +use itertools::{chain, zip_eq, Itertools}; +use num_traits::{One, Zero}; +use prover_types::cpu::*; +use prover_types::simd::*; +use rayon::iter::{ + IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator, ParallelIterator, +}; +use stwo_air_utils::trace::component_trace::ComponentTrace; +use stwo_air_utils_derive::{IterMut, ParIterMut, Uninitialized}; +use stwo_prover::constraint_framework::logup::LogupTraceGenerator; +use stwo_prover::constraint_framework::Relation; +use stwo_prover::core::air::Component; +use stwo_prover::core::backend::simd::column::BaseColumn; +use stwo_prover::core::backend::simd::conversion::Unpack; +use stwo_prover::core::backend::simd::m31::{PackedM31, LOG_N_LANES, N_LANES}; +use stwo_prover::core::backend::simd::qm31::PackedQM31; +use stwo_prover::core::backend::simd::SimdBackend; +use stwo_prover::core::backend::{BackendForChannel, Col, Column}; +use stwo_prover::core::channel::{Channel, MerkleChannel}; +use stwo_prover::core::fields::m31::M31; +use stwo_prover::core::fields::FieldExpOps; +use stwo_prover::core::pcs::TreeBuilder; +use stwo_prover::core::poly::circle::{CanonicCoset, CircleEvaluation}; +use stwo_prover::core::poly::BitReversedOrder; +use stwo_prover::core::utils::{ + bit_reverse_coset_to_circle_domain_order, bit_reverse_index, coset_index_to_circle_domain_index, +}; + +use super::component::{Claim, InteractionClaim}; +use crate::cairo_air::preprocessed::{PreProcessedColumn, Seq}; +use crate::components::{memory_address_to_id, memory_id_to_big, range_check_6}; +use crate::relations; + +const N_TRACE_COLUMNS: usize = 12; + +#[derive(Default)] +pub struct ClaimGenerator { + pub log_size: u32, + pub range_check96_builtin_segment_start: u32, +} +impl ClaimGenerator { + pub fn new(log_size: u32, range_check96_builtin_segment_start: u32) -> Self { + assert_ne!(log_size, 0); + Self { + // TODO(Gali): Remove once air-infra pads to LOG_N_LANES. + log_size: std::cmp::max(log_size, LOG_N_LANES), + range_check96_builtin_segment_start, + } + } + + pub fn write_trace( + self, + tree_builder: &mut TreeBuilder<'_, '_, SimdBackend, MC>, + memory_address_to_id_state: &memory_address_to_id::ClaimGenerator, + memory_id_to_big_state: &memory_id_to_big::ClaimGenerator, + range_check_6_state: &range_check_6::ClaimGenerator, + ) -> (Claim, InteractionClaimGenerator) + where + SimdBackend: BackendForChannel, + { + let log_size = self.log_size; + + let (trace, lookup_data) = write_trace_simd( + log_size, + memory_address_to_id_state, + memory_id_to_big_state, + range_check_6_state, + self.range_check96_builtin_segment_start, + ); + + tree_builder.extend_evals(trace.to_evals()); + + ( + Claim { + log_size, + range_check96_builtin_segment_start: self.range_check96_builtin_segment_start, + }, + InteractionClaimGenerator { + log_size, + lookup_data, + }, + ) + } +} + +#[allow(clippy::clone_on_copy)] +#[allow(clippy::useless_conversion)] +#[allow(unused_variables)] +#[allow(clippy::double_parens)] +#[allow(non_snake_case)] +fn write_trace_simd( + log_size: u32, + memory_address_to_id_state: &memory_address_to_id::ClaimGenerator, + memory_id_to_big_state: &memory_id_to_big::ClaimGenerator, + range_check_6_state: &range_check_6::ClaimGenerator, + range_check96_builtin_segment_start: u32, +) -> (ComponentTrace, LookupData) { + let log_n_packed_rows = log_size - LOG_N_LANES; + let (mut trace, mut lookup_data) = unsafe { + ( + ComponentTrace::::uninitialized(log_size), + LookupData::uninitialized(log_n_packed_rows), + ) + }; + + let M31_0 = PackedM31::broadcast(M31::from(0)); + + trace + .par_iter_mut() + .enumerate() + .zip(lookup_data.par_iter_mut()) + .for_each(|((row_index, row), lookup_data)| { + let seq = PreProcessedColumn::Seq(Seq::new(log_size)).packed_at(row_index); + + // Read Positive Num Bits 96. + + let memory_address_to_id_value_tmp_fd7ee_0 = memory_address_to_id_state.deduce_output( + ((PackedM31::broadcast(M31::from(range_check96_builtin_segment_start))) + + (seq.clone())), + ); + let memory_id_to_big_value_tmp_fd7ee_1 = + memory_id_to_big_state.deduce_output(memory_address_to_id_value_tmp_fd7ee_0); + let value_id_col0 = memory_address_to_id_value_tmp_fd7ee_0; + *row[0] = value_id_col0; + let memory_address_to_id_inputs_0 = + ((PackedM31::broadcast(M31::from(range_check96_builtin_segment_start))) + + (seq.clone())) + .unpack(); + *lookup_data.memory_address_to_id_0 = [ + ((PackedM31::broadcast(M31::from(range_check96_builtin_segment_start))) + + (seq.clone())), + value_id_col0, + ]; + let value_limb_0_col1 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(0); + *row[1] = value_limb_0_col1; + let value_limb_1_col2 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(1); + *row[2] = value_limb_1_col2; + let value_limb_2_col3 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(2); + *row[3] = value_limb_2_col3; + let value_limb_3_col4 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(3); + *row[4] = value_limb_3_col4; + let value_limb_4_col5 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(4); + *row[5] = value_limb_4_col5; + let value_limb_5_col6 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(5); + *row[6] = value_limb_5_col6; + let value_limb_6_col7 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(6); + *row[7] = value_limb_6_col7; + let value_limb_7_col8 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(7); + *row[8] = value_limb_7_col8; + let value_limb_8_col9 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(8); + *row[9] = value_limb_8_col9; + let value_limb_9_col10 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(9); + *row[10] = value_limb_9_col10; + let value_limb_10_col11 = memory_id_to_big_value_tmp_fd7ee_1.get_m31(10); + *row[11] = value_limb_10_col11; + + // Range Check Last Limb Bits In Ms Limb 6. + + let range_check_6_inputs_0 = [value_limb_10_col11].unpack(); + *lookup_data.range_check_6_0 = [value_limb_10_col11]; + + let memory_id_to_big_inputs_0 = value_id_col0.unpack(); + *lookup_data.memory_id_to_big_0 = [ + value_id_col0, + value_limb_0_col1, + value_limb_1_col2, + value_limb_2_col3, + value_limb_3_col4, + value_limb_4_col5, + value_limb_5_col6, + value_limb_6_col7, + value_limb_7_col8, + value_limb_8_col9, + value_limb_9_col10, + value_limb_10_col11, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + M31_0, + ]; + + // Add sub-components inputs. + #[allow(clippy::needless_range_loop)] + for i in 0..N_LANES { + memory_address_to_id_state.add_input(&memory_address_to_id_inputs_0[i]); + range_check_6_state.add_input(&range_check_6_inputs_0[i]); + memory_id_to_big_state.add_input(&memory_id_to_big_inputs_0[i]); + } + }); + + (trace, lookup_data) +} + +#[derive(Uninitialized, IterMut, ParIterMut)] +struct LookupData { + memory_address_to_id_0: Vec<[PackedM31; 2]>, + memory_id_to_big_0: Vec<[PackedM31; 29]>, + range_check_6_0: Vec<[PackedM31; 1]>, +} + +pub struct InteractionClaimGenerator { + log_size: u32, + lookup_data: LookupData, +} +impl InteractionClaimGenerator { + pub fn write_interaction_trace( + self, + tree_builder: &mut TreeBuilder<'_, '_, SimdBackend, MC>, + memory_address_to_id: &relations::MemoryAddressToId, + memory_id_to_big: &relations::MemoryIdToBig, + range_check_6: &relations::RangeCheck_6, + ) -> InteractionClaim + where + SimdBackend: BackendForChannel, + { + let log_size = self.log_size; + let mut logup_gen = LogupTraceGenerator::new(log_size); + + // Sum logup terms in pairs. + let mut col_gen = logup_gen.new_col(); + for (i, (values0, values1)) in zip( + &self.lookup_data.memory_address_to_id_0, + &self.lookup_data.range_check_6_0, + ) + .enumerate() + { + let denom0: PackedQM31 = memory_address_to_id.combine(values0); + let denom1: PackedQM31 = range_check_6.combine(values1); + col_gen.write_frac(i, denom0 + denom1, denom0 * denom1); + } + col_gen.finalize_col(); + + // Sum last logup term. + let mut col_gen = logup_gen.new_col(); + for (i, values) in self.lookup_data.memory_id_to_big_0.iter().enumerate() { + let denom = memory_id_to_big.combine(values); + col_gen.write_frac(i, PackedQM31::one(), denom); + } + col_gen.finalize_col(); + + let (trace, claimed_sum) = logup_gen.finalize_last(); + tree_builder.extend_evals(trace); + + InteractionClaim { + logup_sums: (claimed_sum, None), + } + } +} diff --git a/stwo_cairo_prover/crates/prover/src/components/range_check_vector/mod.rs b/stwo_cairo_prover/crates/prover/src/components/range_check_vector/mod.rs index a5b666c4d..eb36f7dca 100644 --- a/stwo_cairo_prover/crates/prover/src/components/range_check_vector/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/components/range_check_vector/mod.rs @@ -66,12 +66,16 @@ macro_rules! generate_range_check_code { }; } -generate_range_check_code!([19]); +generate_range_check_code!([6]); generate_range_check_code!([11]); +generate_range_check_code!([12]); +generate_range_check_code!([18]); +generate_range_check_code!([19]); +generate_range_check_code!([3, 6]); +generate_range_check_code!([4, 3]); generate_range_check_code!([9, 9]); generate_range_check_code!([7, 2, 5]); -generate_range_check_code!([4, 3]); -generate_range_check_code!([6]); +generate_range_check_code!([3, 6, 6, 3]); #[cfg(test)] mod tests { diff --git a/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs b/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs index f8125bcb9..07fcafa8e 100644 --- a/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs @@ -24,12 +24,38 @@ use crate::input::memory::MemoryBuilder; pub enum VmImportError { #[error("IO error: {0}")] Io(#[from] IoErrorWithPath), + + #[cfg(not(feature = "std"))] #[error("JSON error: {0}")] Json(#[from] serde_json::Error), + + #[cfg(feature = "std")] + #[error("JSON error: {0}")] + Json(#[from] sonic_rs::Error), #[error("No memory segments")] NoMemorySegments, } +fn deserialize_inputs<'a>( + public_input_string: &'a str, + private_input_string: &'a str, +) -> Result<(PublicInput<'a>, PrivateInput), VmImportError> { + #[cfg(feature = "std")] + { + Ok(( + sonic_rs::from_str(public_input_string)?, + sonic_rs::from_str(private_input_string)?, + )) + } + #[cfg(not(feature = "std"))] + { + Ok(( + serde_json::from_str(public_input_string)?, + serde_json::from_str(private_input_string)?, + )) + } +} + // TODO(Ohad): remove dev_mode after adding the rest of the instructions. /// Adapts the VM's output files to the Cairo input of the prover. pub fn adapt_vm_output( @@ -38,10 +64,13 @@ pub fn adapt_vm_output( dev_mode: bool, ) -> Result { let _span = span!(Level::INFO, "adapt_vm_output").entered(); - let public_input_string = read_to_string(public_input_json)?; - let public_input: PublicInput<'_> = serde_json::from_str(&public_input_string)?; - let private_input: PrivateInput = serde_json::from_reader(&open_file(private_input_json)?)?; + let (public_input_string, private_input_string) = ( + read_to_string(public_input_json)?, + read_to_string(private_input_json)?, + ); + let (public_input, private_input) = + deserialize_inputs(&public_input_string, &private_input_string)?; let end_addr = public_input .memory_segments diff --git a/stwo_cairo_prover/crates/prover/src/relations/mod.rs b/stwo_cairo_prover/crates/prover/src/relations/mod.rs index f1924f6f3..41685e376 100644 --- a/stwo_cairo_prover/crates/prover/src/relations/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/relations/mod.rs @@ -6,9 +6,12 @@ relation!(MemoryIdToBig, 29); relation!(Opcodes, 3); relation!(RangeCheck_6, 1); relation!(RangeCheck_11, 1); +relation!(RangeCheck_12, 1); relation!(RangeCheck_18, 1); relation!(RangeCheck_19, 1); -relation!(RangeCheck_9_9, 2); +relation!(RangeCheck_3_6, 2); relation!(RangeCheck_4_3, 2); +relation!(RangeCheck_9_9, 2); relation!(RangeCheck_7_2_5, 3); +relation!(RangeCheck_3_6_6_3, 4); relation!(VerifyInstruction, 29); diff --git a/stwo_cairo_prover/crates/recursion_bridge/src/proof_generation/mod.rs b/stwo_cairo_prover/crates/recursion_bridge/src/proof_generation/mod.rs index 0347dab5c..bfe6ede39 100644 --- a/stwo_cairo_prover/crates/recursion_bridge/src/proof_generation/mod.rs +++ b/stwo_cairo_prover/crates/recursion_bridge/src/proof_generation/mod.rs @@ -5,6 +5,7 @@ mod tests { use cairo_lang_casm::casm; use stwo_cairo_prover::cairo_air::{prove_cairo, verify_cairo, ProverConfig}; use stwo_cairo_prover::input::plain::input_from_plain_casm_with_step_limit; + use stwo_prover::core::pcs::PcsConfig; use stwo_prover::core::vcs::blake2_merkle::Blake2sMerkleChannel; pub fn project_root() -> PathBuf { @@ -21,11 +22,16 @@ mod tests { .instructions; let input = input_from_plain_casm_with_step_limit(instructions, 14); - let proof = prove_cairo::(input, ProverConfig::default()).unwrap(); + let proof = prove_cairo::( + input, + ProverConfig::default(), + PcsConfig::default(), + ) + .unwrap(); let path = project_root().join("artifacts/jrl0_proof.json"); std::fs::write(path, serde_json::to_string(&proof).unwrap()).unwrap(); - verify_cairo::(proof).unwrap(); + verify_cairo::(proof, PcsConfig::default()).unwrap(); } } diff --git a/stwo_cairo_prover/crates/run_and_prove/src/main.rs b/stwo_cairo_prover/crates/run_and_prove/src/main.rs index e487b4eec..6d73b07e8 100644 --- a/stwo_cairo_prover/crates/run_and_prove/src/main.rs +++ b/stwo_cairo_prover/crates/run_and_prove/src/main.rs @@ -9,6 +9,7 @@ use stwo_cairo_prover::input::plain::adapt_finished_runner; use stwo_cairo_prover::input::vm_import::VmImportError; use stwo_cairo_utils::binary_utils::run_binary; use stwo_cairo_utils::vm_utils::{run_vm, VmArgs, VmError}; +use stwo_prover::core::pcs::PcsConfig; use stwo_prover::core::prover::ProvingError; use stwo_prover::core::vcs::blake2_merkle::Blake2sMerkleChannel; use thiserror::Error; @@ -76,12 +77,13 @@ fn run(args: impl Iterator) -> Result<(), Error> { ); // TODO(Ohad): Propagate hash from CLI args. - let proof = prove_cairo::(cairo_input, prover_config)?; + let proof = + prove_cairo::(cairo_input, prover_config, PcsConfig::default())?; std::fs::write(args.proof_path, serde_json::to_string(&proof)?)?; if args.verify { - verify_cairo::(proof)?; + verify_cairo::(proof, PcsConfig::default())?; log::info!("Proof verified successfully"); }