From f0717645480988b339f82e0192519e9ed66536c1 Mon Sep 17 00:00:00 2001 From: collin Date: Thu, 30 Apr 2020 11:36:35 -0700 Subject: [PATCH] fix field pow. fix eq vs enforce_eq --- benchmark/simple.leo | 5 ++-- compiler/src/constraints/boolean.rs | 4 +++ compiler/src/constraints/expression.rs | 33 ++++++++++++++++++----- compiler/src/constraints/field_element.rs | 12 +++++---- compiler/src/constraints/integer.rs | 4 +++ 5 files changed, 44 insertions(+), 14 deletions(-) diff --git a/benchmark/simple.leo b/benchmark/simple.leo index 3ad5b9cb03..e95760f38f 100644 --- a/benchmark/simple.leo +++ b/benchmark/simple.leo @@ -1,5 +1,4 @@ -function main() -> (u32) { - a = 2; - a **= 3; +function main() -> (fe) { + a = 2fe ** 3; return a } \ No newline at end of file diff --git a/compiler/src/constraints/boolean.rs b/compiler/src/constraints/boolean.rs index 25bc5e5bc8..2a18966ba8 100644 --- a/compiler/src/constraints/boolean.rs +++ b/compiler/src/constraints/boolean.rs @@ -136,6 +136,10 @@ impl> ResolvedProgram { } } + pub(crate) fn boolean_eq(left: Boolean, right: Boolean) -> ResolvedValue { + ResolvedValue::Boolean(Boolean::Constant(left.eq(&right))) + } + pub(crate) fn enforce_boolean_eq( &mut self, cs: &mut CS, diff --git a/compiler/src/constraints/expression.rs b/compiler/src/constraints/expression.rs index b884d0a7cc..6b89559d15 100644 --- a/compiler/src/constraints/expression.rs +++ b/compiler/src/constraints/expression.rs @@ -96,7 +96,7 @@ impl> ResolvedProgram { (ResolvedValue::FieldElement(fe1), ResolvedValue::FieldElement(fe2)) => { self.enforce_field_div(fe1, fe2) } - (val1, val2) => unimplemented!("cannot multiply {} * {}", val1, val2), + (val1, val2) => unimplemented!("cannot divide {} / {}", val1, val2), } } fn enforce_pow_expression( @@ -109,14 +109,35 @@ impl> ResolvedProgram { (ResolvedValue::U32(num1), ResolvedValue::U32(num2)) => { Self::enforce_u32_pow(cs, num1, num2) } - (ResolvedValue::FieldElement(fe1), ResolvedValue::FieldElement(fe2)) => { - self.enforce_field_pow(fe1, fe2) + (ResolvedValue::FieldElement(fe1), ResolvedValue::U32(num2)) => { + self.enforce_field_pow(fe1, num2) } - (val1, val2) => unimplemented!("cannot multiply {} * {}", val1, val2), + (_, ResolvedValue::FieldElement(num2)) => { + unimplemented!("exponent power must be an integer, got field {}", num2) + } + (val1, val2) => unimplemented!("cannot enforce exponentiation {} * {}", val1, val2), } } - /// Enforce Boolean operations + /// Evaluate Boolean operations + fn evaluate_eq_expression( + &mut self, + left: ResolvedValue, + right: ResolvedValue, + ) -> ResolvedValue { + match (left, right) { + (ResolvedValue::Boolean(bool1), ResolvedValue::Boolean(bool2)) => { + Self::boolean_eq(bool1, bool2) + } + (ResolvedValue::U32(num1), ResolvedValue::U32(num2)) => Self::u32_eq(num1, num2), + (ResolvedValue::FieldElement(fe1), ResolvedValue::FieldElement(fe2)) => { + Self::field_eq(fe1, fe2) + } + (val1, val2) => unimplemented!("cannot enforce equality between {} == {}", val1, val2), + } + } + + /// Enforce Boolean operations, returns true on success fn enforce_eq_expression( &mut self, cs: &mut CS, @@ -411,7 +432,7 @@ impl> ResolvedProgram { let resolved_right = self.enforce_expression(cs, file_scope.clone(), function_scope.clone(), *right); - self.enforce_eq_expression(cs, resolved_left, resolved_right) + self.evaluate_eq_expression(resolved_left, resolved_right) } Expression::Geq(left, right) => { unimplemented!("expression {} >= {} unimplemented", left, right) diff --git a/compiler/src/constraints/field_element.rs b/compiler/src/constraints/field_element.rs index 9ff0229e14..099ec17f06 100644 --- a/compiler/src/constraints/field_element.rs +++ b/compiler/src/constraints/field_element.rs @@ -4,6 +4,7 @@ use crate::constraints::{ResolvedProgram, ResolvedValue}; use crate::{new_variable_from_variable, Parameter, Variable}; use snarkos_models::curves::{Field, PrimeField}; +use snarkos_models::gadgets::utilities::uint32::UInt32; use snarkos_models::gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean}; // use std::ops::{Add, Div, Mul, Neg, Sub}; @@ -86,9 +87,12 @@ impl> ResolvedProgram { // parameter_variable } - pub(crate) fn enforce_field_eq(&mut self, fe1: F, fe2: F) -> ResolvedValue { + pub(crate) fn field_eq(fe1: F, fe2: F) -> ResolvedValue { ResolvedValue::Boolean(Boolean::Constant(fe1.eq(&fe2))) } + pub(crate) fn enforce_field_eq(&mut self, _fe1: F, _fe2: F) -> ResolvedValue { + unimplemented!("field equality enforcement not implemented") + } pub(crate) fn enforce_field_add(&mut self, fe1: F, fe2: F) -> ResolvedValue { ResolvedValue::FieldElement(fe1.add(&fe2)) @@ -106,9 +110,7 @@ impl> ResolvedProgram { ResolvedValue::FieldElement(fe1.div(&fe2)) } - pub(crate) fn enforce_field_pow(&mut self, _fe1: F, _fe2: F) -> ResolvedValue { - unimplemented!("field element exponentiation not supported") - - // ResolvedValue::FieldElement(fe1.pow(&fe2)) + pub(crate) fn enforce_field_pow(&mut self, fe1: F, num: UInt32) -> ResolvedValue { + ResolvedValue::FieldElement(fe1.pow(&[num.value.unwrap() as u64])) } } diff --git a/compiler/src/constraints/integer.rs b/compiler/src/constraints/integer.rs index 5e1c6e3055..4d556d957e 100644 --- a/compiler/src/constraints/integer.rs +++ b/compiler/src/constraints/integer.rs @@ -95,6 +95,10 @@ impl> ResolvedProgram { } } + pub(crate) fn u32_eq(left: UInt32, right: UInt32) -> ResolvedValue { + ResolvedValue::Boolean(Boolean::Constant(left.eq(&right))) + } + pub(crate) fn enforce_u32_eq(cs: &mut CS, left: UInt32, right: UInt32) -> ResolvedValue { left.conditional_enforce_equal( cs.ns(|| format!("enforce field equal")),