mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-24 07:48:04 +03:00
add relational expression module
This commit is contained in:
parent
f29fac883f
commit
d5017c7666
@ -1,7 +1,6 @@
|
||||
//! Methods to enforce constraints on expressions in a compiled Leo program.
|
||||
|
||||
use crate::{
|
||||
comparator::{ComparatorGadget, EvaluateLtGadget},
|
||||
errors::ExpressionError,
|
||||
program::{new_scope, ConstrainedProgram},
|
||||
value::{
|
||||
@ -31,10 +30,7 @@ use leo_types::{
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::{
|
||||
r1cs::ConstraintSystem,
|
||||
utilities::{eq::EvaluateEqGadget, select::CondSelectGadget},
|
||||
},
|
||||
gadgets::{r1cs::ConstraintSystem, utilities::select::CondSelectGadget},
|
||||
};
|
||||
|
||||
static SELF_KEYWORD: &'static str = "self";
|
||||
@ -75,201 +71,6 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
Ok(result_value)
|
||||
}
|
||||
|
||||
/// Evaluate Boolean operations
|
||||
fn evaluate_eq_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} == {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Address(address_1), ConstrainedValue::Address(address_2)) => {
|
||||
address_1.evaluate_equal(unique_namespace, &address_2)
|
||||
}
|
||||
(ConstrainedValue::Boolean(bool_1), ConstrainedValue::Boolean(bool_2)) => {
|
||||
bool_1.evaluate_equal(unique_namespace, &bool_2)
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.evaluate_equal(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.evaluate_equal(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Group(point_1), ConstrainedValue::Group(point_2)) => {
|
||||
point_1.evaluate_equal(unique_namespace, &point_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_eq_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_eq_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} == {}", val_1, val_2,),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean =
|
||||
constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate equal"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
|
||||
fn evaluate_ge_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} >= {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.greater_than_or_equal(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.greater_than_or_equal(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_ge_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_ge_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} >= {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean = constraint_result
|
||||
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate greater than or equal"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
|
||||
fn evaluate_gt_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} > {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.greater_than(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.greater_than(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_gt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_gt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} > {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean = constraint_result
|
||||
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate greater than"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
|
||||
fn evaluate_le_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} <= {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.less_than_or_equal(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.less_than_or_equal(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_le_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_le_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} <= {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean = constraint_result
|
||||
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate less than or equal"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
|
||||
fn evaluate_lt_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} < {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.less_than(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.less_than(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_lt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_lt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} < {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean =
|
||||
constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate less than"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
|
||||
/// Enforce ternary conditional expression
|
||||
fn enforce_conditional_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
|
@ -1,7 +1,10 @@
|
||||
//! Methods to enforce expressions in a compiled Leo program.
|
||||
|
||||
pub mod arithmetic;
|
||||
pub use arithmetic::*;
|
||||
pub use self::arithmetic::*;
|
||||
|
||||
pub mod expression;
|
||||
pub use expression::*;
|
||||
pub use self::expression::*;
|
||||
|
||||
pub mod relational;
|
||||
pub use self::relational::*;
|
||||
|
58
compiler/src/expression/relational/eq.rs
Normal file
58
compiler/src/expression/relational/eq.rs
Normal file
@ -0,0 +1,58 @@
|
||||
//! Methods to enforce constraints on `==` comparison expressions in a compiled Leo program.
|
||||
|
||||
use crate::{errors::ExpressionError, program::ConstrainedProgram, value::ConstrainedValue, GroupType};
|
||||
use leo_types::Span;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::{r1cs::ConstraintSystem, utilities::eq::EvaluateEqGadget},
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
/// Evaluate Boolean operations
|
||||
pub fn evaluate_eq_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} == {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Address(address_1), ConstrainedValue::Address(address_2)) => {
|
||||
address_1.evaluate_equal(unique_namespace, &address_2)
|
||||
}
|
||||
(ConstrainedValue::Boolean(bool_1), ConstrainedValue::Boolean(bool_2)) => {
|
||||
bool_1.evaluate_equal(unique_namespace, &bool_2)
|
||||
}
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.evaluate_equal(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.evaluate_equal(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Group(point_1), ConstrainedValue::Group(point_2)) => {
|
||||
point_1.evaluate_equal(unique_namespace, &point_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_eq_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_eq_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} == {}", val_1, val_2,),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean =
|
||||
constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate equal"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
}
|
54
compiler/src/expression/relational/ge.rs
Normal file
54
compiler/src/expression/relational/ge.rs
Normal file
@ -0,0 +1,54 @@
|
||||
//! Methods to enforce constraints on `>=` comparison expressions in a compiled Leo program.
|
||||
|
||||
use crate::{
|
||||
comparator::ComparatorGadget,
|
||||
errors::ExpressionError,
|
||||
program::ConstrainedProgram,
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
};
|
||||
use leo_types::Span;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::ConstraintSystem,
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
pub fn evaluate_ge_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} >= {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.greater_than_or_equal(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.greater_than_or_equal(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_ge_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_ge_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} >= {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean = constraint_result
|
||||
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate greater than or equal"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
}
|
54
compiler/src/expression/relational/gt.rs
Normal file
54
compiler/src/expression/relational/gt.rs
Normal file
@ -0,0 +1,54 @@
|
||||
//! Methods to enforce constraints on `>` comparison expressions in a compiled Leo program.
|
||||
|
||||
use crate::{
|
||||
comparator::ComparatorGadget,
|
||||
errors::ExpressionError,
|
||||
program::ConstrainedProgram,
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
};
|
||||
use leo_types::Span;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::ConstraintSystem,
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
pub fn evaluate_gt_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} > {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.greater_than(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.greater_than(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_gt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_gt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} > {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean = constraint_result
|
||||
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate greater than"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
}
|
54
compiler/src/expression/relational/le.rs
Normal file
54
compiler/src/expression/relational/le.rs
Normal file
@ -0,0 +1,54 @@
|
||||
//! Methods to enforce constraints on `<=` comparison expressions in a compiled Leo program.
|
||||
|
||||
use crate::{
|
||||
comparator::ComparatorGadget,
|
||||
errors::ExpressionError,
|
||||
program::ConstrainedProgram,
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
};
|
||||
use leo_types::Span;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::ConstraintSystem,
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
pub fn evaluate_le_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} <= {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.less_than_or_equal(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.less_than_or_equal(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_le_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_le_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} <= {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean = constraint_result
|
||||
.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate less than or equal"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
}
|
54
compiler/src/expression/relational/lt.rs
Normal file
54
compiler/src/expression/relational/lt.rs
Normal file
@ -0,0 +1,54 @@
|
||||
//! Methods to enforce constraints on `<` comparison expressions in a compiled Leo program.
|
||||
|
||||
use crate::{
|
||||
comparator::EvaluateLtGadget,
|
||||
errors::ExpressionError,
|
||||
program::ConstrainedProgram,
|
||||
value::ConstrainedValue,
|
||||
GroupType,
|
||||
};
|
||||
use leo_types::Span;
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::ConstraintSystem,
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
|
||||
pub fn evaluate_lt_expression<CS: ConstraintSystem<F>>(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
left: ConstrainedValue<F, G>,
|
||||
right: ConstrainedValue<F, G>,
|
||||
span: Span,
|
||||
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
|
||||
let mut unique_namespace = cs.ns(|| format!("evaluate {} < {} {}:{}", left, right, span.line, span.start));
|
||||
let constraint_result = match (left, right) {
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
num_1.less_than(unique_namespace, &num_2)
|
||||
}
|
||||
(ConstrainedValue::Field(field_1), ConstrainedValue::Field(field_2)) => {
|
||||
field_1.less_than(unique_namespace, &field_2)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
|
||||
return self.evaluate_lt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, ConstrainedValue::Unresolved(string)) => {
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
|
||||
return self.evaluate_lt_expression(&mut unique_namespace, val_1, val_2, span);
|
||||
}
|
||||
(val_1, val_2) => {
|
||||
return Err(ExpressionError::incompatible_types(
|
||||
format!("{} < {}", val_1, val_2),
|
||||
span,
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
let boolean =
|
||||
constraint_result.map_err(|e| ExpressionError::cannot_enforce(format!("evaluate less than"), e, span))?;
|
||||
|
||||
Ok(ConstrainedValue::Boolean(boolean))
|
||||
}
|
||||
}
|
16
compiler/src/expression/relational/mod.rs
Normal file
16
compiler/src/expression/relational/mod.rs
Normal file
@ -0,0 +1,16 @@
|
||||
//! Methods to enforce constraints on relational expressions in a compiled Leo program.
|
||||
|
||||
pub mod eq;
|
||||
pub use self::eq::*;
|
||||
|
||||
pub mod ge;
|
||||
pub use self::ge::*;
|
||||
|
||||
pub mod gt;
|
||||
pub use self::gt::*;
|
||||
|
||||
pub mod le;
|
||||
pub use self::le::*;
|
||||
|
||||
pub mod lt;
|
||||
pub use self::lt::*;
|
Loading…
Reference in New Issue
Block a user