From 4f0f6ac39daa5459e96c4b9b185e832d70433b0c Mon Sep 17 00:00:00 2001 From: Remco Bloemen Date: Tue, 14 Oct 2025 12:59:21 +0200 Subject: [PATCH] Upgrade to Noir beta14 --- Cargo.toml | 18 +-- provekit/r1cs-compiler/src/noir_to_r1cs.rs | 68 +++++----- tooling/cli/src/cmd/circuit_stats.rs | 147 ++++----------------- 3 files changed, 70 insertions(+), 163 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a0a0f09f..7d31c1e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -128,15 +128,15 @@ zeroize = "1.8.1" zstd = "0.13.3" # Noir language dependencies -acir = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -bn254_blackbox_solver = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -nargo = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -nargo_cli = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -nargo_toml = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -noir_artifact_cli = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -noirc_abi = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -noirc_artifacts = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } -noirc_driver = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.11" } +acir = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +bn254_blackbox_solver = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +nargo = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +nargo_cli = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +nargo_toml = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +noir_artifact_cli = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +noirc_abi = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +noirc_artifacts = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } +noirc_driver = { git = "https://github.com/noir-lang/noir", rev = "v1.0.0-beta.14" } # Cryptography and proof systems ark-bn254 = { version = "0.5.0", default-features = false, features = [ diff --git a/provekit/r1cs-compiler/src/noir_to_r1cs.rs b/provekit/r1cs-compiler/src/noir_to_r1cs.rs index 2bc0838c..177a3567 100644 --- a/provekit/r1cs-compiler/src/noir_to_r1cs.rs +++ b/provekit/r1cs-compiler/src/noir_to_r1cs.rs @@ -7,9 +7,7 @@ use { }, acir::{ circuit::{ - opcodes::{ - BlackBoxFuncCall, BlockType, ConstantOrWitnessEnum as ConstantOrACIRWitness, - }, + opcodes::{BlackBoxFuncCall, BlockType, FunctionInput}, Circuit, Opcode, }, native_types::{Expression, Witness as NoirWitness}, @@ -18,7 +16,7 @@ use { ark_std::One, provekit_common::{ utils::noir_to_native, - witness::{ConstantOrR1CSWitness, ConstantTerm, SumTerm, WitnessBuilder}, + witness::{ConstantOrR1CSWitness, ConstantTerm, SumTerm, WitnessBuilder, BINOP_BITS}, FieldElement, NoirElement, R1CS, }, std::{collections::BTreeMap, num::NonZeroU32, ops::Neg}, @@ -131,14 +129,12 @@ impl NoirToR1CSCompiler { // R1CS witness (and builder) if required. fn fetch_constant_or_r1cs_witness( &mut self, - constant_or_witness: ConstantOrACIRWitness, + constant_or_witness: &FunctionInput, ) -> 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); + FunctionInput::Constant(c) => ConstantOrR1CSWitness::Constant(noir_to_native(*c)), + FunctionInput::Witness(w) => { + let r1cs_witness = self.fetch_r1cs_witness_index(*w); ConstantOrR1CSWitness::Witness(r1cs_witness) } } @@ -276,15 +272,7 @@ impl NoirToR1CSCompiler { 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()); - + Opcode::MemoryOp { block_id, op } => { let block_id = block_id.0 as usize; assert!( memory_blocks.contains_key(&block_id), @@ -329,20 +317,16 @@ impl NoirToR1CSCompiler { } 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(); + BlackBoxFuncCall::RANGE { input, num_bits } => { let input_witness = match input { - ConstantOrACIRWitness::Constant(_) => { + FunctionInput::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) => { - self.fetch_r1cs_witness_index(witness) + FunctionInput::Witness(witness) => { + self.fetch_r1cs_witness_index(*witness) } }; // println!( @@ -351,7 +335,7 @@ impl NoirToR1CSCompiler { // ); // Add the entry into the range blocks. range_checks - .entry(num_bits) + .entry(*num_bits) .or_default() .push(input_witness); } @@ -360,17 +344,29 @@ impl NoirToR1CSCompiler { // 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 } => { + BlackBoxFuncCall::AND { + lhs, + rhs, + output, + num_bits, + } => { + assert_eq!(*num_bits as usize, BINOP_BITS); and_ops.push(( - self.fetch_constant_or_r1cs_witness(lhs.input()), - self.fetch_constant_or_r1cs_witness(rhs.input()), + self.fetch_constant_or_r1cs_witness(lhs), + self.fetch_constant_or_r1cs_witness(rhs), self.fetch_r1cs_witness_index(*output), )); } - BlackBoxFuncCall::XOR { lhs, rhs, output } => { + BlackBoxFuncCall::XOR { + lhs, + rhs, + output, + num_bits, + } => { + assert_eq!(*num_bits as usize, BINOP_BITS); xor_ops.push(( - self.fetch_constant_or_r1cs_witness(lhs.input()), - self.fetch_constant_or_r1cs_witness(rhs.input()), + self.fetch_constant_or_r1cs_witness(lhs), + self.fetch_constant_or_r1cs_witness(rhs), self.fetch_r1cs_witness_index(*output), )); } @@ -381,11 +377,11 @@ impl NoirToR1CSCompiler { } => { let input_witnesses: Vec = inputs .iter() - .map(|input| self.fetch_constant_or_r1cs_witness(input.input())) + .map(|input| self.fetch_constant_or_r1cs_witness(input)) .collect(); let hash_witnesses: Vec = hash_values .iter() - .map(|hv| self.fetch_constant_or_r1cs_witness(hv.input())) + .map(|hv| self.fetch_constant_or_r1cs_witness(hv)) .collect(); let output_witnesses: Vec = outputs .iter() diff --git a/tooling/cli/src/cmd/circuit_stats.rs b/tooling/cli/src/cmd/circuit_stats.rs index 4d012f74..ea06ea47 100644 --- a/tooling/cli/src/cmd/circuit_stats.rs +++ b/tooling/cli/src/cmd/circuit_stats.rs @@ -5,7 +5,7 @@ use { super::Command, acir::{ circuit::{ - opcodes::{BlackBoxFuncCall, ConstantOrWitnessEnum}, + opcodes::{BlackBoxFuncCall, FunctionInput}, Opcode, Program, }, native_types::Expression, @@ -175,6 +175,7 @@ fn main(arg: &Args) { lhs, rhs, output: _, + num_bits, } => { blackbox_func_call_variants .entry("AND") @@ -183,35 +184,23 @@ fn main(arg: &Args) { }); // --- Keep track of the various bit counts we are dealing with --- if let Entry::Occupied(mut x) = - and_opcode_bit_counts.entry((lhs.num_bits(), rhs.num_bits())) + and_opcode_bit_counts.entry((*num_bits, *num_bits)) { x.get_mut().add_assign(1); } else { - and_opcode_bit_counts.insert((lhs.num_bits(), rhs.num_bits()), 1); + and_opcode_bit_counts.insert((*num_bits, *num_bits), 1); } - match (lhs.input(), rhs.input()) { - ( - ConstantOrWitnessEnum::Constant(_), - ConstantOrWitnessEnum::Constant(_), - ) => { + match (lhs, rhs) { + (FunctionInput::Constant(_), FunctionInput::Constant(_)) => { homogeneous_constant_and_inputs_count += 1; } - ( - ConstantOrWitnessEnum::Constant(_), - ConstantOrWitnessEnum::Witness(_), - ) => { + (FunctionInput::Constant(_), FunctionInput::Witness(_)) => { heterogeneous_and_inputs_count += 1; } - ( - ConstantOrWitnessEnum::Witness(_), - ConstantOrWitnessEnum::Constant(_), - ) => { + (FunctionInput::Witness(_), FunctionInput::Constant(_)) => { heterogeneous_and_inputs_count += 1; } - ( - ConstantOrWitnessEnum::Witness(_), - ConstantOrWitnessEnum::Witness(_), - ) => { + (FunctionInput::Witness(_), FunctionInput::Witness(_)) => { homogeneous_witness_and_inputs_count += 1; } } @@ -220,6 +209,7 @@ fn main(arg: &Args) { lhs, rhs, output: _, + num_bits, } => { blackbox_func_call_variants .entry("XOR") @@ -228,60 +218,46 @@ fn main(arg: &Args) { }); // --- Keep track of the various bit counts we are dealing with --- if let Entry::Occupied(mut x) = - xor_opcode_bit_counts.entry((lhs.num_bits(), rhs.num_bits())) + xor_opcode_bit_counts.entry((*num_bits, *num_bits)) { x.get_mut().add_assign(1); } else { - xor_opcode_bit_counts.insert((lhs.num_bits(), rhs.num_bits()), 1); + xor_opcode_bit_counts.insert((*num_bits, *num_bits), 1); } - if let ConstantOrWitnessEnum::Constant(_) = lhs.input() { + if let FunctionInput::Constant(_) = lhs { xor_with_non_witness_value = true; } - if let ConstantOrWitnessEnum::Constant(_) = rhs.input() { + if let FunctionInput::Constant(_) = rhs { xor_with_non_witness_value = true; } - match (lhs.input(), rhs.input()) { - ( - ConstantOrWitnessEnum::Constant(_), - ConstantOrWitnessEnum::Constant(_), - ) => { + match (lhs, rhs) { + (FunctionInput::Constant(_), FunctionInput::Constant(_)) => { homogeneous_constant_xor_inputs_count += 1; } - ( - ConstantOrWitnessEnum::Constant(_), - ConstantOrWitnessEnum::Witness(_), - ) => { + (FunctionInput::Constant(_), FunctionInput::Witness(_)) => { heterogeneous_xor_inputs_count += 1; } - ( - ConstantOrWitnessEnum::Witness(_), - ConstantOrWitnessEnum::Constant(_), - ) => { + (FunctionInput::Witness(_), FunctionInput::Constant(_)) => { heterogeneous_xor_inputs_count += 1; } - ( - ConstantOrWitnessEnum::Witness(_), - ConstantOrWitnessEnum::Witness(_), - ) => { + (FunctionInput::Witness(_), FunctionInput::Witness(_)) => { homogeneous_witness_xor_inputs_count += 1; } } } - BlackBoxFuncCall::RANGE { input } => { + BlackBoxFuncCall::RANGE { input, num_bits } => { // --- We keep track of the total number of RANGE calls --- - dbg!(&input.input()); + dbg!(&input); 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()) - { + if let Entry::Occupied(mut x) = range_check_bit_counts.entry(*num_bits) { x.get_mut().add_assign(1); } else { - range_check_bit_counts.insert(input.num_bits(), 1); + range_check_bit_counts.insert(*num_bits, 1); } } @@ -311,6 +287,7 @@ fn main(arg: &Args) { signature: _, hashed_message: _, output: _, + predicate: _, } => { blackbox_func_call_variants .entry("EcdsaSecp256k1") @@ -324,6 +301,7 @@ fn main(arg: &Args) { signature: _, hashed_message: _, output: _, + predicate: _, } => { blackbox_func_call_variants .entry("EcdsaSecp256r1") @@ -335,6 +313,7 @@ fn main(arg: &Args) { points: _, scalars: _, outputs: _, + predicate: _, } => { blackbox_func_call_variants .entry("MultiScalarMul") @@ -346,6 +325,7 @@ fn main(arg: &Args) { input1: _, input2: _, outputs: _, + predicate: _, } => { blackbox_func_call_variants .entry("EmbeddedCurveAdd") @@ -369,6 +349,7 @@ fn main(arg: &Args) { public_inputs: _, key_hash: _, proof_type: _, + predicate: _, } => { blackbox_func_call_variants .entry("RecursiveAggregation") @@ -376,75 +357,9 @@ fn main(arg: &Args) { 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") @@ -465,11 +380,7 @@ fn main(arg: &Args) { } } } - Opcode::MemoryOp { - block_id, - op, - predicate: _, - } => { + Opcode::MemoryOp { block_id, op } => { // --- 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