diff --git a/compiler/src/constraints/expression.rs b/compiler/src/constraints/expression.rs index fc41ccd52f..46c2a9ca03 100644 --- a/compiler/src/constraints/expression.rs +++ b/compiler/src/constraints/expression.rs @@ -72,7 +72,7 @@ impl> ConstrainedProgram { 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)?)) + Ok(ConstrainedValue::Group(ge_1.add(cs, &ge_2, span)?)) } (ConstrainedValue::Unresolved(string), val_2) => { let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?; @@ -104,7 +104,7 @@ impl> ConstrainedProgram { 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)?)) + Ok(ConstrainedValue::Group(ge_1.sub(cs, &ge_2, span)?)) } (ConstrainedValue::Unresolved(string), val_2) => { let val_1 = ConstrainedValue::from_other(string, &val_2, span.clone())?; @@ -867,7 +867,7 @@ impl> ConstrainedProgram { // Values Expression::Integer(integer) => Ok(ConstrainedValue::Integer(integer)), Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)), - Expression::Group(group_affine, _span) => Ok(ConstrainedValue::Group(G::constant(group_affine)?)), + Expression::Group(group_affine, span) => Ok(ConstrainedValue::Group(G::constant(group_affine, span)?)), Expression::Boolean(bool) => Ok(ConstrainedValue::Boolean(bool)), Expression::Implicit(value, span) => Self::enforce_number_implicit(expected_types, value, span), diff --git a/compiler/src/constraints/function.rs b/compiler/src/constraints/function.rs index f1147034a7..b0fc164fab 100644 --- a/compiler/src/constraints/function.rs +++ b/compiler/src/constraints/function.rs @@ -172,7 +172,7 @@ impl> ConstrainedProgram { span, )?)), Type::Field => Ok(field_from_input(cs, name, input_value, span)?), - Type::Group => Ok(group_from_input(cs, name, input_value)?), + Type::Group => Ok(group_from_input(cs, name, input_value, span)?), 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), _ => unimplemented!("main function input not implemented for type"), diff --git a/compiler/src/constraints/group.rs b/compiler/src/constraints/group.rs index 93c90d0f71..aaf3f4d29c 100644 --- a/compiler/src/constraints/group.rs +++ b/compiler/src/constraints/group.rs @@ -1,5 +1,5 @@ use crate::{errors::GroupError, ConstrainedValue, GroupType}; -use leo_types::InputValue; +use leo_types::{InputValue, Span}; use snarkos_errors::gadgets::SynthesisError; use snarkos_models::{ @@ -11,6 +11,7 @@ pub(crate) fn group_from_input, CS: Const cs: &mut CS, name: String, input_value: Option, + span: Span, ) -> Result, GroupError> { // Check that the parameter value is the correct type let group_option = match input_value { @@ -18,13 +19,18 @@ pub(crate) fn group_from_input, CS: Const if let InputValue::Group(string) = input { Some(string) } else { - return Err(GroupError::Invalid(input.to_string())); + return Err(GroupError::invalid_group(input.to_string(), span)); } } None => None, }; - let group_value = G::alloc(cs.ns(|| name), || group_option.ok_or(SynthesisError::AssignmentMissing))?; + let group_name = format!("{}: group", name); + let group_name_unique = format!("`{}` {}:{}", group_name, span.line, span.start); + let group_value = G::alloc(cs.ns(|| group_name_unique), || { + group_option.ok_or(SynthesisError::AssignmentMissing) + }) + .map_err(|_| GroupError::missing_group(group_name, span))?; Ok(ConstrainedValue::Group(group_value)) } diff --git a/compiler/src/constraints/value.rs b/compiler/src/constraints/value.rs index 0ef6dcde1a..dd93dac19a 100644 --- a/compiler/src/constraints/value.rs +++ b/compiler/src/constraints/value.rs @@ -59,7 +59,7 @@ impl> ConstrainedValue { IntegerType::U128 => Integer::U128(UInt128::constant(value.parse::()?)), })), Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)), - Type::Group => Ok(ConstrainedValue::Group(G::constant(value)?)), + Type::Group => Ok(ConstrainedValue::Group(G::constant(value, span)?)), Type::Boolean => Ok(ConstrainedValue::Boolean(Boolean::Constant(value.parse::()?))), Type::Array(ref _type, _dimensions) => ConstrainedValue::from_type(value, _type, span), _ => Ok(ConstrainedValue::Unresolved(value)), diff --git a/compiler/src/errors/constraints/field.rs b/compiler/src/errors/constraints/field.rs index 8e55965c91..7bd7dc03bd 100644 --- a/compiler/src/errors/constraints/field.rs +++ b/compiler/src/errors/constraints/field.rs @@ -1,4 +1,5 @@ use leo_types::{Error as FormattedError, Span}; + use snarkos_errors::gadgets::SynthesisError; #[derive(Debug, Error)] diff --git a/compiler/src/errors/constraints/group.rs b/compiler/src/errors/constraints/group.rs index fc84a62e37..f9b0411d5f 100644 --- a/compiler/src/errors/constraints/group.rs +++ b/compiler/src/errors/constraints/group.rs @@ -1,10 +1,39 @@ +use leo_types::{Error as FormattedError, Span}; + use snarkos_errors::gadgets::SynthesisError; #[derive(Debug, Error)] pub enum GroupError { - #[error("Expected affine point, got {}", _0)] - Invalid(String), + #[error("{}", _0)] + Error(#[from] FormattedError), #[error("{}", _0)] SynthesisError(#[from] SynthesisError), } + +impl GroupError { + fn new_from_span(message: String, span: Span) -> Self { + GroupError::Error(FormattedError::new_from_span(message, span)) + } + + pub fn cannot_enforce(operation: String, error: SynthesisError, span: Span) -> Self { + let message = format!( + "the group binary operation `{}` failed due to the synthesis error `{}`", + operation, error, + ); + + Self::new_from_span(message, span) + } + + pub fn invalid_group(actual: String, span: Span) -> Self { + let message = format!("expected group affine point input type, found `{}`", actual); + + Self::new_from_span(message, span) + } + + pub fn missing_group(expected: String, span: Span) -> Self { + let message = format!("expected group input `{}` not found", expected); + + Self::new_from_span(message, span) + } +} diff --git a/compiler/src/group/edwards_bls12.rs b/compiler/src/group/edwards_bls12.rs index 34ad793900..c6467639e4 100644 --- a/compiler/src/group/edwards_bls12.rs +++ b/compiler/src/group/edwards_bls12.rs @@ -1,4 +1,5 @@ use crate::{errors::GroupError, GroupType}; +use leo_types::Span; use snarkos_curves::{ edwards_bls12::{EdwardsAffine, EdwardsParameters, Fq}, @@ -31,13 +32,14 @@ pub enum EdwardsGroupType { } impl GroupType for EdwardsGroupType { - fn constant(string: String) -> Result { - let value = Self::edwards_affine_from_str(string)?; + fn constant(string: String, span: Span) -> Result { + let value = + Self::edwards_affine_from_str(string.clone()).map_err(|_| GroupError::invalid_group(string, span))?; Ok(EdwardsGroupType::Constant(value)) } - fn add>(&self, cs: CS, other: &Self) -> Result { + fn add>(&self, cs: CS, other: &Self, span: Span) -> Result { match (self, other) { (EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => { Ok(EdwardsGroupType::Constant(self_value.add(other_value))) @@ -48,18 +50,24 @@ impl GroupType for EdwardsGroupType { self_value, cs, other_value, - )?; + ) + .map_err(|e| GroupError::cannot_enforce(format!("+"), e, span))?; + Ok(EdwardsGroupType::Allocated(result)) } (EdwardsGroupType::Constant(constant_value), EdwardsGroupType::Allocated(allocated_value)) - | (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => Ok( - EdwardsGroupType::Allocated(allocated_value.add_constant(cs, constant_value)?), - ), + | (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => { + Ok(EdwardsGroupType::Allocated( + allocated_value + .add_constant(cs, constant_value) + .map_err(|e| GroupError::cannot_enforce(format!("+"), e, span))?, + )) + } } } - fn sub>(&self, cs: CS, other: &Self) -> Result { + fn sub>(&self, cs: CS, other: &Self, span: Span) -> Result { match (self, other) { (EdwardsGroupType::Constant(self_value), EdwardsGroupType::Constant(other_value)) => { Ok(EdwardsGroupType::Constant(self_value.sub(other_value))) @@ -70,24 +78,30 @@ impl GroupType for EdwardsGroupType { self_value, cs, other_value, - )?; + ) + .map_err(|e| GroupError::cannot_enforce(format!("-"), e, span))?; + Ok(EdwardsGroupType::Allocated(result)) } (EdwardsGroupType::Constant(constant_value), EdwardsGroupType::Allocated(allocated_value)) - | (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => Ok( - EdwardsGroupType::Allocated(allocated_value.sub_constant(cs, constant_value)?), - ), + | (EdwardsGroupType::Allocated(allocated_value), EdwardsGroupType::Constant(constant_value)) => { + Ok(EdwardsGroupType::Allocated( + allocated_value + .sub_constant(cs, constant_value) + .map_err(|e| GroupError::cannot_enforce(format!("-"), e, span))?, + )) + } } } } impl EdwardsGroupType { - pub fn edwards_affine_from_str(string: String) -> Result { + pub fn edwards_affine_from_str(string: String) -> Result { // 0 or (0, 1) match Fq::from_str(&string).ok() { - Some(x) => EdwardsAffine::get_point_from_x(x, false).ok_or(GroupError::Invalid(string)), - None => EdwardsAffine::from_str(&string).map_err(|_| GroupError::Invalid(string)), + Some(x) => EdwardsAffine::get_point_from_x(x, false).ok_or(SynthesisError::AssignmentMissing), + None => EdwardsAffine::from_str(&string).map_err(|_| SynthesisError::AssignmentMissing), } } @@ -102,7 +116,7 @@ impl EdwardsGroupType { _ => Err(SynthesisError::AssignmentMissing), }?; - Self::edwards_affine_from_str(affine_string).map_err(|_| SynthesisError::AssignmentMissing) + Self::edwards_affine_from_str(affine_string) } pub fn allocated>(&self, mut cs: CS) -> Result { diff --git a/compiler/src/group/mod.rs b/compiler/src/group/mod.rs index 6af5532570..5ff7c8aefb 100644 --- a/compiler/src/group/mod.rs +++ b/compiler/src/group/mod.rs @@ -1,6 +1,7 @@ //! A data type that represents members in the group formed by the set of affine points on a curve. use crate::errors::GroupError; +use leo_types::Span; use snarkos_models::{ curves::Field, @@ -32,9 +33,9 @@ pub trait GroupType: + ToBitsGadget + ToBytesGadget { - fn constant(string: String) -> Result; + fn constant(string: String, span: Span) -> Result; - fn add>(&self, cs: CS, other: &Self) -> Result; + fn add>(&self, cs: CS, other: &Self, span: Span) -> Result; - fn sub>(&self, cs: CS, other: &Self) -> Result; + fn sub>(&self, cs: CS, other: &Self, span: Span) -> Result; }