Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions acvm-repo/acir_field/src/field_element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,9 @@
fn bits(&self) -> u32 {
// If we don't have a non-zero byte then the field element is zero,
// which we consider to require a single bit to represent.
// OTOH some operations produce range constraints with 0 bits.
Comment thread
aakoshh marked this conversation as resolved.
Outdated
if self.count == 0 {
return 1;
return 0;
}

let num_bits_for_head_byte = self.head_byte.ilog2();
Expand Down Expand Up @@ -406,8 +407,14 @@
use proptest::prelude::*;

#[test]
fn requires_one_bit_to_hold_zero() {
fn requires_zero_bit_to_hold_zero() {
let field = FieldElement::<ark_bn254::Fr>::zero();
assert_eq!(field.num_bits(), 0);
}

#[test]
fn requires_one_bit_to_hold_one() {
let field = FieldElement::<ark_bn254::Fr>::one();
assert_eq!(field.num_bits(), 1);
}

Expand Down Expand Up @@ -489,7 +496,7 @@
assert_eq!(from_le, field);

// Additional test with a larger number to ensure proper byte handling
let large_field = FieldElement::<ark_bn254::Fr>::from(0x0123_4567_89AB_CDEF_u64);

Check warning on line 499 in acvm-repo/acir_field/src/field_element.rs

View workflow job for this annotation

GitHub Actions / Code

Unknown word (CDEF)
let large_le = large_field.to_le_bytes();
let reconstructed = FieldElement::from_le_bytes_reduce(&large_le);
assert_eq!(reconstructed, large_field);
Expand Down
9 changes: 8 additions & 1 deletion acvm-repo/acvm/src/pwg/blackbox/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ mod tests {
use std::collections::BTreeMap;

use acir::{
FieldElement,
AcirField, FieldElement,
circuit::opcodes::FunctionInput,
native_types::{Witness, WitnessMap},
};
Expand All @@ -42,6 +42,13 @@ mod tests {
assert!(solve_range_opcode(&witness_map, &input, false).is_err());
}

#[test]
fn accepts_zero_for_zero_bits() {
let witness_map = WitnessMap::from(BTreeMap::from([(Witness(0), FieldElement::zero())]));
let input: FunctionInput<FieldElement> = FunctionInput::witness(Witness(0), 0);
assert!(solve_range_opcode(&witness_map, &input, false).is_ok());
}

#[test]
fn accepts_valid_inputs() {
let values: [u32; 4] = [0, 1, 8, 255];
Expand Down
9 changes: 5 additions & 4 deletions compiler/noirc_evaluator/src/acir/acir_context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
// `rhs` has the correct bit-size because either it is enforced by the overflow checks
// or `rhs` is zero when the overflow checks are disabled.
// Indeed, in that case, rhs is replaced with 'predicate * rhs'
self.bound_constraint_with_offset(remainder_var, rhs, predicate, max_rhs_bits, one)?;
self.bound_constraint_with_offset(remainder_var, rhs, one, max_rhs_bits, predicate)?;
Comment thread
aakoshh marked this conversation as resolved.
Outdated
Comment thread
aakoshh marked this conversation as resolved.
Outdated

// a * predicate == (b * q + r) * predicate
// => predicate * (a - b * q - r) == 0
Expand Down Expand Up @@ -930,19 +930,20 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
// quotient_var is the output of a brillig call
self.bound_constraint_with_offset(quotient_var, q0_var, zero, max_q_bits, one)?;

// when q == q0, b*q+r can overflow so we need to bound r to avoid the overflow.
// when q == q0, q*b+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 = F::modulus() - q0_big * rhs_big;
let max_r = F::from_be_bytes_reduce(&max_r_big.to_bytes_be());
let max_r_var = self.add_constant(max_r);

// Bound the remainder to be <p-q0*b, if the predicate is true.
// Bound the remainder to be <p-q0*b, if the predicate is true,
// that is, if q0 == q then assert(r < max_r), where is max_r = p-q0*b, and q0 = p/b, so that q*b+r<p
self.bound_constraint_with_offset(
remainder_var,
max_r_var,
predicate,
one,
Comment thread
aakoshh marked this conversation as resolved.
rhs_const.num_bits(),
predicate,
)?;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading