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 99f98793..d696cc58 100644 --- a/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs +++ b/stwo_cairo_prover/crates/prover/src/cairo_air/air.rs @@ -278,6 +278,7 @@ impl CairoClaimGenerator { tree_builder, &self.memory_address_to_id_trace_generator, &self.memory_id_to_value_trace_generator, + &self.verify_bitwise_xor_9_trace_generator, ); let (verify_bitwise_xor_9_claim, verify_bitwise_xor_9_interaction_gen) = self .verify_bitwise_xor_9_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 314b379d..0a81c2bc 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,50 +13,88 @@ 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::{ + bitwise_builtin, memory_address_to_id, memory_id_to_big, range_check_builtin_bits_128, + verify_bitwise_xor_9, +}; use crate::input::builtin_segments::BuiltinSegments; #[derive(Serialize, Deserialize, CairoSerialize)] pub struct BuiltinsClaim { pub range_check_128_builtin: Option, + pub bitwise_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(bitwise_builtin) = &self.bitwise_builtin { + bitwise_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.bitwise_builtin + .map(|bitwise_builtin| bitwise_builtin.log_sizes()) + .into_iter(), + )) } } pub struct BuiltinsClaimGenerator { range_check_128_builtin_trace_generator: Option, + bitwise_builtin_trace_generator: Option, } impl BuiltinsClaimGenerator { pub fn new(builtin_segments: BuiltinSegments) -> Self { let range_check_128_builtin_trace_generator = builtin_segments - .range_check_bits_128 - .map(|range_check_bits_128| { - assert!( - (range_check_bits_128.stop_ptr - range_check_bits_128.begin_addr) - .is_power_of_two(), - "range_check_bits_128 segment length 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(), - range_check_bits_128.begin_addr as u32, - ) - }); + .range_check_bits_128 + .map(|range_check_bits_128| { + let rc128_builtin_cells_per_instance = + BuiltinSegments::builtin_memory_cells_per_instance(BuiltinName::range_check); + assert!( + ((range_check_bits_128.stop_ptr - range_check_bits_128.begin_addr) % 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_cells_per_instance) + .is_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) / rc128_builtin_cells_per_instance) + .ilog2(), + range_check_bits_128.begin_addr as u32, + ) + }); + let bitwise_builtin_trace_generator = builtin_segments.bitwise.map(|bitwise| { + let bitwise_builtin_cells_per_instance = + BuiltinSegments::builtin_memory_cells_per_instance(BuiltinName::bitwise); + assert!( + ((bitwise.stop_ptr - bitwise.begin_addr) % bitwise_builtin_cells_per_instance) == 0, + "bitwise segment length is not a multiple of bitwise_builtin_cells_per_instance" + ); + assert!( + ((bitwise.stop_ptr - bitwise.begin_addr) / bitwise_builtin_cells_per_instance) + .is_power_of_two(), + "bitwise instances number is not a power of two" + ); + bitwise_builtin::ClaimGenerator::new( + ((bitwise.stop_ptr - bitwise.begin_addr) / bitwise_builtin_cells_per_instance) + .ilog2(), + bitwise.begin_addr as u32, + ) + }); Self { range_check_128_builtin_trace_generator, + bitwise_builtin_trace_generator, } } @@ -64,6 +103,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, + verify_bitwise_xor_9_trace_generator: &verify_bitwise_xor_9::ClaimGenerator, ) -> (BuiltinsClaim, BuiltinsInteractionClaimGenerator) where SimdBackend: BackendForChannel, @@ -81,12 +121,26 @@ impl BuiltinsClaimGenerator { } else { (None, None) }; + let (bitwise_builtin_claim, bitwise_builtin_interaction_gen) = + if let Some(bitwise_builtin_trace_generator) = self.bitwise_builtin_trace_generator { + let (claim, interaction_gen) = bitwise_builtin_trace_generator.write_trace( + tree_builder, + memory_address_to_id_trace_generator, + memory_id_to_value_trace_generator, + verify_bitwise_xor_9_trace_generator, + ); + (Some(claim), Some(interaction_gen)) + } else { + (None, None) + }; ( BuiltinsClaim { range_check_128_builtin: range_check_128_builtin_claim, + bitwise_builtin: bitwise_builtin_claim, }, BuiltinsInteractionClaimGenerator { range_check_128_builtin_interaction_gen, + bitwise_builtin_interaction_gen, }, ) } @@ -95,12 +149,16 @@ impl BuiltinsClaimGenerator { #[derive(Serialize, Deserialize, CairoSerialize)] pub struct BuiltinsInteractionClaim { pub range_check_128_builtin: Option, + pub bitwise_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(bitwise_builtin) = self.bitwise_builtin { + bitwise_builtin.mix_into(channel) + } } pub fn sum(&self) -> SecureField { @@ -108,6 +166,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(bitwise_builtin) = &self.bitwise_builtin { + sum += bitwise_builtin.logup_sums.0; + } sum } } @@ -115,6 +176,7 @@ impl BuiltinsInteractionClaim { pub struct BuiltinsInteractionClaimGenerator { range_check_128_builtin_interaction_gen: Option, + bitwise_builtin_interaction_gen: Option, } impl BuiltinsInteractionClaimGenerator { pub fn write_interaction_trace( @@ -134,14 +196,26 @@ impl BuiltinsInteractionClaimGenerator { &interaction_elements.memory_id_to_value, ) }); + let bitwise_builtin_interaction_claim = + self.bitwise_builtin_interaction_gen + .map(|bitwise_builtin_interaction_gen| { + bitwise_builtin_interaction_gen.write_interaction_trace( + tree_builder, + &interaction_elements.memory_address_to_id, + &interaction_elements.memory_id_to_value, + &interaction_elements.verify_bitwise_xor_9, + ) + }); BuiltinsInteractionClaim { range_check_128_builtin: range_check_128_builtin_interaction_claim, + bitwise_builtin: bitwise_builtin_interaction_claim, } } } pub struct BuiltinComponents { range_check_128_builtin: Option, + bitwise_builtin: Option, } impl BuiltinComponents { pub fn new( @@ -171,8 +245,27 @@ impl BuiltinComponents { .logup_sums, ) }); + let bitwise_builtin_component = claim.bitwise_builtin.map(|bitwise_builtin| { + bitwise_builtin::Component::new( + tree_span_provider, + bitwise_builtin::Eval { + claim: bitwise_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(), + verify_bitwise_xor_9_lookup_elements: interaction_elements + .verify_bitwise_xor_9 + .clone(), + }, + interaction_claim.bitwise_builtin.unwrap().logup_sums, + ) + }); Self { range_check_128_builtin: range_check_128_builtin_component, + bitwise_builtin: bitwise_builtin_component, } } @@ -181,6 +274,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(bitwise_builtin) = &self.bitwise_builtin { + vec.push(bitwise_builtin as &dyn ComponentProver); + } vec } } @@ -194,6 +290,13 @@ impl std::fmt::Display for BuiltinComponents { indented_component_display(range_check_128_builtin) )?; } + if let Some(bitwise_builtin) = &self.bitwise_builtin { + writeln!( + f, + "BitwiseBuiltin: {}", + indented_component_display(bitwise_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 4dcf907c..1e6ad0fe 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 @@ -17,11 +17,11 @@ use super::air::CairoClaim; use crate::components::{ add_ap_opcode, add_ap_opcode_imm, add_ap_opcode_op_1_base_fp, add_opcode, add_opcode_imm, add_opcode_small, add_opcode_small_imm, assert_eq_opcode, assert_eq_opcode_double_deref, - assert_eq_opcode_imm, call_opcode, call_opcode_op_1_base_fp, call_opcode_rel, generic_opcode, - jnz_opcode, jnz_opcode_dst_base_fp, jnz_opcode_taken, jnz_opcode_taken_dst_base_fp, - 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_7_2_5, range_check_9_9, + assert_eq_opcode_imm, bitwise_builtin, call_opcode, call_opcode_op_1_base_fp, call_opcode_rel, + generic_opcode, jnz_opcode, jnz_opcode_dst_base_fp, jnz_opcode_taken, + jnz_opcode_taken_dst_base_fp, 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_7_2_5, range_check_9_9, range_check_builtin_bits_128, ret_opcode, verify_bitwise_xor_9, verify_instruction, }; use crate::felt::split_f252; @@ -485,6 +485,22 @@ where ); } + if let Some(bitwise_builtin) = claim.builtins.bitwise_builtin { + entries.extend( + RelationTrackerComponent::new( + tree_span_provider, + bitwise_builtin::Eval { + claim: bitwise_builtin, + memory_address_to_id_lookup_elements: relations::MemoryAddressToId::dummy(), + memory_id_to_big_lookup_elements: relations::MemoryIdToBig::dummy(), + verify_bitwise_xor_9_lookup_elements: relations::VerifyBitwiseXor_9::dummy(), + }, + 1 << bitwise_builtin.log_size, + ) + .entries(trace), + ); + } + entries.extend( RelationTrackerComponent::new( tree_span_provider,