nizk: optimize range proofs

This commit is contained in:
Gijs Van Laer 2019-08-30 15:55:59 -04:00
parent 2e57633c84
commit 6c2a7147ae
2 changed files with 61 additions and 32 deletions

View File

@ -74,8 +74,8 @@ pub struct ProofUL<E: Engine> {
pub struct RangeProofState<E: Engine> {
pub com1: Commitment<E>,
pub ps1: ProofULState<E>,
pub com2: Commitment<E>,
pub ps2: ProofULState<E>,
pub com2: Option<Commitment<E>>,
pub ps2: Option<ProofULState<E>>,
}
/**
@ -94,7 +94,7 @@ RangeProof contains the necessary elements for the ZK range proof.
))]
pub struct RangeProof<E: Engine> {
pub p1: ProofUL<E>,
pub p2: ProofUL<E>,
pub p2: Option<ProofUL<E>>,
}
/**
@ -184,7 +184,7 @@ impl<E: Engine> ParamsUL<E> {
let mut g = self.csParams.pub_bases[i].clone();
let s1: E::Fr;
if sVec.len() >= i {
s1 = sVec[i-1];
s1 = sVec[i - 1];
} else {
s1 = E::Fr::rand(rng);
}
@ -355,9 +355,14 @@ impl<E: Engine> RPPublicParams<E> {
let mut a = Vec::<E::Fqk>::with_capacity(self.p.l as usize);
for i in 0..rpState.ps1.proofStates.len() {
a.push(rpState.ps1.proofStates[i].a);
a.push(rpState.ps2.proofStates[i].a);
if rpState.ps2.is_some() {
a.push(rpState.ps2.clone().unwrap().proofStates[i].a);
}
}
let ch = hash::<E>(a, vec!(rpState.ps1.D.clone(), rpState.ps2.D.clone()));
let ch = match rpState.ps2.is_some() {
true => hash::<E>(a, vec!(rpState.ps1.D.clone(), rpState.ps2.clone().unwrap().D)),
false => hash::<E>(a, vec!(rpState.ps1.D.clone()))
};
self.prove_response(r, &rpState, ch, k, otherM)
}
@ -380,20 +385,29 @@ impl<E: Engine> RPPublicParams<E> {
comXB.c.add_assign(&gul);
let firstState = self.p.prove_ul_commitment(rng, xb, k, sOptional.clone(), mOptional.clone());
// x - a
let xa = x - self.a;
let mut ga = self.p.csParams.pub_bases[k].clone();
let mut a = E::Fr::from_str(&(self.a.to_string())).unwrap();
a.negate();
ga.mul_assign(a.into_repr());
let mut comXA = C.clone();
comXA.c.add_assign(&ga);
let secondState = self.p.prove_ul_commitment(rng, xa, k, sOptional.clone(), mOptional.clone());
RangeProofState { com1: comXB, ps1: firstState, com2: comXA, ps2: secondState }
let mut comXAOption = None;
let mut secondState = None;
if self.a != 0 || x < 0 {
let xa = x - self.a;
let mut ga = self.p.csParams.pub_bases[k].clone();
let mut a = E::Fr::from_str(&(self.a.to_string())).unwrap();
a.negate();
ga.mul_assign(a.into_repr());
let mut comXA = C.clone();
comXA.c.add_assign(&ga);
comXAOption = Some(comXA);
secondState = Some(self.p.prove_ul_commitment(rng, xa, k, sOptional.clone(), mOptional.clone()));
}
RangeProofState { com1: comXB, ps1: firstState, com2: comXAOption, ps2: secondState }
}
pub fn prove_response(&self, r: E::Fr, rpState: &RangeProofState<E>, ch: E::Fr, k: usize, otherM: Vec<E::Fr>) -> RangeProof<E> {
let first = self.p.prove_ul_response(r.clone(), rpState.com1.clone(), &rpState.ps1, ch.clone(), k, otherM.clone());
let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone(), k, otherM.clone());
let mut second = None;
if rpState.com2.is_some() && rpState.ps2.is_some() {
second = Some(self.p.prove_ul_response(r.clone(), rpState.com2.clone().unwrap(), &rpState.ps2.clone().unwrap(), ch.clone(), k, otherM.clone()));
}
RangeProof { p1: first, p2: second }
}
@ -402,17 +416,26 @@ impl<E: Engine> RPPublicParams<E> {
*/
pub fn verify(&self, proof: RangeProof<E>, ch: E::Fr, k: usize) -> bool {
let first = self.p.verify_ul(&proof.p1, ch.clone(), k);
let second = self.p.verify_ul(&proof.p2, ch.clone(), k);
first & &second
let mut second = true;
if proof.p2.is_some() {
second = self.p.verify_ul(&proof.p2.unwrap(), ch.clone(), k);
}
first && second
}
pub fn compute_challenge(&self, proof: &RangeProof<E>) -> E::Fr {
let mut a = Vec::<E::Fqk>::with_capacity(self.p.l as usize);
for i in 0..proof.p1.sigProofs.len() {
a.push(proof.p1.sigProofs[i].a);
a.push(proof.p2.sigProofs[i].a);
if proof.p2.is_some() {
a.push(proof.p2.clone().unwrap().sigProofs[i].a);
}
}
match proof.p2.is_some() {
true => hash::<E>(a.clone(), vec!(proof.p1.D.clone(), proof.p2.clone().unwrap().D)),
false => hash::<E>(a, vec!(proof.p1.D.clone()))
}
hash::<E>(a, vec!(proof.p1.D.clone(), proof.p2.D.clone()))
}
}
@ -447,7 +470,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
let proof = params.prove_ul(rng, 10, fr, C, 1, vec! {});
assert_eq!(proof.V.len(), 4);
assert_eq!(proof.sigProofs.len(), 4);
}
@ -461,7 +484,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(100.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
params.prove_ul(rng, 100, fr, C, 1, vec!{});
params.prove_ul(rng, 100, fr, C, 1, vec! {});
}
#[test]
@ -472,7 +495,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
let proof = params.prove_ul(rng, 10, fr, C, 1, vec! {});
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify_part1(&proof, ch, 1), true);
}
@ -485,7 +508,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
let proof = params.prove_ul(rng, 10, fr, C, 1, vec! {});
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify_part2(&proof, ch), true);
}
@ -498,7 +521,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
let proof = params.prove_ul(rng, 10, fr, C, 1, vec! {});
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify_ul(&proof, ch, 1), true);
}
@ -513,7 +536,7 @@ mod tests {
let fr1 = Fr::rand(rng);
let fr2 = Fr::rand(rng);
let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone());
let proof = params.prove_ul(rng, 10, fr, C, 2, vec!{fr1, fr2});
let proof = params.prove_ul(rng, 10, fr, C, 2, vec! {fr1, fr2});
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify_ul(&proof, ch, 2), true);
}
@ -526,7 +549,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(10.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove(rng, 10, C, fr, 1, vec!{});
let proof = params.prove(rng, 10, C, fr, 1, vec! {});
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify(proof, ch, 1), true);
@ -542,7 +565,7 @@ mod tests {
let fr1 = Fr::rand(rng);
let fr2 = Fr::rand(rng);
let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone());
let proof = params.prove(rng, 10, C, fr, 2, vec!{fr1, fr2});
let proof = params.prove(rng, 10, C, fr, 2, vec! {fr1, fr2});
let ch = params.compute_challenge(&proof);
assert_eq!(params.verify(proof, ch, 2), true);
@ -557,7 +580,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(26.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
params.prove(rng, 26, C, fr, 1, vec!{});
params.prove(rng, 26, C, fr, 1, vec! {});
}
#[test]
@ -585,7 +608,7 @@ mod tests {
let fr = Fr::rand(rng);
let modx = Fr::from_str(&(x.to_string())).unwrap();
let C = csParams.commit(&vec!(modx), &fr.clone());
let proof = params.prove(rng, x, C, fr, 1, vec!{});
let proof = params.prove(rng, x, C, fr, 1, vec! {});
averageProve = averageProve.add(sProve.to(PreciseTime::now()));
averageProofSize += mem::size_of_val(&proof);

View File

@ -100,7 +100,10 @@ impl<E: Engine> NIZKPublicParams<E> {
let rpStateBM = self.rpParamsBM.prove_commitment(rng, newWallet.bm.clone(), newWalletCom.clone(), 4, None, None);
//Compute challenge
let challenge = NIZKPublicParams::<E>::hash(proofState.a, vec! {D, rpStateBC.ps1.D, rpStateBC.ps2.D, rpStateBM.ps1.D, rpStateBM.ps2.D});
let challenge = match rpStateBC.ps2.is_some() && rpStateBM.ps2.is_some() {
true => NIZKPublicParams::<E>::hash(proofState.a, vec! {D, rpStateBC.ps1.D, rpStateBC.ps2.clone().unwrap().D, rpStateBM.ps1.D, rpStateBM.ps2.clone().unwrap().D}),
false => NIZKPublicParams::<E>::hash(proofState.a, vec! {D, rpStateBC.ps1.D, rpStateBM.ps1.D})
};
//Response phase
//response for signature
@ -141,7 +144,10 @@ impl<E: Engine> NIZKPublicParams<E> {
let r0 = proof.sig.h != E::G1::one();
//compute challenge
let challenge = NIZKPublicParams::<E>::hash(proof.sigProof.a, vec! {proof.comProof.T, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D});
let challenge = match proof.rpBC.p2.is_some() && proof.rpBM.p2.is_some() {
true => NIZKPublicParams::<E>::hash(proof.sigProof.a.clone(), vec! {proof.comProof.T, proof.rpBC.p1.D, proof.rpBC.p2.clone().unwrap().D, proof.rpBM.p1.D, proof.rpBM.p2.clone().unwrap().D}),
false => NIZKPublicParams::<E>::hash(proof.sigProof.a.clone(), vec! {proof.comProof.T, proof.rpBC.p1.D, proof.rpBM.p1.D})
};
//verify knowledge of signature
let mut r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof.clone(), challenge);