impl group cond_select

This commit is contained in:
collin 2020-06-01 17:23:13 -07:00
parent ad2d9f1192
commit f144571530
5 changed files with 107 additions and 52 deletions

View File

@ -380,9 +380,11 @@ impl<
Integer::conditionally_select(cs, &resolved_first, &integer_2, &integer_3)?;
Ok(ConstrainedValue::Integer(result))
}
// (ConstrainedValue::GroupElement(group_2), ConstrainedValue::GroupElement(group_3)) => {
// let result = Group
// }
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
let result =
GType::conditionally_select(cs, &resolved_first, &ge_1, &ge_2)?;
Ok(ConstrainedValue::Group(result))
}
(_, _) => {
unimplemented!("conditional select gadget not implemented between given types")
}

View File

@ -7,10 +7,11 @@ use snarkos_errors::gadgets::SynthesisError;
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::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 snarkos_models::gadgets::utilities::select::CondSelectGadget;
use std::borrow::Borrow;
use std::ops::Sub;
use std::str::FromStr;
@ -107,6 +108,19 @@ impl EdwardsGroupType {
Self::edwards_affine_from_str(affine_string).map_err(|_| SynthesisError::AssignmentMissing)
}
pub fn allocated<CS: ConstraintSystem<Fq>>(
&self,
mut cs: CS,
) -> Result<EdwardsBlsGadget, SynthesisError> {
match self {
EdwardsGroupType::Constant(constant) => <EdwardsBlsGadget as AllocGadget<
GroupAffine<EdwardsParameters>,
Fq,
>>::alloc(&mut cs.ns(|| format!("{:?}", constant)), || Ok(constant)),
EdwardsGroupType::Allocated(allocated) => Ok(allocated.clone()),
}
}
}
impl AllocGadget<String, Fq> for EdwardsGroupType {
@ -223,49 +237,30 @@ impl ConditionalEqGadget<Fq> for EdwardsGroupType {
}
}
// 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()
// }
// }
impl CondSelectGadget<Fq> for EdwardsGroupType {
fn conditionally_select<CS: ConstraintSystem<Fq>>(
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 first_gadget = first.allocated(&mut cs)?;
let second_gadget = second.allocated(&mut cs)?;
let result =
EdwardsBlsGadget::conditionally_select(cs, cond, &first_gadget, &second_gadget)?;
Ok(EdwardsGroupType::Allocated(result))
}
}
fn cost() -> usize {
2 * <EdwardsBlsGadget as CondSelectGadget<Fq>>::cost()
}
}

View File

@ -3,13 +3,20 @@ 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 snarkos_models::gadgets::utilities::select::CondSelectGadget;
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> + AllocGadget<String, F>
Sized
+ Clone
+ Debug
+ EqGadget<F>
+ ConditionalEqGadget<F>
+ AllocGadget<String, F>
+ CondSelectGadget<F>
{
fn constant(string: String) -> Result<Self, GroupError>;

View File

@ -11,6 +11,7 @@ use snarkos_gadgets::curves::edwards_bls12::EdwardsBlsGadget;
use snarkos_models::gadgets::r1cs::TestConstraintSystem;
use snarkos_models::gadgets::utilities::alloc::AllocGadget;
use std::str::FromStr;
use snarkos_models::gadgets::curves::GroupGadget;
const DIRECTORY_NAME: &str = "tests/group/";
@ -126,5 +127,49 @@ fn test_input() {
<EdwardsBlsGadget as AllocGadget<EdwardsAffine, Fq>>::alloc(&mut cs, || Ok(constant_point))
.unwrap();
output_expected_allocated(program, allocated_point)
output_expected_allocated(program, allocated_point);
}
#[test]
fn test_ternary() {
let mut program_1 = compile_program(DIRECTORY_NAME, "ternary.leo").unwrap();
let mut program_2 = program_1.clone();
// true -> point_1
program_1.set_inputs(vec![Some(InputValue::Boolean(true))]);
let point_1 = EdwardsAffine::from_str(TEST_POINT_1).unwrap();
let output_1 = get_output(program_1);
let actual_1: EdwardsAffine = match output_1 {
EdwardsConstrainedValue::Return(vec) => {
match vec.as_slice() {
[ConstrainedValue::Group(EdwardsGroupType::Allocated(edwards_gadget))] => {
<EdwardsBlsGadget as GroupGadget<EdwardsAffine, Fq>>::get_value(edwards_gadget).unwrap()
}
_ => panic!("program output unknown return value")
}
},
_ => panic!("program output unknown return value")
};
assert_eq!(point_1, actual_1);
// false -> point_2
program_2.set_inputs(vec![Some(InputValue::Boolean(false))]);
let point_2 = EdwardsAffine::from_str(TEST_POINT_2).unwrap();
let output_2 = get_output(program_2);
let actual_2: EdwardsAffine = match output_2 {
EdwardsConstrainedValue::Return(vec) => {
match vec.as_slice() {
[ConstrainedValue::Group(EdwardsGroupType::Allocated(edwards_gadget))] => {
<EdwardsBlsGadget as GroupGadget<EdwardsAffine, Fq>>::get_value(edwards_gadget).unwrap()
}
_ => panic!("program output unknown return value")
}
},
_ => panic!("program output unknown return value")
};
assert_eq!(point_2, actual_2);
}

View File

@ -0,0 +1,6 @@
function main (b: bool) -> group {
let point_1 = (7374112779530666882856915975292384652154477718021969292781165691637980424078, 3435195339177955418892975564890903138308061187980579490487898366607011481796)group;
let point_2 = (1005842117974384149622370061042978581211342111653966059496918451529532134799, 79389132189982034519597104273449021362784864778548730890166152019533697186)group;
return if b ? point_1 : point_2
}