impl new group notation for inputs compiler

This commit is contained in:
collin 2020-08-15 17:21:18 -07:00
parent 172431c222
commit a4b29d2651
9 changed files with 118 additions and 124 deletions

View File

@ -27,7 +27,7 @@ pub trait GroupType<F: Field>:
+ EvaluateEqGadget<F>
+ EqGadget<F>
+ ConditionalEqGadget<F>
+ AllocGadget<String, F>
+ AllocGadget<GroupValue, F>
+ CondSelectGadget<F>
+ ToBitsGadget<F>
+ ToBytesGadget<F>

View File

@ -1,7 +1,7 @@
//! Methods to enforce constraints on input group values in a Leo program.
use crate::{errors::GroupError, ConstrainedValue, GroupType};
use leo_typed::{InputValue, Span};
use leo_typed::{GroupValue, InputValue, Span};
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::{
@ -12,7 +12,7 @@ use snarkos_models::{
pub(crate) fn allocate_group<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>>(
cs: &mut CS,
name: String,
option: Option<String>,
option: Option<GroupValue>,
span: Span,
) -> Result<G, GroupError> {
let group_name = format!("{}: group", name);

View File

@ -37,42 +37,7 @@ pub enum EdwardsGroupType {
impl GroupType<Fq> for EdwardsGroupType {
fn constant(group: GroupValue) -> Result<Self, GroupError> {
let span = group.span;
let x = group.x;
let y = group.y;
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)),
};
let value = Self::edwards_affine_from_value(group)?;
Ok(EdwardsGroupType::Constant(value))
}
@ -153,6 +118,45 @@ impl GroupType<Fq> for EdwardsGroupType {
}
impl EdwardsGroupType {
pub fn edwards_affine_from_value(group: GroupValue) -> Result<EdwardsAffine, GroupError> {
let span = group.span;
let x = group.x;
let y = group.y;
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) => Err(GroupError::invalid_group(format!("({}, {})", x, y), span)),
}
}
pub fn edwards_affine_from_x_str(
x_string: String,
x_span: Span,
@ -230,44 +234,18 @@ impl EdwardsGroupType {
}
}
pub fn edwards_affine_from_str(string: String) -> Result<EdwardsAffine, SynthesisError> {
// (x, y)
match Fq::from_str(&string).ok() {
Some(x) => {
// 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(SynthesisError::AssignmentMissing)
}
None => EdwardsAffine::from_str(&string).map_err(|_| SynthesisError::AssignmentMissing),
}
}
pub fn alloc_x_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>>(
pub fn alloc_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>>(
value_gen: Fn,
) -> Result<EdwardsAffine, SynthesisError> {
let affine_string = match value_gen() {
let group_value = match value_gen() {
Ok(value) => {
let string_value = value.borrow().clone();
Ok(string_value)
let group_value = value.borrow().clone();
Ok(group_value)
}
_ => Err(SynthesisError::AssignmentMissing),
}?;
// 1group = generator
if affine_string.eq("1") {
Ok(edwards_affine_one())
} else {
Self::edwards_affine_from_str(affine_string)
}
Self::edwards_affine_from_value(group_value).map_err(|_| SynthesisError::AssignmentMissing)
}
pub fn allocated<CS: ConstraintSystem<Fq>>(&self, mut cs: CS) -> Result<EdwardsBlsGadget, SynthesisError> {
@ -295,24 +273,24 @@ impl EdwardsGroupType {
}
}
impl AllocGadget<String, Fq> for EdwardsGroupType {
fn alloc<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>, CS: ConstraintSystem<Fq>>(
impl AllocGadget<GroupValue, Fq> for EdwardsGroupType {
fn alloc<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>, CS: ConstraintSystem<Fq>>(
cs: CS,
value_gen: Fn,
) -> Result<Self, SynthesisError> {
let value = <EdwardsBlsGadget as AllocGadget<GroupAffine<EdwardsParameters>, Fq>>::alloc(cs, || {
Self::alloc_x_helper(value_gen)
Self::alloc_helper(value_gen)
})?;
Ok(EdwardsGroupType::Allocated(value))
}
fn alloc_input<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>, CS: ConstraintSystem<Fq>>(
fn alloc_input<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<GroupValue>, CS: ConstraintSystem<Fq>>(
cs: CS,
value_gen: Fn,
) -> Result<Self, SynthesisError> {
let value = <EdwardsBlsGadget as AllocGadget<GroupAffine<EdwardsParameters>, Fq>>::alloc_input(cs, || {
Self::alloc_x_helper(value_gen)
Self::alloc_helper(value_gen)
})?;
Ok(EdwardsGroupType::Allocated(value))

View File

@ -0,0 +1,3 @@
[main]
a: group = (1, 0)group;
b: group = (+, +)group;

View File

@ -1,3 +0,0 @@
[main]
a: group = 1;
b: group = 1;

View File

@ -1,3 +0,0 @@
[main]
a: group = 1;
b: group = 0;

View File

@ -0,0 +1,3 @@
[main]
a: group = (0, -)group;
b: group = (0, _)group;

View File

@ -7,18 +7,31 @@ use crate::{
parse_program,
parse_program_with_input,
};
use leo_typed::InputValue;
use leo_typed::{GroupCoordinate, GroupValue, InputValue, Span};
use snarkos_curves::edwards_bls12::EdwardsAffine;
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
pub fn group_to_decimal_string(g: EdwardsAffine) -> String {
pub fn group_element_to_input_value(g: EdwardsAffine) -> GroupValue {
let x = field_to_decimal_string(g.x);
let y = field_to_decimal_string(g.y);
format!("({}, {})", x, y)
format!("({}, {})", x, y);
let fake_span = Span {
text: "".to_string(),
line: 0,
start: 0,
end: 0,
};
GroupValue {
x: GroupCoordinate::Number(x, fake_span.clone()),
y: GroupCoordinate::Number(y, fake_span.clone()),
span: fake_span,
}
}
#[test]
@ -117,8 +130,8 @@ fn test_point_input() {
#[test]
fn test_input() {
let program_bytes = include_bytes!("input.leo");
let input_bytes_pass = include_bytes!("input/one_one.in");
let input_bytes_fail = include_bytes!("input/one_zero.in");
let input_bytes_pass = include_bytes!("input/valid.in");
let input_bytes_fail = include_bytes!("input/invalid.in");
let program = parse_program_with_input(program_bytes, input_bytes_pass).unwrap();
@ -126,7 +139,7 @@ fn test_input() {
let program = parse_program_with_input(program_bytes, input_bytes_fail).unwrap();
expect_synthesis_error(program);
expect_compiler_error(program);
}
#[test]
@ -139,15 +152,15 @@ fn test_negate() {
let a: EdwardsAffine = rng.gen();
let b = a.neg();
let a_string = group_to_decimal_string(a);
let b_string = group_to_decimal_string(b);
let a_element = group_element_to_input_value(a);
let b_element = group_element_to_input_value(b);
let bytes = include_bytes!("negate.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string))),
("b", Some(InputValue::Group(b_string))),
("a", Some(InputValue::Group(a_element))),
("b", Some(InputValue::Group(b_element))),
]);
program.set_main_input(main_input);
@ -166,17 +179,17 @@ fn test_add() {
let b: EdwardsAffine = rng.gen();
let c = a.add(&b);
let a_string = group_to_decimal_string(a);
let b_string = group_to_decimal_string(b);
let c_string = group_to_decimal_string(c);
let a_element = group_element_to_input_value(a);
let b_element = group_element_to_input_value(b);
let c_element = group_element_to_input_value(c);
let bytes = include_bytes!("add.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string))),
("b", Some(InputValue::Group(b_string))),
("c", Some(InputValue::Group(c_string))),
("a", Some(InputValue::Group(a_element))),
("b", Some(InputValue::Group(b_element))),
("c", Some(InputValue::Group(c_element))),
]);
program.set_main_input(main_input);
@ -195,17 +208,17 @@ fn test_sub() {
let b: EdwardsAffine = rng.gen();
let c = a.sub(&b);
let a_string = group_to_decimal_string(a);
let b_string = group_to_decimal_string(b);
let c_string = group_to_decimal_string(c);
let a_element = group_element_to_input_value(a);
let b_element = group_element_to_input_value(b);
let c_element = group_element_to_input_value(c);
let bytes = include_bytes!("sub.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string))),
("b", Some(InputValue::Group(b_string))),
("c", Some(InputValue::Group(c_string))),
("a", Some(InputValue::Group(a_element))),
("b", Some(InputValue::Group(b_element))),
("c", Some(InputValue::Group(c_element))),
]);
program.set_main_input(main_input);
@ -220,14 +233,14 @@ fn test_assert_eq_pass() {
for _ in 0..10 {
let a: EdwardsAffine = rng.gen();
let a_string = group_to_decimal_string(a);
let a_element = group_element_to_input_value(a);
let bytes = include_bytes!("assert_eq.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string.clone()))),
("b", Some(InputValue::Group(a_string))),
("a", Some(InputValue::Group(a_element.clone()))),
("b", Some(InputValue::Group(a_element))),
]);
program.set_main_input(main_input);
@ -248,15 +261,15 @@ fn test_assert_eq_fail() {
continue;
}
let a_string = group_to_decimal_string(a);
let b_string = group_to_decimal_string(b);
let a_element = group_element_to_input_value(a);
let b_element = group_element_to_input_value(b);
let bytes = include_bytes!("assert_eq.leo");
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string))),
("b", Some(InputValue::Group(b_string))),
("a", Some(InputValue::Group(a_element))),
("b", Some(InputValue::Group(b_element))),
]);
program.set_main_input(main_input);
@ -274,8 +287,8 @@ fn test_eq() {
let a: EdwardsAffine = rng.gen();
let b: EdwardsAffine = rng.gen();
let a_string = group_to_decimal_string(a);
let b_string = group_to_decimal_string(b);
let a_element = group_element_to_input_value(a);
let b_element = group_element_to_input_value(b);
// test equal
@ -283,8 +296,8 @@ fn test_eq() {
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string.clone()))),
("b", Some(InputValue::Group(a_string.clone()))),
("a", Some(InputValue::Group(a_element.clone()))),
("b", Some(InputValue::Group(a_element.clone()))),
("c", Some(InputValue::Boolean(true))),
]);
@ -299,8 +312,8 @@ fn test_eq() {
let mut program = parse_program(bytes).unwrap();
let main_input = generate_main_input(vec![
("a", Some(InputValue::Group(a_string))),
("b", Some(InputValue::Group(b_string))),
("a", Some(InputValue::Group(a_element))),
("b", Some(InputValue::Group(b_element))),
("c", Some(InputValue::Boolean(c))),
]);
@ -317,8 +330,8 @@ fn test_ternary() {
let a: EdwardsAffine = rng.gen();
let b: EdwardsAffine = rng.gen();
let a_string = group_to_decimal_string(a);
let b_string = group_to_decimal_string(b);
let a_element = group_element_to_input_value(a);
let b_element = group_element_to_input_value(b);
let bytes = include_bytes!("ternary.leo");
let mut program = parse_program(bytes).unwrap();
@ -326,9 +339,9 @@ fn test_ternary() {
// true -> field a
let main_input = generate_main_input(vec![
("s", Some(InputValue::Boolean(true))),
("a", Some(InputValue::Group(a_string.clone()))),
("b", Some(InputValue::Group(b_string.clone()))),
("c", Some(InputValue::Group(a_string.clone()))),
("a", Some(InputValue::Group(a_element.clone()))),
("b", Some(InputValue::Group(b_element.clone()))),
("c", Some(InputValue::Group(a_element.clone()))),
]);
program.set_main_input(main_input);
@ -340,9 +353,9 @@ fn test_ternary() {
// false -> field b
let main_input = generate_main_input(vec![
("s", Some(InputValue::Boolean(false))),
("a", Some(InputValue::Group(a_string))),
("b", Some(InputValue::Group(b_string.clone()))),
("c", Some(InputValue::Group(b_string))),
("a", Some(InputValue::Group(a_element))),
("b", Some(InputValue::Group(b_element.clone()))),
("c", Some(InputValue::Group(b_element))),
]);
program.set_main_input(main_input);

View File

@ -0,0 +1,3 @@
function main(element: group) {
let b = element;
}