fix field namespaces and errors

This commit is contained in:
collin 2020-06-20 17:49:09 -07:00
parent 2e02d0906c
commit 172ab78497
12 changed files with 236 additions and 140 deletions

View File

@ -51,7 +51,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
return Err(ExpressionError::undefined_identifier(unresolved_identifier));
};
result_value.resolve_type(expected_types)?;
result_value.resolve_type(expected_types, unresolved_identifier.span.clone())?;
Ok(result_value)
}
@ -69,17 +69,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Integer(num_1.add(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.add(cs, &fe_2)?))
Ok(ConstrainedValue::Field(fe_1.add(cs, &fe_2, span)?))
}
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
Ok(ConstrainedValue::Group(ge_1.add(cs, &ge_2)?))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.enforce_add_expression(cs, val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.enforce_add_expression(cs, val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -101,17 +101,17 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Integer(num_1.sub(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.sub(cs, &fe_2)?))
Ok(ConstrainedValue::Field(fe_1.sub(cs, &fe_2, span)?))
}
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
Ok(ConstrainedValue::Group(ge_1.sub(cs, &ge_2)?))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.enforce_sub_expression(cs, val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.enforce_sub_expression(cs, val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -133,14 +133,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Integer(num_1.mul(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.mul(cs, &fe_2)?))
Ok(ConstrainedValue::Field(fe_1.mul(cs, &fe_2, span)?))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.enforce_mul_expression(cs, val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.enforce_mul_expression(cs, val_1, val_2, span)
}
(val_1, val_2) => {
@ -164,14 +164,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Integer(num_1.div(cs, num_2, span)?))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
Ok(ConstrainedValue::Field(fe_1.div(cs, &fe_2)?))
Ok(ConstrainedValue::Field(fe_1.div(cs, &fe_2, span)?))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.enforce_div_expression(cs, val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.enforce_div_expression(cs, val_1, val_2, span)
}
(val_1, val_2) => {
@ -195,11 +195,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Integer(num_1.pow(cs, num_2, span)?))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.enforce_pow_expression(cs, val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.enforce_pow_expression(cs, val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -232,11 +232,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
ge_1.evaluate_equal(expression_namespace, &ge_2)?
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
return self.evaluate_eq_expression(&mut expression_namespace, val_1, val_2, span);
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
return self.evaluate_eq_expression(&mut expression_namespace, val_1, val_2, span);
}
(val_1, val_2) => {
@ -267,11 +267,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.evaluate_ge_expression(val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.evaluate_ge_expression(val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -298,11 +298,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.evaluate_gt_expression(val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.evaluate_gt_expression(val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -329,11 +329,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.evaluate_le_expression(val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.evaluate_le_expression(val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -360,11 +360,11 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Ok(ConstrainedValue::Boolean(Boolean::Constant(result)))
}
(ConstrainedValue::Unresolved(string), val_2) => {
let val_1 = ConstrainedValue::from_other(string, &val_2)?;
let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?;
self.evaluate_lt_expression(val_1, val_2, span)
}
(val_1, ConstrainedValue::Unresolved(string)) => {
let val_2 = ConstrainedValue::from_other(string, &val_1)?;
let val_2 = ConstrainedValue::from_other(string, &val_1, span.clone())?;
self.evaluate_lt_expression(val_1, val_2, span)
}
(val_1, val_2) => Err(ExpressionError::incompatible_types(
@ -397,9 +397,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
value => return Err(ExpressionError::conditional_boolean(value.to_string(), span)),
};
let resolved_second =
self.enforce_expression_value(cs, file_scope.clone(), function_scope.clone(), expected_types, second)?;
let resolved_third = self.enforce_expression_value(cs, file_scope, function_scope, expected_types, third)?;
let resolved_second = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
second,
span.clone(),
)?;
let resolved_third =
self.enforce_expression_value(cs, file_scope, function_scope, expected_types, third, span.clone())?;
match (resolved_second, resolved_third) {
(ConstrainedValue::Boolean(bool_2), ConstrainedValue::Boolean(bool_3)) => {
@ -507,7 +514,14 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
span: Span,
) -> Result<usize, ExpressionError> {
let expected_types = vec![Type::IntegerType(IntegerType::U32)];
match self.enforce_expression_value(cs, file_scope.clone(), function_scope.clone(), &expected_types, index)? {
match self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
&expected_types,
index,
span.clone(),
)? {
ConstrainedValue::Integer(number) => Ok(number.to_usize()),
value => Err(ExpressionError::invalid_index(value.to_string(), span)),
}
@ -529,6 +543,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope.clone(),
expected_types,
*array,
span.clone(),
)? {
ConstrainedValue::Array(array) => array,
value => return Err(ExpressionError::undefined_array(value.to_string(), span)),
@ -633,6 +648,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope.clone(),
expected_types,
*circuit_identifier.clone(),
span.clone(),
)? {
ConstrainedValue::CircuitExpression(name, members) => (name, members),
value => return Err(ExpressionError::undefined_circuit(value.to_string(), span)),
@ -773,9 +789,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
pub(crate) fn enforce_number_implicit(
expected_types: &Vec<Type>,
value: String,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
if expected_types.len() == 1 {
return Ok(ConstrainedValue::from_type(value, &expected_types[0])?);
return Ok(ConstrainedValue::from_type(value, &expected_types[0], span)?);
}
Ok(ConstrainedValue::Unresolved(value))
@ -791,11 +808,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope: String,
expected_types: &Vec<Type>,
expression: Expression,
span: Span,
) -> Result<ConstrainedValue<F, G>, ExpressionError> {
let mut branch = self.enforce_expression(cs, file_scope, function_scope, expected_types, expression)?;
branch.get_inner_mut();
branch.resolve_type(expected_types)?;
branch.resolve_type(expected_types, span)?;
Ok(branch)
}
@ -808,13 +826,26 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types: &Vec<Type>,
left: Expression,
right: Expression,
span: Span,
) -> Result<(ConstrainedValue<F, G>, ConstrainedValue<F, G>), ExpressionError> {
let mut resolved_left =
self.enforce_expression_value(cs, file_scope.clone(), function_scope.clone(), expected_types, left)?;
let mut resolved_right =
self.enforce_expression_value(cs, file_scope.clone(), function_scope.clone(), expected_types, right)?;
let mut resolved_left = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
left,
span.clone(),
)?;
let mut resolved_right = self.enforce_expression_value(
cs,
file_scope.clone(),
function_scope.clone(),
expected_types,
right,
span.clone(),
)?;
resolved_left.resolve_types(&mut resolved_right, expected_types)?;
resolved_left.resolve_types(&mut resolved_right, expected_types, span)?;
Ok((resolved_left, resolved_right))
}
@ -835,10 +866,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Values
Expression::Integer(integer) => Ok(ConstrainedValue::Integer(integer)),
Expression::Field(field) => Ok(ConstrainedValue::Field(FieldType::constant(field)?)),
Expression::Group(group_affine) => Ok(ConstrainedValue::Group(G::constant(group_affine)?)),
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
Expression::Group(group_affine, _span) => Ok(ConstrainedValue::Group(G::constant(group_affine)?)),
Expression::Boolean(bool) => Ok(ConstrainedValue::Boolean(bool)),
Expression::Implicit(value) => Self::enforce_number_implicit(expected_types, value),
Expression::Implicit(value, span) => Self::enforce_number_implicit(expected_types, value, span),
// Binary operations
Expression::Add(left, right, span) => {
@ -849,6 +880,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
self.enforce_add_expression(cs, resolved_left, resolved_right, span)
@ -861,6 +893,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
self.enforce_sub_expression(cs, resolved_left, resolved_right, span)
@ -873,6 +906,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
self.enforce_mul_expression(cs, resolved_left, resolved_right, span)
@ -885,6 +919,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
self.enforce_div_expression(cs, resolved_left, resolved_right, span)
@ -897,6 +932,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
self.enforce_pow_expression(cs, resolved_left, resolved_right, span)
@ -910,7 +946,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*expression,
)?)?),
Expression::Or(left, right, _span) => {
Expression::Or(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
@ -918,11 +954,12 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
Ok(self.enforce_or(cs, resolved_left, resolved_right)?)
}
Expression::And(left, right, _span) => {
Expression::And(left, right, span) => {
let (resolved_left, resolved_right) = self.enforce_binary_expression(
cs,
file_scope.clone(),
@ -930,6 +967,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
expected_types,
*left,
*right,
span.clone(),
)?;
Ok(self.enforce_and(cs, resolved_left, resolved_right)?)
@ -942,6 +980,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
&vec![],
*left,
*right,
span.clone(),
)?;
Ok(self.evaluate_eq_expression(cs, resolved_left, resolved_right, span)?)
@ -954,6 +993,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
&vec![],
*left,
*right,
span.clone(),
)?;
Ok(self.evaluate_ge_expression(resolved_left, resolved_right, span)?)
@ -966,6 +1006,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
&vec![],
*left,
*right,
span.clone(),
)?;
Ok(self.evaluate_gt_expression(resolved_left, resolved_right, span)?)
@ -978,6 +1019,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
&vec![],
*left,
*right,
span.clone(),
)?;
Ok(self.evaluate_le_expression(resolved_left, resolved_right, span)?)
@ -990,6 +1032,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
&vec![],
*left,
*right,
span.clone(),
)?;
Ok(self.evaluate_lt_expression(resolved_left, resolved_right, span)?)

View File

@ -1,7 +1,7 @@
//! Methods to enforce constraints on field elements in a resolved Leo program.
use crate::{constraints::ConstrainedValue, errors::FieldError, FieldType, GroupType};
use leo_types::InputValue;
use leo_types::{InputValue, Span};
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
@ -13,6 +13,7 @@ pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Const
cs: &mut CS,
name: String,
input_value: Option<InputValue>,
span: Span,
) -> Result<ConstrainedValue<F, G>, FieldError> {
// Check that the parameter value is the correct type
let field_option = match input_value {
@ -20,13 +21,18 @@ pub(crate) fn field_from_input<F: Field + PrimeField, G: GroupType<F>, CS: Const
if let InputValue::Field(string) = input {
Some(string)
} else {
return Err(FieldError::Invalid(input.to_string()));
return Err(FieldError::invalid_field(input.to_string(), span));
}
}
None => None,
};
let field_value = FieldType::alloc(cs.ns(|| name), || field_option.ok_or(SynthesisError::AssignmentMissing))?;
let field_name = format!("{}: field", name);
let field_name_unique = format!("`{}` {}:{}", field_name, span.line, span.start);
let field_value = FieldType::alloc(cs.ns(|| field_name_unique), || {
field_option.ok_or(SynthesisError::AssignmentMissing)
})
.map_err(|_| FieldError::missing_field(field_name, span))?;
Ok(ConstrainedValue::Field(field_value))
}

View File

@ -171,7 +171,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
input_value,
span,
)?)),
Type::Field => Ok(field_from_input(cs, name, input_value)?),
Type::Field => Ok(field_from_input(cs, name, input_value, span)?),
Type::Group => Ok(group_from_input(cs, name, input_value)?),
Type::Boolean => Ok(self.bool_from_input(cs, name, input_value)?),
Type::Array(_type, dimensions) => self.allocate_array(cs, name, *_type, dimensions, input_value, span),

View File

@ -74,7 +74,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
// Modify the single value of the array in place
match self.get_mutable_assignee(name, span.clone())? {
ConstrainedValue::Array(old) => {
new_value.resolve_type(&vec![old[index].to_type()])?;
new_value.resolve_type(&vec![old[index].to_type()], span.clone())?;
let selected_value =
ConstrainedValue::conditionally_select(cs, &condition, &new_value, &old[index]).map_err(
@ -144,7 +144,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
return Err(StatementError::immutable_circuit_function("static".into(), span));
}
_ => {
new_value.resolve_type(&vec![object.1.to_type()])?;
new_value.resolve_type(&vec![object.1.to_type()], span.clone())?;
let selected_value =
ConstrainedValue::conditionally_select(cs, &condition, &new_value, &object.1).map_err(
@ -185,7 +185,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Assignee::Identifier(_identifier) => {
let condition = indicator.unwrap_or(Boolean::Constant(true));
let old_value = self.get_mutable_assignee(variable_name.clone(), span.clone())?;
new_value.resolve_type(&vec![old_value.to_type()])?;
new_value.resolve_type(&vec![old_value.to_type()], span.clone())?;
let selected_value = ConstrainedValue::conditionally_select(cs, &condition, &new_value, old_value)
.map_err(|_| StatementError::select_fail(new_value.to_string(), old_value.to_string(), span))?;
@ -325,6 +325,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
function_scope.clone(),
&expected_types,
expression,
span.clone(),
)?;
returns.push(result);
@ -556,7 +557,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
}
Statement::AssertEq(left, right, span) => {
let (resolved_left, resolved_right) =
self.enforce_binary_expression(cs, file_scope, function_scope, &vec![], left, right)?;
self.enforce_binary_expression(cs, file_scope, function_scope, &vec![], left, right, span.clone())?;
self.enforce_assert_eq_statement(cs, indicator, &resolved_left, &resolved_right, span)?;
}

View File

@ -43,13 +43,13 @@ pub enum ConstrainedValue<F: Field + PrimeField, G: GroupType<F>> {
}
impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
pub(crate) fn from_other(value: String, other: &ConstrainedValue<F, G>) -> Result<Self, ValueError> {
pub(crate) fn from_other(value: String, other: &ConstrainedValue<F, G>, span: Span) -> Result<Self, ValueError> {
let other_type = other.to_type();
ConstrainedValue::from_type(value, &other_type)
ConstrainedValue::from_type(value, &other_type, span)
}
pub(crate) fn from_type(value: String, _type: &Type) -> Result<Self, ValueError> {
pub(crate) fn from_type(value: String, _type: &Type, span: Span) -> Result<Self, ValueError> {
match _type {
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(match integer_type {
IntegerType::U8 => Integer::U8(UInt8::constant(value.parse::<u8>()?)),
@ -58,10 +58,10 @@ 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::Field => Ok(ConstrainedValue::Field(FieldType::constant(value)?)),
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
Type::Group => Ok(ConstrainedValue::Group(G::constant(value)?)),
Type::Boolean => Ok(ConstrainedValue::Boolean(Boolean::Constant(value.parse::<bool>()?))),
Type::Array(ref _type, _dimensions) => ConstrainedValue::from_type(value, _type),
Type::Array(ref _type, _dimensions) => ConstrainedValue::from_type(value, _type, span),
_ => Ok(ConstrainedValue::Unresolved(value)),
}
}
@ -76,10 +76,10 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
}
}
pub(crate) fn resolve_type(&mut self, types: &Vec<Type>) -> Result<(), ValueError> {
pub(crate) fn resolve_type(&mut self, types: &Vec<Type>, span: Span) -> Result<(), ValueError> {
if let ConstrainedValue::Unresolved(ref string) = self {
if !types.is_empty() {
*self = ConstrainedValue::from_type(string.clone(), &types[0])?
*self = ConstrainedValue::from_type(string.clone(), &types[0], span)?
}
}
@ -87,16 +87,16 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
}
/// Expect both `self` and `other` to resolve to the same type
pub(crate) fn resolve_types(&mut self, other: &mut Self, types: &Vec<Type>) -> Result<(), ValueError> {
pub(crate) fn resolve_types(&mut self, other: &mut Self, types: &Vec<Type>, span: Span) -> Result<(), ValueError> {
if !types.is_empty() {
self.resolve_type(types)?;
return other.resolve_type(types);
self.resolve_type(types, span.clone())?;
return other.resolve_type(types, span);
}
match (&self, &other) {
(ConstrainedValue::Unresolved(_), ConstrainedValue::Unresolved(_)) => Ok(()),
(ConstrainedValue::Unresolved(_), _) => self.resolve_type(&vec![other.to_type()]),
(_, ConstrainedValue::Unresolved(_)) => other.resolve_type(&vec![self.to_type()]),
(ConstrainedValue::Unresolved(_), _) => self.resolve_type(&vec![other.to_type()], span),
(_, ConstrainedValue::Unresolved(_)) => other.resolve_type(&vec![self.to_type()], span),
_ => Ok(()),
}
}

View File

@ -1,13 +1,44 @@
use leo_types::{Error as FormattedError, Span};
use snarkos_errors::gadgets::SynthesisError;
#[derive(Debug, Error)]
pub enum FieldError {
#[error("Expected field element parameter, got {}", _0)]
Invalid(String),
#[error("No multiplicative inverse found for field {}", _0)]
NoInverse(String),
#[error("{}", _0)]
Error(#[from] FormattedError),
#[error("{}", _0)]
SynthesisError(#[from] SynthesisError),
}
impl FieldError {
fn new_from_span(message: String, span: Span) -> Self {
FieldError::Error(FormattedError::new_from_span(message, span))
}
pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self {
let message = format!(
"the field binary operation `{}` failed due to synthesis error `{}`",
operation, error,
);
Self::new_from_span(message, span)
}
pub fn invalid_field(actual: String, span: Span) -> Self {
let message = format!("expected field element input type, found `{}`", actual);
Self::new_from_span(message, span)
}
pub fn missing_field(expected: String, span: Span) -> Self {
let message = format!("expected integer input `{}` not found", expected);
Self::new_from_span(message, span)
}
pub fn no_inverse(field: String, span: Span) -> Self {
let message = format!("no multiplicative inverse found for field `{}`", field);
Self::new_from_span(message, span)
}
}

View File

@ -1,6 +1,7 @@
//! A data type that represents a field value
use crate::errors::FieldError;
use leo_types::Span;
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
@ -35,82 +36,100 @@ impl<F: Field + PrimeField> FieldType<F> {
}
}
pub fn constant(string: String) -> Result<Self, FieldError> {
let value = F::from_str(&string).map_err(|_| FieldError::Invalid(string))?;
pub fn constant(string: String, span: Span) -> Result<Self, FieldError> {
let value = F::from_str(&string).map_err(|_| FieldError::invalid_field(string, span))?;
Ok(FieldType::Constant(value))
}
pub fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, FieldError> {
pub fn add<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
match (self, other) {
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
Ok(FieldType::Constant(self_value.add(other_value)))
}
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value.add(cs, other_value)?;
Ok(FieldType::Allocated(result))
}
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => {
Ok(FieldType::Allocated(allocated_value.add_constant(cs, constant_value)?))
}
}
}
pub fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, FieldError> {
match (self, other) {
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
Ok(FieldType::Constant(self_value.sub(other_value)))
}
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value.sub(cs, other_value)?;
Ok(FieldType::Allocated(result))
}
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => {
Ok(FieldType::Allocated(allocated_value.sub_constant(cs, constant_value)?))
}
}
}
pub fn mul<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self) -> Result<Self, FieldError> {
match (self, other) {
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
Ok(FieldType::Constant(self_value.mul(other_value)))
}
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value.mul(cs, other_value)?;
let result = self_value
.add(cs, other_value)
.map_err(|e| FieldError::cannot_enforce(format!("+"), e, span))?;
Ok(FieldType::Allocated(result))
}
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
allocated_value.mul_by_constant(cs, constant_value)?,
allocated_value
.add_constant(cs, constant_value)
.map_err(|e| FieldError::cannot_enforce(format!("+"), e, span))?,
)),
}
}
pub fn div<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Self, FieldError> {
pub fn sub<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
match (self, other) {
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
Ok(FieldType::Constant(self_value.sub(other_value)))
}
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value
.sub(cs, other_value)
.map_err(|e| FieldError::cannot_enforce(format!("-"), e, span))?;
Ok(FieldType::Allocated(result))
}
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
allocated_value
.sub_constant(cs, constant_value)
.map_err(|e| FieldError::cannot_enforce(format!("+"), e, span))?,
)),
}
}
pub fn mul<CS: ConstraintSystem<F>>(&self, cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
match (self, other) {
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
Ok(FieldType::Constant(self_value.mul(other_value)))
}
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
let result = self_value
.mul(cs, other_value)
.map_err(|e| FieldError::cannot_enforce(format!("*"), e, span))?;
Ok(FieldType::Allocated(result))
}
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(FieldType::Allocated(
allocated_value
.mul_by_constant(cs, constant_value)
.map_err(|e| FieldError::cannot_enforce(format!("*"), e, span))?,
)),
}
}
pub fn div<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self, span: Span) -> Result<Self, FieldError> {
let inverse = match other {
FieldType::Constant(constant) => {
let constant_inverse = constant.inverse().ok_or(FieldError::NoInverse(constant.to_string()))?;
let constant_inverse = constant
.inverse()
.ok_or(FieldError::no_inverse(constant.to_string(), span.clone()))?;
FieldType::Constant(constant_inverse)
}
FieldType::Allocated(allocated) => {
let allocated_inverse = allocated.inverse(&mut cs)?;
let allocated_inverse = allocated
.inverse(&mut cs)
.map_err(|e| FieldError::cannot_enforce(format!("+"), e, span.clone()))?;
FieldType::Allocated(allocated_inverse)
}
};
self.mul(cs, &inverse)
self.mul(cs, &inverse, span)
}
pub fn alloc_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>>(

View File

@ -54,18 +54,11 @@ fn output_one(program: EdwardsTestCompiler) {
fn fail_field(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::FieldError(FieldError::Invalid(_string))) => {}
CompilerError::FunctionError(FunctionError::FieldError(FieldError::Error(_string))) => {}
error => panic!("Expected invalid field error, got {}", error),
}
}
fn fail_synthesis(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::FieldError(FieldError::SynthesisError(_string))) => {}
error => panic!("Expected synthesis error, got {}", error),
}
}
#[test]
fn test_zero() {
let bytes = include_bytes!("zero.leo");
@ -110,7 +103,7 @@ fn test_input_fail_none() {
let mut program = parse_program(bytes).unwrap();
program.set_inputs(vec![None]);
fail_synthesis(program);
fail_field(program);
}
#[test]

View File

@ -16,12 +16,12 @@ impl<'ast> From<AstRangeOrExpression<'ast>> for RangeOrExpression {
AstRangeOrExpression::Range(range) => {
let from = range.from.map(|from| match Expression::from(from.0) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
Expression::Implicit(string, _span) => Integer::from_implicit(string),
expression => unimplemented!("Range bounds should be integers, found {}", expression),
});
let to = range.to.map(|to| match Expression::from(to.0) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
Expression::Implicit(string, _span) => Integer::from_implicit(string),
expression => unimplemented!("Range bounds should be integers, found {}", expression),
});

View File

@ -28,10 +28,10 @@ pub enum Expression {
// Values
Integer(Integer),
Field(String),
Group(String),
Field(String, Span),
Group(String, Span),
Boolean(Boolean),
Implicit(String),
Implicit(String, Span),
// Number operations
Add(Box<Expression>, Box<Expression>, Span),
@ -69,6 +69,9 @@ pub enum Expression {
impl Expression {
pub fn set_span(&mut self, new_span: &Span) {
match self {
Expression::Field(_, old_span) => *old_span = new_span.clone(),
Expression::Group(_, old_span) => *old_span = new_span.clone(),
Expression::Add(_, _, old_span) => *old_span = new_span.clone(),
Expression::Sub(_, _, old_span) => *old_span = new_span.clone(),
Expression::Mul(_, _, old_span) => *old_span = new_span.clone(),
@ -119,10 +122,10 @@ impl<'ast> fmt::Display for Expression {
// Values
Expression::Integer(ref integer) => write!(f, "{}", integer),
Expression::Field(ref field) => write!(f, "{}", field),
Expression::Group(ref group) => write!(f, "{}", group),
Expression::Field(ref field, ref _span) => write!(f, "{}", field),
Expression::Group(ref group, ref _span) => write!(f, "{}", group),
Expression::Boolean(ref bool) => write!(f, "{}", bool.get_value().unwrap()),
Expression::Implicit(ref value) => write!(f, "{}", value),
Expression::Implicit(ref value, ref _span) => write!(f, "{}", value),
// Number operations
Expression::Add(ref left, ref right, ref _span) => write!(f, "{} + {}", left, right),
@ -413,13 +416,13 @@ impl<'ast> From<NotExpression<'ast>> for Expression {
impl<'ast> From<FieldValue<'ast>> for Expression {
fn from(field: FieldValue<'ast>) -> Self {
Expression::Field(field.number.value)
Expression::Field(field.number.value, Span::from(field.span))
}
}
impl<'ast> From<GroupValue<'ast>> for Expression {
fn from(group: GroupValue<'ast>) -> Self {
Expression::Group(group.to_string())
Expression::Group(group.to_string(), Span::from(group.span))
}
}
@ -433,7 +436,7 @@ impl<'ast> From<BooleanValue<'ast>> for Expression {
impl<'ast> From<NumberImplicitValue<'ast>> for Expression {
fn from(number: NumberImplicitValue<'ast>) -> Self {
Expression::Implicit(number.number.value)
Expression::Implicit(number.number.value, Span::from(number.span))
}
}

View File

@ -392,7 +392,7 @@ impl Integer {
Ok(match (self, other) {
(Integer::U8(left_u8), Integer::U8(right_u8)) => {
let unique_namespace = format!(
"enforce {} / {} {}:{}",
"enforce {} ÷ {} {}:{}",
left_u8.value.unwrap(),
right_u8.value.unwrap(),
span.line,
@ -404,7 +404,7 @@ impl Integer {
}
(Integer::U16(left_u16), Integer::U16(right_u16)) => {
let unique_namespace = format!(
"enforce {} / {} {}:{}",
"enforce {} ÷ {} {}:{}",
left_u16.value.unwrap(),
right_u16.value.unwrap(),
span.line,
@ -416,7 +416,7 @@ impl Integer {
}
(Integer::U32(left_u32), Integer::U32(right_u32)) => {
let unique_namespace = format!(
"enforce {} / {} {}:{}",
"enforce {} ÷ {} {}:{}",
left_u32.value.unwrap(),
right_u32.value.unwrap(),
span.line,
@ -428,7 +428,7 @@ impl Integer {
}
(Integer::U64(left_u64), Integer::U64(right_u64)) => {
let unique_namespace = format!(
"enforce {} / {} {}:{}",
"enforce {} ÷ {} {}:{}",
left_u64.value.unwrap(),
right_u64.value.unwrap(),
span.line,
@ -440,7 +440,7 @@ impl Integer {
}
(Integer::U128(left_u128), Integer::U128(right_u128)) => {
let unique_namespace = format!(
"enforce {} / {} {}:{}",
"enforce {} ÷ {} {}:{}",
left_u128.value.unwrap(),
right_u128.value.unwrap(),
span.line,

View File

@ -151,12 +151,12 @@ impl<'ast> From<ForStatement<'ast>> for Statement {
fn from(statement: ForStatement<'ast>) -> Self {
let from = match Expression::from(statement.start) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
Expression::Implicit(string, _span) => Integer::from_implicit(string),
expression => unimplemented!("Range bounds should be integers, found {}", expression),
};
let to = match Expression::from(statement.stop) {
Expression::Integer(number) => number,
Expression::Implicit(string) => Integer::from_implicit(string),
Expression::Implicit(string, _span) => Integer::from_implicit(string),
expression => unimplemented!("Range bounds should be integers, found {}", expression),
};