From 2da09167f05dd83d2c6a8b53af1e32ca9f1e5838 Mon Sep 17 00:00:00 2001 From: vishruti Date: Thu, 22 May 2025 13:20:06 -0700 Subject: [PATCH 1/3] added support for binary opcodes --- .../bin-opcode/Nargo.toml | 6 + .../bin-opcode/Prover.toml | 4 + .../bin-opcode/src/main.nr | 6 + noir-r1cs/src/binops.rs | 244 ++++++++++++++++++ noir-r1cs/src/digits.rs | 2 +- noir-r1cs/src/lib.rs | 1 + noir-r1cs/src/noir_to_r1cs.rs | 65 +++++ noir-r1cs/src/r1cs_solver.rs | 73 ++++++ noir-r1cs/src/ram.rs | 4 +- noir-r1cs/src/rom.rs | 1 - noir-r1cs/src/test_functions.rs | 8 + 11 files changed, 410 insertions(+), 4 deletions(-) create mode 100644 noir-examples/noir-r1cs-test-programs/bin-opcode/Nargo.toml create mode 100644 noir-examples/noir-r1cs-test-programs/bin-opcode/Prover.toml create mode 100644 noir-examples/noir-r1cs-test-programs/bin-opcode/src/main.nr create mode 100644 noir-r1cs/src/binops.rs diff --git a/noir-examples/noir-r1cs-test-programs/bin-opcode/Nargo.toml b/noir-examples/noir-r1cs-test-programs/bin-opcode/Nargo.toml new file mode 100644 index 000000000..92c044bfe --- /dev/null +++ b/noir-examples/noir-r1cs-test-programs/bin-opcode/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "main" +type = "bin" +authors = [""] + +[dependencies] diff --git a/noir-examples/noir-r1cs-test-programs/bin-opcode/Prover.toml b/noir-examples/noir-r1cs-test-programs/bin-opcode/Prover.toml new file mode 100644 index 000000000..cb426dd77 --- /dev/null +++ b/noir-examples/noir-r1cs-test-programs/bin-opcode/Prover.toml @@ -0,0 +1,4 @@ +w = 7 +x = 10 +y = 3 +z = 15 diff --git a/noir-examples/noir-r1cs-test-programs/bin-opcode/src/main.nr b/noir-examples/noir-r1cs-test-programs/bin-opcode/src/main.nr new file mode 100644 index 000000000..a6534df59 --- /dev/null +++ b/noir-examples/noir-r1cs-test-programs/bin-opcode/src/main.nr @@ -0,0 +1,6 @@ +fn main(w: u32, x: u32, y: u32, z: u32) -> pub u32 { + let hi = x & x ^ y & y & z & z ^ w & w; + let bye = x & (31 as u32); + let rye = y ^ (64 as u32); + bye & rye ^ hi +} diff --git a/noir-r1cs/src/binops.rs b/noir-r1cs/src/binops.rs new file mode 100644 index 000000000..8fec54a52 --- /dev/null +++ b/noir-r1cs/src/binops.rs @@ -0,0 +1,244 @@ +use { + crate::{ + digits::{add_digital_decomposition, decompose_into_digits}, + noir_to_r1cs::{ConstantOrR1CSWitness, NoirToR1CSCompiler}, + r1cs_solver::{SumTerm, WitnessBuilder}, + FieldElement, + }, + ark_ff::One, + std::ops::Neg, +}; + +#[derive(Clone, Debug, Copy)] +pub enum BinOp { + AND, + XOR, +} + +/// The number of bits that ACIR uses for the inputs and output of the binop. +pub const BINOP_BITS: usize = 32; + +/// The number of bits that used by us for the inputs and output of the binop. +/// 2x this number of bits is used for the lookup table. +pub const BINOP_ATOMIC_BITS: usize = 8; + +/// Each operand is decomposed into this many digits. +pub const NUM_DIGITS: usize = BINOP_BITS / BINOP_ATOMIC_BITS; + +/// Add the witnesses and constraints for a [BinOp] (i.e. AND, XOR). Uses a +/// digital decomposition of the operands and output into [NUM_DIGITS] digits of +/// [BINOP_ATOMIC_BITS] bits each, followed by a lookup table of size 2x +/// [BINOP_ATOMIC_BITS]. +pub(crate) fn add_binop( + r1cs_compiler: &mut NoirToR1CSCompiler, + op: BinOp, + inputs_and_outputs: Vec<(ConstantOrR1CSWitness, ConstantOrR1CSWitness, usize)>, +) { + let log_bases = vec![BINOP_ATOMIC_BITS; NUM_DIGITS]; + + // Collect all witnesses that require digital decomposition (constants are + // decomposed separately). + let mut witnesses_to_decompose = vec![]; + for (lh, rh, output) in &inputs_and_outputs { + if let ConstantOrR1CSWitness::Witness(witness) = lh { + witnesses_to_decompose.push(*witness); + } + if let ConstantOrR1CSWitness::Witness(witness) = rh { + witnesses_to_decompose.push(*witness); + } + witnesses_to_decompose.push(*output); + } + let dd_struct = + add_digital_decomposition(r1cs_compiler, log_bases.clone(), witnesses_to_decompose); + + // Match up the digit witnesses and the digits of decompositions of constants to + // obtain a decomposed version of the inputs and outputs. + let mut inputs_and_outputs_atomic = vec![]; + // Track how many witness digital decompositions we've seen so far (for + // associating the digit witnesses with the original witnesses). + let mut witness_dd_counter = 0; + for (lh, rh, _output) in inputs_and_outputs { + let lh_atoms = match lh { + ConstantOrR1CSWitness::Witness(_) => { + let digit_witnesses = (0..NUM_DIGITS) + .map(|digit_place| { + dd_struct.get_digit_witness_index(digit_place, witness_dd_counter) + }) + .collect::>(); + witness_dd_counter += 1; + digit_witnesses + .iter() + .map(|witness| ConstantOrR1CSWitness::Witness(*witness)) + .collect::>() + } + ConstantOrR1CSWitness::Constant(value) => { + let digits = decompose_into_digits(value, &log_bases); + digits + .iter() + .map(|digit| ConstantOrR1CSWitness::Constant(*digit)) + .collect::>() + } + }; + let rh_atoms = match rh { + ConstantOrR1CSWitness::Witness(_) => { + let digit_witnesses = (0..NUM_DIGITS) + .map(|digit_place| { + dd_struct.get_digit_witness_index(digit_place, witness_dd_counter) + }) + .collect::>(); + witness_dd_counter += 1; + digit_witnesses + .iter() + .map(|witness| ConstantOrR1CSWitness::Witness(*witness)) + .collect::>() + } + ConstantOrR1CSWitness::Constant(value) => { + let digits = decompose_into_digits(value, &log_bases); + digits + .iter() + .map(|digit| ConstantOrR1CSWitness::Constant(*digit)) + .collect::>() + } + }; + let output_atoms = (0..NUM_DIGITS) + .map(|digit_place| dd_struct.get_digit_witness_index(digit_place, witness_dd_counter)) + .collect::>(); + witness_dd_counter += 1; + + lh_atoms + .into_iter() + .zip(rh_atoms.into_iter()) + .zip(output_atoms.into_iter()) + .for_each(|((lh, rh), output)| { + inputs_and_outputs_atomic.push((lh, rh, output)); + }); + } + + let multiplicities_wb = WitnessBuilder::MultiplicitiesForBinOp( + r1cs_compiler.num_witnesses(), + inputs_and_outputs_atomic + .iter() + .map(|(lh_operand, rh_operand, _output)| (lh_operand.clone(), rh_operand.clone())) + .collect(), + ); + let multiplicities_first_witness = r1cs_compiler.add_witness_builder(multiplicities_wb); + + // Add two verifier challenges for the lookup + let sz_challenge = + r1cs_compiler.add_witness_builder(WitnessBuilder::Challenge(r1cs_compiler.num_witnesses())); + let rs_challenge = + r1cs_compiler.add_witness_builder(WitnessBuilder::Challenge(r1cs_compiler.num_witnesses())); + let rs_challenge_sqrd = r1cs_compiler.add_product(rs_challenge, rs_challenge); + + // Calculate the sum, over all invocations of the bin op, of 1 / denominator + let summands_for_bin_op = inputs_and_outputs_atomic + .into_iter() + .map(|(lh, rh, output)| { + add_lookup_summand( + r1cs_compiler, + sz_challenge, + rs_challenge, + rs_challenge_sqrd, + lh, + rh, + ConstantOrR1CSWitness::Witness(output), + ) + }) + .map(|coeff| SumTerm(None, coeff)) + .collect(); + let sum_for_bin_op = r1cs_compiler.add_sum(summands_for_bin_op); + + // Calculate the sum over all table elements of multiplicity / denominator + let summands_for_table = (0..1 << BINOP_ATOMIC_BITS) + .flat_map(|lh_operand: u32| { + (0..1 << BINOP_ATOMIC_BITS).map(move |rh_operand: u32| { + let output = match op { + BinOp::AND => lh_operand & rh_operand, + BinOp::XOR => lh_operand ^ rh_operand, + }; + (lh_operand, rh_operand, output) + }) + }) + .map(|(lh_operand, rh_operand, output)| { + let denominator = add_lookup_summand( + r1cs_compiler, + sz_challenge, + rs_challenge, + rs_challenge_sqrd, + ConstantOrR1CSWitness::Constant(FieldElement::from(lh_operand)), + ConstantOrR1CSWitness::Constant(FieldElement::from(rh_operand)), + ConstantOrR1CSWitness::Constant(FieldElement::from(output)), + ); + let multiplicity_witness_idx = multiplicities_first_witness + + (lh_operand << BINOP_ATOMIC_BITS) as usize + + rh_operand as usize; + r1cs_compiler.add_product(multiplicity_witness_idx, denominator) + }) + .map(|coeff| SumTerm(None, coeff)) + .collect(); + let sum_for_table = r1cs_compiler.add_sum(summands_for_table); + + // Check that these two sums are equal. + r1cs_compiler.r1cs.add_constraint( + &[(FieldElement::one(), r1cs_compiler.witness_one())], + &[(FieldElement::one(), sum_for_bin_op)], + &[(FieldElement::one(), sum_for_table)], + ); +} + +// Add and return a new witness `denominator` and constrain it to represent +// (assuming `output` is a witness): +// `w[sz_challenge] - (w[lh_operand] + w[rs_challenge] * w[rh_operand] + +// w[rs_challenge_sqrd] * w[output])` where `w` is the witness vector. If +// `output` is a constant, then the `rs_challenge_sqrd` is instead scaled by +// that constant. Finally, adds a new witness for the inverse of `denominator`, +// constrains it to be such, and returns its index. +fn add_lookup_summand( + r1cs_compiler: &mut NoirToR1CSCompiler, + sz_challenge: usize, + rs_challenge: usize, + rs_challenge_sqrd: usize, + lh_operand: ConstantOrR1CSWitness, + rh_operand: ConstantOrR1CSWitness, + output: ConstantOrR1CSWitness, +) -> usize { + let wb = WitnessBuilder::BinOpLookupDenominator( + r1cs_compiler.num_witnesses(), + sz_challenge, + rs_challenge, + rs_challenge_sqrd, + lh_operand.clone(), + rh_operand.clone(), + output.clone(), + ); + let denominator = r1cs_compiler.add_witness_builder(wb); + // Add an intermediate witness if the output is a witness (otherwise can just + // scale) + let rs_challenge_sqrd_summand = match output { + ConstantOrR1CSWitness::Constant(value) => (FieldElement::from(value), rs_challenge_sqrd), + ConstantOrR1CSWitness::Witness(witness) => ( + FieldElement::one(), + r1cs_compiler.add_product(rs_challenge_sqrd, witness), + ), + }; + r1cs_compiler.r1cs.add_constraint( + &[(FieldElement::one().neg(), rs_challenge)], + &[rh_operand.to_tuple()], + &[ + (FieldElement::one(), denominator), + (FieldElement::one().neg(), sz_challenge), + (lh_operand.to_tuple()), + rs_challenge_sqrd_summand, + ], + ); + let inverse = r1cs_compiler.add_witness_builder(WitnessBuilder::Inverse( + r1cs_compiler.num_witnesses(), + denominator, + )); + r1cs_compiler.r1cs.add_constraint( + &[(FieldElement::one(), denominator)], + &[(FieldElement::one(), inverse)], + &[(FieldElement::one(), r1cs_compiler.witness_one())], + ); + inverse +} diff --git a/noir-r1cs/src/digits.rs b/noir-r1cs/src/digits.rs index 699150087..661bc1a77 100644 --- a/noir-r1cs/src/digits.rs +++ b/noir-r1cs/src/digits.rs @@ -11,7 +11,7 @@ use { /// where each group of witnesses is in 1:1 correspondence with /// witnesses_to_decompose. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub(crate) struct DigitalDecompositionWitnesses { +pub struct DigitalDecompositionWitnesses { /// The log base of each digit (in little-endian order) pub log_bases: Vec, /// The number of witnesses to decompose diff --git a/noir-r1cs/src/lib.rs b/noir-r1cs/src/lib.rs index 26db3f73f..967a1c42a 100644 --- a/noir-r1cs/src/lib.rs +++ b/noir-r1cs/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../README.md")] #![allow(missing_docs)] +mod binops; mod digits; mod file; mod gnark_config; diff --git a/noir-r1cs/src/noir_to_r1cs.rs b/noir-r1cs/src/noir_to_r1cs.rs index 3fa0644f1..2e3400185 100644 --- a/noir-r1cs/src/noir_to_r1cs.rs +++ b/noir-r1cs/src/noir_to_r1cs.rs @@ -1,10 +1,12 @@ use { crate::{ + binops::{add_binop, BinOp}, memory::{MemoryBlock, MemoryOperation}, r1cs_solver::{ConstantTerm, SumTerm, WitnessBuilder}, ram::add_ram_checking, range_check::add_range_checks, rom::add_rom_checking, + serde_ark, utils::noir_to_native, FieldElement, NoirElement, R1CS, }, @@ -19,8 +21,11 @@ use { }, anyhow::{bail, Result}, ark_std::One, + serde::{Deserialize, Serialize}, std::{collections::BTreeMap, num::NonZeroU32, ops::Neg}, }; +/// The index of the constant 1 witness in the R1CS instance +pub const WITNESS_ONE_IDX: usize = 0; /// Compiles an ACIR circuit into an [R1CS] instance, comprising of the A, B, /// and C R1CS matrices, along with the witness vector. @@ -128,6 +133,23 @@ impl NoirToR1CSCompiler { }) } + // Convert a ConstantOrACIRWitness into a ConstantOrR1CSWitness, creating a new + // R1CS witness (and builder) if required. + fn fetch_constant_or_r1cs_witness( + &mut self, + constant_or_witness: ConstantOrACIRWitness, + ) -> ConstantOrR1CSWitness { + match constant_or_witness { + ConstantOrACIRWitness::Constant(c) => { + ConstantOrR1CSWitness::Constant(noir_to_native(c)) + } + ConstantOrACIRWitness::Witness(w) => { + let r1cs_witness = self.fetch_r1cs_witness_index(w); + ConstantOrR1CSWitness::Witness(r1cs_witness) + } + } + } + /// Add a new witness representing the product of two existing witnesses, /// and add an R1CS constraint enforcing this. pub(crate) fn add_product(&mut self, operand_a: usize, operand_b: usize) -> usize { @@ -221,6 +243,11 @@ impl NoirToR1CSCompiler { // are to be constrained within the range [0..2^k]. // These will be digitally decomposed into smaller ranges, if necessary. let mut range_checks: BTreeMap> = BTreeMap::new(); + // (input, input, output) tuples for AND and XOR operations. + // Inputs may be either constants or R1CS witnesses. + // Outputs are always R1CS witnesses. + let mut and_ops = vec![]; + let mut xor_ops = vec![]; for opcode in &circuit.opcodes { match opcode { @@ -333,6 +360,25 @@ impl NoirToR1CSCompiler { .push(input_witness); } + // Binary operations: + // The inputs and outputs will have already been solved for by the ACIR solver. + // Collect the R1CS witnesses indices so that we can later constrain them + // appropriately. + BlackBoxFuncCall::AND { lhs, rhs, output } => { + and_ops.push(( + self.fetch_constant_or_r1cs_witness(lhs.input()), + self.fetch_constant_or_r1cs_witness(rhs.input()), + self.fetch_r1cs_witness_index(*output), + )); + } + BlackBoxFuncCall::XOR { lhs, rhs, output } => { + xor_ops.push(( + self.fetch_constant_or_r1cs_witness(lhs.input()), + self.fetch_constant_or_r1cs_witness(rhs.input()), + self.fetch_r1cs_witness_index(*output), + )); + } + _ => { unimplemented!("Other black box function: {:?}", black_box_func_call); } @@ -359,9 +405,28 @@ impl NoirToR1CSCompiler { } }); + // For the AND and XOR operations, add the appropriate constraints. + add_binop(self, BinOp::AND, and_ops); + add_binop(self, BinOp::XOR, xor_ops); + // Perform all range checks add_range_checks(self, range_checks); Ok(()) } } + +#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] +pub enum ConstantOrR1CSWitness { + Constant(#[serde(with = "serde_ark")] FieldElement), + Witness(usize), +} + +impl ConstantOrR1CSWitness { + pub fn to_tuple(&self) -> (FieldElement, usize) { + match self { + ConstantOrR1CSWitness::Constant(c) => (*c, WITNESS_ONE_IDX), + ConstantOrR1CSWitness::Witness(w) => (FieldElement::one(), *w), + } + } +} diff --git a/noir-r1cs/src/r1cs_solver.rs b/noir-r1cs/src/r1cs_solver.rs index c20f39deb..e8ef7248c 100644 --- a/noir-r1cs/src/r1cs_solver.rs +++ b/noir-r1cs/src/r1cs_solver.rs @@ -1,6 +1,8 @@ use { crate::{ + binops::BINOP_ATOMIC_BITS, digits::DigitalDecompositionWitnesses, + noir_to_r1cs::ConstantOrR1CSWitness, ram::SpiceWitnesses, utils::{noir_to_native, serde_ark, serde_ark_option}, FieldElement, @@ -94,6 +96,22 @@ pub enum WitnessBuilder { /// (Note that some witness values are already solved for by the ACIR /// solver.) SpiceWitnesses(SpiceWitnesses), + /// A witness value for the denominator of a bin op lookup. + /// Arguments: `(witness index, sz_challenge, rs_challenge, + /// rs_challenge_sqrd, lhs, rhs, output)`, where `lhs`, `rhs`, and + /// `output` are either constant or witness values. + BinOpLookupDenominator( + usize, + usize, + usize, + usize, + ConstantOrR1CSWitness, + ConstantOrR1CSWitness, + ConstantOrR1CSWitness, + ), + /// Witness values for the number of times that each pair of input values + /// occurs in the bin op. + MultiplicitiesForBinOp(usize, Vec<(ConstantOrR1CSWitness, ConstantOrR1CSWitness)>), } impl WitnessBuilder { @@ -106,6 +124,7 @@ impl WitnessBuilder { WitnessBuilder::SpiceWitnesses(spice_witnesses_struct) => { spice_witnesses_struct.num_witnesses } + WitnessBuilder::MultiplicitiesForBinOp(..) => 2usize.pow(2 * BINOP_ATOMIC_BITS as u32), _ => 1, } } @@ -128,6 +147,9 @@ impl WitnessBuilder { WitnessBuilder::SpiceWitnesses(spice_witnesses_struct) => { spice_witnesses_struct.first_witness_idx } + + WitnessBuilder::BinOpLookupDenominator(start_idx, ..) => *start_idx, + WitnessBuilder::MultiplicitiesForBinOp(start_idx, _) => *start_idx, } } @@ -258,6 +280,57 @@ impl WitnessBuilder { WitnessBuilder::SpiceWitnesses(spice_witnesses) => { spice_witnesses.solve(witness); } + WitnessBuilder::BinOpLookupDenominator( + witness_idx, + sz_challenge, + rs_challenge, + rs_challenge_sqrd, + lhs, + rhs, + output, + ) => { + let lhs = match lhs { + ConstantOrR1CSWitness::Constant(c) => *c, + ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx].unwrap(), + }; + let rhs = match rhs { + ConstantOrR1CSWitness::Constant(c) => *c, + ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx].unwrap(), + }; + let output = match output { + ConstantOrR1CSWitness::Constant(c) => *c, + ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx].unwrap(), + }; + witness[*witness_idx] = Some( + witness[*sz_challenge].unwrap() + - (lhs + + witness[*rs_challenge].unwrap() * rhs + + witness[*rs_challenge_sqrd].unwrap() * output), + ); + } + WitnessBuilder::MultiplicitiesForBinOp(witness_idx, operands) => { + let mut multiplicities = vec![0u32; 2usize.pow(2 * BINOP_ATOMIC_BITS as u32)]; + for (lhs, rhs) in operands { + let lhs = match lhs { + ConstantOrR1CSWitness::Constant(c) => *c, + ConstantOrR1CSWitness::Witness(witness_idx) => { + witness[*witness_idx].unwrap() + } + }; + let rhs = match rhs { + ConstantOrR1CSWitness::Constant(c) => *c, + ConstantOrR1CSWitness::Witness(witness_idx) => { + witness[*witness_idx].unwrap() + } + }; + let index = + (lhs.into_bigint().0[0] << BINOP_ATOMIC_BITS) + rhs.into_bigint().0[0]; + multiplicities[index as usize] += 1; + } + for (i, count) in multiplicities.iter().enumerate() { + witness[witness_idx + i] = Some(FieldElement::from(*count)); + } + } } } } diff --git a/noir-r1cs/src/ram.rs b/noir-r1cs/src/ram.rs index 50ee64a6f..28d2c4856 100644 --- a/noir-r1cs/src/ram.rs +++ b/noir-r1cs/src/ram.rs @@ -13,7 +13,7 @@ use { /// Like [MemoryOperation], but with the indices of the additional witnesses /// needed by Spice. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub(crate) enum SpiceMemoryOperation { +pub enum SpiceMemoryOperation { /// Load operation. Arguments are R1CS witness indices: /// (address, value read, read timestamp) /// `address` is already solved for by the ACIR solver. @@ -26,7 +26,7 @@ pub(crate) enum SpiceMemoryOperation { } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub(crate) struct SpiceWitnesses { +pub struct SpiceWitnesses { /// The length of the memory block pub memory_length: usize, /// The witness index of the first initial value (they are stored diff --git a/noir-r1cs/src/rom.rs b/noir-r1cs/src/rom.rs index 3b7f26c82..9754e0b01 100644 --- a/noir-r1cs/src/rom.rs +++ b/noir-r1cs/src/rom.rs @@ -7,7 +7,6 @@ use { }, ark_std::One, std::ops::Neg, - tracing::field::Field, }; /// Add witnesses and constraints enforcing the integrity of read operations diff --git a/noir-r1cs/src/test_functions.rs b/noir-r1cs/src/test_functions.rs index af01fe177..4240fd9db 100644 --- a/noir-r1cs/src/test_functions.rs +++ b/noir-r1cs/src/test_functions.rs @@ -108,3 +108,11 @@ fn test_conditional_write() { "../noir-examples/noir-r1cs-test-programs/conditional-write/target/main.gz", ); } + +#[test] +fn test_binops() { + test_compiler( + "../noir-examples/noir-r1cs-test-programs/bin-opcode/target/main.json", + "../noir-examples/noir-r1cs-test-programs/bin-opcode/target/main.gz", + ); +} From 2ad208a557662a8d5382ba768ec073a60f709bdc Mon Sep 17 00:00:00 2001 From: vishruti Date: Thu, 22 May 2025 13:22:03 -0700 Subject: [PATCH 2/3] deleted noir-r1cs-logup directory --- noir-r1cs-logup/Cargo.toml | 33 - noir-r1cs-logup/README.md | 25 - noir-r1cs-logup/noir-examples/.gitignore | 2 - .../noir-examples/basic-2/Nargo.toml | 8 - .../noir-examples/basic-2/Prover.toml | 7 - .../noir-examples/basic-2/prove.sh | 8 - .../noir-examples/basic-2/src/main.nr | 3 - .../noir-examples/basic-3/Nargo.toml | 8 - .../noir-examples/basic-3/Prover.toml | 4 - .../noir-examples/basic-3/prove.sh | 8 - .../noir-examples/basic-3/src/main.nr | 41 - .../noir-examples/basic/Nargo.toml | 8 - .../noir-examples/basic/Prover.toml | 7 - noir-r1cs-logup/noir-examples/basic/prove.sh | 8 - .../noir-examples/basic/src/main.nr | 7 - .../noir-examples/poseidon-rounds/Nargo.toml | 8 - .../noir-examples/poseidon-rounds/Prover.toml | 7 - .../noir-examples/poseidon-rounds/prove.sh | 8 - .../noir-examples/poseidon-rounds/src/main.nr | 11 - .../noir-examples/poseidon-var/Nargo.toml | 8 - .../noir-examples/poseidon-var/Prover.toml | 2 - .../noir-examples/poseidon-var/prove.sh | 8 - .../noir-examples/poseidon-var/src/main.nr | 44 - .../noir-examples/sha256/Nargo.toml | 7 - .../noir-examples/sha256/src/main.nr | 70 - .../noir-examples/zkchase/Nargo.toml | 7 - .../noir-examples/zkchase/Prover.toml | 12 - .../noir-examples/zkchase/prove.sh | 8 - .../noir-examples/zkchase/src/main.nr | 238 --- noir-r1cs-logup/scripts/all_outputs.txt | 1744 ----------------- noir-r1cs-logup/scripts/run_all.sh | 6 - noir-r1cs-logup/src/bin/circuit_stats.rs | 517 ----- noir-r1cs-logup/src/binops.rs | 213 -- noir-r1cs-logup/src/compiler.rs | 450 ----- noir-r1cs-logup/src/digits.rs | 210 -- noir-r1cs-logup/src/main.rs | 101 - noir-r1cs-logup/src/memory.rs | 32 - noir-r1cs-logup/src/r1cs_matrices.rs | 180 -- noir-r1cs-logup/src/ram.rs | 317 --- noir-r1cs-logup/src/range_check.rs | 204 -- noir-r1cs-logup/src/rom.rs | 118 -- noir-r1cs-logup/src/solver.rs | 314 --- noir-r1cs-logup/src/sparse_matrix.rs | 155 -- noir-r1cs-logup/src/test_compiler.rs | 126 -- .../src/test_programs/bin-opcode/Nargo.toml | 6 - .../src/test_programs/bin-opcode/Prover.toml | 4 - .../src/test_programs/bin-opcode/src/main.nr | 6 - .../test_programs/bin-opcode/target/main.gz | Bin 105 -> 0 bytes .../test_programs/bin-opcode/target/main.json | 1 - .../brillig-conditional/Nargo.toml | 6 - .../brillig-conditional/Prover.toml | 2 - .../brillig-conditional/src/main.nr | 5 - .../brillig-conditional/target/main.gz | Bin 60 -> 0 bytes .../brillig-conditional/target/main.json | 1 - .../conditional-write/Nargo.toml | 6 - .../conditional-write/Prover.toml | 4 - .../conditional-write/src/main.nr | 6 - .../conditional-write/target/main.gz | Bin 116 -> 0 bytes .../conditional-write/target/main.json | 1 - .../range-check-mixed-bases/Nargo.toml | 6 - .../range-check-mixed-bases/Prover.toml | 2 - .../range-check-mixed-bases/src/main.nr | 3 - .../range-check-mixed-bases/target/main.gz | Bin 148 -> 0 bytes .../range-check-mixed-bases/target/main.json | 1 - .../test_programs/range-check-u16/Nargo.toml | 6 - .../test_programs/range-check-u16/Prover.toml | 1 - .../test_programs/range-check-u16/src/main.nr | 1 - .../range-check-u16/target/main.gz | Bin 49 -> 0 bytes .../range-check-u16/target/main.json | 1 - .../test_programs/range-check-u8/Nargo.toml | 6 - .../test_programs/range-check-u8/Prover.toml | 1 - .../test_programs/range-check-u8/src/main.nr | 1 - .../range-check-u8/target/main.gz | Bin 46 -> 0 bytes .../range-check-u8/target/main.json | 1 - .../test_programs/read-only-memory/Nargo.toml | 6 - .../read-only-memory/Prover.toml | 4 - .../read-only-memory/src/main.nr | 3 - .../read-only-memory/target/main.gz | Bin 92 -> 0 bytes .../read-only-memory/target/main.json | 1 - .../read-write-memory/Nargo.toml | 6 - .../read-write-memory/Prover.toml | 4 - .../read-write-memory/src/main.nr | 6 - .../read-write-memory/target/main.gz | Bin 78 -> 0 bytes .../read-write-memory/target/main.json | 1 - .../simplest-read-only-memory/Nargo.toml | 6 - .../simplest-read-only-memory/Prover.toml | 2 - .../simplest-read-only-memory/src/main.nr | 3 - .../simplest-read-only-memory/target/main.gz | Bin 61 -> 0 bytes .../target/main.json | 1 - noir-r1cs-logup/src/utils/file_io.rs | 26 - noir-r1cs-logup/src/utils/mod.rs | 3 - noir-r1cs-logup/src/utils/print_abi.rs | 62 - noir-r1cs/src/test_functions.rs | 6 +- 93 files changed, 4 insertions(+), 5516 deletions(-) delete mode 100644 noir-r1cs-logup/Cargo.toml delete mode 100644 noir-r1cs-logup/README.md delete mode 100644 noir-r1cs-logup/noir-examples/.gitignore delete mode 100644 noir-r1cs-logup/noir-examples/basic-2/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/basic-2/Prover.toml delete mode 100755 noir-r1cs-logup/noir-examples/basic-2/prove.sh delete mode 100644 noir-r1cs-logup/noir-examples/basic-2/src/main.nr delete mode 100644 noir-r1cs-logup/noir-examples/basic-3/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/basic-3/Prover.toml delete mode 100755 noir-r1cs-logup/noir-examples/basic-3/prove.sh delete mode 100644 noir-r1cs-logup/noir-examples/basic-3/src/main.nr delete mode 100644 noir-r1cs-logup/noir-examples/basic/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/basic/Prover.toml delete mode 100755 noir-r1cs-logup/noir-examples/basic/prove.sh delete mode 100644 noir-r1cs-logup/noir-examples/basic/src/main.nr delete mode 100644 noir-r1cs-logup/noir-examples/poseidon-rounds/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/poseidon-rounds/Prover.toml delete mode 100755 noir-r1cs-logup/noir-examples/poseidon-rounds/prove.sh delete mode 100644 noir-r1cs-logup/noir-examples/poseidon-rounds/src/main.nr delete mode 100644 noir-r1cs-logup/noir-examples/poseidon-var/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/poseidon-var/Prover.toml delete mode 100755 noir-r1cs-logup/noir-examples/poseidon-var/prove.sh delete mode 100644 noir-r1cs-logup/noir-examples/poseidon-var/src/main.nr delete mode 100644 noir-r1cs-logup/noir-examples/sha256/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/sha256/src/main.nr delete mode 100644 noir-r1cs-logup/noir-examples/zkchase/Nargo.toml delete mode 100644 noir-r1cs-logup/noir-examples/zkchase/Prover.toml delete mode 100755 noir-r1cs-logup/noir-examples/zkchase/prove.sh delete mode 100644 noir-r1cs-logup/noir-examples/zkchase/src/main.nr delete mode 100644 noir-r1cs-logup/scripts/all_outputs.txt delete mode 100644 noir-r1cs-logup/scripts/run_all.sh delete mode 100644 noir-r1cs-logup/src/bin/circuit_stats.rs delete mode 100644 noir-r1cs-logup/src/binops.rs delete mode 100644 noir-r1cs-logup/src/compiler.rs delete mode 100644 noir-r1cs-logup/src/digits.rs delete mode 100644 noir-r1cs-logup/src/main.rs delete mode 100644 noir-r1cs-logup/src/memory.rs delete mode 100644 noir-r1cs-logup/src/r1cs_matrices.rs delete mode 100644 noir-r1cs-logup/src/ram.rs delete mode 100644 noir-r1cs-logup/src/range_check.rs delete mode 100644 noir-r1cs-logup/src/rom.rs delete mode 100644 noir-r1cs-logup/src/solver.rs delete mode 100644 noir-r1cs-logup/src/sparse_matrix.rs delete mode 100644 noir-r1cs-logup/src/test_compiler.rs delete mode 100644 noir-r1cs-logup/src/test_programs/bin-opcode/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/bin-opcode/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/bin-opcode/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/bin-opcode/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/bin-opcode/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/brillig-conditional/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/brillig-conditional/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/brillig-conditional/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/conditional-write/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/conditional-write/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/conditional-write/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/conditional-write/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/conditional-write/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-mixed-bases/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-mixed-bases/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-mixed-bases/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u16/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u16/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u16/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u16/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u16/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u8/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u8/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u8/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u8/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/range-check-u8/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/read-only-memory/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/read-only-memory/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/read-only-memory/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/read-only-memory/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/read-only-memory/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/read-write-memory/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/read-write-memory/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/read-write-memory/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/read-write-memory/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/read-write-memory/target/main.json delete mode 100644 noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Nargo.toml delete mode 100644 noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Prover.toml delete mode 100644 noir-r1cs-logup/src/test_programs/simplest-read-only-memory/src/main.nr delete mode 100644 noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.gz delete mode 100644 noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.json delete mode 100644 noir-r1cs-logup/src/utils/file_io.rs delete mode 100644 noir-r1cs-logup/src/utils/mod.rs delete mode 100644 noir-r1cs-logup/src/utils/print_abi.rs diff --git a/noir-r1cs-logup/Cargo.toml b/noir-r1cs-logup/Cargo.toml deleted file mode 100644 index 8b1615d43..000000000 --- a/noir-r1cs-logup/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -[package] -name = "noir-r1cs-logup" -version = "0.1.0" -edition = "2021" - -[lints] -workspace = true - -[dependencies] -argh.workspace = true -serde.workspace = true -serde_json.workspace = true -anyhow.workspace = true -tracing.workspace = true -tracing-subscriber.workspace = true -base64.workspace = true -clap = { version = "4.4", features = ["derive"] } - -# Noir lang -acir.workspace = true -acvm.workspace = true -acir_field.workspace = true -noirc_artifacts.workspace = true -noirc_abi.workspace = true -noirc_printable_type.workspace = true -rand.workspace = true - -flate2 = "1.0" -bincode = "1.3" - -[[bin]] -name = "circuit_stats" -path = "src/bin/circuit_stats.rs" \ No newline at end of file diff --git a/noir-r1cs-logup/README.md b/noir-r1cs-logup/README.md deleted file mode 100644 index bc0e9a037..000000000 --- a/noir-r1cs-logup/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# noir-r1cs - -PROTOTYPE: DO NOT USE IN PRODUCTION - -### Compile and generate witness -``` -nargo compile && nargo execute witness -``` - -### Generate R1CS -``` -cargo run -- r1cs noir-examples/basic/target/basic.json noir-examples/basic/target/witness.gz -``` - -Example output: -``` -Private inputs: 1 -Public inputs: 3 -Return values: 0 -Opcodes: 1 -Witnesses: 5 -Constraints: 1 -([0, 1, 0, 0, 0] x [1, 1, 2, 3, 5]ᵀ) * ([0, 0, 1, 0, 0] x [1, 1, 2, 3, 5]ᵀ) = ([0, 0, 0, -1, 1] x [1, 1, 2, 3, 5]ᵀ) -✅ All constraints are valid. -``` \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/.gitignore b/noir-r1cs-logup/noir-examples/.gitignore deleted file mode 100644 index 1905b4954..000000000 --- a/noir-r1cs-logup/noir-examples/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# Target folders from Noir -target diff --git a/noir-r1cs-logup/noir-examples/basic-2/Nargo.toml b/noir-r1cs-logup/noir-examples/basic-2/Nargo.toml deleted file mode 100644 index bc5f0b6a3..000000000 --- a/noir-r1cs-logup/noir-examples/basic-2/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "basic" -type = "bin" -authors = [""] -compiler_version = ">=0.22.0" - -[dependencies] -poseidon2 = { tag = "main", git = "https://github.com/TaceoLabs/noir-poseidon", directory = "poseidon2"} diff --git a/noir-r1cs-logup/noir-examples/basic-2/Prover.toml b/noir-r1cs-logup/noir-examples/basic-2/Prover.toml deleted file mode 100644 index e93ce04cf..000000000 --- a/noir-r1cs-logup/noir-examples/basic-2/Prover.toml +++ /dev/null @@ -1,7 +0,0 @@ -plains = [1,2] -a = 1 -b = 2 -c = 3 -d = 5 -x = 0 -result = '0x0e90c132311e864e0c8bca37976f28579a2dd9436bbc11326e21ec7c00cea5b2' \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/basic-2/prove.sh b/noir-r1cs-logup/noir-examples/basic-2/prove.sh deleted file mode 100755 index 7d0069674..000000000 --- a/noir-r1cs-logup/noir-examples/basic-2/prove.sh +++ /dev/null @@ -1,8 +0,0 @@ -nargo compile -nargo check -nargo execute my-witness -bb prove -b ./target/basic.json -w ./target/my-witness.gz -o ./target/proof -echo "✅ Proof generated at ./target/proof" -bb write_vk -b ./target/basic.json -o ./target/vk -bb verify -k ./target/vk -p ./target/proof -echo "✅ Verified the proof at ./target/proof" diff --git a/noir-r1cs-logup/noir-examples/basic-2/src/main.nr b/noir-r1cs-logup/noir-examples/basic-2/src/main.nr deleted file mode 100644 index e864054a1..000000000 --- a/noir-r1cs-logup/noir-examples/basic-2/src/main.nr +++ /dev/null @@ -1,3 +0,0 @@ -fn main(a: Field, b: Field, c: Field, d: Field) { - assert(a * b + c + d == 10); -} diff --git a/noir-r1cs-logup/noir-examples/basic-3/Nargo.toml b/noir-r1cs-logup/noir-examples/basic-3/Nargo.toml deleted file mode 100644 index bc5f0b6a3..000000000 --- a/noir-r1cs-logup/noir-examples/basic-3/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "basic" -type = "bin" -authors = [""] -compiler_version = ">=0.22.0" - -[dependencies] -poseidon2 = { tag = "main", git = "https://github.com/TaceoLabs/noir-poseidon", directory = "poseidon2"} diff --git a/noir-r1cs-logup/noir-examples/basic-3/Prover.toml b/noir-r1cs-logup/noir-examples/basic-3/Prover.toml deleted file mode 100644 index d661159bb..000000000 --- a/noir-r1cs-logup/noir-examples/basic-3/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -i = 1 -j = 7 -k = 3 -l = 1 \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/basic-3/prove.sh b/noir-r1cs-logup/noir-examples/basic-3/prove.sh deleted file mode 100755 index 7d0069674..000000000 --- a/noir-r1cs-logup/noir-examples/basic-3/prove.sh +++ /dev/null @@ -1,8 +0,0 @@ -nargo compile -nargo check -nargo execute my-witness -bb prove -b ./target/basic.json -w ./target/my-witness.gz -o ./target/proof -echo "✅ Proof generated at ./target/proof" -bb write_vk -b ./target/basic.json -o ./target/vk -bb verify -k ./target/vk -p ./target/proof -echo "✅ Verified the proof at ./target/proof" diff --git a/noir-r1cs-logup/noir-examples/basic-3/src/main.nr b/noir-r1cs-logup/noir-examples/basic-3/src/main.nr deleted file mode 100644 index 7ce9d5adb..000000000 --- a/noir-r1cs-logup/noir-examples/basic-3/src/main.nr +++ /dev/null @@ -1,41 +0,0 @@ -fn main(i: Field, j: Field, k: Field, l: Field) { - assert(3 * i * j * l + 2 * (k + 1) * (l + 5) + 1 == (l + 13) * 5); - // assert((i + j) * k * l + (j - i) * (k + l) == 48); - // assert(j * j - i * k * l + (l + k) * (i + j) == 78); - // assert((i * j + k) * (l + 2) - j == 23); - // // Complex nested operations with multiple terms - // assert((i * j * j + k * k) * (l + i) + (j - k) * (j + k) == 156); - - // // Using squares and products with multiple groupings - // assert((j * j * j - k * k * i) * l + (i + l) * (j + k) == 354); - - // // Multiple groups with mixed operations - // assert((i + j) * (j - k) * (k + l) + (j * j - i) * (k - l) == 224); - - // // Nested multiplications with additions and subtractions - // assert((((i + j) * k - l) * (j - k) + i) * (l + k) == 372); - - // // Very complex grouping with multiple terms - // assert((i * j + k * l) * (j * j - k) + (l + i) * (j - k) * (k + i) == 492); - - // // Using differences of squares pattern with extra terms - // assert((j + k) * (j - k) + (i * l) * (j * j - k * k) + l == 81); - - // // Complex polynomial with nested terms - // assert((j * j * j - k * k * i) * (l + i) + (j * k - i) * (j * j - k * l) == 1588); - - // // Nested products with multiple groupings and differences - // assert((j * j + k * i) * (j - k) * (l + k) - (i + l) * (k * k * j) == 706); - - // // Complex cubic terms with mixed operations - // assert((j + k) * (j * j - k * k) * (l + i) + (j - i) * k * (k + l) == 872); - - // // Multiple nested groups with squares and products - // assert((j * j - i) * (k * k + l) * (j - k) + (i + l) * (j * k - l) == 1960); - - // // Complex differences with cubic terms - // assert((j * j * j - k * k * k) * (l + i) - (j - k) * (j + k) * (j * l) == 352); - - // // Nested operations with multiple factors - // assert((j * k + i * l) * (j * j - k * l) * (k + i) - (j - l) * k * k == 3994); -} diff --git a/noir-r1cs-logup/noir-examples/basic/Nargo.toml b/noir-r1cs-logup/noir-examples/basic/Nargo.toml deleted file mode 100644 index bc5f0b6a3..000000000 --- a/noir-r1cs-logup/noir-examples/basic/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "basic" -type = "bin" -authors = [""] -compiler_version = ">=0.22.0" - -[dependencies] -poseidon2 = { tag = "main", git = "https://github.com/TaceoLabs/noir-poseidon", directory = "poseidon2"} diff --git a/noir-r1cs-logup/noir-examples/basic/Prover.toml b/noir-r1cs-logup/noir-examples/basic/Prover.toml deleted file mode 100644 index e93ce04cf..000000000 --- a/noir-r1cs-logup/noir-examples/basic/Prover.toml +++ /dev/null @@ -1,7 +0,0 @@ -plains = [1,2] -a = 1 -b = 2 -c = 3 -d = 5 -x = 0 -result = '0x0e90c132311e864e0c8bca37976f28579a2dd9436bbc11326e21ec7c00cea5b2' \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/basic/prove.sh b/noir-r1cs-logup/noir-examples/basic/prove.sh deleted file mode 100755 index 7d0069674..000000000 --- a/noir-r1cs-logup/noir-examples/basic/prove.sh +++ /dev/null @@ -1,8 +0,0 @@ -nargo compile -nargo check -nargo execute my-witness -bb prove -b ./target/basic.json -w ./target/my-witness.gz -o ./target/proof -echo "✅ Proof generated at ./target/proof" -bb write_vk -b ./target/basic.json -o ./target/vk -bb verify -k ./target/vk -p ./target/proof -echo "✅ Verified the proof at ./target/proof" diff --git a/noir-r1cs-logup/noir-examples/basic/src/main.nr b/noir-r1cs-logup/noir-examples/basic/src/main.nr deleted file mode 100644 index 8afc3e9da..000000000 --- a/noir-r1cs-logup/noir-examples/basic/src/main.nr +++ /dev/null @@ -1,7 +0,0 @@ -use dep::poseidon2; - -fn main(plains: [Field; 2], result: Field) { - let hash = poseidon2::bn254::hash_2(plains); - print(hash); - assert(hash == result); -} diff --git a/noir-r1cs-logup/noir-examples/poseidon-rounds/Nargo.toml b/noir-r1cs-logup/noir-examples/poseidon-rounds/Nargo.toml deleted file mode 100644 index bc5f0b6a3..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-rounds/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "basic" -type = "bin" -authors = [""] -compiler_version = ">=0.22.0" - -[dependencies] -poseidon2 = { tag = "main", git = "https://github.com/TaceoLabs/noir-poseidon", directory = "poseidon2"} diff --git a/noir-r1cs-logup/noir-examples/poseidon-rounds/Prover.toml b/noir-r1cs-logup/noir-examples/poseidon-rounds/Prover.toml deleted file mode 100644 index 56b7f8a0a..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-rounds/Prover.toml +++ /dev/null @@ -1,7 +0,0 @@ -plains = [1,2] -a = 1 -b = 2 -c = 3 -d = 5 -x = 0 -result = '0x0b5b6e4be36ffe606c2f640d972634fcf030bd0346eadcec12d0e3b95bf7f523' \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/poseidon-rounds/prove.sh b/noir-r1cs-logup/noir-examples/poseidon-rounds/prove.sh deleted file mode 100755 index 7d0069674..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-rounds/prove.sh +++ /dev/null @@ -1,8 +0,0 @@ -nargo compile -nargo check -nargo execute my-witness -bb prove -b ./target/basic.json -w ./target/my-witness.gz -o ./target/proof -echo "✅ Proof generated at ./target/proof" -bb write_vk -b ./target/basic.json -o ./target/vk -bb verify -k ./target/vk -p ./target/proof -echo "✅ Verified the proof at ./target/proof" diff --git a/noir-r1cs-logup/noir-examples/poseidon-rounds/src/main.nr b/noir-r1cs-logup/noir-examples/poseidon-rounds/src/main.nr deleted file mode 100644 index 646d1d429..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-rounds/src/main.nr +++ /dev/null @@ -1,11 +0,0 @@ -use dep::poseidon2; - -fn main(plains: [Field; 2], result: Field) { - let mut hash = poseidon2::bn254::hash_2(plains); - let rounds = 1000; - for _ in 0..rounds { - hash = poseidon2::bn254::hash_1([hash]); - } - println(hash); - assert(hash == result); -} diff --git a/noir-r1cs-logup/noir-examples/poseidon-var/Nargo.toml b/noir-r1cs-logup/noir-examples/poseidon-var/Nargo.toml deleted file mode 100644 index bc5f0b6a3..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-var/Nargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "basic" -type = "bin" -authors = [""] -compiler_version = ">=0.22.0" - -[dependencies] -poseidon2 = { tag = "main", git = "https://github.com/TaceoLabs/noir-poseidon", directory = "poseidon2"} diff --git a/noir-r1cs-logup/noir-examples/poseidon-var/Prover.toml b/noir-r1cs-logup/noir-examples/poseidon-var/Prover.toml deleted file mode 100644 index d5ccb416b..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-var/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -plains = [1] -result = "0x019aacea87290b7f5d4c9533494a19308f8e2590a6fb18aa64b3f965af924eb3" diff --git a/noir-r1cs-logup/noir-examples/poseidon-var/prove.sh b/noir-r1cs-logup/noir-examples/poseidon-var/prove.sh deleted file mode 100755 index 7d0069674..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-var/prove.sh +++ /dev/null @@ -1,8 +0,0 @@ -nargo compile -nargo check -nargo execute my-witness -bb prove -b ./target/basic.json -w ./target/my-witness.gz -o ./target/proof -echo "✅ Proof generated at ./target/proof" -bb write_vk -b ./target/basic.json -o ./target/vk -bb verify -k ./target/vk -p ./target/proof -echo "✅ Verified the proof at ./target/proof" diff --git a/noir-r1cs-logup/noir-examples/poseidon-var/src/main.nr b/noir-r1cs-logup/noir-examples/poseidon-var/src/main.nr deleted file mode 100644 index 81301deec..000000000 --- a/noir-r1cs-logup/noir-examples/poseidon-var/src/main.nr +++ /dev/null @@ -1,44 +0,0 @@ -use dep::poseidon2; - -fn hash_variable_input(input: [Field]) -> Field { - let input_size = input.len(); - // Number of permutation events needed (ceiling of input_size/3) - let num_perm_events = (input_size + 2) / 3; - - // Initial state with IV (input length) in last position - // Note: << 64 in Noir would be done differently, using field arithmetic - let iv = input_size as Field; // Simplified IV for example - let mut perm_state = [0, 0, 0, iv]; - - // Process input in chunks of 3 - let mut processed = 0; - for _i in 0..num_perm_events { - // Determine chunk size (3 or remaining elements) - let chunk_size = if input_size - processed >= 3 { - 3 - } else { - input_size - processed - }; - - // Absorb input chunk into state - for j in 0..chunk_size { - perm_state[j] = perm_state[j] + input[processed + j]; - } - - println(perm_state); - // Apply permutation (using x5_4 as it handles 4-element state) - // perm_state = poseidon2::bn254::perm::x5_4(perm_state); - println(perm_state); - - processed += chunk_size; - } - - // Return first element as hash result - perm_state[0] -} - -fn main(plains: [Field; 1], result: Field) { - let hash = hash_variable_input(plains); - println(hash); - assert(hash == 1); -} diff --git a/noir-r1cs-logup/noir-examples/sha256/Nargo.toml b/noir-r1cs-logup/noir-examples/sha256/Nargo.toml deleted file mode 100644 index 91f9bd009..000000000 --- a/noir-r1cs-logup/noir-examples/sha256/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "sha256" -type = "bin" -authors = [""] -compiler_version = ">=0.36.0" - -[dependencies] diff --git a/noir-r1cs-logup/noir-examples/sha256/src/main.nr b/noir-r1cs-logup/noir-examples/sha256/src/main.nr deleted file mode 100644 index 0a01b0766..000000000 --- a/noir-r1cs-logup/noir-examples/sha256/src/main.nr +++ /dev/null @@ -1,70 +0,0 @@ -// Sha256 example -// -// Calls Sha256 from the standard library. -// -// The Compiler sees this special function and creates an ACIR gate -// -// The ACIR SHA256 gate is passed to PLONK who should -// know how to create the necessary constraints. -// -// Not yet here: For R1CS, it is more about manipulating arithmetic gates to get performance -// This can be done in ACIR! -fn main(x: Field, result: [u8; 32], input: [u8; 2], toggle: bool) { - let x = hash(x, 1234); - - // We use the `as` keyword here to denote the fact that we want to take just the first byte from the x Field - // The padding is taken care of by the program - // docs:start:sha256_var - let digest = std::hash::sha256_var([x as u8], 1); - // docs:end:sha256_var - assert(digest == result); - - - let digest = std::hash::sha256([x as u8]); - assert(digest == result); - - // variable size - let size: Field = 1 + toggle as Field; - let var_sha = std::hash::sha256_var(input, size as u64); - assert(var_sha == std::hash::sha256_var(input, 1)); -} - -fn sq(x: Field) -> Field { - x * x -} - -fn cu(x: Field) -> Field { - x * x * x -} - -// hashes two inputs -fn hash(val: Field, salt: Field) -> Field { - // let mut slt = salt as u64; - // let val = val as u64; - let salts = [ - 0xf8bf3bd6c22ba3b1bf3ab2e3fb40818cd4217ffbaf294ca42331d4e3043a0a6, - 0x388c9fcf30fc2841d648f46bad01dd10bee9dc184d25eabc9f617021109cec3, - 0x2bb7f397c5941ac67befa8b232f15c8853dac263da793555441a90cec83b6454, - 0x17f389b52f9ea7a98874a4a31ef6a7beb43fb17db0e499250bb3f0181c59fb21, - 0x3a2090eacb897a31fb10561d560a9aeec24b7ad14d17b145f20c875a0b28c7c, - 0xc398534f0eb580f1fe4bf64553389e67cca4714399430e09619dcbee17ba099, - 0x7095ac9fda46afa7f181259e3635feffa7f11ee63f3ee777a5cebf4822328c4, - 0x2046f7cf1c8f13ef2b69cbc8bc0d5d809f82568abe2b33d1cd060958b1ced683, - ]; - - let v = val * salts[0]; - let v = v * v * v * (salt + salts[1]); // v ** 3 - let v = sq(sq(v)) * v * (salt + salts[2]); // v ** 5 - let v2 = sq(v); - let v = cu(v2) * v * (salt + salts[3]); // v ** 7 - let v2 = sq(v); - let v4 = sq(v2); - let v = sq(v4) * v2 * v * (salt + salts[5]); // v ** 11 - let v4 = sq(sq(v)); - let v = cu(v4) * v * (salt + salts[6]); // v ** 13 - let v = sq(sq(sq(sq(v)))) * v * (salt + salts[7]); // v ** 17 - let v2 = sq(v); - let v = sq(sq(sq(v2))) * v2 * v * (salt + salts[7]); // v ** 19 - - v -} diff --git a/noir-r1cs-logup/noir-examples/zkchase/Nargo.toml b/noir-r1cs-logup/noir-examples/zkchase/Nargo.toml deleted file mode 100644 index 51f3b40db..000000000 --- a/noir-r1cs-logup/noir-examples/zkchase/Nargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "zkchase" -type = "bin" -authors = [""] -compiler_version = ">=0.27.0" - -[dependencies] \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/zkchase/Prover.toml b/noir-r1cs-logup/noir-examples/zkchase/Prover.toml deleted file mode 100644 index 628234d49..000000000 --- a/noir-r1cs-logup/noir-examples/zkchase/Prover.toml +++ /dev/null @@ -1,12 +0,0 @@ -move = "2" -prev_pos = "0x705" -prev_pos_hash = "0x1ff93a22ebf9b6c02df123d028598a51a2f3ce93c675b5d4a8d7ae4de5953a18" -salt = "2134924215" - -[map1] -lo = "0xf31e01c1ce703398" -hi = "0x018630739f9feef3" - -[map0] -lo = "0xf3ddfe7e73831860" -hi = "0x0673039ce0e01e33" \ No newline at end of file diff --git a/noir-r1cs-logup/noir-examples/zkchase/prove.sh b/noir-r1cs-logup/noir-examples/zkchase/prove.sh deleted file mode 100755 index 1b22c97b8..000000000 --- a/noir-r1cs-logup/noir-examples/zkchase/prove.sh +++ /dev/null @@ -1,8 +0,0 @@ -nargo compile -nargo check -nargo execute my-witness -bb prove -b ./target/zkchase.json -w ./target/my-witness.gz -o ./target/proof -echo "✅ Proof generated at ./target/proof" -bb write_vk -b ./target/zkchase.json -o ./target/vk -bb verify -k ./target/vk -p ./target/proof -echo "✅ Verified the proof at ./target/proof" diff --git a/noir-r1cs-logup/noir-examples/zkchase/src/main.nr b/noir-r1cs-logup/noir-examples/zkchase/src/main.nr deleted file mode 100644 index 4c1e721a4..000000000 --- a/noir-r1cs-logup/noir-examples/zkchase/src/main.nr +++ /dev/null @@ -1,238 +0,0 @@ -// -// -// - -// This is an -global COLS = 18; -global ROWS = 14; - -fn sq(x: Field) -> Field { - x * x -} - -fn cu(x: Field) -> Field { - x * x * x -} - -// hashes two inputs -fn hash(val: Field, salt: Field) -> Field { - // let mut slt = salt as u64; - // let val = val as u64; - let salts = [ - 0xf8bf3bd6c22ba3b1bf3ab2e3fb40818cd4217ffbaf294ca42331d4e3043a0a6, - 0x388c9fcf30fc2841d648f46bad01dd10bee9dc184d25eabc9f617021109cec3, - 0x2bb7f397c5941ac67befa8b232f15c8853dac263da793555441a90cec83b6454, - 0x17f389b52f9ea7a98874a4a31ef6a7beb43fb17db0e499250bb3f0181c59fb21, - 0x3a2090eacb897a31fb10561d560a9aeec24b7ad14d17b145f20c875a0b28c7c, - 0xc398534f0eb580f1fe4bf64553389e67cca4714399430e09619dcbee17ba099, - 0x7095ac9fda46afa7f181259e3635feffa7f11ee63f3ee777a5cebf4822328c4, - 0x2046f7cf1c8f13ef2b69cbc8bc0d5d809f82568abe2b33d1cd060958b1ced683, - ]; - - let v = val * salts[0]; - let v = v * v * v * (salt + salts[1]); // v ** 3 - let v = sq(sq(v)) * v * (salt + salts[2]); // v ** 5 - let v2 = sq(v); - let v = cu(v2) * v * (salt + salts[3]); // v ** 7 - let v2 = sq(v); - let v4 = sq(v2); - let v = sq(v4) * v2 * v * (salt + salts[5]); // v ** 11 - let v4 = sq(sq(v)); - let v = cu(v4) * v * (salt + salts[6]); // v ** 13 - let v = sq(sq(sq(sq(v)))) * v * (salt + salts[7]); // v ** 17 - let v2 = sq(v); - let v = sq(sq(sq(v2))) * v2 * v * (salt + salts[7]); // v ** 19 - - v -} - -fn expand_position(position: Field) -> (u8, u8) { - let pos_bytes = position.to_be_bytes(2); - let mut px = pos_bytes[0]; - let mut py = pos_bytes[1]; - (px, py) -} - -fn compress_position(x: u8, y: u8) -> Field { - (x as u64 + y as u64 * 256 as u64) as Field -} - -fn make_move(prev_pos: Field, move: u8) -> (u8, u8) { - let (mut px, mut py) = expand_position(prev_pos); - - if move == 1 { - py += 1; - } else if move == 2 { - py -= 1; - } else if move == 3 { - px -= 1; - } else if move == 4 { - px += 1; - } else { - assert(false, "Invalid move"); - } - (py, px) -} - -// Get map bit at x, y -fn map_bit(map0: U128, map1: U128, x: u8, mut y: u8) -> u8 { - let mut map = map0; - let mut bit = y * COLS + x; - // print(x); - // print(" "); - // print(y); - // print(" "); - // print(bit); - // print(" "); - - // print("bit[ "); - // print(bit); - - // We have a map in two U128, m0 and m1 - // determine which one to use base on the row (y) - if bit > 125 { - bit = bit - 126; - map = map1; - } - // Now use map.lo or map.hi if bit value to fetch is greater than 63 - let mut map_part = map.lo as u64; - let mut total_bits: u8 = 63; - // print(" ~ "); - // print(bit); - // print(" "); - if bit > 63 { - map_part = map.hi as u64; - bit -= 64; - total_bits = 61; - } - - // bits to drop, everything after the reqd bit - let mut drop_bits = bit; - // print(" ] "); - let divide_drop_bits: u64 = 1 as u64 << (drop_bits as u8); - // divide by power of two to drop lower bits - let remainder_map = map_part / divide_drop_bits as u64; - // drop higher bits - let bit = remainder_map % 2; - - // print("map: "); - // print(map_part); - // print(" bit: "); - // print(bit); - - bit as u8 -} - -// Main game circuit -// map: public for Cairo contract to assert equivalence -// and that bushes are correct places in Cairo and the circuit -// prev_pos_hash: public for Cairo contract to compare against the prev pos -// prev_pos: private previous position (before playing move) -// move: between 1, 2, 3, 4 for moving UP, DOWN, LEFT, RIGHT -// salt: for hashing -// returns: public new position hash output for Cairo contract to store in state for next iteration -fn main( - map0: pub U128, - map1: pub U128, - prev_pos_hash: pub Field, - prev_pos: Field, - move: u8, - salt: Field // -) -> pub Field { - // public for Cairo contract assert equivalence - // To make sure bushes are same in Cairo and the circuit - - // Step 1: Output prev public hash - assert(hash(prev_pos, salt) == prev_pos_hash); - - // Step 2: Process move - let (x, y) = make_move(prev_pos, move); - - // Step 3: Assert move is in the bush - let bush = map_bit(map0, map1, x, y); - assert(1 == bush); - - // Step 4: Output new public hash - let pos = compress_position(x, y); - - hash(pos, salt) -} - -mod test { - use crate::{main, map_bit, hash}; - /* - 000110011100110000 - 001110011100111000 - 001110000000011110 - 001100111111001111 - 011101111111100111 - 111001110011100000 - 110001100001100000 - */ - global MAP1 = U128::from_integer(8572555389858747807877673192308021344); - - /* - 000001100001100011 - 000001110011100111 - 111001111111101110 - 111100111111001100 - 011110000000011100 - 000111001110011100 - 000011001110011000 - */ - global MAP0 = U128::from_integer(2025978491129711385918832679433810840); - - #[test] - fn test_bush() { - let rows = [ - [0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0], - [0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0], - [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0], - [0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1], - [0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1], - [1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0], - [1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0], - [0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1], - [0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1], - [1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0], - [1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0], - [0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0], - [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0], - [0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0] - ]; - - for y in 0..14 { - // println(""); - // print("printing row: "); - // println(y); - let row = rows[y]; - for i in 0..18 { - // let i = 17 - i; - // print(i); - // print(" : "); - let bit = map_bit(MAP0, MAP1, i, y); - // print(bit); - if bit == row[i] { - // print(" == "); - } else { - // print(" != "); - } - // println(row[i]); - // assert(row[17 - i] == bit); - } - } - } - - #[test] - fn test_main() { - let salt = 2134924215; - - let prev_pos = 0x705; - let prev_pos_hash = hash(prev_pos, salt); - // print("post_hash: "); - // println(hash(0x704, salt)); - let move = 2; - let result = main(MAP1, MAP0, prev_pos_hash, prev_pos, move, salt); - assert(result == hash(0x704, salt)); - } -} diff --git a/noir-r1cs-logup/scripts/all_outputs.txt b/noir-r1cs-logup/scripts/all_outputs.txt deleted file mode 100644 index 3674cad0d..000000000 --- a/noir-r1cs-logup/scripts/all_outputs.txt +++ /dev/null @@ -1,1744 +0,0 @@ -noir-passport-examples/compare_age.json - Compiling noir-r1cs v0.1.0 (/Users/ryan.cao/ryan_tfh/Client_Side_Proving/noir-r1cs) -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 1.46s - Running `target/release/noir-r1cs r1cs noir-passport-examples/compare_age.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 13 -Return values len: 1 -Num AssertZero: 2344 -Num `mul_term`s: 1432 -Blackbox fn "Poseidon2Permutation": 34 -Blackbox fn "RANGE": 1336 -RANGE check: 32 bits had 557 lookups -RANGE check: 1 bits had 482 lookups -RANGE check: 8 bits had 215 lookups -RANGE check: 128 bits had 40 lookups -RANGE check: 3 bits had 16 lookups -RANGE check: 30 bits had 13 lookups -RANGE check: 2 bits had 5 lookups -RANGE check: 31 bits had 4 lookups -RANGE check: 33 bits had 4 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 726 -Num Unique Brillig opcodes: 4 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -3776 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -2672 constraints from range checks -25850 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -20558 total R1CS constraints (14.327412297270401 num vars) -40028 total R1CS witness size, (15.288721912782648 num vars) -noir-passport-examples/compare_birthdate.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.24s - Running `target/release/noir-r1cs r1cs noir-passport-examples/compare_birthdate.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 27 -Return values len: 1 -Num AssertZero: 3099 -Num `mul_term`s: 1941 -Blackbox fn "RANGE": 1709 -Blackbox fn "Poseidon2Permutation": 34 -RANGE check: 32 bits had 698 lookups -RANGE check: 1 bits had 629 lookups -RANGE check: 8 bits had 286 lookups -RANGE check: 128 bits had 50 lookups -RANGE check: 3 bits had 20 lookups -RANGE check: 30 bits had 13 lookups -RANGE check: 31 bits had 5 lookups -RANGE check: 33 bits had 5 lookups -RANGE check: 2 bits had 3 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 931 -Num Unique Brillig opcodes: 4 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -5040 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -3418 constraints from range checks -32429 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -22568 total R1CS constraints (14.461990950585571 num vars) -46607 total R1CS witness size, (15.508259032001188 num vars) -noir-passport-examples/compare_citizenship.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.23s - Running `target/release/noir-r1cs r1cs noir-passport-examples/compare_citizenship.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 6 -Return values len: 1 -Num AssertZero: 128 -Num `mul_term`s: 30 -Blackbox fn "Poseidon2Permutation": 34 -Blackbox fn "RANGE": 110 -RANGE check: 8 bits had 110 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 2 -Num Unique Brillig opcodes: 1 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -158 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -220 constraints from range checks -880 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -14488 total R1CS constraints (13.822570830950168 num vars) -15058 total R1CS witness size, (13.87824254386927 num vars) -noir-passport-examples/compare_expiry.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.23s - Running `target/release/noir-r1cs r1cs noir-passport-examples/compare_expiry.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 27 -Return values len: 1 -Num AssertZero: 3189 -Num `mul_term`s: 1941 -Blackbox fn "Poseidon2Permutation": 34 -Blackbox fn "RANGE": 1784 -RANGE check: 32 bits had 708 lookups -RANGE check: 1 bits had 629 lookups -RANGE check: 8 bits had 332 lookups -RANGE check: 128 bits had 50 lookups -RANGE check: 3 bits had 20 lookups -RANGE check: 30 bits had 13 lookups -RANGE check: 4 bits had 6 lookups -RANGE check: 31 bits had 5 lookups -RANGE check: 33 bits had 5 lookups -RANGE check: 24 bits had 4 lookups -RANGE check: 2 bits had 3 lookups -RANGE check: 10 bits had 2 lookups -RANGE check: 5 bits had 2 lookups -RANGE check: 7 bits had 2 lookups -RANGE check: 26 bits had 1 lookups -RANGE check: 23 bits had 1 lookups -RANGE check: 29 bits had 1 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 964 -Num Unique Brillig opcodes: 4 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -5130 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -3568 constraints from range checks -33359 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -22808 total R1CS constraints (14.477252323937952 num vars) -47537 total R1CS witness size, (15.536763239041623 num vars) -noir-passport-examples/data_check_dg2_integrity.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.21s - Running `target/release/noir-r1cs r1cs noir-passport-examples/data_check_dg2_integrity.json noir-examples/basic/target/witness.gz` -Private inputs len: 22903 -Public inputs len: 0 -Return values len: 0 -Write after read at BlockId(731), Expression { mul_terms: [], linear_combinations: [(1, Witness(74363))], q_c: 0 } -Num AssertZero: 51131 -Num `mul_term`s: 14744 -Blackbox fn "Sha256Compression": 356 -Blackbox fn "RANGE": 66456 -RANGE check: 32 bits had 42652 lookups -RANGE check: 8 bits had 22980 lookups -RANGE check: 1 bits had 749 lookups -RANGE check: 24 bits had 15 lookups -RANGE check: 9 bits had 10 lookups -RANGE check: 30 bits had 10 lookups -RANGE check: 17 bits had 10 lookups -RANGE check: 25 bits had 10 lookups -RANGE check: 2 bits had 9 lookups -RANGE check: 16 bits had 5 lookups -RANGE check: 64 bits had 4 lookups -RANGE check: 3 bits had 2 lookups -Num Memory inits: 14 -Total memory alloc size: 1092 -Num Memory writes: 1 -Num Memory reads: 262 -Read-only: false -Num Brillig calls: 1204 -Num Unique Brillig opcodes: 6 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -65875 constraints from AssertZero -11129984 constraints from SHA -11021404 witnesses from SHA -0 constraints from Poseidon2 -0 witnesses from Poseidon2 -132912 constraints from range checks -1550983 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -11328771 total R1CS constraints (23.433488023306637 num vars) -12572387 total R1CS witness size, (23.583755250813976 num vars) -noir-passport-examples/data_check_expiry.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.20s - Running `target/release/noir-r1cs r1cs noir-passport-examples/data_check_expiry.json noir-examples/basic/target/witness.gz` -Private inputs len: 95 -Public inputs len: 8 -Return values len: 0 -Num AssertZero: 749 -Num `mul_term`s: 401 -Blackbox fn "RANGE": 571 -RANGE check: 8 bits had 228 lookups -RANGE check: 32 bits had 160 lookups -RANGE check: 1 bits had 142 lookups -RANGE check: 128 bits had 10 lookups -RANGE check: 4 bits had 6 lookups -RANGE check: 3 bits had 4 lookups -RANGE check: 24 bits had 4 lookups -RANGE check: 30 bits had 4 lookups -RANGE check: 2 bits had 2 lookups -RANGE check: 10 bits had 2 lookups -RANGE check: 5 bits had 2 lookups -RANGE check: 7 bits had 2 lookups -RANGE check: 31 bits had 1 lookups -RANGE check: 29 bits had 1 lookups -RANGE check: 26 bits had 1 lookups -RANGE check: 33 bits had 1 lookups -RANGE check: 23 bits had 1 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 252 -Num Unique Brillig opcodes: 4 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -1150 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -0 constraints from Poseidon2 -0 witnesses from Poseidon2 -1142 constraints from range checks -8808 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -2292 total R1CS constraints (11.162391328756906 num vars) -8808 total R1CS witness size, (13.10459875356437 num vars) -noir-passport-examples/data_check_integrity.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.22s - Running `target/release/noir-r1cs r1cs noir-passport-examples/data_check_integrity.json noir-examples/basic/target/witness.gz` -Private inputs len: 1000 -Public inputs len: 9 -Return values len: 1 -Write after read at BlockId(8), Expression { mul_terms: [], linear_combinations: [(1, Witness(3970))], q_c: 0 } -Write after read at BlockId(51), Expression { mul_terms: [], linear_combinations: [(1, Witness(20014))], q_c: 0 } -Num AssertZero: 22305 -Num `mul_term`s: 17614 -Blackbox fn "Poseidon2Permutation": 134 -Blackbox fn "RANGE": 13397 -Blackbox fn "Sha256Compression": 15 -RANGE check: 32 bits had 10952 lookups -RANGE check: 8 bits had 1222 lookups -RANGE check: 1 bits had 1033 lookups -RANGE check: 24 bits had 34 lookups -RANGE check: 30 bits had 24 lookups -RANGE check: 9 bits had 20 lookups -RANGE check: 25 bits had 20 lookups -RANGE check: 17 bits had 20 lookups -RANGE check: 2 bits had 20 lookups -RANGE check: 128 bits had 10 lookups -RANGE check: 16 bits had 10 lookups -RANGE check: 3 bits had 8 lookups -RANGE check: 64 bits had 7 lookups -RANGE check: 4 bits had 6 lookups -RANGE check: 7 bits had 2 lookups -RANGE check: 10 bits had 2 lookups -RANGE check: 5 bits had 2 lookups -RANGE check: 23 bits had 1 lookups -RANGE check: 26 bits had 1 lookups -RANGE check: 31 bits had 1 lookups -RANGE check: 33 bits had 1 lookups -RANGE check: 29 bits had 1 lookups -Num Memory inits: 18 -Total memory alloc size: 1235 -Num Memory writes: 2 -Num Memory reads: 319 -Read-only: false -Num Brillig calls: 1326 -Num Unique Brillig opcodes: 8 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -39919 constraints from AssertZero -468960 constraints from SHA -464385 witnesses from SHA -55610 constraints from Poseidon2 -55878 witnesses from Poseidon2 -26794 constraints from range checks -365991 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -591283 total R1CS constraints (19.1734892731557 num vars) -886254 total R1CS witness size, (19.75736070823285 num vars) -noir-passport-examples/disclose_bytes.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.21s - Running `target/release/noir-r1cs r1cs noir-passport-examples/disclose_bytes.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 93 -Return values len: 91 -Num AssertZero: 278 -Num `mul_term`s: 90 -Blackbox fn "RANGE": 275 -Blackbox fn "Poseidon2Permutation": 34 -RANGE check: 8 bits had 275 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 0 -Num Unique Brillig opcodes: 0 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -368 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -550 constraints from range checks -2200 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -15028 total R1CS constraints (13.87536540064177 num vars) -16378 total R1CS witness size, (13.999471572532684 num vars) -noir-passport-examples/disclose_flags.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.22s - Running `target/release/noir-r1cs r1cs noir-passport-examples/disclose_flags.json noir-examples/basic/target/witness.gz` -Private inputs len: 105 -Public inputs len: 3 -Return values len: 70 -Num AssertZero: 1116 -Num `mul_term`s: 1018 -Blackbox fn "Poseidon2Permutation": 34 -Blackbox fn "RANGE": 593 -RANGE check: 8 bits had 585 lookups -RANGE check: 1 bits had 8 lookups -Num Memory inits: 1 -Total memory alloc size: 90 -Num Memory writes: 0 -Num Memory reads: 9 -Read-only: true -Num Brillig calls: 2 -Num Unique Brillig opcodes: 1 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -2134 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -1186 constraints from range checks -4688 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -17430 total R1CS constraints (14.089284949013047 num vars) -18866 total R1CS witness size, (14.203500952361395 num vars) -noir-passport-examples/exclusion_check_country.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.23s - Running `target/release/noir-r1cs r1cs noir-passport-examples/exclusion_check_country.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 203 -Return values len: 1 -Num AssertZero: 140 -Num `mul_term`s: 40 -Blackbox fn "RANGE": 317 -Blackbox fn "Poseidon2Permutation": 34 -RANGE check: 32 bits had 207 lookups -RANGE check: 8 bits had 107 lookups -RANGE check: 1 bits had 3 lookups -Num Memory inits: 1 -Total memory alloc size: 200 -Num Memory writes: 0 -Num Memory reads: 3 -Read-only: true -Num Brillig calls: 7 -Num Unique Brillig opcodes: 3 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -180 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -634 constraints from range checks -7483 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -14924 total R1CS constraints (13.86534664481678 num vars) -21661 total R1CS witness size, (14.402812227377439 num vars) -noir-passport-examples/inclusion_check_country.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.22s - Running `target/release/noir-r1cs r1cs noir-passport-examples/inclusion_check_country.json noir-examples/basic/target/witness.gz` -Private inputs len: 97 -Public inputs len: 603 -Return values len: 1 -Num AssertZero: 335 -Num `mul_term`s: 32 -Blackbox fn "RANGE": 708 -Blackbox fn "Poseidon2Permutation": 34 -RANGE check: 8 bits had 707 lookups -RANGE check: 32 bits had 1 lookups -Num Memory inits: 2 -Total memory alloc size: 801 -Num Memory writes: 0 -Num Memory reads: 4 -Read-only: true -Num Brillig calls: 4 -Num Unique Brillig opcodes: 2 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -367 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -14110 constraints from Poseidon2 -14178 witnesses from Poseidon2 -1416 constraints from range checks -5688 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -15893 total R1CS constraints (13.95610385644527 num vars) -19866 total R1CS witness size, (14.278013796118156 num vars) -noir-passport-examples/outer.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.22s - Running `target/release/noir-r1cs r1cs noir-passport-examples/outer.json noir-examples/basic/target/witness.gz` -Private inputs len: 2332 -Public inputs len: 201 -Return values len: 0 -Num AssertZero: 200 -Num `mul_term`s: 96 -Blackbox fn "MultiScalarMul": 48 -Blackbox fn "RecursiveAggregation": 4 -Blackbox fn "RANGE": 246 -RANGE check: 8 bits had 198 lookups -RANGE check: 1 bits had 48 lookups -Num Memory inits: 0 -Total memory alloc size: 0 -Num Memory writes: 0 -Num Memory reads: 0 -Read-only: true -Num Brillig calls: 100 -Num Unique Brillig opcodes: 2 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -296 constraints from AssertZero -0 constraints from SHA -0 witnesses from SHA -0 constraints from Poseidon2 -0 witnesses from Poseidon2 -492 constraints from range checks -1632 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -788 total R1CS constraints (9.622051819456376 num vars) -1632 total R1CS witness size, (10.672425341971495 num vars) -noir-passport-examples/sig_check_dsc_tbs_1000_ecdsa_nist_p256.json -warning: unused imports: `WitnessStack`, `Witness`, and `brillig::IntegerBitSize` - --> src/main.rs:5:5 - | -5 | brillig::IntegerBitSize, - | ^^^^^^^^^^^^^^^^^^^^^^^ -6 | circuit::{opcodes::BlackBoxFuncCall, Opcode}, -7 | native_types::{Expression, Witness, WitnessStack}, - | ^^^^^^^ ^^^^^^^^^^^^ - | - = note: `#[warn(unused_imports)]` on by default - -warning: unused imports: `Add`, `BTreeMap`, `Neg`, and `thread::current` - --> src/main.rs:12:36 - | -12 | collections::{hash_map::Entry, BTreeMap, HashMap, HashSet}, - | ^^^^^^^^ -13 | ops::{Add, AddAssign, Neg}, - | ^^^ ^^^ -14 | thread::current, - | ^^^^^^^^^^^^^^^ - -warning: value assigned to `second_idx` is never read - --> src/factoring.rs:133:21 - | -133 | second_idx -= 1; // Everything from `second_idx` gets shifted back by 1 - | ^^^^^^^^^^ - | - = help: maybe it is overwritten before being read? - = note: `#[warn(unused_assignments)]` on by default - -warning: struct `R1CSMatrix` is never constructed - --> src/main.rs:40:8 - | -40 | struct R1CSMatrix { - | ^^^^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: associated items `new`, `set`, `resize`, and `get_matrix` are never used - --> src/main.rs:47:8 - | -46 | impl R1CSMatrix { - | ----------------------------- associated items in this implementation -47 | fn new() -> Self { - | ^^^ -... -55 | pub fn set(&mut self, i: usize, j: usize, value: FieldElement) { - | ^^^ -... -61 | pub fn resize(&mut self, n: usize, m: usize) { - | ^^^^^^ -... -67 | pub fn get_matrix(&self) -> Vec { - | ^^^^^^^^^^ - -warning: function `dot` is never used - --> src/main.rs:78:4 - | -78 | fn dot(a: &[FieldElement], b: &[FieldElement]) -> FieldElement { - | ^^^ - -warning: struct `MulGroup` is never constructed - --> src/factoring.rs:12:19 - | -12 | pub(crate) struct MulGroup { - | ^^^^^^^^ - -warning: method `combine` is never used - --> src/factoring.rs:23:19 - | -18 | impl MulGroup { - | ------------- method in this implementation -... -23 | pub(crate) fn combine(&self, other: &MulGroup) -> Option { - | ^^^^^^^ - -warning: struct `MulGroupTable` is never constructed - --> src/factoring.rs:83:19 - | -83 | pub(crate) struct MulGroupTable { - | ^^^^^^^^^^^^^ - -warning: struct `FactoredPoly` is never constructed - --> src/factoring.rs:91:19 - | -91 | pub(crate) struct FactoredPoly { - | ^^^^^^^^^^^^ - -warning: function `convert_into_most_efficient_mul_grouping` is never used - --> src/factoring.rs:103:15 - | -103 | pub(crate) fn convert_into_most_efficient_mul_grouping( - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -warning: `noir-r1cs` (bin "noir-r1cs") generated 11 warnings (run `cargo fix --bin "noir-r1cs"` to apply 2 suggestions) - Finished `release` profile [optimized] target(s) in 0.22s - Running `target/release/noir-r1cs r1cs noir-passport-examples/sig_check_dsc_tbs_1000_ecdsa_nist_p256.json noir-examples/basic/target/witness.gz` -Private inputs len: 1149 -Public inputs len: 1 -Return values len: 1 -Write after read at BlockId(52), Expression { mul_terms: [], linear_combinations: [(1, Witness(24974))], q_c: 0 } -Num AssertZero: 38924 -Num `mul_term`s: 38870 -Blackbox fn "Poseidon2Permutation": 372 -Blackbox fn "RANGE": 33765 -Blackbox fn "Sha256Compression": 17 -RANGE check: 32 bits had 13103 lookups -RANGE check: 1 bits had 6028 lookups -RANGE check: 120 bits had 4914 lookups -RANGE check: 126 bits had 4880 lookups -RANGE check: 8 bits had 2308 lookups -RANGE check: 16 bits had 1242 lookups -RANGE check: 22 bits had 1220 lookups -RANGE check: 24 bits had 15 lookups -RANGE check: 9 bits had 10 lookups -RANGE check: 17 bits had 10 lookups -RANGE check: 25 bits had 10 lookups -RANGE check: 30 bits had 10 lookups -RANGE check: 2 bits had 9 lookups -RANGE check: 64 bits had 4 lookups -RANGE check: 3 bits had 2 lookups -Num Memory inits: 25 -Total memory alloc size: 532 -Num Memory writes: 1 -Num Memory reads: 1308 -Read-only: false -Num Brillig calls: 2581 -Num Unique Brillig opcodes: 18 -Num Calls: 0 -Num Unique calls: 0 ----------------------------------------------------------------- -77794 constraints from AssertZero -531488 constraints from SHA -526303 witnesses from SHA -154380 constraints from Poseidon2 -155124 witnesses from Poseidon2 -67530 constraints from range checks -1696510 witnesses from range checks -TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS -831192 total R1CS constraints (19.66482224319305 num vars) -2377937 total R1CS witness size, (21.181279062796488 num vars) diff --git a/noir-r1cs-logup/scripts/run_all.sh b/noir-r1cs-logup/scripts/run_all.sh deleted file mode 100644 index 555e8baf2..000000000 --- a/noir-r1cs-logup/scripts/run_all.sh +++ /dev/null @@ -1,6 +0,0 @@ -# Run this in the `noir-r1cs` directory! - -for file in noir-passport-examples/*.json; do - echo "$file" - cargo run --bin circuit_stats -- "$file" noir-examples/basic/target/basic.gz -done \ No newline at end of file diff --git a/noir-r1cs-logup/src/bin/circuit_stats.rs b/noir-r1cs-logup/src/bin/circuit_stats.rs deleted file mode 100644 index be2b0e097..000000000 --- a/noir-r1cs-logup/src/bin/circuit_stats.rs +++ /dev/null @@ -1,517 +0,0 @@ -//! This binary analyzes ACIR circuit statistics and provides insights into -//! constraints, witness size, and various operations used in the circuit. - -use { - acir::{ - circuit::{opcodes::BlackBoxFuncCall, Opcode, Program}, - native_types::Expression, - }, - acir_field::FieldElement, - base64::Engine, - clap::Parser, - std::{ - collections::{hash_map::Entry, HashMap, HashSet}, - fs, - ops::AddAssign, - }, -}; - -/// Simple program to show circuit statistics -#[derive(Parser, Debug)] -#[command(author, version, about, long_about = None)] -struct Args { - /// Path to circuit file - circuit_path: String, - - /// Path to witness file - witness_path: String, -} - -fn program_at_path(acir_path: String) -> Program { - let json_string = - fs::read_to_string(acir_path).expect("There was a problem reading the file content"); - let json_str: &str = &json_string; - let json: serde_json::Value = - serde_json::from_str(json_str).expect("There was a problem parsing the json program"); - let Some(bytecode_str) = json["bytecode"].as_str() else { - panic!("Expected a different circuit format") - }; - let bytecode: &[u8] = &base64::prelude::BASE64_STANDARD - .decode(bytecode_str) - .expect("There was a problem decoding the program from base 64"); - let program = Program::deserialize_program(bytecode); - program.unwrap() -} - -fn main() { - let args = Args::parse(); - let program = program_at_path(args.circuit_path); - - assert!( - program.functions.len() == 1, - "only one function supported at the moment", - ); - - let Program { - mut functions, - unconstrained_functions: _, - } = program; - let circuit = functions.pop().unwrap(); - - println!("Private inputs len: {:?}", circuit.private_parameters.len()); - println!( - "Public inputs len: {:?}", - circuit.public_parameters.0.len() - ); - println!("Return values len: {:?}", circuit.return_values.0.len()); - - let mut total_num_mul_terms = 0; - let mut total_num_assert_zero_opcodes = 0; - - // --- These are all the blackbox functions --- - // --- Manual because the variants don't equal each other when they have - // arguments --- - let mut blackbox_func_call_variants: HashMap<&str, usize> = vec![ - ("AES128Encrypt", 0), - ("AND", 0), - ("XOR", 0), - ("RANGE", 0), - ("Blake2s", 0), - ("Blake3", 0), - ("EcdsaSecp256k1", 0), - ("EcdsaSecp256r1", 0), - ("MultiScalarMul", 0), - ("EmbeddedCurveAdd", 0), - ("Keccakf1600", 0), - ("RecursiveAggregation", 0), - ("BigIntAdd", 0), - ("BigIntSub", 0), - ("BigIntMul", 0), - ("BigIntDiv", 0), - ("BigIntFromLeBytes", 0), - ("BigIntToLeBytes", 0), - ("Poseidon2Permutation", 0), - ("Sha256Compression", 0), - ] - .into_iter() - .collect(); - - // --- Data tracking for range checks --- - let mut range_check_bit_counts: HashMap = HashMap::new(); - - // --- Data tracking for memory operations --- - let mut mem_read_counter = 0; - let mut mem_write_counter = 0; - let mut mem_alloc_counter = 0; - let mut mem_alloc_total_size = 0; - // We want to know if any writes happen AFTER reads to a specific location - let mut mem_read_locs = HashSet::new(); - let mut all_reads_after_writes = true; - - // --- Tracking for `BrilligCall` and `Call` --- - let mut num_brillig_call_opcodes = 0; - let mut unique_brillig_call_opcodes = HashSet::new(); - let mut num_call_opcodes = 0; - let mut unique_call_opcodes = HashSet::new(); - - // --- I'm guessing Noir does it so that you just "execute" the opcodes in a - // linear manner --- --- Or at least that they correspond to constraints - // which should be satisfied in that "order" --- - for opcode in circuit.opcodes.iter() { - match opcode { - Opcode::AssertZero(expr) => { - // println!("AssertZero: {:?}", opcode); - total_num_mul_terms += expr.num_mul_terms(); - total_num_assert_zero_opcodes += 1; - } - Opcode::BlackBoxFuncCall(variant) => { - // println!("BlackBoxFuncCall: {:?}", variant); - match variant { - BlackBoxFuncCall::AES128Encrypt { - inputs: _, - iv: _, - key: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("AES128Encrypt") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::AND { - lhs: _, - rhs: _, - output: _, - } => { - blackbox_func_call_variants - .entry("AND") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::XOR { - lhs: _, - rhs: _, - output: _, - } => { - blackbox_func_call_variants - .entry("XOR") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::RANGE { input } => { - // --- We keep track of the total number of RANGE calls --- - blackbox_func_call_variants - .entry("RANGE") - .and_modify(|count| { - count.add_assign(1); - }); - // --- We also keep track of the RANGE calls, broken down by num bits --- - if let Entry::Occupied(mut x) = - range_check_bit_counts.entry(input.num_bits()) - { - x.get_mut().add_assign(1); - } else { - range_check_bit_counts.insert(input.num_bits(), 1); - } - } - - BlackBoxFuncCall::Blake2s { - inputs: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("Blake2s") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::Blake3 { - inputs: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("Blake3") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::EcdsaSecp256k1 { - public_key_x: _, - public_key_y: _, - signature: _, - hashed_message: _, - output: _, - } => { - blackbox_func_call_variants - .entry("EcdsaSecp256k1") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::EcdsaSecp256r1 { - public_key_x: _, - public_key_y: _, - signature: _, - hashed_message: _, - output: _, - } => { - blackbox_func_call_variants - .entry("EcdsaSecp256r1") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::MultiScalarMul { - points: _, - scalars: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("MultiScalarMul") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::EmbeddedCurveAdd { - input1: _, - input2: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("EmbeddedCurveAdd") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::Keccakf1600 { - inputs: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("Keccakf1600") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::RecursiveAggregation { - verification_key: _, - proof: _, - public_inputs: _, - key_hash: _, - proof_type: _, - } => { - blackbox_func_call_variants - .entry("RecursiveAggregation") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::BigIntAdd { - lhs: _, - rhs: _, - output: _, - } => { - blackbox_func_call_variants - .entry("BigIntAdd") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::BigIntSub { - lhs: _, - rhs: _, - output: _, - } => { - blackbox_func_call_variants - .entry("BigIntSub") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::BigIntMul { - lhs: _, - rhs: _, - output: _, - } => { - blackbox_func_call_variants - .entry("BigIntMul") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::BigIntDiv { - lhs: _, - rhs: _, - output: _, - } => { - blackbox_func_call_variants - .entry("BigIntDiv") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::BigIntFromLeBytes { - inputs: _, - modulus: _, - output: _, - } => { - blackbox_func_call_variants - .entry("BigIntFromLeBytes") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::BigIntToLeBytes { - input: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("BigIntToLeBytes") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::Poseidon2Permutation { - inputs: _, - outputs: _, - len: _, - } => { - blackbox_func_call_variants - .entry("Poseidon2Permutation") - .and_modify(|count| { - count.add_assign(1); - }); - } - BlackBoxFuncCall::Sha256Compression { - inputs: _, - hash_values: _, - outputs: _, - } => { - blackbox_func_call_variants - .entry("Sha256Compression") - .and_modify(|count| { - count.add_assign(1); - }); - } - } - } - Opcode::MemoryOp { - block_id, - op, - predicate: _, - } => { - // --- For MemoryOp there are only two variants: read and write --- - // --- Additionally, each MemoryOp tells you how to read/write a *single* index - // --- --- Therefore we will simply count the total number of - // reads and writes --- (Additionally, check whether each write - // happens before all reads to that address) - - // `Expression::zero()` means read, and `Expression::one()` means write - if op.operation == Expression::zero() { - mem_read_counter += 1; - mem_read_locs.insert((block_id, op.index.clone())); - } else { - mem_write_counter += 1; - // --- If we've read from this location before and *then* wrote to it --- - if mem_read_locs.contains(&(block_id, op.index.clone())) { - println!("Write after read at {:?}, {:?}", block_id, op.index.clone()); - all_reads_after_writes = false; - } - } - - // println!("MemoryOp: {:?}", opcode); - } - Opcode::MemoryInit { - block_id: _, - init, - block_type: _, - } => { - mem_alloc_counter += 1; - mem_alloc_total_size += init.len(); - // println!("MemoryInit: {:?}", opcode); - - // TODO(ryancao): handle block type? - // pub enum BlockType { - // Memory, - // CallData(u32), - // ReturnData, - // } - } - Opcode::BrilligCall { - id, - inputs: _, - outputs: _, - predicate: _, - } => { - // println!("BrilligCall: {:?}", opcode); - // --- Brillig calls aren't really translated into constraints --- - // --- Therefore we can profile them but won't worry about them --- - num_brillig_call_opcodes += 1; - unique_brillig_call_opcodes.insert(id); - } - Opcode::Call { - id, - inputs: _, - outputs: _, - predicate: _, - } => { - // println!("Call: {:?}", opcode); - // --- So these are calls to separate circuits... Not sure where to get those - // circuits, but oh well --- - num_call_opcodes += 1; - unique_call_opcodes.insert(id); - } - } - } - - // --- AssertZero --- - println!("Num AssertZero: {:}", total_num_assert_zero_opcodes,); - println!("Num `mul_term`s: {:}", total_num_mul_terms); - - // --- Blackbox functions --- - blackbox_func_call_variants.iter().for_each(|(k, v)| { - if *v > 0 { - println!("Blackbox fn {:?}: {:?}", k, v); - } - }); - let mut key_value_pairs: Vec<(u32, usize)> = range_check_bit_counts.into_iter().collect(); - key_value_pairs.sort_by(|x, y| y.1.cmp(&x.1)); - key_value_pairs.iter().for_each(|(k, v)| { - println!("RANGE check: {:?} bits had {:?} lookups", k, v); - }); - - // --- Memory operations --- - println!("Num Memory inits: {:?}", mem_alloc_counter); - println!("Total memory alloc size: {:?}", mem_alloc_total_size); - println!("Num Memory writes: {:?}", mem_write_counter); - println!("Num Memory reads: {:?}", mem_read_counter); - println!("Read-only: {:?}", all_reads_after_writes); - - // --- Brillig + Call operations --- - println!("Num Brillig calls: {:?}", num_brillig_call_opcodes); - println!( - "Num Unique Brillig opcodes: {:?}", - unique_brillig_call_opcodes.len() - ); - println!("Num Calls: {:?}", num_call_opcodes); - println!("Num Unique calls: {:?}", unique_call_opcodes.len()); - - println!("----------------------------------------------------------------"); - - // --- Finally, we analyze the total number of constraints + witness size --- - let mut total_num_r1cs_rows = 0; - let mut total_num_witness_size = 0; - total_num_r1cs_rows += total_num_assert_zero_opcodes + total_num_mul_terms; - println!( - "{:?} constraints from AssertZero", - total_num_assert_zero_opcodes + total_num_mul_terms - ); - // SHA adds 31264 R1CS constraints and 30959 witnesses - if let Entry::Occupied(x) = blackbox_func_call_variants.entry("Sha256Compression") { - println!("{:?} constraints from SHA", 31264 * x.get()); - println!("{:?} witnesses from SHA", 30959 * x.get()); - total_num_r1cs_rows += 31264 * x.get(); - total_num_witness_size += 30959 * x.get(); - } - // Poseidon adds 415 R1CS constraints and 417 wires - if let Entry::Occupied(x) = blackbox_func_call_variants.entry("Poseidon2Permutation") { - println!("{:?} constraints from Poseidon2", 415 * x.get()); - println!("{:?} witnesses from Poseidon2", 417 * x.get()); - total_num_r1cs_rows += 415 * x.get(); - total_num_witness_size += 417 * x.get(); - } - // We do a simple (i.e. non-LogUp) approach for computing range checks - let mut total_num_range_check_constraints = 0; - let mut total_num_range_check_witnesses = 0; - key_value_pairs.iter().for_each(|(k, v)| { - total_num_range_check_constraints += 2 * v; // Let's assume for now that we can do the decomp in a single R1CS row - total_num_range_check_witnesses += (*k as usize) * v; // Total # of - // extra witnesses - }); - println!( - "{:?} constraints from range checks", - total_num_range_check_constraints - ); - println!( - "{:?} witnesses from range checks", - total_num_range_check_witnesses - ); - total_num_r1cs_rows += total_num_range_check_constraints; - total_num_witness_size += total_num_range_check_witnesses; - - // TODO(ryancao): COMPUTE THE MEMORY CHECKER CONSTRAINTS - println!("TODO(ryancao): MISSING MEMORY CHECKER CONSTRAINTS"); - println!( - "{:?} total R1CS constraints ({:?} num vars)", - total_num_r1cs_rows, - (total_num_r1cs_rows as f64).log2() - ); - println!( - "{:?} total R1CS witness size, ({:?} num vars)", - total_num_witness_size, - (total_num_witness_size as f64).log2() - ); -} diff --git a/noir-r1cs-logup/src/binops.rs b/noir-r1cs-logup/src/binops.rs deleted file mode 100644 index eb7f7897c..000000000 --- a/noir-r1cs-logup/src/binops.rs +++ /dev/null @@ -1,213 +0,0 @@ -use std::ops::Neg; -use acir::{AcirField, FieldElement}; - -use crate::{compiler::{ConstantOrR1CSWitness, R1CS}, digits::{add_digital_decomposition, decompose_into_digits}, solver::WitnessBuilder}; - -#[derive(Clone, Debug, Copy)] -pub enum BinOp { - AND, - XOR, -} - -/// The number of bits that ACIR uses for the inputs and output of the binop. -pub const BINOP_BITS: usize = 32; - -/// The number of bits that used by us for the inputs and output of the binop. -/// 2x this number of bits is used for the lookup table. -pub const BINOP_ATOMIC_BITS: usize = 8; - -/// Each operand is decomposed into this many digits. -pub const NUM_DIGITS: usize = BINOP_BITS / BINOP_ATOMIC_BITS; - -/// Add the witnesses and constraints for a [BinOp] (i.e. AND, XOR). Uses a digital decomposition of -/// the operands and output into [NUM_DIGITS] digits of [BINOP_ATOMIC_BITS] bits each, followed by a -/// lookup table of size 2x [BINOP_ATOMIC_BITS]. -pub(crate) fn add_binop( - r1cs: &mut R1CS, - op: BinOp, - inputs_and_outputs: Vec<(ConstantOrR1CSWitness, ConstantOrR1CSWitness, usize)> -) { - let log_bases = vec![BINOP_ATOMIC_BITS; NUM_DIGITS]; - - // Collect all witnesses that require digital decomposition (constants are decomposed - // separately). - let mut witnesses_to_decompose = vec![]; - for (lh, rh, output) in &inputs_and_outputs { - if let ConstantOrR1CSWitness::Witness(witness) = lh { - witnesses_to_decompose.push(*witness); - } - if let ConstantOrR1CSWitness::Witness(witness) = rh { - witnesses_to_decompose.push(*witness); - } - witnesses_to_decompose.push(*output); - } - let dd_struct = add_digital_decomposition( - r1cs, - log_bases.clone(), - witnesses_to_decompose - ); - - // Match up the digit witnesses and the digits of decompositions of constants to obtain a - // decomposed version of the inputs and outputs. - let mut inputs_and_outputs_atomic = vec![]; - // Track how many witness digital decompositions we've seen so far (for associating the digit - // witnesses with the original witnesses). - let mut witness_dd_counter = 0; - for (lh, rh, _output) in inputs_and_outputs { - let lh_atoms = match lh { - ConstantOrR1CSWitness::Witness(_) => { - let digit_witnesses = (0..NUM_DIGITS).map(|digit_place| { - dd_struct.get_digit_witness_index(digit_place, witness_dd_counter) - }).collect::>(); - witness_dd_counter += 1; - digit_witnesses.iter().map(|witness| ConstantOrR1CSWitness::Witness(*witness)).collect::>() - }, - ConstantOrR1CSWitness::Constant(value) => { - let digits = decompose_into_digits(value, &log_bases); - digits.iter().map(|digit| { - ConstantOrR1CSWitness::Constant(*digit) - }).collect::>() - } - }; - let rh_atoms = match rh { - ConstantOrR1CSWitness::Witness(_) => { - let digit_witnesses = (0..NUM_DIGITS).map(|digit_place| { - dd_struct.get_digit_witness_index(digit_place, witness_dd_counter) - }).collect::>(); - witness_dd_counter += 1; - digit_witnesses.iter().map(|witness| ConstantOrR1CSWitness::Witness(*witness)).collect::>() - }, - ConstantOrR1CSWitness::Constant(value) => { - let digits = decompose_into_digits(value, &log_bases); - digits.iter().map(|digit| { - ConstantOrR1CSWitness::Constant(*digit) - }).collect::>() - } - }; - let output_atoms = (0..NUM_DIGITS).map(|digit_place| { - dd_struct.get_digit_witness_index(digit_place, witness_dd_counter) - }).collect::>(); - witness_dd_counter += 1; - - lh_atoms.into_iter().zip(rh_atoms.into_iter()).zip(output_atoms.into_iter()).for_each(|((lh, rh), output)| { - inputs_and_outputs_atomic.push((lh, rh, output)); - }); - } - - let multiplicities_wb = WitnessBuilder::MultiplicitiesForBinOp( - r1cs.num_witnesses(), - inputs_and_outputs_atomic - .iter() - .map(|(lh_operand, rh_operand, _output)| (lh_operand.clone(), rh_operand.clone())) - .collect(), - ); - let multiplicities_first_witness = r1cs.add_witness_builder(multiplicities_wb); - - // Add two verifier challenges for the lookup - let sz_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - let rs_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - let rs_challenge_sqrd = r1cs.add_product(rs_challenge, rs_challenge); - - // Calculate the sum, over all invocations of the bin op, of 1 / denominator - let summands_for_bin_op = inputs_and_outputs_atomic - .into_iter() - .map(|(lh, rh, output)| { - add_lookup_summand( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - lh, - rh, - ConstantOrR1CSWitness::Witness(output), - ) - }) - .map(|coeff| (None, coeff)) - .collect(); - let sum_for_bin_op = r1cs.add_sum(summands_for_bin_op); - - // Calculate the sum over all table elements of multiplicity / denominator - let summands_for_table = (0..1 << BINOP_ATOMIC_BITS) - .flat_map(|lh_operand: u32| - (0..1 << BINOP_ATOMIC_BITS) - .map(move |rh_operand: u32| { - let output = match op { - BinOp::AND => lh_operand & rh_operand, - BinOp::XOR => lh_operand ^ rh_operand, - }; - (lh_operand, rh_operand, output) - }) - ) - .map(|(lh_operand, rh_operand, output)| { - let denominator = add_lookup_summand( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - ConstantOrR1CSWitness::Constant(FieldElement::from(lh_operand)), - ConstantOrR1CSWitness::Constant(FieldElement::from(rh_operand)), - ConstantOrR1CSWitness::Constant(FieldElement::from(output)), - ); - let multiplicity_witness_idx = multiplicities_first_witness + (lh_operand << BINOP_ATOMIC_BITS) as usize + rh_operand as usize; - r1cs.add_product(multiplicity_witness_idx, denominator) - }) - .map(|coeff| (None, coeff)) - .collect(); - let sum_for_table = r1cs.add_sum(summands_for_table); - - // Check that these two sums are equal. - r1cs.matrices.add_constraint( - &[(FieldElement::one(), r1cs.witness_one())], - &[(FieldElement::one(), sum_for_bin_op)], - &[(FieldElement::one(), sum_for_table)], - ); -} - -// Add and return a new witness `denominator` and constrain it to represent (assuming `output` is a -// witness): -// `w[sz_challenge] - (w[lh_operand] + w[rs_challenge] * w[rh_operand] + w[rs_challenge_sqrd] * w[output])` -// where `w` is the witness vector. If `output` is a constant, then the `rs_challenge_sqrd` is -// instead scaled by that constant. Finally, adds a new witness for the inverse of `denominator`, -// constrains it to be such, and returns its index. -fn add_lookup_summand( - r1cs: &mut R1CS, - sz_challenge: usize, - rs_challenge: usize, - rs_challenge_sqrd: usize, - lh_operand: ConstantOrR1CSWitness, - rh_operand: ConstantOrR1CSWitness, - output: ConstantOrR1CSWitness, -) -> usize { - let wb = WitnessBuilder::BinOpLookupDenominator( - r1cs.num_witnesses(), - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - lh_operand.clone(), - rh_operand.clone(), - output.clone(), - ); - let denominator = r1cs.add_witness_builder(wb); - // Add an intermediate witness if the output is a witness (otherwise can just scale) - let rs_challenge_sqrd_summand = match output { - ConstantOrR1CSWitness::Constant(value) => (FieldElement::from(value), rs_challenge_sqrd), - ConstantOrR1CSWitness::Witness(witness) => (FieldElement::one(), r1cs.add_product(rs_challenge_sqrd, witness)) - }; - r1cs.matrices.add_constraint( - &[(FieldElement::one().neg(), rs_challenge)], - &[rh_operand.to_tuple()], - &[ - (FieldElement::one(), denominator), - (FieldElement::one().neg(), sz_challenge), - (lh_operand.to_tuple()), - rs_challenge_sqrd_summand, - ], - ); - let inverse = r1cs.add_witness_builder(WitnessBuilder::Inverse(r1cs.num_witnesses(), denominator)); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), denominator)], - &[(FieldElement::one(), inverse)], - &[(FieldElement::one(), r1cs.witness_one())], - ); - inverse -} diff --git a/noir-r1cs-logup/src/compiler.rs b/noir-r1cs-logup/src/compiler.rs deleted file mode 100644 index 29fd75d8b..000000000 --- a/noir-r1cs-logup/src/compiler.rs +++ /dev/null @@ -1,450 +0,0 @@ -use { - crate::{ - binops::{add_binop, BinOp}, - memory::{MemoryBlock, MemoryOperation}, - r1cs_matrices::R1CSMatrices, - ram::add_ram_checking, - range_check::add_range_checks, - rom::add_rom_checking, - solver::{MockTranscript, WitnessBuilder}, - }, - acir::{ - circuit::{ - opcodes::{ - BlackBoxFuncCall, BlockType, ConstantOrWitnessEnum as ConstantOrACIRWitness, - }, - Circuit, Opcode, - }, - native_types::{Expression, Witness as AcirWitness, WitnessMap}, - AcirField, FieldElement, - }, - std::{collections::BTreeMap, fmt::Formatter, ops::Neg, vec}, -}; - -/// Compiles an ACIR circuit into an [R1CS] instance, comprising the -/// [R1CSMatrices] and a vector of [WitnessBuilder]s. -pub struct R1CS { - pub matrices: R1CSMatrices, - - // Maps indices of ACIR witnesses to indices of R1CS witnesses - acir_to_r1cs_witness_map: BTreeMap, - - /// Indicates how to solve for each R1CS witness - pub witness_builders: Vec, - - /// The ACIR witness indices of the initial values of the memory blocks - pub initial_memories: BTreeMap>, -} - -/// The index of the constant 1 witness in the R1CS instance -pub const WITNESS_ONE_IDX: usize = 0; - -impl R1CS { - /// The number of constraints in the R1CS instance. - pub fn num_constraints(&self) -> usize { - self.matrices.num_constraints() - } - - // Add a new witness to the R1CS instance, returning its index. - // If the witness builder implicitly maps an ACIR witness to an R1CS witness, - // then record this. - pub fn add_witness_builder(&mut self, witness_builder: WitnessBuilder) -> usize { - let start_idx = self.num_witnesses(); - self.matrices.add_witnesses(witness_builder.num_witnesses()); - // Add the witness to the mapping if it is an ACIR witness - match &witness_builder { - WitnessBuilder::Acir(r1cs_witness_idx, acir_witness) => { - self.acir_to_r1cs_witness_map - .insert(*acir_witness, *r1cs_witness_idx); - } - _ => {} - } - self.witness_builders.push(witness_builder); - start_idx - } - - /// Given the ACIR witness values, solve for the R1CS witness values. - pub fn solve( - &self, - transcript: &mut MockTranscript, - acir_witnesses: &WitnessMap, - ) -> Vec { - let mut witness = vec![FieldElement::zero(); self.num_witnesses()]; - self.witness_builders.iter().for_each(|witness_builder| { - witness_builder.solve_and_append_to_transcript( - &mut witness, - acir_witnesses, - transcript, - ); - }); - witness - } - - /// The number of witnesses in the R1CS instance. - /// This includes the constant one witness. - pub fn num_witnesses(&self) -> usize { - self.matrices.num_witnesses() - } - - /// Index of the constant 1 witness - pub const fn witness_one(&self) -> usize { - WITNESS_ONE_IDX - } - - /// Create an R1CS instance from an ACIR circuit, introducing R1CS witnesses - /// and constraints as needed. - pub fn from_acir(circuit: &Circuit) -> Self { - // Create a new R1CS instance - let mut r1cs = Self { - matrices: R1CSMatrices::new(), - acir_to_r1cs_witness_map: BTreeMap::new(), - witness_builders: vec![WitnessBuilder::Constant( - WITNESS_ONE_IDX, - FieldElement::one(), - )], - initial_memories: BTreeMap::new(), - }; - - // Read-only memory blocks (used for building the memory lookup constraints at - // the end) - let mut memory_blocks: BTreeMap = BTreeMap::new(); - - // (input, input, output) tuples for AND and XOR operations. - // Inputs may be either constants or R1CS witnesses. - // Outputs are always R1CS witnesses. - let mut and_ops = vec![]; - let mut xor_ops = vec![]; - - // Mapping the log of the range size k to the vector of witness indices that - // are to be constrained within the range [0..2^k]. - // These will be digitally decomposed into smaller ranges, if necessary. - let mut range_checks: BTreeMap> = BTreeMap::new(); - - for opcode in circuit.opcodes.iter() { - match opcode { - Opcode::AssertZero(expr) => { - r1cs.add_acir_assert_zero(expr); - } - - // Brillig instructions are used by the ACVM to solve for ACIR witness values. - // Corresponding ACIR constraints are by Noir as AssertZeros, and we map all ACIR - // witness values to R1CS witness values, so we can safely ignore - // Opcode::BrilligCall. - Opcode::BrilligCall { .. } => { - println!("BrilligCall {:?}", opcode) - } - - // Calls to a function, this is to efficiently represent repeated structure in - // circuits. TODO: We need to implement this so we can store - // circuits concicely. It should not impact the R1CS constraints or - // witness vector. - Opcode::Call { .. } => unimplemented!("Call"), - - Opcode::MemoryInit { - block_id, - init, - block_type, - } => { - if *block_type != BlockType::Memory { - panic!("MemoryInit block type must be Memory") - } - let block_id = block_id.0 as usize; - assert!( - !memory_blocks.contains_key(&block_id), - "Memory block {} already initialized", - block_id - ); - r1cs.initial_memories - .insert(block_id, init.iter().map(|w| w.0 as usize).collect()); - let mut block = MemoryBlock::new(); - init.iter().for_each(|acir_witness| { - let r1cs_witness = r1cs.fetch_r1cs_witness_index(*acir_witness); - block.initial_value_witnesses.push(r1cs_witness); - }); - memory_blocks.insert(block_id, block); - } - - Opcode::MemoryOp { - block_id, - op, - predicate, - } => { - // Panic if the predicate is set (according to Noir developers, predicate is - // always None and will soon be removed). - assert!(predicate.is_none()); - - let block_id = block_id.0 as usize; - assert!( - memory_blocks.contains_key(&block_id), - "Memory block {} not initialized before read", - block_id - ); - let block = memory_blocks.get_mut(&block_id).unwrap(); - - // `op.index` is _always_ just a single ACIR witness, not a more complicated - // expression, and not a constant. See [here](https://discord.com/channels/1113924620781883405/1356865341065531446) - // Static reads are hard-wired into the circuit, or instead rendered as a - // dummy dynamic read by introducing a new witness constrained to have the value - // of the static address. - let addr = op.index.to_witness().map_or_else( - || { - unimplemented!( - "MemoryOp index must be a single witness, not a more general \ - Expression" - ) - }, - |acir_witness| r1cs.fetch_r1cs_witness_index(acir_witness), - ); - - let op = if op.operation.is_zero() { - // Create a new (as yet unconstrained) witness `result_of_read` for the - // result of the read; it will be constrained by later memory block - // processing. - // "In read operations, [op.value] corresponds to the witness index at which - // the value from memory will be written." (from the Noir codebase) - // At R1CS solving time, only need to map over the value of the - // corresponding ACIR witness, whose value is already determined by the ACIR - // solver. - let result_of_read = - r1cs.fetch_r1cs_witness_index(op.value.to_witness().unwrap()); - MemoryOperation::Load(addr, result_of_read) - } else { - let new_value = - r1cs.fetch_r1cs_witness_index(op.value.to_witness().unwrap()); - MemoryOperation::Store(addr, new_value) - }; - block.operations.push(op); - } - - Opcode::BlackBoxFuncCall(black_box_func_call) => match black_box_func_call { - BlackBoxFuncCall::RANGE { - input: function_input, - } => { - let input = function_input.input(); - let num_bits = function_input.num_bits(); - let input_witness = match input { - ConstantOrACIRWitness::Constant(_) => { - panic!( - "We should never be range-checking a constant value, as this \ - should already be done by the noir-ACIR compiler" - ); - } - ConstantOrACIRWitness::Witness(witness) => { - r1cs.fetch_r1cs_witness_index(witness) - } - }; - println!( - "RANGE CHECK of witness {} to {} bits", - input_witness, num_bits - ); - // Add the entry into the range blocks. - range_checks - .entry(num_bits) - .or_default() - .push(input_witness); - } - - // Binary operations: - // The inputs and outputs will have already been solved for by the ACIR solver. - // Collect the R1CS witnesses indices so that we can later constrain them - // appropriately. - BlackBoxFuncCall::AND { lhs, rhs, output } => { - and_ops.push(( - r1cs.fetch_constant_or_r1cs_witness(lhs.input()), - r1cs.fetch_constant_or_r1cs_witness(rhs.input()), - r1cs.fetch_r1cs_witness_index(*output), - )); - } - BlackBoxFuncCall::XOR { lhs, rhs, output } => { - xor_ops.push(( - r1cs.fetch_constant_or_r1cs_witness(lhs.input()), - r1cs.fetch_constant_or_r1cs_witness(rhs.input()), - r1cs.fetch_r1cs_witness_index(*output), - )); - } - - _ => { - unimplemented!("Other black box function: {:?}", black_box_func_call); - } - }, - } - } - - // For each memory block, add appropriate constraints (depending on whether it - // is read-only or not) - memory_blocks.iter().for_each(|(_, block)| { - if block.is_read_only() { - // Use a lookup to enforce that the reads are correct. - add_rom_checking(&mut r1cs, block); - } else { - // Read/write memory block - use Spice offline memory checking. - // Returns witnesses that need to be range checked. - let (num_bits, witnesses_to_range_check) = add_ram_checking(&mut r1cs, block); - let range_check = range_checks.entry(num_bits).or_default(); - witnesses_to_range_check - .iter() - .for_each(|value| range_check.push(*value)); - } - }); - - // For the AND and XOR operations, add the appropriate constraints. - add_binop(&mut r1cs, BinOp::AND, and_ops); - add_binop(&mut r1cs, BinOp::XOR, xor_ops); - - // Perform all range checks - add_range_checks(&mut r1cs, range_checks); - - r1cs - } - - // Return the R1CS witness index corresponding to the AcirWitness provided, - // creating a new R1CS witness (and builder) if required. - fn fetch_r1cs_witness_index(&mut self, acir_witness_index: AcirWitness) -> usize { - self.acir_to_r1cs_witness_map - .get(&acir_witness_index.as_usize()) - .copied() - .unwrap_or_else(|| { - self.add_witness_builder(WitnessBuilder::Acir( - self.num_witnesses(), - acir_witness_index.as_usize(), - )) - }) - } - - // Convert a ConstantOrACIRWitness into a ConstantOrR1CSWitness, creating a new - // R1CS witness (and builder) if required. - fn fetch_constant_or_r1cs_witness( - &mut self, - constant_or_witness: ConstantOrACIRWitness, - ) -> ConstantOrR1CSWitness { - match constant_or_witness { - ConstantOrACIRWitness::Constant(c) => ConstantOrR1CSWitness::Constant(c), - ConstantOrACIRWitness::Witness(w) => { - let r1cs_witness = self.fetch_r1cs_witness_index(w); - ConstantOrR1CSWitness::Witness(r1cs_witness) - } - } - } - - /// Add a new witness representing the product of two existing witnesses, - /// and add an R1CS constraint enforcing this. - pub(crate) fn add_product(&mut self, operand_a: usize, operand_b: usize) -> usize { - let product = self.add_witness_builder(WitnessBuilder::Product( - self.num_witnesses(), - operand_a, - operand_b, - )); - self.matrices.add_constraint( - &[(FieldElement::one(), operand_a)], - &[(FieldElement::one(), operand_b)], - &[(FieldElement::one(), product)], - ); - product - } - - /// Add a new witness representing the sum of existing witnesses, and add an - /// R1CS constraint enforcing this. Vector consists of (optional - /// coefficient, witness index) tuples, one for each summand. - /// The coefficient is optional, and if it is None, the coefficient is 1. - pub(crate) fn add_sum(&mut self, summands: Vec<(Option, usize)>) -> usize { - let sum = - self.add_witness_builder(WitnessBuilder::Sum(self.num_witnesses(), summands.clone())); - let az = summands - .iter() - .map(|(coeff, witness_idx)| (coeff.unwrap_or(FieldElement::one()), *witness_idx)) - .collect::>(); - self.matrices - .add_constraint(&az, &[(FieldElement::one(), self.witness_one())], &[( - FieldElement::one(), - sum, - )]); - sum - } - - // Add R1CS constraints to the instance to enforce that the provided ACIR - // expression is zero. - fn add_acir_assert_zero(&mut self, expr: &Expression) { - // Create individual constraints for all the multiplication terms and collect - // their outputs - let mut linear = vec![]; - let mut a = vec![]; - let mut b = vec![]; - - if expr.mul_terms.len() >= 1 { - // Process all except the last multiplication term - linear = expr - .mul_terms - .iter() - .take(expr.mul_terms.len() - 1) - .map(|(coeff, acir_witness0, acir_witness1)| { - let witness0 = self.fetch_r1cs_witness_index(*acir_witness0); - let witness1 = self.fetch_r1cs_witness_index(*acir_witness1); - (-*coeff, self.add_product(witness0, witness1)) - }) - .collect::>(); - - // Handle the last multiplication term directly - let (coeff, acir_witness0, acir_witness1) = &expr.mul_terms[expr.mul_terms.len() - 1]; - a = vec![( - FieldElement::from(*coeff), - self.fetch_r1cs_witness_index(*acir_witness0), - )]; - b = vec![( - FieldElement::one(), - self.fetch_r1cs_witness_index(*acir_witness1), - )]; - } - - // Extend with linear combinations - linear.extend( - expr.linear_combinations - .iter() - .map(|(coeff, acir_witness)| { - (coeff.neg(), self.fetch_r1cs_witness_index(*acir_witness)) - }), - ); - - // Add constant by multipliying with constant value one. - linear.push((expr.q_c.neg(), self.witness_one())); - - // Add a single linear constraint - // We could avoid this by substituting back into the last multiplication - // constraint. - self.matrices.add_constraint(&a, &b, &linear); - } -} - -impl std::fmt::Display for R1CS { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - writeln!( - f, - "R1CS: {} witnesses, {} constraints, {} memory blocks", - self.num_witnesses(), - self.num_constraints(), - self.initial_memories.len() - )?; - if !self.initial_memories.is_empty() { - writeln!(f, "Memory blocks:")?; - for (block_id, block) in &self.initial_memories { - write!(f, " {}: {} elements; ", block_id, block.len())?; - } - writeln!(f)?; - } - writeln!(f, "{}", self.matrices) - } -} - -#[derive(Clone, Debug)] -pub enum ConstantOrR1CSWitness { - Constant(FieldElement), - Witness(usize), -} - -impl ConstantOrR1CSWitness { - pub fn to_tuple(&self) -> (FieldElement, usize) { - match self { - ConstantOrR1CSWitness::Constant(c) => (*c, WITNESS_ONE_IDX), - ConstantOrR1CSWitness::Witness(w) => (FieldElement::one(), *w), - } - } -} diff --git a/noir-r1cs-logup/src/digits.rs b/noir-r1cs-logup/src/digits.rs deleted file mode 100644 index cfff83f1c..000000000 --- a/noir-r1cs-logup/src/digits.rs +++ /dev/null @@ -1,210 +0,0 @@ -use { - crate::{compiler::R1CS, solver::WitnessBuilder}, - acir::{AcirField, FieldElement}, - serde::{Deserialize, Serialize}, -}; - -/// Allocates witnesses for the digital decomposition of the given witnesses -/// into its digits in the given bases. A log base is specified for each digit -/// (permitting mixed base decompositions). The order of bases is little-endian. -/// Witnesses are grouped by digital place, in the order of the bases, -/// where each group of witnesses is in 1:1 correspondence with -/// witnesses_to_decompose. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] -pub(crate) struct DigitalDecompositionWitnesses { - /// The log base of each digit (in little-endian order) - pub log_bases: Vec, - /// The number of witnesses to decompose - pub num_witnesses_to_decompose: usize, - /// Witness indices of the values to be decomposed - pub witnesses_to_decompose: Vec, - /// The index of the first witness written to - pub first_witness_idx: usize, - /// The number of witnesses written to - pub num_witnesses: usize, -} - -impl DigitalDecompositionWitnesses { - pub fn new( - next_witness_idx: usize, - log_bases: Vec, - witnesses_to_decompose: Vec, - ) -> Self { - let num_witnesses_to_decompose = witnesses_to_decompose.len(); - let digital_decomp_length = log_bases.len(); - Self { - log_bases, - num_witnesses_to_decompose, - witnesses_to_decompose, - first_witness_idx: next_witness_idx, - num_witnesses: digital_decomp_length * num_witnesses_to_decompose, - } - } - - /// Returns the witness index of the `value_offset`-th witness of the - /// `digit_place`-th digit. Note that `value_offset` is the index of the - /// witness in the original list of witnesses (not itself a witness - /// index). - pub fn get_digit_witness_index(&self, digit_place: usize, value_offset: usize) -> usize { - debug_assert!(digit_place < self.log_bases.len()); - debug_assert!(value_offset < self.num_witnesses_to_decompose); - self.first_witness_idx + digit_place * self.num_witnesses_to_decompose + value_offset - } - - /// Solve for the witness values allocated to the digital decomposition. - pub fn solve(&self, witness: &mut [FieldElement]) { - self.witnesses_to_decompose - .iter() - .enumerate() - .for_each(|(i, value_witness_idx)| { - let value = witness[*value_witness_idx]; - let digits = decompose_into_digits(value, &self.log_bases); - digits - .iter() - .enumerate() - .for_each(|(digit_place, digit_value)| { - witness[self.first_witness_idx - + digit_place * self.witnesses_to_decompose.len() - + i] = *digit_value; - }); - }); - } -} - -/// Adds the witnesses and constraints for the digital decomposition of the -/// given witnesses in a mixed base decomposition (see -/// [DigitalDecompositionWitnesses]). Does NOT add constraints for -/// range checking the digits - this is left to the caller (as sometimes these -/// range checks are obviated e.g. by later lookups, as in the case of the binop -/// codes). -pub(crate) fn add_digital_decomposition( - r1cs: &mut R1CS, - log_bases: Vec, - witnesses_to_decompose: Vec, -) -> DigitalDecompositionWitnesses { - let next_witness_idx = r1cs.num_witnesses(); - let dd_struct = DigitalDecompositionWitnesses::new( - next_witness_idx, - log_bases.clone(), - witnesses_to_decompose, - ); - r1cs.add_witness_builder(WitnessBuilder::DigitalDecomposition(dd_struct.clone())); - // Add the constraints for the digital recomposition - let mut digit_multipliers = vec![FieldElement::one()]; - for log_base in log_bases[..log_bases.len() - 1].iter() { - let multiplier = *digit_multipliers.last().unwrap() * FieldElement::from(1u64 << *log_base); - digit_multipliers.push(multiplier); - } - dd_struct - .witnesses_to_decompose - .iter() - .enumerate() - .for_each(|(i, value)| { - let mut recomp_summands = vec![]; - digit_multipliers - .iter() - .enumerate() - .for_each(|(digit_place, digit_multiplier)| { - let digit_witness = dd_struct.get_digit_witness_index(digit_place, i); - recomp_summands.push((FieldElement::from(*digit_multiplier), digit_witness)); - }); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), r1cs.witness_one())], - &[(FieldElement::one(), *value)], - &recomp_summands, - ); - }); - dd_struct -} - -/// Compute a mixed-base decomposition of a field element into its digits, using -/// the given log bases. Decomposition is little-endian. -/// Panics if the value provided can not be represented in the given bases. -pub(crate) fn decompose_into_digits( - value: FieldElement, - log_bases: &Vec, -) -> Vec { - let num_digits = log_bases.len(); - let mut digits = vec![FieldElement::zero(); num_digits]; - let value_bits = field_to_le_bits(value); - // Grab the bits of the element that we need for each digit, and turn them back - // into field elements. - let mut start_bit = 0; - for digit_idx in 0..num_digits { - let log_base = log_bases[digit_idx]; - let digit_bits = &value_bits[start_bit..start_bit + log_base]; - let digit_value = le_bits_to_field(digit_bits); - digits[digit_idx] = digit_value; - start_bit += log_base; - } - let remaining_bits = &value_bits[start_bit..]; - assert!( - remaining_bits.iter().all(|&bit| !bit), - "Higher order bits are not zero" - ); - digits -} - -/// Decomposes a field element into its bits, in little-endian order. -pub(crate) fn field_to_le_bits(value: FieldElement) -> Vec { - value - .to_be_bytes() - .iter() - .rev() - .flat_map(|byte| (0..8).map(move |i| (byte >> i) & 1 != 0)) - .collect() -} - -/// Given the binary representation of a field element in little-endian order, -/// convert it to a field element. The input is padded to the next multiple of 8 -/// bits. -pub(crate) fn le_bits_to_field(bits: &[bool]) -> FieldElement { - let next_multiple_of_8 = bits.len().div_ceil(8) * 8; - let padding_amt = next_multiple_of_8 - bits.len(); - let mut padded_bits_le = vec![false; next_multiple_of_8]; - padded_bits_le[..(next_multiple_of_8 - padding_amt)].copy_from_slice(bits); - let be_byte_vec: Vec = padded_bits_le - .chunks(8) - .map(|chunk_in_bits| { - chunk_in_bits - .iter() - .enumerate() - .fold(0u8, |acc, (i, bit)| acc | ((*bit as u8) << i)) - }) - .rev() - .collect(); - FieldElement::from_be_bytes_reduce(&be_byte_vec) -} - -#[cfg(test)] -#[test] -fn test_decompose_into_digits() { - let value = FieldElement::from(3 + 2u32 * 256 + 1u32 * 256 * 256); - let log_bases = vec![8, 8, 4]; - let digits = decompose_into_digits(value, &log_bases); - assert_eq!(digits.len(), log_bases.len()); - assert_eq!(digits[0], FieldElement::from(3u32)); - assert_eq!(digits[1], FieldElement::from(2u32)); - assert_eq!(digits[2], FieldElement::from(1u32)); -} - -#[cfg(test)] -#[test] -fn test_field_to_le_bits() { - let value = FieldElement::from(5u32); - let bits = field_to_le_bits(value); - assert_eq!(bits.len(), 256); - assert_eq!(bits[0], true); - assert_eq!(bits[1], false); - assert_eq!(bits[2], true); - assert_eq!(bits[254], false); - assert_eq!(bits[255], false); -} - -#[cfg(test)] -#[test] -fn test_le_bits_to_field() { - let bits = vec![true, false, true, false, false]; - let value = le_bits_to_field(&bits); - assert_eq!(value.try_to_u32().unwrap(), 5); -} diff --git a/noir-r1cs-logup/src/main.rs b/noir-r1cs-logup/src/main.rs deleted file mode 100644 index ebb5f4f43..000000000 --- a/noir-r1cs-logup/src/main.rs +++ /dev/null @@ -1,101 +0,0 @@ -#![doc = include_str!("../README.md")] -mod compiler; -mod r1cs_matrices; -mod solver; -mod sparse_matrix; -/// Support for AND and XOR opcodes (using LogUp). -mod binops; -mod digits; -mod memory; -/// Support for read-only memory (using LogUp). -mod rom; -/// Support for read-write memory (using offline memory checking: Spice). -mod ram; -/// Support for range checks (using digital decomposition, if required). -mod range_check; -mod utils; -#[cfg(test)] -mod test_compiler; - -use { - acir::FieldElement, - anyhow::{ensure, Context, Result as AnyResult}, - argh::FromArgs, - compiler::R1CS, - noirc_artifacts::program::ProgramArtifact, - solver::MockTranscript, - std::{fs::File, path::PathBuf}, - tracing::{info, level_filters::LevelFilter}, - tracing_subscriber::{self, fmt::format::FmtSpan, EnvFilter}, - utils::{file_io::deserialize_witness_stack, PrintAbi}, -}; - -/// Compile a R1CS instance and R1CS solver for the compiled Noir program, solve the R1CS witness -/// values from the provided ACIR witness values, then check that the R1CS instance is satisfied. -#[derive(FromArgs)] -struct Args { - /// path to the compiled Noir program - #[argh(positional)] - program_path: PathBuf, - - /// path to the witness file - #[argh(positional)] - witness_path: PathBuf, -} - -fn main() -> AnyResult<()> { - tracing_subscriber::fmt() - .with_span_events(FmtSpan::ACTIVE) - .with_ansi(true) - .with_env_filter( - EnvFilter::builder() - .with_default_directive(LevelFilter::INFO.into()) - .with_env_var("PROVEKIT_LOG") - .from_env_lossy(), - ) - .init(); - let args: Args = argh::from_env(); - info!("Loading Noir program {:?}", args.program_path); - let file = File::open(args.program_path).context("while opening Noir program")?; - let program: ProgramArtifact = - serde_json::from_reader(file).context("while reading Noir program")?; - - info!("Program noir version: {}", program.noir_version); - info!("Program entry point: fn main{};", PrintAbi(&program.abi)); - ensure!( - program.bytecode.functions.len() == 1, - "Program must have one entry point." - ); - let acir_circuit = &program.bytecode.functions[0]; - let num_acir_witnesses = acir_circuit.current_witness_index as usize; - info!( - "ACIR: {} witnesses, {} opcodes.", - num_acir_witnesses, - acir_circuit.opcodes.len() - ); - - // Compile to obtain R1CS matrices and R1CS solver - let r1cs = R1CS::from_acir(acir_circuit); - info!("{}", r1cs); - - // Solve for the R1CS witness using the ACIR witness - let mut witness_stack: acir::native_types::WitnessStack = - deserialize_witness_stack(args.witness_path.to_str().unwrap())?; - let acir_witness = witness_stack.pop().unwrap().witness; - - let mut transcript = MockTranscript::new(); - let witness = r1cs.solve(&mut transcript, &acir_witness); - - // Check that the witness satisfies the R1CS relation - if let Some(failing_constraint_idx) = r1cs.matrices.test_satisfaction(&witness) { - return Err(anyhow::anyhow!( - "Witness does not satisfy constraint {}", - failing_constraint_idx - )); - } - - r1cs.matrices - .write_json_to_file(acir_circuit.public_parameters.0.len(), &witness, "r1cs.json")?; - - Ok(()) -} \ No newline at end of file diff --git a/noir-r1cs-logup/src/memory.rs b/noir-r1cs-logup/src/memory.rs deleted file mode 100644 index 94c45c3f3..000000000 --- a/noir-r1cs-logup/src/memory.rs +++ /dev/null @@ -1,32 +0,0 @@ -#[derive(Debug, Clone)] -/// Used for tracking operations on a memory block. -pub struct MemoryBlock { - /// The R1CS witnesses corresponding to the memory block values - pub initial_value_witnesses: Vec, - /// The memory operations, in the order that they occur - pub operations: Vec, -} - -impl MemoryBlock { - pub fn new() -> Self { - Self { - initial_value_witnesses: vec![], - operations: vec![], - } - } - - pub fn is_read_only(&self) -> bool { - self.operations.iter().all(|op| match op { - MemoryOperation::Load(_, _) => true, - MemoryOperation::Store(_, _) => false, - }) - } -} - -#[derive(Debug, Clone)] -pub enum MemoryOperation { - /// (R1CS witness index of address, R1CS witness index of value read) - Load(usize, usize), - /// (R1CS witness index of address, R1CS witness index of value to write) - Store(usize, usize), -} diff --git a/noir-r1cs-logup/src/r1cs_matrices.rs b/noir-r1cs-logup/src/r1cs_matrices.rs deleted file mode 100644 index 8b4ac86c9..000000000 --- a/noir-r1cs-logup/src/r1cs_matrices.rs +++ /dev/null @@ -1,180 +0,0 @@ -use { - crate::sparse_matrix::{mat_mul, SparseMatrix}, - acir::{AcirField, FieldElement}, - serde::{Deserialize, Serialize}, - std::{fmt::Formatter, fs::File, io::Write}, -}; - -#[derive(Serialize)] -struct JsonR1CS { - num_public: usize, - num_variables: usize, - num_constraints: usize, - a: Vec, - b: Vec, - c: Vec, - witnesses: Vec>, -} - -/// Represents a R1CS constraint system. -/// A witness z satisfies the R1CS iff: -/// Az * Bz = Cz -/// where Az, Bz, Cz are the vectors formed by multiplying the matrices A, B, C -/// by the witness z. -#[derive(Debug, Clone)] -pub struct R1CSMatrices { - pub a: SparseMatrix, - pub b: SparseMatrix, - pub c: SparseMatrix, -} - -#[derive(Serialize, Deserialize)] -struct MatrixEntry { - constraint: usize, - signal: usize, - value: String, -} - -impl R1CSMatrices { - pub fn new() -> Self { - Self { - a: SparseMatrix::new(0, 1, FieldElement::zero()), - b: SparseMatrix::new(0, 1, FieldElement::zero()), - c: SparseMatrix::new(0, 1, FieldElement::zero()), - } - } - - pub fn to_json( - &self, - num_public: usize, - witness: &[FieldElement], - ) -> Result { - // Convert witness to string format - let witnesses = vec![witness - .iter() - .map(|w| w.to_string()) - .collect::>()]; - - let json_r1cs = JsonR1CS { - num_public, - num_variables: self.num_witnesses(), - num_constraints: self.num_constraints(), - a: Self::matrix_to_entries(&self.a), - b: Self::matrix_to_entries(&self.b), - c: Self::matrix_to_entries(&self.c), - witnesses, - }; - - serde_json::to_string_pretty(&json_r1cs) - } - - fn matrix_to_entries(matrix: &SparseMatrix) -> Vec { - matrix - .entries - .iter() - .filter_map(|((row, col), value)| { - if !value.is_zero() { - Some(MatrixEntry { - constraint: *row, - signal: *col, - value: value.to_string(), - }); - } - None - }) - .collect() - } - - pub fn write_json_to_file( - &self, - num_public: usize, - witness: &[FieldElement], - path: &str, - ) -> std::io::Result<()> { - let json = self - .to_json(num_public, witness) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?; - - let mut file = File::create(path)?; - file.write_all(json.as_bytes())?; - Ok(()) - } - - /// The number of constraints in the R1CS instance. - pub fn num_constraints(&self) -> usize { - self.a.rows - } - - /// The number of witnesses in the R1CS instance (including the constant one - /// witness). - pub fn num_witnesses(&self) -> usize { - self.a.cols - } - - /// Add a new witnesses to the R1CS instance. - pub fn add_witnesses(&mut self, count: usize) { - self.grow_matrices(self.num_constraints(), self.num_witnesses() + count); - } - - // Increase the size of the R1CS matrices to the specified dimensions. - fn grow_matrices(&mut self, num_rows: usize, num_cols: usize) { - self.a.grow(num_rows, num_cols); - self.b.grow(num_rows, num_cols); - self.c.grow(num_rows, num_cols); - } - - /// Adds a new R1CS constraint. - pub fn add_constraint( - &mut self, - az: &[(FieldElement, usize)], - bz: &[(FieldElement, usize)], - cz: &[(FieldElement, usize)], - ) { - let next_constraint_idx = self.num_constraints(); - let num_cols = self.num_witnesses(); - self.grow_matrices(self.num_constraints() + 1, num_cols); - - for (coeff, witness_idx) in az.iter().copied() { - self.a.set(next_constraint_idx, witness_idx, coeff) - } - for (coeff, witness_idx) in bz.iter().copied() { - self.b.set(next_constraint_idx, witness_idx, coeff) - } - for (coeff, witness_idx) in cz.iter().copied() { - self.c.set(next_constraint_idx, witness_idx, coeff) - } - } - - /// Returns None if this R1CS instance is satisfied, otherwise returns the - /// index of the first constraint that is not satisfied. - pub fn test_satisfaction(&self, witness: &[FieldElement]) -> Option { - let az = mat_mul(&self.a, witness); - let bz = mat_mul(&self.b, witness); - let cz = mat_mul(&self.c, witness); - for (row, ((a_val, b_val), c_val)) in az - .into_iter() - .zip(bz.into_iter()) - .zip(cz.into_iter()) - .enumerate() - { - if a_val * b_val != c_val { - return Some(row); - } - } - None - } -} - -impl std::fmt::Display for R1CSMatrices { - fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { - if std::cmp::max(self.num_constraints(), self.num_witnesses()) > 25 { - return writeln!(f, "R1CS matrices too large to print"); - } - writeln!(f, "Matrix A:")?; - write!(f, "{}", self.a)?; - writeln!(f, "Matrix B:")?; - write!(f, "{}", self.b)?; - writeln!(f, "Matrix C:")?; - write!(f, "{}", self.c) - } -} diff --git a/noir-r1cs-logup/src/ram.rs b/noir-r1cs-logup/src/ram.rs deleted file mode 100644 index a98b8b7f9..000000000 --- a/noir-r1cs-logup/src/ram.rs +++ /dev/null @@ -1,317 +0,0 @@ -use std::ops::Neg; -use acir::{AcirField, FieldElement}; -use crate::{compiler::R1CS, memory::{MemoryBlock, MemoryOperation}, solver::WitnessBuilder}; - -/// Like [MemoryOperation], but with the indices of the additional witnesses needed by Spice. -#[derive(Debug, Clone)] -pub(crate) enum SpiceMemoryOperation { - /// Load operation. Arguments are R1CS witness indices: - /// (address, value read, read timestamp) - /// `address` is already solved for by the ACIR solver. - Load(usize, usize, usize), - /// Store operation. Arguments are R1CS witness indices: - /// (address, old value, new value, read timestamp) - /// `address`, `old value`, `new value` are already solved for by the ACIR solver. - Store(usize, usize, usize, usize), -} - -#[derive(Debug, Clone)] -pub(crate) struct SpiceWitnesses { - /// The length of the memory block - pub memory_length: usize, - /// The witness index of the first initial value (they are stored contiguously) - /// (Not written to) - pub initial_values_start: usize, - /// The memory operations, in the order that they occur; each SpiceMemoryOperation contains witness indices that will be written to) - pub memory_operations: Vec, - /// The witness index of the first of the memory_length final read values (stored contiguously) (these witnesses are written to) - pub rv_final_start: usize, - /// The witness index of the first of the memory_length final read timestamps (stored contiguously) (these witnesses are written to) - pub rt_final_start: usize, - /// The index of the first witness written to by the SpiceWitnesses struct - pub first_witness_idx: usize, - /// The number of witnesses written to by the SpiceWitnesses struct - pub num_witnesses: usize -} - -impl SpiceWitnesses { - pub fn new( - next_witness_idx: usize, - memory_length: usize, - initial_values_start: usize, - memory_operations: Vec, - ) -> Self { - let start_witness_idx = next_witness_idx; - let mut next_witness_idx = start_witness_idx; - let spice_memory_operations = memory_operations - .into_iter() - .map(|op| match op { - MemoryOperation::Load(addr, value) => { - let op = SpiceMemoryOperation::Load(addr, value, next_witness_idx); - next_witness_idx += 1; - op - }, - MemoryOperation::Store(addr, new_value) => { - let old_value = next_witness_idx; - next_witness_idx += 1; - let read_timestamp = next_witness_idx; - next_witness_idx += 1; - SpiceMemoryOperation::Store(addr, old_value, new_value, read_timestamp) - } - }) - .collect(); - let rv_final_start = next_witness_idx; - next_witness_idx += memory_length; - let rt_final_start = next_witness_idx; - next_witness_idx += memory_length; - let num_witnesses = next_witness_idx - start_witness_idx; - - Self { - memory_length, - initial_values_start, - memory_operations: spice_memory_operations, - rv_final_start, - rt_final_start, - first_witness_idx: start_witness_idx, - num_witnesses - } - } - - /// Solve for the values of the Spice witnesses. - pub fn solve(&self, witness: &mut [FieldElement]) { - let mut rv_final = witness[self.initial_values_start..self.initial_values_start + self.memory_length].to_vec(); - let mut rt_final = vec![0; self.memory_length]; - for (mem_op_index, mem_op) in self.memory_operations.iter().enumerate() { - match mem_op { - SpiceMemoryOperation::Load(addr, value, read_timestamp) => { - let addr = witness[*addr]; - let addr_as_usize = addr.try_to_u64().unwrap() as usize; - witness[*read_timestamp] = FieldElement::from(rt_final[addr_as_usize]); - rv_final[addr_as_usize] = witness[*value]; - rt_final[addr_as_usize] = mem_op_index + 1; - } - SpiceMemoryOperation::Store(addr, old_value, new_value, read_timestamp) => { - let addr = witness[*addr]; - let addr_as_usize = addr.try_to_u64().unwrap() as usize; - witness[*old_value] = rv_final[addr_as_usize]; - witness[*read_timestamp] = FieldElement::from(rt_final[addr_as_usize]); - let new_value = witness[*new_value]; - rv_final[addr_as_usize] = new_value; - rt_final[addr_as_usize] = mem_op_index + 1; - } - } - - } - // Copy the final values and read timestamps into the witness vector - for i in 0..self.memory_length { - witness[self.rv_final_start + i] = rv_final[i]; - witness[self.rt_final_start + i] = FieldElement::from(rt_final[i]); - } - } -} - -/// Add witnesses and constraints ensuring the integrity of read/write operations on a memory block, -/// using the Spice offline memory checking protocol. The final range checks are left to the calling -/// context. -/// Returns (range_check_num_bits, witness_indices_to_range_check). -pub fn add_ram_checking( - r1cs: &mut R1CS, - block: &MemoryBlock -) -> (u32, Vec) { - // Add two verifier challenges for the multiset check - let rs_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - let rs_challenge_sqrd = r1cs.add_product(rs_challenge, rs_challenge); - let sz_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - - // The current witnesses indices for the partial products of the read set (RS) hash - // and the write set (WS) hash - let mut rs_hash = r1cs.witness_one(); - let mut ws_hash = r1cs.witness_one(); - - let memory_length = block.initial_value_witnesses.len(); - - // Track all the (mem_op_index, read timestamp) pairs so we can perform the two - // required range checks later. - let mut all_mem_op_index_and_rt = vec![]; - - println!("INIT"); - // For each of the writes in the inititialization, add a factor to the write hash - block.initial_value_witnesses.iter().enumerate().for_each(|(addr, mem_value)| { - // Initial PUTs. These all use timestamp zero. - let factor = add_mem_op_multiset_factor( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - (FieldElement::from(addr), r1cs.witness_one()), - *mem_value, - (FieldElement::zero(), r1cs.witness_one()), - ); - println!("WS factor [{}]: ({}, [{}], 0)", factor, addr, mem_value); - ws_hash = r1cs.add_product(ws_hash, factor); - }); - - let spice_witnesses = SpiceWitnesses::new( - r1cs.num_witnesses(), - memory_length, - block.initial_value_witnesses[0], - block.operations.clone()); - r1cs.add_witness_builder(WitnessBuilder::SpiceWitnesses(spice_witnesses.clone())); - - spice_witnesses.memory_operations.iter().enumerate().for_each(|(mem_op_index, op)| { - match op { - SpiceMemoryOperation::Load(addr_witness, value_witness, rt_witness) => { - println!("LOAD (mem op {})", mem_op_index); - // GET - all_mem_op_index_and_rt.push((mem_op_index, *rt_witness)); - let factor = add_mem_op_multiset_factor( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - (FieldElement::one(), *addr_witness), - *value_witness, - (FieldElement::one(), *rt_witness), - ); - println!("RS factor [{}]: ([{}], [{}], [{}])", factor, addr_witness, value_witness, rt_witness); - rs_hash = r1cs.add_product(rs_hash, factor); - - // PUT - let factor = add_mem_op_multiset_factor( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - (FieldElement::one(), *addr_witness), - *value_witness, - (FieldElement::from(mem_op_index + 1), r1cs.witness_one()), - ); - println!("WS factor [{}]: ([{}], [{}], {})", factor, addr_witness, value_witness, mem_op_index + 1); - ws_hash = r1cs.add_product(ws_hash, factor); - } - SpiceMemoryOperation::Store(addr_witness, old_value_witness, new_value_witness, rt_witness) => { - println!("STORE (mem op {})", mem_op_index); - // GET - all_mem_op_index_and_rt.push((mem_op_index, *rt_witness)); - let factor = add_mem_op_multiset_factor( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - (FieldElement::one(), *addr_witness), - *old_value_witness, - (FieldElement::one(), *rt_witness), - ); - println!("RS factor [{}]: ([{}], [{}], [{}])", factor, addr_witness, old_value_witness, rt_witness); - rs_hash = r1cs.add_product(rs_hash, factor); - - // PUT - let factor = add_mem_op_multiset_factor( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - (FieldElement::one(), *addr_witness), - *new_value_witness, - (FieldElement::from(mem_op_index + 1), r1cs.witness_one()), - ); - println!("WS factor [{}]: ([{}], [{}], {})", factor, addr_witness, new_value_witness, mem_op_index + 1); - ws_hash = r1cs.add_product(ws_hash, factor); - } - } - }); - - println!("AUDIT"); - // audit(): for each of the cells of the memory block, add a factor to the read hash - // We don't need to keep incrementing the mem op index, since only GET operations remain. - // TODO: see what global timestamp is used in the AUDIT phase of the Spice protocol (check the - // Jolt implementation). - (0..memory_length).for_each(|addr| { - // GET - let value_witness = spice_witnesses.rv_final_start + addr; - let rt_witness = spice_witnesses.rt_final_start + addr; - all_mem_op_index_and_rt.push((block.operations.len(), rt_witness)); - let factor = add_mem_op_multiset_factor( - r1cs, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - (FieldElement::from(addr), r1cs.witness_one()), - value_witness, - (FieldElement::one(), rt_witness), - ); - println!("RS factor [{}]: ({}, [{}], [{}])", factor, addr, value_witness, rt_witness); - rs_hash = r1cs.add_product(rs_hash, factor); - }); - - // Add the final constraint to enforce that the hashes are equal - r1cs.matrices.add_constraint( - &[(FieldElement::one(), r1cs.witness_one())], - &[(FieldElement::one(), rs_hash)], - &[(FieldElement::one(), ws_hash)], - ); - - // We want to establish that mem_op_index = max(mem_op_index, retrieved_timer) - // Or equivalently, that mem_op_index - retrieved_timer >= 0 - // We do this via two separate range checks: - // 1. retrieved_timer in 0..2^K - // 2. (mem_op_index - retrieved_timer) in 0..2^K - // where K is minimal such that 2^K >= block.operations.len(). - // The above range check is sound so long as 2^K is less than the characteristic of the field. - // (Note that range checks implemented only for powers of two). - // The maximum value obtained by the global timestamp is the number of memory operations. - // This is also the maximum value for any valid read timestamp. - - // num_bits is the ceil log of one more than the maximum permitted value - let num_bits = (block.operations.len() + 1).next_power_of_two().ilog2() as u32; - let mut range_check = Vec::with_capacity(2 * all_mem_op_index_and_rt.len()); - all_mem_op_index_and_rt - .iter() - .for_each(|(mem_op_index, rt_witness)| { - // Implementation note: we use an auxiliary witness to represent - // mem_op_index - rt_witness, in order to interface with the range checking - // code below. - let difference_witness_idx = r1cs.add_sum( - vec![ - (Some(FieldElement::from(*mem_op_index)), r1cs.witness_one()), - (Some(FieldElement::one().neg()), *rt_witness), - ] - ); - range_check.push(*rt_witness); - range_check.push(difference_witness_idx); - }); - (num_bits, range_check) -} - -// Add and return a new witness representing `sz_challenge - hash`, where `hash` is the hash value -// of a memory operation, adding an R1CS constraint enforcing this. -fn add_mem_op_multiset_factor( - r1cs: &mut R1CS, - sz_challenge: usize, - rs_challenge: usize, - rs_challenge_sqrd: usize, - (addr, addr_witness): (FieldElement, usize), - value_witness: usize, - (timer, timer_witness): (FieldElement, usize), -) -> usize { - let factor = r1cs.add_witness_builder(WitnessBuilder::SpiceMultisetFactor( - r1cs.num_witnesses(), - sz_challenge, - rs_challenge, - (addr, addr_witness), - value_witness, - (timer, timer_witness), - )); - let intermediate = r1cs.add_product(rs_challenge_sqrd, timer_witness); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), rs_challenge)], - &[(FieldElement::one().neg(), value_witness)], - &[ - (FieldElement::one(), factor), - (FieldElement::one().neg(), sz_challenge), - (timer, intermediate), - (addr, addr_witness), - ], - ); - factor -} diff --git a/noir-r1cs-logup/src/range_check.rs b/noir-r1cs-logup/src/range_check.rs deleted file mode 100644 index 0832194f9..000000000 --- a/noir-r1cs-logup/src/range_check.rs +++ /dev/null @@ -1,204 +0,0 @@ -use std::ops::Neg; -use std::collections::BTreeMap; -use acir::{AcirField, FieldElement}; -use crate::{compiler::R1CS, digits::add_digital_decomposition, solver::WitnessBuilder}; - -const NUM_WITNESS_THRESHOLD_FOR_LOOKUP_TABLE: usize = 5; -pub const NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP: u32 = 8; - -/// Add witnesses and constraints that ensure that the values of the witness belong to a range -/// 0..2^k (for some k). If k is larger than `NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP`, then a digital -/// decomposition is performed: witnesses are allocated for the digits of the decomposition, a -/// constraint is added that enforces the correctness of the digital decomposition, and then the -/// digits themselves are range checked. -/// `range_checks` is a map from the number of bits k to the vector of witness indices that are to -/// be constrained within the range [0..2^k]. -pub(crate) fn add_range_checks( - r1cs: &mut R1CS, - range_checks: BTreeMap>, -) { - // Do a pass through everything that needs to be range checked, - // decomposing each value into digits that are at most [NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP] - // and creating a map `atomic_range_blocks` of each `num_bits` from 1 to the - // NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP (inclusive) to the vec of witness indices that are - // constrained to that range. - - // Mapping the log of the range size k to the vector of witness indices that - // are to be constrained within the range [0..2^k]. - // The witnesses of all small range op codes are added to this map, along with witnesses of - // digits for digital decompositions of larger range checks. - let mut atomic_range_checks: Vec>> = vec![vec![vec![]]; NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP as usize + 1]; - - range_checks - .into_iter() - .for_each(|(num_bits, values_to_lookup)| { - if num_bits > NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP { - let num_big_digits = num_bits / NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP; - let logbase_of_remainder_digit = num_bits % NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP; - let mut log_bases = vec![NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP as usize; num_big_digits as usize]; - if logbase_of_remainder_digit != 0 { - log_bases.push(logbase_of_remainder_digit as usize); - } - let dd_struct = add_digital_decomposition( - r1cs, - log_bases.clone(), - values_to_lookup.clone(), - ); - - // Add the witness indices for the digits to the atomic range checks - dd_struct - .log_bases - .iter() - .enumerate() - .map(|(digit_place, log_base)| { - (*log_base as u32, (0..dd_struct.num_witnesses_to_decompose).map(|i| dd_struct.get_digit_witness_index(digit_place, i)).collect::>()) - }) - .for_each(|(log_base, digit_witnesses)| { - atomic_range_checks[log_base as usize].push(digit_witnesses); - }); - } else { - atomic_range_checks[num_bits as usize].push(values_to_lookup); - } - }); - - // For each of the atomic range checks, add the range check constraints. - // Use logup if the range is large; otherwise use a naive range check. - atomic_range_checks - .iter() - .enumerate() - .for_each(|(num_bits, all_values_to_lookup)| { - let values_to_lookup = all_values_to_lookup - .iter() - .flat_map(|v| v.iter()) - .copied() - .collect::>(); - if values_to_lookup.len() > NUM_WITNESS_THRESHOLD_FOR_LOOKUP_TABLE { - add_range_check_via_lookup(r1cs, num_bits as u32, &values_to_lookup); - } else { - values_to_lookup.iter().for_each(|value| { - add_naive_range_check(r1cs, num_bits as u32, *value); - }) - } - }); -} - -/// Helper function which computes all the terms of the summation for -/// each side (LHS and RHS) of the log-derivative multiset check. -/// -/// Checks that both sums (LHS and RHS) are equal at the end. -fn add_range_check_via_lookup(r1cs: &mut R1CS, num_bits: u32, values_to_lookup: &[usize]) { - // Add witnesses for the multiplicities - let wb = WitnessBuilder::MultiplicitiesForRange(r1cs.num_witnesses(), 1 << num_bits, values_to_lookup.into()); - let multiplicities_first_witness = r1cs.add_witness_builder(wb); - // Sample the Schwartz-Zippel challenge for the log derivative - // multiset check. - let sz_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - - // Compute all the terms in the summation for multiplicity/(X - table_value) - // for each table value. - let table_summands = (0..(1 << num_bits)) - .map(|table_value| { - let table_denom = add_lookup_factor( - r1cs, - sz_challenge, - FieldElement::from(table_value), - r1cs.witness_one(), - ); - let multiplicity_witness = multiplicities_first_witness + table_value; - (None, r1cs.add_product(table_denom, multiplicity_witness)) - }) - .collect(); - let sum_for_table = r1cs.add_sum(table_summands); - // Compute all the terms in the summation for 1/(X - witness_value) for each - // witness value. - let witness_summands = values_to_lookup - .iter() - .map(|value| { - let witness_idx = add_lookup_factor(r1cs, sz_challenge, FieldElement::one(), *value); - (None, witness_idx) - }) - .collect(); - let sum_for_witness = r1cs.add_sum(witness_summands); - // Check that these two sums are equal. - r1cs.matrices.add_constraint( - &[ - (FieldElement::one(), sum_for_table), - (FieldElement::one().neg(), sum_for_witness), - ], - &[(FieldElement::one(), r1cs.witness_one())], - &[(FieldElement::zero(), r1cs.witness_one())], - ); -} - -/// Helper function that computes the LogUp denominator either for -/// the table values: (X - t_j), or for the witness values: -/// (X - w_i). Computes the inverse and also checks that this is -/// the appropriate inverse. -pub(crate) fn add_lookup_factor( - r1cs: &mut R1CS, - sz_challenge: usize, - value_coeff: FieldElement, - value_witness: usize, -) -> usize { - let denom_wb = WitnessBuilder::LogUpDenominator(r1cs.num_witnesses(), sz_challenge, (value_coeff, value_witness)); - let denominator = r1cs.add_witness_builder(denom_wb); - r1cs.matrices.add_constraint( - &[ - (FieldElement::one(), sz_challenge), - (FieldElement::one().neg() * value_coeff, value_witness), - ], - &[(FieldElement::one(), r1cs.witness_one())], - &[(FieldElement::one(), denominator)], - ); - let inverse = r1cs.add_witness_builder(WitnessBuilder::Inverse(r1cs.num_witnesses(), denominator)); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), denominator)], - &[(FieldElement::one(), inverse)], - &[(FieldElement::one(), r1cs.witness_one())], - ); - inverse -} - - -/// A naive range check helper function, computing the -/// $\prod_{i = 0}^{range}(a - i) = 0$ to check whether a witness found at -/// `index_witness`, which is $a$, is in the $range$, which is `num_bits`. -fn add_naive_range_check(r1cs: &mut R1CS, num_bits: u32, index_witness: usize) { - let mut current_product_witness = index_witness; - (1..(1 << num_bits) - 1).for_each(|index: u32| { - let next_product_witness = r1cs.add_witness_builder(WitnessBuilder::ProductLinearOperation( - r1cs.num_witnesses(), - ( - current_product_witness, - FieldElement::one(), - FieldElement::zero(), - ), - ( - index_witness, - FieldElement::one(), - FieldElement::from(index).neg(), - ), - )); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), current_product_witness)], - &[ - (FieldElement::one(), index_witness), - (FieldElement::from(index).neg(), r1cs.witness_one()), - ], - &[(FieldElement::one(), next_product_witness)], - ); - current_product_witness = next_product_witness; - }); - - r1cs.matrices.add_constraint( - &[(FieldElement::one(), current_product_witness)], - &[ - (FieldElement::one(), index_witness), - ( - FieldElement::from((1 << num_bits) - 1 as u32).neg(), - r1cs.witness_one(), - ), - ], - &[(FieldElement::zero(), r1cs.witness_one())], - ); -} \ No newline at end of file diff --git a/noir-r1cs-logup/src/rom.rs b/noir-r1cs-logup/src/rom.rs deleted file mode 100644 index e4b577d54..000000000 --- a/noir-r1cs-logup/src/rom.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::ops::Neg; -use acir::{AcirField, FieldElement}; -use crate::{compiler::R1CS, memory::{MemoryBlock, MemoryOperation}, solver::WitnessBuilder}; - -/// Add witnesses and constraints enforcing the integrity of read operations -/// on a read-only memory block, using LogUp. -pub(crate) fn add_rom_checking(r1cs: &mut R1CS, block: &MemoryBlock) { - assert!(block.is_read_only(), "ROM checking can only be applied to read-only memory blocks"); - let addr_witnesses = block - .operations - .iter() - .map(|op| { - match op { - MemoryOperation::Load(addr_witness, _) => *addr_witness, - MemoryOperation::Store(_, _) => unreachable!(), - } - }) - .collect::>(); - let memory_length = block.initial_value_witnesses.len(); - let wb = WitnessBuilder::MultiplicitiesForRange(r1cs.num_witnesses(), memory_length, addr_witnesses); - let access_counts_first_witness = r1cs.add_witness_builder(wb); - - // Add two verifier challenges for the lookup - let rs_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - let sz_challenge = r1cs.add_witness_builder(WitnessBuilder::Challenge(r1cs.num_witnesses())); - - // Calculate the sum, over all reads, of 1/denominator - let summands_for_reads = block - .operations - .iter() - .map(|op| { - match op { - MemoryOperation::Load(addr_witness, value) => { - add_indexed_lookup_factor( - r1cs, - rs_challenge, - sz_challenge, - FieldElement::one(), - *addr_witness, - *value, - ) - } - MemoryOperation::Store(_, _) => { - unreachable!(); - } - } - }) - .map(|coeff| (None, coeff)) - .collect(); - let sum_for_reads = r1cs.add_sum(summands_for_reads); - - // Calculate the sum over all table elements of multiplicity/factor - let summands_for_table = block - .initial_value_witnesses - .iter() - .zip(0..memory_length) - .enumerate() - .map(|(addr, (value, access_count_idx_offset))| { - let denominator = add_indexed_lookup_factor( - r1cs, - rs_challenge, - sz_challenge, - addr.into(), - r1cs.witness_one(), - *value, - ); - r1cs.add_product(access_counts_first_witness + access_count_idx_offset, denominator) - }) - .map(|coeff| (None, coeff)) - .collect(); - let sum_for_table = r1cs.add_sum(summands_for_table); - - // Enforce that the two sums are equal - r1cs.matrices.add_constraint( - &[(FieldElement::one(), r1cs.witness_one())], - &[(FieldElement::one(), sum_for_reads)], - &[(FieldElement::one(), sum_for_table)], - ); -} - -// Helper function for adding a new lookup factor to the R1CS instance. -// Adds a new witness `denominator` and constrains it to represent -// `denominator - (sz_challenge - (index_coeff * index + rs_challenge * value)) == 0`, -// where `sz_challenge`, `index`, `rs_challenge` and `value` are the provided R1CS witness indices. -// Finally, adds a new witness for its inverse, constrains it to be such, and returns its index. -fn add_indexed_lookup_factor( - r1cs: &mut R1CS, - rs_challenge: usize, - sz_challenge: usize, - index: FieldElement, - index_witness: usize, - value: usize, -) -> usize { - let wb = WitnessBuilder::IndexedLogUpDenominator( - r1cs.num_witnesses(), - sz_challenge, - (index, index_witness), - rs_challenge, - value, - ); - let denominator = r1cs.add_witness_builder(wb); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), rs_challenge)], - &[(FieldElement::one(), value)], - &[ - (FieldElement::one().neg(), denominator), - (FieldElement::one(), sz_challenge), - (index.neg(), index_witness), - ], - ); - let inverse = r1cs.add_witness_builder(WitnessBuilder::Inverse(r1cs.num_witnesses(), denominator)); - r1cs.matrices.add_constraint( - &[(FieldElement::one(), denominator)], - &[(FieldElement::one(), inverse)], - &[(FieldElement::one(), r1cs.witness_one())], - ); - inverse -} diff --git a/noir-r1cs-logup/src/solver.rs b/noir-r1cs-logup/src/solver.rs deleted file mode 100644 index 6cc7ddba0..000000000 --- a/noir-r1cs-logup/src/solver.rs +++ /dev/null @@ -1,314 +0,0 @@ -use { - crate::{ - binops::BINOP_ATOMIC_BITS, compiler::ConstantOrR1CSWitness, - digits::DigitalDecompositionWitnesses, ram::SpiceWitnesses, - }, - acir::{ - native_types::{Witness as AcirWitness, WitnessMap}, - AcirField, FieldElement, - }, - rand::Rng, -}; - -#[derive(Debug, Clone)] -/// Indicates how to solve for a collection of R1CS witnesses in terms of -/// earlier (i.e. already solved for) R1CS witnesses and/or ACIR witness values. -pub enum WitnessBuilder { - /// Constant value, used for the constant one witness & e.g. static lookups - /// (witness index, constant value) - Constant(usize, FieldElement), - /// A witness value carried over from the ACIR circuit (at the specified - /// ACIR witness index) (includes ACIR inputs and outputs) - /// (witness index, ACIR witness index) - Acir(usize, usize), - /// A Fiat-Shamir challenge value - /// (witness index) - Challenge(usize), - /// The inverse of the value at a specified witness index - /// (witness index, operand witness index) - Inverse(usize, usize), - /// A linear combination of witness values, where the coefficients are field - /// elements. First argument is the witness index of the sum. - /// Vector consists of (optional coefficient, witness index) tuples, one for - /// each summand. The coefficient is optional, and if it is None, the - /// coefficient is 1. - Sum(usize, Vec<(Option, usize)>), - /// The product of the values at two specified witness indices - /// (witness index, operand witness index a, operand witness index b) - Product(usize, usize, usize), - /// Solves for the number of times that each memory address occurs in - /// read-only memory. Arguments: (first witness index, range size, - /// vector of all witness indices for values purported to be in the range) - MultiplicitiesForRange(usize, usize, Vec), - /// For solving for the denominator of an indexed lookup. - /// Fields are (witness index, sz_challenge, (index_coeff, index), - /// rs_challenge, value). - IndexedLogUpDenominator(usize, usize, (FieldElement, usize), usize, usize), - /// For solving for the denominator of a lookup (non-indexed). - /// Field are (witness index, sz_challenge, (value_coeff, value)). - LogUpDenominator(usize, usize, (FieldElement, usize)), - /// Products with linear operations on the witness indices. - /// Fields are ProductLinearOperation(witness_idx, (index, a, b), (index, c, - /// d)) such that we wish to compute (ax + b) * (cx + d). - ProductLinearOperation( - usize, - (usize, FieldElement, FieldElement), - (usize, FieldElement, FieldElement), - ), - /// A factor of the multiset check used in read/write memory checking. - /// Values: (witness index, sz_challenge, rs_challenge, (addr, - /// addr_witness), value, (timer, timer_witness)) where sz_challenge, - /// rs_challenge, addr_witness, timer_witness are witness indices. - /// Solver computes: - /// sz_challenge - (addr * addr_witness + rs_challenge * value + - /// rs_challenge * rs_challenge * timer * timer_witness) - SpiceMultisetFactor( - usize, - usize, - usize, - (FieldElement, usize), - usize, - (FieldElement, usize), - ), - /// Builds the witnesses values required for the Spice memory model. - /// (Note that some witness values are already solved for by the ACIR - /// solver.) - SpiceWitnesses(SpiceWitnesses), - /// Builds the witnesses values required for the mixed base digital - /// decomposition of other witness values. - DigitalDecomposition(DigitalDecompositionWitnesses), - - /// A witness value for the denominator of a bin op lookup. - /// Arguments: `(witness index, sz_challenge, rs_challenge, - /// rs_challenge_sqrd, lhs, rhs, output)`, where `lhs`, `rhs`, and - /// `output` are either constant or witness values. - BinOpLookupDenominator( - usize, - usize, - usize, - usize, - ConstantOrR1CSWitness, - ConstantOrR1CSWitness, - ConstantOrR1CSWitness, - ), - /// Witness values for the number of times that each pair of input values - /// occurs in the bin op. - MultiplicitiesForBinOp(usize, Vec<(ConstantOrR1CSWitness, ConstantOrR1CSWitness)>), -} - -impl WitnessBuilder { - /// The number of witness values that this builder writes to the witness - /// vector. - pub fn num_witnesses(&self) -> usize { - match self { - WitnessBuilder::Constant(..) => 1, - WitnessBuilder::Acir(..) => 1, - WitnessBuilder::Challenge(_) => 1, - WitnessBuilder::Inverse(..) => 1, - WitnessBuilder::Sum(..) => 1, - WitnessBuilder::Product(..) => 1, - WitnessBuilder::MultiplicitiesForRange(_, range_size, _) => *range_size, - WitnessBuilder::IndexedLogUpDenominator(..) => 1, - WitnessBuilder::LogUpDenominator(..) => 1, - WitnessBuilder::ProductLinearOperation(..) => 1, - WitnessBuilder::SpiceMultisetFactor(..) => 1, - WitnessBuilder::SpiceWitnesses(spice_witnesses_struct) => { - spice_witnesses_struct.num_witnesses - } - WitnessBuilder::DigitalDecomposition(dd_struct) => dd_struct.num_witnesses, - WitnessBuilder::BinOpLookupDenominator(..) => 1, - WitnessBuilder::MultiplicitiesForBinOp(..) => 2usize.pow(2 * BINOP_ATOMIC_BITS as u32), - } - } - - /// Return the index of the first witness value that this builder writes to. - pub fn first_witness_idx(&self) -> usize { - match self { - WitnessBuilder::Constant(start_idx, _) => *start_idx, - WitnessBuilder::Acir(start_idx, _) => *start_idx, - WitnessBuilder::Challenge(start_idx) => *start_idx, - WitnessBuilder::Inverse(start_idx, _) => *start_idx, - WitnessBuilder::Sum(start_idx, _) => *start_idx, - WitnessBuilder::Product(start_idx, ..) => *start_idx, - WitnessBuilder::MultiplicitiesForRange(start_idx, ..) => *start_idx, - WitnessBuilder::IndexedLogUpDenominator(start_idx, ..) => *start_idx, - WitnessBuilder::LogUpDenominator(start_idx, ..) => *start_idx, - WitnessBuilder::ProductLinearOperation(start_idx, ..) => *start_idx, - WitnessBuilder::SpiceMultisetFactor(start_idx, ..) => *start_idx, - WitnessBuilder::SpiceWitnesses(spice_witnesses_struct) => { - spice_witnesses_struct.first_witness_idx - } - WitnessBuilder::DigitalDecomposition(dd_struct) => dd_struct.first_witness_idx, - WitnessBuilder::BinOpLookupDenominator(start_idx, ..) => *start_idx, - WitnessBuilder::MultiplicitiesForBinOp(start_idx, _) => *start_idx, - } - } - - /// As per solve(), but additionally appends the solved witness values to - /// the transcript. - pub fn solve_and_append_to_transcript( - &self, - witness: &mut [FieldElement], - acir_witnesses: &WitnessMap, - transcript: &mut MockTranscript, - ) { - self.solve(witness, acir_witnesses, transcript); - for i in 0..self.num_witnesses() { - transcript.append(witness[self.first_witness_idx() + i]); - } - } - - /// Solves for the witness value(s) specified by this builder and writes - /// them to the witness vector. - pub fn solve( - &self, - witness: &mut [FieldElement], - acir_witnesses: &WitnessMap, - transcript: &mut MockTranscript, - ) { - match self { - WitnessBuilder::Constant(witness_idx, c) => { - witness[*witness_idx] = *c; - } - WitnessBuilder::Acir(witness_idx, acir_witness_idx) => { - witness[*witness_idx] = acir_witnesses[&AcirWitness(*acir_witness_idx as u32)]; - } - WitnessBuilder::Challenge(witness_idx) => { - witness[*witness_idx] = transcript.draw_challenge(); - } - WitnessBuilder::Inverse(witness_idx, operand_idx) => { - let operand: FieldElement = witness[*operand_idx]; - witness[*witness_idx] = operand.inverse(); - } - WitnessBuilder::Sum(witness_idx, operands) => { - witness[*witness_idx] = operands - .iter() - .map(|(coeff, witness_idx)| { - if let Some(coeff) = coeff { - *coeff * witness[*witness_idx] - } else { - witness[*witness_idx] - } - }) - .fold(FieldElement::zero(), |acc, x| acc + x); - } - WitnessBuilder::Product(witness_idx, operand_idx_a, operand_idx_b) => { - let a: FieldElement = witness[*operand_idx_a]; - let b: FieldElement = witness[*operand_idx_b]; - witness[*witness_idx] = a * b; - } - WitnessBuilder::IndexedLogUpDenominator( - witness_idx, - sz_challenge, - (index_coeff, index), - rs_challenge, - value, - ) => { - let index = witness[*index]; - let value = witness[*value]; - let rs_challenge = witness[*rs_challenge]; - let sz_challenge = witness[*sz_challenge]; - witness[*witness_idx] = - sz_challenge - (*index_coeff * index + rs_challenge * value); - } - WitnessBuilder::LogUpDenominator(witness_idx, sz_challenge, (value_coeff, value)) => { - witness[*witness_idx] = witness[*sz_challenge] - (*value_coeff * witness[*value]); - } - WitnessBuilder::ProductLinearOperation(witness_idx, (x, a, b), (y, c, d)) => { - witness[*witness_idx] = (*a * witness[*x] + *b) * (*c * witness[*y] + *d); - } - WitnessBuilder::MultiplicitiesForRange(start_idx, range_size, value_witnesses) => { - let mut multiplicities = vec![0u32; *range_size]; - for value_witness_idx in value_witnesses { - let value = witness[*value_witness_idx].try_to_u64().unwrap() as usize; - multiplicities[value] += 1; - } - for (i, count) in multiplicities.iter().enumerate() { - witness[start_idx + i] = FieldElement::from(*count); - } - } - WitnessBuilder::SpiceMultisetFactor( - witness_idx, - sz_challenge, - rs_challenge, - (addr, addr_witness), - value, - (timer, timer_witness), - ) => { - witness[*witness_idx] = witness[*sz_challenge] - - (*addr * witness[*addr_witness] - + witness[*rs_challenge] * witness[*value] - + witness[*rs_challenge] - * witness[*rs_challenge] - * *timer - * witness[*timer_witness]); - } - WitnessBuilder::SpiceWitnesses(spice_witnesses) => { - spice_witnesses.solve(witness); - } - WitnessBuilder::DigitalDecomposition(dd_struct) => { - dd_struct.solve(witness); - } - WitnessBuilder::BinOpLookupDenominator( - witness_idx, - sz_challenge, - rs_challenge, - rs_challenge_sqrd, - lhs, - rhs, - output, - ) => { - let lhs = match lhs { - ConstantOrR1CSWitness::Constant(c) => *c, - ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx], - }; - let rhs = match rhs { - ConstantOrR1CSWitness::Constant(c) => *c, - ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx], - }; - let output = match output { - ConstantOrR1CSWitness::Constant(c) => *c, - ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx], - }; - witness[*witness_idx] = witness[*sz_challenge] - - (lhs + witness[*rs_challenge] * rhs + witness[*rs_challenge_sqrd] * output); - } - WitnessBuilder::MultiplicitiesForBinOp(witness_idx, operands) => { - let mut multiplicities = vec![0u32; 2usize.pow(2 * BINOP_ATOMIC_BITS as u32)]; - for (lhs, rhs) in operands { - let lhs = match lhs { - ConstantOrR1CSWitness::Constant(c) => *c, - ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx], - }; - let rhs = match rhs { - ConstantOrR1CSWitness::Constant(c) => *c, - ConstantOrR1CSWitness::Witness(witness_idx) => witness[*witness_idx], - }; - let index = (lhs.try_to_u64().unwrap() << BINOP_ATOMIC_BITS) - + rhs.try_to_u64().unwrap(); - multiplicities[index as usize] += 1; - } - for (i, count) in multiplicities.iter().enumerate() { - witness[witness_idx + i] = FieldElement::from(*count); - } - } - } - } -} - -/// Mock transcript. To be replaced. -pub struct MockTranscript {} - -impl MockTranscript { - pub fn new() -> Self { - Self {} - } - - pub fn append(&mut self, _value: FieldElement) {} - - pub fn draw_challenge(&mut self) -> FieldElement { - let mut rng = rand::thread_rng(); - let n: u32 = rng.gen(); - n.into() - } -} diff --git a/noir-r1cs-logup/src/sparse_matrix.rs b/noir-r1cs-logup/src/sparse_matrix.rs deleted file mode 100644 index 23175f101..000000000 --- a/noir-r1cs-logup/src/sparse_matrix.rs +++ /dev/null @@ -1,155 +0,0 @@ -use std::{ - collections::BTreeMap, - fmt::{Debug, Display, Formatter}, - ops::{AddAssign, Index, IndexMut, Mul}, -}; - -use acir::{AcirField, FieldElement}; - -/// A sparse matrix with elements of type `F`. -#[derive(Debug, Clone, Default)] -pub struct SparseMatrix { - /// The number of rows in the matrix. - pub rows: usize, - - /// The number of columns in the matrix. - pub cols: usize, - - /// The default value of the matrix. - pub default: F, - - /// The non-default entries of the matrix. - pub entries: BTreeMap<(usize, usize), F>, -} - -impl SparseMatrix { - pub fn new(rows: usize, cols: usize, default: F) -> Self { - Self { - rows, - cols, - default, - entries: BTreeMap::new(), - } - } - - pub fn grow(&mut self, rows: usize, cols: usize) { - // TODO: Make it default infinite size instead. - assert!(rows >= self.rows); - assert!(cols >= self.cols); - self.rows = rows; - self.cols = cols; - } - - /// Set the value at the given row and column. - pub fn set(&mut self, row: usize, col: usize, value: F) { - assert!(row < self.rows, "row index out of bounds"); - assert!(col < self.cols, "column index out of bounds"); - self.entries.insert((row, col), value); - } - - /// Return a dense representation of the matrix. - /// (This is a helper method for debugging.) - fn to_dense(&self) -> Vec> - where - F: Clone, - { - let mut result = vec![vec![self.default.clone(); self.cols]; self.rows]; - for ((i, j), value) in self.entries.iter() { - result[*i][*j] = value.clone(); - } - result - } -} - -/// Print a dense representation of the matrix, for debugging. -impl Display for SparseMatrix { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - let dense = self.to_dense(); - for row in dense.iter() { - for value in row.iter() { - write!(f, "{:?}\t", value)?; - } - writeln!(f)?; - } - Ok(()) - } -} - -impl SparseMatrix { - /// Iterate over the non-default entries of the matrix. - pub fn iter(&self) -> impl Iterator { - self.entries.iter().filter_map(|(k, v)| { - if v != &self.default { - Some((*k, v)) - } else { - None - } - }) - } - - // TODO wouldn't it be better to use the CSR format (not the COO format?) for sparse matrices? There should never be a row without a non-zero entry. - /// Iterate over the non-default entries of the given row. - pub fn iter_row(&self, row: usize) -> impl Iterator { - self.entries - .range((row, 0)..(row + 1, 0)) - .filter_map(|((_, c), v)| { - if v != &self.default { - Some((*c, v)) - } else { - None - } - }) - } - - /// Remove the default entries from the entries list. - pub fn cleanup(&mut self) { - self.entries.retain(|_, v| v != &self.default); - } -} - -impl Index<(usize, usize)> for SparseMatrix { - type Output = F; - - fn index(&self, (i, j): (usize, usize)) -> &Self::Output { - assert!(i < self.rows, "row index out of bounds"); - assert!(j < self.cols, "column index out of bounds"); - self.entries.get(&(i, j)).unwrap_or(&self.default) - } -} - -impl IndexMut<(usize, usize)> for SparseMatrix { - fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut Self::Output { - assert!(i < self.rows, "row index out of bounds"); - assert!(j < self.cols, "column index out of bounds"); - self.entries.entry((i, j)).or_insert(self.default.clone()) - } -} - -impl Mul<&[F]> for &SparseMatrix -where - F: Clone + AddAssign, - for<'a> &'a F: Mul, -{ - type Output = Vec; - - fn mul(self, rhs: &[F]) -> Self::Output { - assert_eq!( - self.cols, - rhs.len(), - "Vector length does not match number of columns." - ); - let mut result = vec![self.default.clone(); self.rows]; - for ((i, j), value) in self.entries.iter() { - result[*i] += value * &rhs[*j]; - } - result - } -} - -pub fn mat_mul(a: &SparseMatrix, b: &[FieldElement]) -> Vec { - let mut result = vec![FieldElement::zero(); a.rows]; - for ((i, j), &value) in a.iter() { - result[i] += value * b[j]; - } - result -} diff --git a/noir-r1cs-logup/src/test_compiler.rs b/noir-r1cs-logup/src/test_compiler.rs deleted file mode 100644 index b0024a2f4..000000000 --- a/noir-r1cs-logup/src/test_compiler.rs +++ /dev/null @@ -1,126 +0,0 @@ -use std::fs::File; -use noirc_artifacts::program::ProgramArtifact; -use crate::{compiler::R1CS, range_check::NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP, solver::MockTranscript, utils::file_io::deserialize_witness_stack}; - -// Tests that an ACIR program containing a can be compiled to R1CS and -// the R1CS witness solved for given the ACIR witness. -fn test_compilation_and_solving( - program_path: &str, - witness_path: &str, -) { - let file = File::open(program_path).unwrap(); - let program: ProgramArtifact = serde_json::from_reader(file).unwrap(); - let acir_circuit = &program.bytecode.functions[0]; - // Compile the ACIR circuit to R1CS - let r1cs = R1CS::from_acir(acir_circuit); - println!("R1CS: {}", r1cs); - - // Solve for the R1CS witness using the ACIR witness - let mut witness_stack = deserialize_witness_stack(witness_path).unwrap(); - let acir_witness = witness_stack.pop().unwrap().witness; - - let mut transcript = MockTranscript::new(); - let witness = r1cs.solve(&mut transcript, &acir_witness); - if witness.len() < 100 { - println!("Witness:"); - for (i, w) in witness.iter().enumerate() { - println!("w[{}]: {}", i, w); - } - } else { - println!("Witness length: {} (too long to print)", witness.len()); - } - - // Check that the witness satisfies the R1CS relation - assert!(r1cs.matrices.test_satisfaction(&witness).is_none()); -} - -#[test] -fn test_brillig_conditional() { - test_compilation_and_solving( - "src/test_programs/brillig-conditional/target/main.json", - "src/test_programs/brillig-conditional/target/main.gz", - ); -} - -#[test] -fn test_simplest_read_only() { - test_compilation_and_solving( - "src/test_programs/simplest-read-only-memory/target/main.json", - "src/test_programs/simplest-read-only-memory/target/main.gz", - ); -} - -#[test] -fn test_read_only_memory() { - test_compilation_and_solving( - "src/test_programs/read-only-memory/target/main.json", - "src/test_programs/read-only-memory/target/main.gz", - ); -} - -#[test] -fn test_read_write_memory() { - test_compilation_and_solving( - "src/test_programs/read-write-memory/target/main.json", - "src/test_programs/read-write-memory/target/main.gz", - ); -} - -#[test] -fn test_conditional_write() { - test_compilation_and_solving( - "src/test_programs/conditional-write/target/main.json", - "src/test_programs/conditional-write/target/main.gz", - ); -} - -#[test] -// Test a direct range check (i.e. without a digital decomposition) -fn test_atomic_range_check() { - assert!(8 <= NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP); - test_compilation_and_solving( - "src/test_programs/range-check-u8/target/main.json", - "src/test_programs/range-check-u8/target/main.gz", - ); -} - -#[test] -// Test a range check that requires a digital decomposition -fn test_digital_decomposition_u16() { - assert!(16 > NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP); - test_compilation_and_solving( - "src/test_programs/range-check-u16/target/main.json", - "src/test_programs/range-check-u16/target/main.gz", - ); -} - -#[test] -// Test a range check that requires a digital decomposition mixed bases -// The program compiles to the following ACIR: -// BrilligCall -// RANGE CHECK of witness 1 to 238 bits -// RANGE CHECK of witness 2 to 16 bits -// BrilligCall -// RANGE CHECK of witness 7 to 17 bits -// .. -// + The 238 bit range check is done using a digital decomposition using 29 base-2^8 digits and one -// base-2^6 digit. -// + The 16 bit range check is done using a digital decomposition using 2 base-2^8 digits. -// + The 17 bit range check is done using a digital decomposition using 2 base-2^8 digits and one -// base-2^1 digit. -// Note that the range check of the base-2^1 digit will be done using a direct ("naive") range -// check. -fn test_mixed_base_range_check() { - test_compilation_and_solving( - "src/test_programs/range-check-mixed-bases/target/main.json", - "src/test_programs/range-check-mixed-bases/target/main.gz", - ); -} - -#[test] -fn test_binops() { - test_compilation_and_solving( - "src/test_programs/bin-opcode/target/main.json", - "src/test_programs/bin-opcode/target/main.gz", - ); -} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/bin-opcode/Nargo.toml b/noir-r1cs-logup/src/test_programs/bin-opcode/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/bin-opcode/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/bin-opcode/Prover.toml b/noir-r1cs-logup/src/test_programs/bin-opcode/Prover.toml deleted file mode 100644 index cb426dd77..000000000 --- a/noir-r1cs-logup/src/test_programs/bin-opcode/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -w = 7 -x = 10 -y = 3 -z = 15 diff --git a/noir-r1cs-logup/src/test_programs/bin-opcode/src/main.nr b/noir-r1cs-logup/src/test_programs/bin-opcode/src/main.nr deleted file mode 100644 index a6534df59..000000000 --- a/noir-r1cs-logup/src/test_programs/bin-opcode/src/main.nr +++ /dev/null @@ -1,6 +0,0 @@ -fn main(w: u32, x: u32, y: u32, z: u32) -> pub u32 { - let hi = x & x ^ y & y & z & z ^ w & w; - let bye = x & (31 as u32); - let rye = y ^ (64 as u32); - bye & rye ^ hi -} diff --git a/noir-r1cs-logup/src/test_programs/bin-opcode/target/main.gz b/noir-r1cs-logup/src/test_programs/bin-opcode/target/main.gz deleted file mode 100644 index 03e8e069bff8a1892b43988e5a4ee655ed41701c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 105 zcmV-v0G9tBiwFP!00002|E<%x4FDkwMA2pM`{)EMNI*s_B=lbb2@>S|N$lv!4n}k( zU$y%@Wm}Bktk83o8aOMCob^wf pub u32 {\n let hi = x & x ^ y & y & z & z ^ w & w;\n let bye = x & (31 as u32);\n let rye = y ^ (64 as u32);\n bye & rye ^ hi\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/bin-opcode/src/main.nr"}},"names":["main"],"brillig_names":["directive_integer_quotient"]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/brillig-conditional/Nargo.toml b/noir-r1cs-logup/src/test_programs/brillig-conditional/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/brillig-conditional/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/brillig-conditional/Prover.toml b/noir-r1cs-logup/src/test_programs/brillig-conditional/Prover.toml deleted file mode 100644 index a187696ee..000000000 --- a/noir-r1cs-logup/src/test_programs/brillig-conditional/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -a = "1" -b = "2" diff --git a/noir-r1cs-logup/src/test_programs/brillig-conditional/src/main.nr b/noir-r1cs-logup/src/test_programs/brillig-conditional/src/main.nr deleted file mode 100644 index c78a820a5..000000000 --- a/noir-r1cs-logup/src/test_programs/brillig-conditional/src/main.nr +++ /dev/null @@ -1,5 +0,0 @@ -fn main(a: Field, b: Field) { - if a == 1 { - assert(b == 2); - } -} diff --git a/noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.gz b/noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.gz deleted file mode 100644 index 9c885669bc88c9098f53a714e166a20ceef3b7b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60 zcmb2|=3oE;rvGavY!qa0U}3qxSUzOI|5Yk!C+@11Uu5&nzwmYQ^*oD*F&_){k{5V4 P?B#mPwR+VAMg|4|v2z&8 diff --git a/noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.json b/noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.json deleted file mode 100644 index 01a35bd84..000000000 --- a/noir-r1cs-logup/src/test_programs/brillig-conditional/target/main.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"1.0.0-beta.1+03b58fa2dfcc8acc8cf5198b1b23b55676fbdb02","hash":18086673318627970171,"abi":{"parameters":[{"name":"a","type":{"kind":"field"},"visibility":"private"},{"name":"b","type":{"kind":"field"},"visibility":"private"}],"return_type":null,"error_types":{}},"bytecode":"H4sIAAAAAAAA/7WUQQ6DIBBFRWjarqv3mBFQ2HmVmuL9j9AmQjKZki7q8BMzBsjnzwugukPm8126b/W5rrlamJ1Ly5TQ4hOmuAUPzm9zwIA++NcUrE3BhSVucYGIzibcfbQ7HJL06okXnBOa7KMqDBRjAOeEgrmB5tUtA+sGvkb4YLXo2xDAQr5Nsqqclfv+yzXth0wne1gLz55wrV06PndndSTzWpBj8R/a+MO10uNI/gfWJ+W0CmUofuXB+PXwX9jaG8un5PNhx6QrexU9ch3IWOH5BmlYYRTdBgAA","debug_symbols":"lZBLCsMgFEX38sYOUmNKcSulBL9BEBU/hSLZe01IIIVOHJ57z7uDV0EqXpbZOO0T0GcF6wXLxrtGFYY9SoG5jVJmMQMdCQLlJFAyrAi0sQroHa8vBLc+HffpY59O/ukTPvTp8aM34NFYa5b5+oAWv1k0jFt1oC5OXNr8CWdz3ofohZIlqm1p79r8Fw==","file_map":{"62":{"source":"fn main(a: Field, b: Field) {\n\tif a == 1 {\n\t\tassert(b == 2);\n\t}\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/brillig-conditional/src/main.nr"}},"names":["main"],"brillig_names":["directive_invert"]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/conditional-write/Nargo.toml b/noir-r1cs-logup/src/test_programs/conditional-write/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/conditional-write/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/conditional-write/Prover.toml b/noir-r1cs-logup/src/test_programs/conditional-write/Prover.toml deleted file mode 100644 index 7fa4cd40e..000000000 --- a/noir-r1cs-logup/src/test_programs/conditional-write/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -switch = 1 -mem = [7, 11] -addr0 = 0 -addr1 = 1 diff --git a/noir-r1cs-logup/src/test_programs/conditional-write/src/main.nr b/noir-r1cs-logup/src/test_programs/conditional-write/src/main.nr deleted file mode 100644 index ae8963e24..000000000 --- a/noir-r1cs-logup/src/test_programs/conditional-write/src/main.nr +++ /dev/null @@ -1,6 +0,0 @@ -fn main(switch: Field, mut mem: [Field; 2], addr0: Field, addr1: Field) -> pub Field { - if switch == 0 { - mem[addr0] = 2; - } - mem[addr1] -} diff --git a/noir-r1cs-logup/src/test_programs/conditional-write/target/main.gz b/noir-r1cs-logup/src/test_programs/conditional-write/target/main.gz deleted file mode 100644 index de1c81036cac9b14a7b78fe442177178f175c77a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 116 zcmV-)0E_=0iwFP!00002|E$lkg$J+mnb%u_$Mli1!?wCNY6y}vdRu21BK(7*dRq&2A>{kPKY+?2t^y;D4 W0KG=YnjmY2{ki}R`5-5p1^@v5TQ$Z2 diff --git a/noir-r1cs-logup/src/test_programs/conditional-write/target/main.json b/noir-r1cs-logup/src/test_programs/conditional-write/target/main.json deleted file mode 100644 index 29e35500f..000000000 --- a/noir-r1cs-logup/src/test_programs/conditional-write/target/main.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"1.0.0-beta.1+03b58fa2dfcc8acc8cf5198b1b23b55676fbdb02","hash":13766363820676621577,"abi":{"parameters":[{"name":"switch","type":{"kind":"field"},"visibility":"private"},{"name":"mem","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"private"},{"name":"addr0","type":{"kind":"field"},"visibility":"private"},{"name":"addr1","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"},"error_types":{}},"bytecode":"H4sIAAAAAAAA/+1ZbW6DMAw1pJR2a7duwM6R8FHCv15laPT+R9joEimN8i/P0qLVEgoKyHl+fjgGMvq15uf4MOfCjLkZM+d848z5ZucuZpRxpoC+pIt3ywl4y+C3dHx18tz3y9guqlOfsp1mPch+mM9aaTXo4avVXbfoXo/TPI1yUn23qOswdVfjjCvu0iEY5JcFqzBYfb+xvO6AcecUNiSvHNwiOeDCuGfAGAQaK6inh6AUkgMujM+UiKAOwKBTFdQhAYxHJEZB9/3bqtYj8Yls3VrXEiuwpLQl8WwBsfG+ELZKh/pqVNxcgk1h20fmiQUgV1/6ChYo8QmULflIDrgwnuifCvSNkqmgbMlHcsCF8Z2YBYpoPdan6C+3HidgvBU4ITlDPoCiuX0FqwI4ZZzdCTs25pqSKWZs7WAKxQyZJ0p119kkgLFhwHgzdBUpCFdFkEGvCbE/bQonfvtRQDjX7Xzo3tX23tg41wWQS+u/5vEv3X8V5MXirmtxuO89FxAG608E+CZv3cK7d+fhy/D4lI9FBNayVpmxduYsn98zMAcBYRwAAA==","debug_symbols":"ldNBCoMwEAXQu8zahRNbrV6lFIkaJRCixFgo4t0bpRZb3Pzlz8ybzSczNaqaulLbth+puM9k+lp63duQZuLtaRykXdPopfNU5ByRsg0VHIslolYbRUUqlkdEAtxPwP3L2T7H2Q44+wNXFKQoyFBwQ0GOAo5hwbAQsEhgAdfNcN8MF85w4wxXznDn4rxz8RXJrwihctoY3ZXHHx+en9JpWRn1ie1k68PUv4Z9svvB9bVqJqfWS9ssnH8D","file_map":{"62":{"source":"fn main(switch: Field, mut mem: [Field; 2], addr0: Field, addr1: Field) -> pub Field {\n\tif switch == 0 {\n\t\tmem[addr0] = 2;\n\t}\n\tmem[addr1]\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/conditional-write/src/main.nr"}},"names":["main"],"brillig_names":["directive_invert"]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Nargo.toml b/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Prover.toml b/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Prover.toml deleted file mode 100644 index 369ec53c8..000000000 --- a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -x = 2 -y = 2410 diff --git a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/src/main.nr b/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/src/main.nr deleted file mode 100644 index aa53eeacc..000000000 --- a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/src/main.nr +++ /dev/null @@ -1,3 +0,0 @@ -fn main(x: Field, y: Field) -> pub u16 { - (x as u16) + (y as u16) -} diff --git a/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/target/main.gz b/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/target/main.gz deleted file mode 100644 index dab3b82b16ec3d6b08adbedcdf469d6c26ce5c2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 148 zcmV;F0BipriwFP!00002|E-ft4#O}AM4SHq?NPu^iM{Jp4A}QSLKG=dvd^#pR!=Yk z-EN8Rs{hZGwngYrtSn`ZW7z?>BOQTyomQ+!(sQMngI29AaSD=LB&rn`S8Fat+-DxB zi4Pusq^#VE7!&asGZ# pub u16 {\n (x as u16) + (y as u16)\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/range-check-mixed-bases/src/main.nr"}},"names":["main"],"brillig_names":["directive_integer_quotient","directive_invert"]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/range-check-u16/Nargo.toml b/noir-r1cs-logup/src/test_programs/range-check-u16/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/range-check-u16/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/range-check-u16/Prover.toml b/noir-r1cs-logup/src/test_programs/range-check-u16/Prover.toml deleted file mode 100644 index 87cf3b090..000000000 --- a/noir-r1cs-logup/src/test_programs/range-check-u16/Prover.toml +++ /dev/null @@ -1 +0,0 @@ -x = 2222 diff --git a/noir-r1cs-logup/src/test_programs/range-check-u16/src/main.nr b/noir-r1cs-logup/src/test_programs/range-check-u16/src/main.nr deleted file mode 100644 index b4f772cab..000000000 --- a/noir-r1cs-logup/src/test_programs/range-check-u16/src/main.nr +++ /dev/null @@ -1 +0,0 @@ -fn main(x: u16) { } diff --git a/noir-r1cs-logup/src/test_programs/range-check-u16/target/main.gz b/noir-r1cs-logup/src/test_programs/range-check-u16/target/main.gz deleted file mode 100644 index b1b29452b69627f3a3d7ee72b44895a63045b89a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49 zcmb2|=3oE;rvFQiEfi#6;5h8COHk;f7RR@E#>26%f2%nPJo!DlZGv|?q`ukfQzOxD}~B=dY+pZA>O#7*C22|!f pub Field { - mem[addr0] * mem[addr1] + mem[addr2] -} diff --git a/noir-r1cs-logup/src/test_programs/read-only-memory/target/main.gz b/noir-r1cs-logup/src/test_programs/read-only-memory/target/main.gz deleted file mode 100644 index c049342c3c1f8ec4635eeb80780d545cf9e3e74b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92 zcmV-i0HgmOiwFP!00002|E<%x4FDkwMA2n$u3oqVBBTGRNRS}sPhv+eu*Tw;vCH1Z ybbE<{v&zX?`Qof}b5?ygE4-ZLKk!~ZXE}*kDJZb38tjAt|FHud!UJ*e0{{Rz)G1T| diff --git a/noir-r1cs-logup/src/test_programs/read-only-memory/target/main.json b/noir-r1cs-logup/src/test_programs/read-only-memory/target/main.json deleted file mode 100644 index 02bbc416c..000000000 --- a/noir-r1cs-logup/src/test_programs/read-only-memory/target/main.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"1.0.0-beta.1+03b58fa2dfcc8acc8cf5198b1b23b55676fbdb02","hash":14557024145136099777,"abi":{"parameters":[{"name":"mem","type":{"kind":"array","length":6,"type":{"kind":"field"}},"visibility":"private"},{"name":"addr0","type":{"kind":"field"},"visibility":"private"},{"name":"addr1","type":{"kind":"field"},"visibility":"private"},{"name":"addr2","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"},"error_types":{}},"bytecode":"H4sIAAAAAAAA/+1VUQ6DIAxF55xuHoZSkPK3q4wM73+ESdZFQ/xbf0h8SVMSyuPRQmnUF9NqVx5f2PdqQ7Nay3PdLrZVx3iy139iv78gL/QVaLxLaqy1ULcKND7OQmkYKtA4SWssBaKerU3eJEB4aRMiOW1dnAkIHLm3IcRElnyIwesAFhMsLuDCpPnJ59vUCh98FNQomcScv465RrXh6LvJLTt3g6GIK9f+8AEcY0Ms2wYAAA==","debug_symbols":"bY5LCsMgFEX38sYZxASkupVSgt8giIqfQpHsvSZESEuG591zL6+CVLysi3HaJ6DPCtYLlo13jSqg45QCczulzGIG+pgHUE4CJfM2gDZWAcXT9hpgutMJPnU04j9/vvPRSHoBkZ9CAx6NtWZdrl+285tFw7hVJ+rixCXNn9CT3g/RCyVLVPvSkbX5Lw==","file_map":{"62":{"source":"fn main(mem: [Field; 6], addr0: Field, addr1: Field, addr2: Field) -> pub Field {\n\tmem[addr0] * mem[addr1] + mem[addr2]\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/read-only-memory/src/main.nr"}},"names":["main"],"brillig_names":[]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/read-write-memory/Nargo.toml b/noir-r1cs-logup/src/test_programs/read-write-memory/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/read-write-memory/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/read-write-memory/Prover.toml b/noir-r1cs-logup/src/test_programs/read-write-memory/Prover.toml deleted file mode 100644 index 1d0127cd9..000000000 --- a/noir-r1cs-logup/src/test_programs/read-write-memory/Prover.toml +++ /dev/null @@ -1,4 +0,0 @@ -mem = [3, 7, 6] -addr0 = 1 -addr1 = 2 -addr = 1 diff --git a/noir-r1cs-logup/src/test_programs/read-write-memory/src/main.nr b/noir-r1cs-logup/src/test_programs/read-write-memory/src/main.nr deleted file mode 100644 index ce5754e8a..000000000 --- a/noir-r1cs-logup/src/test_programs/read-write-memory/src/main.nr +++ /dev/null @@ -1,6 +0,0 @@ -fn main(mut mem: [Field; 3], addr0: Field, addr1: Field, addr: Field) -> pub Field { - let z = mem[addr0]; - mem[addr0] = mem[addr1]; - mem[addr1] = z; - mem[addr] -} diff --git a/noir-r1cs-logup/src/test_programs/read-write-memory/target/main.gz b/noir-r1cs-logup/src/test_programs/read-write-memory/target/main.gz deleted file mode 100644 index e6d78a13c992bee0eadb4cc52f5d949f37bb3b95..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78 zcmb2|=3oE;rvGa%T5>Tc@VEp%UbnoEF?a9(l{qYL|6W$Pn(X0n_epwu`n3He57(@; i%$7K}YTD*m%+-}2;u!xVvs9~IxYc;L?mG`N0|Nl`ha!dm diff --git a/noir-r1cs-logup/src/test_programs/read-write-memory/target/main.json b/noir-r1cs-logup/src/test_programs/read-write-memory/target/main.json deleted file mode 100644 index 08cf7e92b..000000000 --- a/noir-r1cs-logup/src/test_programs/read-write-memory/target/main.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"1.0.0-beta.1+03b58fa2dfcc8acc8cf5198b1b23b55676fbdb02","hash":17107723668014488676,"abi":{"parameters":[{"name":"mem","type":{"kind":"array","length":3,"type":{"kind":"field"}},"visibility":"private"},{"name":"addr0","type":{"kind":"field"},"visibility":"private"},{"name":"addr1","type":{"kind":"field"},"visibility":"private"},{"name":"addr","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"},"error_types":{}},"bytecode":"H4sIAAAAAAAA/+1W2wrDIAxttZf1b4yXGt/2K5PZ//+E2S0Fkb3VPgR6ICQQiSc5ROy7H5ZsM8Wy8jv6bIJi0f3Hk7w6ifLOhnVBMuA4t+TIVaiBAccHI6HgqiFw2KhbKCYbdT99eQgjA47LBRy/EI2JTkUto1Zrk9cJDLyUDhGdsi6uCAgO3VujMQkt+hCDVwGsSbC5YDYq1rLpXZCBak1F/8cnS1J+rHL1+QMfcIhQKcUJAAA=","debug_symbols":"bdDRCoMgFAbgdznXXWjaIl9ljLCyEETDdDCkd5/FHCVe/uf3O8gJMInBL73Us9mAPQMoM3InjY4pAD5H28r1kTbHrQPW0QqEnoBhRPcKZqkEsEe9vyqoS+9xjRIgKAOkCFCbAG4zQIuAkAQoyUBTBM3/S013AzEMVioll/56iTh+cyv5oMQvzl6Pl9Z91tQkv1ozislbcWw6u7j+Cw==","file_map":{"62":{"source":"fn main(mut mem: [Field; 3], addr0: Field, addr1: Field, addr: Field) -> pub Field {\n\tlet z = mem[addr0];\n\tmem[addr0] = mem[addr1];\n\tmem[addr1] = z;\n\tmem[addr]\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/read-write-memory/src/main.nr"}},"names":["main"],"brillig_names":[]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Nargo.toml b/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Nargo.toml deleted file mode 100644 index 92c044bfe..000000000 --- a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Nargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "main" -type = "bin" -authors = [""] - -[dependencies] diff --git a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Prover.toml b/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Prover.toml deleted file mode 100644 index 3e7e8d9a3..000000000 --- a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/Prover.toml +++ /dev/null @@ -1,2 +0,0 @@ -mem = [3, 7] -addr = 1 diff --git a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/src/main.nr b/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/src/main.nr deleted file mode 100644 index 10b6cc3c5..000000000 --- a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/src/main.nr +++ /dev/null @@ -1,3 +0,0 @@ -fn main(mem: [Field; 2], addr: Field) -> pub Field { - mem[addr] -} diff --git a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.gz b/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.gz deleted file mode 100644 index b36c83eef0b88515a08f630defe22ccc00e9ec4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 61 zcmb2|=3oE;rvGdEHu5qUa2)oE{>Nyz;nV+69ghvd`X^In`W=4kzV?m5p`Cvo#r$fB Qm4D%NRp$G_35*O30N8vQx&QzG diff --git a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.json b/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.json deleted file mode 100644 index dd22349a3..000000000 --- a/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/target/main.json +++ /dev/null @@ -1 +0,0 @@ -{"noir_version":"1.0.0-beta.1+03b58fa2dfcc8acc8cf5198b1b23b55676fbdb02","hash":16200297735627271051,"abi":{"parameters":[{"name":"mem","type":{"kind":"array","length":2,"type":{"kind":"field"}},"visibility":"private"},{"name":"addr","type":{"kind":"field"},"visibility":"private"}],"return_type":{"abi_type":{"kind":"field"},"visibility":"public"},"error_types":{}},"bytecode":"H4sIAAAAAAAA/9WSwQ3DMAhF7dgDgYEYbl2lVp39R2iruqqb5BbnkCchEIfPR+Ddh/iK0OpvntwPv9PrubUMB1nPG6SL0wU8xhM8/h1tlNHQaRHMzDWnioR3SFZUgKXMioqi8khKVJU1W7EMhkwVFzFamtjIpd8HiU0rdPt7t//MwW15AhlS2OERAwAA","debug_symbols":"TYxLCsMwDAXvonU2/S58lVKCP3IQGNnIdqGY3L1KaCA7zRs0AwK6vszEMVcwrwEpe9sos9KAyz7VYnmj2qw0MI/7BMgBzPO2ThApoZ7X9a3ghFKiZT5HdP5YIesS/jF29ifbvuUwx3+R7DF0wa20O83/AA==","file_map":{"62":{"source":"fn main(mem: [Field; 2], addr: Field) -> pub Field {\n\tmem[addr]\n}\n","path":"/Users/bw/working/ProveKitMain/noir-r1cs-logup/src/test_programs/simplest-read-only-memory/src/main.nr"}},"names":["main"],"brillig_names":[]} \ No newline at end of file diff --git a/noir-r1cs-logup/src/utils/file_io.rs b/noir-r1cs-logup/src/utils/file_io.rs deleted file mode 100644 index fe2587d68..000000000 --- a/noir-r1cs-logup/src/utils/file_io.rs +++ /dev/null @@ -1,26 +0,0 @@ -use { - acir::native_types::{WitnessStack, WitnessStackError}, - anyhow::{Context, Result}, - flate2::read::GzDecoder, - serde::Deserialize, - std::{ - fs::File, - io::{BufReader, Read}, - }, -}; - -/// Deserialize WitnessStack from basic.gz -pub fn deserialize_witness_stack Deserialize<'a>>( - file_path: &str, -) -> Result, WitnessStackError> { - let file = File::open(file_path) - .context("while opening witness file") - .unwrap(); - let mut decoder = GzDecoder::new(BufReader::new(file)); - - let mut decompressed_bytes = Vec::new(); - decoder.read_to_end(&mut decompressed_bytes).unwrap(); - - let witness_stack: WitnessStack = bincode::deserialize(&decompressed_bytes).unwrap(); - Ok(witness_stack) -} diff --git a/noir-r1cs-logup/src/utils/mod.rs b/noir-r1cs-logup/src/utils/mod.rs deleted file mode 100644 index 848a7742b..000000000 --- a/noir-r1cs-logup/src/utils/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod file_io; -mod print_abi; -pub use self::print_abi::PrintAbi; diff --git a/noir-r1cs-logup/src/utils/print_abi.rs b/noir-r1cs-logup/src/utils/print_abi.rs deleted file mode 100644 index 9fe049f8c..000000000 --- a/noir-r1cs-logup/src/utils/print_abi.rs +++ /dev/null @@ -1,62 +0,0 @@ -use { - noirc_abi::{Abi, AbiType, AbiVisibility, Sign}, - std::fmt::{Display, Formatter, Result}, -}; - -pub struct PrintAbi<'a>(pub &'a Abi); - -pub struct PrintType<'a>(pub &'a AbiType); - -impl Display for PrintAbi<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - write!(f, "(")?; - for (i, param) in self.0.parameters.iter().enumerate() { - write!(f, "{}: ", param.name)?; - match param.visibility { - AbiVisibility::Public => write!(f, "pub ")?, - AbiVisibility::Private => {} - AbiVisibility::DataBus => write!(f, "data_bus ")?, - } - write!(f, "{}", PrintType(¶m.typ))?; - if i < self.0.parameters.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ")") - } -} - -impl Display for PrintType<'_> { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - match self.0 { - AbiType::Field => write!(f, "Field"), - AbiType::Boolean => write!(f, "bool"), - AbiType::Integer { sign, width } => match sign { - Sign::Signed => write!(f, "i{width}"), - Sign::Unsigned => write!(f, "u{width}"), - }, - AbiType::String { length } => write!(f, "str<{length}>"), - AbiType::Array { length, typ } => write!(f, "[{}; {length}]", PrintType(typ)), - AbiType::Tuple { fields } => { - write!(f, "(")?; - for (idx, typ) in fields.iter().enumerate() { - write!(f, "{}", PrintType(typ))?; - if idx < fields.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, ")") - } - AbiType::Struct { path, fields } => { - write!(f, "{path} {{")?; - for (idx, (name, typ)) in fields.iter().enumerate() { - write!(f, "{}: {}", name, PrintType(typ))?; - if idx < fields.len() - 1 { - write!(f, ", ")?; - } - } - write!(f, "}}") - } - } - } -} diff --git a/noir-r1cs/src/test_functions.rs b/noir-r1cs/src/test_functions.rs index 4240fd9db..01b614a5c 100644 --- a/noir-r1cs/src/test_functions.rs +++ b/noir-r1cs/src/test_functions.rs @@ -1,7 +1,9 @@ -use crate::range_check::NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP; #[cfg(test)] use { - crate::{utils::file_io::deserialize_witness_stack, NoirProofScheme}, + crate::{ + range_check::NUM_BITS_THRESHOLD_FOR_DIGITAL_DECOMP, + utils::file_io::deserialize_witness_stack, NoirProofScheme, + }, acir::native_types::WitnessMap, acir_field::FieldElement as AcirFieldElement, anyhow::Context, From 6aa4fde719bc52c233ed5b1d5103aa728d84e518 Mon Sep 17 00:00:00 2001 From: vishruti Date: Thu, 22 May 2025 13:29:36 -0700 Subject: [PATCH 3/3] cargo toml no longer has noir-r1cs-logup --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6336bf6ba..e17ce323e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] resolver = "2" members = [ - "noir-r1cs", "noir-r1cs-logup", + "noir-r1cs", "merkle-hash-bench", "fp-rounding", "hla",