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 68e9e2c49..c218b3339 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs @@ -250,6 +250,7 @@ impl CairoClaimGenerator { tree_builder, &self.memory_address_to_id_trace_generator, &self.memory_id_to_value_trace_generator, + &self.range_checks_trace_generator.rc_6_trace_generator, ); let (memory_address_to_id_claim, memory_address_to_id_interaction_gen) = self .memory_address_to_id_trace_generator diff --git a/stwo_cairo_prover/crates/prover/src/cairo_air/builtins_air.rs b/stwo_cairo_prover/crates/prover/src/cairo_air/builtins_air.rs index 314b379d7..5c8903165 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/builtins_air.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/builtins_air.rs @@ -1,3 +1,4 @@ +use cairo_vm::types::builtin_name::BuiltinName; use itertools::chain; use num_traits::Zero; use serde::{Deserialize, Serialize}; @@ -12,30 +13,42 @@ use stwo_prover::core::pcs::{TreeBuilder, TreeVec}; use super::air::CairoInteractionElements; use super::debug_tools::indented_component_display; -use crate::components::{memory_address_to_id, memory_id_to_big, range_check_builtin_bits_128}; +use crate::components::{ + memory_address_to_id, memory_id_to_big, range_check_6, range_check_builtin_bits_128, + range_check_builtin_bits_96, +}; use crate::input::builtin_segments::BuiltinSegments; #[derive(Serialize, Deserialize, CairoSerialize)] pub struct BuiltinsClaim { pub range_check_128_builtin: Option, + pub range_check_96_builtin: Option, } impl BuiltinsClaim { pub fn mix_into(&self, channel: &mut impl Channel) { if let Some(range_check_128_builtin) = &self.range_check_128_builtin { range_check_128_builtin.mix_into(channel); } + if let Some(range_check_96_builtin) = &self.range_check_96_builtin { + range_check_96_builtin.mix_into(channel); + } } pub fn log_sizes(&self) -> TreeVec> { - TreeVec::concat_cols(chain!(self - .range_check_128_builtin - .map(|range_check_128_builtin| range_check_128_builtin.log_sizes()) - .into_iter())) + TreeVec::concat_cols(chain!( + self.range_check_128_builtin + .map(|range_check_128_builtin| range_check_128_builtin.log_sizes()) + .into_iter(), + self.range_check_96_builtin + .map(|range_check_96_builtin| range_check_96_builtin.log_sizes()) + .into_iter(), + )) } } pub struct BuiltinsClaimGenerator { range_check_128_builtin_trace_generator: Option, + range_check_96_builtin_trace_generator: Option, } impl BuiltinsClaimGenerator { pub fn new(builtin_segments: BuiltinSegments) -> Self { @@ -43,19 +56,50 @@ impl BuiltinsClaimGenerator { builtin_segments .range_check_bits_128 .map(|range_check_bits_128| { + let rc128_builtin_cells_per_instance = + BuiltinSegments::builtin_memory_cells_per_instance(BuiltinName::range_check); + let rc128_builtin_segment_length = range_check_bits_128.stop_ptr - range_check_bits_128.begin_addr; + assert!( + (rc128_builtin_segment_length % rc128_builtin_cells_per_instance) == 0, + "range_check_bits_128 segment length is not a multiple of rc128_builtin_cells_per_instance" + ); assert!( - (range_check_bits_128.stop_ptr - range_check_bits_128.begin_addr) + (rc128_builtin_segment_length / rc128_builtin_cells_per_instance) .is_power_of_two(), - "range_check_bits_128 segment length is not a power of two" + "range_check_bits_128 instances number is not a power of two" ); range_check_builtin_bits_128::ClaimGenerator::new( - (range_check_bits_128.stop_ptr - range_check_bits_128.begin_addr).ilog2(), + (rc128_builtin_segment_length / rc128_builtin_cells_per_instance) + .ilog2(), range_check_bits_128.begin_addr as u32, ) }); + let range_check_96_builtin_trace_generator = + builtin_segments + .range_check_bits_96 + .map(|range_check_bits_96| { + let rc96_builtin_cells_per_instance = + BuiltinSegments::builtin_memory_cells_per_instance(BuiltinName::range_check96); + let rc96_builtin_segment_length = range_check_bits_96.stop_ptr - range_check_bits_96.begin_addr; + assert!( + (rc96_builtin_segment_length % rc96_builtin_cells_per_instance) == 0, + "range_check_bits_96 segment length is not a multiple of rc96_builtin_cells_per_instance" + ); + assert!( + (rc96_builtin_segment_length / rc96_builtin_cells_per_instance) + .is_power_of_two(), + "range_check_bits_96 instances number is not a power of two" + ); + range_check_builtin_bits_96::ClaimGenerator::new( + (rc96_builtin_segment_length / rc96_builtin_cells_per_instance) + .ilog2(), + range_check_bits_96.begin_addr as u32, + ) + }); Self { range_check_128_builtin_trace_generator, + range_check_96_builtin_trace_generator, } } @@ -64,6 +108,7 @@ impl BuiltinsClaimGenerator { tree_builder: &mut TreeBuilder<'_, '_, SimdBackend, MC>, memory_address_to_id_trace_generator: &memory_address_to_id::ClaimGenerator, memory_id_to_value_trace_generator: &memory_id_to_big::ClaimGenerator, + range_check_6_trace_generator: &range_check_6::ClaimGenerator, ) -> (BuiltinsClaim, BuiltinsInteractionClaimGenerator) where SimdBackend: BackendForChannel, @@ -81,12 +126,28 @@ impl BuiltinsClaimGenerator { } else { (None, None) }; + let (range_check_96_builtin_claim, range_check_96_builtin_interaction_gen) = + if let Some(range_check_96_builtin_trace_generator) = + self.range_check_96_builtin_trace_generator + { + let (claim, interaction_gen) = range_check_96_builtin_trace_generator.write_trace( + tree_builder, + memory_address_to_id_trace_generator, + memory_id_to_value_trace_generator, + range_check_6_trace_generator, + ); + (Some(claim), Some(interaction_gen)) + } else { + (None, None) + }; ( BuiltinsClaim { range_check_128_builtin: range_check_128_builtin_claim, + range_check_96_builtin: range_check_96_builtin_claim, }, BuiltinsInteractionClaimGenerator { range_check_128_builtin_interaction_gen, + range_check_96_builtin_interaction_gen, }, ) } @@ -95,12 +156,16 @@ impl BuiltinsClaimGenerator { #[derive(Serialize, Deserialize, CairoSerialize)] pub struct BuiltinsInteractionClaim { pub range_check_128_builtin: Option, + pub range_check_96_builtin: Option, } impl BuiltinsInteractionClaim { pub fn mix_into(&self, channel: &mut impl Channel) { if let Some(range_check_128_builtin) = self.range_check_128_builtin { range_check_128_builtin.mix_into(channel) } + if let Some(range_check_96_builtin) = &self.range_check_96_builtin { + range_check_96_builtin.mix_into(channel); + } } pub fn sum(&self) -> SecureField { @@ -108,6 +173,9 @@ impl BuiltinsInteractionClaim { if let Some(range_check_128_builtin) = &self.range_check_128_builtin { sum += range_check_128_builtin.logup_sums.0; } + if let Some(range_check_96_builtin) = &self.range_check_96_builtin { + sum += range_check_96_builtin.logup_sums.0; + } sum } } @@ -115,6 +183,8 @@ impl BuiltinsInteractionClaim { pub struct BuiltinsInteractionClaimGenerator { range_check_128_builtin_interaction_gen: Option, + range_check_96_builtin_interaction_gen: + Option, } impl BuiltinsInteractionClaimGenerator { pub fn write_interaction_trace( @@ -134,14 +204,26 @@ impl BuiltinsInteractionClaimGenerator { &interaction_elements.memory_id_to_value, ) }); + let range_check_96_builtin_interaction_claim = self + .range_check_96_builtin_interaction_gen + .map(|range_check_96_builtin_interaction_gen| { + range_check_96_builtin_interaction_gen.write_interaction_trace( + tree_builder, + &interaction_elements.memory_address_to_id, + &interaction_elements.memory_id_to_value, + &interaction_elements.range_checks.rc_6, + ) + }); BuiltinsInteractionClaim { range_check_128_builtin: range_check_128_builtin_interaction_claim, + range_check_96_builtin: range_check_96_builtin_interaction_claim, } } } pub struct BuiltinComponents { range_check_128_builtin: Option, + range_check_96_builtin: Option, } impl BuiltinComponents { pub fn new( @@ -171,8 +253,29 @@ impl BuiltinComponents { .logup_sums, ) }); + let range_check_96_builtin_component = + claim.range_check_96_builtin.map(|range_check_96_builtin| { + range_check_builtin_bits_96::Component::new( + tree_span_provider, + range_check_builtin_bits_96::Eval { + claim: range_check_96_builtin, + memory_address_to_id_lookup_elements: interaction_elements + .memory_address_to_id + .clone(), + memory_id_to_big_lookup_elements: interaction_elements + .memory_id_to_value + .clone(), + range_check_6_lookup_elements: interaction_elements + .range_checks + .rc_6 + .clone(), + }, + interaction_claim.range_check_96_builtin.unwrap().logup_sums, + ) + }); Self { range_check_128_builtin: range_check_128_builtin_component, + range_check_96_builtin: range_check_96_builtin_component, } } @@ -181,6 +284,9 @@ impl BuiltinComponents { if let Some(range_check_128_builtin) = &self.range_check_128_builtin { vec.push(range_check_128_builtin as &dyn ComponentProver); } + if let Some(range_check_96_builtin) = &self.range_check_96_builtin { + vec.push(range_check_96_builtin as &dyn ComponentProver); + } vec } } @@ -194,6 +300,13 @@ impl std::fmt::Display for BuiltinComponents { indented_component_display(range_check_128_builtin) )?; } + if let Some(range_check_96_builtin) = &self.range_check_96_builtin { + writeln!( + f, + "RangeCheck96Builtin: {}", + indented_component_display(range_check_96_builtin) + )?; + } Ok(()) } } diff --git a/stwo_cairo_prover/crates/prover/src/cairo_air/debug_tools.rs b/stwo_cairo_prover/crates/prover/src/cairo_air/debug_tools.rs index f11aeb1fd..ecd3c72ed 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/debug_tools.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/debug_tools.rs @@ -22,7 +22,7 @@ use crate::components::{ jump_opcode, jump_opcode_double_deref, jump_opcode_rel, jump_opcode_rel_imm, memory_address_to_id, memory_id_to_big, mul_opcode, mul_opcode_imm, range_check_11, range_check_19, range_check_4_3, range_check_6, range_check_7_2_5, range_check_9_9, - range_check_builtin_bits_128, ret_opcode, verify_instruction, + range_check_builtin_bits_128, range_check_builtin_bits_96, ret_opcode, verify_instruction, }; use crate::felt::split_f252; use crate::relations; @@ -485,6 +485,22 @@ where ); } + if let Some(range_check_96_builtin) = claim.builtins.range_check_96_builtin { + entries.extend( + RelationTrackerComponent::new( + tree_span_provider, + range_check_builtin_bits_96::Eval { + claim: range_check_96_builtin, + memory_address_to_id_lookup_elements: relations::MemoryAddressToId::dummy(), + memory_id_to_big_lookup_elements: relations::MemoryIdToBig::dummy(), + range_check_6_lookup_elements: relations::RangeCheck_6::dummy(), + }, + 1 << range_check_96_builtin.log_size, + ) + .entries(trace), + ); + } + // Memory. entries.extend( RelationTrackerComponent::new(