From 8150869c6c70ebca4ee75e4a2c3118b2d2152b55 Mon Sep 17 00:00:00 2001 From: gluax Date: Tue, 16 Feb 2021 12:00:08 -0500 Subject: [PATCH] negative groups, and negative group coords allowed --- .../src/value/group/targets/edwards_bls12.rs | 100 +++++++++++++----- compiler/tests/group/mod.rs | 9 ++ .../tests/group/positive_and_negative.leo | 10 ++ 3 files changed, 95 insertions(+), 24 deletions(-) create mode 100644 compiler/tests/group/positive_and_negative.leo diff --git a/compiler/src/value/group/targets/edwards_bls12.rs b/compiler/src/value/group/targets/edwards_bls12.rs index 8ff4e4d81e..309ff3aa50 100644 --- a/compiler/src/value/group/targets/edwards_bls12.rs +++ b/compiler/src/value/group/targets/edwards_bls12.rs @@ -133,6 +133,23 @@ impl GroupType for EdwardsGroupType { } } +fn number_string_typing(number: &str, span: &Span) -> Result<(String, bool), GroupError> { + let first_char = number.chars().next().unwrap(); + + // Check if first symbol is a negative. + // If so strip it, parse rest of string and then negate it. + if first_char == '-' { + let uint = number + .chars() + .next() + .map(|c| &number[c.len_utf8()..]) + .ok_or_else(|| GroupError::invalid_group(number.to_string(), span.to_owned()))?; + Ok((uint.to_string(), true)) + } else { + Ok((number.to_string(), false)) + } +} + impl EdwardsGroupType { pub fn edwards_affine_from_value(value: &GroupValue, span: &Span) -> Result { match value { @@ -142,12 +159,19 @@ impl EdwardsGroupType { } pub fn edwards_affine_from_single(number: &str, span: &Span) -> Result { - if number.eq("0") { + let number_info = number_string_typing(number, &span.clone())?; + + if number_info.0.eq("0") { Ok(EdwardsAffine::zero()) } else { let one = edwards_affine_one(); - let number_value = - Fp256::from_str(&number).map_err(|_| GroupError::n_group(number.to_string(), span.clone()))?; + let number_value = match number_info { + (number, neg) if neg => { + -Fp256::from_str(&number).map_err(|_| GroupError::n_group(number, span.clone()))? + } + (number, _) => Fp256::from_str(&number).map_err(|_| GroupError::n_group(number, span.clone()))?, + }; + let result: EdwardsAffine = one.mul(&number_value); Ok(result) @@ -164,32 +188,42 @@ impl EdwardsGroupType { match (x, y) { // (x, y) - (GroupCoordinate::Number(x_string), GroupCoordinate::Number(y_string)) => { - Self::edwards_affine_from_pair(x_string, y_string, span, span, span) - } + (GroupCoordinate::Number(x_string), GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_pair( + number_string_typing(&x_string, &span.clone())?, + number_string_typing(&y_string, &span.clone())?, + span, + span, + span, + ), // (x, +) (GroupCoordinate::Number(x_string), GroupCoordinate::SignHigh) => { - Self::edwards_affine_from_x_str(x_string, span, Some(true), span) + Self::edwards_affine_from_x_str(number_string_typing(&x_string, &span.clone())?, span, Some(true), span) } // (x, -) - (GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => { - Self::edwards_affine_from_x_str(x_string, span, Some(false), span) - } + (GroupCoordinate::Number(x_string), GroupCoordinate::SignLow) => Self::edwards_affine_from_x_str( + number_string_typing(&x_string, &span.clone())?, + span, + Some(false), + span, + ), // (x, _) (GroupCoordinate::Number(x_string), GroupCoordinate::Inferred) => { - Self::edwards_affine_from_x_str(x_string, span, None, span) + Self::edwards_affine_from_x_str(number_string_typing(&x_string, &span.clone())?, span, None, span) } // (+, y) (GroupCoordinate::SignHigh, GroupCoordinate::Number(y_string)) => { - Self::edwards_affine_from_y_str(y_string, span, Some(true), span) + Self::edwards_affine_from_y_str(number_string_typing(&y_string, &span.clone())?, span, Some(true), span) } // (-, y) - (GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => { - Self::edwards_affine_from_y_str(y_string, span, Some(false), span) - } + (GroupCoordinate::SignLow, GroupCoordinate::Number(y_string)) => Self::edwards_affine_from_y_str( + number_string_typing(&y_string, &span.clone())?, + span, + Some(false), + span, + ), // (_, y) (GroupCoordinate::Inferred, GroupCoordinate::Number(y_string)) => { - Self::edwards_affine_from_y_str(y_string, span, None, span) + Self::edwards_affine_from_y_str(number_string_typing(&y_string, &span.clone())?, span, None, span) } // Invalid (x, y) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span.clone())), @@ -197,12 +231,16 @@ impl EdwardsGroupType { } pub fn edwards_affine_from_x_str( - x_string: String, + x_info: (String, bool), x_span: &Span, greatest: Option, element_span: &Span, ) -> Result { - let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span.clone()))?; + let x = match x_info { + (x_str, neg) if neg => -Fq::from_str(&x_str).map_err(|_| GroupError::x_invalid(x_str, x_span.clone()))?, + (x_str, _) => Fq::from_str(&x_str).map_err(|_| GroupError::x_invalid(x_str, x_span.clone()))?, + }; + match greatest { // Sign provided Some(greatest) => { @@ -227,12 +265,15 @@ impl EdwardsGroupType { } pub fn edwards_affine_from_y_str( - y_string: String, + y_info: (String, bool), y_span: &Span, greatest: Option, element_span: &Span, ) -> Result { - let y = Fq::from_str(&y_string).map_err(|_| GroupError::y_invalid(y_string, y_span.clone()))?; + let y = match y_info { + (y_str, neg) if neg => -Fq::from_str(&y_str).map_err(|_| GroupError::y_invalid(y_str, y_span.clone()))?, + (y_str, _) => Fq::from_str(&y_str).map_err(|_| GroupError::y_invalid(y_str, y_span.clone()))?, + }; match greatest { // Sign provided @@ -258,14 +299,25 @@ impl EdwardsGroupType { } pub fn edwards_affine_from_pair( - x_string: String, - y_string: String, + x_info: (String, bool), + y_info: (String, bool), x_span: &Span, y_span: &Span, element_span: &Span, ) -> Result { - let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span.clone()))?; - let y = Fq::from_str(&y_string).map_err(|_| GroupError::y_invalid(y_string, y_span.clone()))?; + let x = match x_info { + (x_str, neg) if neg => { + -Fq::from_str(&x_str).map_err(|_| GroupError::x_invalid(x_str.to_string(), x_span.clone()))? + } + (x_str, _) => Fq::from_str(&x_str).map_err(|_| GroupError::x_invalid(x_str.to_string(), x_span.clone()))?, + }; + + let y = match y_info { + (y_str, neg) if neg => { + -Fq::from_str(&y_str).map_err(|_| GroupError::y_invalid(y_str.to_string(), y_span.clone()))? + } + (y_str, _) => Fq::from_str(&y_str).map_err(|_| GroupError::y_invalid(y_str.to_string(), y_span.clone()))?, + }; let element = EdwardsAffine::new(x, y); diff --git a/compiler/tests/group/mod.rs b/compiler/tests/group/mod.rs index 65680f0b14..d7fca2a4cd 100644 --- a/compiler/tests/group/mod.rs +++ b/compiler/tests/group/mod.rs @@ -388,3 +388,12 @@ fn test_ternary() { assert_satisfied(program); } + +#[test] +fn test_positive_and_negative() { + let program_string = include_str!("positive_and_negative.leo"); + + let program = parse_program(program_string).unwrap(); + + assert_satisfied(program); +} diff --git a/compiler/tests/group/positive_and_negative.leo b/compiler/tests/group/positive_and_negative.leo new file mode 100644 index 0000000000..fdf9b892be --- /dev/null +++ b/compiler/tests/group/positive_and_negative.leo @@ -0,0 +1,10 @@ +function main() { + let pos_element = 1group; + let neg_element = -1group; + + let pair_x_pos = (1, _)group; + let pair_x_neg = (-1, _)group; + + let pair_y_pos = (_, 1)group; + let pair_y_neg = (_, -1)group; +} \ No newline at end of file