diff --git a/acvm-repo/brillig_vm/src/arithmetic.rs b/acvm-repo/brillig_vm/src/arithmetic.rs index 51ab8660452..263a733e3c4 100644 --- a/acvm-repo/brillig_vm/src/arithmetic.rs +++ b/acvm-repo/brillig_vm/src/arithmetic.rs @@ -25,18 +25,28 @@ pub(crate) fn evaluate_binary_bigint_op( a: BigUint, b: BigUint, bit_size: u32, -) -> BigUint { +) -> Result { let bit_modulo = &(BigUint::one() << bit_size); - match op { + let result = match op { // Perform addition, subtraction, and multiplication, applying a modulo operation to keep the result within the bit size. BinaryIntOp::Add => (a + b) % bit_modulo, BinaryIntOp::Sub => (bit_modulo + a - b) % bit_modulo, BinaryIntOp::Mul => (a * b) % bit_modulo, // Perform unsigned division using the modulo operation on a and b. - BinaryIntOp::UnsignedDiv => (a % bit_modulo) / (b % bit_modulo), + BinaryIntOp::UnsignedDiv => { + let b_mod = b % bit_modulo; + if b_mod.is_zero() { + return Err("Division by zero".to_owned()); + } + (a % bit_modulo) / b_mod + } // Perform signed division by first converting a and b to signed integers and then back to unsigned after the operation. BinaryIntOp::SignedDiv => { - let signed_div = to_big_signed(a, bit_size) / to_big_signed(b, bit_size); + let b_signed = to_big_signed(b, bit_size); + if b_signed.is_zero() { + return Err("Division by zero".to_owned()); + } + let signed_div = to_big_signed(a, bit_size) / b_signed; to_big_unsigned(signed_div, bit_size) } // Perform a == operation, returning 0 or 1 @@ -77,7 +87,9 @@ pub(crate) fn evaluate_binary_bigint_op( let b = b.to_u128().unwrap(); (a >> b) % bit_modulo } - } + }; + + Ok(result) } fn to_big_signed(a: BigUint, bit_size: u32) -> BigInt { @@ -111,7 +123,7 @@ mod tests { // Convert to big integers let lhs_big = BigUint::from(a); let rhs_big = BigUint::from(b); - let result_value = evaluate_binary_bigint_op(op, lhs_big, rhs_big, bit_size); + let result_value = evaluate_binary_bigint_op(op, lhs_big, rhs_big, bit_size).unwrap(); // Convert back to u128 result_value.to_u128().unwrap() } diff --git a/acvm-repo/brillig_vm/src/lib.rs b/acvm-repo/brillig_vm/src/lib.rs index 48f6bf5f1c4..c13fb8012e2 100644 --- a/acvm-repo/brillig_vm/src/lib.rs +++ b/acvm-repo/brillig_vm/src/lib.rs @@ -177,8 +177,12 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { self.increment_program_counter() } Opcode::BinaryIntOp { op, bit_size, lhs, rhs, destination: result } => { - self.process_binary_int_op(*op, *bit_size, *lhs, *rhs, *result); - self.increment_program_counter() + if let Err(error) = self.process_binary_int_op(*op, *bit_size, *lhs, *rhs, *result) + { + self.fail(error) + } else { + self.increment_program_counter() + } } Opcode::Jump { location: destination } => self.set_program_counter(*destination), Opcode::JumpIf { condition, location: destination } => { @@ -391,17 +395,18 @@ impl<'a, B: BlackBoxFunctionSolver> VM<'a, B> { lhs: RegisterIndex, rhs: RegisterIndex, result: RegisterIndex, - ) { + ) -> Result<(), String> { let lhs_value = self.registers.get(lhs); let rhs_value = self.registers.get(rhs); // Convert to big integers let lhs_big = BigUint::from_bytes_be(&lhs_value.to_field().to_be_bytes()); let rhs_big = BigUint::from_bytes_be(&rhs_value.to_field().to_be_bytes()); - let result_value = evaluate_binary_bigint_op(&op, lhs_big, rhs_big, bit_size); + let result_value = evaluate_binary_bigint_op(&op, lhs_big, rhs_big, bit_size)?; // Convert back to field element self.registers .set(result, FieldElement::from_be_bytes_reduce(&result_value.to_bytes_be()).into()); + Ok(()) } } diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs index 9c820220e07..742642d01d6 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/acir_variable.rs @@ -22,6 +22,7 @@ use acvm::{ use acvm::{BlackBoxFunctionSolver, BlackBoxResolutionError}; use fxhash::FxHashMap as HashMap; use iter_extended::{try_vecmap, vecmap}; +use num_bigint::BigUint; use std::{borrow::Cow, hash::Hash}; #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -529,6 +530,20 @@ impl AcirContext { Ok(self.add_data(AcirVarData::from(sum_expr))) } + /// Adds a new Variable to context whose value will + /// be constrained to be the expression `lhs + k * rhs` + fn add_mul_var( + &mut self, + lhs: AcirVar, + k: FieldElement, + rhs: AcirVar, + ) -> Result { + let k_var = self.add_constant(k); + + let intermediate = self.mul_var(k_var, rhs)?; + self.add_var(lhs, intermediate) + } + /// Adds a new variable that is constrained to be the logical NOT of `x`. pub(crate) fn not_var(&mut self, x: AcirVar, typ: AcirType) -> Result { let bit_size = typ.bit_size(); @@ -545,19 +560,159 @@ impl AcirContext { bit_size: u32, predicate: AcirVar, ) -> Result<(AcirVar, AcirVar), RuntimeError> { - let lhs_expr = self.var_to_expression(lhs)?; + // lhs = rhs * q + r + // + // If predicate is zero, `q_witness` and `r_witness` will be 0 + + // Check that we the rhs is not zero. + // Otherwise, when executing the brillig quotient we may attempt to divide by zero, causing a VM panic. + // + // When the predicate is 0, the equation always passes. + // When the predicate is 1, the rhs must not be 0. + let zero = self.add_constant(FieldElement::zero()); + let one = self.add_constant(FieldElement::one()); + let rhs_expr = self.var_to_expression(rhs)?; - let predicate_expr = self.var_to_expression(predicate)?; + let rhs_is_nonzero_const = rhs_expr.is_const() && !rhs_expr.is_zero(); + if !rhs_is_nonzero_const { + match self.var_to_expression(predicate)?.to_const() { + Some(predicate) if predicate.is_one() => { + // If the predicate is known to be active, we simply assert that an inverse must exist. + // This implies that `rhs != 0`. + let _inverse = self.inv_var(rhs, one)?; + } + + _ => { + // Otherwise we must handle both potential cases. + let rhs_is_zero = self.eq_var(rhs, zero)?; + let rhs_is_not_zero = self.mul_var(rhs_is_zero, predicate)?; + self.assert_eq_var(rhs_is_not_zero, zero, None)?; + } + } + } - let (quotient, remainder) = - self.acir_ir.euclidean_division(&lhs_expr, &rhs_expr, bit_size, &predicate_expr)?; + // maximum bit size for q and for [r and rhs] + let mut max_q_bits = bit_size; + let mut max_rhs_bits = bit_size; + // when rhs is constant, we can better estimate the maximum bit sizes + if let Some(rhs_const) = self.var_to_expression(rhs)?.to_const() { + max_rhs_bits = rhs_const.num_bits(); + if max_rhs_bits != 0 { + if max_rhs_bits > bit_size { + return Ok((zero, zero)); + } + max_q_bits = bit_size - max_rhs_bits + 1; + } + } - let quotient_var = self.add_data(AcirVarData::Witness(quotient)); - let remainder_var = self.add_data(AcirVarData::Witness(remainder)); + // Avoids overflow: 'q*b+r < 2^max_q_bits*2^max_rhs_bits' + let mut avoid_overflow = false; + if max_q_bits + max_rhs_bits >= FieldElement::max_num_bits() - 1 { + // q*b+r can overflow; we avoid this when b is constant + if self.var_to_expression(rhs)?.is_const() { + avoid_overflow = true; + } else { + // we do not support unbounded division + unreachable!("overflow in unbounded division"); + } + } + + let [q_value, r_value]: [AcirValue; 2] = self + .brillig( + predicate, + brillig_directive::directive_quotient(bit_size + 1), + vec![ + AcirValue::Var(lhs, AcirType::unsigned(bit_size)), + AcirValue::Var(rhs, AcirType::unsigned(bit_size)), + ], + vec![AcirType::unsigned(max_q_bits), AcirType::unsigned(max_rhs_bits)], + )? + .try_into() + .expect("quotient only returns two values"); + let quotient_var = q_value.into_var()?; + let remainder_var = r_value.into_var()?; + + // Constrain `q < 2^{max_q_bits}`. + self.range_constrain_var(quotient_var, &NumericType::Unsigned { bit_size: max_q_bits })?; + + // Constrain `r < 2^{max_rhs_bits}`. + // + // If `rhs` is a power of 2, then is just a looser version of the following bound constraint. + // In the case where `rhs` isn't a power of 2 then this range constraint is required + // as the bound constraint creates a new witness. + // This opcode will be optimized out if it is redundant so we always add it for safety. + self.range_constrain_var(remainder_var, &NumericType::Unsigned { bit_size: max_rhs_bits })?; + + // Constrain `r < rhs`. + self.acir_ir.bound_constraint_with_offset( + &self.var_to_expression(remainder_var)?, + &self.var_to_expression(rhs)?, + &self.var_to_expression(predicate)?, + max_rhs_bits, + )?; + + // a * predicate == (b * q + r) * predicate + // => predicate * (a - b * q - r) == 0 + // When the predicate is 0, the equation always passes. + // When the predicate is 1, the euclidean division needs to be + // true. + let rhs_constraint = self.mul_var(rhs, quotient_var)?; + let rhs_constraint = self.add_var(rhs_constraint, remainder_var)?; + let rhs_constraint = self.mul_var(rhs_constraint, predicate)?; + + let lhs_constraint = self.mul_var(lhs, predicate)?; + self.assert_eq_var(lhs_constraint, rhs_constraint, None)?; + + if let Some(rhs_const) = self.var_to_expression(rhs)?.to_const() { + if avoid_overflow { + // we compute q0 = p/rhs + let rhs_big = BigUint::from_bytes_be(&rhs_const.to_be_bytes()); + let q0_big = FieldElement::modulus() / &rhs_big; + let q0 = FieldElement::from_be_bytes_reduce(&q0_big.to_bytes_be()); + let q0_var = self.add_constant(q0); + // when q == q0, b*q+r can overflow so we need to bound r to avoid the overflow. + + let size_predicate = self.eq_var(q0_var, quotient_var)?; + let predicate = self.mul_var(size_predicate, predicate)?; + // Ensure that there is no overflow, under q == q0 predicate + let max_r_big = FieldElement::modulus() - q0_big * rhs_big; + let max_r = FieldElement::from_be_bytes_reduce(&max_r_big.to_bytes_be()); + let max_r_var = self.add_constant(max_r); + + let max_r_predicate = self.mul_var(predicate, max_r_var)?; + let r_predicate = self.mul_var(remainder_var, predicate)?; + // Bound the remainder to be Result { + let max_power_of_two = self.add_constant( + FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)), + ); + + let intermediate = self.sub_var(max_power_of_two, lhs)?; + let intermediate = self.mul_var(intermediate, leading)?; + + self.add_mul_var(lhs, FieldElement::from(2_i128), intermediate) + } + /// Returns the quotient and remainder such that lhs = rhs * quotient + remainder /// and |remainder| < |rhs| /// and remainder has the same sign than lhs @@ -568,14 +723,46 @@ impl AcirContext { rhs: AcirVar, bit_size: u32, ) -> Result<(AcirVar, AcirVar), RuntimeError> { - let l_witness = self.var_to_witness(lhs)?; - let r_witness = self.var_to_witness(rhs)?; + // We derive the signed division from the unsigned euclidean division. + // note that this is not euclidean division! + // If `x` is a signed integer, then `sign(x)x >= 0` + // so if `a` and `b` are signed integers, we can do the unsigned division: + // `sign(a)a = q1*sign(b)b + r1` + // => `a = sign(a)sign(b)q1*b + sign(a)r1` + // => `a = qb+r`, with `|r|<|b|` and `a` and `r` have the same sign. assert_ne!(bit_size, 0, "signed integer should have at least one bit"); - let (q, r) = - self.acir_ir.signed_division(&l_witness.into(), &r_witness.into(), bit_size)?; - Ok((self.add_data(q.into()), self.add_data(r.into()))) + // 2^{max_bit size-1} + let max_power_of_two = self.add_constant( + FieldElement::from(2_i128).pow(&FieldElement::from(bit_size as i128 - 1)), + ); + let one = self.add_constant(FieldElement::one()); + + // Get the sign bit of rhs by computing rhs / max_power_of_two + let (rhs_leading, _) = self.euclidean_division_var(rhs, max_power_of_two, bit_size, one)?; + + // Get the sign bit of lhs by computing lhs / max_power_of_two + let (lhs_leading, _) = self.euclidean_division_var(lhs, max_power_of_two, bit_size, one)?; + + // Signed to unsigned: + let unsigned_lhs = self.two_complement(lhs, lhs_leading, bit_size)?; + let unsigned_rhs = self.two_complement(rhs, rhs_leading, bit_size)?; + + // Performs the division using the unsigned values of lhs and rhs + let (q1, r1) = + self.euclidean_division_var(unsigned_lhs, unsigned_rhs, bit_size - 1, one)?; + + // Unsigned to signed: derive q and r from q1,r1 and the signs of lhs and rhs + // Quotient sign is lhs sign * rhs sign, whose resulting sign bit is the XOR of the sign bits + let sign_sum = self.add_var(lhs_leading, rhs_leading)?; + let sign_prod = self.mul_var(lhs_leading, rhs_leading)?; + let q_sign = self.add_mul_var(sign_sum, -FieldElement::from(2_i128), sign_prod)?; + + let quotient = self.two_complement(q1, q_sign, bit_size)?; + let remainder = self.two_complement(r1, lhs_leading, bit_size)?; + + Ok((quotient, remainder)) } /// Returns a variable which is constrained to be `lhs mod rhs` @@ -626,19 +813,14 @@ impl AcirContext { max_bit_size: u32, ) -> Result { // 2^{rhs} - let divisor = FieldElement::from(2_i128).pow(&FieldElement::from(rhs as i128)); + let divisor = + self.add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(rhs as i128))); + let one = self.add_constant(FieldElement::one()); - let lhs_data = &self.vars[&lhs]; - let lhs_expr = lhs_data.to_expression(); // Computes lhs = 2^{rhs} * q + r - let (_, remainder) = self.acir_ir.euclidean_division( - &lhs_expr, - &Expression::from_field(divisor), - max_bit_size, - &Expression::one(), - )?; + let (_, remainder) = self.euclidean_division_var(lhs, divisor, max_bit_size, one)?; - Ok(self.add_data(AcirVarData::from(remainder))) + Ok(remainder) } /// Returns an `AcirVar` which will be `1` if lhs >= rhs @@ -647,17 +829,69 @@ impl AcirContext { &mut self, lhs: AcirVar, rhs: AcirVar, - bit_size: u32, + max_bits: u32, predicate: AcirVar, ) -> Result { - let lhs_expr = self.var_to_expression(lhs)?; - let rhs_expr = self.var_to_expression(rhs)?; - let predicate_expr = self.var_to_expression(predicate)?; - - let is_greater_than_eq = - self.acir_ir.more_than_eq_comparison(&lhs_expr, &rhs_expr, bit_size, predicate_expr)?; + // Returns a `Witness` that is constrained to be: + // - `1` if lhs >= rhs + // - `0` otherwise + // + // We essentially computes the sign bit of `b-a` + // For this we sign-extend `b-a` with `c = 2^{max_bits} - (b - a)`, since both `a` and `b` are less than `2^{max_bits}` + // Then we get the bit sign of `c`, the 2-complement representation of `(b-a)`, which is a `max_bits+1` integer, + // by doing the euclidean division `c / 2^{max_bits}` + // + // To see why it really works; + // We first note that `c` is an integer of `(max_bits+1)` bits. Therefore, + // if `b-a>0`, then `c < 2^{max_bits}`, so the division by `2^{max_bits}` will give `0` + // If `b-a<=0`, then `c >= 2^{max_bits}`, so the division by `2^{max_bits}` will give `1`. + // + // In other words, `1` means `a >= b` and `0` means `b > a`. + // The important thing here is that `c` does not overflow nor underflow the field; + // - By construction we have `c >= 0`, so there is no underflow + // - We assert at the beginning that `2^{max_bits+1}` does not overflow the field, so neither c. - Ok(self.add_data(AcirVarData::Witness(is_greater_than_eq))) + // Ensure that 2^{max_bits + 1} is less than the field size + // + // TODO: perhaps this should be a user error, instead of an assert + assert!(max_bits + 1 < FieldElement::max_num_bits()); + let two_max_bits = self + .add_constant(FieldElement::from(2_i128).pow(&FieldElement::from(max_bits as i128))); + let diff = self.sub_var(lhs, rhs)?; + let comparison_evaluation = self.add_var(diff, two_max_bits)?; + + // Euclidean division by 2^{max_bits} : 2^{max_bits} + a - b = q * 2^{max_bits} + r + // + // 2^{max_bits} is of max_bits+1 bit size + // If a>b, then a-b is less than 2^{max_bits} - 1, so 2^{max_bits} + a - b is less than 2^{max_bits} + 2^{max_bits} - 1 = 2^{max_bits+1} - 1 + // If a <= b, then 2^{max_bits} + a - b is less than 2^{max_bits} <= 2^{max_bits+1} - 1 + // This means that both operands of the division have at most max_bits+1 bit size. + // + // case: a == b + // + // let k = 0; + // - 2^{max_bits} == q * 2^{max_bits} + r + // - This is only the case when q == 1 and r == 0 (assuming r is bounded to be less than 2^{max_bits}) + // + // case: a > b + // + // let k = a - b; + // - k + 2^{max_bits} == q * 2^{max_bits} + r + // - This is the case when q == 1 and r = k + // + // case: a < b + // + // let k = b - a + // - 2^{max_bits} - k == q * 2^{max_bits} + r + // - This is only the case when q == 0 and r == 2^{max_bits} - k + // + let (q, _) = self.euclidean_division_var( + comparison_evaluation, + two_max_bits, + max_bits + 1, + predicate, + )?; + Ok(q) } /// Returns an `AcirVar` which will be `1` if lhs < rhs diff --git a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs index 3ce1c8893fa..061ecb2fcda 100644 --- a/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs +++ b/compiler/noirc_evaluator/src/ssa/acir_gen/acir_ir/generated_acir.rs @@ -290,24 +290,6 @@ impl GeneratedAcir { Ok(limb_witnesses) } - // Returns the 2-complement of lhs, using the provided sign bit in 'leading' - // if leading is zero, it returns lhs - // if leading is one, it returns 2^bit_size-lhs - fn two_complement( - &mut self, - lhs: &Expression, - leading: Witness, - max_bit_size: u32, - ) -> Expression { - let max_power_of_two = - FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)); - - let intermediate = - self.mul_with_witness(&(&Expression::from(max_power_of_two) - lhs), &leading.into()); - - lhs.add_mul(FieldElement::from(2_i128), &intermediate) - } - /// Returns an expression which represents `lhs * rhs` /// /// If one has multiplicative term and the other is of degree one or more, @@ -357,220 +339,6 @@ impl GeneratedAcir { (&*lhs_reduced * &*rhs_reduced).expect("Both expressions are reduced to be degree <= 1") } - /// Signed division lhs / rhs - /// We derive the signed division from the unsigned euclidean division. - /// note that this is not euclidean division! - // if x is a signed integer, then sign(x)x >= 0 - // so if a and b are signed integers, we can do the unsigned division: - // sign(a)a = q1*sign(b)b + r1 - // => a = sign(a)sign(b)q1*b + sign(a)r1 - // => a = qb+r, with |r|<|b| and a and r have the same sign. - pub(crate) fn signed_division( - &mut self, - lhs: &Expression, - rhs: &Expression, - max_bit_size: u32, - ) -> Result<(Expression, Expression), RuntimeError> { - // 2^{max_bit size-1} - let max_power_of_two = - FieldElement::from(2_i128).pow(&FieldElement::from(max_bit_size as i128 - 1)); - - // Get the sign bit of rhs by computing rhs / max_power_of_two - let (rhs_leading_witness, _) = self.euclidean_division( - rhs, - &max_power_of_two.into(), - max_bit_size, - &Expression::one(), - )?; - - // Get the sign bit of lhs by computing lhs / max_power_of_two - let (lhs_leading_witness, _) = self.euclidean_division( - lhs, - &max_power_of_two.into(), - max_bit_size, - &Expression::one(), - )?; - - // Signed to unsigned: - let unsigned_lhs = self.two_complement(lhs, lhs_leading_witness, max_bit_size); - let unsigned_rhs = self.two_complement(rhs, rhs_leading_witness, max_bit_size); - let unsigned_l_witness = self.get_or_create_witness(&unsigned_lhs); - let unsigned_r_witness = self.get_or_create_witness(&unsigned_rhs); - - // Performs the division using the unsigned values of lhs and rhs - let (q1, r1) = self.euclidean_division( - &unsigned_l_witness.into(), - &unsigned_r_witness.into(), - max_bit_size - 1, - &Expression::one(), - )?; - - // Unsigned to signed: derive q and r from q1,r1 and the signs of lhs and rhs - // Quotient sign is lhs sign * rhs sign, whose resulting sign bit is the XOR of the sign bits - let sign_sum = - &Expression::from(lhs_leading_witness) + &Expression::from(rhs_leading_witness); - let sign_prod = (&Expression::from(lhs_leading_witness) - * &Expression::from(rhs_leading_witness)) - .expect("Product of two witnesses so result is degree 2"); - let q_sign = sign_sum.add_mul(-FieldElement::from(2_i128), &sign_prod); - - let q_sign_witness = self.get_or_create_witness(&q_sign); - let quotient = self.two_complement(&q1.into(), q_sign_witness, max_bit_size); - let remainder = self.two_complement(&r1.into(), lhs_leading_witness, max_bit_size); - Ok((quotient, remainder)) - } - - /// Computes lhs/rhs by using euclidean division. - /// - /// Returns `q` for quotient and `r` for remainder such - /// that lhs = rhs * q + r - pub(crate) fn euclidean_division( - &mut self, - lhs: &Expression, - rhs: &Expression, - max_bit_size: u32, - predicate: &Expression, - ) -> Result<(Witness, Witness), RuntimeError> { - // lhs = rhs * q + r - // - // If predicate is zero, `q_witness` and `r_witness` will be 0 - - // Check that we the rhs is not zero. - // Otherwise, when executing the brillig quotient we may attempt to divide by zero, causing a VM panic. - // - // When the predicate is 0, the equation always passes. - // When the predicate is 1, the rhs must not be 0. - let rhs_is_nonzero_const = rhs.is_const() && !rhs.is_zero(); - if !rhs_is_nonzero_const { - match predicate.to_const() { - Some(predicate) if predicate.is_zero() => { - // If predicate is known to be inactive, we don't need to lay down constraints. - } - - Some(predicate) if predicate.is_one() => { - // If the predicate is known to be active, we simply assert that an inverse must exist. - // This implies that `rhs != 0`. - let unsafe_inverse = self.brillig_inverse(rhs.clone()); - let rhs_has_inverse = - self.mul_with_witness(rhs, &unsafe_inverse.into()) - FieldElement::one(); - self.assert_is_zero(rhs_has_inverse); - } - - _ => { - // Otherwise we must handle both potential cases. - let rhs_is_zero = self.is_zero(rhs); - let rhs_is_not_zero = self.mul_with_witness(&rhs_is_zero.into(), predicate); - self.assert_is_zero(rhs_is_not_zero); - } - } - } - - // maximum bit size for q and for [r and rhs] - let mut max_q_bits = max_bit_size; - let mut max_rhs_bits = max_bit_size; - // when rhs is constant, we can better estimate the maximum bit sizes - if let Some(rhs_const) = rhs.to_const() { - max_rhs_bits = rhs_const.num_bits(); - if max_rhs_bits != 0 { - if max_rhs_bits > max_bit_size { - let zero = self.get_or_create_witness(&Expression::zero()); - return Ok((zero, zero)); - } - max_q_bits = max_bit_size - max_rhs_bits + 1; - } - } - - // Avoids overflow: 'q*b+r < 2^max_q_bits*2^max_rhs_bits' - let mut avoid_overflow = false; - if max_q_bits + max_rhs_bits >= FieldElement::max_num_bits() - 1 { - // q*b+r can overflow; we avoid this when b is constant - if rhs.is_const() { - avoid_overflow = true; - } else { - // we do not support unbounded division - unreachable!("overflow in unbounded division"); - } - } - - let (q_witness, r_witness) = - self.brillig_quotient(lhs.clone(), rhs.clone(), predicate.clone(), max_bit_size + 1); - - // Constrain `q < 2^{max_q_bits}`. - self.range_constraint(q_witness, max_q_bits)?; - - // Constrain `r < 2^{max_rhs_bits}`. - // - // If `rhs` is a power of 2, then is just a looser version of the following bound constraint. - // In the case where `rhs` isn't a power of 2 then this range constraint is required - // as the bound constraint creates a new witness. - // This opcode will be optimized out if it is redundant so we always add it for safety. - self.range_constraint(r_witness, max_rhs_bits)?; - - // Constrain `r < rhs`. - self.bound_constraint_with_offset(&r_witness.into(), rhs, predicate, max_rhs_bits)?; - - // a * predicate == (b * q + r) * predicate - // => predicate * (a - b * q - r) == 0 - // When the predicate is 0, the equation always passes. - // When the predicate is 1, the euclidean division needs to be - // true. - let rhs_constraint = &self.mul_with_witness(rhs, &q_witness.into()) + r_witness; - let div_euclidean = &self.mul_with_witness(lhs, predicate) - - &self.mul_with_witness(&rhs_constraint, predicate); - - if let Some(rhs_const) = rhs.to_const() { - if avoid_overflow { - // we compute q0 = p/rhs - let rhs_big = BigUint::from_bytes_be(&rhs_const.to_be_bytes()); - let q0_big = FieldElement::modulus() / &rhs_big; - let q0 = FieldElement::from_be_bytes_reduce(&q0_big.to_bytes_be()); - // when q == q0, b*q+r can overflow so we need to bound r to avoid the overflow. - let size_predicate = - self.is_equal(&Expression::from_field(q0), &Expression::from(q_witness)); - let predicate = self.mul_with_witness(&size_predicate.into(), predicate); - // Ensure that there is no overflow, under q == q0 predicate - let max_r_big = FieldElement::modulus() - q0_big * rhs_big; - let max_r = FieldElement::from_be_bytes_reduce(&max_r_big.to_bytes_be()); - let max_r_predicate = - self.mul_with_witness(&predicate, &Expression::from_field(max_r)); - let r_predicate = self.mul_with_witness(&Expression::from(r_witness), &predicate); - // Bound the remainder to be (Witness, Witness) { - // Create the witness for the result - let q_witness = self.next_witness_index(); - let r_witness = self.next_witness_index(); - - let quotient_code = brillig_directive::directive_quotient(max_bit_size); - let inputs = vec![BrilligInputs::Single(lhs), BrilligInputs::Single(rhs)]; - let outputs = vec![BrilligOutputs::Simple(q_witness), BrilligOutputs::Simple(r_witness)]; - self.brillig(Some(predicate), quotient_code, inputs, outputs); - - (q_witness, r_witness) - } - /// Generate constraints that are satisfied iff /// lhs < rhs , when offset is 1, or /// lhs <= rhs, when offset is 0 @@ -582,7 +350,7 @@ impl GeneratedAcir { /// n.b: we do NOT check here that lhs and rhs are indeed 'bits' size /// lhs < rhs <=> a+1<=b /// TODO: Consolidate this with bounds_check function. - fn bound_constraint_with_offset( + pub(super) fn bound_constraint_with_offset( &mut self, lhs: &Expression, rhs: &Expression, @@ -616,7 +384,7 @@ impl GeneratedAcir { // we now have lhs+offset <= rhs <=> lhs_offset <= rhs_offset let bit_size = bit_size_u128(rhs_offset); - // r = 2^bit_size - rhs_offset -1, is of bit size 'bit_size' by construtction + // r = 2^bit_size - rhs_offset -1, is of bit size 'bit_size' by construction let r = (1_u128 << bit_size) - rhs_offset - 1; // however, since it is a constant, we can compute it's actual bit size let r_bit_size = bit_size_u128(r); @@ -786,75 +554,6 @@ impl GeneratedAcir { Ok(()) } - /// Returns a `Witness` that is constrained to be: - /// - `1` if lhs >= rhs - /// - `0` otherwise - /// - /// We essentially computes the sign bit of `b-a` - /// For this we sign-extend `b-a` with `c = 2^{max_bits} - (b - a)`, since both `a` and `b` are less than `2^{max_bits}` - /// Then we get the bit sign of `c`, the 2-complement representation of `(b-a)`, which is a `max_bits+1` integer, - /// by doing the euclidean division `c / 2^{max_bits}` - /// - /// To see why it really works; - /// We first note that `c` is an integer of `(max_bits+1)` bits. Therefore, - /// if `b-a>0`, then `c < 2^{max_bits}`, so the division by `2^{max_bits}` will give `0` - /// If `b-a<=0`, then `c >= 2^{max_bits}`, so the division by `2^{max_bits}` will give `1`. - /// - /// In other words, `1` means `a >= b` and `0` means `b > a`. - /// The important thing here is that `c` does not overflow nor underflow the field; - /// - By construction we have `c >= 0`, so there is no underflow - /// - We assert at the beginning that `2^{max_bits+1}` does not overflow the field, so neither c. - pub(crate) fn more_than_eq_comparison( - &mut self, - a: &Expression, - b: &Expression, - max_bits: u32, - predicate: Expression, - ) -> Result { - // Ensure that 2^{max_bits + 1} is less than the field size - // - // TODO: perhaps this should be a user error, instead of an assert - assert!(max_bits + 1 < FieldElement::max_num_bits()); - - // Compute : 2^{max_bits} + a - b - let two = FieldElement::from(2_i128); - let two_max_bits: FieldElement = two.pow(&FieldElement::from(max_bits as i128)); - let comparison_evaluation = (a - b) + two_max_bits; - - // euclidean division by 2^{max_bits} : 2^{max_bits} + a - b = q * 2^{max_bits} + r - // - // 2^{max_bits} is of max_bits+1 bit size - // If a>b, then a-b is less than 2^{max_bits} - 1, so 2^{max_bits} + a - b is less than 2^{max_bits} + 2^{max_bits} - 1 = 2^{max_bits+1} - 1 - // If a <= b, then 2^{max_bits} + a - b is less than 2^{max_bits} <= 2^{max_bits+1} - 1 - // This means that both operands of the division have at most max_bits+1 bit size. - // - // case: a == b - // - // let k = 0; - // - 2^{max_bits} == q * 2^{max_bits} + r - // - This is only the case when q == 1 and r == 0 (assuming r is bounded to be less than 2^{max_bits}) - // - // case: a > b - // - // let k = a - b; - // - k + 2^{max_bits} == q * 2^{max_bits} + r - // - This is the case when q == 1 and r = k - // - // case: a < b - // - // let k = b - a - // - 2^{max_bits} - k == q * 2^{max_bits} + r - // - This is only the case when q == 0 and r == 2^{max_bits} - k - // - let (q, _) = self.euclidean_division( - &comparison_evaluation, - &Expression::from(two_max_bits), - max_bits + 1, - &predicate, - )?; - Ok(q) - } - pub(crate) fn brillig( &mut self, predicate: Option, diff --git a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz index a6681ca770d..633bec13563 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz index ce60a15c551..68e9df80789 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/4_sub/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz index 1cba9585108..ea864f27f0f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/5_over/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz index 122614793e2..b0a38188cab 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/5_over/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz index 84054f59e92..516511ef434 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz index e1ab57f56a1..622a02c80c7 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/6_array/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz index 03407160382..4373423c245 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz index 250f96eab04..53e88658693 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/7_function/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz index 535be51928c..d49834456e9 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/arithmetic_binary_operations/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz index 430c6f5ffff..668b0204fcc 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz index 41a4ec0817e..073cbb51f10 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/array_dynamic/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz index bb100a3693a..5fb7041cdf1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_and/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz index 748bd4c077e..6c245fe57f7 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz index 5de81c483c2..13d2ec1b7b5 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_comptime/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz index 345d4e4cbf9..d3d5649bf06 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz index 105d4dc8781..28357d49cd1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/bit_shifts_runtime/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz index bf2c5179613..68b6c26c6de 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_assert/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz index ae815259717..1a64fd03980 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_keccak/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz index 757fa46041c..68aea535c58 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/brillig_not/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz index 1968cb5fe65..1367919f720 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz index bd0870eefc9..1e245899c18 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/conditional_1/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz index 10fa4e78649..3837082158c 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz index fcce3069d87..12a412826ba 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/eddsa/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz index 9924cf28390..a045447a2f9 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz index 3998fbc8d59..95dc2f89d32 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/higher_order_functions/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz index 6b57ed0fb85..81f409b14d1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/keccak256/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz index 411e4a497a6..36f55ebb7bc 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz index 3343df925a5..cbb3698dba8 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/merkle_insert/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz index 035b98c94db..3a9e0cfd0a7 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz index d5dc73c9bb4..e767768aeaa 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_array_dynamic/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz index a23ec7a04bd..b65653788bf 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz index 8d168b8c19c..d7209d7ffe2 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/nested_slice_dynamic/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz index fb14568cb37..86f6ebf3535 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz index 10c1c42caa0..76afd0975f6 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz index 8a9e4ed2b65..6f4ffaa488f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression_2854/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz index 6e5da316629..38a3da9e732 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz index e8dc551cf13..36c8609c87d 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/regression_mem_op_predicate/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz index 39eb9cb6076..2203f07b639 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz index a3dbc10b567..dc42c0ef0d9 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/schnorr/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz index 8537218ec5c..a2de8064bb5 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/sha256/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz index 1d12077353e..9ca108205cc 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/sha2_blocks/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz index b13e4554bd3..1c03baf0c8d 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/sha2_byte/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz index 8cde5b952f5..e99f259a403 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz index 5a1d190cdf0..bd9d7f2d4ac 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_arithmetic/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz index 2c8bc5cbdac..5741f04879f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz index 598c8658469..c56799e636a 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/signed_division/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz index 04d94da9653..9df85a4d1e5 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_comparison/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz index 8398c03b199..ea49c5a261e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz index 6ecc30eb054..9c0cbe335cc 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_radix/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz index 6134617adb5..28dd13911d0 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz index 55440fb8706..bcd5089b740 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/simple_shield/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz index 9fd24b3639a..0c89ba05956 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz index 0075dd044dc..726a195a03e 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/slice_dynamic_index/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz index feff0471f49..0e3903d5f63 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/slices/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz index d9d8d036339..a0c6a822227 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/slices/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz index 482588122ba..41db5a81be1 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz index 9ffa155a84f..60eea29c8b7 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_be_bytes/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz index b47fdc04a46..b768d5f09f7 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz index 3b931590419..5471a05bedb 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_consistent/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz index 86e3b2aa663..88759966a94 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz index b25db55391c..4be8a5a4019 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_bytes_integration/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz index fdf2c110585..e08e3fc7f9f 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz index b3948caad12..7f4558eaa48 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/to_le_bytes/target/witness.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz index b3f4a10b8f1..015bd555c7a 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/tuple_inputs/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz b/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz index f220605bc2c..a712bd9abf0 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz and b/tooling/nargo_cli/tests/acir_artifacts/tuples/target/acir.gz differ diff --git a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz b/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz index e48187b08c1..582f7d246ca 100644 Binary files a/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz and b/tooling/nargo_cli/tests/acir_artifacts/tuples/target/witness.gz differ