@ -1,121 +0,0 @@ |
|||
#[macro_use]
|
|||
extern crate criterion;
|
|||
|
|||
use algebra::{curves::bls12_377::Bls12_377, fields::bls12_377::Fr, Field};
|
|||
use crypto_primitives::nizk::*;
|
|||
use r1cs_core::{ConstraintSynthesizer, ConstraintSystem, SynthesisError};
|
|||
|
|||
use criterion::Criterion;
|
|||
use rand::{thread_rng, Rng};
|
|||
|
|||
type TestProofSystem = Gm17<Bls12_377, Bench<Fr>, Fr>;
|
|||
|
|||
struct Bench<F: Field> {
|
|||
inputs: Vec<Option<F>>,
|
|||
num_constraints: usize,
|
|||
}
|
|||
|
|||
impl<F: Field> ConstraintSynthesizer<F> for Bench<F> {
|
|||
fn generate_constraints<CS: ConstraintSystem<F>>(
|
|||
self,
|
|||
cs: &mut CS,
|
|||
) -> Result<(), SynthesisError> {
|
|||
assert!(self.inputs.len() >= 2);
|
|||
assert!(self.num_constraints >= self.inputs.len());
|
|||
|
|||
let mut variables: Vec<_> = Vec::with_capacity(self.inputs.len());
|
|||
for (i, input) in self.inputs.into_iter().enumerate() {
|
|||
let input_var = cs.alloc_input(
|
|||
|| format!("Input {}", i),
|
|||
|| input.ok_or(SynthesisError::AssignmentMissing),
|
|||
)?;
|
|||
variables.push((input, input_var));
|
|||
}
|
|||
|
|||
for i in 0..self.num_constraints {
|
|||
let new_entry = {
|
|||
let (input_1_val, input_1_var) = variables[i];
|
|||
let (input_2_val, input_2_var) = variables[i + 1];
|
|||
let result_val =
|
|||
input_1_val.and_then(|input_1| input_2_val.map(|input_2| input_1 * &input_2));
|
|||
let result_var = cs.alloc(
|
|||
|| format!("Result {}", i),
|
|||
|| result_val.ok_or(SynthesisError::AssignmentMissing),
|
|||
)?;
|
|||
cs.enforce(
|
|||
|| format!("Enforce constraint {}", i),
|
|||
|lc| lc + input_1_var,
|
|||
|lc| lc + input_2_var,
|
|||
|lc| lc + result_var,
|
|||
);
|
|||
(result_val, result_var)
|
|||
};
|
|||
variables.push(new_entry);
|
|||
}
|
|||
Ok(())
|
|||
}
|
|||
}
|
|||
|
|||
fn gm17_setup(c: &mut Criterion) {
|
|||
let num_inputs = 100;
|
|||
let num_constraints = num_inputs;
|
|||
let rng = &mut thread_rng();
|
|||
let mut inputs: Vec<Option<Fr>> = Vec::with_capacity(num_inputs);
|
|||
for _ in 0..num_inputs {
|
|||
inputs.push(Some(rng.gen()));
|
|||
}
|
|||
|
|||
c.bench_function("gm17_setup", move |b| {
|
|||
b.iter(|| {
|
|||
TestProofSystem::setup(
|
|||
Bench::<Fr> {
|
|||
inputs: vec![None; num_inputs],
|
|||
num_constraints,
|
|||
},
|
|||
rng,
|
|||
)
|
|||
.unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn gm17_prove(c: &mut Criterion) {
|
|||
let num_inputs = 100;
|
|||
let num_constraints = num_inputs;
|
|||
let rng = &mut thread_rng();
|
|||
let mut inputs: Vec<Option<Fr>> = Vec::with_capacity(num_inputs);
|
|||
for _ in 0..num_inputs {
|
|||
inputs.push(Some(rng.gen()));
|
|||
}
|
|||
|
|||
let params = TestProofSystem::setup(
|
|||
Bench::<Fr> {
|
|||
inputs: vec![None; num_inputs],
|
|||
num_constraints,
|
|||
},
|
|||
rng,
|
|||
)
|
|||
.unwrap();
|
|||
|
|||
c.bench_function("gm17_prove", move |b| {
|
|||
b.iter(|| {
|
|||
TestProofSystem::prove(
|
|||
¶ms.0,
|
|||
Bench {
|
|||
inputs: inputs.clone(),
|
|||
num_constraints,
|
|||
},
|
|||
rng,
|
|||
)
|
|||
.unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
criterion_group! {
|
|||
name = nizk_eval;
|
|||
config = Criterion::default().sample_size(10);
|
|||
targets = gm17_setup, gm17_prove
|
|||
}
|
|||
|
|||
criterion_main!(nizk_eval);
|
@ -1,180 +1,89 @@ |
|||
#[macro_use]
|
|||
extern crate criterion;
|
|||
|
|||
mod affine {
|
|||
use algebra::ed_on_bls12_377::EdwardsAffine as Edwards;
|
|||
use blake2::Blake2s;
|
|||
use criterion::Criterion;
|
|||
use crypto_primitives::signature::{schnorr::*, SignatureScheme};
|
|||
use rand::{self, Rng};
|
|||
|
|||
type SchnorrEdwards = SchnorrSignature<Edwards, Blake2s>;
|
|||
fn schnorr_signature_setup(c: &mut Criterion) {
|
|||
c.bench_function("SchnorrEdwardsAffine: Setup", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::setup(&mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_keygen(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
|
|||
c.bench_function("SchnorrEdwardsAffine: KeyGen", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::keygen(¶meters, &mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_sign(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let message = [100u8; 128];
|
|||
|
|||
c.bench_function("SchnorrEdwardsAffine: Sign", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_verify(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (pk, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let message = [100u8; 128];
|
|||
let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap();
|
|||
|
|||
c.bench_function("SchnorrEdwardsAffine: Verify", move |b| {
|
|||
b.iter(|| SchnorrEdwards::verify(¶meters, &pk, &message, &signature).unwrap())
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_randomize_pk(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (pk, _) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let randomness: [u8; 32] = rng.gen();
|
|||
|
|||
c.bench_function("SchnorrEdwardsAffine: Randomize PubKey", move |b| {
|
|||
b.iter(|| SchnorrEdwards::randomize_public_key(¶meters, &pk, &randomness).unwrap())
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_randomize_signature(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let randomness: [u8; 32] = rng.gen();
|
|||
let message = [100u8; 128];
|
|||
let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap();
|
|||
|
|||
c.bench_function("SchnorrEdwardsAffine: Randomize Signature", move |b| {
|
|||
b.iter(|| {
|
|||
SchnorrEdwards::randomize_signature(¶meters, &signature, &randomness).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
criterion_group! {
|
|||
name = schnorr_sig_affine;
|
|||
config = Criterion::default().sample_size(20);
|
|||
targets = schnorr_signature_setup, schnorr_signature_keygen, schnorr_signature_sign,
|
|||
schnorr_signature_verify, schnorr_signature_randomize_pk, schnorr_signature_randomize_signature
|
|||
}
|
|||
use algebra::ed_on_bls12_377::EdwardsProjective as Edwards;
|
|||
use blake2::Blake2s;
|
|||
use criterion::Criterion;
|
|||
use crypto_primitives::signature::{schnorr::*, SignatureScheme};
|
|||
use rand::{self, Rng};
|
|||
|
|||
type SchnorrEdwards = Schnorr<Edwards, Blake2s>;
|
|||
fn schnorr_signature_setup(c: &mut Criterion) {
|
|||
c.bench_function("SchnorrEdwards: Setup", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::setup(&mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
mod projective {
|
|||
use algebra::ed_on_bls12_377::EdwardsProjective as Edwards;
|
|||
use blake2::Blake2s;
|
|||
use criterion::Criterion;
|
|||
use crypto_primitives::signature::{schnorr::*, SignatureScheme};
|
|||
use rand::{self, Rng};
|
|||
|
|||
type SchnorrEdwards = SchnorrSignature<Edwards, Blake2s>;
|
|||
fn schnorr_signature_setup(c: &mut Criterion) {
|
|||
c.bench_function("SchnorrEdwardsProjective: Setup", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::setup(&mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_keygen(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
|
|||
c.bench_function("SchnorrEdwardsProjective: KeyGen", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::keygen(¶meters, &mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_sign(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let message = [100u8; 128];
|
|||
fn schnorr_signature_keygen(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
|
|||
c.bench_function("SchnorrEdwardsProjective: Sign", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
c.bench_function("SchnorrEdwards: KeyGen", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::keygen(¶meters, &mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
fn schnorr_signature_verify(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (pk, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let message = [100u8; 128];
|
|||
let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap();
|
|||
fn schnorr_signature_sign(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let message = [100u8; 128];
|
|||
|
|||
c.bench_function("SchnorrEdwards: Sign", move |b| {
|
|||
b.iter(|| {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
|
|||
c.bench_function("SchnorrEdwardsProjective: Verify", move |b| {
|
|||
b.iter(|| SchnorrEdwards::verify(¶meters, &pk, &message, &signature).unwrap())
|
|||
});
|
|||
}
|
|||
fn schnorr_signature_verify(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (pk, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let message = [100u8; 128];
|
|||
let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap();
|
|||
|
|||
fn schnorr_signature_randomize_pk(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (pk, _) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let randomness: [u8; 32] = rng.gen();
|
|||
c.bench_function("SchnorrEdwards: Verify", move |b| {
|
|||
b.iter(|| SchnorrEdwards::verify(¶meters, &pk, &message, &signature).unwrap())
|
|||
});
|
|||
}
|
|||
|
|||
c.bench_function("SchnorrEdwardsProjective: Randomize PubKey", move |b| {
|
|||
b.iter(|| SchnorrEdwards::randomize_public_key(¶meters, &pk, &randomness).unwrap())
|
|||
});
|
|||
}
|
|||
fn schnorr_signature_randomize_pk(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (pk, _) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let randomness: [u8; 32] = rng.gen();
|
|||
|
|||
fn schnorr_signature_randomize_signature(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let randomness: [u8; 32] = rng.gen();
|
|||
let message = [100u8; 128];
|
|||
let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap();
|
|||
c.bench_function("SchnorrEdwards: Randomize PubKey", move |b| {
|
|||
b.iter(|| SchnorrEdwards::randomize_public_key(¶meters, &pk, &randomness).unwrap())
|
|||
});
|
|||
}
|
|||
|
|||
c.bench_function("SchnorrEdwardsProjective: Randomize Signature", move |b| {
|
|||
b.iter(|| {
|
|||
SchnorrEdwards::randomize_signature(¶meters, &signature, &randomness).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
criterion_group! {
|
|||
name = schnorr_sig_projective;
|
|||
config = Criterion::default().sample_size(20);
|
|||
targets = schnorr_signature_setup, schnorr_signature_keygen, schnorr_signature_sign,
|
|||
schnorr_signature_verify, schnorr_signature_randomize_pk, schnorr_signature_randomize_signature
|
|||
}
|
|||
fn schnorr_signature_randomize_signature(c: &mut Criterion) {
|
|||
let mut rng = &mut rand::thread_rng();
|
|||
let parameters = SchnorrEdwards::setup(&mut rng).unwrap();
|
|||
let (_, sk) = SchnorrEdwards::keygen(¶meters, &mut rng).unwrap();
|
|||
let randomness: [u8; 32] = rng.gen();
|
|||
let message = [100u8; 128];
|
|||
let signature = SchnorrEdwards::sign(¶meters, &sk, &message, &mut rng).unwrap();
|
|||
|
|||
c.bench_function("SchnorrEdwards: Randomize Signature", move |b| {
|
|||
b.iter(|| {
|
|||
SchnorrEdwards::randomize_signature(¶meters, &signature, &randomness).unwrap()
|
|||
})
|
|||
});
|
|||
}
|
|||
criterion_group! {
|
|||
name = schnorr_sig;
|
|||
config = Criterion::default().sample_size(20);
|
|||
targets = schnorr_signature_setup, schnorr_signature_keygen, schnorr_signature_sign,
|
|||
schnorr_signature_verify, schnorr_signature_randomize_pk, schnorr_signature_randomize_signature
|
|||
}
|
|||
use crate::{affine::schnorr_sig_affine, projective::schnorr_sig_projective};
|
|||
criterion_main!(schnorr_sig_affine, schnorr_sig_projective);
|
|||
criterion_main!(schnorr_sig);
|
@ -1,23 +1,23 @@ |
|||
use crate::CommitmentScheme;
|
|||
use crate::commitment::CommitmentScheme;
|
|||
use algebra_core::Field;
|
|||
use core::fmt::Debug;
|
|||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|||
use r1cs_core::SynthesisError;
|
|||
use r1cs_std::prelude::*;
|
|||
|
|||
pub trait CommitmentGadget<C: CommitmentScheme, ConstraintF: Field> {
|
|||
type OutputGadget: EqGadget<ConstraintF>
|
|||
type OutputVar: EqGadget<ConstraintF>
|
|||
+ ToBytesGadget<ConstraintF>
|
|||
+ AllocGadget<C::Output, ConstraintF>
|
|||
+ AllocVar<C::Output, ConstraintF>
|
|||
+ R1CSVar<ConstraintF>
|
|||
+ Clone
|
|||
+ Sized
|
|||
+ Debug;
|
|||
type ParametersGadget: AllocGadget<C::Parameters, ConstraintF> + Clone;
|
|||
type RandomnessGadget: AllocGadget<C::Randomness, ConstraintF> + Clone;
|
|||
type ParametersVar: AllocVar<C::Parameters, ConstraintF> + Clone;
|
|||
type RandomnessVar: AllocVar<C::Randomness, ConstraintF> + Clone;
|
|||
|
|||
fn check_commitment_gadget<CS: ConstraintSystem<ConstraintF>>(
|
|||
cs: CS,
|
|||
parameters: &Self::ParametersGadget,
|
|||
input: &[UInt8],
|
|||
r: &Self::RandomnessGadget,
|
|||
) -> Result<Self::OutputGadget, SynthesisError>;
|
|||
fn commit(
|
|||
parameters: &Self::ParametersVar,
|
|||
input: &[UInt8<ConstraintF>],
|
|||
r: &Self::RandomnessVar,
|
|||
) -> Result<Self::OutputVar, SynthesisError>;
|
|||
}
|
@ -1,62 +1,59 @@ |
|||
use algebra_core::{Field, PrimeField};
|
|||
|
|||
use crate::commitment::{
|
|||
injective_map::{InjectiveMap, PedersenCommCompressor},
|
|||
pedersen::{
|
|||
constraints::{
|
|||
PedersenCommitmentGadget, PedersenCommitmentGadgetParameters, PedersenRandomnessGadget,
|
|||
},
|
|||
PedersenWindow,
|
|||
constraints::{CommGadget, ParametersVar, RandomnessVar},
|
|||
Window,
|
|||
},
|
|||
CommitmentGadget,
|
|||
};
|
|||
|
|||
pub use crate::crh::injective_map::constraints::InjectiveMapGadget;
|
|||
use algebra_core::groups::Group;
|
|||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|||
use r1cs_std::{groups::GroupGadget, uint8::UInt8};
|
|||
use algebra_core::{Field, PrimeField, ProjectiveCurve};
|
|||
use r1cs_core::SynthesisError;
|
|||
use r1cs_std::{
|
|||
groups::{CurveVar, GroupOpsBounds},
|
|||
uint8::UInt8,
|
|||
};
|
|||
|
|||
use core::marker::PhantomData;
|
|||
|
|||
pub struct PedersenCommitmentCompressorGadget<G, I, ConstraintF, GG, IG>
|
|||
type ConstraintF<C> = <<C as ProjectiveCurve>::BaseField as Field>::BasePrimeField;
|
|||
|
|||
pub struct CommitmentCompressorGadget<C, I, W, GG, IG>
|
|||
where
|
|||
G: Group,
|
|||
I: InjectiveMap<G>,
|
|||
ConstraintF: Field,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
IG: InjectiveMapGadget<G, I, ConstraintF, GG>,
|
|||
C: ProjectiveCurve,
|
|||
I: InjectiveMap<C>,
|
|||
W: Window,
|
|||
GG: CurveVar<C, ConstraintF<C>>,
|
|||
IG: InjectiveMapGadget<C, I, GG>,
|
|||
for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
|
|||
{
|
|||
_compressor: PhantomData<I>,
|
|||
_compressor_gadget: PhantomData<IG>,
|
|||
_crh: PedersenCommitmentGadget<G, ConstraintF, GG>,
|
|||
_comm: PhantomData<CommGadget<C, GG, W>>,
|
|||
}
|
|||
|
|||
impl<G, I, ConstraintF, GG, IG, W> CommitmentGadget<PedersenCommCompressor<G, I, W>, ConstraintF>
|
|||
for PedersenCommitmentCompressorGadget<G, I, ConstraintF, GG, IG>
|
|||
impl<C, I, GG, IG, W>
|
|||
crate::commitment::CommitmentGadget<PedersenCommCompressor<C, I, W>, ConstraintF<C>>
|
|||
for CommitmentCompressorGadget<C, I, W, GG, IG>
|
|||
where
|
|||
G: Group,
|
|||
I: InjectiveMap<G>,
|
|||
ConstraintF: PrimeField,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
IG: InjectiveMapGadget<G, I, ConstraintF, GG>,
|
|||
W: PedersenWindow,
|
|||
C: ProjectiveCurve,
|
|||
I: InjectiveMap<C>,
|
|||
GG: CurveVar<C, ConstraintF<C>>,
|
|||
ConstraintF<C>: PrimeField,
|
|||
IG: InjectiveMapGadget<C, I, GG>,
|
|||
W: Window,
|
|||
for<'a> &'a GG: GroupOpsBounds<'a, C, GG>,
|
|||
{
|
|||
type OutputGadget = IG::OutputGadget;
|
|||
type ParametersGadget = PedersenCommitmentGadgetParameters<G, W, ConstraintF>;
|
|||
type RandomnessGadget = PedersenRandomnessGadget;
|
|||
type OutputVar = IG::OutputVar;
|
|||
type ParametersVar = ParametersVar<C, GG>;
|
|||
type RandomnessVar = RandomnessVar<ConstraintF<C>>;
|
|||
|
|||
fn check_commitment_gadget<CS: ConstraintSystem<ConstraintF>>(
|
|||
mut cs: CS,
|
|||
parameters: &Self::ParametersGadget,
|
|||
input: &[UInt8],
|
|||
r: &Self::RandomnessGadget,
|
|||
) -> Result<Self::OutputGadget, SynthesisError> {
|
|||
let result = PedersenCommitmentGadget::<G, ConstraintF, GG>::check_commitment_gadget(
|
|||
cs.ns(|| "PedersenComm"),
|
|||
parameters,
|
|||
input,
|
|||
r,
|
|||
)?;
|
|||
IG::evaluate_map(cs.ns(|| "InjectiveMap"), &result)
|
|||
fn commit(
|
|||
parameters: &Self::ParametersVar,
|
|||
input: &[UInt8<ConstraintF<C>>],
|
|||
r: &Self::RandomnessVar,
|
|||
) -> Result<Self::OutputVar, SynthesisError> {
|
|||
let result = CommGadget::<C, GG, W>::commit(parameters, input, r)?;
|
|||
IG::evaluate(&result)
|
|||
}
|
|||
}
|
@ -1,47 +1,59 @@ |
|||
use algebra_core::Field;
|
|||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|||
use core::borrow::Borrow;
|
|||
use r1cs_core::{Namespace, SynthesisError};
|
|||
use r1cs_std::prelude::*;
|
|||
|
|||
use crate::nizk::NIZK;
|
|||
|
|||
pub trait NIZKVerifierGadget<N: NIZK, ConstraintF: Field> {
|
|||
type PreparedVerificationKeyGadget;
|
|||
type VerificationKeyGadget: AllocGadget<N::VerificationParameters, ConstraintF>
|
|||
type PreparedVerificationKeyVar;
|
|||
type VerificationKeyVar: AllocVar<N::VerificationParameters, ConstraintF>
|
|||
+ ToBytesGadget<ConstraintF>;
|
|||
type ProofGadget: AllocGadget<N::Proof, ConstraintF>;
|
|||
type ProofVar: AllocVar<N::Proof, ConstraintF>;
|
|||
|
|||
fn check_verify<'a, CS, I, T>(
|
|||
cs: CS,
|
|||
verification_key: &Self::VerificationKeyGadget,
|
|||
input: I,
|
|||
proof: &Self::ProofGadget,
|
|||
) -> Result<(), SynthesisError>
|
|||
where
|
|||
CS: ConstraintSystem<ConstraintF>,
|
|||
I: Iterator<Item = &'a T>,
|
|||
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
|
|||
/// Optionally allocates `N::Proof` in `cs` without performing
|
|||
/// subgroup checks.
|
|||
///
|
|||
/// The default implementation doesn't omit these checks.
|
|||
fn new_proof_unchecked<T: Borrow<N::Proof>>(
|
|||
cs: impl Into<Namespace<ConstraintF>>,
|
|||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
|||
mode: AllocationMode,
|
|||
) -> Result<Self::ProofVar, SynthesisError> {
|
|||
Self::ProofVar::new_variable(cs, f, mode)
|
|||
}
|
|||
|
|||
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;
|
|||
/// Optionally allocates `N::VerificationParameters` in `cs`
|
|||
/// without performing subgroup checks.
|
|||
///
|
|||
/// The default implementation doesn't omit these checks.
|
|||
fn new_verification_key_unchecked<T: Borrow<N::VerificationParameters>>(
|
|||
cs: impl Into<Namespace<ConstraintF>>,
|
|||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
|||
mode: AllocationMode,
|
|||
) -> Result<Self::VerificationKeyVar, SynthesisError> {
|
|||
Self::VerificationKeyVar::new_variable(cs, f, mode)
|
|||
}
|
|||
|
|||
fn conditional_check_verify_prepared<'a, CS, I, T>(
|
|||
cs: CS,
|
|||
prepared_verification_key: &Self::PreparedVerificationKeyGadget,
|
|||
input: I,
|
|||
proof: &Self::ProofGadget,
|
|||
condition: &Boolean,
|
|||
) -> Result<(), SynthesisError>
|
|||
where
|
|||
CS: ConstraintSystem<ConstraintF>,
|
|||
I: Iterator<Item = &'a T>,
|
|||
T: 'a + ToBitsGadget<ConstraintF> + ?Sized;
|
|||
fn verify<'a, T: 'a + ToBitsGadget<ConstraintF> + ?Sized>(
|
|||
verification_key: &Self::VerificationKeyVar,
|
|||
input: impl Iterator<Item = &'a T>,
|
|||
proof: &Self::ProofVar,
|
|||
) -> Result<(), SynthesisError> {
|
|||
Self::conditional_verify(verification_key, input, proof, &Boolean::constant(true))
|
|||
}
|
|||
|
|||
fn conditional_verify<'a, T: 'a + ToBitsGadget<ConstraintF> + ?Sized>(
|
|||
verification_key: &Self::VerificationKeyVar,
|
|||
input: impl Iterator<Item = &'a T>,
|
|||
proof: &Self::ProofVar,
|
|||
condition: &Boolean<ConstraintF>,
|
|||
) -> Result<(), SynthesisError>;
|
|||
|
|||
fn conditional_verify_prepared<'a, T: 'a + ToBitsGadget<ConstraintF> + ?Sized>(
|
|||
prepared_verification_key: &Self::PreparedVerificationKeyVar,
|
|||
input: impl Iterator<Item = &'a T>,
|
|||
proof: &Self::ProofVar,
|
|||
condition: &Boolean<ConstraintF>,
|
|||
) -> Result<(), SynthesisError>;
|
|||
}
|
@ -1,21 +1,20 @@ |
|||
use algebra_core::Field;
|
|||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|||
use r1cs_core::SynthesisError;
|
|||
use r1cs_std::prelude::*;
|
|||
|
|||
use crate::signature::SignatureScheme;
|
|||
|
|||
pub trait SigRandomizePkGadget<S: SignatureScheme, ConstraintF: Field> {
|
|||
type ParametersGadget: AllocGadget<S::Parameters, ConstraintF> + Clone;
|
|||
type ParametersVar: AllocVar<S::Parameters, ConstraintF> + Clone;
|
|||
|
|||
type PublicKeyGadget: ToBytesGadget<ConstraintF>
|
|||
type PublicKeyVar: ToBytesGadget<ConstraintF>
|
|||
+ EqGadget<ConstraintF>
|
|||
+ AllocGadget<S::PublicKey, ConstraintF>
|
|||
+ AllocVar<S::PublicKey, ConstraintF>
|
|||
+ Clone;
|
|||
|
|||
fn check_randomization_gadget<CS: ConstraintSystem<ConstraintF>>(
|
|||
cs: CS,
|
|||
parameters: &Self::ParametersGadget,
|
|||
public_key: &Self::PublicKeyGadget,
|
|||
randomness: &[UInt8],
|
|||
) -> Result<Self::PublicKeyGadget, SynthesisError>;
|
|||
fn randomize(
|
|||
parameters: &Self::ParametersVar,
|
|||
public_key: &Self::PublicKeyVar,
|
|||
randomness: &[UInt8<ConstraintF>],
|
|||
) -> Result<Self::PublicKeyVar, SynthesisError>;
|
|||
}
|
@ -1,242 +1,157 @@ |
|||
use crate::Vec;
|
|||
use algebra_core::{groups::Group, Field};
|
|||
use r1cs_core::{ConstraintSystem, SynthesisError};
|
|||
use algebra_core::{Field, ProjectiveCurve};
|
|||
use r1cs_core::{Namespace, SynthesisError};
|
|||
use r1cs_std::prelude::*;
|
|||
|
|||
use crate::signature::SigRandomizePkGadget;
|
|||
|
|||
use core::{borrow::Borrow, marker::PhantomData};
|
|||
|
|||
use crate::signature::schnorr::{SchnorrPublicKey, SchnorrSigParameters, SchnorrSignature};
|
|||
use crate::signature::schnorr::{Parameters, PublicKey, Schnorr};
|
|||
use digest::Digest;
|
|||
|
|||
pub struct SchnorrSigGadgetParameters<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>>
|
|||
{
|
|||
generator: GG,
|
|||
_group: PhantomData<*const G>,
|
|||
_engine: PhantomData<*const ConstraintF>,
|
|||
}
|
|||
type ConstraintF<C> = <<C as ProjectiveCurve>::BaseField as Field>::BasePrimeField;
|
|||
|
|||
impl<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> Clone
|
|||
for SchnorrSigGadgetParameters<G, ConstraintF, GG>
|
|||
#[derive(Clone)]
|
|||
pub struct ParametersVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
|||
where
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
fn clone(&self) -> Self {
|
|||
Self {
|
|||
generator: self.generator.clone(),
|
|||
_group: PhantomData,
|
|||
_engine: PhantomData,
|
|||
}
|
|||
}
|
|||
generator: GC,
|
|||
_curve: PhantomData<C>,
|
|||
}
|
|||
|
|||
#[derive(Derivative)]
|
|||
#[derivative(
|
|||
Debug(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
|
|||
Clone(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
|
|||
PartialEq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>"),
|
|||
Eq(bound = "G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>")
|
|||
Debug(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>"),
|
|||
Clone(bound = "C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>")
|
|||
)]
|
|||
pub struct SchnorrSigGadgetPk<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
|
|||
pub_key: GG,
|
|||
#[doc(hidden)]
|
|||
_group: PhantomData<*const G>,
|
|||
pub struct PublicKeyVar<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
|||
where
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
pub_key: GC,
|
|||
#[doc(hidden)]
|
|||
_engine: PhantomData<*const ConstraintF>,
|
|||
_group: PhantomData<*const C>,
|
|||
}
|
|||
|
|||
pub struct SchnorrRandomizePkGadget<G: Group, ConstraintF: Field, GG: GroupGadget<G, ConstraintF>> {
|
|||
#[doc(hidden)]
|
|||
_group: PhantomData<*const G>,
|
|||
pub struct SchnorrRandomizePkGadget<C: ProjectiveCurve, GC: CurveVar<C, ConstraintF<C>>>
|
|||
where
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
#[doc(hidden)]
|
|||
_group_gadget: PhantomData<*const GG>,
|
|||
_group: PhantomData<*const C>,
|
|||
#[doc(hidden)]
|
|||
_engine: PhantomData<*const ConstraintF>,
|
|||
_group_gadget: PhantomData<*const GC>,
|
|||
}
|
|||
|
|||
impl<G, GG, D, ConstraintF> SigRandomizePkGadget<SchnorrSignature<G, D>, ConstraintF>
|
|||
for SchnorrRandomizePkGadget<G, ConstraintF, GG>
|
|||
impl<C, GC, D> SigRandomizePkGadget<Schnorr<C, D>, ConstraintF<C>>
|
|||
for SchnorrRandomizePkGadget<C, GC>
|
|||
where
|
|||
G: Group,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
C: ProjectiveCurve,
|
|||
GC: CurveVar<C, ConstraintF<C>>,
|
|||
D: Digest + Send + Sync,
|
|||
ConstraintF: Field,
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
type ParametersGadget = SchnorrSigGadgetParameters<G, ConstraintF, GG>;
|
|||
type PublicKeyGadget = SchnorrSigGadgetPk<G, ConstraintF, GG>;
|
|||
|
|||
fn check_randomization_gadget<CS: ConstraintSystem<ConstraintF>>(
|
|||
mut cs: CS,
|
|||
parameters: &Self::ParametersGadget,
|
|||
public_key: &Self::PublicKeyGadget,
|
|||
randomness: &[UInt8],
|
|||
) -> Result<Self::PublicKeyGadget, SynthesisError> {
|
|||
type ParametersVar = ParametersVar<C, GC>;
|
|||
type PublicKeyVar = PublicKeyVar<C, GC>;
|
|||
|
|||
fn randomize(
|
|||
parameters: &Self::ParametersVar,
|
|||
public_key: &Self::PublicKeyVar,
|
|||
randomness: &[UInt8<ConstraintF<C>>],
|
|||
) -> Result<Self::PublicKeyVar, SynthesisError> {
|
|||
let base = parameters.generator.clone();
|
|||
let randomness = randomness
|
|||
.iter()
|
|||
.flat_map(|b| b.into_bits_le())
|
|||
.collect::<Vec<_>>();
|
|||
let rand_pk = base.mul_bits(
|
|||
&mut cs.ns(|| "Compute Randomizer"),
|
|||
&public_key.pub_key,
|
|||
randomness.iter(),
|
|||
)?;
|
|||
Ok(SchnorrSigGadgetPk {
|
|||
let rand_pk = &public_key.pub_key + &base.mul_bits(randomness.iter())?;
|
|||
Ok(PublicKeyVar {
|
|||
pub_key: rand_pk,
|
|||
_group: PhantomData,
|
|||
_engine: PhantomData,
|
|||
})
|
|||
}
|
|||
}
|
|||
|
|||
impl<G, ConstraintF, GG, D> AllocGadget<SchnorrSigParameters<G, D>, ConstraintF>
|
|||
for SchnorrSigGadgetParameters<G, ConstraintF, GG>
|
|||
impl<C, GC, D> AllocVar<Parameters<C, D>, ConstraintF<C>> for ParametersVar<C, GC>
|
|||
where
|
|||
G: Group,
|
|||
ConstraintF: Field,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
C: ProjectiveCurve,
|
|||
GC: CurveVar<C, ConstraintF<C>>,
|
|||
D: Digest,
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
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)?;
|
|||
fn new_variable<T: Borrow<Parameters<C, D>>>(
|
|||
cs: impl Into<Namespace<ConstraintF<C>>>,
|
|||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
|||
mode: AllocationMode,
|
|||
) -> Result<Self, SynthesisError> {
|
|||
let generator = GC::new_variable(cs, || f().map(|g| g.borrow().generator), mode)?;
|
|||
Ok(Self {
|
|||
generator,
|
|||
_engine: PhantomData,
|
|||
_group: PhantomData,
|
|||
})
|
|||
}
|
|||
|
|||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
|||
where
|
|||
F: FnOnce() -> Result<T, SynthesisError>,
|
|||
T: Borrow<SchnorrSigParameters<G, D>>,
|
|||
{
|
|||
let generator = GG::alloc_checked(cs, || f().map(|pp| pp.borrow().generator))?;
|
|||
Ok(Self {
|
|||
generator,
|
|||
_engine: PhantomData,
|
|||
_group: PhantomData,
|
|||
})
|
|||
}
|
|||
|
|||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
|||
cs: CS,
|
|||
f: F,
|
|||
) -> Result<Self, SynthesisError>
|
|||
where
|
|||
F: FnOnce() -> Result<T, SynthesisError>,
|
|||
T: Borrow<SchnorrSigParameters<G, D>>,
|
|||
{
|
|||
let generator = GG::alloc_input(cs, || f().map(|pp| pp.borrow().generator))?;
|
|||
Ok(Self {
|
|||
generator,
|
|||
_engine: PhantomData,
|
|||
_group: PhantomData,
|
|||
_curve: PhantomData,
|
|||
})
|
|||
}
|
|||
}
|
|||
|
|||
impl<G, ConstraintF, GG> AllocGadget<SchnorrPublicKey<G>, ConstraintF>
|
|||
for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
|||
impl<C, GC> AllocVar<PublicKey<C>, ConstraintF<C>> for PublicKeyVar<C, GC>
|
|||
where
|
|||
G: Group,
|
|||
ConstraintF: Field,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
C: ProjectiveCurve,
|
|||
GC: CurveVar<C, ConstraintF<C>>,
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
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())?;
|
|||
fn new_variable<T: Borrow<PublicKey<C>>>(
|
|||
cs: impl Into<Namespace<ConstraintF<C>>>,
|
|||
f: impl FnOnce() -> Result<T, SynthesisError>,
|
|||
mode: AllocationMode,
|
|||
) -> Result<Self, SynthesisError> {
|
|||
let pub_key = GC::new_variable(cs, f, mode)?;
|
|||
Ok(Self {
|
|||
pub_key,
|
|||
_engine: PhantomData,
|
|||
_group: PhantomData,
|
|||
})
|
|||
}
|
|||
|
|||
fn alloc<F, T, CS: ConstraintSystem<ConstraintF>>(cs: CS, f: F) -> Result<Self, SynthesisError>
|
|||
where
|
|||
F: FnOnce() -> Result<T, SynthesisError>,
|
|||
T: Borrow<SchnorrPublicKey<G>>,
|
|||
{
|
|||
let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
|
|||
Ok(Self {
|
|||
pub_key,
|
|||
_engine: PhantomData,
|
|||
_group: PhantomData,
|
|||
})
|
|||
}
|
|||
|
|||
fn alloc_input<F, T, CS: ConstraintSystem<ConstraintF>>(
|
|||
cs: CS,
|
|||
f: F,
|
|||
) -> Result<Self, SynthesisError>
|
|||
where
|
|||
F: FnOnce() -> Result<T, SynthesisError>,
|
|||
T: Borrow<SchnorrPublicKey<G>>,
|
|||
{
|
|||
let pub_key = GG::alloc_input(cs, || f().map(|pk| *pk.borrow()))?;
|
|||
Ok(Self {
|
|||
pub_key,
|
|||
_engine: PhantomData,
|
|||
_group: PhantomData,
|
|||
})
|
|||
}
|
|||
}
|
|||
|
|||
impl<G, ConstraintF, GG> ConditionalEqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
|||
impl<C, GC> EqGadget<ConstraintF<C>> for PublicKeyVar<C, GC>
|
|||
where
|
|||
G: Group,
|
|||
ConstraintF: Field,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
C: ProjectiveCurve,
|
|||
GC: CurveVar<C, ConstraintF<C>>,
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
#[inline]
|
|||
fn conditional_enforce_equal<CS: ConstraintSystem<ConstraintF>>(
|
|||
fn is_eq(&self, other: &Self) -> Result<Boolean<ConstraintF<C>>, SynthesisError> {
|
|||
self.pub_key.is_eq(&other.pub_key)
|
|||
}
|
|||
|
|||
#[inline]
|
|||
fn conditional_enforce_equal(
|
|||
&self,
|
|||
mut cs: CS,
|
|||
other: &Self,
|
|||
condition: &Boolean,
|
|||
condition: &Boolean<ConstraintF<C>>,
|
|||
) -> Result<(), SynthesisError> {
|
|||
self.pub_key.conditional_enforce_equal(
|
|||
&mut cs.ns(|| "PubKey equality"),
|
|||
&other.pub_key,
|
|||
condition,
|
|||
)?;
|
|||
Ok(())
|
|||
self.pub_key
|
|||
.conditional_enforce_equal(&other.pub_key, condition)
|
|||
}
|
|||
|
|||
fn cost() -> usize {
|
|||
<GG as ConditionalEqGadget<ConstraintF>>::cost()
|
|||
#[inline]
|
|||
fn conditional_enforce_not_equal(
|
|||
&self,
|
|||
other: &Self,
|
|||
condition: &Boolean<ConstraintF<C>>,
|
|||
) -> Result<(), SynthesisError> {
|
|||
self.pub_key
|
|||
.conditional_enforce_not_equal(&other.pub_key, condition)
|
|||
}
|
|||
}
|
|||
|
|||
impl<G, ConstraintF, GG> EqGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
|||
where
|
|||
G: Group,
|
|||
ConstraintF: Field,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
{
|
|||
}
|
|||
|
|||
impl<G, ConstraintF, GG> ToBytesGadget<ConstraintF> for SchnorrSigGadgetPk<G, ConstraintF, GG>
|
|||
impl<C, GC> ToBytesGadget<ConstraintF<C>> for PublicKeyVar<C, GC>
|
|||
where
|
|||
G: Group,
|
|||
ConstraintF: Field,
|
|||
GG: GroupGadget<G, ConstraintF>,
|
|||
C: ProjectiveCurve,
|
|||
GC: CurveVar<C, ConstraintF<C>>,
|
|||
for<'a> &'a GC: GroupOpsBounds<'a, C, GC>,
|
|||
{
|
|||
fn to_bytes<CS: ConstraintSystem<ConstraintF>>(
|
|||
&self,
|
|||
mut cs: CS,
|
|||
) -> Result<Vec<UInt8>, SynthesisError> {
|
|||
self.pub_key.to_bytes(&mut cs.ns(|| "PubKey To Bytes"))
|
|||
fn to_bytes(&self) -> Result<Vec<UInt8<ConstraintF<C>>>, SynthesisError> {
|
|||
self.pub_key.to_bytes()
|
|||
}
|
|||
}
|