mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
deprecate FieldElement. use FieldType
This commit is contained in:
parent
0240eed168
commit
a2dfc5e9fc
@ -8,7 +8,7 @@ use crate::{
|
||||
CircuitFieldDefinition, CircuitMember, Expression, Identifier, RangeOrExpression,
|
||||
SpreadOrExpression,
|
||||
},
|
||||
GroupType, Integer, IntegerType, Type,
|
||||
FieldType, GroupType, Integer, IntegerType, Type,
|
||||
};
|
||||
|
||||
use snarkos_models::{
|
||||
@ -60,8 +60,8 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(Self::enforce_integer_add(cs, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(self.enforce_field_add(cs, fe_1, fe_2)?)
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
Ok(ConstrainedValue::Field(fe_1.add(cs, &fe_2)?))
|
||||
}
|
||||
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
|
||||
Ok(ConstrainedValue::Group(ge_1.add(cs, &ge_2)?))
|
||||
@ -91,8 +91,8 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(Self::enforce_integer_sub(cs, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(self.enforce_field_sub(cs, fe_1, fe_2)?)
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
Ok(ConstrainedValue::Field(fe_1.sub(cs, &fe_2)?))
|
||||
}
|
||||
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
|
||||
Ok(ConstrainedValue::Group(ge_1.sub(cs, &ge_2)?))
|
||||
@ -122,8 +122,8 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(Self::enforce_integer_mul(cs, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(self.enforce_field_mul(cs, fe_1, fe_2)?)
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
Ok(ConstrainedValue::Field(fe_1.mul(cs, &fe_2)?))
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
@ -152,8 +152,8 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(Self::enforce_integer_div(cs, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(self.enforce_field_div(cs, fe_1, fe_2)?)
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
Ok(ConstrainedValue::Field(fe_1.div(cs, &fe_2)?))
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
@ -181,9 +181,6 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(Self::enforce_integer_pow(cs, num_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(self.enforce_field_pow(cs, fe_1, num_2)?)
|
||||
}
|
||||
(ConstrainedValue::Unresolved(string), val_2) => {
|
||||
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
|
||||
self.enforce_pow_expression(cs, val_1, val_2)
|
||||
@ -192,7 +189,7 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
|
||||
self.enforce_pow_expression(cs, val_1, val_2)
|
||||
}
|
||||
(_, ConstrainedValue::FieldElement(num_2)) => {
|
||||
(_, ConstrainedValue::Field(num_2)) => {
|
||||
Err(ExpressionError::InvalidExponent(num_2.to_string()))
|
||||
}
|
||||
(val_1, val_2) => Err(ExpressionError::IncompatibleTypes(format!(
|
||||
@ -215,9 +212,9 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Ok(Self::evaluate_integer_eq(num_1, num_2)?)
|
||||
}
|
||||
// (ResolvedValue::FieldElement(fe_1), ResolvedValue::FieldElement(fe_2)) => {
|
||||
// Self::field_eq(fe_1, fe_2)
|
||||
// }
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(fe_1.eq(&fe_2))))
|
||||
}
|
||||
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
|
||||
Ok(ConstrainedValue::Boolean(Boolean::Constant(ge_1.eq(&ge_2))))
|
||||
}
|
||||
@ -819,7 +816,7 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
|
||||
// Values
|
||||
Expression::Integer(integer) => Ok(Self::get_integer_constant(integer)),
|
||||
Expression::FieldElement(fe) => Ok(Self::get_field_element_constant(fe)),
|
||||
Expression::Field(field) => Ok(ConstrainedValue::Field(FieldType::constant(field)?)),
|
||||
Expression::Group(group_affine) => {
|
||||
Ok(ConstrainedValue::Group(G::constant(group_affine)?))
|
||||
}
|
||||
|
44
compiler/src/constraints/field.rs
Normal file
44
compiler/src/constraints/field.rs
Normal file
@ -0,0 +1,44 @@
|
||||
//! Methods to enforce constraints on field elements in a resolved Leo program.
|
||||
|
||||
use crate::{
|
||||
constraints::ConstrainedValue, errors::FieldElementError, types::InputValue, FieldType,
|
||||
GroupType,
|
||||
};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::{r1cs::ConstraintSystem, utilities::alloc::AllocGadget},
|
||||
};
|
||||
|
||||
pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
|
||||
cs: &mut CS,
|
||||
name: String,
|
||||
private: bool,
|
||||
input_value: Option<InputValue<F>>,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
// Check that the parameter value is the correct type
|
||||
let field_option = match input_value {
|
||||
Some(input) => {
|
||||
if let InputValue::Field(field_string) = input {
|
||||
Some(field_string)
|
||||
} else {
|
||||
return Err(FieldElementError::Invalid(input.to_string()));
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
// Check visibility of parameter
|
||||
let field_value = if private {
|
||||
FieldType::alloc(cs.ns(|| name), || {
|
||||
field_option.ok_or(SynthesisError::AssignmentMissing)
|
||||
})?
|
||||
} else {
|
||||
FieldType::alloc_input(cs.ns(|| name), || {
|
||||
field_option.ok_or(SynthesisError::AssignmentMissing)
|
||||
})?
|
||||
};
|
||||
|
||||
Ok(ConstrainedValue::Field(field_value))
|
||||
}
|
@ -1,471 +0,0 @@
|
||||
//! Methods to enforce constraints on field elements in a resolved Leo program.
|
||||
|
||||
use crate::{
|
||||
constraints::{ConstrainedProgram, ConstrainedValue},
|
||||
errors::FieldElementError,
|
||||
types::{FieldElement, InputValue, Integer},
|
||||
GroupType,
|
||||
};
|
||||
|
||||
use snarkos_errors::gadgets::SynthesisError;
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::r1cs::{ConstraintSystem, LinearCombination, Variable as R1CSVariable},
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> ConstrainedProgram<F, G, CS> {
|
||||
pub(crate) fn field_element_from_input(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
name: String,
|
||||
private: bool,
|
||||
input_value: Option<InputValue<F>>,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
// Check that the parameter value is the correct type
|
||||
let field_option = match input_value {
|
||||
Some(input) => {
|
||||
if let InputValue::Field(fe) = input {
|
||||
Some(fe)
|
||||
} else {
|
||||
return Err(FieldElementError::InvalidField(input.to_string()));
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
// Check visibility of parameter
|
||||
let field_value = if private {
|
||||
cs.alloc(
|
||||
|| name,
|
||||
|| field_option.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?
|
||||
} else {
|
||||
cs.alloc_input(
|
||||
|| name,
|
||||
|| field_option.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?
|
||||
};
|
||||
|
||||
Ok(ConstrainedValue::FieldElement(FieldElement::Allocated(
|
||||
field_option,
|
||||
field_value,
|
||||
)))
|
||||
}
|
||||
|
||||
pub(crate) fn get_field_element_constant(fe: FieldElement<F>) -> ConstrainedValue<F, G> {
|
||||
ConstrainedValue::FieldElement(fe)
|
||||
}
|
||||
|
||||
// pub(crate) fn field_eq(fe1: F, fe2: F) -> ResolvedValue<F> {
|
||||
// ResolvedValue::Boolean(Boolean::Constant(fe1.eq(&fe2)))
|
||||
// }
|
||||
//
|
||||
// pub(crate) fn field_geq(fe1: F, fe2: F) -> ResolvedValue<F> {
|
||||
// ResolvedValue::Boolean(Boolean::Constant(fe1.ge(&fe2)))
|
||||
// }
|
||||
//
|
||||
// pub(crate) fn field_gt(fe1: F, fe2: F) -> ResolvedValue<F> {
|
||||
// ResolvedValue::Boolean(Boolean::Constant(fe1.gt(&fe2)))
|
||||
// }
|
||||
//
|
||||
// pub(crate) fn field_leq(fe1: F, fe2: F) -> ResolvedValue<F> {
|
||||
// ResolvedValue::Boolean(Boolean::Constant(fe1.le(&fe2)))
|
||||
// }
|
||||
//
|
||||
// pub(crate) fn field_lt(fe1: F, fe2: F) -> ResolvedValue<F> {
|
||||
// ResolvedValue::Boolean(Boolean::Constant(fe1.lt(&fe2)))
|
||||
// }
|
||||
|
||||
pub(crate) fn enforce_field_eq(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
fe_1: FieldElement<F>,
|
||||
fe_2: FieldElement<F>,
|
||||
) {
|
||||
let mut lc = LinearCombination::zero();
|
||||
|
||||
match (fe_1, fe_2) {
|
||||
(FieldElement::Constant(fe_1_constant), FieldElement::Constant(fe_2_constant)) => {
|
||||
// lc = lc + (fe_1_constant * 1) - (fe_2_constant * 1)
|
||||
// lc = lc + fe_1 - fe_2
|
||||
lc = lc + (fe_1_constant, CS::one()) - (fe_2_constant, CS::one());
|
||||
}
|
||||
// else, return an allocated result
|
||||
(
|
||||
FieldElement::Allocated(_fe_1_value, fe_1_variable),
|
||||
FieldElement::Constant(fe_2_constant),
|
||||
) => {
|
||||
// lc = lc + fe_1 - (fe_2_constant * 1)
|
||||
// lc = lc + fe_1 - fe_2
|
||||
lc = lc + fe_1_variable - (fe_2_constant, CS::one())
|
||||
}
|
||||
(
|
||||
FieldElement::Constant(fe_1_constant),
|
||||
FieldElement::Allocated(_fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
// lc = lc + (fe_1_constant * 1) - fe_2
|
||||
// lc = lc + fe_1 - fe_2
|
||||
lc = lc + (fe_1_constant, CS::one()) - fe_2_variable
|
||||
}
|
||||
(
|
||||
FieldElement::Allocated(_fe_1_value, fe_1_variable),
|
||||
FieldElement::Allocated(_fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
// lc = lc + fe_1 - fe_2
|
||||
lc = lc + fe_1_variable - fe_2_variable
|
||||
}
|
||||
}
|
||||
|
||||
// enforce that the linear combination is zero
|
||||
cs.enforce(|| "field equality", |lc| lc, |lc| lc, |_| lc);
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_field_add(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
fe_1: FieldElement<F>,
|
||||
fe_2: FieldElement<F>,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
Ok(match (fe_1, fe_2) {
|
||||
// if both constants, then return a constant result
|
||||
(FieldElement::Constant(fe_1_constant), FieldElement::Constant(fe_2_constant)) => {
|
||||
ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
fe_1_constant.add(&fe_2_constant),
|
||||
))
|
||||
}
|
||||
// else, return an allocated result
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Constant(fe_2_constant),
|
||||
) => {
|
||||
let sum_value: Option<F> = fe_1_value.map(|v| v.add(&fe_2_constant));
|
||||
let sum_variable: R1CSVariable = cs.alloc(
|
||||
|| "field addition",
|
||||
|| sum_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "sum = 1 * (fe_1 + fe2)",
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + fe_1_variable + (fe_2_constant, CS::one()),
|
||||
|lc| lc + sum_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(sum_value, sum_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Constant(fe_1_constant),
|
||||
FieldElement::Allocated(fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
let sum_value: Option<F> = fe_2_value.map(|v| fe_1_constant.add(&v));
|
||||
let sum_variable: R1CSVariable = cs.alloc(
|
||||
|| "field addition",
|
||||
|| sum_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "sum = 1 * (fe_1 + fe_2)",
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + (fe_1_constant, CS::one()) + fe_2_variable,
|
||||
|lc| lc + sum_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(sum_value, sum_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Allocated(fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
let sum_value: Option<F> = match (fe_1_value, fe_2_value) {
|
||||
(Some(fe_1_value), Some(fe_2_value)) => Some(fe_1_value.add(&fe_2_value)),
|
||||
(_, _) => None,
|
||||
};
|
||||
let sum_variable: R1CSVariable = cs.alloc(
|
||||
|| "field addition",
|
||||
|| sum_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "sum = 1 * (fe_1 + fe_2)",
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + fe_1_variable + fe_2_variable,
|
||||
|lc| lc + sum_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(sum_value, sum_variable))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_field_sub(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
fe_1: FieldElement<F>,
|
||||
fe_2: FieldElement<F>,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
Ok(match (fe_1, fe_2) {
|
||||
// if both constants, then return a constant result
|
||||
(FieldElement::Constant(fe_1_constant), FieldElement::Constant(fe_2_constant)) => {
|
||||
ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
fe_1_constant.sub(&fe_2_constant),
|
||||
))
|
||||
}
|
||||
// else, return an allocated result
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Constant(fe_2_constant),
|
||||
) => {
|
||||
let sub_value: Option<F> = fe_1_value.map(|v| v.sub(&fe_2_constant));
|
||||
let sub_variable: R1CSVariable = cs.alloc(
|
||||
|| "field subtraction",
|
||||
|| sub_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "sub = 1 * (fe_1 - fe2)",
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + fe_1_variable - (fe_2_constant, CS::one()),
|
||||
|lc| lc + sub_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(sub_value, sub_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Constant(fe_1_constant),
|
||||
FieldElement::Allocated(fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
let sub_value: Option<F> = fe_2_value.map(|v| fe_1_constant.sub(&v));
|
||||
let sub_variable: R1CSVariable = cs.alloc(
|
||||
|| "field subtraction",
|
||||
|| sub_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "sub = 1 * (fe_1 - fe_2)",
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + (fe_1_constant, CS::one()) - fe_2_variable,
|
||||
|lc| lc + sub_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(sub_value, sub_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Allocated(fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
let sub_value: Option<F> = match (fe_1_value, fe_2_value) {
|
||||
(Some(fe_1_value), Some(fe_2_value)) => Some(fe_1_value.sub(&fe_2_value)),
|
||||
(_, _) => None,
|
||||
};
|
||||
let sub_variable: R1CSVariable = cs.alloc(
|
||||
|| "field subtraction",
|
||||
|| sub_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "sub = 1 * (fe_1 - fe_2)",
|
||||
|lc| lc + CS::one(),
|
||||
|lc| lc + fe_1_variable - fe_2_variable,
|
||||
|lc| lc + sub_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(sub_value, sub_variable))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_field_mul(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
fe_1: FieldElement<F>,
|
||||
fe_2: FieldElement<F>,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
Ok(match (fe_1, fe_2) {
|
||||
// if both constants, then return a constant result
|
||||
(FieldElement::Constant(fe_1_constant), FieldElement::Constant(fe_2_constant)) => {
|
||||
ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
fe_1_constant.mul(&fe_2_constant),
|
||||
))
|
||||
}
|
||||
// else, return an allocated result
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Constant(fe_2_constant),
|
||||
) => {
|
||||
let mul_value: Option<F> = fe_1_value.map(|v| v.mul(&fe_2_constant));
|
||||
let mul_variable: R1CSVariable = cs.alloc(
|
||||
|| "field multiplication",
|
||||
|| mul_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "mul = fe_1 * fe_2",
|
||||
|lc| lc + fe_1_variable,
|
||||
|lc| lc + (fe_2_constant, CS::one()),
|
||||
|lc| lc + mul_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(mul_value, mul_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Constant(fe_1_constant),
|
||||
FieldElement::Allocated(fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
let mul_value: Option<F> = fe_2_value.map(|v| fe_1_constant.mul(&v));
|
||||
let mul_variable: R1CSVariable = cs.alloc(
|
||||
|| "field multiplication",
|
||||
|| mul_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "mul = fe_1 * fe_2",
|
||||
|lc| lc + (fe_1_constant, CS::one()),
|
||||
|lc| lc + fe_2_variable,
|
||||
|lc| lc + mul_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(mul_value, mul_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Allocated(fe_2_value, fe_2_variable),
|
||||
) => {
|
||||
let mul_value: Option<F> = match (fe_1_value, fe_2_value) {
|
||||
(Some(fe_1_value), Some(fe_2_value)) => Some(fe_1_value.mul(&fe_2_value)),
|
||||
(_, _) => None,
|
||||
};
|
||||
let mul_variable: R1CSVariable = cs.alloc(
|
||||
|| "field multiplication",
|
||||
|| mul_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "mul = fe_1 * fe_2",
|
||||
|lc| lc + fe_1_variable,
|
||||
|lc| lc + fe_2_variable,
|
||||
|lc| lc + mul_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(mul_value, mul_variable))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_field_div(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
fe_1: FieldElement<F>,
|
||||
fe_2: FieldElement<F>,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
Ok(match (fe_1, fe_2) {
|
||||
// if both constants, then return a constant result
|
||||
(FieldElement::Constant(fe_1_constant), FieldElement::Constant(fe_2_constant)) => {
|
||||
ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
fe_1_constant.div(&fe_2_constant),
|
||||
))
|
||||
}
|
||||
// else, return an allocated result
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Constant(fe_2_constant),
|
||||
) => {
|
||||
let div_value: Option<F> = fe_1_value.map(|v| v.div(&fe_2_constant));
|
||||
let div_variable: R1CSVariable = cs.alloc(
|
||||
|| "field division",
|
||||
|| div_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
let fe_2_inverse_value = fe_2_constant.inverse().unwrap();
|
||||
|
||||
cs.enforce(
|
||||
|| "div = fe_1 * fe_2^-1",
|
||||
|lc| lc + fe_1_variable,
|
||||
|lc| lc + (fe_2_inverse_value, CS::one()),
|
||||
|lc| lc + div_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(div_value, div_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Constant(fe_1_constant),
|
||||
FieldElement::Allocated(fe_2_value, _fe_2_variable),
|
||||
) => {
|
||||
let div_value: Option<F> = fe_2_value.map(|v| fe_1_constant.div(&v));
|
||||
let div_variable: R1CSVariable = cs.alloc(
|
||||
|| "field division",
|
||||
|| div_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
let fe_2_inverse_value = fe_2_value.map(|v| v.inverse().unwrap());
|
||||
let fe_2_inverse_variable = cs.alloc(
|
||||
|| "field inverse",
|
||||
|| fe_2_inverse_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "div = fe_1 * fe_2^-1",
|
||||
|lc| lc + (fe_1_constant, CS::one()),
|
||||
|lc| lc + fe_2_inverse_variable,
|
||||
|lc| lc + div_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(div_value, div_variable))
|
||||
}
|
||||
(
|
||||
FieldElement::Allocated(fe_1_value, fe_1_variable),
|
||||
FieldElement::Allocated(fe_2_value, _fe_2_variable),
|
||||
) => {
|
||||
let div_value: Option<F> = match (fe_1_value, fe_2_value) {
|
||||
(Some(fe_1_value), Some(fe_2_value)) => Some(fe_1_value.div(&fe_2_value)),
|
||||
(_, _) => None,
|
||||
};
|
||||
let div_variable: R1CSVariable = cs.alloc(
|
||||
|| "field division",
|
||||
|| div_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
let fe_2_inverse_value = fe_2_value.map(|v| v.inverse().unwrap());
|
||||
let fe_2_inverse_variable = cs.alloc(
|
||||
|| "field inverse",
|
||||
|| fe_2_inverse_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
cs.enforce(
|
||||
|| "div = fe_1 * fe_2^-1",
|
||||
|lc| lc + fe_1_variable,
|
||||
|lc| lc + fe_2_inverse_variable,
|
||||
|lc| lc + div_variable.clone(),
|
||||
);
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(div_value, div_variable))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn enforce_field_pow(
|
||||
&mut self,
|
||||
cs: &mut CS,
|
||||
fe_1: FieldElement<F>,
|
||||
num: Integer,
|
||||
) -> Result<ConstrainedValue<F, G>, FieldElementError> {
|
||||
Ok(match fe_1 {
|
||||
// if both constants, then return a constant result
|
||||
FieldElement::Constant(fe_1_constant) => ConstrainedValue::FieldElement(
|
||||
FieldElement::Constant(fe_1_constant.pow(&[num.to_usize() as u64])),
|
||||
),
|
||||
// else, return an allocated result
|
||||
FieldElement::Allocated(fe_1_value, _fe_1_variable) => {
|
||||
let pow_value: Option<F> = fe_1_value.map(|v| v.pow(&[num.to_usize() as u64]));
|
||||
let pow_variable: R1CSVariable = cs.alloc(
|
||||
|| "field exponentiation",
|
||||
|| pow_value.ok_or(SynthesisError::AssignmentMissing),
|
||||
)?;
|
||||
|
||||
// cs.enforce( //todo: find a linear combination for this
|
||||
// || "pow = 1 + fe_1^num",
|
||||
// |lc| lc + fe_1_variable,
|
||||
// |lc| lc + (fe_2_inverse_value, CS::one()),
|
||||
// |lc| lc + pow_variable.clone());
|
||||
|
||||
ConstrainedValue::FieldElement(FieldElement::Allocated(pow_value, pow_variable))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@
|
||||
use crate::{
|
||||
constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
|
||||
errors::{FunctionError, ImportError},
|
||||
group_from_input,
|
||||
field_from_input, group_from_input,
|
||||
types::{Expression, Function, Identifier, InputValue, Program, Type},
|
||||
GroupType,
|
||||
};
|
||||
@ -179,9 +179,7 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
Type::IntegerType(integer_type) => {
|
||||
Ok(self.integer_from_parameter(cs, integer_type, name, private, input_value)?)
|
||||
}
|
||||
Type::FieldElement => {
|
||||
Ok(self.field_element_from_input(cs, name, private, input_value)?)
|
||||
}
|
||||
Type::Field => Ok(field_from_input(cs, name, private, input_value)?),
|
||||
Type::Group => Ok(group_from_input(cs, name, private, input_value)?),
|
||||
Type::Boolean => Ok(self.bool_from_input(cs, name, private, input_value)?),
|
||||
Type::Array(_type, dimensions) => {
|
||||
|
@ -15,8 +15,8 @@ pub use import::*;
|
||||
pub mod integer;
|
||||
pub use integer::*;
|
||||
|
||||
pub mod field_element;
|
||||
pub use field_element::*;
|
||||
pub(crate) mod field;
|
||||
pub(crate) use field::*;
|
||||
|
||||
pub(crate) mod group;
|
||||
pub(crate) use group::*;
|
||||
|
@ -13,7 +13,10 @@ use crate::{
|
||||
|
||||
use snarkos_models::{
|
||||
curves::{Field, PrimeField},
|
||||
gadgets::{r1cs::ConstraintSystem, utilities::boolean::Boolean, utilities::uint32::UInt32},
|
||||
gadgets::{
|
||||
r1cs::ConstraintSystem,
|
||||
utilities::{boolean::Boolean, eq::EqGadget, uint32::UInt32},
|
||||
},
|
||||
};
|
||||
|
||||
impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> ConstrainedProgram<F, G, CS> {
|
||||
@ -413,8 +416,8 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
|
||||
(ConstrainedValue::Integer(num_1), ConstrainedValue::Integer(num_2)) => {
|
||||
Self::enforce_integer_eq(cs, num_1, num_2)?
|
||||
}
|
||||
(ConstrainedValue::FieldElement(fe_1), ConstrainedValue::FieldElement(fe_2)) => {
|
||||
self.enforce_field_eq(cs, fe_1, fe_2)
|
||||
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
|
||||
fe_1.enforce_equal(cs, &fe_2)?
|
||||
}
|
||||
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
|
||||
ge_1.enforce_equal(cs, &ge_2)?
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
use crate::{
|
||||
errors::ValueError,
|
||||
types::{Circuit, FieldElement, Function, Identifier, Integer, IntegerType, Type},
|
||||
GroupType,
|
||||
types::{Circuit, Function, Identifier, Integer, IntegerType, Type},
|
||||
FieldType, GroupType,
|
||||
};
|
||||
|
||||
use snarkos_models::{
|
||||
@ -24,7 +24,7 @@ pub struct ConstrainedCircuitMember<F: Field + PrimeField, G: GroupType<F>>(
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum ConstrainedValue<F: Field + PrimeField, G: GroupType<F>> {
|
||||
Integer(Integer),
|
||||
FieldElement(FieldElement<F>),
|
||||
Field(FieldType<F>),
|
||||
Group(G),
|
||||
Boolean(Boolean),
|
||||
|
||||
@ -60,9 +60,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
IntegerType::U64 => Integer::U64(UInt64::constant(value.parse::<u64>()?)),
|
||||
IntegerType::U128 => Integer::U128(UInt128::constant(value.parse::<u128>()?)),
|
||||
})),
|
||||
Type::FieldElement => Ok(ConstrainedValue::FieldElement(FieldElement::Constant(
|
||||
F::from_str(&value).unwrap_or_default(),
|
||||
))),
|
||||
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value)?)),
|
||||
Type::Group => Ok(ConstrainedValue::Group(G::constant(value)?)),
|
||||
Type::Boolean => Ok(ConstrainedValue::Boolean(Boolean::Constant(
|
||||
value.parse::<bool>()?,
|
||||
@ -75,7 +73,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
|
||||
pub(crate) fn to_type(&self) -> Type<F> {
|
||||
match self {
|
||||
ConstrainedValue::Integer(integer) => Type::IntegerType(integer.get_type()),
|
||||
ConstrainedValue::FieldElement(_field) => Type::FieldElement,
|
||||
ConstrainedValue::Field(_field) => Type::Field,
|
||||
ConstrainedValue::Group(_group) => Type::Group,
|
||||
ConstrainedValue::Boolean(_bool) => Type::Boolean,
|
||||
_ => unimplemented!("to type only implemented for primitives"),
|
||||
@ -103,7 +101,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> fmt::Display for ConstrainedValue<F
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
ConstrainedValue::Integer(ref value) => write!(f, "{}", value),
|
||||
ConstrainedValue::FieldElement(ref value) => write!(f, "{}", value),
|
||||
ConstrainedValue::Field(ref value) => write!(f, "{}", value),
|
||||
ConstrainedValue::Group(ref value) => write!(f, "{:?}", value),
|
||||
ConstrainedValue::Boolean(ref value) => write!(f, "{}", value.get_value().unwrap()),
|
||||
ConstrainedValue::Array(ref array) => {
|
||||
|
@ -3,7 +3,7 @@ use snarkos_errors::gadgets::SynthesisError;
|
||||
#[derive(Debug, Error)]
|
||||
pub enum FieldElementError {
|
||||
#[error("Expected field element parameter, got {}", _0)]
|
||||
InvalidField(String),
|
||||
Invalid(String),
|
||||
|
||||
#[error("{}", _0)]
|
||||
SynthesisError(SynthesisError),
|
||||
|
@ -18,7 +18,7 @@ use snarkos_models::{
|
||||
},
|
||||
},
|
||||
};
|
||||
use std::borrow::Borrow;
|
||||
use std::{borrow::Borrow, str::FromStr};
|
||||
|
||||
pub enum FieldType<F: Field + PrimeField> {
|
||||
Constant(F),
|
||||
@ -26,6 +26,11 @@ pub enum FieldType<F: Field + PrimeField> {
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> FieldType<F> {
|
||||
pub fn constant(string: String) -> Result<Self, FieldElementError> {
|
||||
let value = F::from_str(&string).map_err(|_| FieldElementError::Invalid(string))?;
|
||||
Ok(FieldType::Constant(value))
|
||||
}
|
||||
|
||||
pub fn add<CS: ConstraintSystem<F>>(
|
||||
&self,
|
||||
cs: CS,
|
||||
|
@ -82,7 +82,7 @@ pub enum Expression<F: Field + PrimeField> {
|
||||
|
||||
// Values
|
||||
Integer(Integer),
|
||||
FieldElement(FieldElement<F>),
|
||||
Field(String),
|
||||
Group(String),
|
||||
Boolean(Boolean),
|
||||
Implicit(String),
|
||||
@ -142,7 +142,7 @@ pub enum IntegerType {
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum Type<F: Field + PrimeField> {
|
||||
IntegerType(IntegerType),
|
||||
FieldElement,
|
||||
Field,
|
||||
Group,
|
||||
Boolean,
|
||||
Array(Box<Type<F>>, Vec<usize>),
|
||||
@ -237,7 +237,7 @@ pub struct InputModel<F: Field + PrimeField> {
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum InputValue<F: Field + PrimeField> {
|
||||
Integer(usize),
|
||||
Field(F),
|
||||
Field(String),
|
||||
Group(String),
|
||||
Boolean(bool),
|
||||
Array(Vec<InputValue<F>>),
|
||||
|
@ -2,8 +2,8 @@
|
||||
|
||||
use crate::{
|
||||
Assignee, Circuit, CircuitMember, ConditionalNestedOrEnd, ConditionalStatement, Expression,
|
||||
FieldElement, Function, Identifier, InputModel, InputValue, Integer, IntegerType,
|
||||
RangeOrExpression, SpreadOrExpression, Statement, Type, Variable,
|
||||
Function, Identifier, InputModel, InputValue, Integer, IntegerType, RangeOrExpression,
|
||||
SpreadOrExpression, Statement, Type, Variable,
|
||||
};
|
||||
|
||||
use snarkos_models::curves::{Field, PrimeField};
|
||||
@ -42,33 +42,6 @@ impl fmt::Display for Integer {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> FieldElement<F> {
|
||||
fn format(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
FieldElement::Constant(ref constant) => write!(f, "{}", constant),
|
||||
FieldElement::Allocated(ref option, ref _r1cs_var) => {
|
||||
if option.is_some() {
|
||||
write!(f, "{}", option.unwrap())
|
||||
} else {
|
||||
write!(f, "allocated field")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> fmt::Display for FieldElement<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field + PrimeField> fmt::Debug for FieldElement<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.format(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ast, F: Field + PrimeField> fmt::Display for RangeOrExpression<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
@ -104,7 +77,7 @@ impl<'ast, F: Field + PrimeField> fmt::Display for Expression<F> {
|
||||
|
||||
// Values
|
||||
Expression::Integer(ref integer) => write!(f, "{}", integer),
|
||||
Expression::FieldElement(ref field) => write!(f, "{}", field),
|
||||
Expression::Field(ref field) => write!(f, "{}", field),
|
||||
Expression::Group(ref group) => write!(f, "{}", group),
|
||||
Expression::Boolean(ref bool) => write!(f, "{}", bool.get_value().unwrap()),
|
||||
Expression::Implicit(ref value) => write!(f, "{}", value),
|
||||
@ -278,7 +251,7 @@ impl<F: Field + PrimeField> fmt::Display for Type<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Type::IntegerType(ref integer_type) => write!(f, "{}", integer_type),
|
||||
Type::FieldElement => write!(f, "field"),
|
||||
Type::Field => write!(f, "field"),
|
||||
Type::Group => write!(f, "group"),
|
||||
Type::Boolean => write!(f, "bool"),
|
||||
Type::Circuit(ref variable) => write!(f, "{}", variable),
|
||||
|
@ -114,9 +114,7 @@ impl<'ast, F: Field + PrimeField> From<ast::RangeOrExpression<'ast>>
|
||||
|
||||
impl<'ast, F: Field + PrimeField> From<ast::Field<'ast>> for types::Expression<F> {
|
||||
fn from(field: ast::Field<'ast>) -> Self {
|
||||
types::Expression::FieldElement(types::FieldElement::Constant(
|
||||
F::from_str(&field.number.value).unwrap_or_default(),
|
||||
))
|
||||
types::Expression::Field(field.number.value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -653,7 +651,7 @@ impl<F: Field + PrimeField> From<ast::BasicType> for types::Type<F> {
|
||||
ast::BasicType::Integer(_type) => {
|
||||
types::Type::IntegerType(types::IntegerType::from(_type))
|
||||
}
|
||||
ast::BasicType::Field(_type) => types::Type::FieldElement,
|
||||
ast::BasicType::Field(_type) => types::Type::Field,
|
||||
ast::BasicType::Group(_type) => types::Type::Group,
|
||||
ast::BasicType::Boolean(_type) => types::Type::Boolean,
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ const DIRECTORY_NAME: &str = "tests/field_element/";
|
||||
fn output_zero(program: EdwardsTestCompiler) {
|
||||
let output = get_output(program);
|
||||
assert_eq!(
|
||||
EdwardsConstrainedValue::Return(vec![ConstrainedValue::FieldElement(
|
||||
FieldElement::Constant(Fq::zero())
|
||||
)])
|
||||
EdwardsConstrainedValue::Return(vec![ConstrainedValue::Field(FieldElement::Constant(
|
||||
Fq::zero()
|
||||
))])
|
||||
.to_string(),
|
||||
output.to_string()
|
||||
);
|
||||
@ -23,9 +23,9 @@ fn output_zero(program: EdwardsTestCompiler) {
|
||||
fn output_one(program: EdwardsTestCompiler) {
|
||||
let output = get_output(program);
|
||||
assert_eq!(
|
||||
EdwardsConstrainedValue::Return(vec![ConstrainedValue::FieldElement(
|
||||
FieldElement::Constant(Fq::one())
|
||||
)])
|
||||
EdwardsConstrainedValue::Return(vec![ConstrainedValue::Field(FieldElement::Constant(
|
||||
Fq::one()
|
||||
))])
|
||||
.to_string(),
|
||||
output.to_string()
|
||||
);
|
||||
@ -34,7 +34,7 @@ fn output_one(program: EdwardsTestCompiler) {
|
||||
fn fail_field(program: EdwardsTestCompiler) {
|
||||
match get_error(program) {
|
||||
CompilerError::FunctionError(FunctionError::FieldElementError(
|
||||
FieldElementError::InvalidField(_string),
|
||||
FieldElementError::Invalid(_string),
|
||||
)) => {}
|
||||
error => panic!("Expected invalid field error, got {}", error),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user