diff --git a/stwo_cairo_prover/crates/cairo-air/src/air.rs b/stwo_cairo_prover/crates/cairo-air/src/air.rs deleted file mode 100644 index 9a17abedd6..0000000000 --- a/stwo_cairo_prover/crates/cairo-air/src/air.rs +++ /dev/null @@ -1,1012 +0,0 @@ -use std::collections::HashMap; - -use itertools::{chain, Itertools}; -use num_traits::Zero; -use serde::{Deserialize, Serialize}; -use stwo::core::air::Component; -use stwo::core::channel::Channel; -use stwo::core::fields::m31::M31; -use stwo::core::fields::qm31::{SecureField, QM31}; -use stwo::core::fields::FieldExpOps; -use stwo::core::pcs::TreeVec; -use stwo::core::proof::StarkProof; -use stwo::core::vcs::MerkleHasher; -use stwo::prover::backend::simd::SimdBackend; -use stwo::prover::ComponentProver; -use stwo_cairo_common::prover_types::cpu::CasmState; -use stwo_cairo_common::prover_types::felt::split_f252; -use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; -use stwo_constraint_framework::preprocessed_columns::PreProcessedColumnId; -use stwo_constraint_framework::{Relation, TraceLocationAllocator}; - -use super::blake::air::{BlakeContextClaim, BlakeContextComponents, BlakeContextInteractionClaim}; -use super::builtins_air::{BuiltinComponents, BuiltinsClaim, BuiltinsInteractionClaim}; -use super::components::indented_component_display; -use super::opcodes_air::{OpcodeClaim, OpcodeComponents, OpcodeInteractionClaim}; -use super::pedersen::air::{ - PedersenContextClaim, PedersenContextComponents, PedersenContextInteractionClaim, -}; -use super::poseidon::air::{ - PoseidonContextClaim, PoseidonContextComponents, PoseidonContextInteractionClaim, -}; -use super::range_checks_air::{ - RangeChecksClaim, RangeChecksComponents, RangeChecksInteractionClaim, - RangeChecksInteractionElements, -}; -use crate::components::{ - memory_address_to_id, memory_id_to_big, verify_bitwise_xor_4, verify_bitwise_xor_7, - verify_bitwise_xor_8, verify_bitwise_xor_8_b, verify_bitwise_xor_9, verify_instruction, -}; -use crate::relations; -use crate::verifier::RelationUse; - -#[derive(Serialize, Deserialize)] -pub struct CairoProof { - pub claim: CairoClaim, - pub interaction_pow: u64, - pub interaction_claim: CairoInteractionClaim, - pub stark_proof: StarkProof, - /// Optional salt used in the channel initialization. - pub channel_salt: Option, -} - -impl CairoSerialize for CairoProof -where - H::Hash: CairoSerialize, -{ - fn serialize(&self, output: &mut Vec) { - let Self { - claim, - interaction_pow, - interaction_claim, - stark_proof, - channel_salt, - } = self; - CairoSerialize::serialize(claim, output); - CairoSerialize::serialize(interaction_pow, output); - CairoSerialize::serialize(interaction_claim, output); - CairoSerialize::serialize(stark_proof, output); - CairoSerialize::serialize(channel_salt, output); - } -} - -impl CairoDeserialize for CairoProof -where - H::Hash: CairoDeserialize, -{ - fn deserialize<'a>(data: &mut impl Iterator) -> Self { - let claim = CairoDeserialize::deserialize(data); - let interaction_pow = CairoDeserialize::deserialize(data); - let interaction_claim = CairoDeserialize::deserialize(data); - let stark_proof = CairoDeserialize::deserialize(data); - let channel_salt = CairoDeserialize::deserialize(data); - Self { - claim, - interaction_pow, - interaction_claim, - stark_proof, - channel_salt, - } - } -} - -pub type RelationUsesDict = HashMap<&'static str, u64>; - -/// Accumulates the number of uses of each relation in a map. -pub fn accumulate_relation_uses( - relation_uses: &mut RelationUsesDict, - relation_uses_per_row: [RelationUse; N], - log_size: u32, -) { - let component_size = 1 << log_size; - for relation_use in relation_uses_per_row { - let relation_uses_in_component = relation_use.uses.checked_mul(component_size).unwrap(); - let prev = relation_uses.entry(relation_use.relation_id).or_insert(0); - *prev = prev.checked_add(relation_uses_in_component).unwrap(); - } -} - -#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] -pub struct CairoClaim { - pub public_data: PublicData, - pub opcodes: OpcodeClaim, - pub verify_instruction: verify_instruction::Claim, - pub blake_context: BlakeContextClaim, - pub builtins: BuiltinsClaim, - pub pedersen_context: PedersenContextClaim, - pub poseidon_context: PoseidonContextClaim, - pub memory_address_to_id: memory_address_to_id::Claim, - pub memory_id_to_value: memory_id_to_big::Claim, - pub range_checks: RangeChecksClaim, - pub verify_bitwise_xor_4: verify_bitwise_xor_4::Claim, - pub verify_bitwise_xor_7: verify_bitwise_xor_7::Claim, - pub verify_bitwise_xor_8: verify_bitwise_xor_8::Claim, - pub verify_bitwise_xor_8_b: verify_bitwise_xor_8_b::Claim, - pub verify_bitwise_xor_9: verify_bitwise_xor_9::Claim, - // ... -} - -impl CairoClaim { - pub fn mix_into(&self, channel: &mut impl Channel) { - let Self { - public_data, - opcodes, - verify_instruction, - blake_context, - builtins, - pedersen_context, - poseidon_context, - memory_address_to_id, - memory_id_to_value, - range_checks, - verify_bitwise_xor_4, - verify_bitwise_xor_7, - verify_bitwise_xor_8, - verify_bitwise_xor_8_b, - verify_bitwise_xor_9, - } = self; - public_data.mix_into(channel); - opcodes.mix_into(channel); - verify_instruction.mix_into(channel); - blake_context.mix_into(channel); - builtins.mix_into(channel); - pedersen_context.mix_into(channel); - poseidon_context.mix_into(channel); - memory_address_to_id.mix_into(channel); - memory_id_to_value.mix_into(channel); - range_checks.mix_into(channel); - verify_bitwise_xor_4.mix_into(channel); - verify_bitwise_xor_7.mix_into(channel); - verify_bitwise_xor_8.mix_into(channel); - verify_bitwise_xor_8_b.mix_into(channel); - verify_bitwise_xor_9.mix_into(channel); - } - - /// Returns the log sizes of the components. - /// Does not include the preprocessed trace log sizes. - pub fn log_sizes(&self) -> TreeVec> { - let log_sizes_list = vec![ - self.opcodes.log_sizes(), - self.verify_instruction.log_sizes(), - self.blake_context.log_sizes(), - self.builtins.log_sizes(), - self.pedersen_context.log_sizes(), - self.poseidon_context.log_sizes(), - self.memory_address_to_id.log_sizes(), - self.memory_id_to_value.log_sizes(), - self.range_checks.log_sizes(), - self.verify_bitwise_xor_4.log_sizes(), - self.verify_bitwise_xor_7.log_sizes(), - self.verify_bitwise_xor_8.log_sizes(), - self.verify_bitwise_xor_8_b.log_sizes(), - self.verify_bitwise_xor_9.log_sizes(), - ]; - - TreeVec::concat_cols(log_sizes_list.into_iter()) - } - - pub fn accumulate_relation_uses(&self, relation_uses: &mut RelationUsesDict) { - let Self { - public_data: _, - opcodes, - verify_instruction, - blake_context, - builtins, - pedersen_context, - poseidon_context, - memory_address_to_id: _, - memory_id_to_value, - range_checks: _, - verify_bitwise_xor_4: _, - verify_bitwise_xor_7: _, - verify_bitwise_xor_8: _, - verify_bitwise_xor_8_b: _, - verify_bitwise_xor_9: _, - } = self; - // NOTE: The following components do not USE relations: - // - range_checks - // - verify_bitwise_xor_* - // - memory_address_to_id - - opcodes.accumulate_relation_uses(relation_uses); - builtins.accumulate_relation_uses(relation_uses); - blake_context.accumulate_relation_uses(relation_uses); - pedersen_context.accumulate_relation_uses(relation_uses); - poseidon_context.accumulate_relation_uses(relation_uses); - accumulate_relation_uses( - relation_uses, - verify_instruction::RELATION_USES_PER_ROW, - verify_instruction.log_size, - ); - - // TODO(ShaharS): Look into the file name of memory_id_to_big. - // memory_id_to_value has a big value component and a small value component. - for &log_size in &memory_id_to_value.big_log_sizes { - accumulate_relation_uses( - relation_uses, - memory_id_to_big::RELATION_USES_PER_ROW_BIG, - log_size, - ); - } - accumulate_relation_uses( - relation_uses, - memory_id_to_big::RELATION_USES_PER_ROW_SMALL, - memory_id_to_value.small_log_size, - ); - } -} - -#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] -pub struct PublicData { - pub public_memory: PublicMemory, - pub initial_state: CasmState, - pub final_state: CasmState, -} -impl PublicData { - /// Sums the logup of the public data. - pub fn logup_sum(&self, lookup_elements: &CairoInteractionElements) -> QM31 { - let mut values_to_inverse = vec![]; - // Use public memory in the memory relations. - self.public_memory - .get_entries( - self.initial_state.pc.0, - self.initial_state.ap.0, - self.final_state.ap.0, - ) - .for_each(|(addr, id, val)| { - values_to_inverse.push( - >::combine( - &lookup_elements.memory_address_to_id, - &[M31::from_u32_unchecked(addr), M31::from_u32_unchecked(id)], - ), - ); - values_to_inverse.push(>::combine( - &lookup_elements.memory_id_to_value, - &[ - [M31::from_u32_unchecked(id)].as_slice(), - split_f252(val).as_slice(), - ] - .concat(), - )); - }); - - // Yield initial state and use the final. - values_to_inverse.push(>::combine( - &lookup_elements.opcodes, - &self.final_state.values(), - )); - values_to_inverse.push(->::combine( - &lookup_elements.opcodes, - &self.initial_state.values(), - )); - - let inverted_values = QM31::batch_inverse(&values_to_inverse); - inverted_values.iter().sum::() - } - - pub fn mix_into(&self, channel: &mut impl Channel) { - let Self { - public_memory, - initial_state, - final_state, - } = self; - public_memory.mix_into(channel); - initial_state.mix_into(channel); - final_state.mix_into(channel); - } -} - -// TODO(alonf) Change all the obscure types and structs to a meaningful struct system for the -// memory. -#[derive(Clone, Debug, Serialize, Deserialize, Copy, CairoSerialize, CairoDeserialize)] -pub struct MemorySmallValue { - pub id: u32, - pub value: u32, -} -impl MemorySmallValue { - pub fn mix_into(&self, channel: &mut impl Channel) { - channel.mix_u64(self.id as u64); - channel.mix_u64(self.value as u64); - } -} - -// TODO(alonf): Change this into a struct. Remove Pub prefix. -// (id, value) -pub type PubMemoryValue = (u32, [u32; 8]); - -// TODO(alonf): Change this into a struct. Remove Pub prefix. -// (address, id, value) -pub type PubMemoryEntry = (u32, u32, [u32; 8]); - -#[derive(Clone, Debug, Serialize, Deserialize, Copy, CairoSerialize, CairoDeserialize)] -pub struct SegmentRange { - pub start_ptr: MemorySmallValue, - pub stop_ptr: MemorySmallValue, -} - -impl SegmentRange { - pub fn is_empty(&self) -> bool { - self.start_ptr.value == self.stop_ptr.value - } - - pub fn mix_into(&self, channel: &mut impl Channel) { - self.start_ptr.mix_into(channel); - self.stop_ptr.mix_into(channel); - } -} - -#[derive(Clone, Debug, Serialize, Deserialize, Copy)] -pub struct PublicSegmentRanges { - pub output: SegmentRange, - pub pedersen: Option, - pub range_check_128: Option, - pub ecdsa: Option, - pub bitwise: Option, - pub ec_op: Option, - pub keccak: Option, - pub poseidon: Option, - pub range_check_96: Option, - pub add_mod: Option, - pub mul_mod: Option, -} - -/// Same as PublicSegmentRanges, but with all segments present, this serialization of the struct is -/// used by the Cairo1 verifier. -#[derive(Clone, Debug, Serialize, Deserialize, Copy, CairoSerialize, CairoDeserialize)] -pub struct FullSegmentRanges { - pub output: SegmentRange, - pub pedersen: SegmentRange, - pub range_check_128: SegmentRange, - pub ecdsa: SegmentRange, - pub bitwise: SegmentRange, - pub ec_op: SegmentRange, - pub keccak: SegmentRange, - pub poseidon: SegmentRange, - pub range_check_96: SegmentRange, - pub add_mod: SegmentRange, - pub mul_mod: SegmentRange, -} - -// The Cairo1 verifier currently requires all the segments to be present. -impl CairoSerialize for PublicSegmentRanges { - fn serialize(&self, serialized: &mut Vec) { - let Self { - output, - pedersen, - range_check_128, - ecdsa, - bitwise, - ec_op, - keccak, - poseidon, - range_check_96, - add_mod, - mul_mod, - } = self; - - CairoSerialize::serialize( - &FullSegmentRanges { - output: *output, - pedersen: pedersen.unwrap(), - range_check_128: range_check_128.unwrap(), - ecdsa: ecdsa.unwrap(), - bitwise: bitwise.unwrap(), - ec_op: ec_op.unwrap(), - keccak: keccak.unwrap(), - poseidon: poseidon.unwrap(), - range_check_96: range_check_96.unwrap(), - add_mod: add_mod.unwrap(), - mul_mod: mul_mod.unwrap(), - }, - serialized, - ); - } -} - -impl CairoDeserialize for PublicSegmentRanges { - fn deserialize<'a>(data: &mut impl Iterator) -> Self { - let FullSegmentRanges { - output, - pedersen, - range_check_128, - ecdsa, - bitwise, - ec_op, - keccak, - poseidon, - range_check_96, - add_mod, - mul_mod, - } = CairoDeserialize::deserialize(data); - - Self { - output, - pedersen: Some(pedersen), - range_check_128: Some(range_check_128), - ecdsa: Some(ecdsa), - bitwise: Some(bitwise), - ec_op: Some(ec_op), - keccak: Some(keccak), - poseidon: Some(poseidon), - range_check_96: Some(range_check_96), - add_mod: Some(add_mod), - mul_mod: Some(mul_mod), - } - } -} - -impl PublicSegmentRanges { - pub fn memory_entries( - &self, - initial_ap: u32, - final_ap: u32, - ) -> impl Iterator { - let segments = self.present_segments(); - - let n_segments = segments.len() as u32; - - segments - .into_iter() - .enumerate() - .flat_map( - move |( - i, - SegmentRange { - start_ptr, - stop_ptr, - }, - )| { - let start_address = initial_ap + i as u32; - let stop_address = final_ap - n_segments + i as u32; - [ - (start_address, start_ptr.id, start_ptr.value), - (stop_address, stop_ptr.id, stop_ptr.value), - ] - }, - ) - .map(|(addr, id, value)| (addr, id, [value, 0, 0, 0, 0, 0, 0, 0])) - } - - pub fn mix_into(&self, channel: &mut impl Channel) { - for segment in self.present_segments() { - segment.mix_into(channel); - } - } - - pub fn present_segments(&self) -> Vec { - let Self { - output, - pedersen, - range_check_128, - ecdsa, - bitwise, - ec_op, - keccak, - poseidon, - range_check_96, - add_mod, - mul_mod, - } = *self; - vec![ - Some(output), - pedersen, - range_check_128, - ecdsa, - bitwise, - ec_op, - keccak, - poseidon, - range_check_96, - add_mod, - mul_mod, - ] - .into_iter() - .flatten() - .collect_vec() - } -} - -pub type MemorySection = Vec; - -#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] -pub struct PublicMemory { - pub program: MemorySection, - pub public_segments: PublicSegmentRanges, - pub output: MemorySection, - pub safe_call_ids: [u32; 2], -} - -impl PublicMemory { - /// Returns [`PubMemoryEntry`] for all public memory. - pub fn get_entries( - &self, - initial_pc: u32, - initial_ap: u32, - final_ap: u32, - ) -> impl Iterator { - let [program, output] = - [&self.program, &self.output].map(|section| section.clone().into_iter().enumerate()); - let program_iter = program.map(move |(i, (id, value))| (initial_pc + i as u32, id, value)); - let output_iter = output.map(move |(i, (id, value))| (final_ap + i as u32, id, value)); - - let [safe_call_id0, safe_call_id1] = self.safe_call_ids; - // The safe call area should be [initial_fp, 0] and initial_fp should be the same as - // initial_ap. - let safe_call_iter = [ - ( - initial_ap - 2, - safe_call_id0, - [initial_ap, 0, 0, 0, 0, 0, 0, 0], - ), - (initial_ap - 1, safe_call_id1, [0, 0, 0, 0, 0, 0, 0, 0]), - ]; - let segment_ranges_iter = self.public_segments.memory_entries(initial_ap, final_ap); - - program_iter - .chain(safe_call_iter) - .chain(segment_ranges_iter) - .chain(output_iter) - } - - pub fn mix_into(&self, channel: &mut impl Channel) { - let Self { - program, - public_segments, - output, - safe_call_ids, - } = self; - - // Mix program memory section. All the ids are mixed first, then all the values, each of - // them in the order it appears in the section. - channel.mix_u32s(&program.iter().map(|(id, _)| *id).collect_vec()); - channel.mix_u32s(&program.iter().flat_map(|(_, value)| *value).collect_vec()); - - // Mix public segments. - public_segments.mix_into(channel); - - // Mix output memory section. All the ids are mixed first, then all the values, each of them - // in the order it appears in the section. - channel.mix_u32s(&output.iter().map(|(id, _)| *id).collect_vec()); - channel.mix_u32s(&output.iter().flat_map(|(_, value)| *value).collect_vec()); - - // Mix safe_ids memory section. - for id in safe_call_ids { - channel.mix_u64(*id as u64); - } - } -} - -pub struct CairoInteractionElements { - pub opcodes: relations::Opcodes, - pub verify_instruction: relations::VerifyInstruction, - pub blake_round: relations::BlakeRound, - pub blake_g: relations::BlakeG, - pub blake_sigma: relations::BlakeRoundSigma, - pub triple_xor_32: relations::TripleXor32, - pub partial_ec_mul: relations::PartialEcMul, - pub pedersen_points_table: relations::PedersenPointsTable, - pub poseidon_3_partial_rounds_chain: relations::Poseidon3PartialRoundsChain, - pub poseidon_full_round_chain: relations::PoseidonFullRoundChain, - pub cube_252: relations::Cube252, - pub poseidon_round_keys: relations::PoseidonRoundKeys, - pub range_check_252_width_27: relations::RangeCheck252Width27, - pub memory_address_to_id: relations::MemoryAddressToId, - pub memory_id_to_value: relations::MemoryIdToBig, - pub range_checks: RangeChecksInteractionElements, - pub verify_bitwise_xor_4: relations::VerifyBitwiseXor_4, - pub verify_bitwise_xor_7: relations::VerifyBitwiseXor_7, - pub verify_bitwise_xor_8: relations::VerifyBitwiseXor_8, - pub verify_bitwise_xor_8_b: relations::VerifyBitwiseXor_8_B, - pub verify_bitwise_xor_9: relations::VerifyBitwiseXor_9, - pub verify_bitwise_xor_12: relations::VerifyBitwiseXor_12, -} -impl CairoInteractionElements { - pub fn draw(channel: &mut impl Channel) -> CairoInteractionElements { - CairoInteractionElements { - opcodes: relations::Opcodes::draw(channel), - verify_instruction: relations::VerifyInstruction::draw(channel), - blake_round: relations::BlakeRound::draw(channel), - blake_g: relations::BlakeG::draw(channel), - blake_sigma: relations::BlakeRoundSigma::draw(channel), - triple_xor_32: relations::TripleXor32::draw(channel), - poseidon_3_partial_rounds_chain: relations::Poseidon3PartialRoundsChain::draw(channel), - poseidon_full_round_chain: relations::PoseidonFullRoundChain::draw(channel), - cube_252: relations::Cube252::draw(channel), - poseidon_round_keys: relations::PoseidonRoundKeys::draw(channel), - range_check_252_width_27: relations::RangeCheck252Width27::draw(channel), - partial_ec_mul: relations::PartialEcMul::draw(channel), - pedersen_points_table: relations::PedersenPointsTable::draw(channel), - memory_address_to_id: relations::MemoryAddressToId::draw(channel), - memory_id_to_value: relations::MemoryIdToBig::draw(channel), - range_checks: RangeChecksInteractionElements::draw(channel), - verify_bitwise_xor_4: relations::VerifyBitwiseXor_4::draw(channel), - verify_bitwise_xor_7: relations::VerifyBitwiseXor_7::draw(channel), - verify_bitwise_xor_8: relations::VerifyBitwiseXor_8::draw(channel), - verify_bitwise_xor_8_b: relations::VerifyBitwiseXor_8_B::draw(channel), - verify_bitwise_xor_9: relations::VerifyBitwiseXor_9::draw(channel), - verify_bitwise_xor_12: relations::VerifyBitwiseXor_12::draw(channel), - } - } -} - -#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] -pub struct CairoInteractionClaim { - pub opcodes: OpcodeInteractionClaim, - pub verify_instruction: verify_instruction::InteractionClaim, - pub blake_context: BlakeContextInteractionClaim, - pub builtins: BuiltinsInteractionClaim, - pub pedersen_context: PedersenContextInteractionClaim, - pub poseidon_context: PoseidonContextInteractionClaim, - pub memory_address_to_id: memory_address_to_id::InteractionClaim, - pub memory_id_to_value: memory_id_to_big::InteractionClaim, - pub range_checks: RangeChecksInteractionClaim, - pub verify_bitwise_xor_4: verify_bitwise_xor_4::InteractionClaim, - pub verify_bitwise_xor_7: verify_bitwise_xor_7::InteractionClaim, - pub verify_bitwise_xor_8: verify_bitwise_xor_8::InteractionClaim, - pub verify_bitwise_xor_8_b: verify_bitwise_xor_8_b::InteractionClaim, - pub verify_bitwise_xor_9: verify_bitwise_xor_9::InteractionClaim, -} -impl CairoInteractionClaim { - pub fn mix_into(&self, channel: &mut impl Channel) { - self.opcodes.mix_into(channel); - self.verify_instruction.mix_into(channel); - self.blake_context.mix_into(channel); - self.builtins.mix_into(channel); - self.pedersen_context.mix_into(channel); - self.poseidon_context.mix_into(channel); - self.memory_address_to_id.mix_into(channel); - self.memory_id_to_value.mix_into(channel); - self.range_checks.mix_into(channel); - self.verify_bitwise_xor_4.mix_into(channel); - self.verify_bitwise_xor_7.mix_into(channel); - self.verify_bitwise_xor_8.mix_into(channel); - self.verify_bitwise_xor_8_b.mix_into(channel); - self.verify_bitwise_xor_9.mix_into(channel); - } -} - -pub fn lookup_sum( - claim: &CairoClaim, - elements: &CairoInteractionElements, - interaction_claim: &CairoInteractionClaim, -) -> SecureField { - let mut sum = QM31::zero(); - sum += claim.public_data.logup_sum(elements); - - // If the table is padded, take the sum of the non-padded values. - // Otherwise, the claimed_sum is the total_sum. - sum += interaction_claim.opcodes.sum(); - sum += interaction_claim.verify_instruction.claimed_sum; - sum += interaction_claim.blake_context.sum(); - sum += interaction_claim.builtins.sum(); - sum += interaction_claim.pedersen_context.sum(); - sum += interaction_claim.poseidon_context.sum(); - sum += interaction_claim.memory_address_to_id.claimed_sum; - sum += interaction_claim.memory_id_to_value.claimed_sum(); - sum += interaction_claim.range_checks.sum(); - sum += interaction_claim.verify_bitwise_xor_4.claimed_sum; - sum += interaction_claim.verify_bitwise_xor_7.claimed_sum; - sum += interaction_claim.verify_bitwise_xor_8.claimed_sum; - sum += interaction_claim.verify_bitwise_xor_8_b.claimed_sum; - sum += interaction_claim.verify_bitwise_xor_9.claimed_sum; - - sum -} - -pub struct CairoComponents { - pub opcodes: OpcodeComponents, - pub verify_instruction: verify_instruction::Component, - pub blake_context: BlakeContextComponents, - pub builtins: BuiltinComponents, - pub pedersen_context: PedersenContextComponents, - pub poseidon_context: PoseidonContextComponents, - pub memory_address_to_id: memory_address_to_id::Component, - pub memory_id_to_value: ( - Vec, - memory_id_to_big::SmallComponent, - ), - pub range_checks: RangeChecksComponents, - pub verify_bitwise_xor_4: verify_bitwise_xor_4::Component, - pub verify_bitwise_xor_7: verify_bitwise_xor_7::Component, - pub verify_bitwise_xor_8: verify_bitwise_xor_8::Component, - pub verify_bitwise_xor_8_b: verify_bitwise_xor_8_b::Component, - pub verify_bitwise_xor_9: verify_bitwise_xor_9::Component, - // ... -} -impl CairoComponents { - pub fn new( - cairo_claim: &CairoClaim, - interaction_elements: &CairoInteractionElements, - interaction_claim: &CairoInteractionClaim, - // Describes the structure of the preprocessed trace. Sensitive to order. - preprocessed_column_ids: &[PreProcessedColumnId], - ) -> Self { - let tree_span_provider = - &mut TraceLocationAllocator::new_with_preprocessed_columns(preprocessed_column_ids); - - let opcode_components = OpcodeComponents::new( - tree_span_provider, - &cairo_claim.opcodes, - interaction_elements, - &interaction_claim.opcodes, - ); - - let verify_instruction_component = verify_instruction::Component::new( - tree_span_provider, - verify_instruction::Eval { - claim: cairo_claim.verify_instruction, - memory_address_to_id_lookup_elements: interaction_elements - .memory_address_to_id - .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_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, - ); - - let blake_context = BlakeContextComponents::new( - tree_span_provider, - &cairo_claim.blake_context, - interaction_elements, - &interaction_claim.blake_context, - ); - let builtin_components = BuiltinComponents::new( - tree_span_provider, - &cairo_claim.builtins, - interaction_elements, - &interaction_claim.builtins, - ); - let pedersen_context = PedersenContextComponents::new( - tree_span_provider, - &cairo_claim.pedersen_context, - interaction_elements, - &interaction_claim.pedersen_context, - ); - let poseidon_context = PoseidonContextComponents::new( - tree_span_provider, - &cairo_claim.poseidon_context, - interaction_elements, - &interaction_claim.poseidon_context, - ); - let memory_address_to_id_component = memory_address_to_id::Component::new( - tree_span_provider, - memory_address_to_id::Eval::new( - cairo_claim.memory_address_to_id.clone(), - interaction_elements.memory_address_to_id.clone(), - ), - interaction_claim.memory_address_to_id.clone().claimed_sum, - ); - - let memory_id_to_value_components = memory_id_to_big::big_components_from_claim( - &cairo_claim.memory_id_to_value.big_log_sizes, - &interaction_claim.memory_id_to_value.big_claimed_sums, - &interaction_elements.memory_id_to_value, - &interaction_elements.range_checks.rc_9_9, - &interaction_elements.range_checks.rc_9_9_b, - &interaction_elements.range_checks.rc_9_9_c, - &interaction_elements.range_checks.rc_9_9_d, - &interaction_elements.range_checks.rc_9_9_e, - &interaction_elements.range_checks.rc_9_9_f, - &interaction_elements.range_checks.rc_9_9_g, - &interaction_elements.range_checks.rc_9_9_h, - tree_span_provider, - ); - let small_memory_id_to_value_component = memory_id_to_big::SmallComponent::new( - tree_span_provider, - memory_id_to_big::SmallEval::new( - cairo_claim.memory_id_to_value.clone(), - interaction_elements.memory_id_to_value.clone(), - interaction_elements.range_checks.rc_9_9.clone(), - interaction_elements.range_checks.rc_9_9_b.clone(), - interaction_elements.range_checks.rc_9_9_c.clone(), - interaction_elements.range_checks.rc_9_9_d.clone(), - ), - interaction_claim - .memory_id_to_value - .clone() - .small_claimed_sum, - ); - let range_checks_component = RangeChecksComponents::new( - tree_span_provider, - &interaction_elements.range_checks, - &interaction_claim.range_checks, - ); - let verify_bitwise_xor_4_component = verify_bitwise_xor_4::Component::new( - tree_span_provider, - verify_bitwise_xor_4::Eval { - claim: cairo_claim.verify_bitwise_xor_4, - verify_bitwise_xor_4_lookup_elements: interaction_elements - .verify_bitwise_xor_4 - .clone(), - }, - interaction_claim.verify_bitwise_xor_4.claimed_sum, - ); - let verify_bitwise_xor_7_component = verify_bitwise_xor_7::Component::new( - tree_span_provider, - verify_bitwise_xor_7::Eval { - claim: cairo_claim.verify_bitwise_xor_7, - verify_bitwise_xor_7_lookup_elements: interaction_elements - .verify_bitwise_xor_7 - .clone(), - }, - interaction_claim.verify_bitwise_xor_7.claimed_sum, - ); - let verify_bitwise_xor_8_component = verify_bitwise_xor_8::Component::new( - tree_span_provider, - verify_bitwise_xor_8::Eval { - claim: cairo_claim.verify_bitwise_xor_8, - verify_bitwise_xor_8_lookup_elements: interaction_elements - .verify_bitwise_xor_8 - .clone(), - }, - interaction_claim.verify_bitwise_xor_8.claimed_sum, - ); - let verify_bitwise_xor_8_b_component = verify_bitwise_xor_8_b::Component::new( - tree_span_provider, - verify_bitwise_xor_8_b::Eval { - claim: cairo_claim.verify_bitwise_xor_8_b, - verify_bitwise_xor_8_b_lookup_elements: interaction_elements - .verify_bitwise_xor_8_b - .clone(), - }, - interaction_claim.verify_bitwise_xor_8_b.claimed_sum, - ); - let verify_bitwise_xor_9_component = verify_bitwise_xor_9::Component::new( - tree_span_provider, - verify_bitwise_xor_9::Eval { - claim: cairo_claim.verify_bitwise_xor_9, - verify_bitwise_xor_9_lookup_elements: interaction_elements - .verify_bitwise_xor_9 - .clone(), - }, - interaction_claim.verify_bitwise_xor_9.claimed_sum, - ); - Self { - opcodes: opcode_components, - verify_instruction: verify_instruction_component, - blake_context, - builtins: builtin_components, - pedersen_context, - poseidon_context, - memory_address_to_id: memory_address_to_id_component, - memory_id_to_value: ( - memory_id_to_value_components, - small_memory_id_to_value_component, - ), - range_checks: range_checks_component, - verify_bitwise_xor_4: verify_bitwise_xor_4_component, - verify_bitwise_xor_7: verify_bitwise_xor_7_component, - verify_bitwise_xor_8: verify_bitwise_xor_8_component, - verify_bitwise_xor_8_b: verify_bitwise_xor_8_b_component, - verify_bitwise_xor_9: verify_bitwise_xor_9_component, - } - } - - pub fn provers(&self) -> Vec<&dyn ComponentProver> { - chain!( - self.opcodes.provers(), - [&self.verify_instruction as &dyn ComponentProver,], - self.blake_context.provers(), - self.builtins.provers(), - self.pedersen_context.provers(), - self.poseidon_context.provers(), - [&self.memory_address_to_id as &dyn ComponentProver,], - self.memory_id_to_value - .0 - .iter() - .map(|component| component as &dyn ComponentProver), - [&self.memory_id_to_value.1 as &dyn ComponentProver,], - self.range_checks.provers(), - [ - &self.verify_bitwise_xor_4 as &dyn ComponentProver, - &self.verify_bitwise_xor_7 as &dyn ComponentProver, - &self.verify_bitwise_xor_8 as &dyn ComponentProver, - &self.verify_bitwise_xor_8_b as &dyn ComponentProver, - &self.verify_bitwise_xor_9 as &dyn ComponentProver, - ] - ) - .collect() - } - - pub fn components(&self) -> Vec<&dyn Component> { - self.provers() - .into_iter() - .map(|component| component as &dyn Component) - .collect() - } -} - -impl std::fmt::Display for CairoComponents { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "CairoComponents")?; - writeln!(f, "Opcodes: {}", self.opcodes)?; - writeln!( - f, - "VerifyInstruction: {}", - indented_component_display(&self.verify_instruction) - )?; - writeln!(f, "BlakeContext: {}", self.blake_context)?; - writeln!(f, "Builtins: {}", self.builtins)?; - writeln!(f, "PedersenContext: {}", self.pedersen_context)?; - writeln!(f, "PoseidonContext: {}", self.poseidon_context)?; - writeln!( - f, - "MemoryAddressToId: {}", - indented_component_display(&self.memory_address_to_id) - )?; - for component in &self.memory_id_to_value.0 { - writeln!( - f, - "MemoryIdToValue: {}", - indented_component_display(component) - )?; - } - writeln!( - f, - "SmallMemoryIdToValue: {}", - indented_component_display(&self.memory_id_to_value.1) - )?; - writeln!(f, "RangeChecks: {}", self.range_checks)?; - writeln!( - f, - "VerifyBitwiseXor4: {}", - indented_component_display(&self.verify_bitwise_xor_4) - )?; - writeln!( - f, - "VerifyBitwiseXor7: {}", - indented_component_display(&self.verify_bitwise_xor_7) - )?; - writeln!( - f, - "VerifyBitwiseXor8: {}", - indented_component_display(&self.verify_bitwise_xor_8) - )?; - writeln!( - f, - "VerifyBitwiseXor8B: {}", - indented_component_display(&self.verify_bitwise_xor_8_b) - )?; - writeln!( - f, - "VerifyBitwiseXor9: {}", - indented_component_display(&self.verify_bitwise_xor_9) - )?; - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use crate::air::accumulate_relation_uses; - use crate::verifier::RelationUse; - - #[test] - fn test_accumulate_relation_uses() { - let mut relation_uses = HashMap::from([("relation_1", 4), ("relation_2", 10)]); - let log_size = 2; - let relation_uses_per_row = [ - RelationUse { - relation_id: "relation_1", - uses: 2, - }, - RelationUse { - relation_id: "relation_2", - uses: 4, - }, - ]; - - accumulate_relation_uses(&mut relation_uses, relation_uses_per_row, log_size); - - assert_eq!(relation_uses.len(), 2); - assert_eq!(relation_uses.get("relation_1"), Some(&12)); - assert_eq!(relation_uses.get("relation_2"), Some(&26)); - } -} diff --git a/stwo_cairo_prover/crates/cairo-air/src/blake/air.rs b/stwo_cairo_prover/crates/cairo-air/src/blake/air.rs index ab92de133b..4143ac1a50 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/blake/air.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/blake/air.rs @@ -8,7 +8,8 @@ use stwo::prover::ComponentProver; use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; use stwo_constraint_framework::TraceLocationAllocator; -use crate::air::{accumulate_relation_uses, CairoInteractionElements, RelationUsesDict}; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::cairo_claim::{accumulate_relation_uses, RelationUsesDict}; use crate::components::{ blake_g, blake_round, blake_round_sigma, triple_xor_32, verify_bitwise_xor_12, }; diff --git a/stwo_cairo_prover/crates/cairo-air/src/builtins_air.rs b/stwo_cairo_prover/crates/cairo-air/src/builtins_air.rs index 8dd89de989..7e65bdc8bf 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/builtins_air.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/builtins_air.rs @@ -9,8 +9,8 @@ use stwo::prover::ComponentProver; use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; use stwo_constraint_framework::TraceLocationAllocator; -use super::air::CairoInteractionElements; -use crate::air::{accumulate_relation_uses, RelationUsesDict}; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::cairo_claim::{accumulate_relation_uses, RelationUsesDict}; use crate::components::{ add_mod_builtin, bitwise_builtin, indented_component_display, mul_mod_builtin, pedersen_builtin, poseidon_builtin, range_check_builtin_bits_128, range_check_builtin_bits_96, diff --git a/stwo_cairo_prover/crates/cairo-air/src/cairo_claim.rs b/stwo_cairo_prover/crates/cairo-air/src/cairo_claim.rs new file mode 100644 index 0000000000..173e19c6e0 --- /dev/null +++ b/stwo_cairo_prover/crates/cairo-air/src/cairo_claim.rs @@ -0,0 +1,194 @@ +use stwo::core::channel::Channel; +use stwo::core::pcs::TreeVec; +use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; +use serde::{Deserialize, Serialize}; + +use crate::blake::air::BlakeContextClaim; +use crate::builtins_air::BuiltinsClaim; +use std::collections::HashMap; +use crate::verifier::RelationUse; +use crate::public_data::PublicData; +use crate::components::{ + memory_address_to_id, memory_id_to_big, verify_bitwise_xor_4, verify_bitwise_xor_7, + verify_bitwise_xor_8, verify_bitwise_xor_8_b, verify_bitwise_xor_9, verify_instruction, +}; +use crate::opcodes_air::OpcodeClaim; +use crate::pedersen::air::PedersenContextClaim; +use crate::poseidon::air::PoseidonContextClaim; +use crate::range_checks_air::RangeChecksClaim; + +#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] +pub struct CairoClaim { + pub public_data: PublicData, + pub opcodes: OpcodeClaim, + pub verify_instruction: verify_instruction::Claim, + pub blake_context: BlakeContextClaim, + pub builtins: BuiltinsClaim, + pub pedersen_context: PedersenContextClaim, + pub poseidon_context: PoseidonContextClaim, + pub memory_address_to_id: memory_address_to_id::Claim, + pub memory_id_to_value: memory_id_to_big::Claim, + pub range_checks: RangeChecksClaim, + pub verify_bitwise_xor_4: verify_bitwise_xor_4::Claim, + pub verify_bitwise_xor_7: verify_bitwise_xor_7::Claim, + pub verify_bitwise_xor_8: verify_bitwise_xor_8::Claim, + pub verify_bitwise_xor_8_b: verify_bitwise_xor_8_b::Claim, + pub verify_bitwise_xor_9: verify_bitwise_xor_9::Claim, + // ... +} + +impl CairoClaim { + pub fn mix_into(&self, channel: &mut impl Channel) { + let Self { + public_data, + opcodes, + verify_instruction, + blake_context, + builtins, + pedersen_context, + poseidon_context, + memory_address_to_id, + memory_id_to_value, + range_checks, + verify_bitwise_xor_4, + verify_bitwise_xor_7, + verify_bitwise_xor_8, + verify_bitwise_xor_8_b, + verify_bitwise_xor_9, + } = self; + public_data.mix_into(channel); + opcodes.mix_into(channel); + verify_instruction.mix_into(channel); + blake_context.mix_into(channel); + builtins.mix_into(channel); + pedersen_context.mix_into(channel); + poseidon_context.mix_into(channel); + memory_address_to_id.mix_into(channel); + memory_id_to_value.mix_into(channel); + range_checks.mix_into(channel); + verify_bitwise_xor_4.mix_into(channel); + verify_bitwise_xor_7.mix_into(channel); + verify_bitwise_xor_8.mix_into(channel); + verify_bitwise_xor_8_b.mix_into(channel); + verify_bitwise_xor_9.mix_into(channel); + } + + /// Returns the log sizes of the components. + /// Does not include the preprocessed trace log sizes. + pub fn log_sizes(&self) -> TreeVec> { + let log_sizes_list = vec![ + self.opcodes.log_sizes(), + self.verify_instruction.log_sizes(), + self.blake_context.log_sizes(), + self.builtins.log_sizes(), + self.pedersen_context.log_sizes(), + self.poseidon_context.log_sizes(), + self.memory_address_to_id.log_sizes(), + self.memory_id_to_value.log_sizes(), + self.range_checks.log_sizes(), + self.verify_bitwise_xor_4.log_sizes(), + self.verify_bitwise_xor_7.log_sizes(), + self.verify_bitwise_xor_8.log_sizes(), + self.verify_bitwise_xor_8_b.log_sizes(), + self.verify_bitwise_xor_9.log_sizes(), + ]; + + TreeVec::concat_cols(log_sizes_list.into_iter()) + } + + pub fn accumulate_relation_uses(&self, relation_uses: &mut RelationUsesDict) { + let Self { + public_data: _, + opcodes, + verify_instruction, + blake_context, + builtins, + pedersen_context, + poseidon_context, + memory_address_to_id: _, + memory_id_to_value, + range_checks: _, + verify_bitwise_xor_4: _, + verify_bitwise_xor_7: _, + verify_bitwise_xor_8: _, + verify_bitwise_xor_8_b: _, + verify_bitwise_xor_9: _, + } = self; + // NOTE: The following components do not USE relations: + // - range_checks + // - verify_bitwise_xor_* + // - memory_address_to_id + + opcodes.accumulate_relation_uses(relation_uses); + builtins.accumulate_relation_uses(relation_uses); + blake_context.accumulate_relation_uses(relation_uses); + pedersen_context.accumulate_relation_uses(relation_uses); + poseidon_context.accumulate_relation_uses(relation_uses); + accumulate_relation_uses( + relation_uses, + verify_instruction::RELATION_USES_PER_ROW, + verify_instruction.log_size, + ); + + // TODO(ShaharS): Look into the file name of memory_id_to_big. + // memory_id_to_value has a big value component and a small value component. + for &log_size in &memory_id_to_value.big_log_sizes { + accumulate_relation_uses( + relation_uses, + memory_id_to_big::RELATION_USES_PER_ROW_BIG, + log_size, + ); + } + accumulate_relation_uses( + relation_uses, + memory_id_to_big::RELATION_USES_PER_ROW_SMALL, + memory_id_to_value.small_log_size, + ); + } +} + +pub type RelationUsesDict = HashMap<&'static str, u64>; + +/// Accumulates the number of uses of each relation in a map. +pub fn accumulate_relation_uses( + relation_uses: &mut RelationUsesDict, + relation_uses_per_row: [RelationUse; N], + log_size: u32, +) { + let component_size = 1 << log_size; + for relation_use in relation_uses_per_row { + let relation_uses_in_component = relation_use.uses.checked_mul(component_size).unwrap(); + let prev = relation_uses.entry(relation_use.relation_id).or_insert(0); + *prev = prev.checked_add(relation_uses_in_component).unwrap(); + } +} + + +#[cfg(test)] +mod tests { + use std::collections::HashMap; + use super::accumulate_relation_uses; + use crate::verifier::RelationUse; + + #[test] + fn test_accumulate_relation_uses() { + let mut relation_uses = HashMap::from([("relation_1", 4), ("relation_2", 10)]); + let log_size = 2; + let relation_uses_per_row = [ + RelationUse { + relation_id: "relation_1", + uses: 2, + }, + RelationUse { + relation_id: "relation_2", + uses: 4, + }, + ]; + + accumulate_relation_uses(&mut relation_uses, relation_uses_per_row, log_size); + + assert_eq!(relation_uses.len(), 2); + assert_eq!(relation_uses.get("relation_1"), Some(&12)); + assert_eq!(relation_uses.get("relation_2"), Some(&26)); + } +} \ No newline at end of file diff --git a/stwo_cairo_prover/crates/cairo-air/src/cairo_components.rs b/stwo_cairo_prover/crates/cairo-air/src/cairo_components.rs new file mode 100644 index 0000000000..e6db99d193 --- /dev/null +++ b/stwo_cairo_prover/crates/cairo-air/src/cairo_components.rs @@ -0,0 +1,308 @@ +use itertools::chain; +use stwo::core::air::Component; +use stwo::prover::backend::simd::SimdBackend; +use stwo::prover::ComponentProver; +use stwo_constraint_framework::preprocessed_columns::PreProcessedColumnId; +use stwo_constraint_framework::TraceLocationAllocator; + +use crate::cairo_claim::CairoClaim; +use crate::cairo_interaction_claim::CairoInteractionClaim; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::components::{ + indented_component_display, memory_address_to_id, memory_id_to_big, verify_bitwise_xor_4, + verify_bitwise_xor_7, verify_bitwise_xor_8, verify_bitwise_xor_8_b, verify_bitwise_xor_9, + verify_instruction, +}; +use crate::opcodes_air::OpcodeComponents; +use crate::builtins_air::BuiltinComponents; +use crate::range_checks_air::RangeChecksComponents; +use crate::blake::air::BlakeContextComponents; +use crate::pedersen::air::PedersenContextComponents; +use crate::poseidon::air::PoseidonContextComponents; +pub struct CairoComponents { + pub opcodes: OpcodeComponents, + pub verify_instruction: verify_instruction::Component, + pub blake_context: BlakeContextComponents, + pub builtins: BuiltinComponents, + pub pedersen_context: PedersenContextComponents, + pub poseidon_context: PoseidonContextComponents, + pub memory_address_to_id: memory_address_to_id::Component, + pub memory_id_to_value: ( + Vec, + memory_id_to_big::SmallComponent, + ), + pub range_checks: RangeChecksComponents, + pub verify_bitwise_xor_4: verify_bitwise_xor_4::Component, + pub verify_bitwise_xor_7: verify_bitwise_xor_7::Component, + pub verify_bitwise_xor_8: verify_bitwise_xor_8::Component, + pub verify_bitwise_xor_8_b: verify_bitwise_xor_8_b::Component, + pub verify_bitwise_xor_9: verify_bitwise_xor_9::Component, + // ... +} +impl CairoComponents { + pub fn new( + cairo_claim: &CairoClaim, + interaction_elements: &CairoInteractionElements, + interaction_claim: &CairoInteractionClaim, + // Describes the structure of the preprocessed trace. Sensitive to order. + preprocessed_column_ids: &[PreProcessedColumnId], + ) -> Self { + let tree_span_provider = + &mut TraceLocationAllocator::new_with_preprocessed_columns(preprocessed_column_ids); + + let opcode_components = OpcodeComponents::new( + tree_span_provider, + &cairo_claim.opcodes, + interaction_elements, + &interaction_claim.opcodes, + ); + + let verify_instruction_component = verify_instruction::Component::new( + tree_span_provider, + verify_instruction::Eval { + claim: cairo_claim.verify_instruction, + memory_address_to_id_lookup_elements: interaction_elements + .memory_address_to_id + .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_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, + ); + + let blake_context = BlakeContextComponents::new( + tree_span_provider, + &cairo_claim.blake_context, + interaction_elements, + &interaction_claim.blake_context, + ); + let builtin_components = BuiltinComponents::new( + tree_span_provider, + &cairo_claim.builtins, + interaction_elements, + &interaction_claim.builtins, + ); + let pedersen_context = PedersenContextComponents::new( + tree_span_provider, + &cairo_claim.pedersen_context, + interaction_elements, + &interaction_claim.pedersen_context, + ); + let poseidon_context = PoseidonContextComponents::new( + tree_span_provider, + &cairo_claim.poseidon_context, + interaction_elements, + &interaction_claim.poseidon_context, + ); + let memory_address_to_id_component = memory_address_to_id::Component::new( + tree_span_provider, + memory_address_to_id::Eval::new( + cairo_claim.memory_address_to_id.clone(), + interaction_elements.memory_address_to_id.clone(), + ), + interaction_claim.memory_address_to_id.clone().claimed_sum, + ); + + let memory_id_to_value_components = memory_id_to_big::big_components_from_claim( + &cairo_claim.memory_id_to_value.big_log_sizes, + &interaction_claim.memory_id_to_value.big_claimed_sums, + &interaction_elements.memory_id_to_value, + &interaction_elements.range_checks.rc_9_9, + &interaction_elements.range_checks.rc_9_9_b, + &interaction_elements.range_checks.rc_9_9_c, + &interaction_elements.range_checks.rc_9_9_d, + &interaction_elements.range_checks.rc_9_9_e, + &interaction_elements.range_checks.rc_9_9_f, + &interaction_elements.range_checks.rc_9_9_g, + &interaction_elements.range_checks.rc_9_9_h, + tree_span_provider, + ); + let small_memory_id_to_value_component = memory_id_to_big::SmallComponent::new( + tree_span_provider, + memory_id_to_big::SmallEval::new( + cairo_claim.memory_id_to_value.clone(), + interaction_elements.memory_id_to_value.clone(), + interaction_elements.range_checks.rc_9_9.clone(), + interaction_elements.range_checks.rc_9_9_b.clone(), + interaction_elements.range_checks.rc_9_9_c.clone(), + interaction_elements.range_checks.rc_9_9_d.clone(), + ), + interaction_claim + .memory_id_to_value + .clone() + .small_claimed_sum, + ); + let range_checks_component = RangeChecksComponents::new( + tree_span_provider, + &interaction_elements.range_checks, + &interaction_claim.range_checks, + ); + let verify_bitwise_xor_4_component = verify_bitwise_xor_4::Component::new( + tree_span_provider, + verify_bitwise_xor_4::Eval { + claim: cairo_claim.verify_bitwise_xor_4, + verify_bitwise_xor_4_lookup_elements: interaction_elements + .verify_bitwise_xor_4 + .clone(), + }, + interaction_claim.verify_bitwise_xor_4.claimed_sum, + ); + let verify_bitwise_xor_7_component = verify_bitwise_xor_7::Component::new( + tree_span_provider, + verify_bitwise_xor_7::Eval { + claim: cairo_claim.verify_bitwise_xor_7, + verify_bitwise_xor_7_lookup_elements: interaction_elements + .verify_bitwise_xor_7 + .clone(), + }, + interaction_claim.verify_bitwise_xor_7.claimed_sum, + ); + let verify_bitwise_xor_8_component = verify_bitwise_xor_8::Component::new( + tree_span_provider, + verify_bitwise_xor_8::Eval { + claim: cairo_claim.verify_bitwise_xor_8, + verify_bitwise_xor_8_lookup_elements: interaction_elements + .verify_bitwise_xor_8 + .clone(), + }, + interaction_claim.verify_bitwise_xor_8.claimed_sum, + ); + let verify_bitwise_xor_8_b_component = verify_bitwise_xor_8_b::Component::new( + tree_span_provider, + verify_bitwise_xor_8_b::Eval { + claim: cairo_claim.verify_bitwise_xor_8_b, + verify_bitwise_xor_8_b_lookup_elements: interaction_elements + .verify_bitwise_xor_8_b + .clone(), + }, + interaction_claim.verify_bitwise_xor_8_b.claimed_sum, + ); + let verify_bitwise_xor_9_component = verify_bitwise_xor_9::Component::new( + tree_span_provider, + verify_bitwise_xor_9::Eval { + claim: cairo_claim.verify_bitwise_xor_9, + verify_bitwise_xor_9_lookup_elements: interaction_elements + .verify_bitwise_xor_9 + .clone(), + }, + interaction_claim.verify_bitwise_xor_9.claimed_sum, + ); + Self { + opcodes: opcode_components, + verify_instruction: verify_instruction_component, + blake_context, + builtins: builtin_components, + pedersen_context, + poseidon_context, + memory_address_to_id: memory_address_to_id_component, + memory_id_to_value: ( + memory_id_to_value_components, + small_memory_id_to_value_component, + ), + range_checks: range_checks_component, + verify_bitwise_xor_4: verify_bitwise_xor_4_component, + verify_bitwise_xor_7: verify_bitwise_xor_7_component, + verify_bitwise_xor_8: verify_bitwise_xor_8_component, + verify_bitwise_xor_8_b: verify_bitwise_xor_8_b_component, + verify_bitwise_xor_9: verify_bitwise_xor_9_component, + } + } + + pub fn provers(&self) -> Vec<&dyn ComponentProver> { + chain!( + self.opcodes.provers(), + [&self.verify_instruction as &dyn ComponentProver,], + self.blake_context.provers(), + self.builtins.provers(), + self.pedersen_context.provers(), + self.poseidon_context.provers(), + [&self.memory_address_to_id as &dyn ComponentProver,], + self.memory_id_to_value + .0 + .iter() + .map(|component| component as &dyn ComponentProver), + [&self.memory_id_to_value.1 as &dyn ComponentProver,], + self.range_checks.provers(), + [ + &self.verify_bitwise_xor_4 as &dyn ComponentProver, + &self.verify_bitwise_xor_7 as &dyn ComponentProver, + &self.verify_bitwise_xor_8 as &dyn ComponentProver, + &self.verify_bitwise_xor_8_b as &dyn ComponentProver, + &self.verify_bitwise_xor_9 as &dyn ComponentProver, + ] + ) + .collect() + } + + pub fn components(&self) -> Vec<&dyn Component> { + self.provers() + .into_iter() + .map(|component| component as &dyn Component) + .collect() + } +} + +impl std::fmt::Display for CairoComponents { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!(f, "CairoComponents")?; + writeln!(f, "Opcodes: {}", self.opcodes)?; + writeln!( + f, + "VerifyInstruction: {}", + indented_component_display(&self.verify_instruction) + )?; + writeln!(f, "BlakeContext: {}", self.blake_context)?; + writeln!(f, "Builtins: {}", self.builtins)?; + writeln!(f, "PedersenContext: {}", self.pedersen_context)?; + writeln!(f, "PoseidonContext: {}", self.poseidon_context)?; + writeln!( + f, + "MemoryAddressToId: {}", + indented_component_display(&self.memory_address_to_id) + )?; + for component in &self.memory_id_to_value.0 { + writeln!( + f, + "MemoryIdToValue: {}", + indented_component_display(component) + )?; + } + writeln!( + f, + "SmallMemoryIdToValue: {}", + indented_component_display(&self.memory_id_to_value.1) + )?; + writeln!(f, "RangeChecks: {}", self.range_checks)?; + writeln!( + f, + "VerifyBitwiseXor4: {}", + indented_component_display(&self.verify_bitwise_xor_4) + )?; + writeln!( + f, + "VerifyBitwiseXor7: {}", + indented_component_display(&self.verify_bitwise_xor_7) + )?; + writeln!( + f, + "VerifyBitwiseXor8: {}", + indented_component_display(&self.verify_bitwise_xor_8) + )?; + writeln!( + f, + "VerifyBitwiseXor8B: {}", + indented_component_display(&self.verify_bitwise_xor_8_b) + )?; + writeln!( + f, + "VerifyBitwiseXor9: {}", + indented_component_display(&self.verify_bitwise_xor_9) + )?; + Ok(()) + } +} diff --git a/stwo_cairo_prover/crates/cairo-air/src/cairo_interaction_claim.rs b/stwo_cairo_prover/crates/cairo-air/src/cairo_interaction_claim.rs new file mode 100644 index 0000000000..830e1f5034 --- /dev/null +++ b/stwo_cairo_prover/crates/cairo-air/src/cairo_interaction_claim.rs @@ -0,0 +1,82 @@ +use serde::{Deserialize, Serialize}; +use num_traits::Zero; +use stwo::core::channel::Channel; +use stwo::core::fields::qm31::{SecureField, QM31}; +use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; + +use crate::cairo_claim::CairoClaim; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::components::{ + memory_address_to_id, memory_id_to_big, verify_bitwise_xor_4, verify_bitwise_xor_7, + verify_bitwise_xor_8, verify_bitwise_xor_8_b, verify_bitwise_xor_9, verify_instruction, +}; +use crate::opcodes_air::OpcodeInteractionClaim; +use crate::blake::air::BlakeContextInteractionClaim; +use crate::builtins_air::BuiltinsInteractionClaim; +use crate::pedersen::air::PedersenContextInteractionClaim; +use crate::poseidon::air::PoseidonContextInteractionClaim; +use crate::range_checks_air::RangeChecksInteractionClaim; + +#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] +pub struct CairoInteractionClaim { + pub opcodes: OpcodeInteractionClaim, + pub verify_instruction: verify_instruction::InteractionClaim, + pub blake_context: BlakeContextInteractionClaim, + pub builtins: BuiltinsInteractionClaim, + pub pedersen_context: PedersenContextInteractionClaim, + pub poseidon_context: PoseidonContextInteractionClaim, + pub memory_address_to_id: memory_address_to_id::InteractionClaim, + pub memory_id_to_value: memory_id_to_big::InteractionClaim, + pub range_checks: RangeChecksInteractionClaim, + pub verify_bitwise_xor_4: verify_bitwise_xor_4::InteractionClaim, + pub verify_bitwise_xor_7: verify_bitwise_xor_7::InteractionClaim, + pub verify_bitwise_xor_8: verify_bitwise_xor_8::InteractionClaim, + pub verify_bitwise_xor_8_b: verify_bitwise_xor_8_b::InteractionClaim, + pub verify_bitwise_xor_9: verify_bitwise_xor_9::InteractionClaim, +} +impl CairoInteractionClaim { + pub fn mix_into(&self, channel: &mut impl Channel) { + self.opcodes.mix_into(channel); + self.verify_instruction.mix_into(channel); + self.blake_context.mix_into(channel); + self.builtins.mix_into(channel); + self.pedersen_context.mix_into(channel); + self.poseidon_context.mix_into(channel); + self.memory_address_to_id.mix_into(channel); + self.memory_id_to_value.mix_into(channel); + self.range_checks.mix_into(channel); + self.verify_bitwise_xor_4.mix_into(channel); + self.verify_bitwise_xor_7.mix_into(channel); + self.verify_bitwise_xor_8.mix_into(channel); + self.verify_bitwise_xor_8_b.mix_into(channel); + self.verify_bitwise_xor_9.mix_into(channel); + } +} + +pub fn lookup_sum( + claim: &CairoClaim, + elements: &CairoInteractionElements, + interaction_claim: &CairoInteractionClaim, +) -> SecureField { + let mut sum = QM31::zero(); + sum += claim.public_data.logup_sum(elements); + + // If the table is padded, take the sum of the non-padded values. + // Otherwise, the claimed_sum is the total_sum. + sum += interaction_claim.opcodes.sum(); + sum += interaction_claim.verify_instruction.claimed_sum; + sum += interaction_claim.blake_context.sum(); + sum += interaction_claim.builtins.sum(); + sum += interaction_claim.pedersen_context.sum(); + sum += interaction_claim.poseidon_context.sum(); + sum += interaction_claim.memory_address_to_id.claimed_sum; + sum += interaction_claim.memory_id_to_value.claimed_sum(); + sum += interaction_claim.range_checks.sum(); + sum += interaction_claim.verify_bitwise_xor_4.claimed_sum; + sum += interaction_claim.verify_bitwise_xor_7.claimed_sum; + sum += interaction_claim.verify_bitwise_xor_8.claimed_sum; + sum += interaction_claim.verify_bitwise_xor_8_b.claimed_sum; + sum += interaction_claim.verify_bitwise_xor_9.claimed_sum; + + sum +} diff --git a/stwo_cairo_prover/crates/cairo-air/src/cairo_interaction_elements.rs b/stwo_cairo_prover/crates/cairo-air/src/cairo_interaction_elements.rs new file mode 100644 index 0000000000..9077af0d31 --- /dev/null +++ b/stwo_cairo_prover/crates/cairo-air/src/cairo_interaction_elements.rs @@ -0,0 +1,56 @@ +use stwo::core::channel::Channel; + +use crate::range_checks_air::RangeChecksInteractionElements; +use crate::relations; +pub struct CairoInteractionElements { + pub opcodes: relations::Opcodes, + pub verify_instruction: relations::VerifyInstruction, + pub blake_round: relations::BlakeRound, + pub blake_g: relations::BlakeG, + pub blake_sigma: relations::BlakeRoundSigma, + pub triple_xor_32: relations::TripleXor32, + pub partial_ec_mul: relations::PartialEcMul, + pub pedersen_points_table: relations::PedersenPointsTable, + pub poseidon_3_partial_rounds_chain: relations::Poseidon3PartialRoundsChain, + pub poseidon_full_round_chain: relations::PoseidonFullRoundChain, + pub cube_252: relations::Cube252, + pub poseidon_round_keys: relations::PoseidonRoundKeys, + pub range_check_252_width_27: relations::RangeCheck252Width27, + pub memory_address_to_id: relations::MemoryAddressToId, + pub memory_id_to_value: relations::MemoryIdToBig, + pub range_checks: RangeChecksInteractionElements, + pub verify_bitwise_xor_4: relations::VerifyBitwiseXor_4, + pub verify_bitwise_xor_7: relations::VerifyBitwiseXor_7, + pub verify_bitwise_xor_8: relations::VerifyBitwiseXor_8, + pub verify_bitwise_xor_8_b: relations::VerifyBitwiseXor_8_B, + pub verify_bitwise_xor_9: relations::VerifyBitwiseXor_9, + pub verify_bitwise_xor_12: relations::VerifyBitwiseXor_12, +} +impl CairoInteractionElements { + pub fn draw(channel: &mut impl Channel) -> CairoInteractionElements { + CairoInteractionElements { + opcodes: relations::Opcodes::draw(channel), + verify_instruction: relations::VerifyInstruction::draw(channel), + blake_round: relations::BlakeRound::draw(channel), + blake_g: relations::BlakeG::draw(channel), + blake_sigma: relations::BlakeRoundSigma::draw(channel), + triple_xor_32: relations::TripleXor32::draw(channel), + poseidon_3_partial_rounds_chain: relations::Poseidon3PartialRoundsChain::draw(channel), + poseidon_full_round_chain: relations::PoseidonFullRoundChain::draw(channel), + cube_252: relations::Cube252::draw(channel), + poseidon_round_keys: relations::PoseidonRoundKeys::draw(channel), + range_check_252_width_27: relations::RangeCheck252Width27::draw(channel), + partial_ec_mul: relations::PartialEcMul::draw(channel), + pedersen_points_table: relations::PedersenPointsTable::draw(channel), + memory_address_to_id: relations::MemoryAddressToId::draw(channel), + memory_id_to_value: relations::MemoryIdToBig::draw(channel), + range_checks: RangeChecksInteractionElements::draw(channel), + verify_bitwise_xor_4: relations::VerifyBitwiseXor_4::draw(channel), + verify_bitwise_xor_7: relations::VerifyBitwiseXor_7::draw(channel), + verify_bitwise_xor_8: relations::VerifyBitwiseXor_8::draw(channel), + verify_bitwise_xor_8_b: relations::VerifyBitwiseXor_8_B::draw(channel), + verify_bitwise_xor_9: relations::VerifyBitwiseXor_9::draw(channel), + verify_bitwise_xor_12: relations::VerifyBitwiseXor_12::draw(channel), + } + } +} diff --git a/stwo_cairo_prover/crates/cairo-air/src/cairo_proof.rs b/stwo_cairo_prover/crates/cairo-air/src/cairo_proof.rs new file mode 100644 index 0000000000..0a1c84532d --- /dev/null +++ b/stwo_cairo_prover/crates/cairo-air/src/cairo_proof.rs @@ -0,0 +1,57 @@ +use serde::{Deserialize, Serialize}; +use stwo::core::proof::StarkProof; +use stwo::core::vcs::MerkleHasher; +use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; + +use crate::cairo_claim::CairoClaim; +use crate::cairo_interaction_claim::CairoInteractionClaim; + +#[derive(Serialize, Deserialize)] +pub struct CairoProof { + pub claim: CairoClaim, + pub interaction_pow: u64, + pub interaction_claim: CairoInteractionClaim, + pub stark_proof: StarkProof, + /// Optional salt used in the channel initialization. + pub channel_salt: Option, +} + +impl CairoSerialize for CairoProof +where + H::Hash: CairoSerialize, +{ + fn serialize(&self, output: &mut Vec) { + let Self { + claim, + interaction_pow, + interaction_claim, + stark_proof, + channel_salt, + } = self; + CairoSerialize::serialize(claim, output); + CairoSerialize::serialize(interaction_pow, output); + CairoSerialize::serialize(interaction_claim, output); + CairoSerialize::serialize(stark_proof, output); + CairoSerialize::serialize(channel_salt, output); + } +} + +impl CairoDeserialize for CairoProof +where + H::Hash: CairoDeserialize, +{ + fn deserialize<'a>(data: &mut impl Iterator) -> Self { + let claim = CairoDeserialize::deserialize(data); + let interaction_pow = CairoDeserialize::deserialize(data); + let interaction_claim = CairoDeserialize::deserialize(data); + let stark_proof = CairoDeserialize::deserialize(data); + let channel_salt = CairoDeserialize::deserialize(data); + Self { + claim, + interaction_pow, + interaction_claim, + stark_proof, + channel_salt, + } + } +} diff --git a/stwo_cairo_prover/crates/cairo-air/src/lib.rs b/stwo_cairo_prover/crates/cairo-air/src/lib.rs index 7348131638..bf9debfe69 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/lib.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/lib.rs @@ -2,9 +2,14 @@ #![feature(array_chunks)] use serde::{Deserialize, Serialize}; -pub mod air; pub mod blake; pub mod builtins_air; +pub mod cairo_proof; +pub mod cairo_components; +pub mod cairo_claim; +pub mod cairo_interaction_elements; +pub mod public_data; +pub mod cairo_interaction_claim; pub mod components; pub mod opcodes_air; pub mod pedersen; @@ -16,7 +21,7 @@ pub mod utils; // TODO(Ohad): verifier crate. pub mod verifier; -pub use air::CairoProof; +pub use cairo_proof::CairoProof; use stwo_cairo_common::preprocessed_columns::preprocessed_trace::PreProcessedTrace; /// The preprocessed trace used for the prover. diff --git a/stwo_cairo_prover/crates/cairo-air/src/opcodes_air.rs b/stwo_cairo_prover/crates/cairo-air/src/opcodes_air.rs index eb071c5b08..91bc8fed95 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/opcodes_air.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/opcodes_air.rs @@ -9,9 +9,9 @@ use stwo::prover::ComponentProver; use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; use stwo_constraint_framework::TraceLocationAllocator; -use super::air::CairoInteractionElements; +use crate::cairo_interaction_elements::CairoInteractionElements; use super::components::display_components; -use crate::air::{accumulate_relation_uses, RelationUsesDict}; +use crate::cairo_claim::{accumulate_relation_uses, RelationUsesDict}; use crate::components::{ add_ap_opcode, add_opcode, add_opcode_small, assert_eq_opcode, assert_eq_opcode_double_deref, assert_eq_opcode_imm, blake_compress_opcode, call_opcode_abs, call_opcode_rel_imm, diff --git a/stwo_cairo_prover/crates/cairo-air/src/pedersen/air.rs b/stwo_cairo_prover/crates/cairo-air/src/pedersen/air.rs index 7efba98fcf..88019b9eb4 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/pedersen/air.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/pedersen/air.rs @@ -4,7 +4,8 @@ use stwo::prover::backend::simd::SimdBackend; use stwo::prover::ComponentProver; use stwo_constraint_framework::TraceLocationAllocator; -use crate::air::{accumulate_relation_uses, CairoInteractionElements, RelationUsesDict}; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::cairo_claim::{accumulate_relation_uses, RelationUsesDict}; use crate::components::prelude::*; use crate::components::{indented_component_display, partial_ec_mul, pedersen_points_table}; diff --git a/stwo_cairo_prover/crates/cairo-air/src/poseidon/air.rs b/stwo_cairo_prover/crates/cairo-air/src/poseidon/air.rs index 277e2555d0..e1610cc9a6 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/poseidon/air.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/poseidon/air.rs @@ -4,7 +4,8 @@ use stwo::prover::backend::simd::SimdBackend; use stwo::prover::ComponentProver; use stwo_constraint_framework::TraceLocationAllocator; -use crate::air::{accumulate_relation_uses, CairoInteractionElements, RelationUsesDict}; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::cairo_claim::{accumulate_relation_uses, RelationUsesDict}; use crate::components::prelude::*; use crate::components::{ cube_252, indented_component_display, poseidon_3_partial_rounds_chain, diff --git a/stwo_cairo_prover/crates/cairo-air/src/public_data.rs b/stwo_cairo_prover/crates/cairo-air/src/public_data.rs new file mode 100644 index 0000000000..03ed23d0a8 --- /dev/null +++ b/stwo_cairo_prover/crates/cairo-air/src/public_data.rs @@ -0,0 +1,353 @@ +use itertools::Itertools; +use serde::{Deserialize, Serialize}; +use stwo::core::channel::Channel; +use stwo::core::fields::m31::M31; +use stwo::core::fields::qm31::QM31; +use stwo::core::fields::FieldExpOps; +use stwo_cairo_common::prover_types::cpu::CasmState; +use stwo_cairo_common::prover_types::felt::split_f252; +use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; +use stwo_constraint_framework::Relation; + +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::relations; + +#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] +pub struct PublicData { + pub public_memory: PublicMemory, + pub initial_state: CasmState, + pub final_state: CasmState, +} +impl PublicData { + /// Sums the logup of the public data. + pub fn logup_sum(&self, lookup_elements: &CairoInteractionElements) -> QM31 { + let mut values_to_inverse = vec![]; + // Use public memory in the memory relations. + self.public_memory + .get_entries( + self.initial_state.pc.0, + self.initial_state.ap.0, + self.final_state.ap.0, + ) + .for_each(|(addr, id, val)| { + values_to_inverse.push( + >::combine( + &lookup_elements.memory_address_to_id, + &[M31::from_u32_unchecked(addr), M31::from_u32_unchecked(id)], + ), + ); + values_to_inverse.push(>::combine( + &lookup_elements.memory_id_to_value, + &[ + [M31::from_u32_unchecked(id)].as_slice(), + split_f252(val).as_slice(), + ] + .concat(), + )); + }); + + // Yield initial state and use the final. + values_to_inverse.push(>::combine( + &lookup_elements.opcodes, + &self.final_state.values(), + )); + values_to_inverse.push(->::combine( + &lookup_elements.opcodes, + &self.initial_state.values(), + )); + + let inverted_values = QM31::batch_inverse(&values_to_inverse); + inverted_values.iter().sum::() + } + + pub fn mix_into(&self, channel: &mut impl Channel) { + let Self { + public_memory, + initial_state, + final_state, + } = self; + public_memory.mix_into(channel); + initial_state.mix_into(channel); + final_state.mix_into(channel); + } +} + +// TODO(alonf) Change all the obscure types and structs to a meaningful struct system for the +// memory. +#[derive(Clone, Debug, Serialize, Deserialize, Copy, CairoSerialize, CairoDeserialize)] +pub struct MemorySmallValue { + pub id: u32, + pub value: u32, +} +impl MemorySmallValue { + pub fn mix_into(&self, channel: &mut impl Channel) { + channel.mix_u64(self.id as u64); + channel.mix_u64(self.value as u64); + } +} + +// TODO(alonf): Change this into a struct. Remove Pub prefix. +// (id, value) +pub type PubMemoryValue = (u32, [u32; 8]); + +// TODO(alonf): Change this into a struct. Remove Pub prefix. +// (address, id, value) +pub type PubMemoryEntry = (u32, u32, [u32; 8]); + +#[derive(Clone, Debug, Serialize, Deserialize, Copy, CairoSerialize, CairoDeserialize)] +pub struct SegmentRange { + pub start_ptr: MemorySmallValue, + pub stop_ptr: MemorySmallValue, +} + +impl SegmentRange { + pub fn is_empty(&self) -> bool { + self.start_ptr.value == self.stop_ptr.value + } + + pub fn mix_into(&self, channel: &mut impl Channel) { + self.start_ptr.mix_into(channel); + self.stop_ptr.mix_into(channel); + } +} + +#[derive(Clone, Debug, Serialize, Deserialize, Copy)] +pub struct PublicSegmentRanges { + pub output: SegmentRange, + pub pedersen: Option, + pub range_check_128: Option, + pub ecdsa: Option, + pub bitwise: Option, + pub ec_op: Option, + pub keccak: Option, + pub poseidon: Option, + pub range_check_96: Option, + pub add_mod: Option, + pub mul_mod: Option, +} + +/// Same as PublicSegmentRanges, but with all segments present, this serialization of the struct is +/// used by the Cairo1 verifier. +#[derive(Clone, Debug, Serialize, Deserialize, Copy, CairoSerialize, CairoDeserialize)] +pub struct FullSegmentRanges { + pub output: SegmentRange, + pub pedersen: SegmentRange, + pub range_check_128: SegmentRange, + pub ecdsa: SegmentRange, + pub bitwise: SegmentRange, + pub ec_op: SegmentRange, + pub keccak: SegmentRange, + pub poseidon: SegmentRange, + pub range_check_96: SegmentRange, + pub add_mod: SegmentRange, + pub mul_mod: SegmentRange, +} + +// The Cairo1 verifier currently requires all the segments to be present. +impl CairoSerialize for PublicSegmentRanges { + fn serialize(&self, serialized: &mut Vec) { + let Self { + output, + pedersen, + range_check_128, + ecdsa, + bitwise, + ec_op, + keccak, + poseidon, + range_check_96, + add_mod, + mul_mod, + } = self; + + CairoSerialize::serialize( + &FullSegmentRanges { + output: *output, + pedersen: pedersen.unwrap(), + range_check_128: range_check_128.unwrap(), + ecdsa: ecdsa.unwrap(), + bitwise: bitwise.unwrap(), + ec_op: ec_op.unwrap(), + keccak: keccak.unwrap(), + poseidon: poseidon.unwrap(), + range_check_96: range_check_96.unwrap(), + add_mod: add_mod.unwrap(), + mul_mod: mul_mod.unwrap(), + }, + serialized, + ); + } +} + +impl CairoDeserialize for PublicSegmentRanges { + fn deserialize<'a>(data: &mut impl Iterator) -> Self { + let FullSegmentRanges { + output, + pedersen, + range_check_128, + ecdsa, + bitwise, + ec_op, + keccak, + poseidon, + range_check_96, + add_mod, + mul_mod, + } = CairoDeserialize::deserialize(data); + + Self { + output, + pedersen: Some(pedersen), + range_check_128: Some(range_check_128), + ecdsa: Some(ecdsa), + bitwise: Some(bitwise), + ec_op: Some(ec_op), + keccak: Some(keccak), + poseidon: Some(poseidon), + range_check_96: Some(range_check_96), + add_mod: Some(add_mod), + mul_mod: Some(mul_mod), + } + } +} + +impl PublicSegmentRanges { + pub fn memory_entries( + &self, + initial_ap: u32, + final_ap: u32, + ) -> impl Iterator { + let segments = self.present_segments(); + + let n_segments = segments.len() as u32; + + segments + .into_iter() + .enumerate() + .flat_map( + move |( + i, + SegmentRange { + start_ptr, + stop_ptr, + }, + )| { + let start_address = initial_ap + i as u32; + let stop_address = final_ap - n_segments + i as u32; + [ + (start_address, start_ptr.id, start_ptr.value), + (stop_address, stop_ptr.id, stop_ptr.value), + ] + }, + ) + .map(|(addr, id, value)| (addr, id, [value, 0, 0, 0, 0, 0, 0, 0])) + } + + pub fn mix_into(&self, channel: &mut impl Channel) { + for segment in self.present_segments() { + segment.mix_into(channel); + } + } + + pub fn present_segments(&self) -> Vec { + let Self { + output, + pedersen, + range_check_128, + ecdsa, + bitwise, + ec_op, + keccak, + poseidon, + range_check_96, + add_mod, + mul_mod, + } = *self; + vec![ + Some(output), + pedersen, + range_check_128, + ecdsa, + bitwise, + ec_op, + keccak, + poseidon, + range_check_96, + add_mod, + mul_mod, + ] + .into_iter() + .flatten() + .collect_vec() + } +} + +pub type MemorySection = Vec; + +#[derive(Serialize, Deserialize, CairoSerialize, CairoDeserialize)] +pub struct PublicMemory { + pub program: MemorySection, + pub public_segments: PublicSegmentRanges, + pub output: MemorySection, + pub safe_call_ids: [u32; 2], +} + +impl PublicMemory { + /// Returns [`PubMemoryEntry`] for all public memory. + pub fn get_entries( + &self, + initial_pc: u32, + initial_ap: u32, + final_ap: u32, + ) -> impl Iterator { + let [program, output] = + [&self.program, &self.output].map(|section| section.clone().into_iter().enumerate()); + let program_iter = program.map(move |(i, (id, value))| (initial_pc + i as u32, id, value)); + let output_iter = output.map(move |(i, (id, value))| (final_ap + i as u32, id, value)); + + let [safe_call_id0, safe_call_id1] = self.safe_call_ids; + // The safe call area should be [initial_fp, 0] and initial_fp should be the same as + // initial_ap. + let safe_call_iter = [ + ( + initial_ap - 2, + safe_call_id0, + [initial_ap, 0, 0, 0, 0, 0, 0, 0], + ), + (initial_ap - 1, safe_call_id1, [0, 0, 0, 0, 0, 0, 0, 0]), + ]; + let segment_ranges_iter = self.public_segments.memory_entries(initial_ap, final_ap); + + program_iter + .chain(safe_call_iter) + .chain(segment_ranges_iter) + .chain(output_iter) + } + + pub fn mix_into(&self, channel: &mut impl Channel) { + let Self { + program, + public_segments, + output, + safe_call_ids, + } = self; + + // Mix program memory section. All the ids are mixed first, then all the values, each of + // them in the order it appears in the section. + channel.mix_u32s(&program.iter().map(|(id, _)| *id).collect_vec()); + channel.mix_u32s(&program.iter().flat_map(|(_, value)| *value).collect_vec()); + + // Mix public segments. + public_segments.mix_into(channel); + + // Mix output memory section. All the ids are mixed first, then all the values, each of them + // in the order it appears in the section. + channel.mix_u32s(&output.iter().map(|(id, _)| *id).collect_vec()); + channel.mix_u32s(&output.iter().flat_map(|(_, value)| *value).collect_vec()); + + // Mix safe_ids memory section. + for id in safe_call_ids { + channel.mix_u64(*id as u64); + } + } +} diff --git a/stwo_cairo_prover/crates/cairo-air/src/utils.rs b/stwo_cairo_prover/crates/cairo-air/src/utils.rs index 9ddfeb34db..4474a40cea 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/utils.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/utils.rs @@ -13,7 +13,7 @@ use stwo::core::vcs::MerkleHasher; use stwo_cairo_serialize::{CairoDeserialize, CairoSerialize}; use tracing::{span, Level}; -use crate::air::{MemorySection, PublicMemory}; +use crate::public_data::{MemorySection, PublicMemory}; use crate::CairoProof; mod json { diff --git a/stwo_cairo_prover/crates/cairo-air/src/verifier.rs b/stwo_cairo_prover/crates/cairo-air/src/verifier.rs index c87133f626..6203fcfbb8 100644 --- a/stwo_cairo_prover/crates/cairo-air/src/verifier.rs +++ b/stwo_cairo_prover/crates/cairo-air/src/verifier.rs @@ -17,11 +17,13 @@ use stwo_cairo_common::prover_types::cpu::{CasmState, PRIME}; use stwo_constraint_framework::PREPROCESSED_TRACE_IDX; use thiserror::Error; -use crate::air::{ - lookup_sum, CairoClaim, CairoComponents, CairoInteractionElements, MemorySection, PublicData, - PublicMemory, PublicSegmentRanges, SegmentRange, -}; use crate::builtins_air::BuiltinsClaim; +use crate::cairo_claim::CairoClaim; +use crate::cairo_components::CairoComponents; +use crate::cairo_interaction_claim::lookup_sum; +use crate::cairo_interaction_elements::CairoInteractionElements; +use crate::public_data::{MemorySection, PublicMemory, PublicSegmentRanges, SegmentRange}; +use crate::public_data::PublicData; use crate::components::memory_address_to_id::MEMORY_ADDRESS_TO_ID_SPLIT; use crate::{CairoProof, PreProcessedTraceVariant}; diff --git a/stwo_cairo_prover/crates/prover/src/debug_tools/assert_constraints.rs b/stwo_cairo_prover/crates/prover/src/debug_tools/assert_constraints.rs index bf891016d2..da23b5be6e 100644 --- a/stwo_cairo_prover/crates/prover/src/debug_tools/assert_constraints.rs +++ b/stwo_cairo_prover/crates/prover/src/debug_tools/assert_constraints.rs @@ -1,7 +1,8 @@ use std::ops::Deref; -use cairo_air::air::{CairoComponents, CairoInteractionElements}; use cairo_air::builtins_air::BuiltinComponents; +use cairo_air::cairo_components::CairoComponents; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use cairo_air::opcodes_air::OpcodeComponents; use cairo_air::range_checks_air::RangeChecksComponents; use itertools::Itertools; diff --git a/stwo_cairo_prover/crates/prover/src/debug_tools/relation_tracker.rs b/stwo_cairo_prover/crates/prover/src/debug_tools/relation_tracker.rs index 9d5ebe2a5b..87a84d49a2 100644 --- a/stwo_cairo_prover/crates/prover/src/debug_tools/relation_tracker.rs +++ b/stwo_cairo_prover/crates/prover/src/debug_tools/relation_tracker.rs @@ -1,4 +1,5 @@ -use cairo_air::air::{CairoComponents, PublicData}; +use cairo_air::cairo_components::CairoComponents; +use cairo_air::public_data::PublicData; use cairo_air::builtins_air::BuiltinComponents; use cairo_air::opcodes_air::OpcodeComponents; use cairo_air::range_checks_air::RangeChecksComponents; diff --git a/stwo_cairo_prover/crates/prover/src/prover.rs b/stwo_cairo_prover/crates/prover/src/prover.rs index 64ea3bbba2..13c69ab710 100644 --- a/stwo_cairo_prover/crates/prover/src/prover.rs +++ b/stwo_cairo_prover/crates/prover/src/prover.rs @@ -2,7 +2,9 @@ use std::fs::read_to_string; use std::path::PathBuf; use anyhow::Result; -use cairo_air::air::{lookup_sum, CairoComponents, CairoInteractionElements}; +use cairo_air::cairo_components::CairoComponents; +use cairo_air::cairo_interaction_claim::lookup_sum; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use cairo_air::utils::{serialize_proof_to_file, ProofFormat}; use cairo_air::verifier::{verify_cairo, INTERACTION_POW_BITS}; use cairo_air::{CairoProof, PreProcessedTraceVariant}; diff --git a/stwo_cairo_prover/crates/prover/src/witness/blake_context.rs b/stwo_cairo_prover/crates/prover/src/witness/blake_context.rs index af7f6e95da..c14f694067 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/blake_context.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/blake_context.rs @@ -1,7 +1,7 @@ -use cairo_air::air::CairoInteractionElements; use cairo_air::blake::air::{ BlakeContextClaim, BlakeContextInteractionClaim, Claim, InteractionClaim, }; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use stwo::prover::backend::simd::SimdBackend; use stwo_cairo_adapter::memory::Memory; use tracing::{span, Level}; diff --git a/stwo_cairo_prover/crates/prover/src/witness/builtins.rs b/stwo_cairo_prover/crates/prover/src/witness/builtins.rs index ec683adcb3..3d0a032347 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/builtins.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/builtins.rs @@ -1,5 +1,5 @@ -use cairo_air::air::CairoInteractionElements; use cairo_air::builtins_air::{BuiltinsClaim, BuiltinsInteractionClaim}; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use stwo::prover::backend::simd::SimdBackend; use stwo_cairo_adapter::builtins::BuiltinSegments; use stwo_cairo_common::builtins::{ diff --git a/stwo_cairo_prover/crates/prover/src/witness/cairo.rs b/stwo_cairo_prover/crates/prover/src/witness/cairo.rs index cb08be0b70..1ae945c6fb 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/cairo.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/cairo.rs @@ -1,9 +1,9 @@ use std::array; -use cairo_air::air::{ - CairoClaim, CairoInteractionClaim, CairoInteractionElements, MemorySmallValue, PublicData, - PublicMemory, PublicSegmentRanges, SegmentRange, -}; +use cairo_air::cairo_claim::CairoClaim; +use cairo_air::cairo_interaction_claim::CairoInteractionClaim; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; +use cairo_air::public_data::{MemorySmallValue, PublicData, PublicMemory, PublicSegmentRanges, SegmentRange}; use itertools::Itertools; use stwo::core::fields::m31::M31; use stwo::prover::backend::simd::SimdBackend; diff --git a/stwo_cairo_prover/crates/prover/src/witness/components/memory_id_to_big.rs b/stwo_cairo_prover/crates/prover/src/witness/components/memory_id_to_big.rs index 73c21b92c3..914d399bdb 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/components/memory_id_to_big.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/components/memory_id_to_big.rs @@ -585,7 +585,7 @@ impl InteractionClaimGenerator { #[cfg(test)] mod tests { - use cairo_air::air::CairoInteractionElements; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use cairo_air::components::memory_id_to_big::{self, SmallEval}; use cairo_air::PreProcessedTraceVariant; use itertools::Itertools; diff --git a/stwo_cairo_prover/crates/prover/src/witness/components/pedersen.rs b/stwo_cairo_prover/crates/prover/src/witness/components/pedersen.rs index 7599a39e32..d021625b1a 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/components/pedersen.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/components/pedersen.rs @@ -1,4 +1,4 @@ -use cairo_air::air::CairoInteractionElements; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use cairo_air::pedersen::air::{ Claim, InteractionClaim, PedersenContextClaim, PedersenContextInteractionClaim, }; diff --git a/stwo_cairo_prover/crates/prover/src/witness/components/poseidon.rs b/stwo_cairo_prover/crates/prover/src/witness/components/poseidon.rs index 145935fb9a..d8db3b8428 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/components/poseidon.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/components/poseidon.rs @@ -1,4 +1,4 @@ -use cairo_air::air::CairoInteractionElements; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use cairo_air::poseidon::air::{ Claim, InteractionClaim, PoseidonContextClaim, PoseidonContextInteractionClaim, }; diff --git a/stwo_cairo_prover/crates/prover/src/witness/opcodes.rs b/stwo_cairo_prover/crates/prover/src/witness/opcodes.rs index fd2a75f46b..d5d451619b 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/opcodes.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/opcodes.rs @@ -1,4 +1,4 @@ -use cairo_air::air::CairoInteractionElements; +use cairo_air::cairo_interaction_elements::CairoInteractionElements; use cairo_air::opcodes_air::{OpcodeClaim, OpcodeInteractionClaim}; use stwo::prover::backend::simd::SimdBackend; use stwo_cairo_adapter::opcodes::StateTransitions; diff --git a/stwo_cairo_prover/crates/prover/src/witness/utils.rs b/stwo_cairo_prover/crates/prover/src/witness/utils.rs index b981d787d4..7fc1545818 100644 --- a/stwo_cairo_prover/crates/prover/src/witness/utils.rs +++ b/stwo_cairo_prover/crates/prover/src/witness/utils.rs @@ -1,6 +1,6 @@ use std::sync::atomic::{AtomicU32, Ordering}; -use cairo_air::air::CairoClaim; +use cairo_air::cairo_claim::CairoClaim; use cairo_air::PreProcessedTraceVariant; use itertools::Itertools; use num_traits::{One, Zero};