impl FieldType gadgets

This commit is contained in:
collin 2020-06-02 13:25:07 -07:00
parent 2d4efdfd5b
commit 2e188b483b
4 changed files with 139 additions and 74 deletions

View File

@ -368,6 +368,10 @@ impl<F: Field + PrimeField, G: GroupType<F>, CS: ConstraintSystem<F>> Constraine
Integer::conditionally_select(cs, &resolved_first, &integer_2, &integer_3)?;
Ok(ConstrainedValue::Integer(result))
}
(ConstrainedValue::Field(fe_1), ConstrainedValue::Field(fe_2)) => {
let result = FieldType::conditionally_select(cs, &resolved_first, &fe_1, &fe_2)?;
Ok(ConstrainedValue::Field(result))
}
(ConstrainedValue::Group(ge_1), ConstrainedValue::Group(ge_2)) => {
let result = G::conditionally_select(cs, &resolved_first, &ge_1, &ge_2)?;
Ok(ConstrainedValue::Group(result))

View File

@ -3,6 +3,7 @@
use crate::errors::FieldError;
use snarkos_errors::gadgets::SynthesisError;
use snarkos_models::gadgets::curves::FieldGadget;
use snarkos_models::{
curves::{Field, PrimeField},
gadgets::{
@ -19,7 +20,6 @@ use snarkos_models::{
},
};
use std::borrow::Borrow;
use snarkos_models::gadgets::curves::FieldGadget;
#[derive(Clone, Debug)]
pub enum FieldType<F: Field + PrimeField> {
@ -28,6 +28,13 @@ pub enum FieldType<F: Field + PrimeField> {
}
impl<F: Field + PrimeField> FieldType<F> {
pub fn get_value(&self) -> Option<F> {
match self {
FieldType::Constant(field) => Some(*field),
FieldType::Allocated(gadget) => gadget.get_value(),
}
}
pub fn constant(string: String) -> Result<Self, FieldError> {
let value = F::from_str(&string).map_err(|_| FieldError::Invalid(string))?;
@ -46,16 +53,10 @@ impl<F: Field + PrimeField> FieldType<F> {
Ok(FieldType::Allocated(result))
}
(
FieldType::Constant(constant_value),
FieldType::Allocated(allocated_value),
)
| (
FieldType::Allocated(allocated_value),
FieldType::Constant(constant_value),
) => Ok(FieldType::Allocated(
allocated_value.add_constant(cs, constant_value)?,
)),
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(
FieldType::Allocated(allocated_value.add_constant(cs, constant_value)?),
),
}
}
@ -71,16 +72,10 @@ impl<F: Field + PrimeField> FieldType<F> {
Ok(FieldType::Allocated(result))
}
(
FieldType::Constant(constant_value),
FieldType::Allocated(allocated_value),
)
| (
FieldType::Allocated(allocated_value),
FieldType::Constant(constant_value),
) => Ok(FieldType::Allocated(
allocated_value.sub_constant(cs, constant_value)?,
)),
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(
FieldType::Allocated(allocated_value.sub_constant(cs, constant_value)?),
),
}
}
@ -96,23 +91,23 @@ impl<F: Field + PrimeField> FieldType<F> {
Ok(FieldType::Allocated(result))
}
(
FieldType::Constant(constant_value),
FieldType::Allocated(allocated_value),
)
| (
FieldType::Allocated(allocated_value),
FieldType::Constant(constant_value),
) => Ok(FieldType::Allocated(
allocated_value.mul_by_constant(cs, constant_value)?,
)),
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => Ok(
FieldType::Allocated(allocated_value.mul_by_constant(cs, constant_value)?),
),
}
}
pub fn div<CS: ConstraintSystem<F>>(&self, mut cs: CS, other: &Self) -> Result<Self, FieldError> {
pub fn div<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &Self,
) -> Result<Self, FieldError> {
let inverse = match other {
FieldType::Constant(constant) => {
let constant_inverse = constant.inverse().ok_or(FieldError::NoInverse(constant.to_string()))?;
let constant_inverse = constant
.inverse()
.ok_or(FieldError::NoInverse(constant.to_string()))?;
FieldType::Constant(constant_inverse)
}
FieldType::Allocated(allocated) => {
@ -123,30 +118,31 @@ impl<F: Field + PrimeField> FieldType<F> {
self.mul(cs, &inverse)
}
}
impl<F: Field + PrimeField> Eq for FieldType<F> {}
pub fn alloc_helper<Fn: FnOnce() -> Result<T, SynthesisError>, T: Borrow<String>>(
value_gen: Fn,
) -> Result<F, SynthesisError> {
let field_string = match value_gen() {
Ok(value) => {
let string_value = value.borrow().clone();
Ok(string_value)
}
_ => Err(SynthesisError::AssignmentMissing),
}?;
impl<F: Field + PrimeField> PartialEq for FieldType<F> {
fn eq(&self, other: &Self) -> bool {
unimplemented!()
F::from_str(&field_string).map_err(|_| SynthesisError::AssignmentMissing)
}
}
impl<F: Field + PrimeField> EqGadget<F> for FieldType<F> {}
impl<F: Field + PrimeField> ConditionalEqGadget<F> for FieldType<F> {
fn conditional_enforce_equal<CS: ConstraintSystem<F>>(
pub fn allocated<CS: ConstraintSystem<F>>(
&self,
cs: CS,
other: &Self,
condition: &Boolean,
) -> Result<(), SynthesisError> {
unimplemented!()
}
fn cost() -> usize {
unimplemented!()
mut cs: CS,
) -> Result<FpGadget<F>, SynthesisError> {
match self {
FieldType::Constant(constant) => {
FpGadget::alloc(&mut cs.ns(|| format!("{:?}", constant)), || Ok(constant))
}
FieldType::Allocated(allocated) => Ok(allocated.clone()),
}
}
}
@ -157,9 +153,11 @@ impl<F: Field + PrimeField> AllocGadget<String, F> for FieldType<F> {
CS: ConstraintSystem<F>,
>(
cs: CS,
f: Fn,
value_gen: Fn,
) -> Result<Self, SynthesisError> {
unimplemented!()
let value = FpGadget::alloc(cs, || Self::alloc_helper(value_gen))?;
Ok(FieldType::Allocated(value))
}
fn alloc_input<
@ -168,49 +166,114 @@ impl<F: Field + PrimeField> AllocGadget<String, F> for FieldType<F> {
CS: ConstraintSystem<F>,
>(
cs: CS,
f: Fn,
value_gen: Fn,
) -> Result<Self, SynthesisError> {
unimplemented!()
let value = FpGadget::alloc_input(cs, || Self::alloc_helper(value_gen))?;
Ok(FieldType::Allocated(value))
}
}
impl<F: Field + PrimeField> PartialEq for FieldType<F> {
fn eq(&self, other: &Self) -> bool {
let self_value = self.get_value();
let other_value = other.get_value();
self_value.is_some() && other_value.is_some() && self_value.eq(&other_value)
}
}
impl<F: Field + PrimeField> Eq for FieldType<F> {}
impl<F: Field + PrimeField> EqGadget<F> for FieldType<F> {}
impl<F: Field + PrimeField> ConditionalEqGadget<F> for FieldType<F> {
fn conditional_enforce_equal<CS: ConstraintSystem<F>>(
&self,
mut cs: CS,
other: &Self,
condition: &Boolean,
) -> Result<(), SynthesisError> {
match (self, other) {
// c - c
(FieldType::Constant(self_value), FieldType::Constant(other_value)) => {
if self_value == other_value {
return Ok(());
}
Err(SynthesisError::AssignmentMissing)
}
// a - a
(FieldType::Allocated(self_value), FieldType::Allocated(other_value)) => {
self_value.conditional_enforce_equal(cs, other_value, condition)
}
// c - a = a - c
(FieldType::Constant(constant_value), FieldType::Allocated(allocated_value))
| (FieldType::Allocated(allocated_value), FieldType::Constant(constant_value)) => {
let constant_gadget = FpGadget::from(&mut cs, constant_value);
constant_gadget.conditional_enforce_equal(cs, allocated_value, condition)
}
}
}
fn cost() -> usize {
2 * <FpGadget<F> as ConditionalEqGadget<F>>::cost()
}
}
impl<F: Field + PrimeField> CondSelectGadget<F> for FieldType<F> {
fn conditionally_select<CS: ConstraintSystem<F>>(
cs: CS,
mut cs: CS,
cond: &Boolean,
first: &Self,
second: &Self,
) -> Result<Self, SynthesisError> {
unimplemented!()
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 = FpGadget::conditionally_select(cs, cond, &first_gadget, &second_gadget)?;
Ok(FieldType::Allocated(result))
}
}
fn cost() -> usize {
unimplemented!()
2 * <FpGadget<F> as CondSelectGadget<F>>::cost()
}
}
impl<F: Field + PrimeField> ToBitsGadget<F> for FieldType<F> {
fn to_bits<CS: ConstraintSystem<F>>(&self, cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
unimplemented!()
fn to_bits<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
let self_gadget = self.allocated(&mut cs)?;
self_gadget.to_bits(cs)
}
fn to_bits_strict<CS: ConstraintSystem<F>>(
&self,
cs: CS,
mut cs: CS,
) -> Result<Vec<Boolean>, SynthesisError> {
unimplemented!()
let self_gadget = self.allocated(&mut cs)?;
self_gadget.to_bits_strict(cs)
}
}
impl<F: Field + PrimeField> ToBytesGadget<F> for FieldType<F> {
fn to_bytes<CS: ConstraintSystem<F>>(&self, cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
unimplemented!()
fn to_bytes<CS: ConstraintSystem<F>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
let self_gadget = self.allocated(&mut cs)?;
self_gadget.to_bytes(cs)
}
fn to_bytes_strict<CS: ConstraintSystem<F>>(
&self,
cs: CS,
mut cs: CS,
) -> Result<Vec<UInt8>, SynthesisError> {
unimplemented!()
let self_gadget = self.allocated(&mut cs)?;
self_gadget.to_bytes_strict(cs)
}
}

View File

@ -214,7 +214,7 @@ impl ConditionalEqGadget<Fq> for EdwardsGroupType {
}
// a - a
(EdwardsGroupType::Allocated(self_value), EdwardsGroupType::Allocated(other_value)) => {
return <EdwardsBlsGadget>::conditional_enforce_equal(
<EdwardsBlsGadget>::conditional_enforce_equal(
self_value,
cs,
other_value,

View File

@ -33,18 +33,16 @@ fn output_one(program: EdwardsTestCompiler) {
fn fail_field(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::FieldError(FieldError::Invalid(
_string,
))) => {}
CompilerError::FunctionError(FunctionError::FieldError(FieldError::Invalid(_string))) => {}
error => panic!("Expected invalid field error, got {}", error),
}
}
fn fail_synthesis(program: EdwardsTestCompiler) {
match get_error(program) {
CompilerError::FunctionError(FunctionError::FieldError(
FieldError::SynthesisError(_string),
)) => {}
CompilerError::FunctionError(FunctionError::FieldError(FieldError::SynthesisError(
_string,
))) => {}
error => panic!("Expected synthesis error, got {}", error),
}
}