Skip to content

Commit

Permalink
Merge 20a5713 into ee0754b
Browse files Browse the repository at this point in the history
  • Loading branch information
jfecher authored Dec 19, 2024
2 parents ee0754b + 20a5713 commit aedd79c
Show file tree
Hide file tree
Showing 76 changed files with 2,678 additions and 2,711 deletions.
4 changes: 3 additions & 1 deletion acvm-repo/acir/src/circuit/black_box_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use serde::{Deserialize, Serialize};
use strum_macros::EnumIter;

#[allow(clippy::upper_case_acronyms)]
#[derive(Clone, Debug, Hash, Copy, PartialEq, Eq, Serialize, Deserialize, EnumIter)]
#[derive(
Clone, Debug, Hash, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, EnumIter,
)]
pub enum BlackBoxFunc {
/// Ciphers (encrypts) the provided plaintext using AES128 in CBC mode,
/// padding the input using PKCS#7.
Expand Down
22 changes: 14 additions & 8 deletions acvm-repo/brillig/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ pub enum IntegerBitSize {
U128,
}

impl From<IntegerBitSize> for u32 {
fn from(bit_size: IntegerBitSize) -> u32 {
impl From<IntegerBitSize> for u8 {
fn from(bit_size: IntegerBitSize) -> u8 {
match bit_size {
IntegerBitSize::U1 => 1,
IntegerBitSize::U8 => 8,
Expand All @@ -123,10 +123,16 @@ impl From<IntegerBitSize> for u32 {
}
}

impl TryFrom<u32> for IntegerBitSize {
impl From<IntegerBitSize> for u32 {
fn from(bit_size: IntegerBitSize) -> u32 {
u8::from(bit_size) as u32
}
}

impl TryFrom<u8> for IntegerBitSize {
type Error = &'static str;

fn try_from(value: u32) -> Result<Self, Self::Error> {
fn try_from(value: u8) -> Result<Self, Self::Error> {
match value {
1 => Ok(IntegerBitSize::U1),
8 => Ok(IntegerBitSize::U8),
Expand Down Expand Up @@ -159,15 +165,15 @@ pub enum BitSize {
}

impl BitSize {
pub fn to_u32<F: AcirField>(self) -> u32 {
pub fn to_u8<F: AcirField>(self) -> u8 {
match self {
BitSize::Field => F::max_num_bits(),
BitSize::Field => F::max_num_bits().try_into().unwrap(),
BitSize::Integer(bit_size) => bit_size.into(),
}
}

pub fn try_from_u32<F: AcirField>(value: u32) -> Result<Self, &'static str> {
if value == F::max_num_bits() {
pub fn try_from_u8<F: AcirField>(value: u8) -> Result<Self, &'static str> {
if value as u32 == F::max_num_bits() {
Ok(BitSize::Field)
} else {
Ok(BitSize::Integer(IntegerBitSize::try_from(value)?))
Expand Down
2 changes: 1 addition & 1 deletion compiler/noirc_driver/src/abi_gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ pub(super) fn abi_type_from_hir_type(context: &Context, typ: &Type) -> AbiType {
Signedness::Signed => Sign::Signed,
};

AbiType::Integer { sign, width: (*bit_width).into() }
AbiType::Integer { sign, width: bit_width.bit_size() as u32 }
}
Type::TypeVariable(binding) => {
if binding.is_integer() || binding.is_integer_or_field() {
Expand Down
51 changes: 25 additions & 26 deletions compiler/noirc_evaluator/src/acir/acir_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ impl AcirType {
}

/// Returns the bit size of the underlying type
pub(crate) fn bit_size<F: AcirField>(&self) -> u32 {
pub(crate) fn bit_size<F: AcirField>(&self) -> u8 {
match self {
AcirType::NumericType(numeric_type) => match numeric_type {
NumericType::Signed { bit_size } => *bit_size,
NumericType::Unsigned { bit_size } => *bit_size,
NumericType::NativeField => F::max_num_bits(),
NumericType::NativeField => F::max_num_bits() as u8,
},
AcirType::Array(_, _) => unreachable!("cannot fetch bit size of array type"),
}
Expand All @@ -68,7 +68,7 @@ impl AcirType {
}

/// Returns an unsigned type of the specified bit size
pub(crate) fn unsigned(bit_size: u32) -> Self {
pub(crate) fn unsigned(bit_size: u8) -> Self {
AcirType::NumericType(NumericType::Unsigned { bit_size })
}

Expand Down Expand Up @@ -112,9 +112,7 @@ impl From<NumericType> for AcirType {
pub(crate) struct AcirContext<F: AcirField, B: BlackBoxFunctionSolver<F>> {
blackbox_solver: B,

/// Two-way map that links `AcirVar` to `AcirVarData`.
///
/// The vars object is an instance of the `TwoWayMap`, which provides a bidirectional mapping between `AcirVar` and `AcirVarData`.
/// Map that links `AcirVar` to `AcirVarData`.
vars: HashMap<AcirVar, AcirVarData<F>>,

constant_witnesses: HashMap<F, Witness>,
Expand Down Expand Up @@ -772,7 +770,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
bit_size: u32,
bit_size: u8,
predicate: AcirVar,
) -> Result<(AcirVar, AcirVar), RuntimeError> {
let zero = self.add_constant(F::zero());
Expand Down Expand Up @@ -831,7 +829,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
let mut max_rhs_bits = bit_size;
// when rhs is constant, we can better estimate the maximum bit sizes
if let Some(rhs_const) = rhs_expr.to_const() {
max_rhs_bits = rhs_const.num_bits();
max_rhs_bits = rhs_const.num_bits().try_into().unwrap();
if max_rhs_bits != 0 {
if max_rhs_bits > bit_size {
return Ok((zero, zero));
Expand Down Expand Up @@ -895,7 +893,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {

// 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 >= F::max_num_bits() - 1 {
if ((max_q_bits + max_rhs_bits) as u32) >= F::max_num_bits() - 1 {
// q*b+r can overflow; we avoid this when b is constant
if rhs_expr.is_const() {
avoid_overflow = true;
Expand Down Expand Up @@ -928,7 +926,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
r_predicate,
max_r_predicate,
predicate,
rhs_const.num_bits(),
rhs_const.num_bits().try_into().unwrap(),
)?;
}
}
Expand All @@ -952,7 +950,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
lhs: AcirVar,
rhs: AcirVar,
offset: AcirVar,
bits: u32,
bits: u8,
) -> Result<(), RuntimeError> {
#[allow(unused_qualifications)]
const fn num_bits<T>() -> usize {
Expand All @@ -964,7 +962,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
}

assert!(
bits < F::max_num_bits(),
(bits as u32) < F::max_num_bits(),
"range check with bit size of the prime field is not implemented yet"
);

Expand All @@ -982,13 +980,13 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
};
// we now have lhs+offset <= rhs <=> lhs_offset <= rhs_offset

let bit_size = bit_size_u128(rhs_offset);
let bit_size = bit_size_u128(rhs_offset) as u8;
// 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);
// witness = lhs_offset + r
assert!(bits + r_bit_size < F::max_num_bits()); //we need to ensure lhs_offset + r does not overflow
assert!(bits as u32 + r_bit_size < F::max_num_bits()); //we need to ensure lhs_offset + r does not overflow

let r_var = self.add_constant(r);
let aor = self.add_var(lhs_offset, r_var)?;
Expand All @@ -1010,7 +1008,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
&mut self,
lhs: AcirVar,
leading: AcirVar,
max_bit_size: u32,
max_bit_size: u8,
) -> Result<AcirVar, RuntimeError> {
let max_power_of_two =
self.add_constant(F::from(2_u128).pow(&F::from(max_bit_size as u128 - 1)));
Expand All @@ -1029,7 +1027,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
bit_size: u32,
bit_size: u8,
) -> Result<(AcirVar, AcirVar), RuntimeError> {
// We derive the signed division from the unsigned euclidean division.
// note that this is not euclidean division!
Expand Down Expand Up @@ -1086,7 +1084,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
lhs: AcirVar,
rhs: AcirVar,
typ: AcirType,
bit_size: u32,
bit_size: u8,
predicate: AcirVar,
) -> Result<AcirVar, RuntimeError> {
let numeric_type = match typ {
Expand Down Expand Up @@ -1115,7 +1113,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
// If `variable` is constant then we don't need to add a constraint.
// We _do_ add a constraint if `variable` would fail the range check however so that we throw an error.
if let Some(constant) = self.var_to_expression(variable)?.to_const() {
if constant.num_bits() <= *bit_size {
if constant.num_bits() <= *bit_size as u32 {
return Ok(variable);
}
}
Expand Down Expand Up @@ -1143,8 +1141,8 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
pub(crate) fn truncate_var(
&mut self,
lhs: AcirVar,
rhs: u32,
max_bit_size: u32,
rhs: u8,
max_bit_size: u8,
) -> Result<AcirVar, RuntimeError> {
// 2^{rhs}
let divisor = self.add_constant(F::from(2_u128).pow(&F::from(rhs as u128)));
Expand All @@ -1166,7 +1164,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
bit_count: u32,
bit_count: u8,
) -> Result<AcirVar, RuntimeError> {
let pow_last = self.add_constant(F::from(1_u128 << (bit_count - 1)));
let pow = self.add_constant(F::from(1_u128 << (bit_count)));
Expand Down Expand Up @@ -1214,7 +1212,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
max_bits: u32,
max_bits: u8,
) -> Result<AcirVar, RuntimeError> {
// Returns a `Witness` that is constrained to be:
// - `1` if lhs >= rhs
Expand All @@ -1238,7 +1236,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
// 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 < F::max_num_bits());
assert!(max_bits as u32 + 1 < F::max_num_bits());

let two_max_bits = self.add_constant(F::from(2_u128).pow(&F::from(max_bits as u128)));
let diff = self.sub_var(lhs, rhs)?;
Expand Down Expand Up @@ -1282,7 +1280,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
&mut self,
lhs: AcirVar,
rhs: AcirVar,
bit_size: u32,
bit_size: u8,
) -> Result<AcirVar, RuntimeError> {
// Flip the result of calling more than equal method to
// compute less than.
Expand Down Expand Up @@ -1518,7 +1516,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
match self.vars[&input].as_constant() {
Some(constant) if allow_constant_inputs => {
single_val_witnesses.push(
FunctionInput::constant(*constant, num_bits).map_err(
FunctionInput::constant(*constant, num_bits as u32).map_err(
|invalid_input_bit_size| {
RuntimeError::InvalidBlackBoxInputBitSize {
value: invalid_input_bit_size.value,
Expand All @@ -1533,7 +1531,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
_ => {
let witness_var = self.get_or_create_witness_var(input)?;
let witness = self.var_to_witness(witness_var)?;
single_val_witnesses.push(FunctionInput::witness(witness, num_bits));
single_val_witnesses.push(FunctionInput::witness(witness, num_bits as u32));
}
}
}
Expand Down Expand Up @@ -1604,6 +1602,7 @@ impl<F: AcirField, B: BlackBoxFunctionSolver<F>> AcirContext<F, B> {
let input_expr = self.var_to_expression(input_var)?;

let bit_size = u32::BITS - (radix - 1).leading_zeros();
let bit_size: u8 = bit_size.try_into().unwrap();
let limbs = self.acir_ir.radix_le_decompose(&input_expr, radix, limb_count, bit_size)?;

let mut limb_vars = vecmap(limbs, |witness| {
Expand Down
10 changes: 5 additions & 5 deletions compiler/noirc_evaluator/src/acir/generated_acir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,11 +359,11 @@ impl<F: AcirField> GeneratedAcir<F> {
input_expr: &Expression<F>,
radix: u32,
limb_count: u32,
bit_size: u32,
bit_size: u8,
) -> Result<Vec<Witness>, RuntimeError> {
let radix_big = BigUint::from(radix);
assert_eq!(
BigUint::from(2u128).pow(bit_size),
BigUint::from(2u128).pow(bit_size as u32),
radix_big,
"ICE: Radix must be a power of 2"
);
Expand Down Expand Up @@ -574,19 +574,19 @@ impl<F: AcirField> GeneratedAcir<F> {
pub(crate) fn range_constraint(
&mut self,
witness: Witness,
num_bits: u32,
num_bits: u8,
) -> Result<(), RuntimeError> {
// We class this as an error because users should instead
// do `as Field`.
if num_bits >= F::max_num_bits() {
if num_bits as u32 >= F::max_num_bits() {
return Err(RuntimeError::InvalidRangeConstraint {
num_bits: F::max_num_bits(),
call_stack: self.call_stack.clone(),
});
};

let constraint = AcirOpcode::BlackBoxFuncCall(BlackBoxFuncCall::RANGE {
input: FunctionInput::witness(witness, num_bits),
input: FunctionInput::witness(witness, num_bits as u32),
});
self.push_opcode(constraint);

Expand Down
Loading

0 comments on commit aedd79c

Please sign in to comment.