impl group alloc input

This commit is contained in:
collin 2020-06-01 14:20:14 -07:00
parent d1297fc60c
commit ad2d9f1192
7 changed files with 200 additions and 20 deletions

View File

@ -4,6 +4,7 @@
use crate::{
constraints::{new_scope, ConstrainedProgram, ConstrainedValue},
errors::{FunctionError, ImportError},
group_from_input,
types::{Expression, Function, Identifier, InputValue, Program, Type},
GroupType,
};
@ -187,9 +188,7 @@ impl<
Type::FieldElement => {
Ok(self.field_element_from_input(cs, name, private, input_value)?)
}
// Type::Group => {
// Ok(self.group_element_from_input(cs, name, private, input_value)?)
// }
Type::Group => Ok(group_from_input(cs, name, private, input_value)?),
Type::Boolean => Ok(self.bool_from_input(cs, name, private, input_value)?),
Type::Array(_type, dimensions) => {
self.allocate_array(cs, name, private, *_type, dimensions, input_value)

View File

@ -0,0 +1,42 @@
use crate::errors::GroupError;
use crate::{ConstrainedValue, GroupType, InputValue};
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::curves::{Field, PrimeField};
use snarkos_models::gadgets::r1cs::ConstraintSystem;
pub(crate) fn group_from_input<
NativeF: Field,
F: Field + PrimeField,
GType: GroupType<NativeF, F>,
CS: ConstraintSystem<F>,
>(
cs: &mut CS,
name: String,
private: bool,
input_value: Option<InputValue<F>>,
) -> Result<ConstrainedValue<NativeF, F, GType>, GroupError> {
// Check that the parameter value is the correct type
let group_option = match input_value {
Some(input) => {
if let InputValue::Group(group_string) = input {
Some(group_string)
} else {
return Err(GroupError::InvalidGroup(input.to_string()));
}
}
None => None,
};
// Check visibility of parameter
let group_value = if private {
GType::alloc(cs.ns(|| name), || {
group_option.ok_or(SynthesisError::AssignmentMissing)
})?
} else {
GType::alloc_input(cs.ns(|| name), || {
group_option.ok_or(SynthesisError::AssignmentMissing)
})?
};
Ok(ConstrainedValue::Group(group_value))
}

View File

@ -18,6 +18,9 @@ pub use integer::*;
pub mod field_element;
pub use field_element::*;
pub(crate) mod group;
pub(crate) use group::*;
pub mod program;
pub use program::*;

View File

@ -8,8 +8,10 @@ use snarkos_gadgets::curves::edwards_bls12::EdwardsBlsGadget;
use snarkos_models::curves::{AffineCurve, ModelParameters};
use snarkos_models::gadgets::curves::{FpGadget, GroupGadget};
use snarkos_models::gadgets::r1cs::ConstraintSystem;
use snarkos_models::gadgets::utilities::alloc::AllocGadget;
use snarkos_models::gadgets::utilities::boolean::Boolean;
use snarkos_models::gadgets::utilities::eq::{ConditionalEqGadget, EqGadget};
use std::borrow::Borrow;
use std::ops::Sub;
use std::str::FromStr;
@ -21,16 +23,9 @@ pub enum EdwardsGroupType {
impl GroupType<<EdwardsParameters as ModelParameters>::BaseField, Fq> for EdwardsGroupType {
fn constant(string: String) -> Result<Self, GroupError> {
// 0 or (0, 1)
let result =
match Fq::from_str(&string).ok() {
Some(x) => EdwardsAffine::get_point_from_x(x, false)
.ok_or(GroupError::InvalidGroup(string))?,
None => EdwardsAffine::from_str(&string)
.map_err(|_| GroupError::InvalidGroup(string))?,
};
let value = Self::edwards_affine_from_str(string)?;
Ok(EdwardsGroupType::Constant(result))
Ok(EdwardsGroupType::Constant(value))
}
fn add<CS: ConstraintSystem<Fq>>(&self, cs: CS, other: &Self) -> Result<Self, GroupError> {
@ -88,6 +83,67 @@ impl GroupType<<EdwardsParameters as ModelParameters>::BaseField, Fq> for Edward
}
}
impl EdwardsGroupType {
pub fn edwards_affine_from_str(string: String) -> Result<EdwardsAffine, GroupError> {
// 0 or (0, 1)
match Fq::from_str(&string).ok() {
Some(x) => {
EdwardsAffine::get_point_from_x(x, false).ok_or(GroupError::InvalidGroup(string))
}
None => EdwardsAffine::from_str(&string).map_err(|_| GroupError::InvalidGroup(string)),
}
}
pub fn alloc_x_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>>(
value_gen: Fn,
) -> Result<EdwardsAffine, SynthesisError> {
let affine_string = match value_gen() {
Ok(value) => {
let string_value = value.borrow().clone();
Ok(string_value)
}
_ => Err(SynthesisError::AssignmentMissing),
}?;
Self::edwards_affine_from_str(affine_string).map_err(|_| SynthesisError::AssignmentMissing)
}
}
impl AllocGadget<String, Fq> for EdwardsGroupType {
fn alloc<
Fn: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<String>,
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),
)?;
Ok(EdwardsGroupType::Allocated(value))
}
fn alloc_input<
Fn: FnOnce() -> Result<T, SynthesisError>,
T: Borrow<String>,
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),
)?;
Ok(EdwardsGroupType::Allocated(value))
}
}
impl PartialEq for EdwardsGroupType {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@ -166,3 +222,50 @@ impl ConditionalEqGadget<Fq> for EdwardsGroupType {
2 * <EdwardsBlsGadget as ConditionalEqGadget<Fq>>::cost() //upper bound
}
}
// impl CondSelectGadget<Fq> for EdwardsGroupType {
// fn conditionally_select<CS: ConstraintSystem<F>>(
// mut cs: CS,
// cond: &Boolean,
// first: &Self,
// second: &Self
// ) -> Result<Self, SynthesisError> {
// if let Boolean::Constant(cond) = *cond {
// if cond { Ok(first.clone()) } else { Ok(second.clone()) }
// } else {
// let result = Self::a
// // // c - c
// // (EdwardsGroupType::Constant(first_value), EdwardsGroupType::Constant(other_value)) => {
// // Ok(EdwardsGroupType::Constant(first_value.clone()))
// // }
// // // a - a
// // (EdwardsGroupType::Allocated(self_value), EdwardsGroupType::Allocated(other_value)) => {
// // return <EdwardsBlsGadget>::conditional_enforce_equal(
// // self_value,
// // cs,
// // other_value,
// // condition,
// // )
// // }
// // // c - a = a - c
// // (
// // EdwardsGroupType::Constant(constant_value),
// // EdwardsGroupType::Allocated(allocated_value),
// // )
// // | (
// // EdwardsGroupType::Allocated(allocated_value),
// // EdwardsGroupType::Constant(constant_value),
// // ) => {
// // let x = FpGadget::from(&mut cs, &constant_value.x);
// // let y = FpGadget::from(&mut cs, &constant_value.y);
// // let constant_gadget = EdwardsBlsGadget::new(x, y);
// //
// // constant_gadget.conditional_enforce_equal(cs, allocated_value, condition)
// // }
// }
// }
//
// fn cost() -> usize {
// 2 * <EdwardsBlsGadget as CondSelectGadget<Fq>>::cost()
// }
// }

View File

@ -1,13 +1,15 @@
use crate::errors::GroupError;
use snarkos_models::curves::Field;
use snarkos_models::gadgets::r1cs::ConstraintSystem;
use snarkos_models::gadgets::utilities::alloc::AllocGadget;
use snarkos_models::gadgets::utilities::eq::{ConditionalEqGadget, EqGadget};
use std::fmt::Debug;
// use snarkos_models::gadgets::utilities::select::CondSelectGadget;
pub mod edwards_bls12;
pub trait GroupType<NativeF: Field, F: Field>:
Sized + Clone + Debug + EqGadget<F> + ConditionalEqGadget<F>
Sized + Clone + Debug + EqGadget<F> + ConditionalEqGadget<F> + AllocGadget<String, F>
{
fn constant(string: String) -> Result<Self, GroupError>;

View File

@ -0,0 +1,3 @@
function main(g: group) -> group {
return g
}

View File

@ -1,12 +1,15 @@
use crate::{compile_program, get_error, get_output, EdwardsConstrainedValue, EdwardsTestCompiler};
use leo_compiler::group::edwards_bls12::EdwardsGroupType;
use leo_compiler::ConstrainedValue;
use leo_compiler::{ConstrainedValue, InputValue};
use snarkos_curves::edwards_bls12::EdwardsAffine;
use snarkos_curves::edwards_bls12::{EdwardsAffine, Fq};
use snarkos_models::curves::Group;
use crate::boolean::{output_false, output_true};
use leo_compiler::errors::{CompilerError, FunctionError, StatementError};
use snarkos_gadgets::curves::edwards_bls12::EdwardsBlsGadget;
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
use snarkos_models::gadgets::utilities::alloc::AllocGadget;
use std::str::FromStr;
const DIRECTORY_NAME: &str = "tests/group/";
@ -14,7 +17,7 @@ const DIRECTORY_NAME: &str = "tests/group/";
const TEST_POINT_1: &str = "(7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)";
const TEST_POINT_2: &str = "(1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)";
fn output_expected(program: EdwardsTestCompiler, expected: EdwardsAffine) {
fn output_expected_constant(program: EdwardsTestCompiler, expected: EdwardsAffine) {
let output = get_output(program);
assert_eq!(
EdwardsConstrainedValue::Return(vec![ConstrainedValue::Group(EdwardsGroupType::Constant(
@ -25,8 +28,19 @@ fn output_expected(program: EdwardsTestCompiler, expected: EdwardsAffine) {
)
}
fn output_expected_allocated(program: EdwardsTestCompiler, expected: EdwardsBlsGadget) {
let output = get_output(program);
assert_eq!(
EdwardsConstrainedValue::Return(vec![ConstrainedValue::Group(
EdwardsGroupType::Allocated(expected)
)])
.to_string(),
output.to_string()
)
}
fn output_zero(program: EdwardsTestCompiler) {
output_expected(program, EdwardsAffine::zero())
output_expected_constant(program, EdwardsAffine::zero())
}
fn fail_enforce(program: EdwardsTestCompiler) {
@ -48,7 +62,7 @@ fn test_zero() {
fn test_point() {
let point = EdwardsAffine::from_str(TEST_POINT_1).unwrap();
let program = compile_program(DIRECTORY_NAME, "point.leo").unwrap();
output_expected(program, point);
output_expected_constant(program, point);
}
#[test]
@ -61,7 +75,7 @@ fn test_add() {
let sum = point_1.add(&point_2);
let program = compile_program(DIRECTORY_NAME, "add.leo").unwrap();
output_expected(program, sum);
output_expected_constant(program, sum);
}
#[test]
@ -74,7 +88,7 @@ fn test_sub() {
let sum = point_1.sub(&point_2);
let program = compile_program(DIRECTORY_NAME, "sub.leo").unwrap();
output_expected(program, sum);
output_expected_constant(program, sum);
}
#[test]
@ -100,3 +114,17 @@ fn test_assert_eq_false() {
let program = compile_program(DIRECTORY_NAME, "assert_eq_false.leo").unwrap();
fail_enforce(program);
}
#[test]
fn test_input() {
let mut program = compile_program(DIRECTORY_NAME, "input.leo").unwrap();
program.set_inputs(vec![Some(InputValue::Group(TEST_POINT_1.into()))]);
let mut cs = TestConstraintSystem::<Fq>::new();
let constant_point = EdwardsAffine::from_str(TEST_POINT_1).unwrap();
let allocated_point =
<EdwardsBlsGadget as AllocGadget<EdwardsAffine, Fq>>::alloc(&mut cs, || Ok(constant_point))
.unwrap();
output_expected_allocated(program, allocated_point)
}