impl new group notation compiler

This commit is contained in:
collin 2020-08-15 16:20:43 -07:00
parent 60bf079e33
commit 3fe25da23f
7 changed files with 167 additions and 25 deletions

View File

@ -52,4 +52,34 @@ impl GroupError {
Self::new_from_span(message, span)
}
pub fn x_invalid(x: String, span: Span) -> Self {
let message = format!("invalid x coordinate `{}`", x);
Self::new_from_span(message, span)
}
pub fn y_invalid(y: String, span: Span) -> Self {
let message = format!("invalid y coordinate `{}`", y);
Self::new_from_span(message, span)
}
pub fn not_on_curve(element: String, span: Span) -> Self {
let message = format!("group element `{}` is not on the supported curve", element);
Self::new_from_span(message, span)
}
pub fn x_recover(span: Span) -> Self {
let message = format!("could not recover group element from x coordinate");
Self::new_from_span(message, span)
}
pub fn y_recover(span: Span) -> Self {
let message = format!("could not recover group element from x coordinate");
Self::new_from_span(message, span)
}
}

View File

@ -45,4 +45,10 @@ impl ValueError {
Self::new_from_span(message, span)
}
pub fn implicit_group(span: Span) -> Self {
let message = format!("group coordinates should be in (x, y)group format");
Self::new_from_span(message, span)
}
}

View File

@ -38,7 +38,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedProgram<F, G> {
Expression::Address(address, span) => Ok(ConstrainedValue::Address(Address::new(address, span)?)),
Expression::Boolean(boolean, span) => Ok(ConstrainedValue::Boolean(new_bool_constant(boolean, span)?)),
Expression::Field(field, span) => Ok(ConstrainedValue::Field(FieldType::constant(field, span)?)),
Expression::Group(group_affine, span) => Ok(ConstrainedValue::Group(G::constant(group_affine, span)?)),
Expression::Group(group_affine) => Ok(ConstrainedValue::Group(G::constant(group_affine)?)),
Expression::Implicit(value, span) => Ok(enforce_number_implicit(expected_type, value, span)?),
Expression::Integer(type_, integer, span) => {
Ok(ConstrainedValue::Integer(Integer::new_constant(&type_, integer, span)?))

View File

@ -1,7 +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_typed::Span;
use leo_typed::{GroupValue, Span};
use snarkos_models::{
curves::{Field, One},
@ -32,7 +32,7 @@ pub trait GroupType<F: Field>:
+ ToBitsGadget<F>
+ ToBytesGadget<F>
{
fn constant(string: String, span: Span) -> Result<Self, GroupError>;
fn constant(value: GroupValue) -> Result<Self, GroupError>;
fn to_allocated<CS: ConstraintSystem<F>>(&self, cs: CS, span: Span) -> Result<Self, GroupError>;

View File

@ -1,5 +1,5 @@
use crate::{errors::GroupError, GroupType};
use leo_typed::Span;
use leo_typed::{GroupCoordinate, GroupValue, Span};
use snarkos_curves::{
edwards_bls12::{EdwardsAffine, EdwardsParameters, Fq},
@ -36,14 +36,43 @@ pub enum EdwardsGroupType {
}
impl GroupType<Fq> for EdwardsGroupType {
fn constant(string: String, span: Span) -> Result<Self, GroupError> {
// 1group = generator
if string.eq("1") {
return Ok(Self::one());
}
fn constant(group: GroupValue) -> Result<Self, GroupError> {
let span = group.span;
let x = group.x;
let y = group.y;
let value =
Self::edwards_affine_from_str(string.clone()).map_err(|_| GroupError::invalid_group(string, span))?;
let value = match (x, y) {
// (x, y)
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::Number(y_string, y_span)) => {
Self::edwards_affine_from_pair(x_string, y_string, x_span, y_span, span)?
}
// (x, +)
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::SignHigh) => {
Self::edwards_affine_from_x_str(x_string, x_span, Some(true), span)?
}
// (x, -)
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::SignLow) => {
Self::edwards_affine_from_x_str(x_string, x_span, Some(false), span)?
}
// (x, _)
(GroupCoordinate::Number(x_string, x_span), GroupCoordinate::Inferred) => {
Self::edwards_affine_from_x_str(x_string, x_span, None, span)?
}
// (+, y)
(GroupCoordinate::SignHigh, GroupCoordinate::Number(y_string, y_span)) => {
Self::edwards_affine_from_y_str(y_string, y_span, Some(true), span)?
}
// (-, y)
(GroupCoordinate::SignLow, GroupCoordinate::Number(y_string, y_span)) => {
Self::edwards_affine_from_y_str(y_string, y_span, Some(false), span)?
}
// (_, y)
(GroupCoordinate::Inferred, GroupCoordinate::Number(y_string, y_span)) => {
Self::edwards_affine_from_y_str(y_string, y_span, None, span)?
}
// Invalid
(x, y) => return Err(GroupError::invalid_group(format!("({}, {})", x, y), span)),
};
Ok(EdwardsGroupType::Constant(value))
}
@ -124,8 +153,85 @@ impl GroupType<Fq> for EdwardsGroupType {
}
impl EdwardsGroupType {
pub fn edwards_affine_from_x_str(
x_string: String,
x_span: Span,
greatest: Option<bool>,
element_span: Span,
) -> Result<EdwardsAffine, GroupError> {
let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span))?;
match greatest {
// Sign provided
Some(greatest) => EdwardsAffine::from_x_coordinate(x, greatest).ok_or(GroupError::x_recover(element_span)),
// Sign inferred
None => {
// Attempt to recover with a sign_low bit.
if let Some(element) = EdwardsAffine::from_x_coordinate(x.clone(), false) {
return Ok(element);
}
// Attempt to recover with a sign_high bit.
if let Some(element) = EdwardsAffine::from_x_coordinate(x, true) {
return Ok(element);
}
// Otherwise return error.
Err(GroupError::x_recover(element_span))
}
}
}
pub fn edwards_affine_from_y_str(
y_string: String,
y_span: Span,
_greatest: Option<bool>,
_element_span: Span,
) -> Result<EdwardsAffine, GroupError> {
let _y = Fq::from_str(&y_string).map_err(|_| GroupError::y_invalid(y_string, y_span))?;
unimplemented!("recover from_y_coordinate not implemented for Edwards Affine")
// match greatest {
// // Sign provided
// Some(greatest) => EdwardsAffine::from_y_coordinate(y, greatest).ok_or(GroupError::y_recover(element_span)),
// // Sign inferred
// None => {
// // Attempt to recover with a sign_low bit.
// if let Some(element) = EdwardsAffine::from_y_coordinate(y.clone(), false) {
// return Ok(element);
// }
//
// // Attempt to recover with a sign_high bit.
// if let Some(element) = EdwardsAffine::from_y_coordinate(y, true) {
// return Ok(element);
// }
//
// // Otherwise return error.
// Err(GroupError::y_recover(element_span))
// }
// }
}
pub fn edwards_affine_from_pair(
x_string: String,
y_string: String,
x_span: Span,
y_span: Span,
element_span: Span,
) -> Result<EdwardsAffine, GroupError> {
let x = Fq::from_str(&x_string).map_err(|_| GroupError::x_invalid(x_string, x_span))?;
let y = Fq::from_str(&y_string).map_err(|_| GroupError::y_invalid(y_string, y_span))?;
let element = EdwardsAffine::new(x, y);
if element.is_on_curve() {
Ok(element)
} else {
Err(GroupError::not_on_curve(format!("{}", element), element_span))
}
}
pub fn edwards_affine_from_str(string: String) -> Result<EdwardsAffine, SynthesisError> {
// x or (x, y)
// (x, y)
match Fq::from_str(&string).ok() {
Some(x) => {
// Attempt to recover with a sign_low bit.

View File

@ -69,7 +69,7 @@ impl<F: Field + PrimeField, G: GroupType<F>> ConstrainedValue<F, G> {
Type::Address => Ok(ConstrainedValue::Address(Address::new(value, span)?)),
Type::Boolean => Ok(ConstrainedValue::Boolean(new_bool_constant(value, span)?)),
Type::Field => Ok(ConstrainedValue::Field(FieldType::constant(value, span)?)),
Type::Group => Ok(ConstrainedValue::Group(G::constant(value, span)?)),
Type::Group => Err(ValueError::implicit_group(span)),
Type::IntegerType(integer_type) => Ok(ConstrainedValue::Integer(Integer::new_constant(
integer_type,
value,

View File

@ -13,9 +13,9 @@ use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum GroupCoordinate {
Number(String, Span),
SignHigh(Span),
SignLow(Span),
Inferred(Span),
SignHigh,
SignLow,
Inferred,
}
impl<'ast> From<AstGroupCoordinate<'ast>> for GroupCoordinate {
@ -33,9 +33,9 @@ impl fmt::Display for GroupCoordinate {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GroupCoordinate::Number(number, _) => write!(f, "{}", number),
GroupCoordinate::SignHigh(_) => write!(f, "+"),
GroupCoordinate::SignLow(_) => write!(f, "-"),
GroupCoordinate::Inferred(_) => write!(f, "_"),
GroupCoordinate::SignHigh => write!(f, "+"),
GroupCoordinate::SignLow => write!(f, "-"),
GroupCoordinate::Inferred => write!(f, "_"),
}
}
}
@ -50,19 +50,19 @@ impl<'ast> From<AstNumberValue<'ast>> for GroupCoordinate {
}
impl<'ast> From<AstSignHigh<'ast>> for GroupCoordinate {
fn from(sign: AstSignHigh<'ast>) -> Self {
GroupCoordinate::SignHigh(Span::from(sign.span))
fn from(_sign: AstSignHigh<'ast>) -> Self {
GroupCoordinate::SignHigh
}
}
impl<'ast> From<AstSignLow<'ast>> for GroupCoordinate {
fn from(sign: AstSignLow<'ast>) -> Self {
GroupCoordinate::SignLow(Span::from(sign.span))
fn from(_sign: AstSignLow<'ast>) -> Self {
GroupCoordinate::SignLow
}
}
impl<'ast> From<AstInferred<'ast>> for GroupCoordinate {
fn from(sign: AstInferred<'ast>) -> Self {
GroupCoordinate::Inferred(Span::from(sign.span))
fn from(_sign: AstInferred<'ast>) -> Self {
GroupCoordinate::Inferred
}
}