mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-11 00:11:29 +01:00
Adds Bowe-Hopwood hash
This commit is contained in:
committed by
Pratyush Mishra
parent
19856bd9b6
commit
581f3df55f
206
crypto-primitives/src/crh/bowe_hopwood/constraints.rs
Normal file
206
crypto-primitives/src/crh/bowe_hopwood/constraints.rs
Normal file
@@ -0,0 +1,206 @@
|
||||
use algebra::Field;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::crh::{
|
||||
bowe_hopwood::{BoweHopwoodPedersenCRH, BoweHopwoodPedersenParameters, CHUNK_SIZE},
|
||||
pedersen::PedersenWindow,
|
||||
FixedLengthCRHGadget,
|
||||
};
|
||||
use algebra::groups::Group;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use r1cs_std::{alloc::AllocGadget, groups::GroupGadget, uint8::UInt8};
|
||||
|
||||
use r1cs_std::bits::boolean::Boolean;
|
||||
use std::{borrow::Borrow, marker::PhantomData};
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Clone(
|
||||
bound = "G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"
|
||||
))]
|
||||
pub struct BoweHopwoodPedersenCRHGadgetParameters<
|
||||
G: Group,
|
||||
W: PedersenWindow,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
> {
|
||||
params: BoweHopwoodPedersenParameters<G>,
|
||||
_group_g: PhantomData<GG>,
|
||||
_engine: PhantomData<ConstraintF>,
|
||||
_window: PhantomData<W>,
|
||||
}
|
||||
|
||||
pub struct BoweHopwoodPedersenCRHGadget<
|
||||
G: Group,
|
||||
ConstraintF: Field,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
> {
|
||||
_group: PhantomData<*const G>,
|
||||
_group_gadget: PhantomData<*const GG>,
|
||||
_engine: PhantomData<ConstraintF>,
|
||||
}
|
||||
|
||||
impl<ConstraintF, G, GG, W> FixedLengthCRHGadget<BoweHopwoodPedersenCRH<G, W>, ConstraintF>
|
||||
for BoweHopwoodPedersenCRHGadget<G, ConstraintF, GG>
|
||||
where
|
||||
ConstraintF: Field,
|
||||
G: Group + Hash,
|
||||
GG: GroupGadget<G, ConstraintF>,
|
||||
W: PedersenWindow,
|
||||
{
|
||||
type OutputGadget = GG;
|
||||
type ParametersGadget = BoweHopwoodPedersenCRHGadgetParameters<G, W, ConstraintF, GG>;
|
||||
|
||||
fn check_evaluation_gadget<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
parameters: &Self::ParametersGadget,
|
||||
input: &[UInt8],
|
||||
) -> Result<Self::OutputGadget, SynthesisError> {
|
||||
// Pad the input if it is not the current length.
|
||||
let mut input_in_bits: Vec<_> = input.iter().flat_map(|byte| byte.into_bits_le()).collect();
|
||||
if (input_in_bits.len()) % CHUNK_SIZE != 0 {
|
||||
let current_length = input_in_bits.len();
|
||||
for _ in 0..(CHUNK_SIZE - current_length % CHUNK_SIZE) {
|
||||
input_in_bits.push(Boolean::constant(false));
|
||||
}
|
||||
}
|
||||
assert!(input_in_bits.len() % CHUNK_SIZE == 0);
|
||||
assert_eq!(parameters.params.generators.len(), W::NUM_WINDOWS);
|
||||
for generators in parameters.params.generators.iter() {
|
||||
assert_eq!(generators.len(), W::WINDOW_SIZE);
|
||||
}
|
||||
|
||||
// Allocate new variable for the result.
|
||||
let input_in_bits = input_in_bits
|
||||
.chunks(W::WINDOW_SIZE * CHUNK_SIZE)
|
||||
.map(|x| x.chunks(CHUNK_SIZE).into_iter().collect::<Vec<_>>())
|
||||
.collect::<Vec<_>>();
|
||||
let result = GG::precomputed_base_3_bit_signed_digit_scalar_mul(
|
||||
cs,
|
||||
¶meters.params.generators,
|
||||
&input_in_bits,
|
||||
)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>>
|
||||
AllocGadget<BoweHopwoodPedersenParameters<G>, ConstraintF>
|
||||
for BoweHopwoodPedersenCRHGadgetParameters<G, W, ConstraintF, GG>
|
||||
{
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
_cs: CS,
|
||||
value_gen: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<BoweHopwoodPedersenParameters<G>>,
|
||||
{
|
||||
let params = value_gen()?.borrow().clone();
|
||||
Ok(BoweHopwoodPedersenCRHGadgetParameters {
|
||||
params,
|
||||
_group_g: PhantomData,
|
||||
_engine: PhantomData,
|
||||
_window: PhantomData,
|
||||
})
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
_cs: CS,
|
||||
value_gen: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<BoweHopwoodPedersenParameters<G>>,
|
||||
{
|
||||
let params = value_gen()?.borrow().clone();
|
||||
Ok(BoweHopwoodPedersenCRHGadgetParameters {
|
||||
params,
|
||||
_group_g: PhantomData,
|
||||
_engine: PhantomData,
|
||||
_window: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use algebra::fields::sw6::fr::Fr;
|
||||
use rand::{thread_rng, Rng};
|
||||
|
||||
use crate::crh::{
|
||||
bowe_hopwood::{constraints::BoweHopwoodPedersenCRHGadget, BoweHopwoodPedersenCRH},
|
||||
pedersen::PedersenWindow,
|
||||
FixedLengthCRH, FixedLengthCRHGadget,
|
||||
};
|
||||
use algebra::{curves::edwards_sw6::EdwardsProjective as Edwards, ProjectiveCurve};
|
||||
use r1cs_core::ConstraintSystem;
|
||||
use r1cs_std::{
|
||||
alloc::AllocGadget, groups::curves::twisted_edwards::edwards_sw6::EdwardsSWGadget,
|
||||
test_constraint_system::TestConstraintSystem, uint8::UInt8,
|
||||
};
|
||||
|
||||
type TestCRH = BoweHopwoodPedersenCRH<Edwards, Window>;
|
||||
type TestCRHGadget = BoweHopwoodPedersenCRHGadget<Edwards, Fr, EdwardsSWGadget>;
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub(super) struct Window;
|
||||
|
||||
impl PedersenWindow for Window {
|
||||
const WINDOW_SIZE: usize = 90;
|
||||
const NUM_WINDOWS: usize = 8;
|
||||
}
|
||||
|
||||
fn generate_input<CS: ConstraintSystem<Fr>, R: Rng>(
|
||||
mut cs: CS,
|
||||
rng: &mut R,
|
||||
) -> ([u8; 270], Vec<UInt8>) {
|
||||
let mut input = [1u8; 270];
|
||||
rng.fill_bytes(&mut input);
|
||||
|
||||
let mut input_bytes = vec![];
|
||||
for (byte_i, input_byte) in input.into_iter().enumerate() {
|
||||
let cs = cs.ns(|| format!("input_byte_gadget_{}", byte_i));
|
||||
input_bytes.push(UInt8::alloc(cs, || Ok(*input_byte)).unwrap());
|
||||
}
|
||||
(input, input_bytes)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn crh_primitive_gadget_test() {
|
||||
let rng = &mut thread_rng();
|
||||
let mut cs = TestConstraintSystem::<Fr>::new();
|
||||
|
||||
let (input, input_bytes) = generate_input(&mut cs, rng);
|
||||
println!("number of constraints for input: {}", cs.num_constraints());
|
||||
|
||||
let parameters = TestCRH::setup(rng).unwrap();
|
||||
let primitive_result = TestCRH::evaluate(¶meters, &input).unwrap();
|
||||
|
||||
let gadget_parameters =
|
||||
<TestCRHGadget as FixedLengthCRHGadget<TestCRH, Fr>>::ParametersGadget::alloc(
|
||||
&mut cs.ns(|| "gadget_parameters"),
|
||||
|| Ok(¶meters),
|
||||
)
|
||||
.unwrap();
|
||||
println!(
|
||||
"number of constraints for input + params: {}",
|
||||
cs.num_constraints()
|
||||
);
|
||||
|
||||
let gadget_result =
|
||||
<TestCRHGadget as FixedLengthCRHGadget<TestCRH, Fr>>::check_evaluation_gadget(
|
||||
&mut cs.ns(|| "gadget_evaluation"),
|
||||
&gadget_parameters,
|
||||
&input_bytes,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
println!("number of constraints total: {}", cs.num_constraints());
|
||||
|
||||
let primitive_result = primitive_result.into_affine();
|
||||
assert_eq!(primitive_result.x, gadget_result.x.value.unwrap());
|
||||
assert_eq!(primitive_result.y, gadget_result.y.value.unwrap());
|
||||
assert!(cs.is_satisfied());
|
||||
}
|
||||
}
|
||||
194
crypto-primitives/src/crh/bowe_hopwood/mod.rs
Normal file
194
crypto-primitives/src/crh/bowe_hopwood/mod.rs
Normal file
@@ -0,0 +1,194 @@
|
||||
use crate::Error;
|
||||
use rand::Rng;
|
||||
use rayon::prelude::*;
|
||||
use std::{
|
||||
fmt::{Debug, Formatter, Result as FmtResult},
|
||||
marker::PhantomData,
|
||||
};
|
||||
|
||||
use super::pedersen::{bytes_to_bits, PedersenCRH, PedersenWindow};
|
||||
use crate::crh::FixedLengthCRH;
|
||||
use algebra::{biginteger::BigInteger, fields::PrimeField, groups::Group};
|
||||
|
||||
#[cfg(feature = "r1cs")]
|
||||
pub mod constraints;
|
||||
|
||||
pub const CHUNK_SIZE: usize = 3;
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub struct BoweHopwoodPedersenParameters<G: Group> {
|
||||
pub generators: Vec<Vec<G>>,
|
||||
}
|
||||
|
||||
pub struct BoweHopwoodPedersenCRH<G: Group, W: PedersenWindow> {
|
||||
group: PhantomData<G>,
|
||||
window: PhantomData<W>,
|
||||
}
|
||||
|
||||
impl<G: Group, W: PedersenWindow> BoweHopwoodPedersenCRH<G, W> {
|
||||
pub fn create_generators<R: Rng>(rng: &mut R) -> Vec<Vec<G>> {
|
||||
let mut generators = Vec::new();
|
||||
for _ in 0..W::NUM_WINDOWS {
|
||||
let mut generators_for_segment = Vec::new();
|
||||
let mut base = G::rand(rng);
|
||||
for _ in 0..W::WINDOW_SIZE {
|
||||
generators_for_segment.push(base);
|
||||
for _ in 0..4 {
|
||||
base.double_in_place();
|
||||
}
|
||||
}
|
||||
generators.push(generators_for_segment);
|
||||
}
|
||||
generators
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group, W: PedersenWindow> FixedLengthCRH for BoweHopwoodPedersenCRH<G, W> {
|
||||
const INPUT_SIZE_BITS: usize = PedersenCRH::<G, W>::INPUT_SIZE_BITS;
|
||||
type Output = G;
|
||||
type Parameters = BoweHopwoodPedersenParameters<G>;
|
||||
|
||||
fn setup<R: Rng>(rng: &mut R) -> Result<Self::Parameters, Error> {
|
||||
fn calculate_num_chunks_in_segment<F: PrimeField>() -> usize {
|
||||
let upper_limit = F::modulus_minus_one_div_two();
|
||||
let mut c = 0;
|
||||
let mut range = F::BigInt::from(2_u64);
|
||||
while range < upper_limit {
|
||||
range.muln(4);
|
||||
c += 1;
|
||||
}
|
||||
|
||||
c
|
||||
}
|
||||
|
||||
let maximum_num_chunks_in_segment = calculate_num_chunks_in_segment::<G::ScalarField>();
|
||||
if W::WINDOW_SIZE > maximum_num_chunks_in_segment {
|
||||
return Err(format!(
|
||||
"Bowe-Hopwood hash must have a window size resulting in scalars < (p-1)/2, \
|
||||
maximum segment size is {}",
|
||||
maximum_num_chunks_in_segment
|
||||
)
|
||||
.into());
|
||||
}
|
||||
|
||||
let time = start_timer!(|| format!(
|
||||
"BoweHopwoodPedersenCRH::Setup: {} segments of {} 3-bit chunks; {{0,1}}^{{{}}} -> G",
|
||||
W::NUM_WINDOWS,
|
||||
W::WINDOW_SIZE,
|
||||
W::WINDOW_SIZE * W::NUM_WINDOWS * CHUNK_SIZE
|
||||
));
|
||||
let generators = Self::create_generators(rng);
|
||||
end_timer!(time);
|
||||
Ok(Self::Parameters { generators })
|
||||
}
|
||||
|
||||
fn evaluate(parameters: &Self::Parameters, input: &[u8]) -> Result<Self::Output, Error> {
|
||||
let eval_time = start_timer!(|| "BoweHopwoodPedersenCRH::Eval");
|
||||
|
||||
if (input.len() * 8) > W::WINDOW_SIZE * W::NUM_WINDOWS * CHUNK_SIZE {
|
||||
panic!(
|
||||
"incorrect input length {:?} for window params {:?}x{:?}x{}",
|
||||
input.len(),
|
||||
W::WINDOW_SIZE,
|
||||
W::NUM_WINDOWS,
|
||||
CHUNK_SIZE,
|
||||
);
|
||||
}
|
||||
|
||||
let mut padded_input = Vec::with_capacity(input.len());
|
||||
let input = bytes_to_bits(input);
|
||||
// Pad the input if it is not the current length.
|
||||
padded_input.extend_from_slice(&input);
|
||||
if input.len() % CHUNK_SIZE != 0 {
|
||||
let current_length = input.len();
|
||||
for _ in 0..(CHUNK_SIZE - current_length % CHUNK_SIZE) {
|
||||
padded_input.push(false);
|
||||
}
|
||||
}
|
||||
|
||||
assert_eq!(padded_input.len() % CHUNK_SIZE, 0);
|
||||
|
||||
assert_eq!(
|
||||
parameters.generators.len(),
|
||||
W::NUM_WINDOWS,
|
||||
"Incorrect pp of size {:?} for window params {:?}x{:?}x{}",
|
||||
parameters.generators.len(),
|
||||
W::WINDOW_SIZE,
|
||||
W::NUM_WINDOWS,
|
||||
CHUNK_SIZE,
|
||||
);
|
||||
for generators in parameters.generators.iter() {
|
||||
assert_eq!(generators.len(), W::WINDOW_SIZE);
|
||||
}
|
||||
assert_eq!(CHUNK_SIZE, 3);
|
||||
|
||||
// Compute sum of h_i^{sum of (1-2*c_{i,j,2})*(1+c_{i,j,0}+2*c_{i,j,1})*2^{4*(j-1)} for all j in segment} for all i.
|
||||
// Described in section 5.4.1.7 in the Zcash protocol specification.
|
||||
let result = padded_input
|
||||
.par_chunks(W::WINDOW_SIZE * CHUNK_SIZE)
|
||||
.zip(¶meters.generators)
|
||||
.map(|(segment_bits, segment_generators)| {
|
||||
segment_bits
|
||||
.par_chunks(CHUNK_SIZE)
|
||||
.zip(segment_generators)
|
||||
.map(|(chunk_bits, generator)| {
|
||||
let mut encoded = generator.clone();
|
||||
if chunk_bits[0] {
|
||||
encoded = encoded + &generator;
|
||||
}
|
||||
if chunk_bits[1] {
|
||||
encoded = encoded + &generator.double();
|
||||
}
|
||||
if chunk_bits[2] {
|
||||
encoded = encoded.neg();
|
||||
}
|
||||
encoded
|
||||
})
|
||||
.reduce(|| G::zero(), |a, b| a + &b)
|
||||
})
|
||||
.reduce(|| G::zero(), |a, b| a + &b);
|
||||
end_timer!(eval_time);
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: Group> Debug for BoweHopwoodPedersenParameters<G> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
|
||||
write!(f, "Bowe-Hopwood Pedersen Hash Parameters {{\n")?;
|
||||
for (i, g) in self.generators.iter().enumerate() {
|
||||
write!(f, "\t Generator {}: {:?}\n", i, g)?;
|
||||
}
|
||||
write!(f, "}}\n")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::{
|
||||
crh::{bowe_hopwood::BoweHopwoodPedersenCRH, pedersen::PedersenWindow},
|
||||
FixedLengthCRH,
|
||||
};
|
||||
use algebra::curves::edwards_sw6::EdwardsProjective;
|
||||
use rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn test_simple_bh() {
|
||||
#[derive(Clone)]
|
||||
struct TestWindow {}
|
||||
impl PedersenWindow for TestWindow {
|
||||
const WINDOW_SIZE: usize = 90;
|
||||
const NUM_WINDOWS: usize = 8;
|
||||
}
|
||||
|
||||
let rng = &mut thread_rng();
|
||||
let params =
|
||||
<BoweHopwoodPedersenCRH<EdwardsProjective, TestWindow> as FixedLengthCRH>::setup(rng)
|
||||
.unwrap();
|
||||
<BoweHopwoodPedersenCRH<EdwardsProjective, TestWindow> as FixedLengthCRH>::evaluate(
|
||||
¶ms,
|
||||
&[1, 2, 3],
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ use algebra::bytes::ToBytes;
|
||||
use rand::Rng;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub mod bowe_hopwood;
|
||||
pub mod injective_map;
|
||||
pub mod pedersen;
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<V>;
|
||||
|
||||
fn alloc_checked<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
fn alloc_checked<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
f: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<V>,
|
||||
@@ -20,7 +23,10 @@ where
|
||||
Self::alloc(cs, f)
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
f: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<V>;
|
||||
@@ -37,8 +43,13 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], ConstraintF> for Vec<A> {
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(mut cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], ConstraintF>
|
||||
for Vec<A>
|
||||
{
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
f: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<[I]>,
|
||||
@@ -52,7 +63,10 @@ impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], Con
|
||||
Ok(vec)
|
||||
}
|
||||
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(mut cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
f: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<[I]>,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use algebra::{BitIterator, Field, FpParameters, PrimeField};
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::Assignment;
|
||||
use crate::{prelude::*, Assignment};
|
||||
use r1cs_core::{ConstraintSystem, LinearCombination, SynthesisError, Variable};
|
||||
use std::borrow::Borrow;
|
||||
|
||||
@@ -346,7 +345,11 @@ impl Boolean {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lc<ConstraintF: Field>(&self, one: Variable, coeff: ConstraintF) -> LinearCombination<ConstraintF> {
|
||||
pub fn lc<ConstraintF: Field>(
|
||||
&self,
|
||||
one: Variable,
|
||||
coeff: ConstraintF,
|
||||
) -> LinearCombination<ConstraintF> {
|
||||
match *self {
|
||||
Boolean::Constant(c) => {
|
||||
if c {
|
||||
@@ -396,7 +399,11 @@ impl Boolean {
|
||||
}
|
||||
|
||||
/// Perform XOR over two boolean operands
|
||||
pub fn xor<'a, ConstraintF, CS>(cs: CS, a: &'a Self, b: &'a Self) -> Result<Self, SynthesisError>
|
||||
pub fn xor<'a, ConstraintF, CS>(
|
||||
cs: CS,
|
||||
a: &'a Self,
|
||||
b: &'a Self,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
ConstraintF: Field,
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
@@ -441,7 +448,11 @@ impl Boolean {
|
||||
}
|
||||
|
||||
/// Perform AND over two boolean operands
|
||||
pub fn and<'a, ConstraintF, CS>(cs: CS, a: &'a Self, b: &'a Self) -> Result<Self, SynthesisError>
|
||||
pub fn and<'a, ConstraintF, CS>(
|
||||
cs: CS,
|
||||
a: &'a Self,
|
||||
b: &'a Self,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
ConstraintF: Field,
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
@@ -629,7 +640,10 @@ impl From<AllocatedBit> for Boolean {
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for Boolean {
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, value_gen: F) -> Result<Self, SynthesisError>
|
||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
value_gen: F,
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
F: FnOnce() -> Result<T, SynthesisError>,
|
||||
T: Borrow<bool>,
|
||||
@@ -713,7 +727,10 @@ impl<ConstraintF: Field> ConditionalEqGadget<ConstraintF> for Boolean {
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for Boolean {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
let mut bits = vec![Boolean::constant(false); 7];
|
||||
bits.push(*self);
|
||||
bits.reverse();
|
||||
@@ -734,15 +751,11 @@ impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for Boolean {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{AllocatedBit, Boolean};
|
||||
use crate::{
|
||||
test_constraint_system::TestConstraintSystem,
|
||||
prelude::*
|
||||
};
|
||||
use algebra::{fields::bls12_381::Fr, BitIterator, Field, PrimeField};
|
||||
use algebra::UniformRand;
|
||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem};
|
||||
use algebra::{fields::bls12_381::Fr, BitIterator, Field, PrimeField, UniformRand};
|
||||
use r1cs_core::ConstraintSystem;
|
||||
use rand::SeedableRng;
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use r1cs_core::ConstraintSystem;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
@@ -1775,8 +1788,8 @@ use rand_xorshift::XorShiftRng;
|
||||
// let mut bits = vec![];
|
||||
// for (i, b) in BitIterator::new(r).skip(1).enumerate() {
|
||||
// bits.push(Boolean::from(
|
||||
// AllocatedBit::alloc(cs.ns(|| format!("bit_gadget {}", i)),
|
||||
// Some(b)) .unwrap(),
|
||||
// AllocatedBit::alloc(cs.ns(|| format!("bit_gadget {}",
|
||||
// i)), Some(b)) .unwrap(),
|
||||
// ));
|
||||
// }
|
||||
|
||||
|
||||
@@ -7,7 +7,10 @@ pub mod uint32;
|
||||
pub mod uint8;
|
||||
|
||||
pub trait ToBitsGadget<ConstraintF: Field> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Vec<Boolean>, SynthesisError>;
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError>;
|
||||
|
||||
/// Additionally checks if the produced list of booleans is 'valid'.
|
||||
fn to_bits_strict<CS: ConstraintSystem<ConstraintF>>(
|
||||
@@ -17,7 +20,10 @@ pub trait ToBitsGadget<ConstraintF: Field> {
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Boolean {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, _: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
Ok(vec![self.clone()])
|
||||
}
|
||||
|
||||
@@ -30,7 +36,10 @@ impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Boolean {
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [Boolean] {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
Ok(self.to_vec())
|
||||
}
|
||||
|
||||
@@ -42,7 +51,10 @@ impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [Boolean] {
|
||||
}
|
||||
}
|
||||
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Vec<Boolean> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
Ok(self.clone())
|
||||
}
|
||||
|
||||
@@ -55,7 +67,10 @@ impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Vec<Boolean> {
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<Boolean>, SynthesisError> {
|
||||
let mut result = Vec::with_capacity(&self.len() * 8);
|
||||
for byte in self {
|
||||
result.extend_from_slice(&byte.into_bits_le());
|
||||
@@ -72,7 +87,10 @@ impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
|
||||
}
|
||||
|
||||
pub trait ToBytesGadget<ConstraintF: Field> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Vec<UInt8>, SynthesisError>;
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError>;
|
||||
|
||||
/// Additionally checks if the produced list of booleans is 'valid'.
|
||||
fn to_bytes_strict<CS: ConstraintSystem<ConstraintF>>(
|
||||
@@ -82,7 +100,10 @@ pub trait ToBytesGadget<ConstraintF: Field> {
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for [UInt8] {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
Ok(self.to_vec())
|
||||
}
|
||||
|
||||
@@ -94,8 +115,13 @@ impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for [UInt8] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, ConstraintF: Field, T: 'a + ToBytesGadget<ConstraintF>> ToBytesGadget<ConstraintF> for &'a T {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
impl<'a, ConstraintF: Field, T: 'a + ToBytesGadget<ConstraintF>> ToBytesGadget<ConstraintF>
|
||||
for &'a T
|
||||
{
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
(*self).to_bytes(cs)
|
||||
}
|
||||
|
||||
@@ -108,7 +134,10 @@ impl<'a, ConstraintF: Field, T: 'a + ToBytesGadget<ConstraintF>> ToBytesGadget<C
|
||||
}
|
||||
|
||||
impl<'a, ConstraintF: Field> ToBytesGadget<ConstraintF> for &'a [UInt8] {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
Ok(self.to_vec())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use algebra::{FpParameters, PrimeField, Field};
|
||||
use algebra::{Field, FpParameters, PrimeField};
|
||||
|
||||
use r1cs_core::{ConstraintSystem, LinearCombination, SynthesisError};
|
||||
|
||||
use crate::boolean::{AllocatedBit, Boolean};
|
||||
use crate::Assignment;
|
||||
use crate::prelude::*;
|
||||
use crate::{
|
||||
boolean::{AllocatedBit, Boolean},
|
||||
prelude::*,
|
||||
Assignment,
|
||||
};
|
||||
|
||||
/// Represents an interpretation of 32 `Boolean` objects as an
|
||||
/// unsigned integer.
|
||||
@@ -270,7 +272,10 @@ impl UInt32 {
|
||||
|
||||
impl<ConstraintF: Field> ToBytesGadget<ConstraintF> for UInt32 {
|
||||
#[inline]
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(&self, _cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
_cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
let value_chunks = match self.value.map(|val| {
|
||||
use algebra::bytes::ToBytes;
|
||||
let mut bytes = [0u8; 4];
|
||||
@@ -340,9 +345,9 @@ mod test {
|
||||
use super::UInt32;
|
||||
use crate::{bits::boolean::Boolean, test_constraint_system::TestConstraintSystem};
|
||||
use algebra::fields::{bls12_381::Fr, Field};
|
||||
use r1cs_core::ConstraintSystem;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use r1cs_core::ConstraintSystem;
|
||||
|
||||
#[test]
|
||||
fn test_uint32_from_bits() {
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
use algebra::{ToConstraintField, FpParameters, Field, PrimeField};
|
||||
use algebra::{Field, FpParameters, PrimeField, ToConstraintField};
|
||||
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
use crate::boolean::AllocatedBit;
|
||||
use crate::fields::fp::FpGadget;
|
||||
use crate::prelude::*;
|
||||
use crate::Assignment;
|
||||
use crate::{boolean::AllocatedBit, fields::fp::FpGadget, prelude::*, Assignment};
|
||||
use std::borrow::Borrow;
|
||||
|
||||
/// Represents an interpretation of 8 `Boolean` objects as an
|
||||
@@ -53,7 +50,10 @@ impl UInt8 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn alloc_vec<ConstraintF, CS, T>(mut cs: CS, values: &[T]) -> Result<Vec<Self>, SynthesisError>
|
||||
pub fn alloc_vec<ConstraintF, CS, T>(
|
||||
mut cs: CS,
|
||||
values: &[T],
|
||||
) -> Result<Vec<Self>, SynthesisError>
|
||||
where
|
||||
ConstraintF: Field,
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
@@ -69,15 +69,20 @@ impl UInt8 {
|
||||
}
|
||||
|
||||
/// Allocates a vector of `u8`'s by first converting (chunks of) them to
|
||||
/// `ConstraintF` elements, (thus reducing the number of input allocations), and
|
||||
/// then converts this list of `ConstraintF` gadgets back into bytes.
|
||||
pub fn alloc_input_vec<ConstraintF, CS>(mut cs: CS, values: &[u8]) -> Result<Vec<Self>, SynthesisError>
|
||||
/// `ConstraintF` elements, (thus reducing the number of input allocations),
|
||||
/// and then converts this list of `ConstraintF` gadgets back into
|
||||
/// bytes.
|
||||
pub fn alloc_input_vec<ConstraintF, CS>(
|
||||
mut cs: CS,
|
||||
values: &[u8],
|
||||
) -> Result<Vec<Self>, SynthesisError>
|
||||
where
|
||||
ConstraintF: PrimeField,
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
{
|
||||
let values_len = values.len();
|
||||
let field_elements: Vec<ConstraintF> = ToConstraintField::<ConstraintF>::to_field_elements(values).unwrap();
|
||||
let field_elements: Vec<ConstraintF> =
|
||||
ToConstraintField::<ConstraintF>::to_field_elements(values).unwrap();
|
||||
|
||||
let max_size = 8 * (ConstraintF::Params::CAPACITY / 8) as usize;
|
||||
let mut allocated_bits = Vec::new();
|
||||
@@ -294,9 +299,9 @@ mod test {
|
||||
use super::UInt8;
|
||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem};
|
||||
use algebra::fields::bls12_381::Fr;
|
||||
use r1cs_core::ConstraintSystem;
|
||||
use rand::{Rng, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use r1cs_core::ConstraintSystem;
|
||||
|
||||
#[test]
|
||||
fn test_uint8_from_bits_to_bits() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::prelude::*;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use algebra::Field;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
/// If `condition == 1`, then enforces that `self` and `other` are equal;
|
||||
/// otherwise, it doesn't enforce anything.
|
||||
@@ -14,7 +14,9 @@ pub trait ConditionalEqGadget<ConstraintF: Field>: Eq {
|
||||
|
||||
fn cost() -> usize;
|
||||
}
|
||||
impl<T: ConditionalEqGadget<ConstraintF>, ConstraintF: Field> ConditionalEqGadget<ConstraintF> for [T] {
|
||||
impl<T: ConditionalEqGadget<ConstraintF>, ConstraintF: Field> ConditionalEqGadget<ConstraintF>
|
||||
for [T]
|
||||
{
|
||||
fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
@@ -77,7 +79,9 @@ where
|
||||
fn cost() -> usize;
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field, T: Sized + ConditionalOrEqualsGadget<ConstraintF>> OrEqualsGadget<ConstraintF> for T {
|
||||
impl<ConstraintF: Field, T: Sized + ConditionalOrEqualsGadget<ConstraintF>>
|
||||
OrEqualsGadget<ConstraintF> for T
|
||||
{
|
||||
fn enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
cond: &Boolean,
|
||||
@@ -109,8 +113,10 @@ where
|
||||
fn cost() -> usize;
|
||||
}
|
||||
|
||||
impl<ConstraintF: Field, T: Sized + ConditionalEqGadget<ConstraintF> + CondSelectGadget<ConstraintF>>
|
||||
ConditionalOrEqualsGadget<ConstraintF> for T
|
||||
impl<
|
||||
ConstraintF: Field,
|
||||
T: Sized + ConditionalEqGadget<ConstraintF> + CondSelectGadget<ConstraintF>,
|
||||
> ConditionalOrEqualsGadget<ConstraintF> for T
|
||||
{
|
||||
fn conditional_enforce_equal_or<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
@@ -130,8 +136,7 @@ impl<ConstraintF: Field, T: Sized + ConditionalEqGadget<ConstraintF> + CondSelec
|
||||
}
|
||||
|
||||
fn cost() -> usize {
|
||||
<Self as ConditionalEqGadget<ConstraintF>>::cost() + <Self as CondSelectGadget<ConstraintF>>::cost()
|
||||
<Self as ConditionalEqGadget<ConstraintF>>::cost()
|
||||
+ <Self as CondSelectGadget<ConstraintF>>::cost()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<
|
||||
|
||||
@@ -15,11 +15,10 @@ mod test {
|
||||
use rand;
|
||||
|
||||
use super::{G1Gadget, G2Gadget};
|
||||
use crate::{test_constraint_system::TestConstraintSystem, prelude::*};
|
||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem};
|
||||
use algebra::{
|
||||
curves::bls12_377::{G1Projective as G1, G2Projective as G2},
|
||||
fields::bls12_377::Fr,
|
||||
fields::bls12_377::Fq,
|
||||
fields::bls12_377::{Fq, Fr},
|
||||
AffineCurve, BitIterator, PrimeField, ProjectiveCurve,
|
||||
};
|
||||
use r1cs_core::ConstraintSystem;
|
||||
@@ -52,10 +51,7 @@ mod test {
|
||||
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
cond_select_cost,
|
||||
<G1Gadget as CondSelectGadget<Fq>>::cost()
|
||||
);
|
||||
assert_eq!(cond_select_cost, <G1Gadget as CondSelectGadget<Fq>>::cost());
|
||||
assert_eq!(add_cost, G1Gadget::cost_of_add());
|
||||
}
|
||||
|
||||
@@ -87,10 +83,7 @@ mod test {
|
||||
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
|
||||
|
||||
assert!(cs.is_satisfied());
|
||||
assert_eq!(
|
||||
cond_select_cost,
|
||||
<G2Gadget as CondSelectGadget<Fq>>::cost()
|
||||
);
|
||||
assert_eq!(cond_select_cost, <G2Gadget as CondSelectGadget<Fq>>::cost());
|
||||
assert_eq!(add_cost, G2Gadget::cost_of_add());
|
||||
}
|
||||
|
||||
|
||||
@@ -5,17 +5,23 @@ use algebra::{
|
||||
};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
|
||||
use crate::prelude::*;
|
||||
use crate::fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget};
|
||||
use crate::groups::curves::short_weierstrass::AffineGadget;
|
||||
use crate::{
|
||||
fields::{fp::FpGadget, fp2::Fp2Gadget, FieldGadget},
|
||||
groups::curves::short_weierstrass::AffineGadget,
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub mod bls12_377;
|
||||
|
||||
pub type G1Gadget<P> = AffineGadget<<P as Bls12Parameters>::G1Parameters, <P as Bls12Parameters>::Fp, FpGadget<<P as Bls12Parameters>::Fp>>;
|
||||
pub type G2Gadget<P> = AffineGadget<<P as Bls12Parameters>::G2Parameters, <P as Bls12Parameters>::Fp, Fp2G<P>>;
|
||||
pub type G1Gadget<P> = AffineGadget<
|
||||
<P as Bls12Parameters>::G1Parameters,
|
||||
<P as Bls12Parameters>::Fp,
|
||||
FpGadget<<P as Bls12Parameters>::Fp>,
|
||||
>;
|
||||
pub type G2Gadget<P> =
|
||||
AffineGadget<<P as Bls12Parameters>::G2Parameters, <P as Bls12Parameters>::Fp, Fp2G<P>>;
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(
|
||||
@@ -41,7 +47,10 @@ impl<P: Bls12Parameters> G1PreparedGadget<P> {
|
||||
|
||||
impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G1PreparedGadget<P> {
|
||||
#[inline]
|
||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
self.0.to_bytes(&mut cs.ns(|| "g_alpha to bytes"))
|
||||
}
|
||||
|
||||
@@ -66,7 +75,10 @@ pub struct G2PreparedGadget<P: Bls12Parameters> {
|
||||
|
||||
impl<P: Bls12Parameters> ToBytesGadget<P::Fp> for G2PreparedGadget<P> {
|
||||
#[inline]
|
||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(&self, mut cs: CS) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
fn to_bytes<CS: ConstraintSystem<P::Fp>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Vec<UInt8>, SynthesisError> {
|
||||
let mut bytes = Vec::new();
|
||||
for (i, coeffs) in self.ell_coeffs.iter().enumerate() {
|
||||
let mut cs = cs.ns(|| format!("Iteration {}", i));
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
use algebra::{AffineCurve, Field, ProjectiveCurve};
|
||||
use algebra::{
|
||||
curves::{
|
||||
short_weierstrass_jacobian::{GroupAffine as SWAffine, GroupProjective as SWProjective},
|
||||
SWModelParameters,
|
||||
},
|
||||
BitIterator, PrimeField,
|
||||
AffineCurve, BitIterator, Field, PrimeField, ProjectiveCurve,
|
||||
};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use std::{borrow::Borrow, marker::PhantomData, ops::Neg};
|
||||
|
||||
use crate::Assignment;
|
||||
use crate::prelude::*;
|
||||
use crate::{prelude::*, Assignment};
|
||||
|
||||
pub mod bls12;
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug, Clone)]
|
||||
#[must_use]
|
||||
pub struct AffineGadget<P: SWModelParameters, ConstraintF: Field, F: FieldGadget<P::BaseField, ConstraintF>> {
|
||||
pub struct AffineGadget<
|
||||
P: SWModelParameters,
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, ConstraintF>,
|
||||
> {
|
||||
pub x: F,
|
||||
pub y: F,
|
||||
_params: PhantomData<P>,
|
||||
@@ -80,7 +82,8 @@ where
|
||||
{
|
||||
}
|
||||
|
||||
impl<P, ConstraintF, F> GroupGadget<SWProjective<P>, ConstraintF> for AffineGadget<P, ConstraintF, F>
|
||||
impl<P, ConstraintF, F> GroupGadget<SWProjective<P>, ConstraintF>
|
||||
for AffineGadget<P, ConstraintF, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
ConstraintF: Field,
|
||||
@@ -297,7 +300,10 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
Ok(Self::new(
|
||||
self.x.clone(),
|
||||
self.y.negate(cs.ns(|| "negate y"))?,
|
||||
@@ -400,7 +406,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, ConstraintF, F> AllocGadget<SWProjective<P>, ConstraintF> for AffineGadget<P, ConstraintF, F>
|
||||
impl<P, ConstraintF, F> AllocGadget<SWProjective<P>, ConstraintF>
|
||||
for AffineGadget<P, ConstraintF, F>
|
||||
where
|
||||
P: SWModelParameters,
|
||||
ConstraintF: Field,
|
||||
@@ -572,7 +579,10 @@ where
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, 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 x_bits = self.x.to_bits(&mut cs.ns(|| "X Coordinate To Bits"))?;
|
||||
let y_bits = self.y.to_bits(&mut cs.ns(|| "Y Coordinate To Bits"))?;
|
||||
x_bits.extend_from_slice(&y_bits);
|
||||
@@ -601,7 +611,10 @@ where
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, 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 x_bytes = self.x.to_bytes(&mut cs.ns(|| "X Coordinate To Bytes"))?;
|
||||
let y_bytes = self.y.to_bytes(&mut cs.ns(|| "Y Coordinate To Bytes"))?;
|
||||
x_bytes.extend_from_slice(&y_bytes);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::groups::curves::twisted_edwards::AffineGadget;
|
||||
use algebra::curves::edwards_bls12::EdwardsParameters;
|
||||
use algebra::fields::edwards_bls12::fq::Fq;
|
||||
use algebra::{curves::edwards_bls12::EdwardsParameters, fields::edwards_bls12::fq::Fq};
|
||||
|
||||
use crate::fields::edwards_bls12::FqGadget;
|
||||
|
||||
@@ -13,8 +12,7 @@ mod test {
|
||||
groups::curves::twisted_edwards::test::{edwards_constraint_costs, edwards_test},
|
||||
test_constraint_system::TestConstraintSystem,
|
||||
};
|
||||
use algebra::fields::edwards_bls12::fq::Fq;
|
||||
use algebra::curves::edwards_bls12::EdwardsParameters;
|
||||
use algebra::{curves::edwards_bls12::EdwardsParameters, fields::edwards_bls12::fq::Fq};
|
||||
|
||||
#[test]
|
||||
fn edwards_constraint_costs_test() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::groups::curves::twisted_edwards::AffineGadget;
|
||||
use algebra::curves::edwards_sw6::EdwardsParameters;
|
||||
use algebra::fields::edwards_sw6::fq::Fq;
|
||||
use algebra::{curves::edwards_sw6::EdwardsParameters, fields::edwards_sw6::fq::Fq};
|
||||
|
||||
use crate::fields::edwards_sw6::FqGadget;
|
||||
|
||||
@@ -13,8 +12,7 @@ mod test {
|
||||
groups::curves::twisted_edwards::test::{edwards_constraint_costs, edwards_test},
|
||||
test_constraint_system::TestConstraintSystem,
|
||||
};
|
||||
use algebra::curves::edwards_sw6::EdwardsParameters;
|
||||
use algebra::fields::edwards_sw6::fq::Fq;
|
||||
use algebra::{curves::edwards_sw6::EdwardsParameters, fields::edwards_sw6::fq::Fq};
|
||||
|
||||
#[test]
|
||||
fn edwards_constraint_costs_test() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use crate::groups::curves::twisted_edwards::AffineGadget;
|
||||
use algebra::curves::jubjub::JubJubParameters;
|
||||
use algebra::fields::jubjub::fq::Fq;
|
||||
use algebra::{curves::jubjub::JubJubParameters, fields::jubjub::fq::Fq};
|
||||
|
||||
use crate::fields::jubjub::FqGadget;
|
||||
|
||||
@@ -13,8 +12,7 @@ mod test {
|
||||
groups::curves::twisted_edwards::test::{edwards_constraint_costs, edwards_test},
|
||||
test_constraint_system::TestConstraintSystem,
|
||||
};
|
||||
use algebra::fields::jubjub::fq::Fq;
|
||||
use algebra::curves::jubjub::JubJubParameters as EdwardsParameters;
|
||||
use algebra::{curves::jubjub::JubJubParameters as EdwardsParameters, fields::jubjub::fq::Fq};
|
||||
|
||||
#[test]
|
||||
fn edwards_constraint_costs_test() {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
use algebra::{
|
||||
curves::{twisted_edwards_extended::GroupAffine as TEAffine, TEModelParameters},
|
||||
BitIterator, Field
|
||||
curves::{
|
||||
twisted_edwards_extended::GroupAffine as TEAffine, MontgomeryModelParameters,
|
||||
TEModelParameters,
|
||||
},
|
||||
BitIterator, Field,
|
||||
};
|
||||
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
@@ -19,7 +22,185 @@ mod test;
|
||||
#[derivative(Debug, Clone)]
|
||||
#[derivative(Debug(bound = "P: TEModelParameters, ConstraintF: Field"))]
|
||||
#[must_use]
|
||||
pub struct AffineGadget<P: TEModelParameters, ConstraintF: Field, F: FieldGadget<P::BaseField, ConstraintF>> {
|
||||
pub struct MontgomeryAffineGadget<
|
||||
P: TEModelParameters,
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, ConstraintF>,
|
||||
> {
|
||||
pub x: F,
|
||||
pub y: F,
|
||||
#[derivative(Debug = "ignore")]
|
||||
_params: PhantomData<P>,
|
||||
#[derivative(Debug = "ignore")]
|
||||
_engine: PhantomData<ConstraintF>,
|
||||
}
|
||||
|
||||
mod montgomery_affine_impl {
|
||||
use super::*;
|
||||
use crate::Assignment;
|
||||
use algebra::{twisted_edwards_extended::GroupAffine, AffineCurve, Field};
|
||||
use std::ops::{AddAssign, MulAssign, SubAssign};
|
||||
|
||||
impl<P: TEModelParameters, ConstraintF: Field, F: FieldGadget<P::BaseField, ConstraintF>>
|
||||
MontgomeryAffineGadget<P, ConstraintF, F>
|
||||
{
|
||||
pub fn new(x: F, y: F) -> Self {
|
||||
Self {
|
||||
x,
|
||||
y,
|
||||
_params: PhantomData,
|
||||
_engine: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_edwards_to_coords(
|
||||
p: &TEAffine<P>,
|
||||
) -> Result<(P::BaseField, P::BaseField), SynthesisError> {
|
||||
let montgomery_point: GroupAffine<P> = if p.y == P::BaseField::one() {
|
||||
GroupAffine::zero()
|
||||
} else {
|
||||
if p.x == P::BaseField::zero() {
|
||||
GroupAffine::new(P::BaseField::zero(), P::BaseField::zero())
|
||||
} else {
|
||||
let u = (P::BaseField::one() + &p.y)
|
||||
* &(P::BaseField::one() - &p.y).inverse().unwrap();
|
||||
let v = u * &p.x.inverse().unwrap();
|
||||
GroupAffine::new(u, v)
|
||||
}
|
||||
};
|
||||
|
||||
Ok((montgomery_point.x, montgomery_point.y))
|
||||
}
|
||||
|
||||
pub fn from_edwards<CS: ConstraintSystem<ConstraintF>>(
|
||||
mut cs: CS,
|
||||
p: &TEAffine<P>,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let montgomery_coords = Self::from_edwards_to_coords(p)?;
|
||||
|
||||
let u = F::alloc(cs.ns(|| "u"), || Ok(montgomery_coords.0))?;
|
||||
|
||||
let v = F::alloc(cs.ns(|| "v"), || Ok(montgomery_coords.1))?;
|
||||
|
||||
Ok(Self::new(u, v))
|
||||
}
|
||||
|
||||
pub fn into_edwards<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<AffineGadget<P, ConstraintF, F>, SynthesisError> {
|
||||
// Compute u = x / y
|
||||
let u = F::alloc(cs.ns(|| "u"), || {
|
||||
let mut t0 = self.x.get_value().get()?;
|
||||
|
||||
match self.y.get_value().get()?.inverse() {
|
||||
Some(invy) => {
|
||||
t0.mul_assign(&invy);
|
||||
|
||||
Ok(t0)
|
||||
},
|
||||
None => Err(SynthesisError::DivisionByZero),
|
||||
}
|
||||
})?;
|
||||
|
||||
u.mul_equals(cs.ns(|| "u equals"), &self.y, &self.x)?;
|
||||
|
||||
let v = F::alloc(cs.ns(|| "v"), || {
|
||||
let mut t0 = self.x.get_value().get()?;
|
||||
let mut t1 = t0.clone();
|
||||
t0.sub_assign(&P::BaseField::one());
|
||||
t1.add_assign(&P::BaseField::one());
|
||||
|
||||
match t1.inverse() {
|
||||
Some(t1) => {
|
||||
t0.mul_assign(&t1);
|
||||
|
||||
Ok(t0)
|
||||
},
|
||||
None => Err(SynthesisError::DivisionByZero),
|
||||
}
|
||||
})?;
|
||||
|
||||
let xplusone = self
|
||||
.x
|
||||
.add_constant(cs.ns(|| "x plus one"), &P::BaseField::one())?;
|
||||
let xminusone = self
|
||||
.x
|
||||
.sub_constant(cs.ns(|| "x minus one"), &P::BaseField::one())?;
|
||||
v.mul_equals(cs.ns(|| "v equals"), &xplusone, &xminusone)?;
|
||||
|
||||
Ok(AffineGadget::new(u, v))
|
||||
}
|
||||
|
||||
pub fn add<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
other: &Self,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
let lambda = F::alloc(cs.ns(|| "lambda"), || {
|
||||
let mut n = other.y.get_value().get()?;
|
||||
n.sub_assign(&self.y.get_value().get()?);
|
||||
|
||||
let mut d = other.x.get_value().get()?;
|
||||
d.sub_assign(&self.x.get_value().get()?);
|
||||
|
||||
match d.inverse() {
|
||||
Some(d) => {
|
||||
n.mul_assign(&d);
|
||||
Ok(n)
|
||||
},
|
||||
None => Err(SynthesisError::DivisionByZero),
|
||||
}
|
||||
})?;
|
||||
let lambda_n = other.y.sub(cs.ns(|| "other.y - self.y"), &self.y)?;
|
||||
let lambda_d = other.x.sub(cs.ns(|| "other.x - self.x"), &self.x)?;
|
||||
lambda_d.mul_equals(cs.ns(|| "lambda equals"), &lambda, &lambda_n)?;
|
||||
|
||||
// Compute x'' = B*lambda^2 - A - x - x'
|
||||
let xprime = F::alloc(cs.ns(|| "xprime"), || {
|
||||
Ok(
|
||||
lambda.get_value().get()?.square() * &P::MontgomeryModelParameters::COEFF_B
|
||||
- &P::MontgomeryModelParameters::COEFF_A
|
||||
- &self.x.get_value().get()?
|
||||
- &other.x.get_value().get()?,
|
||||
)
|
||||
})?;
|
||||
|
||||
let xprime_lc = self
|
||||
.x
|
||||
.add(cs.ns(|| "self.x + other.x"), &other.x)?
|
||||
.add(cs.ns(|| "+ xprime"), &xprime)?
|
||||
.add_constant(cs.ns(|| "+ A"), &P::MontgomeryModelParameters::COEFF_A)?;
|
||||
// (lambda) * (lambda) = (A + x + x' + x'')
|
||||
let lambda_b = lambda.mul_by_constant(
|
||||
cs.ns(|| "lambda * b"),
|
||||
&P::MontgomeryModelParameters::COEFF_B,
|
||||
)?;
|
||||
lambda_b.mul_equals(cs.ns(|| "xprime equals"), &lambda, &xprime_lc)?;
|
||||
|
||||
let yprime = F::alloc(cs.ns(|| "yprime"), || {
|
||||
Ok(-(self.y.get_value().get()?
|
||||
+ &(lambda.get_value().get()?
|
||||
* &(xprime.get_value().get()? - &self.x.get_value().get()?))))
|
||||
})?;
|
||||
|
||||
let xres = self.x.sub(cs.ns(|| "xres"), &xprime)?;
|
||||
let yres = self.y.add(cs.ns(|| "yres"), &yprime)?;
|
||||
lambda.mul_equals(cs.ns(|| "yprime equals"), &xres, &yres)?;
|
||||
Ok(MontgomeryAffineGadget::new(xprime, yprime))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Derivative)]
|
||||
#[derivative(Debug, Clone)]
|
||||
#[derivative(Debug(bound = "P: TEModelParameters, ConstraintF: Field"))]
|
||||
#[must_use]
|
||||
pub struct AffineGadget<
|
||||
P: TEModelParameters,
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, ConstraintF>,
|
||||
> {
|
||||
pub x: F,
|
||||
pub y: F,
|
||||
#[derivative(Debug = "ignore")]
|
||||
@@ -293,7 +474,10 @@ mod affine_impl {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
Ok(Self::new(
|
||||
self.x.negate(cs.ns(|| "negate x"))?,
|
||||
self.y.clone(),
|
||||
@@ -487,7 +671,8 @@ mod projective_impl {
|
||||
};
|
||||
use std::ops::Neg;
|
||||
|
||||
impl<P, ConstraintF, F> GroupGadget<TEProjective<P>, ConstraintF> for AffineGadget<P, ConstraintF, F>
|
||||
impl<P, ConstraintF, F> GroupGadget<TEProjective<P>, ConstraintF>
|
||||
for AffineGadget<P, ConstraintF, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
ConstraintF: Field,
|
||||
@@ -694,7 +879,10 @@ mod projective_impl {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, mut cs: CS) -> Result<Self, SynthesisError> {
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
mut cs: CS,
|
||||
) -> Result<Self, SynthesisError> {
|
||||
Ok(Self::new(
|
||||
self.x.negate(cs.ns(|| "negate x"))?,
|
||||
self.y.clone(),
|
||||
@@ -757,6 +945,141 @@ mod projective_impl {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn precomputed_base_3_bit_signed_digit_scalar_mul<'a, CS, I, J, B>(
|
||||
mut cs: CS,
|
||||
bases: &[B],
|
||||
scalars: &[J],
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
I: Borrow<[Boolean]>,
|
||||
J: Borrow<[I]>,
|
||||
B: Borrow<[TEProjective<P>]>,
|
||||
{
|
||||
const CHUNK_SIZE: usize = 3;
|
||||
let mut edwards_result: Option<AffineGadget<P, ConstraintF, F>> = None;
|
||||
let mut result: Option<MontgomeryAffineGadget<P, ConstraintF, F>> = None;
|
||||
|
||||
let mut process_segment_result =
|
||||
|mut cs: r1cs_core::Namespace<_, _>,
|
||||
result: &MontgomeryAffineGadget<P, ConstraintF, F>|
|
||||
-> Result<(), SynthesisError> {
|
||||
let segment_result = result.into_edwards(cs.ns(|| "segment result"))?;
|
||||
match edwards_result {
|
||||
None => {
|
||||
edwards_result = Some(segment_result);
|
||||
},
|
||||
Some(ref mut edwards_result) => {
|
||||
*edwards_result = GroupGadget::<TEAffine<P>, ConstraintF>::add(
|
||||
&segment_result,
|
||||
cs.ns(|| "edwards addition"),
|
||||
edwards_result,
|
||||
)?;
|
||||
},
|
||||
}
|
||||
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// Compute ∏(h_i^{m_i}) for all i.
|
||||
for (segment_i, (segment_bits_chunks, segment_powers)) in
|
||||
scalars.into_iter().zip(bases.iter()).enumerate()
|
||||
{
|
||||
for (i, (bits, base_power)) in segment_bits_chunks
|
||||
.borrow()
|
||||
.into_iter()
|
||||
.zip(segment_powers.borrow().iter())
|
||||
.enumerate()
|
||||
{
|
||||
let base_power = base_power.borrow();
|
||||
let mut acc_power = *base_power;
|
||||
let mut coords = vec![];
|
||||
for _ in 0..4 {
|
||||
coords.push(acc_power);
|
||||
acc_power = acc_power + base_power;
|
||||
}
|
||||
|
||||
let bits = bits.borrow().to_bits(
|
||||
&mut cs.ns(|| format!("Convert Scalar {}, {} to bits", segment_i, i)),
|
||||
)?;
|
||||
if bits.len() != CHUNK_SIZE {
|
||||
return Err(SynthesisError::Unsatisfiable);
|
||||
}
|
||||
|
||||
let coords = coords
|
||||
.iter()
|
||||
.map(|p| {
|
||||
let p = p.into_affine();
|
||||
MontgomeryAffineGadget::<P, ConstraintF, F>::from_edwards_to_coords(&p)
|
||||
.unwrap()
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let x_coeffs = coords.iter().map(|p| p.0).collect::<Vec<_>>();
|
||||
let y_coeffs = coords.iter().map(|p| p.1).collect::<Vec<_>>();
|
||||
|
||||
let precomp = Boolean::and(
|
||||
cs.ns(|| format!("precomp in window {}, {}", segment_i, i)),
|
||||
&bits[0],
|
||||
&bits[1],
|
||||
)?;
|
||||
|
||||
let x = F::zero(cs.ns(|| format!("x in window {}, {}", segment_i, i)))?
|
||||
.conditionally_add_constant(
|
||||
cs.ns(|| format!("add bool 00 in window {}, {}", segment_i, i)),
|
||||
&Boolean::constant(true),
|
||||
x_coeffs[0],
|
||||
)?
|
||||
.conditionally_add_constant(
|
||||
cs.ns(|| format!("add bool 01 in window {}, {}", segment_i, i)),
|
||||
&bits[0],
|
||||
x_coeffs[1] - &x_coeffs[0],
|
||||
)?
|
||||
.conditionally_add_constant(
|
||||
cs.ns(|| format!("add bool 10 in window {}, {}", segment_i, i)),
|
||||
&bits[1],
|
||||
x_coeffs[2] - &x_coeffs[0],
|
||||
)?
|
||||
.conditionally_add_constant(
|
||||
cs.ns(|| format!("add bool 11 in window {}, {}", segment_i, i)),
|
||||
&precomp,
|
||||
x_coeffs[3] - &x_coeffs[2] - &x_coeffs[1] + &x_coeffs[0],
|
||||
)?;
|
||||
|
||||
let y = F::three_bit_cond_neg_lookup(
|
||||
cs.ns(|| format!("y lookup in window {}, {}", segment_i, i)),
|
||||
&bits,
|
||||
&precomp,
|
||||
&y_coeffs,
|
||||
)?;
|
||||
|
||||
let tmp = MontgomeryAffineGadget::new(x, y);
|
||||
|
||||
match result {
|
||||
None => {
|
||||
result = Some(tmp);
|
||||
},
|
||||
Some(ref mut result) => {
|
||||
*result = tmp.add(
|
||||
cs.ns(|| format!("addition of window {}, {}", segment_i, i)),
|
||||
result,
|
||||
)?;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
process_segment_result(
|
||||
cs.ns(|| format!("window {}", segment_i)),
|
||||
&result.unwrap(),
|
||||
)?;
|
||||
result = None;
|
||||
}
|
||||
if result.is_some() {
|
||||
process_segment_result(cs.ns(|| "leftover"), &result.unwrap())?;
|
||||
}
|
||||
Ok(edwards_result.unwrap())
|
||||
}
|
||||
|
||||
fn cost_of_add() -> usize {
|
||||
4 + 2 * F::cost_of_mul()
|
||||
}
|
||||
@@ -766,7 +1089,8 @@ mod projective_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P, ConstraintF, F> AllocGadget<TEProjective<P>, ConstraintF> for AffineGadget<P, ConstraintF, F>
|
||||
impl<P, ConstraintF, F> AllocGadget<TEProjective<P>, ConstraintF>
|
||||
for AffineGadget<P, ConstraintF, F>
|
||||
where
|
||||
P: TEModelParameters,
|
||||
ConstraintF: Field,
|
||||
@@ -1033,7 +1357,10 @@ where
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, 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 x_bits = self.x.to_bits(cs.ns(|| "X Coordinate To Bits"))?;
|
||||
let y_bits = self.y.to_bits(cs.ns(|| "Y Coordinate To Bits"))?;
|
||||
x_bits.extend_from_slice(&y_bits);
|
||||
@@ -1058,7 +1385,10 @@ where
|
||||
ConstraintF: Field,
|
||||
F: FieldGadget<P::BaseField, 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 x_bytes = self.x.to_bytes(cs.ns(|| "x"))?;
|
||||
let y_bytes = self.y.to_bytes(cs.ns(|| "y"))?;
|
||||
x_bytes.extend_from_slice(&y_bytes);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use rand::thread_rng;
|
||||
|
||||
use crate::{prelude::*, groups::test::group_test};
|
||||
use crate::{groups::test::group_test, prelude::*};
|
||||
|
||||
use algebra::{
|
||||
curves::{models::TEModelParameters, twisted_edwards_extended::GroupAffine as TEAffine},
|
||||
BitIterator, Group, PrimeField, Field, UniformRand,
|
||||
BitIterator, Field, Group, PrimeField, UniformRand,
|
||||
};
|
||||
|
||||
use r1cs_core::ConstraintSystem;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::prelude::*;
|
||||
use algebra::{Group, Field};
|
||||
use algebra::{Field, Group};
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
use std::{borrow::Borrow, fmt::Debug};
|
||||
@@ -31,7 +31,11 @@ pub trait GroupGadget<G: Group, ConstraintF: Field>:
|
||||
|
||||
fn zero<CS: ConstraintSystem<ConstraintF>>(cs: CS) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS, other: &Self) -> Result<Self, SynthesisError>;
|
||||
fn add<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
cs: CS,
|
||||
other: &Self,
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn sub<CS: ConstraintSystem<ConstraintF>>(
|
||||
&self,
|
||||
@@ -57,7 +61,10 @@ pub trait GroupGadget<G: Group, ConstraintF: Field>:
|
||||
self.add_constant(cs.ns(|| "Self - other"), &neg_other)
|
||||
}
|
||||
|
||||
fn double_in_place<CS: ConstraintSystem<ConstraintF>>(&mut self, cs: CS) -> Result<(), SynthesisError>;
|
||||
fn double_in_place<CS: ConstraintSystem<ConstraintF>>(
|
||||
&mut self,
|
||||
cs: CS,
|
||||
) -> Result<(), SynthesisError>;
|
||||
|
||||
fn negate<CS: ConstraintSystem<ConstraintF>>(&self, cs: CS) -> Result<Self, SynthesisError>;
|
||||
|
||||
@@ -111,6 +118,20 @@ pub trait GroupGadget<G: Group, ConstraintF: Field>:
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn precomputed_base_3_bit_signed_digit_scalar_mul<'a, CS, I, J, B>(
|
||||
_: CS,
|
||||
_: &[B],
|
||||
_: &[J],
|
||||
) -> Result<Self, SynthesisError>
|
||||
where
|
||||
CS: ConstraintSystem<ConstraintF>,
|
||||
I: Borrow<[Boolean]>,
|
||||
J: Borrow<[I]>,
|
||||
B: Borrow<[G]>,
|
||||
{
|
||||
Err(SynthesisError::AssignmentMissing)
|
||||
}
|
||||
|
||||
fn precomputed_base_multiscalar_mul<'a, CS, T, I, B>(
|
||||
mut cs: CS,
|
||||
bases: &[B],
|
||||
@@ -145,9 +166,7 @@ mod test {
|
||||
use algebra::Field;
|
||||
use r1cs_core::ConstraintSystem;
|
||||
|
||||
use crate::{
|
||||
prelude::*, test_constraint_system::TestConstraintSystem,
|
||||
};
|
||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem};
|
||||
use algebra::groups::Group;
|
||||
use rand;
|
||||
|
||||
@@ -203,8 +222,7 @@ mod test {
|
||||
#[test]
|
||||
fn jubjub_group_gadgets_test() {
|
||||
use crate::groups::jubjub::JubJubGadget;
|
||||
use algebra::fields::jubjub::fq::Fq;
|
||||
use algebra::curves::jubjub::JubJubProjective;
|
||||
use algebra::{curves::jubjub::JubJubProjective, fields::jubjub::fq::Fq};
|
||||
|
||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
||||
|
||||
|
||||
@@ -49,18 +49,20 @@ pub mod groups;
|
||||
|
||||
pub mod pairing;
|
||||
|
||||
pub mod alloc;
|
||||
pub mod eq;
|
||||
pub mod select;
|
||||
pub mod alloc;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::eq::*;
|
||||
pub use crate::select::*;
|
||||
pub use crate::alloc::*;
|
||||
pub use crate::fields::FieldGadget;
|
||||
pub use crate::groups::GroupGadget;
|
||||
pub use crate::pairing::PairingGadget;
|
||||
pub use crate::bits::{ToBitsGadget, ToBytesGadget, boolean::Boolean, uint8::UInt8, uint32::UInt32};
|
||||
pub use crate::{
|
||||
alloc::*,
|
||||
bits::{boolean::Boolean, uint32::UInt32, uint8::UInt8, ToBitsGadget, ToBytesGadget},
|
||||
eq::*,
|
||||
fields::FieldGadget,
|
||||
groups::GroupGadget,
|
||||
pairing::PairingGadget,
|
||||
select::*,
|
||||
};
|
||||
}
|
||||
|
||||
pub trait Assignment<T> {
|
||||
|
||||
@@ -65,14 +65,18 @@ mod test {
|
||||
#[test]
|
||||
fn bls12_377_gadget_bilinearity_test() {
|
||||
use algebra::{
|
||||
fields::{bls12_377::{fr::Fr, fq::Fq}, PrimeField},
|
||||
fields::{
|
||||
bls12_377::{fq::Fq, fr::Fr},
|
||||
PrimeField,
|
||||
},
|
||||
PairingEngine, ProjectiveCurve,
|
||||
};
|
||||
|
||||
use super::bls12_377::PairingGadget;
|
||||
use crate::{
|
||||
groups::bls12::bls12_377::{G1Gadget, G1PreparedGadget, G2Gadget, G2PreparedGadget},
|
||||
prelude::*, pairing::PairingGadget as _,
|
||||
pairing::PairingGadget as _,
|
||||
prelude::*,
|
||||
};
|
||||
use algebra::curves::bls12_377::{Bls12_377, G1Projective, G2Projective};
|
||||
use std::ops::Mul;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::prelude::*;
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
use algebra::Field;
|
||||
|
||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||
|
||||
/// If condition is `true`, return `first`; else, select `second`.
|
||||
pub trait CondSelectGadget<ConstraintF: Field>
|
||||
@@ -33,4 +32,19 @@ where
|
||||
fn cost() -> usize;
|
||||
}
|
||||
|
||||
/// Uses three bits to perform a lookup into a table, where the last bit
|
||||
/// performs negation
|
||||
pub trait ThreeBitCondNegLookupGadget<ConstraintF: Field>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
type TableConstant;
|
||||
fn three_bit_cond_neg_lookup<CS: ConstraintSystem<ConstraintF>>(
|
||||
cs: CS,
|
||||
bits: &[Boolean],
|
||||
b0b1: &Boolean,
|
||||
constants: &[Self::TableConstant],
|
||||
) -> Result<Self, SynthesisError>;
|
||||
|
||||
fn cost() -> usize;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user