make custom transcript that is implementable as SC

This commit is contained in:
Alex Vlasov 2019-02-05 17:23:26 +03:00
parent 528f0623ef
commit 7239a60044
8 changed files with 434 additions and 456 deletions

@ -22,5 +22,11 @@ pairing = { git = 'https://github.com/matterinc/pairing' }
byteorder = "1"
ff = { git = 'https://github.com/matterinc/ff', features = ["derive"] }
tiny-keccak = "1.4.2"
[dependencies.blake2-rfc]
git = "https://github.com/gtank/blake2-rfc"
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
[features]
default = []

@ -126,3 +126,39 @@ impl<E: Engine> Batch<E> {
])).unwrap() == E::Fqk::one()
}
}
pub struct VerificationKey<E:Engine> {
alpha_x: E::G2Affine,
alpha: E::G2Affine,
neg_h: E::G2Affine,
neg_x_n_minus_d: E::G2Affine
}
impl<E: Engine> VerificationKey<E> {
pub fn new(srs: &SRS<E>, n: usize) -> Self {
Self {
alpha_x: srs.h_positive_x_alpha[1],
alpha: srs.h_positive_x_alpha[0],
neg_h: {
let mut tmp = srs.h_negative_x[0];
tmp.negate();
tmp
},
neg_x_n_minus_d: {
let mut tmp = srs.h_negative_x[srs.d - n];
tmp.negate();
tmp
},
}
}
}

228
src/sonic/helped/helper.rs Normal file

@ -0,0 +1,228 @@
use ff::{Field};
use pairing::{Engine, CurveProjective};
use std::marker::PhantomData;
use super::{Proof, SxyAdvice};
use super::batch::Batch;
use super::poly::{SxEval, SyEval};
use crate::SynthesisError;
use crate::sonic::transcript::{Transcript, TranscriptProtocol};
use crate::sonic::util::*;
use crate::sonic::cs::{Backend, SynthesisDriver};
use crate::sonic::cs::{Circuit, Variable, Coeff};
use crate::sonic::srs::SRS;
#[derive(Clone)]
pub struct Aggregate<E: Engine> {
// Commitment to s(z, Y)
pub c: E::G1Affine,
// We have to open each of the S commitments to a random point `z`
pub s_opening: E::G1Affine,
// We have to open C to each constituent `y`
pub c_openings: Vec<(E::G1Affine, E::Fr)>,
// Then we have to finally open C
pub opening: E::G1Affine,
}
pub fn create_aggregate<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
circuit: &C,
inputs: &[(Proof<E>, SxyAdvice<E>)],
srs: &SRS<E>,
) -> Aggregate<E>
{
// TODO: precompute this?
let (n, q) = {
struct CountN {
n: usize,
q: usize
}
impl<'a, E: Engine> Backend<E> for &'a mut CountN {
fn new_multiplication_gate(&mut self) {
self.n += 1;
}
fn new_linear_constraint(&mut self) {
self.q += 1;
}
}
let mut tmp = CountN{n:0,q:0};
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
(tmp.n, tmp.q)
};
let mut transcript = Transcript::new(&[]);
let mut y_values: Vec<E::Fr> = Vec::with_capacity(inputs.len());
for &(ref proof, ref sxyadvice) in inputs {
{
let mut transcript = Transcript::new(&[]);
transcript.commit_point(&proof.r);
y_values.push(transcript.get_challenge_scalar());
}
transcript.commit_point(&sxyadvice.s);
}
let z: E::Fr = transcript.get_challenge_scalar();
// Compute s(z, Y)
let (s_poly_negative, s_poly_positive) = {
let mut tmp = SyEval::new(z, n, q);
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
tmp.poly()
};
// Compute C = g^{s(z, x)}
let c = multiexp(
srs.g_positive_x_alpha[0..(n + q)]
.iter()
.chain_ext(srs.g_negative_x_alpha[0..n].iter()),
s_poly_positive.iter().chain_ext(s_poly_negative.iter())
).into_affine();
transcript.commit_point(&c);
// Open C at w
let w: E::Fr = transcript.get_challenge_scalar();
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
let opening = {
let mut value = value;
value.negate();
let poly = kate_divison(
s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()),
w,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
// TODO: parallelize
// Let's open up C to every y.
fn compute_value<E: Engine>(y: &E::Fr, poly_positive: &[E::Fr], poly_negative: &[E::Fr]) -> E::Fr {
let mut value = E::Fr::zero();
let yinv = y.inverse().unwrap(); // TODO
let mut tmp = yinv;
for &coeff in poly_negative {
let mut coeff = coeff;
coeff.mul_assign(&tmp);
value.add_assign(&coeff);
tmp.mul_assign(&yinv);
}
let mut tmp = *y;
for &coeff in poly_positive {
let mut coeff = coeff;
coeff.mul_assign(&tmp);
value.add_assign(&coeff);
tmp.mul_assign(&y);
}
value
}
let mut c_openings = vec![];
for y in &y_values {
let value = compute_value::<E>(y, &s_poly_positive, &s_poly_negative);
let opening = {
let mut value = value;
value.negate();
let poly = kate_divison(
s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()),
*y,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
c_openings.push((opening, value));
}
// Okay, great. Now we need to open up each S at the same point z to the same value.
// Since we're opening up all the S's at the same point, we create a bunch of random
// challenges instead and open up a random linear combination.
let mut poly_negative = vec![E::Fr::zero(); n];
let mut poly_positive = vec![E::Fr::zero(); 2*n];
let mut expected_value = E::Fr::zero();
for (y, c_opening) in y_values.iter().zip(c_openings.iter()) {
// Compute s(X, y_i)
let (s_poly_negative, s_poly_positive) = {
let mut tmp = SxEval::new(*y, n);
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
tmp.poly()
};
let mut value = c_opening.1;
let r: E::Fr = transcript.get_challenge_scalar();
value.mul_assign(&r);
expected_value.add_assign(&value);
for (mut coeff, target) in s_poly_negative.into_iter().zip(poly_negative.iter_mut()) {
coeff.mul_assign(&r);
target.add_assign(&coeff);
}
for (mut coeff, target) in s_poly_positive.into_iter().zip(poly_positive.iter_mut()) {
coeff.mul_assign(&r);
target.add_assign(&coeff);
}
}
// TODO: parallelize
let s_opening = {
let mut value = expected_value;
value.negate();
let poly = kate_divison(
poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(poly_positive.iter()),
z,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
Aggregate {
// Commitment to s(z, Y)
c,
// We have to open each of the S commitments to a random point `z`
s_opening,
// We have to open C to each constituent `y`
c_openings,
// Then we have to finally open C
opening,
}
}

@ -1,25 +1,20 @@
extern crate ff;
extern crate pairing;
// extern crate merlin;
use ff::{Field};
use pairing::{Engine, CurveProjective};
use std::marker::PhantomData;
// use merlin::{Transcript};
mod verifier;
mod prover;
mod batch;
mod poly;
mod helper;
pub use self::verifier::{MultiVerifier, create_aggregate};
pub use self::prover::{Aggregate, create_proof, create_advice};
// use super::super::util::*;
// pub use super::batch::Batch;
// use crate::synthesis::{Backend, SynthesisDriver};
// use crate::{Circuit, SynthesisError, Variable, Coeff};
// use crate::srs::SRS;
pub use self::batch::{Batch, VerificationKey};
pub use self::helper::{Aggregate, create_aggregate};
pub use self::verifier::{MultiVerifier};
pub use self::prover::{create_proof, create_advice};
#[derive(Clone)]
pub struct SxyAdvice<E: Engine> {

@ -14,217 +14,6 @@ use crate::sonic::cs::{Backend, SynthesisDriver};
use crate::sonic::cs::{Circuit, Variable, Coeff};
use crate::sonic::srs::SRS;
#[derive(Clone)]
pub struct Aggregate<E: Engine> {
// Commitment to s(z, Y)
c: E::G1Affine,
// We have to open each of the S commitments to a random point `z`
s_opening: E::G1Affine,
// We have to open C to each constituent `y`
c_openings: Vec<(E::G1Affine, E::Fr)>,
// Then we have to finally open C
opening: E::G1Affine,
}
pub fn create_aggregate<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
circuit: &C,
inputs: &[(Proof<E>, SxyAdvice<E>)],
srs: &SRS<E>,
) -> Aggregate<E>
{
// TODO: precompute this?
let (n, q) = {
struct CountN {
n: usize,
q: usize
}
impl<'a, E: Engine> Backend<E> for &'a mut CountN {
fn new_multiplication_gate(&mut self) {
self.n += 1;
}
fn new_linear_constraint(&mut self) {
self.q += 1;
}
}
let mut tmp = CountN{n:0,q:0};
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
(tmp.n, tmp.q)
};
let mut transcript = Transcript::new(&[]);
let mut y_values: Vec<E::Fr> = Vec::with_capacity(inputs.len());
for &(ref proof, ref sxyadvice) in inputs {
{
let mut transcript = Transcript::new(&[]);
transcript.commit_point(&proof.r);
y_values.push(transcript.get_challenge_scalar());
}
transcript.commit_point(&sxyadvice.s);
}
let z: E::Fr = transcript.get_challenge_scalar();
// Compute s(z, Y)
let (s_poly_negative, s_poly_positive) = {
let mut tmp = SyEval::new(z, n, q);
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
tmp.poly()
};
// Compute C = g^{s(z, x)}
let c = multiexp(
srs.g_positive_x_alpha[0..(n + q)]
.iter()
.chain_ext(srs.g_negative_x_alpha[0..n].iter()),
s_poly_positive.iter().chain_ext(s_poly_negative.iter())
).into_affine();
transcript.commit_point(&c);
// Open C at w
let w: E::Fr = transcript.get_challenge_scalar();
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
let opening = {
let mut value = value;
value.negate();
let poly = kate_divison(
s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()),
w,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
// Let's open up C to every y.
fn compute_value<E: Engine>(y: &E::Fr, poly_positive: &[E::Fr], poly_negative: &[E::Fr]) -> E::Fr {
let mut value = E::Fr::zero();
let yinv = y.inverse().unwrap(); // TODO
let mut tmp = yinv;
for &coeff in poly_negative {
let mut coeff = coeff;
coeff.mul_assign(&tmp);
value.add_assign(&coeff);
tmp.mul_assign(&yinv);
}
let mut tmp = *y;
for &coeff in poly_positive {
let mut coeff = coeff;
coeff.mul_assign(&tmp);
value.add_assign(&coeff);
tmp.mul_assign(&y);
}
value
}
let mut c_openings = vec![];
for y in &y_values {
let value = compute_value::<E>(y, &s_poly_positive, &s_poly_negative);
let opening = {
let mut value = value;
value.negate();
let poly = kate_divison(
s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()),
*y,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
c_openings.push((opening, value));
}
// Okay, great. Now we need to open up each S at the same point z to the same value.
// Since we're opening up all the S's at the same point, we create a bunch of random
// challenges instead and open up a random linear combination.
let mut poly_negative = vec![E::Fr::zero(); n];
let mut poly_positive = vec![E::Fr::zero(); 2*n];
let mut expected_value = E::Fr::zero();
for (y, c_opening) in y_values.iter().zip(c_openings.iter()) {
// Compute s(X, y_i)
let (s_poly_negative, s_poly_positive) = {
let mut tmp = SxEval::new(*y, n);
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
tmp.poly()
};
let mut value = c_opening.1;
let r: E::Fr = transcript.get_challenge_scalar();
value.mul_assign(&r);
expected_value.add_assign(&value);
for (mut coeff, target) in s_poly_negative.into_iter().zip(poly_negative.iter_mut()) {
coeff.mul_assign(&r);
target.add_assign(&coeff);
}
for (mut coeff, target) in s_poly_positive.into_iter().zip(poly_positive.iter_mut()) {
coeff.mul_assign(&r);
target.add_assign(&coeff);
}
}
let s_opening = {
let mut value = expected_value;
value.negate();
let poly = kate_divison(
poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(poly_positive.iter()),
z,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
Aggregate {
// Commitment to s(z, Y)
c,
// We have to open each of the S commitments to a random point `z`
s_opening,
// We have to open C to each constituent `y`
c_openings,
// Then we have to finally open C
opening,
}
}
pub fn create_advice<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
circuit: &C,
proof: &Proof<E>,

@ -5,6 +5,7 @@ use std::marker::PhantomData;
use super::{Proof, SxyAdvice};
use super::batch::Batch;
use super::poly::{SxEval, SyEval};
use super::helper::Aggregate;
use crate::SynthesisError;
@ -249,217 +250,4 @@ impl<E: Engine, C: Circuit<E>, S: SynthesisDriver> MultiVerifier<E, C, S> {
pub fn check_all(self) -> bool {
self.batch.check_all()
}
}
#[derive(Clone)]
pub struct Aggregate<E: Engine> {
// Commitment to s(z, Y)
c: E::G1Affine,
// We have to open each of the S commitments to a random point `z`
s_opening: E::G1Affine,
// We have to open C to each constituent `y`
c_openings: Vec<(E::G1Affine, E::Fr)>,
// Then we have to finally open C
opening: E::G1Affine,
}
pub fn create_aggregate<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
circuit: &C,
inputs: &[(Proof<E>, SxyAdvice<E>)],
srs: &SRS<E>,
) -> Aggregate<E>
{
// TODO: precompute this?
let (n, q) = {
struct CountN {
n: usize,
q: usize
}
impl<'a, E: Engine> Backend<E> for &'a mut CountN {
fn new_multiplication_gate(&mut self) {
self.n += 1;
}
fn new_linear_constraint(&mut self) {
self.q += 1;
}
}
let mut tmp = CountN{n:0,q:0};
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
(tmp.n, tmp.q)
};
let mut transcript = Transcript::new(&[]);
let mut y_values: Vec<E::Fr> = Vec::with_capacity(inputs.len());
for &(ref proof, ref sxyadvice) in inputs {
{
let mut transcript = Transcript::new(&[]);
transcript.commit_point(&proof.r);
y_values.push(transcript.get_challenge_scalar());
}
transcript.commit_point(&sxyadvice.s);
}
let z: E::Fr = transcript.get_challenge_scalar();
// Compute s(z, Y)
let (s_poly_negative, s_poly_positive) = {
let mut tmp = SyEval::new(z, n, q);
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
tmp.poly()
};
// Compute C = g^{s(z, x)}
let c = multiexp(
srs.g_positive_x_alpha[0..(n + q)]
.iter()
.chain_ext(srs.g_negative_x_alpha[0..n].iter()),
s_poly_positive.iter().chain_ext(s_poly_negative.iter())
).into_affine();
transcript.commit_point(&c);
// Open C at w
let w: E::Fr = transcript.get_challenge_scalar();
let value = compute_value::<E>(&w, &s_poly_positive, &s_poly_negative);
let opening = {
let mut value = value;
value.negate();
let poly = kate_divison(
s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()),
w,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
// TODO: parallelize
// Let's open up C to every y.
fn compute_value<E: Engine>(y: &E::Fr, poly_positive: &[E::Fr], poly_negative: &[E::Fr]) -> E::Fr {
let mut value = E::Fr::zero();
let yinv = y.inverse().unwrap(); // TODO
let mut tmp = yinv;
for &coeff in poly_negative {
let mut coeff = coeff;
coeff.mul_assign(&tmp);
value.add_assign(&coeff);
tmp.mul_assign(&yinv);
}
let mut tmp = *y;
for &coeff in poly_positive {
let mut coeff = coeff;
coeff.mul_assign(&tmp);
value.add_assign(&coeff);
tmp.mul_assign(&y);
}
value
}
let mut c_openings = vec![];
for y in &y_values {
let value = compute_value::<E>(y, &s_poly_positive, &s_poly_negative);
let opening = {
let mut value = value;
value.negate();
let poly = kate_divison(
s_poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(s_poly_positive.iter()),
*y,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
c_openings.push((opening, value));
}
// Okay, great. Now we need to open up each S at the same point z to the same value.
// Since we're opening up all the S's at the same point, we create a bunch of random
// challenges instead and open up a random linear combination.
let mut poly_negative = vec![E::Fr::zero(); n];
let mut poly_positive = vec![E::Fr::zero(); 2*n];
let mut expected_value = E::Fr::zero();
for (y, c_opening) in y_values.iter().zip(c_openings.iter()) {
// Compute s(X, y_i)
let (s_poly_negative, s_poly_positive) = {
let mut tmp = SxEval::new(*y, n);
S::synthesize(&mut tmp, circuit).unwrap(); // TODO
tmp.poly()
};
let mut value = c_opening.1;
let r: E::Fr = transcript.get_challenge_scalar();
value.mul_assign(&r);
expected_value.add_assign(&value);
for (mut coeff, target) in s_poly_negative.into_iter().zip(poly_negative.iter_mut()) {
coeff.mul_assign(&r);
target.add_assign(&coeff);
}
for (mut coeff, target) in s_poly_positive.into_iter().zip(poly_positive.iter_mut()) {
coeff.mul_assign(&r);
target.add_assign(&coeff);
}
}
// TODO: parallelize
let s_opening = {
let mut value = expected_value;
value.negate();
let poly = kate_divison(
poly_negative.iter().rev().chain_ext(Some(value).iter()).chain_ext(poly_positive.iter()),
z,
);
let negative_poly = poly[0..n].iter().rev();
let positive_poly = poly[n..].iter();
multiexp(
srs.g_negative_x[1..(negative_poly.len() + 1)].iter().chain_ext(
srs.g_positive_x[0..positive_poly.len()].iter()
),
negative_poly.chain_ext(positive_poly)
).into_affine()
};
Aggregate {
// Commitment to s(z, Y)
c,
// We have to open each of the S commitments to a random point `z`
s_opening,
// We have to open C to each constituent `y`
c_openings,
// Then we have to finally open C
opening,
}
}

@ -0,0 +1,73 @@
extern crate tiny_keccak;
extern crate blake2_rfc;
use self::tiny_keccak::Keccak;
use self::blake2_rfc::blake2s::Blake2s;
pub trait Hasher {
fn new(personalization: &[u8]) -> Self;
fn update(&mut self, data: &[u8]);
fn finalize(&mut self) -> Vec<u8>;
}
#[derive(Clone)]
pub struct BlakeHasher {
h: Blake2s
}
impl Hasher for BlakeHasher {
fn new(personalization: &[u8]) -> Self {
let h = Blake2s::with_params(32, &[], &[], personalization);
Self {
h: h
}
}
fn update(&mut self, data: &[u8]) {
self.h.update(data);
}
fn finalize(&mut self) -> Vec<u8> {
use std::mem;
let new_h = Blake2s::with_params(32, &[], &[], &[]);
let h = std::mem::replace(&mut self.h, new_h);
let result = h.finalize();
result.as_ref().to_vec().clone()
}
}
#[derive(Clone)]
pub struct Keccak256Hasher {
h: Keccak
}
impl Hasher for Keccak256Hasher {
fn new(personalization: &[u8]) -> Self {
let mut h = Keccak::new_keccak256();
h.update(personalization);
Self {
h: h
}
}
fn update(&mut self, data: &[u8]) {
self.h.update(data);
}
fn finalize(&mut self) -> Vec<u8> {
use std::mem;
let new_h = Keccak::new_keccak256();
let h = std::mem::replace(&mut self.h, new_h);
let mut res: [u8; 32] = [0; 32];
h.finalize(&mut res);
res[..].to_vec()
}
}

@ -5,25 +5,77 @@ use ff::{Field, PrimeField, PrimeFieldRepr};
use pairing::{CurveAffine, CurveProjective, Engine};
use std::io;
// transcript is mocked for now
mod hasher;
use self::hasher::{Hasher, Keccak256Hasher, BlakeHasher};
#[derive(Clone)]
pub struct Transcript {
buffer: Vec<u8>
transcriptor: RollingHashTranscript<Keccak256Hasher>
}
impl Transcript {
pub fn new(personalization: &[u8]) -> Self {
Self {
buffer: vec![]
transcriptor: RollingHashTranscript::new(personalization)
}
}
}
impl TranscriptProtocol for Transcript {
fn commit_point<G: CurveAffine>(&mut self, point: &G) {
self.transcriptor.commit_point(point);
}
fn commit_scalar<F: PrimeField>(&mut self, scalar: &F) {
self.transcriptor.commit_scalar(scalar);
}
fn get_challenge_scalar<F: PrimeField>(&mut self) -> F {
self.transcriptor.get_challenge_scalar()
}
}
use std::marker::PhantomData;
#[derive(Clone)]
pub struct RollingHashTranscript<H: Hasher> {
buffer: Vec<u8>,
last_finalized_value: Vec<u8>,
_marker: PhantomData<H>
}
impl<H: Hasher> RollingHashTranscript<H> {
pub fn new(personalization: &[u8]) -> Self {
let mut h = H::new(personalization);
let buffer = h.finalize();
Self {
buffer: buffer,
last_finalized_value: vec![],
_marker: PhantomData
}
}
pub fn commit_bytes(&mut self, personalization: &[u8], bytes: &[u8]) {
let mut h = H::new(personalization);
h.update(&self.buffer);
h.update(personalization);
h.update(bytes);
self.buffer = h.finalize();
}
pub fn challenge_bytes(&mut self, personalization: &[u8], bytes: &[u8]) {
pub fn get_challenge_bytes(&mut self, nonce: &[u8]) -> Vec<u8> {
let challenge_bytes = &self.buffer;
let mut h = H::new(&[]);
h.update(challenge_bytes);
h.update(nonce);
let challenge_bytes = h.finalize();
challenge_bytes
}
}
@ -33,37 +85,48 @@ pub trait TranscriptProtocol {
fn get_challenge_scalar<F: PrimeField>(&mut self) -> F;
}
impl TranscriptProtocol for Transcript {
impl<H:Hasher> TranscriptProtocol for RollingHashTranscript<H> {
fn commit_point<G: CurveAffine>(&mut self, point: &G) {
self.commit_bytes(b"point", point.into_compressed().as_ref());
self.commit_bytes(b"point", point.into_uncompressed().as_ref());
// self.commit_bytes(b"point", point.into_compressed().as_ref());
}
fn commit_scalar<F: PrimeField>(&mut self, scalar: &F) {
let mut v = vec![];
scalar.into_repr().write_le(&mut v).unwrap();
scalar.into_repr().write_be(&mut v).unwrap();
// scalar.into_repr().write_le(&mut v).unwrap();
self.commit_bytes(b"scalar", &v);
}
fn get_challenge_scalar<F: PrimeField>(&mut self) -> F {
return F::one();
// loop {
// let mut repr: F::Repr = Default::default();
// repr.read_be(TranscriptReader(self)).unwrap();
use byteorder::ByteOrder;
// if let Ok(result) = F::from_repr(repr) {
// return result;
// }
// }
let mut nonce = 0u32;
loop {
let mut nonce_bytes = vec![0u8; 4];
byteorder::BigEndian::write_u32(&mut nonce_bytes, nonce);
let mut repr: F::Repr = Default::default();
let challenge_bytes = self.get_challenge_bytes(&nonce_bytes);
repr.read_be(&challenge_bytes[..]).unwrap();
if let Ok(result) = F::from_repr(repr) {
return result;
}
if nonce == (0xffffffff as u32) {
panic!("can not make challenge scalar");
}
nonce += 1;
}
}
}
struct TranscriptReader<'a>(&'a mut Transcript);
// struct TranscriptReader<'a, H:Hasher>(&'a mut Transcript<H>);
impl<'a> io::Read for TranscriptReader<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.challenge_bytes(b"read", buf);
// impl<'a, H:Hasher> io::Read for TranscriptReader<'a, H: Hasher> {
// fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
// self.0.challenge_bytes(b"read", buf);
Ok(buf.len())
}
}
// Ok(buf.len())
// }
// }