use super::bullet::BulletReductionProof;
|
|
use super::commitments::{Commitments, MultiCommitGens};
|
|
use super::errors::ProofVerifyError;
|
|
use super::group::CompressedGroup;
|
|
use super::math::Math;
|
|
use super::scalar::Scalar;
|
|
use super::transcript::{AppendToTranscript, ProofTranscript};
|
|
use merlin::Transcript;
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct KnowledgeProof {
|
|
alpha: CompressedGroup,
|
|
z1: Scalar,
|
|
z2: Scalar,
|
|
}
|
|
|
|
impl KnowledgeProof {
|
|
fn protocol_name() -> &'static [u8] {
|
|
b"knowledge proof"
|
|
}
|
|
|
|
pub fn prove(
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
random_tape: &mut Transcript,
|
|
x: &Scalar,
|
|
r: &Scalar,
|
|
) -> (KnowledgeProof, CompressedGroup) {
|
|
transcript.append_protocol_name(KnowledgeProof::protocol_name());
|
|
|
|
// produce two random Scalars
|
|
let t1 = random_tape.challenge_scalar(b"t1");
|
|
let t2 = random_tape.challenge_scalar(b"t2");
|
|
|
|
let C = x.commit(&r, gens_n).compress();
|
|
C.append_to_transcript(b"C", transcript);
|
|
|
|
let alpha = t1.commit(&t2, gens_n).compress();
|
|
alpha.append_to_transcript(b"alpha", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let z1 = x * &c + &t1;
|
|
let z2 = r * &c + &t2;
|
|
|
|
(KnowledgeProof { alpha, z1, z2 }, C)
|
|
}
|
|
|
|
pub fn verify(
|
|
&self,
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
C: &CompressedGroup,
|
|
) -> Result<(), ProofVerifyError> {
|
|
transcript.append_protocol_name(KnowledgeProof::protocol_name());
|
|
C.append_to_transcript(b"C", transcript);
|
|
self.alpha.append_to_transcript(b"alpha", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let lhs = self.z1.commit(&self.z2, gens_n).compress();
|
|
let rhs = (&c * C.decompress().expect("Could not decompress C")
|
|
+ self
|
|
.alpha
|
|
.decompress()
|
|
.expect("Could not decompress self.alpha"))
|
|
.compress();
|
|
|
|
if lhs == rhs {
|
|
Ok(())
|
|
} else {
|
|
Err(ProofVerifyError)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct EqualityProof {
|
|
alpha: CompressedGroup,
|
|
z: Scalar,
|
|
}
|
|
|
|
impl EqualityProof {
|
|
fn protocol_name() -> &'static [u8] {
|
|
b"equality proof"
|
|
}
|
|
|
|
pub fn prove(
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
random_tape: &mut Transcript,
|
|
v1: &Scalar,
|
|
s1: &Scalar,
|
|
v2: &Scalar,
|
|
s2: &Scalar,
|
|
) -> (EqualityProof, CompressedGroup, CompressedGroup) {
|
|
transcript.append_protocol_name(EqualityProof::protocol_name());
|
|
|
|
// produce a random Scalar
|
|
let r = random_tape.challenge_scalar(b"r");
|
|
|
|
let C1 = v1.commit(&s1, gens_n).compress();
|
|
C1.append_to_transcript(b"C1", transcript);
|
|
|
|
let C2 = v2.commit(&s2, gens_n).compress();
|
|
C2.append_to_transcript(b"C2", transcript);
|
|
|
|
let alpha = (&r * gens_n.h).compress();
|
|
alpha.append_to_transcript(b"alpha", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let z = &c * (s1 - s2) + &r;
|
|
|
|
(EqualityProof { alpha, z }, C1, C2)
|
|
}
|
|
|
|
pub fn verify(
|
|
&self,
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
C1: &CompressedGroup,
|
|
C2: &CompressedGroup,
|
|
) -> Result<(), ProofVerifyError> {
|
|
transcript.append_protocol_name(EqualityProof::protocol_name());
|
|
C1.append_to_transcript(b"C1", transcript);
|
|
C2.append_to_transcript(b"C2", transcript);
|
|
self.alpha.append_to_transcript(b"alpha", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
let rhs = {
|
|
let C = &C1.decompress().unwrap() - &C2.decompress().unwrap();
|
|
(&c * C + &self.alpha.decompress().unwrap()).compress()
|
|
};
|
|
|
|
let lhs = (&self.z * gens_n.h).compress();
|
|
|
|
if lhs == rhs {
|
|
Ok(())
|
|
} else {
|
|
Err(ProofVerifyError)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Debug)]
|
|
pub struct ProductProof {
|
|
alpha: CompressedGroup,
|
|
beta: CompressedGroup,
|
|
delta: CompressedGroup,
|
|
z: [Scalar; 5],
|
|
}
|
|
|
|
impl ProductProof {
|
|
fn protocol_name() -> &'static [u8] {
|
|
b"product proof"
|
|
}
|
|
|
|
pub fn prove(
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
random_tape: &mut Transcript,
|
|
x: &Scalar,
|
|
rX: &Scalar,
|
|
y: &Scalar,
|
|
rY: &Scalar,
|
|
z: &Scalar,
|
|
rZ: &Scalar,
|
|
) -> (
|
|
ProductProof,
|
|
CompressedGroup,
|
|
CompressedGroup,
|
|
CompressedGroup,
|
|
) {
|
|
transcript.append_protocol_name(ProductProof::protocol_name());
|
|
|
|
// produce five random Scalar
|
|
let b1 = random_tape.challenge_scalar(b"b1");
|
|
let b2 = random_tape.challenge_scalar(b"b2");
|
|
let b3 = random_tape.challenge_scalar(b"b3");
|
|
let b4 = random_tape.challenge_scalar(b"b4");
|
|
let b5 = random_tape.challenge_scalar(b"b5");
|
|
|
|
let X = x.commit(&rX, gens_n).compress();
|
|
X.append_to_transcript(b"X", transcript);
|
|
|
|
let Y = y.commit(&rY, gens_n).compress();
|
|
Y.append_to_transcript(b"Y", transcript);
|
|
|
|
let Z = z.commit(&rZ, gens_n).compress();
|
|
Z.append_to_transcript(b"Z", transcript);
|
|
|
|
let alpha = b1.commit(&b2, gens_n).compress();
|
|
alpha.append_to_transcript(b"alpha", transcript);
|
|
|
|
let beta = b3.commit(&b4, gens_n).compress();
|
|
beta.append_to_transcript(b"beta", transcript);
|
|
|
|
let delta = {
|
|
let gens_X = &MultiCommitGens {
|
|
n: 1,
|
|
G: vec![X.decompress().unwrap()],
|
|
h: gens_n.h,
|
|
};
|
|
b3.commit(&b5, gens_X).compress()
|
|
};
|
|
delta.append_to_transcript(b"delta", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let z1 = &b1 + &c * x;
|
|
let z2 = &b2 + &c * rX;
|
|
let z3 = &b3 + &c * y;
|
|
let z4 = &b4 + &c * rY;
|
|
let z5 = &b5 + &c * (rZ - rX * y);
|
|
let z = [z1, z2, z3, z4, z5];
|
|
|
|
(
|
|
ProductProof {
|
|
alpha,
|
|
beta,
|
|
delta,
|
|
z,
|
|
},
|
|
X,
|
|
Y,
|
|
Z,
|
|
)
|
|
}
|
|
|
|
fn check_equality(
|
|
P: &CompressedGroup,
|
|
X: &CompressedGroup,
|
|
c: &Scalar,
|
|
gens_n: &MultiCommitGens,
|
|
z1: &Scalar,
|
|
z2: &Scalar,
|
|
) -> bool {
|
|
let lhs = (P.decompress().unwrap() + c * X.decompress().unwrap()).compress();
|
|
let rhs = z1.commit(&z2, gens_n).compress();
|
|
|
|
if lhs == rhs {
|
|
true
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
|
|
pub fn verify(
|
|
&self,
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
X: &CompressedGroup,
|
|
Y: &CompressedGroup,
|
|
Z: &CompressedGroup,
|
|
) -> Result<(), ProofVerifyError> {
|
|
transcript.append_protocol_name(ProductProof::protocol_name());
|
|
|
|
X.append_to_transcript(b"X", transcript);
|
|
Y.append_to_transcript(b"Y", transcript);
|
|
Z.append_to_transcript(b"Z", transcript);
|
|
self.alpha.append_to_transcript(b"alpha", transcript);
|
|
self.beta.append_to_transcript(b"beta", transcript);
|
|
self.delta.append_to_transcript(b"delta", transcript);
|
|
|
|
let z1 = self.z[0];
|
|
let z2 = self.z[1];
|
|
let z3 = self.z[2];
|
|
let z4 = self.z[3];
|
|
let z5 = self.z[4];
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
if ProductProof::check_equality(&self.alpha, &X, &c, &gens_n, &z1, &z2)
|
|
&& ProductProof::check_equality(&self.beta, &Y, &c, &gens_n, &z3, &z4)
|
|
&& ProductProof::check_equality(
|
|
&self.delta,
|
|
&Z,
|
|
&c,
|
|
&MultiCommitGens {
|
|
n: 1,
|
|
G: vec![X.decompress().unwrap()],
|
|
h: gens_n.h,
|
|
},
|
|
&z3,
|
|
&z5,
|
|
)
|
|
{
|
|
Ok(())
|
|
} else {
|
|
Err(ProofVerifyError)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct DotProductProof {
|
|
delta: CompressedGroup,
|
|
beta: CompressedGroup,
|
|
z: Vec<Scalar>,
|
|
z_delta: Scalar,
|
|
z_beta: Scalar,
|
|
}
|
|
|
|
impl DotProductProof {
|
|
fn protocol_name() -> &'static [u8] {
|
|
b"dot product proof"
|
|
}
|
|
|
|
pub fn compute_dotproduct(a: &Vec<Scalar>, b: &Vec<Scalar>) -> Scalar {
|
|
assert_eq!(a.len(), b.len());
|
|
(0..a.len()).map(|i| &a[i] * &b[i]).sum()
|
|
}
|
|
|
|
pub fn prove(
|
|
gens_1: &MultiCommitGens,
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
random_tape: &mut Transcript,
|
|
x: &Vec<Scalar>,
|
|
r_x: &Scalar,
|
|
a: &Vec<Scalar>,
|
|
y: &Scalar,
|
|
r_y: &Scalar,
|
|
) -> (DotProductProof, CompressedGroup, CompressedGroup) {
|
|
transcript.append_protocol_name(DotProductProof::protocol_name());
|
|
|
|
let n = x.len();
|
|
assert_eq!(x.len(), a.len());
|
|
assert_eq!(gens_n.n, a.len());
|
|
assert_eq!(gens_1.n, 1);
|
|
|
|
// produce randomness for the proofs
|
|
let d = random_tape.challenge_vector(b"d", n);
|
|
let r_delta = random_tape.challenge_scalar(b"r_delta");
|
|
let r_beta = random_tape.challenge_scalar(b"r_beta");
|
|
|
|
let Cx = x.commit(&r_x, gens_n).compress();
|
|
Cx.append_to_transcript(b"Cx", transcript);
|
|
|
|
let Cy = y.commit(&r_y, gens_1).compress();
|
|
Cy.append_to_transcript(b"Cy", transcript);
|
|
|
|
let delta = d.commit(&r_delta, gens_n).compress();
|
|
delta.append_to_transcript(b"delta", transcript);
|
|
|
|
let dotproduct_a_d = DotProductProof::compute_dotproduct(&a, &d);
|
|
|
|
let beta = dotproduct_a_d.commit(&r_beta, gens_1).compress();
|
|
beta.append_to_transcript(b"beta", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let z = (0..d.len())
|
|
.map(|i| c * x[i] + d[i])
|
|
.collect::<Vec<Scalar>>();
|
|
|
|
let z_delta = c * r_x + r_delta;
|
|
let z_beta = c * r_y + r_beta;
|
|
|
|
(
|
|
DotProductProof {
|
|
delta,
|
|
beta,
|
|
z,
|
|
z_delta,
|
|
z_beta,
|
|
},
|
|
Cx,
|
|
Cy,
|
|
)
|
|
}
|
|
|
|
pub fn verify(
|
|
&self,
|
|
gens_1: &MultiCommitGens,
|
|
gens_n: &MultiCommitGens,
|
|
transcript: &mut Transcript,
|
|
a: &Vec<Scalar>,
|
|
Cx: &CompressedGroup,
|
|
Cy: &CompressedGroup,
|
|
) -> Result<(), ProofVerifyError> {
|
|
assert_eq!(gens_n.n, a.len());
|
|
assert_eq!(gens_1.n, 1);
|
|
|
|
transcript.append_protocol_name(DotProductProof::protocol_name());
|
|
Cx.append_to_transcript(b"Cx", transcript);
|
|
Cy.append_to_transcript(b"Cy", transcript);
|
|
self.delta.append_to_transcript(b"delta", transcript);
|
|
self.beta.append_to_transcript(b"beta", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let mut result = &c * Cx.decompress().unwrap() + self.delta.decompress().unwrap()
|
|
== self.z.commit(&self.z_delta, gens_n);
|
|
|
|
let dotproduct_z_a = DotProductProof::compute_dotproduct(&self.z, &a);
|
|
result &= &c * Cy.decompress().unwrap() + self.beta.decompress().unwrap()
|
|
== dotproduct_z_a.commit(&self.z_beta, gens_1);
|
|
|
|
if result {
|
|
Ok(())
|
|
} else {
|
|
Err(ProofVerifyError)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct DotProductProofGens {
|
|
n: usize,
|
|
pub gens_n: MultiCommitGens,
|
|
pub gens_1: MultiCommitGens,
|
|
}
|
|
|
|
impl DotProductProofGens {
|
|
pub fn new(n: usize, label: &[u8]) -> Self {
|
|
let (gens_n, gens_1) = MultiCommitGens::new(n + 1, label).split_at_mut(n);
|
|
DotProductProofGens { n, gens_n, gens_1 }
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct DotProductProofLog {
|
|
bullet_reduction_proof: BulletReductionProof,
|
|
delta: CompressedGroup,
|
|
beta: CompressedGroup,
|
|
z1: Scalar,
|
|
z2: Scalar,
|
|
}
|
|
|
|
impl DotProductProofLog {
|
|
fn protocol_name() -> &'static [u8] {
|
|
b"dot product proof (log)"
|
|
}
|
|
|
|
pub fn compute_dotproduct(a: &Vec<Scalar>, b: &Vec<Scalar>) -> Scalar {
|
|
assert_eq!(a.len(), b.len());
|
|
(0..a.len()).map(|i| &a[i] * &b[i]).sum()
|
|
}
|
|
|
|
pub fn prove(
|
|
gens: &DotProductProofGens,
|
|
transcript: &mut Transcript,
|
|
random_tape: &mut Transcript,
|
|
x: &Vec<Scalar>,
|
|
r_x: &Scalar,
|
|
a: &Vec<Scalar>,
|
|
y: &Scalar,
|
|
r_y: &Scalar,
|
|
) -> (DotProductProofLog, CompressedGroup, CompressedGroup) {
|
|
transcript.append_protocol_name(DotProductProofLog::protocol_name());
|
|
|
|
let n = x.len();
|
|
assert_eq!(x.len(), a.len());
|
|
assert_eq!(gens.n, n);
|
|
|
|
// produce randomness for generating a proof
|
|
let d = random_tape.challenge_scalar(b"d");
|
|
let r_delta = random_tape.challenge_scalar(b"r_delta");
|
|
let r_beta = random_tape.challenge_scalar(b"r_delta");
|
|
let blinds_vec = {
|
|
let v1 = random_tape.challenge_vector(b"blinds_vec_1", 2 * n.log2());
|
|
let v2 = random_tape.challenge_vector(b"blinds_vec_2", 2 * n.log2());
|
|
(0..v1.len())
|
|
.map(|i| (v1[i], v2[i]))
|
|
.collect::<Vec<(Scalar, Scalar)>>()
|
|
};
|
|
|
|
let Cx = x.commit(&r_x, &gens.gens_n).compress();
|
|
Cx.append_to_transcript(b"Cx", transcript);
|
|
|
|
let Cy = y.commit(&r_y, &gens.gens_1).compress();
|
|
Cy.append_to_transcript(b"Cy", transcript);
|
|
|
|
let r_Gamma = r_x + r_y;
|
|
let (bullet_reduction_proof, _Gamma_hat, x_hat, a_hat, g_hat, rhat_Gamma) =
|
|
BulletReductionProof::prove(
|
|
transcript,
|
|
&gens.gens_1.G[0],
|
|
&gens.gens_n.G,
|
|
&gens.gens_n.h,
|
|
x,
|
|
a,
|
|
&r_Gamma,
|
|
&blinds_vec,
|
|
);
|
|
let y_hat = x_hat * a_hat;
|
|
|
|
let delta = {
|
|
let gens_hat = MultiCommitGens {
|
|
n: 1,
|
|
G: vec![g_hat],
|
|
h: gens.gens_1.h,
|
|
};
|
|
d.commit(&r_delta, &gens_hat).compress()
|
|
};
|
|
delta.append_to_transcript(b"delta", transcript);
|
|
|
|
let beta = d.commit(&r_beta, &gens.gens_1).compress();
|
|
beta.append_to_transcript(b"beta", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let z1 = d + c * y_hat;
|
|
let z2 = a_hat * (c * rhat_Gamma + r_beta) + r_delta;
|
|
|
|
(
|
|
DotProductProofLog {
|
|
bullet_reduction_proof,
|
|
delta,
|
|
beta,
|
|
z1,
|
|
z2,
|
|
},
|
|
Cx,
|
|
Cy,
|
|
)
|
|
}
|
|
|
|
pub fn verify(
|
|
&self,
|
|
n: usize,
|
|
gens: &DotProductProofGens,
|
|
transcript: &mut Transcript,
|
|
a: &Vec<Scalar>,
|
|
Cx: &CompressedGroup,
|
|
Cy: &CompressedGroup,
|
|
) -> Result<(), ProofVerifyError> {
|
|
assert_eq!(gens.n, n);
|
|
assert_eq!(a.len(), n);
|
|
|
|
transcript.append_protocol_name(DotProductProofLog::protocol_name());
|
|
Cx.append_to_transcript(b"Cx", transcript);
|
|
Cy.append_to_transcript(b"Cy", transcript);
|
|
|
|
let Gamma = Cx.decompress().unwrap() + Cy.decompress().unwrap();
|
|
|
|
let (g_hat, Gamma_hat, a_hat) = self
|
|
.bullet_reduction_proof
|
|
.verify(n, a, transcript, &Gamma, &gens.gens_n.G)
|
|
.unwrap();
|
|
|
|
self.delta.append_to_transcript(b"delta", transcript);
|
|
self.beta.append_to_transcript(b"beta", transcript);
|
|
|
|
let c = transcript.challenge_scalar(b"c");
|
|
|
|
let c_s = &c;
|
|
let beta_s = self.beta.decompress().unwrap();
|
|
let a_hat_s = &a_hat;
|
|
let delta_s = self.delta.decompress().unwrap();
|
|
let z1_s = &self.z1;
|
|
let z2_s = &self.z2;
|
|
|
|
let lhs = ((Gamma_hat * c_s + beta_s) * a_hat_s + delta_s).compress();
|
|
let rhs = ((g_hat + &gens.gens_1.G[0] * a_hat_s) * z1_s + gens.gens_1.h * z2_s).compress();
|
|
|
|
assert_eq!(lhs, rhs);
|
|
|
|
if lhs == rhs {
|
|
Ok(())
|
|
} else {
|
|
Err(ProofVerifyError)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use rand::rngs::OsRng;
|
|
#[test]
|
|
fn check_knowledgeproof() {
|
|
let mut csprng: OsRng = OsRng;
|
|
|
|
let gens_1 = MultiCommitGens::new(1, b"test-knowledgeproof");
|
|
|
|
let x = Scalar::random(&mut csprng);
|
|
let r = Scalar::random(&mut csprng);
|
|
|
|
let mut random_tape = {
|
|
let mut csprng: OsRng = OsRng;
|
|
let mut tape = Transcript::new(b"proof");
|
|
tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
|
|
tape
|
|
};
|
|
let mut prover_transcript = Transcript::new(b"example");
|
|
let (proof, committed_value) =
|
|
KnowledgeProof::prove(&gens_1, &mut prover_transcript, &mut random_tape, &x, &r);
|
|
|
|
let mut verifier_transcript = Transcript::new(b"example");
|
|
assert!(proof
|
|
.verify(&gens_1, &mut verifier_transcript, &committed_value)
|
|
.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn check_equalityproof() {
|
|
let mut csprng: OsRng = OsRng;
|
|
|
|
let gens_1 = MultiCommitGens::new(1, b"test-equalityproof");
|
|
let v1 = Scalar::random(&mut csprng);
|
|
let v2 = v1;
|
|
let s1 = Scalar::random(&mut csprng);
|
|
let s2 = Scalar::random(&mut csprng);
|
|
|
|
let mut random_tape = {
|
|
let mut csprng: OsRng = OsRng;
|
|
let mut tape = Transcript::new(b"proof");
|
|
tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
|
|
tape
|
|
};
|
|
let mut prover_transcript = Transcript::new(b"example");
|
|
let (proof, C1, C2) = EqualityProof::prove(
|
|
&gens_1,
|
|
&mut prover_transcript,
|
|
&mut random_tape,
|
|
&v1,
|
|
&s1,
|
|
&v2,
|
|
&s2,
|
|
);
|
|
|
|
let mut verifier_transcript = Transcript::new(b"example");
|
|
assert!(proof
|
|
.verify(&gens_1, &mut verifier_transcript, &C1, &C2)
|
|
.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn check_productproof() {
|
|
let mut csprng: OsRng = OsRng;
|
|
|
|
let gens_1 = MultiCommitGens::new(1, b"test-productproof");
|
|
let x = Scalar::random(&mut csprng);
|
|
let rX = Scalar::random(&mut csprng);
|
|
let y = Scalar::random(&mut csprng);
|
|
let rY = Scalar::random(&mut csprng);
|
|
let z = x * y;
|
|
let rZ = Scalar::random(&mut csprng);
|
|
|
|
let mut random_tape = {
|
|
let mut csprng: OsRng = OsRng;
|
|
let mut tape = Transcript::new(b"proof");
|
|
tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
|
|
tape
|
|
};
|
|
let mut prover_transcript = Transcript::new(b"example");
|
|
let (proof, X, Y, Z) = ProductProof::prove(
|
|
&gens_1,
|
|
&mut prover_transcript,
|
|
&mut random_tape,
|
|
&x,
|
|
&rX,
|
|
&y,
|
|
&rY,
|
|
&z,
|
|
&rZ,
|
|
);
|
|
|
|
let mut verifier_transcript = Transcript::new(b"example");
|
|
assert!(proof
|
|
.verify(&gens_1, &mut verifier_transcript, &X, &Y, &Z)
|
|
.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn check_dotproductproof() {
|
|
let mut csprng: OsRng = OsRng;
|
|
|
|
let n = 1024;
|
|
|
|
let gens_1 = MultiCommitGens::new(1, b"test-two");
|
|
let gens_1024 = MultiCommitGens::new(n, b"test-1024");
|
|
|
|
let mut x: Vec<Scalar> = Vec::new();
|
|
let mut a: Vec<Scalar> = Vec::new();
|
|
for _ in 0..n {
|
|
x.push(Scalar::random(&mut csprng));
|
|
a.push(Scalar::random(&mut csprng));
|
|
}
|
|
let y = DotProductProofLog::compute_dotproduct(&x, &a);
|
|
let r_x = Scalar::random(&mut csprng);
|
|
let r_y = Scalar::random(&mut csprng);
|
|
|
|
let mut random_tape = {
|
|
let mut csprng: OsRng = OsRng;
|
|
let mut tape = Transcript::new(b"proof");
|
|
tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
|
|
tape
|
|
};
|
|
let mut prover_transcript = Transcript::new(b"example");
|
|
let (proof, Cx, Cy) = DotProductProof::prove(
|
|
&gens_1,
|
|
&gens_1024,
|
|
&mut prover_transcript,
|
|
&mut random_tape,
|
|
&x,
|
|
&r_x,
|
|
&a,
|
|
&y,
|
|
&r_y,
|
|
);
|
|
|
|
let mut verifier_transcript = Transcript::new(b"example");
|
|
assert!(proof
|
|
.verify(&gens_1, &gens_1024, &mut verifier_transcript, &a, &Cx, &Cy)
|
|
.is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn check_dotproductproof_log() {
|
|
let mut csprng: OsRng = OsRng;
|
|
|
|
let n = 1024;
|
|
|
|
let gens = DotProductProofGens::new(n, b"test-1024");
|
|
|
|
let x: Vec<Scalar> = (0..n).map(|_i| Scalar::random(&mut csprng)).collect();
|
|
let a: Vec<Scalar> = (0..n).map(|_i| Scalar::random(&mut csprng)).collect();
|
|
let y = DotProductProof::compute_dotproduct(&x, &a);
|
|
|
|
let r_x = Scalar::random(&mut csprng);
|
|
let r_y = Scalar::random(&mut csprng);
|
|
|
|
let mut random_tape = {
|
|
let mut csprng: OsRng = OsRng;
|
|
let mut tape = Transcript::new(b"proof");
|
|
tape.append_scalar(b"init_randomness", &Scalar::random(&mut csprng));
|
|
tape
|
|
};
|
|
let mut prover_transcript = Transcript::new(b"example");
|
|
let (proof, Cx, Cy) = DotProductProofLog::prove(
|
|
&gens,
|
|
&mut prover_transcript,
|
|
&mut random_tape,
|
|
&x,
|
|
&r_x,
|
|
&a,
|
|
&y,
|
|
&r_y,
|
|
);
|
|
|
|
let mut verifier_transcript = Transcript::new(b"example");
|
|
assert!(proof
|
|
.verify(n, &gens, &mut verifier_transcript, &a, &Cx, &Cy)
|
|
.is_ok());
|
|
}
|
|
}
|