From 7239a60044354544b0c97dfca635227dc9436646 Mon Sep 17 00:00:00 2001 From: Alex Vlasov Date: Tue, 5 Feb 2019 17:23:26 +0300 Subject: [PATCH] make custom transcript that is implementable as SC --- Cargo.toml | 6 + src/sonic/helped/batch.rs | 36 ++++++ src/sonic/helped/helper.rs | 228 +++++++++++++++++++++++++++++++++ src/sonic/helped/mod.rs | 15 +-- src/sonic/helped/prover.rs | 211 ------------------------------ src/sonic/helped/verifier.rs | 214 +------------------------------ src/sonic/transcript/hasher.rs | 73 +++++++++++ src/sonic/transcript/mod.rs | 107 ++++++++++++---- 8 files changed, 434 insertions(+), 456 deletions(-) create mode 100644 src/sonic/helped/helper.rs create mode 100644 src/sonic/transcript/hasher.rs diff --git a/Cargo.toml b/Cargo.toml index 0a71a2d..5c62eac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 = [] diff --git a/src/sonic/helped/batch.rs b/src/sonic/helped/batch.rs index 81fe5f6..4ab4868 100644 --- a/src/sonic/helped/batch.rs +++ b/src/sonic/helped/batch.rs @@ -126,3 +126,39 @@ impl Batch { ])).unwrap() == E::Fqk::one() } } + + +pub struct VerificationKey { + alpha_x: E::G2Affine, + + alpha: E::G2Affine, + + neg_h: E::G2Affine, + + neg_x_n_minus_d: E::G2Affine + +} + +impl VerificationKey { + pub fn new(srs: &SRS, 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 + }, + } + } +} \ No newline at end of file diff --git a/src/sonic/helped/helper.rs b/src/sonic/helped/helper.rs new file mode 100644 index 0000000..44d695a --- /dev/null +++ b/src/sonic/helped/helper.rs @@ -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 { + // 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, S: SynthesisDriver>( + circuit: &C, + inputs: &[(Proof, SxyAdvice)], + srs: &SRS, +) -> Aggregate +{ + // TODO: precompute this? + let (n, q) = { + struct CountN { + n: usize, + q: usize + } + + impl<'a, E: Engine> Backend 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 = 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::(&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(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::(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, + } +} \ No newline at end of file diff --git a/src/sonic/helped/mod.rs b/src/sonic/helped/mod.rs index bf59409..51769f6 100644 --- a/src/sonic/helped/mod.rs +++ b/src/sonic/helped/mod.rs @@ -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 { diff --git a/src/sonic/helped/prover.rs b/src/sonic/helped/prover.rs index 8b13dd2..65a29fa 100644 --- a/src/sonic/helped/prover.rs +++ b/src/sonic/helped/prover.rs @@ -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 { - // 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, S: SynthesisDriver>( - circuit: &C, - inputs: &[(Proof, SxyAdvice)], - srs: &SRS, -) -> Aggregate -{ - // TODO: precompute this? - let (n, q) = { - struct CountN { - n: usize, - q: usize - } - - impl<'a, E: Engine> Backend 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 = 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::(&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(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::(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, S: SynthesisDriver>( circuit: &C, proof: &Proof, diff --git a/src/sonic/helped/verifier.rs b/src/sonic/helped/verifier.rs index 35e1ae4..1bed9a4 100644 --- a/src/sonic/helped/verifier.rs +++ b/src/sonic/helped/verifier.rs @@ -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, S: SynthesisDriver> MultiVerifier { pub fn check_all(self) -> bool { self.batch.check_all() } -} - -#[derive(Clone)] -pub struct Aggregate { - // 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, S: SynthesisDriver>( - circuit: &C, - inputs: &[(Proof, SxyAdvice)], - srs: &SRS, -) -> Aggregate -{ - // TODO: precompute this? - let (n, q) = { - struct CountN { - n: usize, - q: usize - } - - impl<'a, E: Engine> Backend 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 = 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::(&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(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::(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, - } } \ No newline at end of file diff --git a/src/sonic/transcript/hasher.rs b/src/sonic/transcript/hasher.rs new file mode 100644 index 0000000..7474d30 --- /dev/null +++ b/src/sonic/transcript/hasher.rs @@ -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; +} + +#[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 { + 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 { + 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() + } +} \ No newline at end of file diff --git a/src/sonic/transcript/mod.rs b/src/sonic/transcript/mod.rs index d3d4d07..bede612 100644 --- a/src/sonic/transcript/mod.rs +++ b/src/sonic/transcript/mod.rs @@ -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 + transcriptor: RollingHashTranscript } impl Transcript { pub fn new(personalization: &[u8]) -> Self { Self { - buffer: vec![] + transcriptor: RollingHashTranscript::new(personalization) + } + } +} + +impl TranscriptProtocol for Transcript { + fn commit_point(&mut self, point: &G) { + self.transcriptor.commit_point(point); + } + + fn commit_scalar(&mut self, scalar: &F) { + self.transcriptor.commit_scalar(scalar); + } + + fn get_challenge_scalar(&mut self) -> F { + self.transcriptor.get_challenge_scalar() + } +} + +use std::marker::PhantomData; + +#[derive(Clone)] +pub struct RollingHashTranscript { + buffer: Vec, + last_finalized_value: Vec, + _marker: PhantomData +} + +impl RollingHashTranscript { + 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 { + 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(&mut self) -> F; } -impl TranscriptProtocol for Transcript { +impl TranscriptProtocol for RollingHashTranscript { fn commit_point(&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(&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(&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); -impl<'a> io::Read for TranscriptReader<'a> { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - 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 { +// self.0.challenge_bytes(b"read", buf); - Ok(buf.len()) - } -} \ No newline at end of file +// Ok(buf.len()) +// } +// } \ No newline at end of file