deprecate FieldElement. use FieldType

This commit is contained in:
collin 2020-06-02 12:09:14 -07:00
parent 0240eed168
commit a2dfc5e9fc
13 changed files with 97 additions and 552 deletions

View File

@ -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)?))
}

View 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))
}

View File

@ -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))
}
})
}
}

View File

@ -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) => {

View File

@ -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::*;

View File

@ -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)?

View File

@ -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) => {

View File

@ -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),

View File

@ -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,

View File

@ -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>>),

View File

@ -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),

View File

@ -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,
}

View File

@ -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),
}