mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-09-11 05:45:30 +03:00
impl FieldType gadgets
This commit is contained in:
parent
2d4efdfd5b
commit
2e188b483b
@ -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))
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user