nizk: extract proof of knowledge of a commitment
This commit is contained in:
parent
c947a446ea
commit
cc921e5786
|
@ -14,14 +14,14 @@ use pairing::{Engine, CurveProjective};
|
|||
use pairing::bls12_381::{Bls12};
|
||||
use ff::PrimeField;
|
||||
use cl::{BlindKeyPair, KeyPair, Signature, PublicParams, setup};
|
||||
use ped92::{CSParams, Commitment, CSMultiParams};
|
||||
use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof};
|
||||
use util::{hash_pubkey_to_fr, convert_int_to_fr, hash_to_fr, RevokedMessage, hash_to_slice};
|
||||
use rand::Rng;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use std::ptr::hash;
|
||||
use nizk::{NIZKPublicParams, CommitmentProof, Proof};
|
||||
use nizk::{NIZKPublicParams, NIZKProof};
|
||||
use wallet::Wallet;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
@ -330,7 +330,7 @@ impl<E: Engine> CustomerState<E> {
|
|||
}
|
||||
|
||||
// for channel pay
|
||||
pub fn generate_payment<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, amount: i32) -> (Proof<E>, Commitment<E>, secp256k1::PublicKey, CustomerState<E>) {
|
||||
pub fn generate_payment<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, amount: i32) -> (NIZKProof<E>, Commitment<E>, secp256k1::PublicKey, CustomerState<E>) {
|
||||
// 1 - chooose new wpk/wsk pair
|
||||
let mut kp = secp256k1::Secp256k1::new();
|
||||
kp.randomize(csprng);
|
||||
|
@ -557,7 +557,7 @@ impl<E: Engine> MerchantState<E> {
|
|||
return self.pay_tokens.get(&wpk_str).unwrap().clone();
|
||||
}
|
||||
|
||||
pub fn verify_payment<R: Rng>(&mut self, csprng: &mut R, channel: &ChannelState<E>, proof: &Proof<E>, com: &Commitment<E>, wpk: &secp256k1::PublicKey, amount: i32) -> ResultBoltSig<Signature<E>> {
|
||||
pub fn verify_payment<R: Rng>(&mut self, csprng: &mut R, channel: &ChannelState<E>, proof: &NIZKProof<E>, com: &Commitment<E>, wpk: &secp256k1::PublicKey, amount: i32) -> ResultBoltSig<Signature<E>> {
|
||||
let cp = channel.cp.as_ref().unwrap();
|
||||
let pay_proof = proof.clone();
|
||||
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
||||
|
|
|
@ -130,9 +130,10 @@ pub mod bidirectional {
|
|||
pub use BoltResult;
|
||||
pub use channels::{ChannelState, ChannelToken, CustomerState, MerchantState, ChannelcloseM,
|
||||
PubKeyMap, ChannelParams, BoltError, ResultBoltSig};
|
||||
pub use nizk::{CommitmentProof, Proof};
|
||||
pub use nizk::NIZKProof;
|
||||
pub use wallet::Wallet;
|
||||
pub use cl::PublicParams;
|
||||
pub use ped92::CommitmentProof;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||
|
@ -157,7 +158,7 @@ pub mod bidirectional {
|
|||
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
||||
))]
|
||||
pub struct Payment<E: Engine> {
|
||||
proof: Proof<E>,
|
||||
proof: NIZKProof<E>,
|
||||
com: Commitment<E>,
|
||||
wpk: secp256k1::PublicKey,
|
||||
amount: i32,
|
||||
|
|
185
src/nizk.rs
185
src/nizk.rs
|
@ -4,14 +4,16 @@ extern crate rand;
|
|||
use super::*;
|
||||
use rand::Rng;
|
||||
use cl::{KeyPair, Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey};
|
||||
use ped92::{CSParams, Commitment, CSMultiParams};
|
||||
use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use ff::PrimeField;
|
||||
use wallet::Wallet;
|
||||
use ccs08::{RPPublicParams, RangeProof};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use util;
|
||||
use std::borrow::BorrowMut;
|
||||
|
||||
/// NIZKProof is the object that represents the NIZK Proof of Knowledge during the payment and closing protocol
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||
<E as pairing::Engine>::G1: serde::Serialize, \
|
||||
|
@ -23,15 +25,15 @@ use util;
|
|||
<E as pairing::Engine>::G2: serde::Deserialize<'de>, \
|
||||
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
||||
))]
|
||||
pub struct Proof<E: Engine> {
|
||||
pub struct NIZKProof<E: Engine> {
|
||||
pub sig: Signature<E>,
|
||||
pub sigProof: SignatureProof<E>,
|
||||
pub D: E::G1,
|
||||
pub z: Vec<E::Fr>,
|
||||
pub comProof: CommitmentProof<E>,
|
||||
pub rpBC: RangeProof<E>,
|
||||
pub rpBM: RangeProof<E>,
|
||||
}
|
||||
|
||||
/// NIZKPublicParams are public parameters to perform a NIZK Proof of Knowledge during the payment and closing protocol
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||
<E as pairing::Engine>::G1: serde::Serialize, \
|
||||
|
@ -50,6 +52,8 @@ pub struct NIZKPublicParams<E: Engine> {
|
|||
}
|
||||
|
||||
impl<E: Engine> NIZKPublicParams<E> {
|
||||
/// Basic setup for the NIZKPublicParams
|
||||
/// Takes as input a random generator and the length of the message which should be 4 during payment protocol and 5 for the closing protocol
|
||||
pub fn setup<R: Rng>(rng: &mut R, messageLength: usize) -> Self {
|
||||
let mpk = setup(rng);
|
||||
let keypair = BlindKeyPair::<E>::generate(rng, &mpk, messageLength);
|
||||
|
@ -57,14 +61,25 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||
let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||
|
||||
NIZKPublicParams{mpk, keypair, comParams, rpParamsBC, rpParamsBM}
|
||||
NIZKPublicParams { mpk, keypair, comParams, rpParamsBC, rpParamsBM }
|
||||
}
|
||||
|
||||
/** This method can be called to create the proof during the payment and closing protocol
|
||||
Input:
|
||||
rng: random generator
|
||||
r: randomness of commitment of old wallet (TODO: still necessary?)
|
||||
oldWallet: This is the wallet before payment occurs
|
||||
newWallet: This is the new state of the wallet after payment
|
||||
newWalletCom: A commitment of the new wallet
|
||||
rPrime: randomness of commitment of new wallet
|
||||
paymentToken: A blind signature on the old wallet
|
||||
Output:
|
||||
NIZKProof: a proof that can be verified by the merchant during payment or closing protocol
|
||||
*/
|
||||
pub fn prove<R: Rng>(&self, rng: &mut R, r: E::Fr, oldWallet: Wallet<E>, newWallet: Wallet<E>,
|
||||
newWalletCom: Commitment<E>, rPrime: E::Fr, paymentToken: &Signature<E>) -> Proof<E> {
|
||||
newWalletCom: Commitment<E>, rPrime: E::Fr, paymentToken: &Signature<E>) -> NIZKProof<E> {
|
||||
//Commitment phase
|
||||
//commit commitment
|
||||
let mut D = E::G1::zero();
|
||||
let w_len = newWallet.as_fr_vec().len();
|
||||
let diff = self.comParams.pub_bases.len() - w_len;
|
||||
let max = match diff > 1 {
|
||||
|
@ -72,14 +87,7 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
false => self.comParams.pub_bases.len()
|
||||
};
|
||||
|
||||
let mut t = Vec::<E::Fr>::with_capacity(max );
|
||||
for i in 0 .. max {
|
||||
let ti = E::Fr::rand(rng);
|
||||
t.push(ti);
|
||||
let mut gt = self.comParams.pub_bases[i].clone();
|
||||
gt.mul_assign(ti.into_repr());
|
||||
D.add_assign(>);
|
||||
}
|
||||
let (D, t, rt, mut reveal_wallet) = CommitmentProof::<E>::prove_commitment(rng, &self.comParams, &newWallet.as_fr_vec(), &vec! {});
|
||||
|
||||
//commit signature
|
||||
let zero = E::Fr::zero();
|
||||
|
@ -102,18 +110,8 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
|
||||
|
||||
//response commitment
|
||||
let mut z = Vec::<E::Fr>::with_capacity(t.len());
|
||||
let mut z0 = rPrime.clone();
|
||||
z0.mul_assign(&challenge);
|
||||
z0.add_assign(&t[0]);
|
||||
z.push(z0);
|
||||
let newWalletVec = newWallet.as_fr_vec();
|
||||
for i in 1..t.len() {
|
||||
let mut zi = newWalletVec[i - 1].clone();
|
||||
zi.mul_assign(&challenge);
|
||||
zi.add_assign(&t[i]);
|
||||
z.push(zi);
|
||||
}
|
||||
let comProof = CommitmentProof::<E>::prove_response(&newWalletVec, &rPrime, &vec! {}, D, &t, rt, reveal_wallet.borrow_mut(), &challenge);
|
||||
|
||||
//response range proof
|
||||
let mut vec01 = newWalletVec[0..2].to_vec();
|
||||
|
@ -121,7 +119,7 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
let mut vec3 = newWalletVec[3..].to_vec();
|
||||
vecWithout2.append(&mut vec3);
|
||||
let vec2 = newWalletVec[2].clone();
|
||||
vec01.push( vec2);
|
||||
vec01.push(vec2);
|
||||
if newWalletVec.len() > 4 {
|
||||
let mut vec4 = newWalletVec[4..].to_vec();
|
||||
vec01.append(&mut vec4);
|
||||
|
@ -129,15 +127,23 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
let rpBC = self.rpParamsBC.prove_response(rPrime.clone(), &rpStateBC, challenge.clone(), 3, vecWithout2.to_vec());
|
||||
let rpBM = self.rpParamsBM.prove_response(rPrime.clone(), &rpStateBM, challenge.clone(), 4, vec01.to_vec());
|
||||
|
||||
Proof { sig: proofState.blindSig, sigProof, D, z, rpBC, rpBM }
|
||||
NIZKProof { sig: proofState.blindSig, sigProof, comProof, rpBC, rpBM }
|
||||
}
|
||||
|
||||
pub fn verify(&self, proof: Proof<E>, epsilon: E::Fr, com2: &Commitment<E>, wpk: E::Fr) -> bool {
|
||||
/**
|
||||
Verify a NIZK Proof of Knowledge during payment or closing protocl
|
||||
Input:
|
||||
proof: A NIZK proof created by the Customer
|
||||
epsilon: The transaction amount of the payment
|
||||
com: Commitment of the new wallet that needs to be signed
|
||||
wpk: reveal of wallet public key of the old wallet.
|
||||
*/
|
||||
pub fn verify(&self, proof: NIZKProof<E>, epsilon: E::Fr, com: &Commitment<E>, wpk: E::Fr) -> bool {
|
||||
//verify signature is not the identity
|
||||
let r0 = proof.sig.h != E::G1::one();
|
||||
|
||||
//compute challenge
|
||||
let challenge = NIZKPublicParams::<E>::hash(proof.sigProof.a, vec! {proof.D, proof.rpBC.p1.D, proof.rpBC.p2.D, proof.rpBM.p1.D, proof.rpBM.p2.D});
|
||||
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});
|
||||
|
||||
//verify knowledge of signature
|
||||
let mut r1 = self.keypair.public.verify_proof(&self.mpk, proof.sig, proof.sigProof.clone(), challenge);
|
||||
|
@ -146,31 +152,22 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
r1 = r1 && proof.sigProof.zsig[1] == wpkc;
|
||||
|
||||
//verify knowledge of commitment
|
||||
let mut comc = com2.c.clone();
|
||||
comc.mul_assign(challenge.into_repr());
|
||||
comc.add_assign(&proof.D.clone());
|
||||
let mut x = E::G1::zero();
|
||||
for i in 0..proof.z.len() {
|
||||
let mut base = self.comParams.pub_bases[i].clone();
|
||||
base.mul_assign(proof.z[i].into_repr());
|
||||
x.add_assign(&base);
|
||||
}
|
||||
let r2 = x == comc;
|
||||
let r2 = proof.comProof.verify_proof(&self.comParams, &com.c.clone(), &challenge);
|
||||
|
||||
//verify range proofs
|
||||
let r3 = self.rpParamsBC.verify(proof.rpBC.clone(), challenge.clone(), 3);
|
||||
let r4 = self.rpParamsBM.verify(proof.rpBM.clone(), challenge.clone(), 4);
|
||||
|
||||
//verify linear relationship
|
||||
let mut r5 = proof.z[1] == proof.sigProof.zsig[0];
|
||||
let mut r5 = proof.comProof.z[1] == proof.sigProof.zsig[0];
|
||||
let mut zsig2 = proof.sigProof.zsig[2].clone();
|
||||
let mut epsC = epsilon.clone();
|
||||
epsC.mul_assign(&challenge.clone());
|
||||
zsig2.sub_assign(&epsC.clone());
|
||||
r5 = r5 && proof.z[3] == zsig2;
|
||||
r5 = r5 && proof.comProof.z[3] == zsig2;
|
||||
let mut zsig3 = proof.sigProof.zsig[3].clone();
|
||||
zsig3.add_assign(&epsC.clone());
|
||||
r5 = r5 && proof.z[4] == zsig3;
|
||||
r5 = r5 && proof.comProof.z[4] == zsig3;
|
||||
|
||||
r0 && r1 && r2 && r3 && r4 && r5
|
||||
}
|
||||
|
@ -186,104 +183,17 @@ impl<E: Engine> NIZKPublicParams<E> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||
<E as pairing::Engine>::G1: serde::Serialize, \
|
||||
<E as pairing::Engine>::G2: serde::Serialize"
|
||||
))]
|
||||
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
||||
<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
|
||||
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
||||
))]
|
||||
pub struct CommitmentProof<E: Engine> {
|
||||
pub T: E::G1,
|
||||
pub z: Vec<E::Fr>,
|
||||
pub t: Vec<E::Fr>,
|
||||
pub index: Vec<usize>,
|
||||
pub reveal: Vec<E::Fr>
|
||||
}
|
||||
|
||||
impl<E: Engine> CommitmentProof<E> {
|
||||
pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>) -> Self {
|
||||
let mut Tvals = E::G1::zero();
|
||||
assert!(wallet.len() <= com_params.pub_bases.len());
|
||||
|
||||
let mut t = Vec::<E::Fr>::with_capacity( wallet.len()+1 );
|
||||
let mut rt: Vec<E::Fr> = Vec::new(); // t values that will be revealed
|
||||
let mut reveal_wallet: Vec<E::Fr> = Vec::new(); // aspects of wallet being revealed
|
||||
|
||||
for i in 0..wallet.len()+1 {
|
||||
let ti = E::Fr::rand(csprng);
|
||||
t.push(ti);
|
||||
// check if we are revealing this index
|
||||
if (reveal_index.contains(&i)) {
|
||||
rt.push(ti);
|
||||
} else {
|
||||
rt.push( E::Fr::zero());
|
||||
}
|
||||
let mut gt = com_params.pub_bases[i].clone();
|
||||
gt.mul_assign(ti.into_repr());
|
||||
Tvals.add_assign(>);
|
||||
}
|
||||
|
||||
// compute the challenge
|
||||
let x: Vec<E::G1> = vec![Tvals, com.clone()];
|
||||
let challenge = util::hash_g1_to_fr::<E>(&x);
|
||||
|
||||
// compute the response
|
||||
let mut z: Vec<E::Fr> = Vec::new();
|
||||
let mut z0 = r.clone();
|
||||
z0.mul_assign(&challenge);
|
||||
z0.add_assign(&t[0]);
|
||||
z.push(z0);
|
||||
reveal_wallet.push( E::Fr::zero());
|
||||
|
||||
for i in 1..t.len() {
|
||||
let mut zi = wallet[i-1].clone();
|
||||
zi.mul_assign(&challenge);
|
||||
zi.add_assign(&t[i]);
|
||||
z.push(zi);
|
||||
// check if we are revealing this index
|
||||
if (reveal_index.contains(&i)) {
|
||||
reveal_wallet.push(wallet[i-1].clone() );
|
||||
} else {
|
||||
reveal_wallet.push( E::Fr::zero());
|
||||
}
|
||||
}
|
||||
|
||||
CommitmentProof {
|
||||
T: Tvals, // commitment challenge
|
||||
z: z, // response values
|
||||
t: rt, // randomness for verifying partial reveals
|
||||
index: reveal_index.clone(),
|
||||
reveal: reveal_wallet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Verify PoK for the opening of a commitment
|
||||
/// Verify PoK for the opening of a commitment during the establishment protocol
|
||||
///
|
||||
pub fn verify_opening<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, proof: &CommitmentProof<E>, init_cust: i32, init_merch: i32) -> bool {
|
||||
|
||||
let mut comc = com.clone();
|
||||
let T = proof.T.clone();
|
||||
|
||||
let xvec: Vec<E::G1> = vec![T, comc];
|
||||
let xvec: Vec<E::G1> = vec![proof.T.clone(), com.clone()];
|
||||
let challenge = util::hash_g1_to_fr::<E>(&xvec);
|
||||
|
||||
// compute the
|
||||
comc.mul_assign(challenge.into_repr());
|
||||
comc.add_assign(&T);
|
||||
let com_equal = proof.verify_proof(com_params, com, &challenge);
|
||||
|
||||
let mut x = E::G1::zero();
|
||||
for i in 0..proof.z.len() {
|
||||
let mut base = com_params.pub_bases[i].clone();
|
||||
base.mul_assign(proof.z[i].into_repr());
|
||||
x.add_assign(&base);
|
||||
}
|
||||
|
||||
if (proof.index.len() == 0) {
|
||||
if proof.index.len() == 0 {
|
||||
println!("verify_opening - doing any partial reveals?");
|
||||
return false;
|
||||
}
|
||||
|
@ -309,7 +219,7 @@ pub fn verify_opening<E: Engine>(com_params: &CSMultiParams<E>, com: &E::G1, pro
|
|||
let init_m = util::convert_int_to_fr::<E>(init_merch);
|
||||
let bm_equal = (s4 == proof.z[4]) && (proof.reveal[4] == init_m);
|
||||
|
||||
return comc == x && pkc_equal && bc_equal && bm_equal;
|
||||
return com_equal && pkc_equal && bc_equal && bm_equal;
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,7 +254,7 @@ mod tests {
|
|||
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
||||
|
||||
let proof = pubParams.prove(rng, r, wallet1, wallet2,
|
||||
commitment2.clone(), rprime, &paymentToken);
|
||||
commitment2.clone(), rprime, &paymentToken);
|
||||
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
||||
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
|
||||
}
|
||||
|
@ -499,7 +409,7 @@ mod tests {
|
|||
let com2 = pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t);
|
||||
|
||||
let com1_proof = CommitmentProof::<Bls12>::new(rng, &pubParams.comParams,
|
||||
&com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]);
|
||||
&com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]);
|
||||
|
||||
assert!(verify_opening(&pubParams.comParams, &com1.c, &com1_proof, bc, bm));
|
||||
assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof, bc2, bm));
|
||||
|
@ -524,5 +434,4 @@ mod tests {
|
|||
|
||||
// deserialize
|
||||
}
|
||||
|
||||
}
|
||||
|
|
101
src/ped92.rs
101
src/ped92.rs
|
@ -1,10 +1,12 @@
|
|||
// ped92.rs
|
||||
use rand::{thread_rng, Rng};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use ff::Rand;
|
||||
use ff::{Rand, Field, PrimeField};
|
||||
use std::fmt;
|
||||
use util::is_vec_g1_equal;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use util;
|
||||
use std::borrow::BorrowMut;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct CSParams<E: Engine> {
|
||||
|
@ -173,6 +175,103 @@ impl<E: Engine> CSMultiParams<E> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize, Debug)]
|
||||
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
||||
<E as pairing::Engine>::G1: serde::Serialize, \
|
||||
<E as pairing::Engine>::G2: serde::Serialize"
|
||||
))]
|
||||
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
||||
<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
|
||||
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
||||
))]
|
||||
pub struct CommitmentProof<E: Engine> {
|
||||
pub T: E::G1,
|
||||
pub z: Vec<E::Fr>,
|
||||
pub t: Vec<E::Fr>,
|
||||
pub index: Vec<usize>,
|
||||
pub reveal: Vec<E::Fr>
|
||||
}
|
||||
|
||||
impl<E: Engine> CommitmentProof<E> {
|
||||
pub fn new<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, com: &E::G1, wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>) -> Self {
|
||||
let (Tvals, t, rt, mut reveal_wallet) = CommitmentProof::<E>::prove_commitment::<R>(csprng, com_params, wallet, reveal_index);
|
||||
|
||||
// compute the challenge
|
||||
let x: Vec<E::G1> = vec![Tvals, com.clone()];
|
||||
let challenge = util::hash_g1_to_fr::<E>(&x);
|
||||
|
||||
// compute the response
|
||||
CommitmentProof::<E>::prove_response(wallet, r, reveal_index, Tvals, &t, rt, reveal_wallet.borrow_mut(), &challenge)
|
||||
}
|
||||
|
||||
pub fn prove_commitment<R: Rng>(csprng: &mut R, com_params: &CSMultiParams<E>, wallet: &Vec<E::Fr>, reveal_index: &Vec<usize>) -> (E::G1, Vec<E::Fr>, Vec<E::Fr>, Vec<E::Fr>) {
|
||||
let mut Tvals = E::G1::zero();
|
||||
assert!(wallet.len() <= com_params.pub_bases.len());
|
||||
let mut t = Vec::<E::Fr>::with_capacity(wallet.len() + 1);
|
||||
let mut rt: Vec<E::Fr> = Vec::new();
|
||||
// t values that will be revealed
|
||||
let mut reveal_wallet: Vec<E::Fr> = Vec::new();
|
||||
// aspects of wallet being revealed
|
||||
for i in 0..wallet.len() + 1 {
|
||||
let ti = E::Fr::rand(csprng);
|
||||
t.push(ti);
|
||||
// check if we are revealing this index
|
||||
if reveal_index.contains(&i) {
|
||||
rt.push(ti);
|
||||
} else {
|
||||
rt.push(E::Fr::zero());
|
||||
}
|
||||
let mut gt = com_params.pub_bases[i].clone();
|
||||
gt.mul_assign(ti.into_repr());
|
||||
Tvals.add_assign(>);
|
||||
}
|
||||
(Tvals, t, rt, reveal_wallet)
|
||||
}
|
||||
|
||||
pub fn prove_response(wallet: &Vec<E::Fr>, r: &E::Fr, reveal_index: &Vec<usize>, Tvals: E::G1, t: &Vec<E::Fr>, rt: Vec<E::Fr>, reveal_wallet: &mut Vec<E::Fr>, challenge: &E::Fr) -> CommitmentProof<E> {
|
||||
let mut z: Vec<E::Fr> = Vec::new();
|
||||
let mut z0 = r.clone();
|
||||
z0.mul_assign(&challenge);
|
||||
z0.add_assign(&t[0]);
|
||||
z.push(z0);
|
||||
reveal_wallet.push(E::Fr::zero());
|
||||
for i in 1..t.len() {
|
||||
let mut zi = wallet[i - 1].clone();
|
||||
zi.mul_assign(&challenge);
|
||||
zi.add_assign(&t[i]);
|
||||
z.push(zi);
|
||||
// check if we are revealing this index
|
||||
if reveal_index.contains(&i) {
|
||||
reveal_wallet.push(wallet[i - 1].clone());
|
||||
} else {
|
||||
reveal_wallet.push(E::Fr::zero());
|
||||
}
|
||||
}
|
||||
|
||||
CommitmentProof {
|
||||
T: Tvals, // commitment challenge
|
||||
z: z, // response values
|
||||
t: rt, // randomness for verifying partial reveals
|
||||
index: reveal_index.clone(),
|
||||
reveal: reveal_wallet.clone()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify_proof(&self, com_params: &CSMultiParams<E>, com: &<E as Engine>::G1, challenge: &E::Fr) -> bool {
|
||||
let mut comc = com.clone();
|
||||
let T = self.T.clone();
|
||||
comc.mul_assign(challenge.into_repr());
|
||||
comc.add_assign(&T);
|
||||
let mut x = E::G1::zero();
|
||||
for i in 0..self.z.len() {
|
||||
let mut base = com_params.pub_bases[i].clone();
|
||||
base.mul_assign(self.z[i].into_repr());
|
||||
x.add_assign(&base);
|
||||
}
|
||||
comc == x
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
Loading…
Reference in New Issue