mirror of
https://github.com/arnaucube/ark-r1cs-std.git
synced 2026-01-30 15:36:39 +01:00
Merge branch 'master' into inline-asm
This commit is contained in:
@@ -3,7 +3,7 @@ use r1cs_core::{ConstraintSystem, SynthesisError};
|
|||||||
use crate::{
|
use crate::{
|
||||||
commitment::blake2s::Blake2sCommitment,
|
commitment::blake2s::Blake2sCommitment,
|
||||||
prf::blake2s::constraints::{blake2s_gadget, Blake2sOutputGadget},
|
prf::blake2s::constraints::{blake2s_gadget, Blake2sOutputGadget},
|
||||||
CommitmentGadget,
|
CommitmentGadget, Vec,
|
||||||
};
|
};
|
||||||
use algebra_core::{Field, PrimeField};
|
use algebra_core::{Field, PrimeField};
|
||||||
use r1cs_std::prelude::*;
|
use r1cs_std::prelude::*;
|
||||||
@@ -48,6 +48,16 @@ impl<ConstraintF: PrimeField> CommitmentGadget<Blake2sCommitment, ConstraintF>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ConstraintF: Field> AllocGadget<(), ConstraintF> for Blake2sParametersGadget {
|
impl<ConstraintF: Field> AllocGadget<(), ConstraintF> for Blake2sParametersGadget {
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<()>,
|
||||||
|
{
|
||||||
|
Self::alloc(cs, || Ok(val))
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError>
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(_: CS, _: F) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
F: FnOnce() -> Result<T, SynthesisError>,
|
||||||
@@ -69,6 +79,22 @@ impl<ConstraintF: Field> AllocGadget<(), ConstraintF> for Blake2sParametersGadge
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget {
|
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sRandomnessGadget {
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<[u8; 32]>,
|
||||||
|
{
|
||||||
|
let mut bytes = vec![];
|
||||||
|
for (i, b) in val.borrow().iter().enumerate() {
|
||||||
|
bytes.push(UInt8::alloc_constant(cs.ns(|| format!("value {}", i)), b)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Blake2sRandomnessGadget(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
cs: CS,
|
cs: CS,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
commitment::pedersen::{PedersenCommitment, PedersenParameters, PedersenRandomness},
|
commitment::pedersen::{PedersenCommitment, PedersenParameters, PedersenRandomness},
|
||||||
crh::pedersen::PedersenWindow,
|
crh::pedersen::PedersenWindow,
|
||||||
|
Vec,
|
||||||
};
|
};
|
||||||
use algebra_core::{
|
use algebra_core::{
|
||||||
fields::{Field, PrimeField},
|
fields::{Field, PrimeField},
|
||||||
@@ -97,16 +98,14 @@ where
|
|||||||
W: PedersenWindow,
|
W: PedersenWindow,
|
||||||
ConstraintF: PrimeField,
|
ConstraintF: PrimeField,
|
||||||
{
|
{
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
_cs: CS,
|
_cs: CS,
|
||||||
value_gen: F,
|
val: T,
|
||||||
) -> Result<Self, SynthesisError>
|
) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
|
||||||
T: Borrow<PedersenParameters<G>>,
|
T: Borrow<PedersenParameters<G>>,
|
||||||
{
|
{
|
||||||
let temp = value_gen()?;
|
let parameters = val.borrow().clone();
|
||||||
let parameters = temp.borrow().clone();
|
|
||||||
|
|
||||||
Ok(PedersenCommitmentGadgetParameters {
|
Ok(PedersenCommitmentGadgetParameters {
|
||||||
params: parameters,
|
params: parameters,
|
||||||
@@ -116,6 +115,18 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
|
value_gen: F,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
F: FnOnce() -> Result<T, SynthesisError>,
|
||||||
|
T: Borrow<PedersenParameters<G>>,
|
||||||
|
{
|
||||||
|
let temp = value_gen()?;
|
||||||
|
Self::alloc_constant(cs, temp)
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
_cs: CS,
|
_cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
@@ -141,6 +152,21 @@ where
|
|||||||
G: Group,
|
G: Group,
|
||||||
ConstraintF: PrimeField,
|
ConstraintF: PrimeField,
|
||||||
{
|
{
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<PedersenRandomness<G>>,
|
||||||
|
{
|
||||||
|
let mut result_bytes = vec![];
|
||||||
|
for (i, byte) in to_bytes![val.borrow().0].unwrap().into_iter().enumerate() {
|
||||||
|
let cur = UInt8::alloc_constant(cs.ns(|| format!("byte {}", i)), byte)?;
|
||||||
|
result_bytes.push(cur);
|
||||||
|
}
|
||||||
|
Ok(PedersenRandomnessGadget(result_bytes))
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
cs: CS,
|
cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
use core::{borrow::Borrow, hash::Hash, marker::PhantomData};
|
use core::{borrow::Borrow, hash::Hash, marker::PhantomData};
|
||||||
|
|
||||||
use crate::crh::{
|
use crate::{
|
||||||
|
crh::{
|
||||||
bowe_hopwood::{BoweHopwoodPedersenCRH, BoweHopwoodPedersenParameters, CHUNK_SIZE},
|
bowe_hopwood::{BoweHopwoodPedersenCRH, BoweHopwoodPedersenParameters, CHUNK_SIZE},
|
||||||
pedersen::PedersenWindow,
|
pedersen::PedersenWindow,
|
||||||
FixedLengthCRHGadget,
|
FixedLengthCRHGadget,
|
||||||
|
},
|
||||||
|
Vec,
|
||||||
};
|
};
|
||||||
use algebra_core::{groups::Group, Field};
|
use algebra_core::{groups::Group, Field};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||||
@@ -86,8 +89,24 @@ impl<G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, Constra
|
|||||||
AllocGadget<BoweHopwoodPedersenParameters<G>, ConstraintF>
|
AllocGadget<BoweHopwoodPedersenParameters<G>, ConstraintF>
|
||||||
for BoweHopwoodPedersenCRHGadgetParameters<G, W, ConstraintF, GG>
|
for BoweHopwoodPedersenCRHGadgetParameters<G, W, ConstraintF, GG>
|
||||||
{
|
{
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
_cs: CS,
|
_cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<BoweHopwoodPedersenParameters<G>>,
|
||||||
|
{
|
||||||
|
let params = val.borrow().clone();
|
||||||
|
Ok(BoweHopwoodPedersenCRHGadgetParameters {
|
||||||
|
params,
|
||||||
|
_group_g: PhantomData,
|
||||||
|
_engine: PhantomData,
|
||||||
|
_window: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
) -> Result<Self, SynthesisError>
|
) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
@@ -95,12 +114,7 @@ impl<G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, Constra
|
|||||||
T: Borrow<BoweHopwoodPedersenParameters<G>>,
|
T: Borrow<BoweHopwoodPedersenParameters<G>>,
|
||||||
{
|
{
|
||||||
let params = value_gen()?.borrow().clone();
|
let params = value_gen()?.borrow().clone();
|
||||||
Ok(BoweHopwoodPedersenCRHGadgetParameters {
|
Self::alloc_constant(cs, params)
|
||||||
params,
|
|
||||||
_group_g: PhantomData,
|
|
||||||
_engine: PhantomData,
|
|
||||||
_window: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
use crate::crh::{
|
use crate::{
|
||||||
|
crh::{
|
||||||
pedersen::{PedersenCRH, PedersenParameters, PedersenWindow},
|
pedersen::{PedersenCRH, PedersenParameters, PedersenWindow},
|
||||||
FixedLengthCRHGadget,
|
FixedLengthCRHGadget,
|
||||||
|
},
|
||||||
|
Vec,
|
||||||
};
|
};
|
||||||
use algebra_core::{Field, Group};
|
use algebra_core::{Field, Group};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||||
@@ -77,8 +80,24 @@ impl<G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, Constra
|
|||||||
AllocGadget<PedersenParameters<G>, ConstraintF>
|
AllocGadget<PedersenParameters<G>, ConstraintF>
|
||||||
for PedersenCRHGadgetParameters<G, W, ConstraintF, GG>
|
for PedersenCRHGadgetParameters<G, W, ConstraintF, GG>
|
||||||
{
|
{
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
_cs: CS,
|
_cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<PedersenParameters<G>>,
|
||||||
|
{
|
||||||
|
let params = val.borrow().clone();
|
||||||
|
Ok(PedersenCRHGadgetParameters {
|
||||||
|
params,
|
||||||
|
_group_g: PhantomData,
|
||||||
|
_engine: PhantomData,
|
||||||
|
_window: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
) -> Result<Self, SynthesisError>
|
) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
@@ -86,12 +105,7 @@ impl<G: Group, W: PedersenWindow, ConstraintF: Field, GG: GroupGadget<G, Constra
|
|||||||
T: Borrow<PedersenParameters<G>>,
|
T: Borrow<PedersenParameters<G>>,
|
||||||
{
|
{
|
||||||
let params = value_gen()?.borrow().clone();
|
let params = value_gen()?.borrow().clone();
|
||||||
Ok(PedersenCRHGadgetParameters {
|
Self::alloc_constant(cs, params)
|
||||||
params,
|
|
||||||
_group_g: PhantomData,
|
|
||||||
_engine: PhantomData,
|
|
||||||
_window: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
|||||||
@@ -128,6 +128,28 @@ where
|
|||||||
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
|
HGadget: FixedLengthCRHGadget<P::H, ConstraintF>,
|
||||||
ConstraintF: Field,
|
ConstraintF: Field,
|
||||||
{
|
{
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<MerkleTreePath<P>>,
|
||||||
|
{
|
||||||
|
let mut path = Vec::new();
|
||||||
|
for (i, &(ref l, ref r)) in val.borrow().path.iter().enumerate() {
|
||||||
|
let l_hash = HGadget::OutputGadget::alloc_constant(
|
||||||
|
&mut cs.ns(|| format!("l_child_{}", i)),
|
||||||
|
l.clone(),
|
||||||
|
)?;
|
||||||
|
let r_hash = HGadget::OutputGadget::alloc_constant(
|
||||||
|
&mut cs.ns(|| format!("r_child_{}", i)),
|
||||||
|
r.clone(),
|
||||||
|
)?;
|
||||||
|
path.push((l_hash, r_hash));
|
||||||
|
}
|
||||||
|
Ok(MerkleTreePathGadget { path })
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
|
|||||||
@@ -20,4 +20,16 @@ pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
|
|||||||
CS: ConstraintSystem<ConstraintF>,
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
I: Iterator<Item = &'a T>,
|
I: Iterator<Item = &'a T>,
|
||||||
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
|
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
|
||||||
|
|
||||||
|
fn conditional_check_verify<'a, CS, I, T>(
|
||||||
|
cs: CS,
|
||||||
|
verification_key: &Self::VerificationKeyGadget,
|
||||||
|
input: I,
|
||||||
|
proof: &Self::ProofGadget,
|
||||||
|
condition: &Boolean,
|
||||||
|
) -> Result<(), SynthesisError>
|
||||||
|
where
|
||||||
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
|
I: Iterator<Item = &'a T>,
|
||||||
|
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::nizk::{gm17::Gm17, NIZKVerifierGadget};
|
use crate::{
|
||||||
|
nizk::{gm17::Gm17, NIZKVerifierGadget},
|
||||||
|
Vec,
|
||||||
|
};
|
||||||
use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField};
|
use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField};
|
||||||
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
|
||||||
use r1cs_std::prelude::*;
|
use r1cs_std::prelude::*;
|
||||||
@@ -106,10 +109,31 @@ where
|
|||||||
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;
|
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;
|
||||||
|
|
||||||
fn check_verify<'a, CS, I, T>(
|
fn check_verify<'a, CS, I, T>(
|
||||||
|
cs: CS,
|
||||||
|
vk: &Self::VerificationKeyGadget,
|
||||||
|
public_inputs: I,
|
||||||
|
proof: &Self::ProofGadget,
|
||||||
|
) -> Result<(), SynthesisError>
|
||||||
|
where
|
||||||
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
|
I: Iterator<Item = &'a T>,
|
||||||
|
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
|
||||||
|
{
|
||||||
|
<Self as NIZKVerifierGadget<Gm17<PairingE, C, V>, ConstraintF>>::conditional_check_verify(
|
||||||
|
cs,
|
||||||
|
vk,
|
||||||
|
public_inputs,
|
||||||
|
proof,
|
||||||
|
&Boolean::constant(true),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conditional_check_verify<'a, CS, I, T>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
vk: &Self::VerificationKeyGadget,
|
vk: &Self::VerificationKeyGadget,
|
||||||
mut public_inputs: I,
|
mut public_inputs: I,
|
||||||
proof: &Self::ProofGadget,
|
proof: &Self::ProofGadget,
|
||||||
|
condition: &Boolean,
|
||||||
) -> Result<(), SynthesisError>
|
) -> Result<(), SynthesisError>
|
||||||
where
|
where
|
||||||
CS: ConstraintSystem<ConstraintF>,
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
@@ -186,8 +210,8 @@ where
|
|||||||
let test2 = P::final_exponentiation(cs.ns(|| "Final Exp 2"), &test2_exp)?;
|
let test2 = P::final_exponentiation(cs.ns(|| "Final Exp 2"), &test2_exp)?;
|
||||||
|
|
||||||
let one = P::GTGadget::one(cs.ns(|| "GT One"))?;
|
let one = P::GTGadget::one(cs.ns(|| "GT One"))?;
|
||||||
test1.enforce_equal(cs.ns(|| "Test 1"), &one)?;
|
test1.conditional_enforce_equal(cs.ns(|| "Test 1"), &one, condition)?;
|
||||||
test2.enforce_equal(cs.ns(|| "Test 2"), &one)?;
|
test2.conditional_enforce_equal(cs.ns(|| "Test 2"), &one, condition)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -199,6 +223,54 @@ where
|
|||||||
ConstraintF: Field,
|
ConstraintF: Field,
|
||||||
P: PairingGadget<PairingE, ConstraintF>,
|
P: PairingGadget<PairingE, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<VerifyingKey<PairingE>>,
|
||||||
|
{
|
||||||
|
let VerifyingKey {
|
||||||
|
h_g2,
|
||||||
|
g_alpha_g1,
|
||||||
|
h_beta_g2,
|
||||||
|
g_gamma_g1,
|
||||||
|
h_gamma_g2,
|
||||||
|
query,
|
||||||
|
} = val.borrow().clone();
|
||||||
|
let h_g2 = P::G2Gadget::alloc_constant(cs.ns(|| "h_g2"), h_g2.into_projective())?;
|
||||||
|
let g_alpha_g1 =
|
||||||
|
P::G1Gadget::alloc_constant(cs.ns(|| "g_alpha"), g_alpha_g1.into_projective())?;
|
||||||
|
let h_beta_g2 =
|
||||||
|
P::G2Gadget::alloc_constant(cs.ns(|| "h_beta"), h_beta_g2.into_projective())?;
|
||||||
|
let g_gamma_g1 =
|
||||||
|
P::G1Gadget::alloc_constant(cs.ns(|| "g_gamma_g1"), g_gamma_g1.into_projective())?;
|
||||||
|
let h_gamma_g2 =
|
||||||
|
P::G2Gadget::alloc_constant(cs.ns(|| "h_gamma_g2"), h_gamma_g2.into_projective())?;
|
||||||
|
|
||||||
|
let query = query
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, query_i)| {
|
||||||
|
P::G1Gadget::alloc_constant(
|
||||||
|
cs.ns(|| format!("query_{}", i)),
|
||||||
|
query_i.into_projective(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
Ok(Self {
|
||||||
|
h_g2,
|
||||||
|
g_alpha_g1,
|
||||||
|
h_beta_g2,
|
||||||
|
g_gamma_g1,
|
||||||
|
h_gamma_g2,
|
||||||
|
query,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
@@ -309,6 +381,21 @@ where
|
|||||||
ConstraintF: Field,
|
ConstraintF: Field,
|
||||||
P: PairingGadget<PairingE, ConstraintF>,
|
P: PairingGadget<PairingE, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Proof<PairingE>>,
|
||||||
|
{
|
||||||
|
let Proof { a, b, c } = val.borrow().clone();
|
||||||
|
let a = P::G1Gadget::alloc_constant(cs.ns(|| "a"), a.into_projective())?;
|
||||||
|
let b = P::G2Gadget::alloc_constant(cs.ns(|| "b"), b.into_projective())?;
|
||||||
|
let c = P::G1Gadget::alloc_constant(cs.ns(|| "c"), c.into_projective())?;
|
||||||
|
Ok(Self { a, b, c })
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ impl<E: PairingEngine, C: ConstraintSynthesizer<E::Fr>, V: ToConstraintField<E::
|
|||||||
{
|
{
|
||||||
type Circuit = C;
|
type Circuit = C;
|
||||||
type AssignedCircuit = C;
|
type AssignedCircuit = C;
|
||||||
|
type VerifierInput = V;
|
||||||
type ProvingParameters = Parameters<E>;
|
type ProvingParameters = Parameters<E>;
|
||||||
type VerificationParameters = VerifyingKey<E>;
|
type VerificationParameters = VerifyingKey<E>;
|
||||||
type PreparedVerificationParameters = PreparedVerifyingKey<E>;
|
type PreparedVerificationParameters = PreparedVerifyingKey<E>;
|
||||||
type VerifierInput = V;
|
|
||||||
type Proof = Proof<E>;
|
type Proof = Proof<E>;
|
||||||
|
|
||||||
fn setup<R: Rng>(
|
fn setup<R: Rng>(
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
use crate::nizk::{groth16::Groth16, NIZKVerifierGadget};
|
use crate::{
|
||||||
|
nizk::{groth16::Groth16, NIZKVerifierGadget},
|
||||||
|
Vec,
|
||||||
|
};
|
||||||
use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField};
|
use algebra_core::{AffineCurve, Field, PairingEngine, ToConstraintField};
|
||||||
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
|
||||||
use r1cs_std::prelude::*;
|
use r1cs_std::prelude::*;
|
||||||
@@ -107,10 +110,31 @@ where
|
|||||||
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;
|
type ProofGadget = ProofGadget<PairingE, ConstraintF, P>;
|
||||||
|
|
||||||
fn check_verify<'a, CS, I, T>(
|
fn check_verify<'a, CS, I, T>(
|
||||||
|
cs: CS,
|
||||||
|
vk: &Self::VerificationKeyGadget,
|
||||||
|
public_inputs: I,
|
||||||
|
proof: &Self::ProofGadget,
|
||||||
|
) -> Result<(), SynthesisError>
|
||||||
|
where
|
||||||
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
|
I: Iterator<Item = &'a T>,
|
||||||
|
T: 'a + ToBitsGadget<ConstraintF> + ?Sized,
|
||||||
|
{
|
||||||
|
<Self as NIZKVerifierGadget<Groth16<PairingE, C, V>, ConstraintF>>::conditional_check_verify(
|
||||||
|
cs,
|
||||||
|
vk,
|
||||||
|
public_inputs,
|
||||||
|
proof,
|
||||||
|
&Boolean::constant(true),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn conditional_check_verify<'a, CS, I, T>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
vk: &Self::VerificationKeyGadget,
|
vk: &Self::VerificationKeyGadget,
|
||||||
mut public_inputs: I,
|
mut public_inputs: I,
|
||||||
proof: &Self::ProofGadget,
|
proof: &Self::ProofGadget,
|
||||||
|
condition: &Boolean,
|
||||||
) -> Result<(), SynthesisError>
|
) -> Result<(), SynthesisError>
|
||||||
where
|
where
|
||||||
CS: ConstraintSystem<ConstraintF>,
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
@@ -158,7 +182,7 @@ where
|
|||||||
|
|
||||||
let test = P::final_exponentiation(cs.ns(|| "Final Exp"), &test_exp).unwrap();
|
let test = P::final_exponentiation(cs.ns(|| "Final Exp"), &test_exp).unwrap();
|
||||||
|
|
||||||
test.enforce_equal(cs.ns(|| "Test 1"), &pvk.alpha_g1_beta_g2)?;
|
test.conditional_enforce_equal(cs.ns(|| "Test 1"), &pvk.alpha_g1_beta_g2, condition)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,6 +194,50 @@ where
|
|||||||
ConstraintF: Field,
|
ConstraintF: Field,
|
||||||
P: PairingGadget<PairingE, ConstraintF>,
|
P: PairingGadget<PairingE, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<VerifyingKey<PairingE>>,
|
||||||
|
{
|
||||||
|
let VerifyingKey {
|
||||||
|
alpha_g1,
|
||||||
|
beta_g2,
|
||||||
|
gamma_g2,
|
||||||
|
delta_g2,
|
||||||
|
gamma_abc_g1,
|
||||||
|
} = val.borrow().clone();
|
||||||
|
let alpha_g1 =
|
||||||
|
P::G1Gadget::alloc_constant(cs.ns(|| "alpha_g1"), alpha_g1.into_projective())?;
|
||||||
|
let beta_g2 = P::G2Gadget::alloc_constant(cs.ns(|| "beta_g2"), beta_g2.into_projective())?;
|
||||||
|
let gamma_g2 =
|
||||||
|
P::G2Gadget::alloc_constant(cs.ns(|| "gamma_g2"), gamma_g2.into_projective())?;
|
||||||
|
let delta_g2 =
|
||||||
|
P::G2Gadget::alloc_constant(cs.ns(|| "delta_g2"), delta_g2.into_projective())?;
|
||||||
|
|
||||||
|
let gamma_abc_g1 = gamma_abc_g1
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, gamma_abc_i)| {
|
||||||
|
P::G1Gadget::alloc_constant(
|
||||||
|
cs.ns(|| format!("gamma_abc_{}", i)),
|
||||||
|
gamma_abc_i.into_projective(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.into_iter()
|
||||||
|
.collect::<Result<_, _>>()?;
|
||||||
|
Ok(Self {
|
||||||
|
alpha_g1,
|
||||||
|
beta_g2,
|
||||||
|
gamma_g2,
|
||||||
|
delta_g2,
|
||||||
|
gamma_abc_g1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
@@ -273,6 +341,21 @@ where
|
|||||||
ConstraintF: Field,
|
ConstraintF: Field,
|
||||||
P: PairingGadget<PairingE, ConstraintF>,
|
P: PairingGadget<PairingE, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Proof<PairingE>>,
|
||||||
|
{
|
||||||
|
let Proof { a, b, c } = val.borrow().clone();
|
||||||
|
let a = P::G1Gadget::alloc_constant(cs.ns(|| "a"), a.into_projective())?;
|
||||||
|
let b = P::G2Gadget::alloc_constant(cs.ns(|| "b"), b.into_projective())?;
|
||||||
|
let c = P::G1Gadget::alloc_constant(cs.ns(|| "c"), c.into_projective())?;
|
||||||
|
Ok(Self { a, b, c })
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -35,10 +35,10 @@ impl<E: PairingEngine, C: ConstraintSynthesizer<E::Fr>, V: ToConstraintField<E::
|
|||||||
{
|
{
|
||||||
type Circuit = C;
|
type Circuit = C;
|
||||||
type AssignedCircuit = C;
|
type AssignedCircuit = C;
|
||||||
|
type VerifierInput = V;
|
||||||
type ProvingParameters = Parameters<E>;
|
type ProvingParameters = Parameters<E>;
|
||||||
type VerificationParameters = VerifyingKey<E>;
|
type VerificationParameters = VerifyingKey<E>;
|
||||||
type PreparedVerificationParameters = PreparedVerifyingKey<E>;
|
type PreparedVerificationParameters = PreparedVerifyingKey<E>;
|
||||||
type VerifierInput = V;
|
|
||||||
type Proof = Proof<E>;
|
type Proof = Proof<E>;
|
||||||
|
|
||||||
fn setup<R: Rng>(
|
fn setup<R: Rng>(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use algebra_core::PrimeField;
|
use algebra_core::PrimeField;
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||||
|
|
||||||
use crate::prf::PRFGadget;
|
use crate::{prf::PRFGadget, Vec};
|
||||||
use r1cs_std::prelude::*;
|
use r1cs_std::prelude::*;
|
||||||
|
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
@@ -450,6 +450,22 @@ impl<ConstraintF: PrimeField> ToBytesGadget<ConstraintF> for Blake2sOutputGadget
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sOutputGadget {
|
impl<ConstraintF: PrimeField> AllocGadget<[u8; 32], ConstraintF> for Blake2sOutputGadget {
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<[u8; 32]>,
|
||||||
|
{
|
||||||
|
let mut bytes = vec![];
|
||||||
|
for (i, b) in val.borrow().iter().enumerate() {
|
||||||
|
bytes.push(UInt8::alloc_constant(cs.ns(|| format!("value {}", i)), b)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Blake2sOutputGadget(bytes))
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
cs: CS,
|
cs: CS,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use algebra_core::Field;
|
use algebra_core::Field;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
|
|
||||||
use crate::prf::PRF;
|
use crate::{prf::PRF, Vec};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||||
|
|
||||||
use r1cs_std::prelude::*;
|
use r1cs_std::prelude::*;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::Vec;
|
||||||
use algebra_core::{groups::Group, Field};
|
use algebra_core::{groups::Group, Field};
|
||||||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
use r1cs_core::{ConstraintSystem, SynthesisError};
|
||||||
use r1cs_std::prelude::*;
|
use r1cs_std::prelude::*;
|
||||||
@@ -95,6 +96,21 @@ where
|
|||||||
GG: GroupGadget<G, ConstraintF>,
|
GG: GroupGadget<G, ConstraintF>,
|
||||||
D: Digest,
|
D: Digest,
|
||||||
{
|
{
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<SchnorrSigParameters<G, D>>,
|
||||||
|
{
|
||||||
|
let generator = GG::alloc_constant(cs, val.borrow().generator)?;
|
||||||
|
Ok(Self {
|
||||||
|
generator,
|
||||||
|
_engine: PhantomData,
|
||||||
|
_group: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
F: FnOnce() -> Result<T, SynthesisError>,
|
||||||
@@ -132,6 +148,21 @@ where
|
|||||||
ConstraintF: Field,
|
ConstraintF: Field,
|
||||||
GG: GroupGadget<G, ConstraintF>,
|
GG: GroupGadget<G, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
|
val: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<SchnorrPublicKey<G>>,
|
||||||
|
{
|
||||||
|
let pub_key = GG::alloc_constant(cs, val.borrow())?;
|
||||||
|
Ok(Self {
|
||||||
|
pub_key,
|
||||||
|
_engine: PhantomData,
|
||||||
|
_group: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
F: FnOnce() -> Result<T, SynthesisError>,
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ where
|
|||||||
Self: Sized,
|
Self: Sized,
|
||||||
V: ?Sized,
|
V: ?Sized,
|
||||||
{
|
{
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<V>;
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<T, SynthesisError>,
|
F: FnOnce() -> Result<T, SynthesisError>,
|
||||||
@@ -47,6 +54,21 @@ where
|
|||||||
impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], ConstraintF>
|
impl<I, ConstraintF: Field, A: AllocGadget<I, ConstraintF>> AllocGadget<[I], ConstraintF>
|
||||||
for Vec<A>
|
for Vec<A>
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<[I]>,
|
||||||
|
{
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
for (i, value) in t.borrow().iter().enumerate() {
|
||||||
|
vec.push(A::alloc_constant(cs.ns(|| format!("value_{}", i)), value)?);
|
||||||
|
}
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
f: F,
|
f: F,
|
||||||
|
|||||||
@@ -235,6 +235,16 @@ impl PartialEq for AllocatedBit {
|
|||||||
impl Eq for AllocatedBit {}
|
impl Eq for AllocatedBit {}
|
||||||
|
|
||||||
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for AllocatedBit {
|
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for AllocatedBit {
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
_cs: CS,
|
||||||
|
_t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<bool>,
|
||||||
|
{
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
@@ -539,6 +549,22 @@ impl Boolean {
|
|||||||
Ok(cur)
|
Ok(cur)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn kary_or<ConstraintF, CS>(mut cs: CS, bits: &[Self]) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
ConstraintF: Field,
|
||||||
|
CS: ConstraintSystem<ConstraintF>,
|
||||||
|
{
|
||||||
|
assert!(!bits.is_empty());
|
||||||
|
let mut bits = bits.iter();
|
||||||
|
|
||||||
|
let mut cur: Self = *bits.next().unwrap();
|
||||||
|
for (i, next) in bits.enumerate() {
|
||||||
|
cur = Boolean::or(cs.ns(|| format!("OR {}", i)), &cur, next)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(cur)
|
||||||
|
}
|
||||||
|
|
||||||
/// Asserts that at least one operand is false.
|
/// Asserts that at least one operand is false.
|
||||||
pub fn enforce_nand<ConstraintF, CS>(mut cs: CS, bits: &[Self]) -> Result<(), SynthesisError>
|
pub fn enforce_nand<ConstraintF, CS>(mut cs: CS, bits: &[Self]) -> Result<(), SynthesisError>
|
||||||
where
|
where
|
||||||
@@ -715,6 +741,16 @@ impl From<AllocatedBit> for Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for Boolean {
|
impl<ConstraintF: Field> AllocGadget<bool, ConstraintF> for Boolean {
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
_cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<bool>,
|
||||||
|
{
|
||||||
|
Ok(Boolean::constant(*t.borrow()))
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
cs: CS,
|
cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
|
|||||||
@@ -58,6 +58,15 @@ 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> {
|
||||||
|
Ok(self.into_bits_le())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
|
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
|
||||||
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
fn to_bits<CS: ConstraintSystem<ConstraintF>>(
|
||||||
&self,
|
&self,
|
||||||
@@ -71,6 +80,19 @@ impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for [UInt8] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<ConstraintF: Field> ToBitsGadget<ConstraintF> for Vec<UInt8> {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
Ok(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ToBytesGadget<ConstraintF: Field> {
|
pub trait ToBytesGadget<ConstraintF: Field> {
|
||||||
/// Outputs a canonical byte-wise representation of `self`.
|
/// Outputs a canonical byte-wise representation of `self`.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ impl UInt64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
v
|
v
|
||||||
},
|
}
|
||||||
None => vec![None; 64],
|
None => vec![None; 64],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,19 +95,19 @@ impl UInt64 {
|
|||||||
if b {
|
if b {
|
||||||
value.as_mut().map(|v| *v |= 1);
|
value.as_mut().map(|v| *v |= 1);
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
&Boolean::Is(ref b) => match b.get_value() {
|
&Boolean::Is(ref b) => match b.get_value() {
|
||||||
Some(true) => {
|
Some(true) => {
|
||||||
value.as_mut().map(|v| *v |= 1);
|
value.as_mut().map(|v| *v |= 1);
|
||||||
},
|
}
|
||||||
Some(false) => {},
|
Some(false) => {}
|
||||||
None => value = None,
|
None => value = None,
|
||||||
},
|
},
|
||||||
&Boolean::Not(ref b) => match b.get_value() {
|
&Boolean::Not(ref b) => match b.get_value() {
|
||||||
Some(false) => {
|
Some(false) => {
|
||||||
value.as_mut().map(|v| *v |= 1);
|
value.as_mut().map(|v| *v |= 1);
|
||||||
},
|
}
|
||||||
Some(true) => {},
|
Some(true) => {}
|
||||||
None => value = None,
|
None => value = None,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -194,12 +194,12 @@ impl UInt64 {
|
|||||||
match op.value {
|
match op.value {
|
||||||
Some(val) => {
|
Some(val) => {
|
||||||
result_value.as_mut().map(|v| *v += u128::from(val));
|
result_value.as_mut().map(|v| *v += u128::from(val));
|
||||||
},
|
}
|
||||||
None => {
|
None => {
|
||||||
// If any of our operands have unknown value, we won't
|
// If any of our operands have unknown value, we won't
|
||||||
// know the value of the result
|
// know the value of the result
|
||||||
result_value = None;
|
result_value = None;
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over each bit_gadget of the operand and add the operand to
|
// Iterate over each bit_gadget of the operand and add the operand to
|
||||||
@@ -212,18 +212,18 @@ impl UInt64 {
|
|||||||
|
|
||||||
// Add coeff * bit_gadget
|
// Add coeff * bit_gadget
|
||||||
lc += (coeff, bit.get_variable());
|
lc += (coeff, bit.get_variable());
|
||||||
},
|
}
|
||||||
Boolean::Not(ref bit) => {
|
Boolean::Not(ref bit) => {
|
||||||
all_constants = false;
|
all_constants = false;
|
||||||
|
|
||||||
// Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget
|
// Add coeff * (1 - bit_gadget) = coeff * ONE - coeff * bit_gadget
|
||||||
lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable());
|
lc = lc + (coeff, CS::one()) - (coeff, bit.get_variable());
|
||||||
},
|
}
|
||||||
Boolean::Constant(bit) => {
|
Boolean::Constant(bit) => {
|
||||||
if bit {
|
if bit {
|
||||||
lc += (coeff, CS::one());
|
lc += (coeff, CS::one());
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
coeff.double_in_place();
|
coeff.double_in_place();
|
||||||
@@ -277,6 +277,16 @@ impl UInt64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<ConstraintF: Field> AllocGadget<u64, ConstraintF> for UInt64 {
|
impl<ConstraintF: Field> AllocGadget<u64, ConstraintF> for UInt64 {
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
_cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<u64>,
|
||||||
|
{
|
||||||
|
Ok(UInt64::constant(*t.borrow()))
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
@@ -397,7 +407,7 @@ mod test {
|
|||||||
match bit_gadget {
|
match bit_gadget {
|
||||||
&Boolean::Constant(bit_gadget) => {
|
&Boolean::Constant(bit_gadget) => {
|
||||||
assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1));
|
assert!(bit_gadget == ((b.value.unwrap() >> i) & 1 == 1));
|
||||||
},
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -406,8 +416,8 @@ mod test {
|
|||||||
|
|
||||||
for x in v.iter().zip(expected_to_be_same.iter()) {
|
for x in v.iter().zip(expected_to_be_same.iter()) {
|
||||||
match x {
|
match x {
|
||||||
(&Boolean::Constant(true), &Boolean::Constant(true)) => {},
|
(&Boolean::Constant(true), &Boolean::Constant(true)) => {}
|
||||||
(&Boolean::Constant(false), &Boolean::Constant(false)) => {},
|
(&Boolean::Constant(false), &Boolean::Constant(false)) => {}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -442,13 +452,13 @@ mod test {
|
|||||||
match b {
|
match b {
|
||||||
&Boolean::Is(ref b) => {
|
&Boolean::Is(ref b) => {
|
||||||
assert!(b.get_value().unwrap() == (expected & 1 == 1));
|
assert!(b.get_value().unwrap() == (expected & 1 == 1));
|
||||||
},
|
}
|
||||||
&Boolean::Not(ref b) => {
|
&Boolean::Not(ref b) => {
|
||||||
assert!(!b.get_value().unwrap() == (expected & 1 == 1));
|
assert!(!b.get_value().unwrap() == (expected & 1 == 1));
|
||||||
},
|
}
|
||||||
&Boolean::Constant(b) => {
|
&Boolean::Constant(b) => {
|
||||||
assert!(b == (expected & 1 == 1));
|
assert!(b == (expected & 1 == 1));
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expected >>= 1;
|
expected >>= 1;
|
||||||
@@ -483,7 +493,7 @@ mod test {
|
|||||||
&Boolean::Not(_) => panic!(),
|
&Boolean::Not(_) => panic!(),
|
||||||
&Boolean::Constant(b) => {
|
&Boolean::Constant(b) => {
|
||||||
assert!(b == (expected & 1 == 1));
|
assert!(b == (expected & 1 == 1));
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expected >>= 1;
|
expected >>= 1;
|
||||||
@@ -521,10 +531,10 @@ mod test {
|
|||||||
match b {
|
match b {
|
||||||
&Boolean::Is(ref b) => {
|
&Boolean::Is(ref b) => {
|
||||||
assert!(b.get_value().unwrap() == (expected & 1 == 1));
|
assert!(b.get_value().unwrap() == (expected & 1 == 1));
|
||||||
},
|
}
|
||||||
&Boolean::Not(ref b) => {
|
&Boolean::Not(ref b) => {
|
||||||
assert!(!b.get_value().unwrap() == (expected & 1 == 1));
|
assert!(!b.get_value().unwrap() == (expected & 1 == 1));
|
||||||
},
|
}
|
||||||
&Boolean::Constant(_) => unreachable!(),
|
&Boolean::Constant(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,7 +570,7 @@ mod test {
|
|||||||
match b {
|
match b {
|
||||||
&Boolean::Constant(b) => {
|
&Boolean::Constant(b) => {
|
||||||
assert_eq!(b, tmp & 1 == 1);
|
assert_eq!(b, tmp & 1 == 1);
|
||||||
},
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,6 +214,16 @@ impl<ConstraintF: Field> ConditionalEqGadget<ConstraintF> for UInt8 {
|
|||||||
impl<ConstraintF: Field> EqGadget<ConstraintF> for UInt8 {}
|
impl<ConstraintF: Field> EqGadget<ConstraintF> for UInt8 {}
|
||||||
|
|
||||||
impl<ConstraintF: Field> AllocGadget<u8, ConstraintF> for UInt8 {
|
impl<ConstraintF: Field> AllocGadget<u8, ConstraintF> for UInt8 {
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
_cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<u8>,
|
||||||
|
{
|
||||||
|
Ok(UInt8::constant(*t.borrow()))
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
value_gen: F,
|
value_gen: F,
|
||||||
|
|||||||
@@ -584,6 +584,18 @@ impl<F: PrimeField> Clone for FpGadget<F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<F: PrimeField> AllocGadget<F, F> for FpGadget<F> {
|
impl<F: PrimeField> AllocGadget<F, F> for FpGadget<F> {
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<F>>(_cs: CS, t: T) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<F>,
|
||||||
|
{
|
||||||
|
let value = t.borrow().clone();
|
||||||
|
Ok(Self {
|
||||||
|
value: Some(value),
|
||||||
|
variable: LinearCombination::from((value, CS::one())).into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<F>>(
|
fn alloc<FN, T, CS: ConstraintSystem<F>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -834,6 +834,17 @@ where
|
|||||||
P: Fp12Parameters,
|
P: Fp12Parameters,
|
||||||
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
<P::Fp6Params as Fp6Parameters>::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Fp12<P>>,
|
||||||
|
{
|
||||||
|
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -611,6 +611,17 @@ impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField>
|
|||||||
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp2<P>, ConstraintF>
|
impl<P: Fp2Parameters<Fp = ConstraintF>, ConstraintF: PrimeField> AllocGadget<Fp2<P>, ConstraintF>
|
||||||
for Fp2Gadget<P, ConstraintF>
|
for Fp2Gadget<P, ConstraintF>
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Fp2<P>>,
|
||||||
|
{
|
||||||
|
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -867,6 +867,17 @@ impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootFie
|
|||||||
impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootField>
|
impl<P: Fp3Parameters<Fp = ConstraintF>, ConstraintF: PrimeField + SquareRootField>
|
||||||
AllocGadget<Fp3<P>, ConstraintF> for Fp3Gadget<P, ConstraintF>
|
AllocGadget<Fp3<P>, ConstraintF> for Fp3Gadget<P, ConstraintF>
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Fp3<P>>,
|
||||||
|
{
|
||||||
|
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -673,6 +673,17 @@ where
|
|||||||
P: Fp4Parameters,
|
P: Fp4Parameters,
|
||||||
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Fp4<P>>,
|
||||||
|
{
|
||||||
|
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -664,6 +664,17 @@ where
|
|||||||
P: Fp6Parameters,
|
P: Fp6Parameters,
|
||||||
P::Fp3Params: Fp3Parameters<Fp = ConstraintF>,
|
P::Fp3Params: Fp3Parameters<Fp = ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Fp6<P>>,
|
||||||
|
{
|
||||||
|
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -964,6 +964,17 @@ where
|
|||||||
P: Fp6Parameters,
|
P: Fp6Parameters,
|
||||||
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
P::Fp2Params: Fp2Parameters<Fp = ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<Fp6<P>>,
|
||||||
|
{
|
||||||
|
Self::zero(cs.ns(|| "zero"))?.add_constant(cs.ns(|| "add constant"), t.borrow())
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
|
|||||||
@@ -437,6 +437,24 @@ where
|
|||||||
ConstraintF: PrimeField,
|
ConstraintF: PrimeField,
|
||||||
F: FieldGadget<P::BaseField, ConstraintF>,
|
F: FieldGadget<P::BaseField, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<SWProjective<P>>,
|
||||||
|
{
|
||||||
|
let p = t.borrow().into_affine();
|
||||||
|
Ok(Self {
|
||||||
|
x: F::alloc_constant(cs.ns(|| "x"), &p.x)?,
|
||||||
|
y: F::alloc_constant(cs.ns(|| "y"), &p.y)?,
|
||||||
|
infinity: Boolean::constant(p.infinity),
|
||||||
|
_params: PhantomData,
|
||||||
|
_engine: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
@@ -661,3 +679,113 @@ where
|
|||||||
Ok(x_bytes)
|
Ok(x_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) fn test<ConstraintF, P, GG>()
|
||||||
|
where
|
||||||
|
ConstraintF: Field,
|
||||||
|
P: SWModelParameters,
|
||||||
|
GG: GroupGadget<SWProjective<P>, ConstraintF, Value = SWProjective<P>>,
|
||||||
|
{
|
||||||
|
use crate::{boolean::AllocatedBit, prelude::*, test_constraint_system::TestConstraintSystem};
|
||||||
|
use algebra::{test_rng, Group, UniformRand};
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
// Incomplete addition doesn't allow us to call the group_test.
|
||||||
|
// group_test::<ConstraintF, SWProjective<P>, GG>();
|
||||||
|
|
||||||
|
let mut rng = test_rng();
|
||||||
|
|
||||||
|
let mut cs = TestConstraintSystem::<ConstraintF>::new();
|
||||||
|
|
||||||
|
let a = SWProjective::<P>::rand(&mut rng);
|
||||||
|
let b = SWProjective::<P>::rand(&mut rng);
|
||||||
|
let a_affine = a.into_affine();
|
||||||
|
let b_affine = b.into_affine();
|
||||||
|
let mut gadget_a = GG::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
||||||
|
let gadget_b = GG::alloc_checked(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
||||||
|
assert_eq!(gadget_a.get_value().unwrap().x, a_affine.x);
|
||||||
|
assert_eq!(gadget_a.get_value().unwrap().y, a_affine.y);
|
||||||
|
assert_eq!(gadget_b.get_value().unwrap().x, b_affine.x);
|
||||||
|
assert_eq!(gadget_b.get_value().unwrap().y, b_affine.y);
|
||||||
|
|
||||||
|
// Check addition
|
||||||
|
let ab = a + &b;
|
||||||
|
let ab_affine = ab.into_affine();
|
||||||
|
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
||||||
|
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
||||||
|
gadget_ba
|
||||||
|
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let ab_val = gadget_ab
|
||||||
|
.get_value()
|
||||||
|
.expect("Doubling should be successful")
|
||||||
|
.into_affine();
|
||||||
|
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
|
||||||
|
|
||||||
|
// Check doubling
|
||||||
|
let aa = Group::double(&a);
|
||||||
|
let aa_affine = aa.into_affine();
|
||||||
|
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
||||||
|
let aa_val = gadget_a
|
||||||
|
.get_value()
|
||||||
|
.expect("Doubling should be successful")
|
||||||
|
.into_affine();
|
||||||
|
assert_eq!(
|
||||||
|
aa_val, aa_affine,
|
||||||
|
"Gadget and native values are unequal after double."
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check mul_bits
|
||||||
|
let scalar = P::ScalarField::rand(&mut rng);
|
||||||
|
let native_result = aa.into_affine().mul(scalar) + &b;
|
||||||
|
let native_result = native_result.into_affine();
|
||||||
|
|
||||||
|
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
||||||
|
// Get the scalar bits into little-endian form.
|
||||||
|
scalar.reverse();
|
||||||
|
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
|
||||||
|
let result = gadget_a
|
||||||
|
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
|
||||||
|
.unwrap();
|
||||||
|
let result_val = result.get_value().unwrap().into_affine();
|
||||||
|
assert_eq!(
|
||||||
|
result_val, native_result,
|
||||||
|
"gadget & native values are diff. after scalar mul"
|
||||||
|
);
|
||||||
|
|
||||||
|
if !cs.is_satisfied() {
|
||||||
|
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
assert!(cs.is_satisfied());
|
||||||
|
|
||||||
|
// Constraint cost etc.
|
||||||
|
let mut cs = TestConstraintSystem::<ConstraintF>::new();
|
||||||
|
|
||||||
|
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
|
|
||||||
|
let mut rng = test_rng();
|
||||||
|
let a: SWProjective<P> = rng.gen();
|
||||||
|
let b: SWProjective<P> = rng.gen();
|
||||||
|
let gadget_a = GG::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
||||||
|
let gadget_b = GG::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
||||||
|
let alloc_cost = cs.num_constraints();
|
||||||
|
let _ =
|
||||||
|
GG::conditionally_select(&mut cs.ns(|| "cond_select"), &bit, &gadget_a, &gadget_b).unwrap();
|
||||||
|
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
||||||
|
|
||||||
|
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
||||||
|
let add_cost = cs.num_constraints() - cond_select_cost - alloc_cost;
|
||||||
|
|
||||||
|
assert!(cs.is_satisfied());
|
||||||
|
assert_eq!(
|
||||||
|
cond_select_cost,
|
||||||
|
<GG as CondSelectGadget<ConstraintF>>::cost()
|
||||||
|
);
|
||||||
|
assert_eq!(add_cost, GG::cost_of_add());
|
||||||
|
}
|
||||||
|
|||||||
@@ -492,6 +492,23 @@ mod affine_impl {
|
|||||||
F: FieldGadget<P::BaseField, ConstraintF>,
|
F: FieldGadget<P::BaseField, ConstraintF>,
|
||||||
Self: GroupGadget<TEAffine<P>, ConstraintF>,
|
Self: GroupGadget<TEAffine<P>, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<TEAffine<P>>,
|
||||||
|
{
|
||||||
|
let p = t.borrow();
|
||||||
|
Ok(Self {
|
||||||
|
x: F::alloc_constant(cs.ns(|| "x"), &p.x)?,
|
||||||
|
y: F::alloc_constant(cs.ns(|| "y"), &p.y)?,
|
||||||
|
_params: PhantomData,
|
||||||
|
_engine: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
value_gen: FN,
|
value_gen: FN,
|
||||||
@@ -1089,6 +1106,23 @@ mod projective_impl {
|
|||||||
F: FieldGadget<P::BaseField, ConstraintF>,
|
F: FieldGadget<P::BaseField, ConstraintF>,
|
||||||
Self: GroupGadget<TEProjective<P>, ConstraintF>,
|
Self: GroupGadget<TEProjective<P>, ConstraintF>,
|
||||||
{
|
{
|
||||||
|
#[inline]
|
||||||
|
fn alloc_constant<T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
|
mut cs: CS,
|
||||||
|
t: T,
|
||||||
|
) -> Result<Self, SynthesisError>
|
||||||
|
where
|
||||||
|
T: Borrow<TEProjective<P>>,
|
||||||
|
{
|
||||||
|
let p = t.borrow().into_affine();
|
||||||
|
Ok(Self {
|
||||||
|
x: F::alloc_constant(cs.ns(|| "x"), &p.x)?,
|
||||||
|
y: F::alloc_constant(cs.ns(|| "y"), &p.y)?,
|
||||||
|
_params: PhantomData,
|
||||||
|
_engine: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
fn alloc<FN, T, CS: ConstraintSystem<ConstraintF>>(
|
||||||
mut cs: CS,
|
mut cs: CS,
|
||||||
value_gen: FN,
|
value_gen: FN,
|
||||||
|
|||||||
@@ -7,192 +7,17 @@ pub type G2Gadget = bls12::G2Gadget<Parameters>;
|
|||||||
pub type G1PreparedGadget = bls12::G1PreparedGadget<Parameters>;
|
pub type G1PreparedGadget = bls12::G1PreparedGadget<Parameters>;
|
||||||
pub type G2PreparedGadget = bls12::G2PreparedGadget<Parameters>;
|
pub type G2PreparedGadget = bls12::G2PreparedGadget<Parameters>;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
use super::{G1Gadget, G2Gadget};
|
|
||||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
|
|
||||||
use algebra::{bls12_377::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
|
|
||||||
use r1cs_core::ConstraintSystem;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn bls12_g1_constraint_costs() {
|
fn test() {
|
||||||
use crate::boolean::AllocatedBit;
|
use algebra::curves::models::bls12::Bls12Parameters;
|
||||||
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
_,
|
||||||
|
<Parameters as Bls12Parameters>::G1Parameters,
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
G1Gadget,
|
||||||
.unwrap()
|
>();
|
||||||
.into();
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
|
_,
|
||||||
let mut rng = test_rng();
|
<Parameters as Bls12Parameters>::G2Parameters,
|
||||||
let a: G1Projective = rng.gen();
|
G2Gadget,
|
||||||
let b: G1Projective = rng.gen();
|
>();
|
||||||
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G1Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G1Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bls12_g2_constraint_costs() {
|
|
||||||
use crate::boolean::AllocatedBit;
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
|
||||||
.unwrap()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G2Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G2Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bls12_g1_gadget_test() {
|
|
||||||
use algebra::UniformRand;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use rand_xorshift::XorShiftRng;
|
|
||||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let a = G1Projective::rand(&mut rng);
|
|
||||||
let b = G1Projective::rand(&mut rng);
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
// Check addition
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let ab_val = gadget_ab
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
|
|
||||||
|
|
||||||
// Check doubling
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
let aa_val = gadget_a
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
aa_val, aa_affine,
|
|
||||||
"Gadget and native values are unequal after double."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check mul_bits
|
|
||||||
let scalar = Fr::rand(&mut rng);
|
|
||||||
let native_result = aa.into_affine().mul(scalar) + &b;
|
|
||||||
let native_result = native_result.into_affine();
|
|
||||||
|
|
||||||
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
|
||||||
// Get the scalar bits into little-endian form.
|
|
||||||
scalar.reverse();
|
|
||||||
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
|
|
||||||
let result = gadget_a
|
|
||||||
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
|
|
||||||
.unwrap();
|
|
||||||
let result_val = result.get_value().unwrap().into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
result_val, native_result,
|
|
||||||
"gadget & native values are diff. after scalar mul"
|
|
||||||
);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bls12_g2_gadget_test() {
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
|
|
||||||
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
|
|
||||||
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
|
|
||||||
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,192 +7,17 @@ pub type G2Gadget = mnt4::G2Gadget<Parameters>;
|
|||||||
pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>;
|
pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>;
|
||||||
pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>;
|
pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
use super::{G1Gadget, G2Gadget};
|
|
||||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
|
|
||||||
use algebra::{mnt4_298::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
|
|
||||||
use r1cs_core::ConstraintSystem;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mnt4_298_g1_constraint_costs() {
|
fn test() {
|
||||||
use crate::boolean::AllocatedBit;
|
use algebra::curves::models::mnt4::MNT4Parameters;
|
||||||
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
_,
|
||||||
|
<Parameters as MNT4Parameters>::G1Parameters,
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
G1Gadget,
|
||||||
.unwrap()
|
>();
|
||||||
.into();
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
|
_,
|
||||||
let mut rng = test_rng();
|
<Parameters as MNT4Parameters>::G2Parameters,
|
||||||
let a: G1Projective = rng.gen();
|
G2Gadget,
|
||||||
let b: G1Projective = rng.gen();
|
>();
|
||||||
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G1Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G1Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt4_298_g2_constraint_costs() {
|
|
||||||
use crate::boolean::AllocatedBit;
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
|
||||||
.unwrap()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G2Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G2Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt4_298_g1_gadget_test() {
|
|
||||||
use algebra::UniformRand;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use rand_xorshift::XorShiftRng;
|
|
||||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let a = G1Projective::rand(&mut rng);
|
|
||||||
let b = G1Projective::rand(&mut rng);
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
// Check addition
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let ab_val = gadget_ab
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
|
|
||||||
|
|
||||||
// Check doubling
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
let aa_val = gadget_a
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
aa_val, aa_affine,
|
|
||||||
"Gadget and native values are unequal after double."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check mul_bits
|
|
||||||
let scalar = Fr::rand(&mut rng);
|
|
||||||
let native_result = aa.into_affine().mul(scalar) + &b;
|
|
||||||
let native_result = native_result.into_affine();
|
|
||||||
|
|
||||||
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
|
||||||
// Get the scalar bits into little-endian form.
|
|
||||||
scalar.reverse();
|
|
||||||
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
|
|
||||||
let result = gadget_a
|
|
||||||
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
|
|
||||||
.unwrap();
|
|
||||||
let result_val = result.get_value().unwrap().into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
result_val, native_result,
|
|
||||||
"gadget & native values are diff. after scalar mul"
|
|
||||||
);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt4_298_g2_gadget_test() {
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
|
|
||||||
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
|
|
||||||
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
|
|
||||||
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,192 +7,17 @@ pub type G2Gadget = mnt4::G2Gadget<Parameters>;
|
|||||||
pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>;
|
pub type G1PreparedGadget = mnt4::G1PreparedGadget<Parameters>;
|
||||||
pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>;
|
pub type G2PreparedGadget = mnt4::G2PreparedGadget<Parameters>;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
use super::{G1Gadget, G2Gadget};
|
|
||||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
|
|
||||||
use algebra::{mnt4_753::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
|
|
||||||
use r1cs_core::ConstraintSystem;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mnt4_753_g1_constraint_costs() {
|
fn test() {
|
||||||
use crate::boolean::AllocatedBit;
|
use algebra::curves::models::mnt4::MNT4Parameters;
|
||||||
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
_,
|
||||||
|
<Parameters as MNT4Parameters>::G1Parameters,
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
G1Gadget,
|
||||||
.unwrap()
|
>();
|
||||||
.into();
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
|
_,
|
||||||
let mut rng = test_rng();
|
<Parameters as MNT4Parameters>::G2Parameters,
|
||||||
let a: G1Projective = rng.gen();
|
G2Gadget,
|
||||||
let b: G1Projective = rng.gen();
|
>();
|
||||||
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G1Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G1Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt4_753_g2_constraint_costs() {
|
|
||||||
use crate::boolean::AllocatedBit;
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
|
||||||
.unwrap()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G2Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G2Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt4_753_g1_gadget_test() {
|
|
||||||
use algebra::UniformRand;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use rand_xorshift::XorShiftRng;
|
|
||||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let a = G1Projective::rand(&mut rng);
|
|
||||||
let b = G1Projective::rand(&mut rng);
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
// Check addition
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let ab_val = gadget_ab
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
|
|
||||||
|
|
||||||
// Check doubling
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
let aa_val = gadget_a
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
aa_val, aa_affine,
|
|
||||||
"Gadget and native values are unequal after double."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check mul_bits
|
|
||||||
let scalar = Fr::rand(&mut rng);
|
|
||||||
let native_result = aa.into_affine().mul(scalar) + &b;
|
|
||||||
let native_result = native_result.into_affine();
|
|
||||||
|
|
||||||
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
|
||||||
// Get the scalar bits into little-endian form.
|
|
||||||
scalar.reverse();
|
|
||||||
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
|
|
||||||
let result = gadget_a
|
|
||||||
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
|
|
||||||
.unwrap();
|
|
||||||
let result_val = result.get_value().unwrap().into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
result_val, native_result,
|
|
||||||
"gadget & native values are diff. after scalar mul"
|
|
||||||
);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt4_753_g2_gadget_test() {
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
|
|
||||||
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
|
|
||||||
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
|
|
||||||
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,192 +7,17 @@ pub type G2Gadget = mnt6::G2Gadget<Parameters>;
|
|||||||
pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>;
|
pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>;
|
||||||
pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>;
|
pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
use super::{G1Gadget, G2Gadget};
|
|
||||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
|
|
||||||
use algebra::{mnt6_298::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
|
|
||||||
use r1cs_core::ConstraintSystem;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mnt6_298_g1_constraint_costs() {
|
fn test() {
|
||||||
use crate::boolean::AllocatedBit;
|
use algebra::curves::models::mnt6::MNT6Parameters;
|
||||||
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
_,
|
||||||
|
<Parameters as MNT6Parameters>::G1Parameters,
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
G1Gadget,
|
||||||
.unwrap()
|
>();
|
||||||
.into();
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
|
_,
|
||||||
let mut rng = test_rng();
|
<Parameters as MNT6Parameters>::G2Parameters,
|
||||||
let a: G1Projective = rng.gen();
|
G2Gadget,
|
||||||
let b: G1Projective = rng.gen();
|
>();
|
||||||
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G1Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G1Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt6_298_g2_constraint_costs() {
|
|
||||||
use crate::boolean::AllocatedBit;
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
|
||||||
.unwrap()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G2Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G2Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt6_298_g1_gadget_test() {
|
|
||||||
use algebra::UniformRand;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use rand_xorshift::XorShiftRng;
|
|
||||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let a = G1Projective::rand(&mut rng);
|
|
||||||
let b = G1Projective::rand(&mut rng);
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
// Check addition
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let ab_val = gadget_ab
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
|
|
||||||
|
|
||||||
// Check doubling
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
let aa_val = gadget_a
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
aa_val, aa_affine,
|
|
||||||
"Gadget and native values are unequal after double."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check mul_bits
|
|
||||||
let scalar = Fr::rand(&mut rng);
|
|
||||||
let native_result = aa.into_affine().mul(scalar) + &b;
|
|
||||||
let native_result = native_result.into_affine();
|
|
||||||
|
|
||||||
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
|
||||||
// Get the scalar bits into little-endian form.
|
|
||||||
scalar.reverse();
|
|
||||||
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
|
|
||||||
let result = gadget_a
|
|
||||||
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
|
|
||||||
.unwrap();
|
|
||||||
let result_val = result.get_value().unwrap().into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
result_val, native_result,
|
|
||||||
"gadget & native values are diff. after scalar mul"
|
|
||||||
);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt6_298_g2_gadget_test() {
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
|
|
||||||
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
|
|
||||||
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
|
|
||||||
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,192 +7,17 @@ pub type G2Gadget = mnt6::G2Gadget<Parameters>;
|
|||||||
pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>;
|
pub type G1PreparedGadget = mnt6::G1PreparedGadget<Parameters>;
|
||||||
pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>;
|
pub type G2PreparedGadget = mnt6::G2PreparedGadget<Parameters>;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod test {
|
|
||||||
use rand::Rng;
|
|
||||||
|
|
||||||
use super::{G1Gadget, G2Gadget};
|
|
||||||
use crate::{prelude::*, test_constraint_system::TestConstraintSystem, Vec};
|
|
||||||
use algebra::{mnt6_753::*, test_rng, AffineCurve, BitIterator, PrimeField, ProjectiveCurve};
|
|
||||||
use r1cs_core::ConstraintSystem;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn mnt6_753_g1_constraint_costs() {
|
fn test() {
|
||||||
use crate::boolean::AllocatedBit;
|
use algebra::curves::models::mnt6::MNT6Parameters;
|
||||||
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
_,
|
||||||
|
<Parameters as MNT6Parameters>::G1Parameters,
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
G1Gadget,
|
||||||
.unwrap()
|
>();
|
||||||
.into();
|
crate::groups::curves::short_weierstrass::test::<
|
||||||
|
_,
|
||||||
let mut rng = test_rng();
|
<Parameters as MNT6Parameters>::G2Parameters,
|
||||||
let a: G1Projective = rng.gen();
|
G2Gadget,
|
||||||
let b: G1Projective = rng.gen();
|
>();
|
||||||
let gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G1Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G1Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt6_753_g2_constraint_costs() {
|
|
||||||
use crate::boolean::AllocatedBit;
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let bit = AllocatedBit::alloc(&mut cs.ns(|| "bool"), || Ok(true))
|
|
||||||
.unwrap()
|
|
||||||
.into();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
let alloc_cost = cs.num_constraints();
|
|
||||||
let _ = G2Gadget::conditionally_select(
|
|
||||||
&mut cs.ns(|| "cond_select"),
|
|
||||||
&bit,
|
|
||||||
&gadget_a,
|
|
||||||
&gadget_b,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let cond_select_cost = cs.num_constraints() - alloc_cost;
|
|
||||||
|
|
||||||
let _ = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
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!(add_cost, G2Gadget::cost_of_add());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt6_753_g1_gadget_test() {
|
|
||||||
use algebra::UniformRand;
|
|
||||||
use rand::SeedableRng;
|
|
||||||
use rand_xorshift::XorShiftRng;
|
|
||||||
let mut rng = XorShiftRng::seed_from_u64(1231275789u64);
|
|
||||||
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let a = G1Projective::rand(&mut rng);
|
|
||||||
let b = G1Projective::rand(&mut rng);
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
let mut gadget_a = G1Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G1Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.value.unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.value.unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.value.unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.value.unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
// Check addition
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let ab_val = gadget_ab
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(ab_val, ab_affine, "Result of addition is unequal");
|
|
||||||
|
|
||||||
// Check doubling
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
let aa_val = gadget_a
|
|
||||||
.get_value()
|
|
||||||
.expect("Doubling should be successful")
|
|
||||||
.into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
aa_val, aa_affine,
|
|
||||||
"Gadget and native values are unequal after double."
|
|
||||||
);
|
|
||||||
|
|
||||||
// Check mul_bits
|
|
||||||
let scalar = Fr::rand(&mut rng);
|
|
||||||
let native_result = aa.into_affine().mul(scalar) + &b;
|
|
||||||
let native_result = native_result.into_affine();
|
|
||||||
|
|
||||||
let mut scalar: Vec<bool> = BitIterator::new(scalar.into_repr()).collect();
|
|
||||||
// Get the scalar bits into little-endian form.
|
|
||||||
scalar.reverse();
|
|
||||||
let input = Vec::<Boolean>::alloc(cs.ns(|| "Input"), || Ok(scalar)).unwrap();
|
|
||||||
let result = gadget_a
|
|
||||||
.mul_bits(cs.ns(|| "mul_bits"), &gadget_b, input.iter())
|
|
||||||
.unwrap();
|
|
||||||
let result_val = result.get_value().unwrap().into_affine();
|
|
||||||
assert_eq!(
|
|
||||||
result_val, native_result,
|
|
||||||
"gadget & native values are diff. after scalar mul"
|
|
||||||
);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn mnt6_753_g2_gadget_test() {
|
|
||||||
let mut cs = TestConstraintSystem::<Fq>::new();
|
|
||||||
|
|
||||||
let mut rng = test_rng();
|
|
||||||
let a: G2Projective = rng.gen();
|
|
||||||
let b: G2Projective = rng.gen();
|
|
||||||
let a_affine = a.into_affine();
|
|
||||||
let b_affine = b.into_affine();
|
|
||||||
|
|
||||||
let mut gadget_a = G2Gadget::alloc(&mut cs.ns(|| "a"), || Ok(a)).unwrap();
|
|
||||||
let gadget_b = G2Gadget::alloc(&mut cs.ns(|| "b"), || Ok(b)).unwrap();
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), a_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), a_affine.y);
|
|
||||||
assert_eq!(gadget_b.x.get_value().unwrap(), b_affine.x);
|
|
||||||
assert_eq!(gadget_b.y.get_value().unwrap(), b_affine.y);
|
|
||||||
|
|
||||||
let ab = a + &b;
|
|
||||||
let ab_affine = ab.into_affine();
|
|
||||||
let gadget_ab = gadget_a.add(&mut cs.ns(|| "ab"), &gadget_b).unwrap();
|
|
||||||
let gadget_ba = gadget_b.add(&mut cs.ns(|| "ba"), &gadget_a).unwrap();
|
|
||||||
gadget_ba
|
|
||||||
.enforce_equal(&mut cs.ns(|| "b + a == a + b?"), &gadget_ab)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(gadget_ab.x.get_value().unwrap(), ab_affine.x);
|
|
||||||
assert_eq!(gadget_ab.y.get_value().unwrap(), ab_affine.y);
|
|
||||||
|
|
||||||
let aa = a.double();
|
|
||||||
let aa_affine = aa.into_affine();
|
|
||||||
gadget_a.double_in_place(&mut cs.ns(|| "2a")).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(gadget_a.x.get_value().unwrap(), aa_affine.x);
|
|
||||||
assert_eq!(gadget_a.y.get_value().unwrap(), aa_affine.y);
|
|
||||||
|
|
||||||
if !cs.is_satisfied() {
|
|
||||||
println!("{:?}", cs.which_is_unsatisfied().unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert!(cs.is_satisfied());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user