mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-12 00:41:32 +01:00
Adds Bowe-Hopwood hash
This commit is contained in:
committed by
Pratyush Mishra
parent
19856bd9b6
commit
581f3df55f
@@ -1,6 +1,4 @@
|
||||
use algebra::{
|
||||
fields::bls12_377::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters},
|
||||
};
|
||||
use algebra::fields::bls12_377::{Fq, Fq12Parameters, Fq2Parameters, Fq6Parameters};
|
||||
|
||||
use super::{fp::FpGadget, fp12::Fp12Gadget, fp2::Fp2Gadget, fp6_3over2::Fp6Gadget};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use algebra::fields::edwards_bls12::fq::Fq;
|
||||
use crate::fields::fp::FpGadget;
|
||||
use algebra::fields::edwards_bls12::fq::Fq;
|
||||
|
||||
pub type FqGadget = FpGadget<Fq>;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use algebra::fields::edwards_sw6::fq::Fq;
|
||||
use crate::fields::fp::FpGadget;
|
||||
use algebra::fields::edwards_sw6::fq::Fq;
|
||||
|
||||
pub type FqGadget = FpGadget<Fq>;
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use algebra::{bytes::ToBytes, FpParameters, PrimeField};
|
||||
use r1cs_core::{ConstraintSystem, LinearCombination, SynthesisError, ConstraintVar::{self, *}};
|
||||
use r1cs_core::{
|
||||
ConstraintSystem,
|
||||
ConstraintVar::{self, *},
|
||||
LinearCombination, SynthesisError,
|
||||
};
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
||||
use crate::boolean::AllocatedBit;
|
||||
use crate::Assignment;
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::{boolean::AllocatedBit, prelude::*, Assignment};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FpGadget<F: PrimeField> {
|
||||
@@ -52,6 +53,23 @@ impl<F: PrimeField> FieldGadget<F, F> for FpGadget<F> {
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conditionally_add_constant<CS: ConstraintSystem<F>>(
|
||||
&self,
|
||||
mut _cs: CS,
|
||||
bit: &Boolean,
|
||||
coeff: F,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let value = match (self.value, bit.get_value()) {
|
||||
(Some(v), Some(b)) => Some(if b { v + &coeff } else { v }),
|
||||
(..) => None,
|
||||
};
|
||||
Ok(FpGadget {
|
||||
value,
|
||||
variable: LC(bit.lc(CS::one(), coeff)) + &self.variable,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add<CS: ConstraintSystem<F>>(
|
||||
&self,
|
||||
@@ -503,6 +521,52 @@ impl<F: PrimeField> TwoBitLookupGadget<F> for FpGadget<F> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: PrimeField> ThreeBitCondNegLookupGadget<F> for FpGadget<F> {
|
||||
type TableConstant = F;
|
||||
|
||||
fn three_bit_cond_neg_lookup<CS: ConstraintSystem<F>>(
|
||||
mut cs: CS,
|
||||
b: &[Boolean],
|
||||
b0b1: &Boolean,
|
||||
c: &[Self::TableConstant],
|
||||
) -> Result<Self, SynthesisError> {
|
||||
debug_assert!(b.len() == 3);
|
||||
debug_assert!(c.len() == 4);
|
||||
|
||||
let result = Self::alloc(cs.ns(|| "Allocate lookup result"), || {
|
||||
let y = match (b[0].get_value().get()?, b[1].get_value().get()?) {
|
||||
(false, false) => c[0],
|
||||
(false, true) => c[2],
|
||||
(true, false) => c[1],
|
||||
(true, true) => c[3],
|
||||
};
|
||||
if b[2].get_value().get()? {
|
||||
Ok(-y)
|
||||
} else {
|
||||
Ok(y)
|
||||
}
|
||||
})?;
|
||||
|
||||
let one = CS::one();
|
||||
let y_lc = b0b1.lc(one, c[3] - &c[2] - &c[1] + &c[0])
|
||||
+ b[0].lc(one, c[1] - &c[0])
|
||||
+ b[1].lc(one, c[2] - &c[0])
|
||||
+ (c[0], one);
|
||||
cs.enforce(
|
||||
|| "Enforce lookup",
|
||||
|_| y_lc.clone() + y_lc.clone(),
|
||||
|lc| lc + b[2].lc(one, F::one()),
|
||||
|_| -result.get_variable() + y_lc.clone(),
|
||||
);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: PrimeField> Clone for FpGadget<F> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
use algebra::{
|
||||
PrimeField, Field,
|
||||
fields::{
|
||||
fp12_2over3over2::{Fp12, Fp12Parameters},
|
||||
fp6_3over2::{Fp6, Fp6Parameters},
|
||||
Fp2Parameters,
|
||||
},
|
||||
BitIterator,
|
||||
BitIterator, Field, PrimeField,
|
||||
};
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::Assignment;
|
||||
use crate::{prelude::*, Assignment};
|
||||
|
||||
type Fp2Gadget<P, ConstraintF> =
|
||||
super::fp2::Fp2Gadget<<<P as Fp12Parameters>::Fp6Params as Fp6Parameters>::Fp2Params, ConstraintF>;
|
||||
type Fp6Gadget<P, ConstraintF> = super::fp6_3over2::Fp6Gadget<<P as Fp12Parameters>::Fp6Params, ConstraintF>;
|
||||
type Fp6GadgetVariable<P, ConstraintF> =
|
||||
<Fp6Gadget<P, ConstraintF> as FieldGadget<Fp6<<P as Fp12Parameters>::Fp6Params>, ConstraintF>>::Variable;
|
||||
type Fp2Gadget<P, ConstraintF> = super::fp2::Fp2Gadget<
|
||||
<<P as Fp12Parameters>::Fp6Params as Fp6Parameters>::Fp2Params,
|
||||
ConstraintF,
|
||||
>;
|
||||
type Fp6Gadget<P, ConstraintF> =
|
||||
super::fp6_3over2::Fp6Gadget<<P as Fp12Parameters>::Fp6Params, ConstraintF>;
|
||||
type Fp6GadgetVariable<P, ConstraintF> = <Fp6Gadget<P, ConstraintF> as FieldGadget<
|
||||
Fp6<<P as Fp12Parameters>::Fp6Params>,
|
||||
ConstraintF,
|
||||
>>::Variable;
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = "ConstraintF: PrimeField"))]
|
||||
@@ -272,7 +275,10 @@ where
|
||||
P: Fp12Parameters,
|
||||
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
type Variable = (Fp6GadgetVariable<P, ConstraintF>, Fp6GadgetVariable<P, ConstraintF>);
|
||||
type Variable = (
|
||||
Fp6GadgetVariable<P, ConstraintF>,
|
||||
Fp6GadgetVariable<P, ConstraintF>,
|
||||
);
|
||||
|
||||
#[inline]
|
||||
fn get_value(&self) -> Option<Fp12<P>> {
|
||||
@@ -298,6 +304,22 @@ where
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conditionally_add_constant<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
bit: &Boolean,
|
||||
coeff: Fp12<P>,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0 = self
|
||||
.c0
|
||||
.conditionally_add_constant(cs.ns(|| "c0"), bit, coeff.c0)?;
|
||||
let c1 = self
|
||||
.c1
|
||||
.conditionally_add_constant(cs.ns(|| "c1"), bit, coeff.c1)?;
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
@@ -343,7 +365,10 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0 = self.c0.negate(cs.ns(|| "c0"))?;
|
||||
let c1 = self.c1.negate(cs.ns(|| "c1"))?;
|
||||
Ok(Self::new(c0, c1))
|
||||
@@ -396,7 +421,10 @@ where
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
fn square<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn square<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
// From Libsnark/fp2_gadget.tcc
|
||||
// Complex multiplication for Fp2:
|
||||
// v0 = A.c0 * A.c1
|
||||
@@ -518,7 +546,10 @@ where
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn inverse<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn inverse<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
|
||||
self.get_value().and_then(|val| val.inverse()).get()
|
||||
})?;
|
||||
@@ -690,7 +721,10 @@ where
|
||||
P: Fp12Parameters,
|
||||
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bits(&mut cs)?;
|
||||
let mut c1 = self.c1.to_bits(cs)?;
|
||||
c0.append(&mut c1);
|
||||
@@ -713,7 +747,10 @@ where
|
||||
P: Fp12Parameters,
|
||||
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes(cs.ns(|| "c0"))?;
|
||||
let mut c1 = self.c1.to_bytes(cs.ns(|| "c1"))?;
|
||||
c0.append(&mut c1);
|
||||
@@ -797,6 +834,42 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, ConstraintF: PrimeField> ThreeBitCondNegLookupGadget<ConstraintF>
|
||||
for Fp12Gadget<P, ConstraintF>
|
||||
where
|
||||
P: Fp12Parameters,
|
||||
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
type TableConstant = Fp12<P>;
|
||||
|
||||
fn three_bit_cond_neg_lookup<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
b: &[Boolean],
|
||||
b0b1: &Boolean,
|
||||
c: &[Self::TableConstant],
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0s = c.iter().map(|f| f.c0).collect::<Vec<_>>();
|
||||
let c1s = c.iter().map(|f| f.c1).collect::<Vec<_>>();
|
||||
let c0 = Fp6Gadget::<P, ConstraintF>::three_bit_cond_neg_lookup(
|
||||
cs.ns(|| "Lookup c0"),
|
||||
b,
|
||||
b0b1,
|
||||
&c0s,
|
||||
)?;
|
||||
let c1 = Fp6Gadget::<P, ConstraintF>::three_bit_cond_neg_lookup(
|
||||
cs.ns(|| "Lookup c1"),
|
||||
b,
|
||||
b0b1,
|
||||
&c1s,
|
||||
)?;
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
2 * <Fp6Gadget<P, ConstraintF> as ThreeBitCondNegLookupGadget<ConstraintF>>::cost()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, ConstraintF: PrimeField> AllocGadget<Fp12<P>, ConstraintF> for Fp12Gadget<P, ConstraintF>
|
||||
where
|
||||
P: Fp12Parameters,
|
||||
|
||||
@@ -2,12 +2,10 @@ use algebra::{
|
||||
fields::{Fp2, Fp2Parameters},
|
||||
Field, PrimeField,
|
||||
};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError, ConstraintVar};
|
||||
use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError};
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
use crate::fields::fp::FpGadget;
|
||||
use crate::prelude::*;
|
||||
use crate::Assignment;
|
||||
use crate::{fields::fp::FpGadget, prelude::*, Assignment};
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = "P: Fp2Parameters, ConstraintF: PrimeField"))]
|
||||
@@ -62,7 +60,9 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> Fp2Gadget<P, C
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp2<P>, ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp2<P>, ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
type Variable = (ConstraintVar<ConstraintF>, ConstraintVar<ConstraintF>);
|
||||
|
||||
#[inline]
|
||||
@@ -95,6 +95,22 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conditionally_add_constant<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
bit: &Boolean,
|
||||
coeff: Fp2<P>,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0 = self
|
||||
.c0
|
||||
.conditionally_add_constant(cs.ns(|| "c0"), bit, coeff.c0)?;
|
||||
let c1 = self
|
||||
.c1
|
||||
.conditionally_add_constant(cs.ns(|| "c1"), bit, coeff.c1)?;
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
@@ -191,7 +207,10 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn square<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn square<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
// From Libsnark/fp2_gadget.tcc
|
||||
// Complex multiplication for Fp2:
|
||||
// v0 = A.c0 * A.c1
|
||||
@@ -274,7 +293,10 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inverse<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn inverse<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
|
||||
self.get_value().and_then(|val| val.inverse()).get()
|
||||
})?;
|
||||
@@ -439,7 +461,9 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> FieldGadget<Fp
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> PartialEq for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> PartialEq
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.c0 == other.c0 && self.c1 == other.c1
|
||||
}
|
||||
@@ -447,9 +471,14 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> PartialEq for
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> Eq for Fp2Gadget<P, ConstraintF> {}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> EqGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {}
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> EqGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ConditionalEqGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ConditionalEqGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
#[inline]
|
||||
fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
@@ -469,7 +498,9 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ConditionalEqG
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> NEqGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> NEqGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
#[inline]
|
||||
fn enforce_not_equal<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
@@ -486,8 +517,13 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> NEqGadget<Cons
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ToBitsGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ToBitsGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bits(&mut cs)?;
|
||||
let mut c1 = self.c1.to_bits(cs)?;
|
||||
c0.append(&mut c1);
|
||||
@@ -505,8 +541,13 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ToBitsGadget<C
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ToBytesGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ToBytesGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes(cs.ns(|| "c0"))?;
|
||||
let mut c1 = self.c1.to_bytes(cs.ns(|| "c1"))?;
|
||||
c0.append(&mut c1);
|
||||
@@ -524,7 +565,9 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> ToBytesGadget<
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> Clone for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> Clone
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
c0: self.c0.clone(),
|
||||
@@ -534,7 +577,9 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> Clone for Fp2G
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> CondSelectGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> CondSelectGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
#[inline]
|
||||
fn conditionally_select<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
@@ -542,10 +587,18 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> CondSelectGadg
|
||||
first: &Self,
|
||||
second: &Self,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0 =
|
||||
FpGadget::<ConstraintF>::conditionally_select(&mut cs.ns(|| "c0"), cond, &first.c0, &second.c0)?;
|
||||
let c1 =
|
||||
FpGadget::<ConstraintF>::conditionally_select(&mut cs.ns(|| "c1"), cond, &first.c1, &second.c1)?;
|
||||
let c0 = FpGadget::<ConstraintF>::conditionally_select(
|
||||
&mut cs.ns(|| "c0"),
|
||||
cond,
|
||||
&first.c0,
|
||||
&second.c0,
|
||||
)?;
|
||||
let c1 = FpGadget::<ConstraintF>::conditionally_select(
|
||||
&mut cs.ns(|| "c1"),
|
||||
cond,
|
||||
&first.c1,
|
||||
&second.c1,
|
||||
)?;
|
||||
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
@@ -555,7 +608,9 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> CondSelectGadg
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> TwoBitLookupGadget<ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> TwoBitLookupGadget<ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
type TableConstant = Fp2<P>;
|
||||
fn two_bit_lookup<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
@@ -574,7 +629,32 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> TwoBitLookupGa
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp2<P>, ConstraintF> for Fp2Gadget<P, ConstraintF> {
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField>
|
||||
ThreeBitCondNegLookupGadget<ConstraintF> for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
type TableConstant = Fp2<P>;
|
||||
|
||||
fn three_bit_cond_neg_lookup<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
b: &[Boolean],
|
||||
b0b1: &Boolean,
|
||||
c: &[Self::TableConstant],
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0s = c.iter().map(|f| f.c0).collect::<Vec<_>>();
|
||||
let c1s = c.iter().map(|f| f.c1).collect::<Vec<_>>();
|
||||
let c0 = FpGadget::three_bit_cond_neg_lookup(cs.ns(|| "Lookup c0"), b, b0b1, &c0s)?;
|
||||
let c1 = FpGadget::three_bit_cond_neg_lookup(cs.ns(|| "Lookup c1"), b, b0b1, &c1s)?;
|
||||
Ok(Self::new(c0, c1))
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
2 * <FpGadget<ConstraintF> as ThreeBitCondNegLookupGadget<ConstraintF>>::cost()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp2<P>, ConstraintF>
|
||||
for Fp2Gadget<P, ConstraintF>
|
||||
{
|
||||
#[inline]
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
|
||||
@@ -5,13 +5,13 @@ use algebra::{
|
||||
},
|
||||
PrimeField,
|
||||
};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError, ConstraintVar};
|
||||
use r1cs_core::{ConstraintSystem, ConstraintVar, SynthesisError};
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::Assignment;
|
||||
use crate::{prelude::*, Assignment};
|
||||
|
||||
type Fp2Gadget<P, ConstraintF> = super::fp2::Fp2Gadget<<P as Fp6Parameters>::Fp2Params, ConstraintF>;
|
||||
type Fp2Gadget<P, ConstraintF> =
|
||||
super::fp2::Fp2Gadget<<P as Fp6Parameters>::Fp2Params, ConstraintF>;
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug(bound = "ConstraintF: PrimeField"))]
|
||||
@@ -34,7 +34,11 @@ where
|
||||
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn new(c0: Fp2Gadget<P, ConstraintF>, c1: Fp2Gadget<P, ConstraintF>, c2: Fp2Gadget<P, ConstraintF>) -> Self {
|
||||
pub fn new(
|
||||
c0: Fp2Gadget<P, ConstraintF>,
|
||||
c1: Fp2Gadget<P, ConstraintF>,
|
||||
c2: Fp2Gadget<P, ConstraintF>,
|
||||
) -> Self {
|
||||
Self {
|
||||
c0,
|
||||
c1,
|
||||
@@ -183,6 +187,25 @@ where
|
||||
Ok(Self::new(c0, c1, c2))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn conditionally_add_constant<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
bit: &Boolean,
|
||||
coeff: Fp6<P>,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0 = self
|
||||
.c0
|
||||
.conditionally_add_constant(cs.ns(|| "c0"), bit, coeff.c0)?;
|
||||
let c1 = self
|
||||
.c1
|
||||
.conditionally_add_constant(cs.ns(|| "c1"), bit, coeff.c1)?;
|
||||
let c2 = self
|
||||
.c2
|
||||
.conditionally_add_constant(cs.ns(|| "c2"), bit, coeff.c2)?;
|
||||
Ok(Self::new(c0, c1, c2))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
@@ -208,7 +231,10 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0 = self.c0.negate(&mut cs.ns(|| "negate c0"))?;
|
||||
let c1 = self.c1.negate(&mut cs.ns(|| "negate c1"))?;
|
||||
let c2 = self.c2.negate(&mut cs.ns(|| "negate c2"))?;
|
||||
@@ -374,7 +400,10 @@ where
|
||||
|
||||
/// Use the Toom-Cook-3x method to compute multiplication.
|
||||
#[inline]
|
||||
fn square<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn square<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
// Uses Toom-Cool-3x multiplication from
|
||||
//
|
||||
// Reference:
|
||||
@@ -473,7 +502,10 @@ where
|
||||
|
||||
// 18 constaints, we can probably do better but not sure it's worth it.
|
||||
#[inline]
|
||||
fn inverse<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn inverse<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let inverse = Self::alloc(&mut cs.ns(|| "alloc inverse"), || {
|
||||
self.get_value().and_then(|val| val.inverse()).get()
|
||||
})?;
|
||||
@@ -754,7 +786,10 @@ where
|
||||
P: Fp6Parameters,
|
||||
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bits(&mut cs)?;
|
||||
let mut c1 = self.c1.to_bits(&mut cs)?;
|
||||
let mut c2 = self.c2.to_bits(cs)?;
|
||||
@@ -785,7 +820,10 @@ where
|
||||
P: Fp6Parameters,
|
||||
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
let mut c0 = self.c0.to_bytes(cs.ns(|| "c0"))?;
|
||||
let mut c1 = self.c1.to_bytes(cs.ns(|| "c1"))?;
|
||||
let mut c2 = self.c2.to_bytes(cs.ns(|| "c2"))?;
|
||||
@@ -878,6 +916,49 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, ConstraintF: PrimeField> ThreeBitCondNegLookupGadget<ConstraintF>
|
||||
for Fp6Gadget<P, ConstraintF>
|
||||
where
|
||||
P: Fp6Parameters,
|
||||
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||
{
|
||||
type TableConstant = Fp6<P>;
|
||||
|
||||
fn three_bit_cond_neg_lookup<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
b: &[Boolean],
|
||||
b0b1: &Boolean,
|
||||
c: &[Self::TableConstant],
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let c0s = c.iter().map(|f| f.c0).collect::<Vec<_>>();
|
||||
let c1s = c.iter().map(|f| f.c1).collect::<Vec<_>>();
|
||||
let c2s = c.iter().map(|f| f.c2).collect::<Vec<_>>();
|
||||
let c0 = Fp2Gadget::<P, ConstraintF>::three_bit_cond_neg_lookup(
|
||||
cs.ns(|| "Lookup c0"),
|
||||
b,
|
||||
b0b1,
|
||||
&c0s,
|
||||
)?;
|
||||
let c1 = Fp2Gadget::<P, ConstraintF>::three_bit_cond_neg_lookup(
|
||||
cs.ns(|| "Lookup c1"),
|
||||
b,
|
||||
b0b1,
|
||||
&c1s,
|
||||
)?;
|
||||
let c2 = Fp2Gadget::<P, ConstraintF>::three_bit_cond_neg_lookup(
|
||||
cs.ns(|| "Lookup c2"),
|
||||
b,
|
||||
b0b1,
|
||||
&c2s,
|
||||
)?;
|
||||
Ok(Self::new(c0, c1, c2))
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
3 * <Fp2Gadget<P, ConstraintF> as ThreeBitCondNegLookupGadget<ConstraintF>>::cost()
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, ConstraintF: PrimeField> AllocGadget<Fp6<P>, ConstraintF> for Fp6Gadget<P, ConstraintF>
|
||||
where
|
||||
P: Fp6Parameters,
|
||||
|
||||
@@ -26,6 +26,7 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
|
||||
+ ToBytesGadget<ConstraintF>
|
||||
+ CondSelectGadget<ConstraintF>
|
||||
+ TwoBitLookupGadget<ConstraintF, TableConstant = F>
|
||||
+ ThreeBitCondNegLookupGadget<ConstraintF, TableConstant = F>
|
||||
+ Debug
|
||||
{
|
||||
type Variable: Clone + Debug;
|
||||
@@ -38,7 +39,18 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
|
||||
|
||||
fn one<CS: ConstraintSystem<ConstraintF>>(_: CS) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(&self, _: CS, _: &Self) -> Result<Self, SynthesisError>;
|
||||
fn conditionally_add_constant<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_: CS,
|
||||
_: &Boolean,
|
||||
_: F,
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_: CS,
|
||||
_: &Self,
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn add_in_place<CS: ConstraintSystem<ConstraintF>>(
|
||||
&mut self,
|
||||
@@ -61,7 +73,11 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn sub<CS: ConstraintSystem<ConstraintF>>(&self, _: CS, _: &Self) -> Result<Self, SynthesisError>;
|
||||
fn sub<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_: CS,
|
||||
_: &Self,
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn sub_in_place<CS: ConstraintSystem<ConstraintF>>(
|
||||
&mut self,
|
||||
@@ -83,7 +99,11 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn mul<CS: ConstraintSystem<ConstraintF>>(&self, _: CS, _: &Self) -> Result<Self, SynthesisError>;
|
||||
fn mul<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_: CS,
|
||||
_: &Self,
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn mul_in_place<CS: ConstraintSystem<ConstraintF>>(
|
||||
&mut self,
|
||||
@@ -125,7 +145,11 @@ pub trait FieldGadget<F: Field, ConstraintF: Field>:
|
||||
result.enforce_equal(&mut cs.ns(|| "test_equals"), &actual_result)
|
||||
}
|
||||
|
||||
fn add_constant<CS: ConstraintSystem<ConstraintF>>(&self, _: CS, _: &F) -> Result<Self, SynthesisError>;
|
||||
fn add_constant<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_: CS,
|
||||
_: &F,
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn add_constant_in_place<CS: ConstraintSystem<ConstraintF>>(
|
||||
&mut self,
|
||||
@@ -217,10 +241,15 @@ mod test {
|
||||
use rand_xorshift::XorShiftRng;
|
||||
|
||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem};
|
||||
use algebra::{UniformRand, Field, BitIterator};
|
||||
use algebra::{BitIterator, Field, UniformRand};
|
||||
use r1cs_core::ConstraintSystem;
|
||||
|
||||
fn field_test<FE: Field, ConstraintF: Field, F: FieldGadget<FE, ConstraintF>, CS: ConstraintSystem<ConstraintF>>(
|
||||
fn field_test<
|
||||
FE: Field,
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<FE, ConstraintF>,
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
>(
|
||||
mut cs: CS,
|
||||
a: F,
|
||||
b: F,
|
||||
@@ -402,6 +431,23 @@ mod test {
|
||||
let n = F::alloc(&mut cs.ns(|| "alloc new var"), || Ok(negone)).unwrap();
|
||||
let _ = n.to_bytes(&mut cs.ns(|| "ToBytes")).unwrap();
|
||||
let _ = n.to_bytes_strict(&mut cs.ns(|| "ToBytes Strict")).unwrap();
|
||||
|
||||
let ab_false = a
|
||||
.conditionally_add_constant(
|
||||
cs.ns(|| "Add bool with coeff false"),
|
||||
&Boolean::constant(false),
|
||||
b_native,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(ab_false.get_value().unwrap(), a_native);
|
||||
let ab_true = a
|
||||
.conditionally_add_constant(
|
||||
cs.ns(|| "Add bool with coeff true"),
|
||||
&Boolean::constant(true),
|
||||
b_native,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(ab_true.get_value().unwrap(), a_native + &b_native);
|
||||
}
|
||||
|
||||
fn random_frobenius_tests<
|
||||
|
||||
Reference in New Issue
Block a user