nizk: split secret and public params
This commit is contained in:
parent
cb7791a447
commit
8a52a76ce4
|
@ -50,16 +50,12 @@ fn main() {
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
channel_state.setup(&mut rng); // or load_setup params
|
|
||||||
|
|
||||||
let b0_customer = 150;
|
let b0_customer = 150;
|
||||||
let b0_merchant = 10;
|
let b0_merchant = 10;
|
||||||
let pay_inc = 20;
|
let pay_inc = 20;
|
||||||
let pay_inc2 = 10;
|
let pay_inc2 = 10;
|
||||||
|
|
||||||
let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
|
||||||
// initialize the balance for merch_state
|
|
||||||
merch_state.init_balance(b0_merchant);
|
|
||||||
|
|
||||||
let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice");
|
let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice");
|
||||||
|
|
||||||
|
|
304
src/ccs08.rs
304
src/ccs08.rs
|
@ -9,7 +9,7 @@ extern crate rand;
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use super::*;
|
use super::*;
|
||||||
use cl::{Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof};
|
use cl::{Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey};
|
||||||
use ped92::{Commitment, CSMultiParams};
|
use ped92::{Commitment, CSMultiParams};
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
|
@ -26,7 +26,7 @@ struct ParamsUL<E: Engine> {
|
||||||
pub mpk: PublicParams<E>,
|
pub mpk: PublicParams<E>,
|
||||||
pub signatures: HashMap<String, Signature<E>>,
|
pub signatures: HashMap<String, Signature<E>>,
|
||||||
pub csParams: CSMultiParams<E>,
|
pub csParams: CSMultiParams<E>,
|
||||||
kp: BlindKeyPair<E>,
|
pk: BlindPublicKey<E>,
|
||||||
// u determines the amount of signatures we need in the public params.
|
// u determines the amount of signatures we need in the public params.
|
||||||
// Each signature can be compressed to just 1 field element of 256 bits.
|
// Each signature can be compressed to just 1 field element of 256 bits.
|
||||||
// Then the parameters have minimum size equal to 256*u bits.
|
// Then the parameters have minimum size equal to 256*u bits.
|
||||||
|
@ -37,6 +37,18 @@ struct ParamsUL<E: Engine> {
|
||||||
l: i32,
|
l: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
paramsUL contains elements generated by the verifier, which are necessary for the prover.
|
||||||
|
This must be computed in a trusted setup.
|
||||||
|
*/
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
#[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>"))]
|
||||||
|
struct SecretParamsUL<E: Engine> {
|
||||||
|
pub pubParams: ParamsUL<E>,
|
||||||
|
kp: BlindKeyPair<E>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ProofULState<E: Engine> {
|
pub struct ProofULState<E: Engine> {
|
||||||
pub decx: Vec<i32>,
|
pub decx: Vec<i32>,
|
||||||
|
@ -110,7 +122,19 @@ pub struct RPPublicParams<E: Engine> {
|
||||||
b: i32,
|
b: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> ParamsUL<E> {
|
/**
|
||||||
|
params contains elements generated by the verifier, which are necessary for the prover.
|
||||||
|
This must be computed in a trusted setup.
|
||||||
|
*/
|
||||||
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
#[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 RPSecretParams<E: Engine> {
|
||||||
|
pub pubParams: RPPublicParams<E>,
|
||||||
|
p: SecretParamsUL<E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> SecretParamsUL<E> {
|
||||||
/**
|
/**
|
||||||
setup_ul generates the signature for the interval [0,u^l).
|
setup_ul generates the signature for the interval [0,u^l).
|
||||||
The value of u should be roughly b/log(b), but we can choose smaller values in
|
The value of u should be roughly b/log(b), but we can choose smaller values in
|
||||||
|
@ -125,10 +149,74 @@ impl<E: Engine> ParamsUL<E> {
|
||||||
let sig_i = kp.sign(rng, &vec! {E::Fr::from_str(i.to_string().as_str()).unwrap()});
|
let sig_i = kp.sign(rng, &vec! {E::Fr::from_str(i.to_string().as_str()).unwrap()});
|
||||||
signatures.insert(i.to_string(), sig_i);
|
signatures.insert(i.to_string(), sig_i);
|
||||||
}
|
}
|
||||||
|
let pubParams = ParamsUL { mpk, signatures, csParams, pk: kp.public.clone(), u, l };
|
||||||
|
|
||||||
return ParamsUL { mpk, signatures, csParams, kp, u, l };
|
SecretParamsUL{pubParams, kp}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid.
|
||||||
|
*/
|
||||||
|
pub fn verify_ul(&self, proof: &ProofUL<E>, ch: E::Fr, k: usize) -> bool {
|
||||||
|
let r1 = self.verify_part1(&proof, ch.clone(), k);
|
||||||
|
let r2 = self.verify_part2(&proof, ch.clone());
|
||||||
|
r1 && r2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compute_challenge(&self, proof: &ProofUL<E>) -> E::Fr {
|
||||||
|
let mut a = Vec::<E::Fqk>::with_capacity(self.pubParams.l as usize);
|
||||||
|
for sigProof in proof.sigProofs.clone() {
|
||||||
|
a.push(sigProof.a);
|
||||||
|
}
|
||||||
|
hash::<E>(a, vec!(proof.D.clone()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_part2(&self, proof: &ProofUL<E>, challenge: E::Fr) -> bool {
|
||||||
|
let mut r2 = true;
|
||||||
|
for i in 0..self.pubParams.l as usize {
|
||||||
|
let subResult = self.kp.public.verify_proof(&self.pubParams.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), challenge);
|
||||||
|
|
||||||
|
r2 = r2 && subResult;
|
||||||
|
}
|
||||||
|
r2
|
||||||
|
}
|
||||||
|
|
||||||
|
fn verify_part1(&self, proof: &ProofUL<E>, challenge: E::Fr, k: usize) -> bool {
|
||||||
|
let mut D = proof.comm.c.clone();
|
||||||
|
D.mul_assign(challenge);
|
||||||
|
D.negate();
|
||||||
|
let mut hzr = self.pubParams.csParams.pub_bases[0].clone();
|
||||||
|
hzr.mul_assign(proof.zr);
|
||||||
|
D.add_assign(&hzr);
|
||||||
|
for i in 0..self.pubParams.l as usize {
|
||||||
|
let ui = self.pubParams.u.pow(i as u32);
|
||||||
|
let mut aux = self.pubParams.csParams.pub_bases[k].clone();
|
||||||
|
for j in 0..self.kp.public.Y1.len() {
|
||||||
|
let mut muizsigi = proof.sigProofs[i].zsig[j];
|
||||||
|
muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
|
||||||
|
aux.mul_assign(muizsigi);
|
||||||
|
}
|
||||||
|
D.add_assign(&aux);
|
||||||
|
}
|
||||||
|
for i in 1..self.pubParams.csParams.pub_bases.len() {
|
||||||
|
let j: usize;
|
||||||
|
if i < k {
|
||||||
|
j = i - 1;
|
||||||
|
} else if i > k {
|
||||||
|
j = i - 2;
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let mut g = self.pubParams.csParams.pub_bases[i].clone();
|
||||||
|
g.mul_assign(proof.zs[j].into_repr());
|
||||||
|
D.add_assign(&g);
|
||||||
|
}
|
||||||
|
D == proof.D
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> ParamsUL<E> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L).
|
prove_ul method is used to produce the ZKRP proof that secret x belongs to the interval [0,U^L).
|
||||||
*/
|
*/
|
||||||
|
@ -163,14 +251,14 @@ impl<E: Engine> ParamsUL<E> {
|
||||||
hm.mul_assign(m);
|
hm.mul_assign(m);
|
||||||
for i in 0..self.l as usize {
|
for i in 0..self.l as usize {
|
||||||
let signature = self.signatures.get(&decx[i].to_string()).unwrap();
|
let signature = self.signatures.get(&decx[i].to_string()).unwrap();
|
||||||
let proofState = self.kp.prove_commitment(rng, &self.mpk, &signature, None, None);
|
let proofState = self.pk.prove_commitment(rng, &self.mpk, &signature, None, None);
|
||||||
|
|
||||||
V.push(proofState.blindSig.clone());
|
V.push(proofState.blindSig.clone());
|
||||||
proofStates.push(proofState);
|
proofStates.push(proofState);
|
||||||
|
|
||||||
let ui = self.u.pow(i as u32);
|
let ui = self.u.pow(i as u32);
|
||||||
let mut aux = self.csParams.pub_bases[k].clone();
|
let mut aux = self.csParams.pub_bases[k].clone();
|
||||||
for j in 0..self.kp.public.Y1.len() {
|
for j in 0..self.pk.Y1.len() {
|
||||||
let mut muiti = proofStates[i].t[j].clone();
|
let mut muiti = proofStates[i].t[j].clone();
|
||||||
muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
|
muiti.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
|
||||||
aux.mul_assign(muiti);
|
aux.mul_assign(muiti);
|
||||||
|
@ -207,7 +295,7 @@ impl<E: Engine> ParamsUL<E> {
|
||||||
for i in 0..self.l as usize {
|
for i in 0..self.l as usize {
|
||||||
let dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap();
|
let dx = E::Fr::from_str(&proofUlState.decx[i].to_string()).unwrap();
|
||||||
|
|
||||||
let proof = self.kp.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx});
|
let proof = self.pk.prove_response(&proofUlState.proofStates[i].clone(), c, &mut vec! {dx});
|
||||||
|
|
||||||
sigProofs.push(proof);
|
sigProofs.push(proof);
|
||||||
}
|
}
|
||||||
|
@ -230,66 +318,6 @@ impl<E: Engine> ParamsUL<E> {
|
||||||
}
|
}
|
||||||
ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr, zs }
|
ProofUL { V: proofUlState.V.clone(), D: proofUlState.D.clone(), comm: C, sigProofs, zr, zs }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
verify_ul is used to validate the ZKRP proof. It returns true iff the proof is valid.
|
|
||||||
*/
|
|
||||||
pub fn verify_ul(&self, proof: &ProofUL<E>, ch: E::Fr, k: usize) -> bool {
|
|
||||||
let r1 = self.verify_part1(&proof, ch.clone(), k);
|
|
||||||
let r2 = self.verify_part2(&proof, ch.clone());
|
|
||||||
r1 && r2
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compute_challenge(&self, proof: &ProofUL<E>) -> E::Fr {
|
|
||||||
let mut a = Vec::<E::Fqk>::with_capacity(self.l as usize);
|
|
||||||
for sigProof in proof.sigProofs.clone() {
|
|
||||||
a.push(sigProof.a);
|
|
||||||
}
|
|
||||||
hash::<E>(a, vec!(proof.D.clone()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify_part2(&self, proof: &ProofUL<E>, challenge: E::Fr) -> bool {
|
|
||||||
let mut r2 = true;
|
|
||||||
for i in 0..self.l as usize {
|
|
||||||
let subResult = self.kp.public.verify_proof(&self.mpk, proof.V[i].clone(), proof.sigProofs[i].clone(), challenge);
|
|
||||||
|
|
||||||
r2 = r2 && subResult;
|
|
||||||
}
|
|
||||||
r2
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify_part1(&self, proof: &ProofUL<E>, challenge: E::Fr, k: usize) -> bool {
|
|
||||||
let mut D = proof.comm.c.clone();
|
|
||||||
D.mul_assign(challenge);
|
|
||||||
D.negate();
|
|
||||||
let mut hzr = self.csParams.pub_bases[0].clone();
|
|
||||||
hzr.mul_assign(proof.zr);
|
|
||||||
D.add_assign(&hzr);
|
|
||||||
for i in 0..self.l as usize {
|
|
||||||
let ui = self.u.pow(i as u32);
|
|
||||||
let mut aux = self.csParams.pub_bases[k].clone();
|
|
||||||
for j in 0..self.kp.public.Y1.len() {
|
|
||||||
let mut muizsigi = proof.sigProofs[i].zsig[j];
|
|
||||||
muizsigi.mul_assign(&E::Fr::from_str(&ui.to_string()).unwrap());
|
|
||||||
aux.mul_assign(muizsigi);
|
|
||||||
}
|
|
||||||
D.add_assign(&aux);
|
|
||||||
}
|
|
||||||
for i in 1..self.csParams.pub_bases.len() {
|
|
||||||
let j: usize;
|
|
||||||
if i < k {
|
|
||||||
j = i - 1;
|
|
||||||
} else if i > k {
|
|
||||||
j = i - 2;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let mut g = self.csParams.pub_bases[i].clone();
|
|
||||||
g.mul_assign(proof.zs[j].into_repr());
|
|
||||||
D.add_assign(&g);
|
|
||||||
}
|
|
||||||
D == proof.D
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash<E: Engine>(a: Vec<E::Fqk>, D: Vec<E::G1>) -> E::Fr {
|
fn hash<E: Engine>(a: Vec<E::Fqk>, D: Vec<E::G1>) -> E::Fr {
|
||||||
|
@ -322,7 +350,7 @@ fn decompose(x: i32, u: i32, l: i32) -> Vec<i32> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> RPPublicParams<E> {
|
impl<E: Engine> RPSecretParams<E> {
|
||||||
/**
|
/**
|
||||||
Setup receives integers a and b, and configures the parameters for the rangeproof scheme.
|
Setup receives integers a and b, and configures the parameters for the rangeproof scheme.
|
||||||
*/
|
*/
|
||||||
|
@ -339,13 +367,34 @@ impl<E: Engine> RPPublicParams<E> {
|
||||||
u = 57; //TODO: optimize u?
|
u = 57; //TODO: optimize u?
|
||||||
let l = (b as f32).log(u as f32).ceil() as i32;
|
let l = (b as f32).log(u as f32).ceil() as i32;
|
||||||
|
|
||||||
let params_out: ParamsUL<E> = ParamsUL::<E>::setup_ul(rng, u, l, csParams.clone());
|
let secParamsOut = SecretParamsUL::<E>::setup_ul(rng, u, l, csParams.clone());
|
||||||
return RPPublicParams { p: params_out, a, b };
|
let pubParams = RPPublicParams { p: secParamsOut.pubParams.clone(), a, b };
|
||||||
|
RPSecretParams{pubParams, p: secParamsOut}
|
||||||
} else {
|
} else {
|
||||||
panic!("log(log(b)) is zero");
|
panic!("log(log(b)) is zero");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify is responsible for validating the range proof.
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn compute_challenge(&self, proof: &RangeProof<E>) -> E::Fr {
|
||||||
|
let mut a = Vec::<E::Fqk>::with_capacity(self.p.pubParams.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);
|
||||||
|
}
|
||||||
|
hash::<E>(a, vec!(proof.p1.D.clone(), proof.p2.D.clone()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> RPPublicParams<E> {
|
||||||
/**
|
/**
|
||||||
Prove method is responsible for generating the zero knowledge range proof.
|
Prove method is responsible for generating the zero knowledge range proof.
|
||||||
*/
|
*/
|
||||||
|
@ -396,24 +445,6 @@ impl<E: Engine> RPPublicParams<E> {
|
||||||
let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone(), k, otherM.clone());
|
let second = self.p.prove_ul_response(r.clone(), rpState.com2.clone(), &rpState.ps2, ch.clone(), k, otherM.clone());
|
||||||
RangeProof { p1: first, p2: second }
|
RangeProof { p1: first, p2: second }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Verify is responsible for validating the range proof.
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
hash::<E>(a, vec!(proof.p1.D.clone(), proof.p2.D.clone()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -431,10 +462,10 @@ mod tests {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
|
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
|
||||||
assert_eq!(params.signatures.len(), 2);
|
assert_eq!(secParams.pubParams.signatures.len(), 2);
|
||||||
for (m, s) in params.signatures {
|
for (m, s) in secParams.pubParams.signatures {
|
||||||
assert_eq!(params.kp.verify(¶ms.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
|
assert_eq!(secParams.kp.public.verify_blind(&secParams.pubParams.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,11 +474,11 @@ mod tests {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
|
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
|
let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{});
|
||||||
assert_eq!(proof.V.len(), 4);
|
assert_eq!(proof.V.len(), 4);
|
||||||
assert_eq!(proof.sigProofs.len(), 4);
|
assert_eq!(proof.sigProofs.len(), 4);
|
||||||
}
|
}
|
||||||
|
@ -457,95 +488,95 @@ mod tests {
|
||||||
fn prove_ul_not_in_range() {
|
fn prove_ul_not_in_range() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 3, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(100.to_string())).unwrap();
|
let modx = Fr::from_str(&(100.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
params.prove_ul(rng, 100, fr, C, 1, vec!{});
|
secParams.pubParams.prove_ul(rng, 100, fr, C, 1, vec!{});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prove_and_verify_part1_ul_works() {
|
fn prove_and_verify_part1_ul_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
|
let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{});
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
assert_eq!(params.verify_part1(&proof, ch, 1), true);
|
assert_eq!(secParams.verify_part1(&proof, ch, 1), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prove_and_verify_part2_ul_works() {
|
fn prove_and_verify_part2_ul_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
|
let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{});
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
assert_eq!(params.verify_part2(&proof, ch), true);
|
assert_eq!(secParams.verify_part2(&proof, ch), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prove_and_verify_ul_works() {
|
fn prove_and_verify_ul_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
let proof = params.prove_ul(rng, 10, fr, C, 1, vec!{});
|
let proof = secParams.pubParams.prove_ul(rng, 10, fr, C, 1, vec!{});
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
assert_eq!(params.verify_ul(&proof, ch, 1), true);
|
assert_eq!(secParams.verify_ul(&proof, ch, 1), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prove_and_verify_ul_bigger_commit_works() {
|
fn prove_and_verify_ul_bigger_commit_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 3);
|
let csParams = CSMultiParams::setup_gen_params(rng, 3);
|
||||||
let params = ParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
let secParams = SecretParamsUL::<Bls12>::setup_ul(rng, 2, 4, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let fr1 = Fr::rand(rng);
|
let fr1 = Fr::rand(rng);
|
||||||
let fr2 = Fr::rand(rng);
|
let fr2 = Fr::rand(rng);
|
||||||
let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone());
|
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 = secParams.pubParams.prove_ul(rng, 10, fr, C, 2, vec!{fr1, fr2});
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
assert_eq!(params.verify_ul(&proof, ch, 2), true);
|
assert_eq!(secParams.verify_ul(&proof, ch, 2), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prove_and_verify_works() {
|
fn prove_and_verify_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
|
let secParams = RPSecretParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
let proof = params.prove(rng, 10, C, fr, 1, vec!{});
|
let proof = secParams.pubParams.prove(rng, 10, C, fr, 1, vec!{});
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
|
|
||||||
assert_eq!(params.verify(proof, ch, 1), true);
|
assert_eq!(secParams.verify(proof, ch, 1), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn prove_and_verify_bigger_commit_works() {
|
fn prove_and_verify_bigger_commit_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 3);
|
let csParams = CSMultiParams::setup_gen_params(rng, 3);
|
||||||
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
|
let secParams = RPSecretParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
let modx = Fr::from_str(&(10.to_string())).unwrap();
|
||||||
let fr1 = Fr::rand(rng);
|
let fr1 = Fr::rand(rng);
|
||||||
let fr2 = Fr::rand(rng);
|
let fr2 = Fr::rand(rng);
|
||||||
let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone());
|
let C = csParams.commit(&vec!(fr1, modx, fr2), &fr.clone());
|
||||||
let proof = params.prove(rng, 10, C, fr, 2, vec!{fr1, fr2});
|
let proof = secParams.pubParams.prove(rng, 10, C, fr, 2, vec!{fr1, fr2});
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
|
|
||||||
assert_eq!(params.verify(proof, ch, 2), true);
|
assert_eq!(secParams.verify(proof, ch, 2), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -553,11 +584,11 @@ mod tests {
|
||||||
fn prove_not_in_range() {
|
fn prove_not_in_range() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = RPPublicParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
|
let secParams = RPSecretParams::<Bls12>::setup(rng, 2, 25, csParams.clone());
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(26.to_string())).unwrap();
|
let modx = Fr::from_str(&(26.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
params.prove(rng, 26, C, fr, 1, vec!{});
|
secParams.pubParams.prove(rng, 26, C, fr, 1, vec!{});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -577,21 +608,21 @@ mod tests {
|
||||||
|
|
||||||
let sSetup = PreciseTime::now();
|
let sSetup = PreciseTime::now();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let params = RPPublicParams::<Bls12>::setup(rng, a, b, csParams.clone());
|
let secParams = RPSecretParams::<Bls12>::setup(rng, a, b, csParams.clone());
|
||||||
averageSetup = averageSetup.add(sSetup.to(PreciseTime::now()));
|
averageSetup = averageSetup.add(sSetup.to(PreciseTime::now()));
|
||||||
averageSetupSize += mem::size_of_val(¶ms);
|
averageSetupSize += mem::size_of_val(&secParams.pubParams);
|
||||||
|
|
||||||
let sProve = PreciseTime::now();
|
let sProve = PreciseTime::now();
|
||||||
let fr = Fr::rand(rng);
|
let fr = Fr::rand(rng);
|
||||||
let modx = Fr::from_str(&(x.to_string())).unwrap();
|
let modx = Fr::from_str(&(x.to_string())).unwrap();
|
||||||
let C = csParams.commit(&vec!(modx), &fr.clone());
|
let C = csParams.commit(&vec!(modx), &fr.clone());
|
||||||
let proof = params.prove(rng, x, C, fr, 1, vec!{});
|
let proof = secParams.pubParams.prove(rng, x, C, fr, 1, vec!{});
|
||||||
averageProve = averageProve.add(sProve.to(PreciseTime::now()));
|
averageProve = averageProve.add(sProve.to(PreciseTime::now()));
|
||||||
averageProofSize += mem::size_of_val(&proof);
|
averageProofSize += mem::size_of_val(&proof);
|
||||||
|
|
||||||
let sVerify = PreciseTime::now();
|
let sVerify = PreciseTime::now();
|
||||||
let ch = params.compute_challenge(&proof);
|
let ch = secParams.compute_challenge(&proof);
|
||||||
params.verify(proof, ch, 1);
|
secParams.verify(proof, ch, 1);
|
||||||
averageVerify = averageVerify.add(sVerify.to(PreciseTime::now()));
|
averageVerify = averageVerify.add(sVerify.to(PreciseTime::now()));
|
||||||
}
|
}
|
||||||
print!("Setup: {}\n", averageSetup.num_milliseconds() / iter);
|
print!("Setup: {}\n", averageSetup.num_milliseconds() / iter);
|
||||||
|
@ -631,14 +662,15 @@ mod tests {
|
||||||
fn setup_works() {
|
fn setup_works() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
let public_params = RPPublicParams::<Bls12>::setup(rng, 2, 10, csParams);
|
let secParams = RPSecretParams::<Bls12>::setup(rng, 2, 10, csParams);
|
||||||
|
let public_params = secParams.pubParams.clone();
|
||||||
assert_eq!(public_params.a, 2);
|
assert_eq!(public_params.a, 2);
|
||||||
assert_eq!(public_params.b, 10);
|
assert_eq!(public_params.b, 10);
|
||||||
assert_eq!(public_params.p.signatures.len(), 57);
|
assert_eq!(public_params.p.signatures.len(), 57);
|
||||||
assert_eq!(public_params.p.u, 57);
|
assert_eq!(public_params.p.u, 57);
|
||||||
assert_eq!(public_params.p.l, 1);
|
assert_eq!(public_params.p.l, 1);
|
||||||
for (m, s) in public_params.p.signatures {
|
for (m, s) in public_params.p.signatures {
|
||||||
assert_eq!(public_params.p.kp.verify(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
|
assert_eq!(secParams.p.kp.public.verify_blind(&public_params.p.mpk, &vec! {Fr::from_str(m.to_string().as_str()).unwrap()}, &Fr::zero(), &s), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +679,7 @@ mod tests {
|
||||||
fn setup_wrong_a_and_b() {
|
fn setup_wrong_a_and_b() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
RPPublicParams::<Bls12>::setup(rng, 10, 2, csParams);
|
RPSecretParams::<Bls12>::setup(rng, 10, 2, csParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -655,7 +687,7 @@ mod tests {
|
||||||
fn setup_wrong_logb() {
|
fn setup_wrong_logb() {
|
||||||
let rng = &mut rand::thread_rng();
|
let rng = &mut rand::thread_rng();
|
||||||
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
let csParams = CSMultiParams::setup_gen_params(rng, 1);
|
||||||
RPPublicParams::<Bls12>::setup(rng, -2, -1, csParams);
|
RPSecretParams::<Bls12>::setup(rng, -2, -1, csParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -668,11 +700,11 @@ mod tests {
|
||||||
let m1 = Fr::rand(rng);
|
let m1 = Fr::rand(rng);
|
||||||
let m2 = Fr::rand(rng);
|
let m2 = Fr::rand(rng);
|
||||||
let sig = kp.sign(rng, &vec! {m1, m2});
|
let sig = kp.sign(rng, &vec! {m1, m2});
|
||||||
let state = kp.prove_commitment(rng, ¶ms, &sig, None, None);
|
let state = kp.public.prove_commitment(rng, ¶ms, &sig, None, None);
|
||||||
let state1 = kp.prove_commitment(rng, ¶ms, &sig, None, None);
|
let state1 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None);
|
||||||
let state2 = kp.prove_commitment(rng, ¶ms, &sig, None, None);
|
let state2 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None);
|
||||||
let state3 = kp.prove_commitment(rng, ¶ms, &sig, None, None);
|
let state3 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None);
|
||||||
let state4 = kp.prove_commitment(rng, ¶ms, &sig, None, None);
|
let state4 = kp.public.prove_commitment(rng, ¶ms, &sig, None, None);
|
||||||
let a = vec! {state.a, state1.a, state2.a};
|
let a = vec! {state.a, state1.a, state2.a};
|
||||||
let a2 = vec! {state3.a, state4.a};
|
let a2 = vec! {state3.a, state4.a};
|
||||||
assert_eq!(hash::<Bls12>(a.clone(), vec!(D.clone())).is_zero(), false);
|
assert_eq!(hash::<Bls12>(a.clone(), vec!(D.clone())).is_zero(), false);
|
||||||
|
|
158
src/channels.rs
158
src/channels.rs
|
@ -11,7 +11,7 @@ extern crate rand;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use pairing::bls12_381::{Bls12};
|
use pairing::bls12_381::Bls12;
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use cl::{BlindKeyPair, KeyPair, Signature, PublicParams, setup};
|
use cl::{BlindKeyPair, KeyPair, Signature, PublicParams, setup};
|
||||||
use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof};
|
use ped92::{CSParams, Commitment, CSMultiParams, CommitmentProof};
|
||||||
|
@ -21,7 +21,7 @@ use std::collections::HashMap;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use std::ptr::hash;
|
use std::ptr::hash;
|
||||||
use nizk::{NIZKPublicParams, NIZKProof};
|
use nizk::{NIZKPublicParams, NIZKSecretParams, NIZKProof};
|
||||||
use wallet::Wallet;
|
use wallet::Wallet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -34,13 +34,13 @@ pub type ResultBoltType<E> = Result<E, BoltError>;
|
||||||
|
|
||||||
impl BoltError {
|
impl BoltError {
|
||||||
fn new(msg: &str) -> BoltError {
|
fn new(msg: &str) -> BoltError {
|
||||||
BoltError{details: msg.to_string()}
|
BoltError { details: msg.to_string() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BoltError {
|
impl fmt::Display for BoltError {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f,"{}",self.details)
|
write!(f, "{}", self.details)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ impl Error for BoltError {
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
pub struct PubKeyMap {
|
pub struct PubKeyMap {
|
||||||
pub wpk: secp256k1::PublicKey,
|
pub wpk: secp256k1::PublicKey,
|
||||||
pub revoke_token: Option<secp256k1::Signature>
|
pub revoke_token: Option<secp256k1::Signature>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
@ -68,8 +68,9 @@ pub struct PubKeyMap {
|
||||||
))]
|
))]
|
||||||
pub struct ChannelParams<E: Engine> {
|
pub struct ChannelParams<E: Engine> {
|
||||||
pub pub_params: NIZKPublicParams<E>,
|
pub pub_params: NIZKPublicParams<E>,
|
||||||
l: usize, // messages for commitment
|
l: usize,
|
||||||
extra_verify: bool // extra verification for certain points in the establish/pay protocol
|
// messages for commitment
|
||||||
|
extra_verify: bool, // extra verification for certain points in the establish/pay protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ pub struct ChannelState<E: Engine> {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub pay_init: bool,
|
pub pay_init: bool,
|
||||||
pub channel_established: bool,
|
pub channel_established: bool,
|
||||||
pub third_party: bool
|
pub third_party: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
@ -102,10 +103,14 @@ pub struct ChannelState<E: Engine> {
|
||||||
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
<E as pairing::Engine>::G2: serde::Deserialize<'de>"
|
||||||
))]
|
))]
|
||||||
pub struct ChannelToken<E: Engine> {
|
pub struct ChannelToken<E: Engine> {
|
||||||
pub pk_c: Option<secp256k1::PublicKey>, // pk_c
|
pub pk_c: Option<secp256k1::PublicKey>,
|
||||||
pub pk_m: secp256k1::PublicKey, // pk_m
|
// pk_c
|
||||||
pub cl_pk_m: cl::PublicKey<E>, // PK_m (used for verifying blind signatures)
|
pub pk_m: secp256k1::PublicKey,
|
||||||
pub mpk: cl::PublicParams<E>, // mpk for PK_m
|
// pk_m
|
||||||
|
pub cl_pk_m: cl::PublicKey<E>,
|
||||||
|
// PK_m (used for verifying blind signatures)
|
||||||
|
pub mpk: cl::PublicParams<E>,
|
||||||
|
// mpk for PK_m
|
||||||
pub comParams: CSMultiParams<E>,
|
pub comParams: CSMultiParams<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +145,6 @@ impl<E: Engine> ChannelToken<E> {
|
||||||
|
|
||||||
return hash_to_slice(&input);
|
return hash_to_slice(&input);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// add methods to check if channel token is initialized
|
// add methods to check if channel token is initialized
|
||||||
// (only if
|
// (only if
|
||||||
|
@ -149,7 +153,6 @@ impl<E: Engine> ChannelToken<E> {
|
||||||
/// Channel state for generating/loading channel parameters and generating keypairs
|
/// Channel state for generating/loading channel parameters and generating keypairs
|
||||||
///
|
///
|
||||||
impl<E: Engine> ChannelState<E> {
|
impl<E: Engine> ChannelState<E> {
|
||||||
|
|
||||||
pub fn new(name: String, third_party_support: bool) -> ChannelState<E> {
|
pub fn new(name: String, third_party_support: bool) -> ChannelState<E> {
|
||||||
ChannelState {
|
ChannelState {
|
||||||
R: 0,
|
R: 0,
|
||||||
|
@ -158,7 +161,7 @@ impl<E: Engine> ChannelState<E> {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
pay_init: false,
|
pay_init: false,
|
||||||
channel_established: false,
|
channel_established: false,
|
||||||
third_party: third_party_support
|
third_party: third_party_support,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,17 +169,6 @@ impl<E: Engine> ChannelState<E> {
|
||||||
sodiumoxide::init();
|
sodiumoxide::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// setup - generate public parameters for bidirectional payment channels
|
|
||||||
///
|
|
||||||
pub fn setup<R: Rng>(&mut self, csprng: &mut R) {
|
|
||||||
let l = 5;
|
|
||||||
let pubParams = NIZKPublicParams::<E>::setup(csprng, l);
|
|
||||||
|
|
||||||
let cp = ChannelParams { pub_params: pubParams, l: l, extra_verify: true };
|
|
||||||
self.cp = Some(cp);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// keygen - takes as input public parameters and generates a digital signature keypair
|
/// keygen - takes as input public parameters and generates a digital signature keypair
|
||||||
///
|
///
|
||||||
|
@ -203,7 +195,7 @@ impl<E: Engine> ChannelState<E> {
|
||||||
#[derive(Copy, Clone, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||||
struct WalletKeyPair {
|
struct WalletKeyPair {
|
||||||
pub wpk: secp256k1::PublicKey,
|
pub wpk: secp256k1::PublicKey,
|
||||||
pub wsk: secp256k1::SecretKey
|
pub wsk: secp256k1::SecretKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -222,17 +214,23 @@ pub struct CustomerState<E: Engine> {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub pk_c: secp256k1::PublicKey,
|
pub pk_c: secp256k1::PublicKey,
|
||||||
sk_c: secp256k1::SecretKey,
|
sk_c: secp256k1::SecretKey,
|
||||||
pub cust_balance: i32, //
|
pub cust_balance: i32,
|
||||||
|
//
|
||||||
pub merch_balance: i32,
|
pub merch_balance: i32,
|
||||||
pub wpk: secp256k1::PublicKey, // keypair bound to the wallet
|
pub wpk: secp256k1::PublicKey,
|
||||||
|
// keypair bound to the wallet
|
||||||
wsk: secp256k1::SecretKey,
|
wsk: secp256k1::SecretKey,
|
||||||
old_kp: Option<WalletKeyPair>, // old wallet key pair
|
old_kp: Option<WalletKeyPair>,
|
||||||
t: E::Fr, // randomness used to form the commitment
|
// old wallet key pair
|
||||||
wallet: Wallet<E>, // vector of field elements that represent wallet
|
t: E::Fr,
|
||||||
pub w_com: Commitment<E>, // commitment to the current state of the wallet
|
// randomness used to form the commitment
|
||||||
|
wallet: Wallet<E>,
|
||||||
|
// vector of field elements that represent wallet
|
||||||
|
pub w_com: Commitment<E>,
|
||||||
|
// commitment to the current state of the wallet
|
||||||
index: i32,
|
index: i32,
|
||||||
close_tokens: HashMap<i32, Signature<E>>,
|
close_tokens: HashMap<i32, Signature<E>>,
|
||||||
pay_tokens: HashMap<i32, Signature<E>>
|
pay_tokens: HashMap<i32, Signature<E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> CustomerState<E> {
|
impl<E: Engine> CustomerState<E> {
|
||||||
|
@ -259,8 +257,8 @@ impl<E: Engine> CustomerState<E> {
|
||||||
|
|
||||||
assert!(channel_token.is_init());
|
assert!(channel_token.is_init());
|
||||||
|
|
||||||
let ct_db= HashMap::new();
|
let ct_db = HashMap::new();
|
||||||
let pt_db= HashMap::new();
|
let pt_db = HashMap::new();
|
||||||
|
|
||||||
return CustomerState {
|
return CustomerState {
|
||||||
name: name,
|
name: name,
|
||||||
|
@ -276,8 +274,8 @@ impl<E: Engine> CustomerState<E> {
|
||||||
wallet: wallet,
|
wallet: wallet,
|
||||||
index: 0,
|
index: 0,
|
||||||
close_tokens: ct_db,
|
close_tokens: ct_db,
|
||||||
pay_tokens: pt_db
|
pay_tokens: pt_db,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_wallet(&self) -> Wallet<E> {
|
pub fn get_wallet(&self) -> Wallet<E> {
|
||||||
|
@ -304,21 +302,21 @@ impl<E: Engine> CustomerState<E> {
|
||||||
let mpk = cp.pub_params.mpk.clone();
|
let mpk = cp.pub_params.mpk.clone();
|
||||||
//println!("verify_close_token - Wallet: {}", &self.wallet);
|
//println!("verify_close_token - Wallet: {}", &self.wallet);
|
||||||
|
|
||||||
let is_close_valid = cp.pub_params.keypair.verify(&mpk, &close_wallet, &self.t, &close_token);
|
let is_close_valid = cp.pub_params.pk.verify_blind(&mpk, &close_wallet, &self.t, &close_token);
|
||||||
if is_close_valid {
|
if is_close_valid {
|
||||||
//println!("verify_close_token - Blinded close token is valid!!");
|
//println!("verify_close_token - Blinded close token is valid!!");
|
||||||
let pk = cp.pub_params.keypair.get_public_key(&mpk);
|
let unblind_close_token = cp.pub_params.pk.unblind(&self.t, &close_token);
|
||||||
let unblind_close_token = cp.pub_params.keypair.unblind(&self.t, &close_token);
|
let pk = cp.pub_params.pk.get_pub_key();
|
||||||
let is_valid = pk.verify(&mpk, &close_wallet, &unblind_close_token);
|
let is_valid = pk.verify(&mpk, &close_wallet, &unblind_close_token);
|
||||||
if is_valid {
|
if is_valid {
|
||||||
// record the unblinded close token
|
// record the unblinded close token
|
||||||
self.close_tokens.insert( self.index, unblind_close_token);
|
self.close_tokens.insert(self.index, unblind_close_token);
|
||||||
}
|
}
|
||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//println!("Customer - Verification failed for close token!");
|
//println!("Customer - Verification failed for close token!");
|
||||||
return false;
|
return is_close_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_pay_token(&mut self, channel: &ChannelState<E>, pay_token: &Signature<E>) -> bool {
|
pub fn verify_pay_token(&mut self, channel: &ChannelState<E>, pay_token: &Signature<E>) -> bool {
|
||||||
|
@ -329,11 +327,11 @@ impl<E: Engine> CustomerState<E> {
|
||||||
let wallet = self.wallet.without_close();
|
let wallet = self.wallet.without_close();
|
||||||
//println!("verify_pay_token - Wallet: {}", &self.wallet);
|
//println!("verify_pay_token - Wallet: {}", &self.wallet);
|
||||||
|
|
||||||
let is_pay_valid = cp.pub_params.keypair.verify(&mpk, &wallet, &self.t, &pay_token);
|
let is_pay_valid = cp.pub_params.pk.verify_blind(&mpk, &wallet, &self.t, &pay_token);
|
||||||
if is_pay_valid {
|
if is_pay_valid {
|
||||||
//println!("verify_pay_token - Blinded pay token is valid!!");
|
//println!("verify_pay_token - Blinded pay token is valid!!");
|
||||||
let unblind_pay_token = cp.pub_params.keypair.unblind(&self.t, &pay_token);
|
let unblind_pay_token = cp.pub_params.pk.unblind(&self.t, &pay_token);
|
||||||
let pk = cp.pub_params.keypair.get_public_key(&mpk);
|
let pk = cp.pub_params.pk.get_pub_key();
|
||||||
let is_valid = pk.verify(&mpk, &wallet, &unblind_pay_token);
|
let is_valid = pk.verify(&mpk, &wallet, &unblind_pay_token);
|
||||||
if is_valid {
|
if is_valid {
|
||||||
self.pay_tokens.insert(self.index, unblind_pay_token);
|
self.pay_tokens.insert(self.index, unblind_pay_token);
|
||||||
|
@ -342,7 +340,7 @@ impl<E: Engine> CustomerState<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
//println!("Customer - Verification failed for pay token!");
|
//println!("Customer - Verification failed for pay token!");
|
||||||
return false;
|
return is_pay_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_tokens(&self) -> bool {
|
pub fn has_tokens(&self) -> bool {
|
||||||
|
@ -361,7 +359,7 @@ impl<E: Engine> CustomerState<E> {
|
||||||
let wpk_h = hash_pubkey_to_fr::<E>(&new_wpk);
|
let wpk_h = hash_pubkey_to_fr::<E>(&new_wpk);
|
||||||
|
|
||||||
// 2 - form new wallet and commitment
|
// 2 - form new wallet and commitment
|
||||||
let new_cust_bal= self.cust_balance - amount;
|
let new_cust_bal = self.cust_balance - amount;
|
||||||
let new_merch_bal = self.merch_balance + amount;
|
let new_merch_bal = self.merch_balance + amount;
|
||||||
let new_t = E::Fr::rand(csprng);
|
let new_t = E::Fr::rand(csprng);
|
||||||
|
|
||||||
|
@ -393,7 +391,7 @@ impl<E: Engine> CustomerState<E> {
|
||||||
wallet: new_wallet.clone(),
|
wallet: new_wallet.clone(),
|
||||||
index: self.index, // increment index here
|
index: self.index, // increment index here
|
||||||
close_tokens: self.close_tokens.clone(),
|
close_tokens: self.close_tokens.clone(),
|
||||||
pay_tokens: self.pay_tokens.clone()
|
pay_tokens: self.pay_tokens.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
return (pay_proof, new_wcom, self.wpk, new_cw);
|
return (pay_proof, new_wcom, self.wpk, new_cw);
|
||||||
|
@ -433,7 +431,6 @@ impl<E: Engine> CustomerState<E> {
|
||||||
|
|
||||||
Err(BoltError::new("generate_revoke_token - could not verify the close token."))
|
Err(BoltError::new("generate_revoke_token - could not verify the close token."))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> fmt::Display for CustomerState<E> {
|
impl<E: Engine> fmt::Display for CustomerState<E> {
|
||||||
|
@ -468,7 +465,7 @@ impl<E: Engine> fmt::Display for CustomerState<E> {
|
||||||
pub struct ChannelcloseM {
|
pub struct ChannelcloseM {
|
||||||
pub address: String,
|
pub address: String,
|
||||||
pub revoke: Option<secp256k1::Signature>,
|
pub revoke: Option<secp256k1::Signature>,
|
||||||
pub signature: secp256k1::Signature
|
pub signature: secp256k1::Signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -485,55 +482,55 @@ pub struct ChannelcloseM {
|
||||||
))]
|
))]
|
||||||
pub struct MerchantState<E: Engine> {
|
pub struct MerchantState<E: Engine> {
|
||||||
keypair: cl::BlindKeyPair<E>,
|
keypair: cl::BlindKeyPair<E>,
|
||||||
pub init_balance: i32,
|
nizkParams: NIZKSecretParams<E>,
|
||||||
pk: secp256k1::PublicKey, // pk_m
|
pk: secp256k1::PublicKey,
|
||||||
sk: secp256k1::SecretKey, // sk_m
|
// pk_m
|
||||||
|
sk: secp256k1::SecretKey,
|
||||||
|
// sk_m
|
||||||
comParams: CSMultiParams<E>,
|
comParams: CSMultiParams<E>,
|
||||||
pub keys: HashMap<String, PubKeyMap>,
|
pub keys: HashMap<String, PubKeyMap>,
|
||||||
pub pay_tokens: HashMap<String, cl::Signature<E>>
|
pub pay_tokens: HashMap<String, cl::Signature<E>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> MerchantState<E> {
|
impl<E: Engine> MerchantState<E> {
|
||||||
pub fn new<R: Rng>(csprng: &mut R, channel: &mut ChannelState<E>, id: String) -> Self {
|
pub fn new<R: Rng>(csprng: &mut R, channel: &mut ChannelState<E>, id: String) -> (Self, ChannelState<E>) {
|
||||||
|
let l = 5;
|
||||||
// generate keys here
|
// generate keys here
|
||||||
let mut tx_kp = secp256k1::Secp256k1::new();
|
let mut tx_kp = secp256k1::Secp256k1::new();
|
||||||
tx_kp.randomize(csprng);
|
tx_kp.randomize(csprng);
|
||||||
let (wsk, wpk) = tx_kp.generate_keypair(csprng);
|
let (wsk, wpk) = tx_kp.generate_keypair(csprng);
|
||||||
let cp = channel.cp.as_ref().unwrap(); // if not set, then panic!
|
let mut ch = channel.clone();
|
||||||
|
let nizkParams = NIZKSecretParams::<E>::setup(csprng, l);
|
||||||
|
ch.cp = Some(ChannelParams::<E> { pub_params: nizkParams.pubParams.clone(), l, extra_verify: true });
|
||||||
|
|
||||||
MerchantState {
|
(MerchantState {
|
||||||
keypair: cp.pub_params.keypair.clone(),
|
keypair: nizkParams.keypair.clone(),
|
||||||
init_balance: 0,
|
nizkParams: nizkParams.clone(),
|
||||||
pk: wpk,
|
pk: wpk,
|
||||||
sk: wsk,
|
sk: wsk,
|
||||||
comParams: cp.pub_params.comParams.clone(),
|
comParams: nizkParams.pubParams.comParams.clone(),
|
||||||
keys: HashMap::new(), // store wpks/revoke_tokens
|
keys: HashMap::new(), // store wpks/revoke_tokens
|
||||||
pay_tokens: HashMap::new()
|
pay_tokens: HashMap::new(),
|
||||||
}
|
}, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init<R: Rng>(&mut self, csprng: &mut R, channel: &mut ChannelState<E>) -> ChannelToken<E> {
|
pub fn init<R: Rng>(&mut self, csprng: &mut R, channel: &mut ChannelState<E>) -> ChannelToken<E> {
|
||||||
let cp = channel.cp.as_ref().unwrap(); // if not set, then panic!
|
let cp = channel.cp.as_ref().unwrap(); // if not set, then panic!
|
||||||
let mpk = cp.pub_params.mpk.clone();
|
let mpk = cp.pub_params.mpk.clone();
|
||||||
let cl_pk = cp.pub_params.keypair.get_public_key(&mpk);
|
let cl_pk = self.keypair.get_public_key(&mpk);
|
||||||
|
|
||||||
return ChannelToken {
|
return ChannelToken {
|
||||||
pk_c: None,
|
pk_c: None,
|
||||||
cl_pk_m: cl_pk.clone(), // extract the regular public key
|
cl_pk_m: cl_pk.clone(), // extract the regular public key
|
||||||
pk_m: self.pk.clone(),
|
pk_m: self.pk.clone(),
|
||||||
mpk: mpk,
|
mpk: mpk,
|
||||||
comParams: self.comParams.clone()
|
comParams: self.comParams.clone(),
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_balance(&mut self, balance: i32) {
|
|
||||||
// set by the escrow/funding transactionf for the channel
|
|
||||||
self.init_balance = balance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn issue_close_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, extend_close: bool) -> Signature<E> {
|
pub fn issue_close_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, extend_close: bool) -> Signature<E> {
|
||||||
//println!("issue_close_token => generating token");
|
//println!("issue_close_token => generating token");
|
||||||
let x = hash_to_fr::<E>(String::from("close").into_bytes() );
|
let x = hash_to_fr::<E>(String::from("close").into_bytes());
|
||||||
let close_com = match extend_close {
|
let close_com = match extend_close {
|
||||||
true => self.comParams.extend_commit(com, &x),
|
true => self.comParams.extend_commit(com, &x),
|
||||||
false => com.clone()
|
false => com.clone()
|
||||||
|
@ -544,7 +541,7 @@ impl<E: Engine> MerchantState<E> {
|
||||||
|
|
||||||
pub fn issue_pay_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, remove_close: bool) -> Signature<E> {
|
pub fn issue_pay_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, remove_close: bool) -> Signature<E> {
|
||||||
//println!("issue_pay_token => generating token");
|
//println!("issue_pay_token => generating token");
|
||||||
let x = hash_to_fr::<E>(String::from("close").into_bytes() );
|
let x = hash_to_fr::<E>(String::from("close").into_bytes());
|
||||||
let pay_com = match remove_close {
|
let pay_com = match remove_close {
|
||||||
true => self.comParams.remove_commit(com, &x),
|
true => self.comParams.remove_commit(com, &x),
|
||||||
false => com.clone()
|
false => com.clone()
|
||||||
|
@ -584,7 +581,7 @@ impl<E: Engine> MerchantState<E> {
|
||||||
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
||||||
let epsilon = util::convert_int_to_fr::<E>(amount);
|
let epsilon = util::convert_int_to_fr::<E>(amount);
|
||||||
|
|
||||||
if cp.pub_params.verify(pay_proof, epsilon, com, prev_wpk) {
|
if self.nizkParams.verify(pay_proof, epsilon, com, prev_wpk) {
|
||||||
// 1 - proceed with generating close and pay token
|
// 1 - proceed with generating close and pay token
|
||||||
let close_token = self.issue_close_token(csprng, cp, com, false);
|
let close_token = self.issue_close_token(csprng, cp, com, false);
|
||||||
let pay_token = self.issue_pay_token(csprng, cp, com, true);
|
let pay_token = self.issue_pay_token(csprng, cp, com, true);
|
||||||
|
@ -613,11 +610,10 @@ impl<E: Engine> MerchantState<E> {
|
||||||
let r = revoke_token.unwrap().serialize_der().to_vec();
|
let r = revoke_token.unwrap().serialize_der().to_vec();
|
||||||
msg.extend(r);
|
msg.extend(r);
|
||||||
}
|
}
|
||||||
let msg2 = secp256k1::Message::from_slice(&hash_to_slice(&msg) ).unwrap();
|
let msg2 = secp256k1::Message::from_slice(&hash_to_slice(&msg)).unwrap();
|
||||||
let merch_sig = secp.sign(&msg2, &self.sk);
|
let merch_sig = secp.sign(&msg2, &self.sk);
|
||||||
return ChannelcloseM { address: address.clone(), revoke: revoke_token.clone(), signature: merch_sig };
|
return ChannelcloseM { address: address.clone(), revoke: revoke_token.clone(), signature: merch_sig };
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -625,8 +621,8 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use ff::Rand;
|
use ff::Rand;
|
||||||
use pairing::bls12_381::{Bls12};
|
use pairing::bls12_381::Bls12;
|
||||||
use rand::{SeedableRng};
|
use rand::SeedableRng;
|
||||||
use rand_xorshift::XorShiftRng;
|
use rand_xorshift::XorShiftRng;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -634,16 +630,12 @@ mod tests {
|
||||||
let mut channel = ChannelState::<Bls12>::new(String::from("Channel A <-> B"), false);
|
let mut channel = ChannelState::<Bls12>::new(String::from("Channel A <-> B"), false);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
// run setup to generate the public parameters
|
|
||||||
channel.setup(&mut rng); // or load_setup params
|
|
||||||
|
|
||||||
let b0_cust = 100;
|
let b0_cust = 100;
|
||||||
let b0_merch = 20;
|
let b0_merch = 20;
|
||||||
// each party executes the init algorithm on the agreed initial challenge balance
|
// each party executes the init algorithm on the agreed initial challenge balance
|
||||||
// in order to derive the channel tokens
|
// in order to derive the channel tokens
|
||||||
// initialize on the merchant side with balance: b0_merch
|
// initialize on the merchant side with balance: b0_merch
|
||||||
let mut merch_state = MerchantState::<Bls12>::new(rng, &mut channel, String::from("Merchant B"));
|
let (mut merch_state, mut channel) = MerchantState::<Bls12>::new(rng, &mut channel, String::from("Merchant B"));
|
||||||
merch_state.init_balance(b0_merch);
|
|
||||||
|
|
||||||
// initialize the merchant wallet with the balance
|
// initialize the merchant wallet with the balance
|
||||||
let mut channel_token = merch_state.init(rng, &mut channel);
|
let mut channel_token = merch_state.init(rng, &mut channel);
|
||||||
|
|
188
src/cl.rs
188
src/cl.rs
|
@ -36,7 +36,6 @@ pub struct SecretKey<E: Engine> {
|
||||||
|
|
||||||
impl<E: Engine> fmt::Display for SecretKey<E> {
|
impl<E: Engine> fmt::Display for SecretKey<E> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
||||||
let mut y_str = String::new();
|
let mut y_str = String::new();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for y in self.y.iter() {
|
for y in self.y.iter() {
|
||||||
|
@ -63,7 +62,6 @@ pub struct PublicKey<E: Engine> {
|
||||||
|
|
||||||
impl<E: Engine> fmt::Display for PublicKey<E> {
|
impl<E: Engine> fmt::Display for PublicKey<E> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
||||||
let mut y_s = String::new();
|
let mut y_s = String::new();
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for y in self.Y.iter() {
|
for y in self.Y.iter() {
|
||||||
|
@ -92,7 +90,6 @@ pub struct BlindPublicKey<E: Engine> {
|
||||||
|
|
||||||
impl<E: Engine> fmt::Display for BlindPublicKey<E> {
|
impl<E: Engine> fmt::Display for BlindPublicKey<E> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
||||||
let mut y1_str = String::new();
|
let mut y1_str = String::new();
|
||||||
for y in self.Y1.iter() {
|
for y in self.Y1.iter() {
|
||||||
y1_str = format!("{}\n{}", y1_str, y);
|
y1_str = format!("{}\n{}", y1_str, y);
|
||||||
|
@ -206,22 +203,6 @@ impl<E: Engine> SecretKey<E> {
|
||||||
|
|
||||||
Signature { h: h, H: H }
|
Signature { h: h, H: H }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn blind<R: Rng>(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
|
||||||
let r = E::Fr::rand(csprng);
|
|
||||||
let t = bf.clone();
|
|
||||||
let mut h1 = signature.h;
|
|
||||||
h1.mul_assign(r); // sigma1 ^ r
|
|
||||||
|
|
||||||
let mut h = signature.h;
|
|
||||||
let mut H1 = signature.H;
|
|
||||||
h.mul_assign(t); // sigma1 ^ t (blinding factor)
|
|
||||||
H1.add_assign(&h); // (sigma2 * sigma1 ^ t)
|
|
||||||
|
|
||||||
// (sigma2 * sigma1 ^ t) ^ r
|
|
||||||
H1.mul_assign(r);
|
|
||||||
Signature { h: h1, H: H1 }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -302,6 +283,10 @@ impl<E: Engine> BlindPublicKey<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_pub_key(&self) -> PublicKey<E> {
|
||||||
|
PublicKey { X: self.X2.clone(), Y: self.Y2.clone() }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn verify(&self, mpk: &PublicParams<E>, message: &Vec<E::Fr>, signature: &Signature<E>) -> bool {
|
pub fn verify(&self, mpk: &PublicParams<E>, message: &Vec<E::Fr>, signature: &Signature<E>) -> bool {
|
||||||
let mut L = E::G2::zero();
|
let mut L = E::G2::zero();
|
||||||
let l = self.Y2.len();
|
let l = self.Y2.len();
|
||||||
|
@ -339,6 +324,14 @@ impl<E: Engine> BlindPublicKey<E> {
|
||||||
signature.h != E::G1::one() && lhs == rhs
|
signature.h != E::G1::one() && lhs == rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// verify a blinded signature without unblinding it first
|
||||||
|
pub fn verify_blind(&self, mpk: &PublicParams<E>, message: &Vec<E::Fr>, bf: &E::Fr, signature: &Signature<E>) -> bool {
|
||||||
|
let mut m = message.clone();
|
||||||
|
let t = bf.clone();
|
||||||
|
m.push(t);
|
||||||
|
self.verify(mpk, &m, signature)
|
||||||
|
}
|
||||||
|
|
||||||
/// Verify a proof of knowledge of a signature
|
/// Verify a proof of knowledge of a signature
|
||||||
/// Takes in a proof generated by prove_response(), a blind signature, and a challenge
|
/// Takes in a proof generated by prove_response(), a blind signature, and a challenge
|
||||||
/// outputs: boolean
|
/// outputs: boolean
|
||||||
|
@ -358,6 +351,80 @@ impl<E: Engine> BlindPublicKey<E> {
|
||||||
g.mul_assign(&p.a);
|
g.mul_assign(&p.a);
|
||||||
gx == g
|
gx == g
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn blind<R: Rng>(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
||||||
|
let r = E::Fr::rand(csprng);
|
||||||
|
let t = bf.clone();
|
||||||
|
let mut h1 = signature.h;
|
||||||
|
h1.mul_assign(r); // sigma1 ^ r
|
||||||
|
|
||||||
|
let mut h = signature.h;
|
||||||
|
let mut H1 = signature.H;
|
||||||
|
h.mul_assign(t); // sigma1 ^ t (blinding factor)
|
||||||
|
H1.add_assign(&h); // (sigma2 * sigma1 ^ t)
|
||||||
|
|
||||||
|
// (sigma2 * sigma1 ^ t) ^ r
|
||||||
|
H1.mul_assign(r);
|
||||||
|
Signature { h: h1, H: H1 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unblind(&self, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
||||||
|
let mut H = signature.h;
|
||||||
|
let mut inv_bf = bf.clone();
|
||||||
|
inv_bf.negate();
|
||||||
|
|
||||||
|
// sigma2 / sigma1 ^ t
|
||||||
|
H.mul_assign(inv_bf);
|
||||||
|
H.add_assign(&signature.H);
|
||||||
|
|
||||||
|
Signature { h: signature.h, H: H }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// prove knowledge of a signature: commitment phase
|
||||||
|
/// returns the proof state, including commitment a and a blind signature blindSig
|
||||||
|
pub fn prove_commitment<R: Rng>(&self, rng: &mut R, mpk: &PublicParams<E>, signature: &Signature<E>,
|
||||||
|
tOptional: Option<Vec<E::Fr>>, ttOptional: Option<E::Fr>) -> ProofState<E> {
|
||||||
|
let v = E::Fr::rand(rng);
|
||||||
|
let blindSig = self.blind(rng, &v, signature);
|
||||||
|
let mut t = tOptional.unwrap_or(Vec::<E::Fr>::with_capacity(self.Y2.len()));
|
||||||
|
let tt = ttOptional.unwrap_or(E::Fr::rand(rng));
|
||||||
|
let mut a = E::Fqk::one();
|
||||||
|
// TODO: consider optimizations to pairing in loop
|
||||||
|
for j in 0..self.Y2.len() {
|
||||||
|
if t.len() == j {
|
||||||
|
t.push(E::Fr::rand(rng));
|
||||||
|
}
|
||||||
|
let mut gy = E::pairing(blindSig.h, self.Y2[j]);
|
||||||
|
gy = gy.pow(t[j].into_repr());
|
||||||
|
a.mul_assign(&gy);
|
||||||
|
}
|
||||||
|
let mut h = E::pairing(blindSig.h, mpk.g2);
|
||||||
|
h = h.pow(tt.into_repr());
|
||||||
|
a.mul_assign(&h);
|
||||||
|
ProofState { v, t, tt, a, blindSig }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// prove knowledge of a signature: response phase
|
||||||
|
/// returns a proof that can be send to the verifier together with the challenge and the blind signature
|
||||||
|
pub fn prove_response(&self, ps: &ProofState<E>, challenge: E::Fr, message: &mut Vec<E::Fr>) -> SignatureProof<E> {
|
||||||
|
let mut zsig = ps.t.clone();
|
||||||
|
let z_len = zsig.len();
|
||||||
|
|
||||||
|
for i in 0..message.len() {
|
||||||
|
if i < z_len {
|
||||||
|
let mut message1 = message[i];
|
||||||
|
message1.mul_assign(&challenge);
|
||||||
|
zsig[i].add_assign(&message1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut zv = ps.tt.clone();
|
||||||
|
let mut vic = ps.v.clone();
|
||||||
|
vic.mul_assign(&challenge);
|
||||||
|
zv.add_assign(&vic);
|
||||||
|
SignatureProof { zsig, zv, a: ps.a }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -442,74 +509,13 @@ impl<E: Engine> BlindKeyPair<E> {
|
||||||
|
|
||||||
/// computes a blind signature from an existing one
|
/// computes a blind signature from an existing one
|
||||||
pub fn blind<R: Rng>(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
pub fn blind<R: Rng>(&self, csprng: &mut R, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
||||||
self.secret.blind(csprng, bf, signature)
|
self.public.blind(csprng, bf, signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// unblinds a signature given knowledge of blinding factor, t. Output should be
|
/// unblinds a signature given knowledge of blinding factor, t. Output should be
|
||||||
/// verifiable with standard signature scheme.
|
/// verifiable with standard signature scheme.
|
||||||
pub fn unblind(&self, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
pub fn unblind(&self, bf: &E::Fr, signature: &Signature<E>) -> Signature<E> {
|
||||||
let mut H = signature.h;
|
self.public.unblind(bf, signature)
|
||||||
let mut inv_bf = bf.clone();
|
|
||||||
inv_bf.negate();
|
|
||||||
|
|
||||||
// sigma2 / sigma1 ^ t
|
|
||||||
H.mul_assign(inv_bf);
|
|
||||||
H.add_assign(&signature.H);
|
|
||||||
|
|
||||||
Signature { h: signature.h, H: H }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// verify a blinded signature without unblinding it first
|
|
||||||
pub fn verify(&self, mpk: &PublicParams<E>, message: &Vec<E::Fr>, bf: &E::Fr, signature: &Signature<E>) -> bool {
|
|
||||||
let mut m = message.clone();
|
|
||||||
let t = bf.clone();
|
|
||||||
m.push(t);
|
|
||||||
self.public.verify(mpk, &m, signature)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// prove knowledge of a signature: commitment phase
|
|
||||||
/// returns the proof state, including commitment a and a blind signature blindSig
|
|
||||||
pub fn prove_commitment<R: Rng>(&self, rng: &mut R, mpk: &PublicParams<E>, signature: &Signature<E>,
|
|
||||||
tOptional: Option<Vec<E::Fr>>, ttOptional: Option<E::Fr>) -> ProofState<E> {
|
|
||||||
let v = E::Fr::rand(rng);
|
|
||||||
let blindSig = self.blind(rng, &v, signature);
|
|
||||||
let mut t = tOptional.unwrap_or(Vec::<E::Fr>::with_capacity(self.public.Y2.len()));
|
|
||||||
let tt = ttOptional.unwrap_or(E::Fr::rand(rng));
|
|
||||||
let mut a = E::Fqk::one();
|
|
||||||
// TODO: consider optimizations to pairing in loop
|
|
||||||
for j in 0..self.public.Y2.len() {
|
|
||||||
if t.len() == j {
|
|
||||||
t.push(E::Fr::rand(rng));
|
|
||||||
}
|
|
||||||
let mut gy = E::pairing(blindSig.h, self.public.Y2[j]);
|
|
||||||
gy = gy.pow(t[j].into_repr());
|
|
||||||
a.mul_assign(&gy);
|
|
||||||
}
|
|
||||||
let mut h = E::pairing(blindSig.h, mpk.g2);
|
|
||||||
h = h.pow(tt.into_repr());
|
|
||||||
a.mul_assign(&h);
|
|
||||||
ProofState { v, t, tt, a, blindSig }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// prove knowledge of a signature: response phase
|
|
||||||
/// returns a proof that can be send to the verifier together with the challenge and the blind signature
|
|
||||||
pub fn prove_response(&self, ps: &ProofState<E>, challenge: E::Fr, message: &mut Vec<E::Fr>) -> SignatureProof<E> {
|
|
||||||
let mut zsig = ps.t.clone();
|
|
||||||
let z_len = zsig.len();
|
|
||||||
|
|
||||||
for i in 0..message.len() {
|
|
||||||
if i < z_len {
|
|
||||||
let mut message1 = message[i];
|
|
||||||
message1.mul_assign(&challenge);
|
|
||||||
zsig[i].add_assign(&message1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut zv = ps.tt.clone();
|
|
||||||
let mut vic = ps.v.clone();
|
|
||||||
vic.mul_assign(&challenge);
|
|
||||||
zv.add_assign(&vic);
|
|
||||||
SignatureProof { zsig, zv, a: ps.a }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,9 +593,9 @@ mod tests {
|
||||||
let t1 = Fr::rand(&mut rng);
|
let t1 = Fr::rand(&mut rng);
|
||||||
|
|
||||||
// verify blind signatures and provide blinding factor as input
|
// verify blind signatures and provide blinding factor as input
|
||||||
assert_eq!(keypair.verify(&mpk, &message1, &t, &blind_sig), true);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message1, &t, &blind_sig), true);
|
||||||
assert_eq!(keypair.verify(&mpk, &message2, &t, &blind_sig), false);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message2, &t, &blind_sig), false);
|
||||||
assert_eq!(keypair.verify(&mpk, &message1, &t1, &blind_sig), false);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message1, &t1, &blind_sig), false);
|
||||||
|
|
||||||
let rand_sig = keypair.rerandomize_signature(&mut rng, &sig);
|
let rand_sig = keypair.rerandomize_signature(&mut rng, &sig);
|
||||||
assert_eq!(public_key.verify(&mpk, &message1, &rand_sig), true);
|
assert_eq!(public_key.verify(&mpk, &message1, &rand_sig), true);
|
||||||
|
@ -616,7 +622,7 @@ mod tests {
|
||||||
|
|
||||||
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &signature1), true);
|
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &signature1), true);
|
||||||
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &blind_sig), false);
|
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &blind_sig), false);
|
||||||
assert_eq!(keypair.verify(&mpk, &message1, &r, &blind_sig), true);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message1, &r, &blind_sig), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -648,10 +654,10 @@ mod tests {
|
||||||
let t1 = Fr::rand(&mut rng);
|
let t1 = Fr::rand(&mut rng);
|
||||||
|
|
||||||
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &unblinded_sig), true);
|
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message1, &unblinded_sig), true);
|
||||||
assert_eq!(keypair.verify(&mpk, &message1, &t, &signature), true);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message1, &t, &signature), true);
|
||||||
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message2, &unblinded_sig), false);
|
assert_eq!(keypair.get_public_key(&mpk).verify(&mpk, &message2, &unblinded_sig), false);
|
||||||
assert_eq!(keypair.verify(&mpk, &message2, &t, &signature), false);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message2, &t, &signature), false);
|
||||||
assert_eq!(keypair.verify(&mpk, &message1, &t1, &signature), false);
|
assert_eq!(keypair.public.verify_blind(&mpk, &message1, &t1, &signature), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -671,9 +677,9 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
let sig = keypair.sign(&mut rng, &message1);
|
let sig = keypair.sign(&mut rng, &message1);
|
||||||
let proof_state = keypair.prove_commitment(rng, &mpk, &sig, None, None);
|
let proof_state = keypair.public.prove_commitment(rng, &mpk, &sig, None, None);
|
||||||
let challenge = Fr::rand(&mut rng);
|
let challenge = Fr::rand(&mut rng);
|
||||||
let proof = keypair.prove_response(&proof_state.clone(), challenge, &mut message1);
|
let proof = keypair.public.prove_response(&proof_state.clone(), challenge, &mut message1);
|
||||||
|
|
||||||
assert_eq!(keypair.public.verify_proof(&mpk, proof_state.blindSig, proof, challenge), true);
|
assert_eq!(keypair.public.verify_proof(&mpk, proof_state.blindSig, proof, challenge), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,6 @@ pub mod ffishim {
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(name.to_string(), tps);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(name.to_string(), tps);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
channel_state.setup(&mut rng);
|
|
||||||
let ser = ["{\'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat();
|
let ser = ["{\'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat();
|
||||||
let cser = CString::new(ser).unwrap();
|
let cser = CString::new(ser).unwrap();
|
||||||
cser.into_raw()
|
cser.into_raw()
|
||||||
|
@ -112,9 +111,7 @@ pub mod ffishim {
|
||||||
let bytes = unsafe { CStr::from_ptr(name_ptr).to_bytes() };
|
let bytes = unsafe { CStr::from_ptr(name_ptr).to_bytes() };
|
||||||
let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8
|
let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8
|
||||||
|
|
||||||
let (channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, name);
|
let (channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, name);
|
||||||
// initialize the balance for merch_state
|
|
||||||
merch_state.init_balance(balance);
|
|
||||||
|
|
||||||
let ser = ["{\'channel_token\':\'", serde_json::to_string(&channel_token).unwrap().as_str(), "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str() ,"\'}"].concat();
|
let ser = ["{\'channel_token\':\'", serde_json::to_string(&channel_token).unwrap().as_str(), "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str() ,"\'}"].concat();
|
||||||
|
|
||||||
|
|
47
src/lib.rs
47
src/lib.rs
|
@ -186,14 +186,14 @@ pub mod bidirectional {
|
||||||
/// init_merchant - takes as input the public params, merchant balance and keypair.
|
/// init_merchant - takes as input the public params, merchant balance and keypair.
|
||||||
/// Generates merchant data which consists of channel token and merchant state.
|
/// Generates merchant data which consists of channel token and merchant state.
|
||||||
///
|
///
|
||||||
pub fn init_merchant<'a, R: Rng, E: Engine>(csprng: &mut R, channel_state: &mut ChannelState<E>, name: &'a str) -> (ChannelToken<E>, MerchantState<E>) {
|
pub fn init_merchant<'a, R: Rng, E: Engine>(csprng: &mut R, channel_state: &mut ChannelState<E>, name: &'a str) -> (ChannelToken<E>, MerchantState<E>, ChannelState<E>) {
|
||||||
// create new merchant state
|
// create new merchant state
|
||||||
let merch_name = String::from(name);
|
let merch_name = String::from(name);
|
||||||
let mut merch_state = MerchantState::<E>::new(csprng, channel_state, merch_name);
|
let (mut merch_state, mut channel_state) = MerchantState::<E>::new(csprng, channel_state, merch_name);
|
||||||
// initialize the merchant state
|
// initialize the merchant state
|
||||||
let channel_token = merch_state.init(csprng, channel_state);
|
let channel_token = merch_state.init(csprng, &mut channel_state);
|
||||||
|
|
||||||
return (channel_token, merch_state);
|
return (channel_token, merch_state, channel_state.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -231,7 +231,7 @@ pub mod bidirectional {
|
||||||
init_cust_balance: i32, init_merch_balance: i32,
|
init_cust_balance: i32, init_merch_balance: i32,
|
||||||
merch_state: &MerchantState<E>) -> BoltResult<cl::Signature<E>> {
|
merch_state: &MerchantState<E>) -> BoltResult<cl::Signature<E>> {
|
||||||
// verifies proof of committed values and derives blind signature on the committed values to the customer's initial wallet
|
// verifies proof of committed values and derives blind signature on the committed values to the customer's initial wallet
|
||||||
match merch_state.verify_proof(csprng, channel_state, com, com_proof, init_cust_balance, merch_state.init_balance) {
|
match merch_state.verify_proof(csprng, channel_state, com, com_proof, init_cust_balance, init_merch_balance) {
|
||||||
Ok(n) => Ok(Some(n.0)), // just close token
|
Ok(n) => Ok(Some(n.0)), // just close token
|
||||||
Err(err) => Err(String::from(err.to_string()))
|
Err(err) => Err(String::from(err.to_string()))
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ pub mod bidirectional {
|
||||||
let close_token = cust_state.get_close_token();
|
let close_token = cust_state.get_close_token();
|
||||||
|
|
||||||
let cp = channel_state.cp.as_ref().unwrap();
|
let cp = channel_state.cp.as_ref().unwrap();
|
||||||
let pk = cp.pub_params.keypair.get_public_key(&cp.pub_params.mpk);
|
let pk = cp.pub_params.pk.get_pub_key();
|
||||||
let close_wallet = wallet.with_close(String::from("close"));
|
let close_wallet = wallet.with_close(String::from("close"));
|
||||||
|
|
||||||
assert!(pk.verify(&cp.pub_params.mpk, &close_wallet, &close_token));
|
assert!(pk.verify(&cp.pub_params.mpk, &close_wallet, &close_token));
|
||||||
|
@ -435,7 +435,7 @@ pub mod bidirectional {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cp = channel_state.cp.as_ref().unwrap();
|
let cp = channel_state.cp.as_ref().unwrap();
|
||||||
let pk = cp.pub_params.keypair.get_public_key(&channel_token.mpk);
|
let pk = cp.pub_params.pk.get_pub_key();
|
||||||
let mut wallet = cust_close.message.clone();
|
let mut wallet = cust_close.message.clone();
|
||||||
let close_wallet = wallet.with_close(String::from("close")).clone();
|
let close_wallet = wallet.with_close(String::from("close")).clone();
|
||||||
let close_token = cust_close.signature.clone();
|
let close_token = cust_close.signature.clone();
|
||||||
|
@ -532,10 +532,11 @@ mod tests {
|
||||||
use ff::Rand;
|
use ff::Rand;
|
||||||
use pairing::bls12_381::{Bls12};
|
use pairing::bls12_381::{Bls12};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use channels::ChannelState;
|
||||||
|
|
||||||
fn setup_new_channel_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
fn setup_new_channel_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
||||||
init_cust_bal: i32, init_merch_bal: i32)
|
init_cust_bal: i32, init_merch_bal: i32)
|
||||||
-> (bidirectional::ChannelToken<Bls12>, bidirectional::MerchantState<Bls12>, bidirectional::CustomerState<Bls12>) {
|
-> (bidirectional::ChannelToken<Bls12>, bidirectional::MerchantState<Bls12>, bidirectional::CustomerState<Bls12>, bidirectional::ChannelState<Bls12>) {
|
||||||
|
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
let merch_name = "Bob";
|
let merch_name = "Bob";
|
||||||
|
@ -547,13 +548,12 @@ mod tests {
|
||||||
// each party executes the init algorithm on the agreed initial challenge balance
|
// each party executes the init algorithm on the agreed initial challenge balance
|
||||||
// in order to derive the channel tokens
|
// in order to derive the channel tokens
|
||||||
// initialize on the merchant side with balance: b0_merch
|
// initialize on the merchant side with balance: b0_merch
|
||||||
let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, channel_state, merch_name);
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, channel_state, merch_name);
|
||||||
merch_state.init_balance(b0_merch);
|
|
||||||
|
|
||||||
// initialize on the customer side with balance: b0_cust
|
// initialize on the customer side with balance: b0_cust
|
||||||
let cust_state = bidirectional::init_customer(rng, channel_state, &mut channel_token, b0_cust, b0_merch, cust_name);
|
let cust_state = bidirectional::init_customer(rng, &channel_state, &mut channel_token, b0_cust, b0_merch, cust_name);
|
||||||
|
|
||||||
return (channel_token, merch_state, cust_state);
|
return (channel_token, merch_state, cust_state, channel_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_establish_protocol_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
fn execute_establish_protocol_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
||||||
|
@ -614,16 +614,12 @@ mod tests {
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
channel_state.setup(&mut rng); // or load_setup params
|
|
||||||
|
|
||||||
let total_owed = 40;
|
let total_owed = 40;
|
||||||
let b0_customer = 90;
|
let b0_customer = 90;
|
||||||
let b0_merchant = 20;
|
let b0_merchant = 20;
|
||||||
let payment_increment = 20;
|
let payment_increment = 20;
|
||||||
|
|
||||||
let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
|
||||||
// initialize the balance for merch_state
|
|
||||||
merch_state.init_balance(b0_merchant);
|
|
||||||
|
|
||||||
let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice");
|
let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice");
|
||||||
|
|
||||||
|
@ -682,8 +678,6 @@ mod tests {
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
channel_state.setup(&mut rng); // or load_setup params
|
|
||||||
|
|
||||||
// set fee for channel
|
// set fee for channel
|
||||||
let fee = 5;
|
let fee = 5;
|
||||||
channel_state.set_channel_fee(fee);
|
channel_state.set_channel_fee(fee);
|
||||||
|
@ -729,9 +723,7 @@ mod tests {
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
|
|
||||||
channel_state.setup(&mut rng); // or load_setup params
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant);
|
||||||
|
|
||||||
let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant);
|
|
||||||
|
|
||||||
// run establish protocol for customer and merchant channel
|
// run establish protocol for customer and merchant channel
|
||||||
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
||||||
|
@ -759,9 +751,7 @@ mod tests {
|
||||||
|
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
|
|
||||||
channel_state.setup(&mut rng); // or load_setup params
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant);
|
||||||
|
|
||||||
let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant);
|
|
||||||
|
|
||||||
// run establish protocol for customer and merchant channel
|
// run establish protocol for customer and merchant channel
|
||||||
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
||||||
|
@ -806,9 +796,7 @@ mod tests {
|
||||||
|
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
|
|
||||||
channel_state.setup(&mut rng); // or load_setup params
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant);
|
||||||
|
|
||||||
let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant);
|
|
||||||
|
|
||||||
// run establish protocol for customer and merchant channel
|
// run establish protocol for customer and merchant channel
|
||||||
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
||||||
|
@ -935,14 +923,13 @@ mod tests {
|
||||||
fn serialization_tests() {
|
fn serialization_tests() {
|
||||||
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
||||||
let mut rng = &mut rand::thread_rng();
|
let mut rng = &mut rand::thread_rng();
|
||||||
channel_state.setup(&mut rng);
|
|
||||||
|
|
||||||
let serialized = serde_json::to_string(&channel_state).unwrap();
|
let serialized = serde_json::to_string(&channel_state).unwrap();
|
||||||
println!("new channel state len: {}", &serialized.len());
|
println!("new channel state len: {}", &serialized.len());
|
||||||
|
|
||||||
let chan_state: bidirectional::ChannelState<Bls12> = serde_json::from_str(&serialized).unwrap();
|
let chan_state: bidirectional::ChannelState<Bls12> = serde_json::from_str(&serialized).unwrap();
|
||||||
|
|
||||||
let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant A");
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant A");
|
||||||
|
|
||||||
let b0_cust = 100;
|
let b0_cust = 100;
|
||||||
let b0_merch = 10;
|
let b0_merch = 10;
|
||||||
|
|
226
src/nizk.rs
226
src/nizk.rs
|
@ -3,11 +3,11 @@ extern crate rand;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use cl::{Signature, PublicParams, setup, BlindKeyPair, SignatureProof};
|
use cl::{Signature, PublicParams, setup, BlindKeyPair, SignatureProof, PublicKey, BlindPublicKey};
|
||||||
use ped92::{Commitment, CSMultiParams, CommitmentProof};
|
use ped92::{Commitment, CSMultiParams, CommitmentProof};
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use wallet::Wallet;
|
use wallet::Wallet;
|
||||||
use ccs08::{RPPublicParams, RangeProof};
|
use ccs08::{RPPublicParams, RPSecretParams, RangeProof};
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use util;
|
use util;
|
||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
|
@ -44,25 +44,87 @@ pub struct NIZKProof<E: Engine> {
|
||||||
))]
|
))]
|
||||||
pub struct NIZKPublicParams<E: Engine> {
|
pub struct NIZKPublicParams<E: Engine> {
|
||||||
pub mpk: PublicParams<E>,
|
pub mpk: PublicParams<E>,
|
||||||
pub keypair: BlindKeyPair<E>,
|
pub pk: BlindPublicKey<E>,
|
||||||
pub comParams: CSMultiParams<E>,
|
pub comParams: CSMultiParams<E>,
|
||||||
pub rpParamsBC: RPPublicParams<E>,
|
pub rpParamsBC: RPPublicParams<E>,
|
||||||
pub rpParamsBM: RPPublicParams<E>,
|
pub rpParamsBM: RPPublicParams<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> NIZKPublicParams<E> {
|
/// NIZKSecretParams are secret parameters to perform the verification of 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, \
|
||||||
|
<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 NIZKSecretParams<E: Engine> {
|
||||||
|
pub pubParams: NIZKPublicParams<E>,
|
||||||
|
pub keypair: BlindKeyPair<E>,
|
||||||
|
pub rpParamsBC: RPSecretParams<E>,
|
||||||
|
pub rpParamsBM: RPSecretParams<E>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> NIZKSecretParams<E> {
|
||||||
/// Basic setup for the NIZKPublicParams
|
/// 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
|
/// 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 {
|
pub fn setup<R: Rng>(rng: &mut R, messageLength: usize) -> Self {
|
||||||
let mpk = setup(rng);
|
let mpk = setup(rng);
|
||||||
let keypair = BlindKeyPair::<E>::generate(rng, &mpk, messageLength);
|
let keypair = BlindKeyPair::<E>::generate(rng, &mpk, messageLength);
|
||||||
let comParams = keypair.generate_cs_multi_params(&mpk);
|
let comParams = keypair.generate_cs_multi_params(&mpk);
|
||||||
let rpParamsBC = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
let rpParamsBC = RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||||
let rpParamsBM = RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
let rpParamsBM = RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||||
|
let pubParams = NIZKPublicParams { mpk, pk: keypair.public.clone(), comParams, rpParamsBC: rpParamsBC.pubParams.clone(), rpParamsBM: rpParamsBM.pubParams.clone() };
|
||||||
|
|
||||||
NIZKPublicParams { mpk, keypair, comParams, rpParamsBC, rpParamsBM }
|
NIZKSecretParams{pubParams, keypair, rpParamsBC, rpParamsBM}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify a NIZK Proof of Knowledge during payment or closing protocol
|
||||||
|
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.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.pubParams.mpk, proof.sig, proof.sigProof.clone(), challenge);
|
||||||
|
let mut wpkc = wpk.clone();
|
||||||
|
wpkc.mul_assign(&challenge.clone());
|
||||||
|
r1 = r1 && proof.sigProof.zsig[1] == wpkc;
|
||||||
|
|
||||||
|
//verify knowledge of commitment
|
||||||
|
let r2 = proof.comProof.verify_proof(&self.pubParams.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.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.comProof.z[3] == zsig2;
|
||||||
|
let mut zsig3 = proof.sigProof.zsig[3].clone();
|
||||||
|
zsig3.add_assign(&epsC.clone());
|
||||||
|
r5 = r5 && proof.comProof.z[4] == zsig3;
|
||||||
|
|
||||||
|
r0 && r1 && r2 && r3 && r4 && r5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> NIZKPublicParams<E> {
|
||||||
/** This method can be called to create the proof during the payment and closing protocol
|
/** This method can be called to create the proof during the payment and closing protocol
|
||||||
Input:
|
Input:
|
||||||
rng: random generator
|
rng: random generator
|
||||||
|
@ -93,7 +155,7 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
true => Some(vec!(t[1], zero, t[3].clone(), t[4].clone())),
|
true => Some(vec!(t[1], zero, t[3].clone(), t[4].clone())),
|
||||||
false => Some(vec!(t[1], zero, t[3].clone()))
|
false => Some(vec!(t[1], zero, t[3].clone()))
|
||||||
};
|
};
|
||||||
let proofState = self.keypair.prove_commitment(rng, &self.mpk, &paymentToken, tOptional, None);
|
let proofState = self.pk.prove_commitment(rng, &self.mpk, &paymentToken, tOptional, None);
|
||||||
|
|
||||||
//commit range proof
|
//commit range proof
|
||||||
let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3, None, None);
|
let rpStateBC = self.rpParamsBC.prove_commitment(rng, newWallet.bc.clone(), newWalletCom.clone(), 3, None, None);
|
||||||
|
@ -105,7 +167,7 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
//Response phase
|
//Response phase
|
||||||
//response for signature
|
//response for signature
|
||||||
let oldWalletVec = oldWallet.as_fr_vec();
|
let oldWalletVec = oldWallet.as_fr_vec();
|
||||||
let sigProof = self.keypair.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
|
let sigProof = self.pk.prove_response(&proofState, challenge, &mut oldWalletVec.clone());
|
||||||
|
|
||||||
//response commitment
|
//response commitment
|
||||||
let newWalletVec = newWallet.as_fr_vec();
|
let newWalletVec = newWallet.as_fr_vec();
|
||||||
|
@ -128,48 +190,6 @@ impl<E: Engine> NIZKPublicParams<E> {
|
||||||
NIZKProof { sig: proofState.blindSig, sigProof, comProof, rpBC, rpBM }
|
NIZKProof { sig: proofState.blindSig, sigProof, comProof, rpBC, rpBM }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
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.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);
|
|
||||||
let mut wpkc = wpk.clone();
|
|
||||||
wpkc.mul_assign(&challenge.clone());
|
|
||||||
r1 = r1 && proof.sigProof.zsig[1] == wpkc;
|
|
||||||
|
|
||||||
//verify knowledge of commitment
|
|
||||||
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.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.comProof.z[3] == zsig2;
|
|
||||||
let mut zsig3 = proof.sigProof.zsig[3].clone();
|
|
||||||
zsig3.add_assign(&epsC.clone());
|
|
||||||
r5 = r5 && proof.comProof.z[4] == zsig3;
|
|
||||||
|
|
||||||
r0 && r1 && r2 && r3 && r4 && r5
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hash(a: E::Fqk, T: Vec<E::G1>) -> E::Fr {
|
fn hash(a: E::Fqk, T: Vec<E::G1>) -> E::Fr {
|
||||||
let mut x_vec: Vec<u8> = Vec::new();
|
let mut x_vec: Vec<u8> = Vec::new();
|
||||||
x_vec.extend(format!("{}", a).bytes());
|
x_vec.extend(format!("{}", a).bytes());
|
||||||
|
@ -245,18 +265,18 @@ mod tests {
|
||||||
let r = Fr::rand(rng);
|
let r = Fr::rand(rng);
|
||||||
let rprime = Fr::rand(rng);
|
let rprime = Fr::rand(rng);
|
||||||
|
|
||||||
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 4);
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
||||||
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
||||||
let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
||||||
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
||||||
let commitment2 = pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
||||||
let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
||||||
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
||||||
|
|
||||||
let proof = pubParams.prove(rng, wallet1, wallet2,
|
let proof = secParams.pubParams.prove(rng, wallet1, wallet2,
|
||||||
commitment2.clone(), rprime, &paymentToken);
|
commitment2.clone(), rprime, &paymentToken);
|
||||||
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
||||||
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
|
assert_eq!(secParams.verify(proof, fr, &commitment2, wpk), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -275,18 +295,18 @@ mod tests {
|
||||||
let r = Fr::rand(rng);
|
let r = Fr::rand(rng);
|
||||||
let rprime = Fr::rand(rng);
|
let rprime = Fr::rand(rng);
|
||||||
|
|
||||||
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 4);
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
||||||
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
||||||
let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
||||||
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
||||||
let commitment2 = pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
||||||
let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
||||||
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
||||||
|
|
||||||
let proof = pubParams.prove(rng, wallet1, wallet2,
|
let proof = secParams.pubParams.prove(rng, wallet1, wallet2,
|
||||||
commitment2.clone(), rprime, &paymentToken);
|
commitment2.clone(), rprime, &paymentToken);
|
||||||
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
let fr = convert_int_to_fr::<Bls12>(*epsilon);
|
||||||
assert_eq!(pubParams.verify(proof, fr, &commitment2, wpk), true);
|
assert_eq!(secParams.verify(proof, fr, &commitment2, wpk), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -306,28 +326,28 @@ mod tests {
|
||||||
let rprime = Fr::rand(rng);
|
let rprime = Fr::rand(rng);
|
||||||
|
|
||||||
let _closeToken = Fr::rand(rng);
|
let _closeToken = Fr::rand(rng);
|
||||||
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 5);
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 5);
|
||||||
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
||||||
let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec(), &r);
|
||||||
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: Some(_closeToken) };
|
let wallet2 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2, close: Some(_closeToken) };
|
||||||
let commitment2 = pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec(), &rprime);
|
||||||
let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
||||||
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
||||||
|
|
||||||
let blindCloseToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment2.clone());
|
let blindCloseToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment2.clone());
|
||||||
let closeToken = pubParams.keypair.unblind(&rprime, &blindCloseToken);
|
let closeToken = secParams.pubParams.pk.unblind(&rprime, &blindCloseToken);
|
||||||
|
|
||||||
// verify the blind signatures
|
// verify the blind signatures
|
||||||
let pk = pubParams.keypair.get_public_key(&pubParams.mpk);
|
let pk = secParams.keypair.get_public_key(&secParams.pubParams.mpk);
|
||||||
assert!(pk.verify(&pubParams.mpk, &wallet1.as_fr_vec(), &paymentToken));
|
assert!(pk.verify(&secParams.pubParams.mpk, &wallet1.as_fr_vec(), &paymentToken));
|
||||||
|
|
||||||
println!("close => {}", &wallet2);
|
println!("close => {}", &wallet2);
|
||||||
assert!(pk.verify(&pubParams.mpk, &wallet2.as_fr_vec(), &closeToken));
|
assert!(pk.verify(&secParams.pubParams.mpk, &wallet2.as_fr_vec(), &closeToken));
|
||||||
|
|
||||||
let proof = pubParams.prove(rng, wallet1, wallet2,
|
let proof = secParams.pubParams.prove(rng, wallet1, wallet2,
|
||||||
commitment2.clone(), rprime, &paymentToken);
|
commitment2.clone(), rprime, &paymentToken);
|
||||||
|
|
||||||
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true);
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -346,28 +366,28 @@ mod tests {
|
||||||
let r = Fr::rand(rng);
|
let r = Fr::rand(rng);
|
||||||
let rprime = Fr::rand(rng);
|
let rprime = Fr::rand(rng);
|
||||||
|
|
||||||
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 4);
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
||||||
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
let wallet1 = Wallet { pkc, wpk, bc, bm, close: None };
|
||||||
|
|
||||||
let bc2Prime = bc.clone();
|
let bc2Prime = bc.clone();
|
||||||
let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2, close: None };
|
let wallet3 = Wallet { pkc, wpk: wpkprime, bc: bc2Prime, bm: bm2, close: None };
|
||||||
let commitment1 = pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &r);
|
let commitment1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &r);
|
||||||
let commitment2 = pubParams.comParams.commit(&wallet3.as_fr_vec(), &rprime);
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet3.as_fr_vec(), &rprime);
|
||||||
let blindPaymentToken = pubParams.keypair.sign_blind(rng, &pubParams.mpk, commitment1.clone());
|
let blindPaymentToken = secParams.keypair.sign_blind(rng, &secParams.pubParams.mpk, commitment1.clone());
|
||||||
let paymentToken = pubParams.keypair.unblind(&r, &blindPaymentToken);
|
let paymentToken = secParams.keypair.unblind(&r, &blindPaymentToken);
|
||||||
let proof = pubParams.prove(rng, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken);
|
let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet3, commitment2.clone(), rprime, &paymentToken);
|
||||||
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
||||||
|
|
||||||
let bm2Prime = bm.clone();
|
let bm2Prime = bm.clone();
|
||||||
let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime, close: None };
|
let wallet4 = Wallet { pkc, wpk: wpkprime, bc: bc2, bm: bm2Prime, close: None };
|
||||||
let commitment2 = pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime);
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet4.as_fr_vec(), &rprime);
|
||||||
let proof = pubParams.prove(rng, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken);
|
let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet4, commitment2.clone(), rprime, &paymentToken);
|
||||||
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
||||||
|
|
||||||
let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
let wallet5 = Wallet { pkc: Fr::rand(rng), wpk: wpkprime, bc: bc2, bm: bm2, close: None };
|
||||||
let commitment2 = pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime);
|
let commitment2 = secParams.pubParams.comParams.commit(&wallet5.as_fr_vec(), &rprime);
|
||||||
let proof = pubParams.prove(rng, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken);
|
let proof = secParams.pubParams.prove(rng, wallet1.clone(), wallet5, commitment2.clone(), rprime, &paymentToken);
|
||||||
assert_eq!(pubParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
assert_eq!(secParams.verify(proof, Fr::from_str(&epsilon.to_string()).unwrap(), &commitment2, wpk), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -381,13 +401,13 @@ mod tests {
|
||||||
let bm = rng.gen_range(100, 1000);
|
let bm = rng.gen_range(100, 1000);
|
||||||
let wallet = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None };
|
let wallet = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None };
|
||||||
|
|
||||||
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 4);
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
||||||
let com = pubParams.comParams.commit(&wallet.as_fr_vec().clone(), &t);
|
let com = secParams.pubParams.comParams.commit(&wallet.as_fr_vec().clone(), &t);
|
||||||
|
|
||||||
let com_proof = CommitmentProof::<Bls12>::new(rng, &pubParams.comParams,
|
let com_proof = CommitmentProof::<Bls12>::new(rng, &secParams.pubParams.comParams,
|
||||||
&com.c, &wallet.as_fr_vec(), &t, &vec![1, 3, 4]);
|
&com.c, &wallet.as_fr_vec(), &t, &vec![1, 3, 4]);
|
||||||
|
|
||||||
assert!(verify_opening(&pubParams.comParams, &com.c, &com_proof, bc, bm));
|
assert!(verify_opening(&secParams.pubParams.comParams, &com.c, &com_proof, bc, bm));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -403,15 +423,15 @@ mod tests {
|
||||||
let wallet1 = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None };
|
let wallet1 = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc, bm: bm, close: None };
|
||||||
let wallet2 = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc2, bm: bm, close: None };
|
let wallet2 = Wallet::<Bls12> { pkc: pkc, wpk: wpk, bc: bc2, bm: bm, close: None };
|
||||||
|
|
||||||
let pubParams = NIZKPublicParams::<Bls12>::setup(rng, 4);
|
let secParams = NIZKSecretParams::<Bls12>::setup(rng, 4);
|
||||||
let com1 = pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &t);
|
let com1 = secParams.pubParams.comParams.commit(&wallet1.as_fr_vec().clone(), &t);
|
||||||
let com2 = pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t);
|
let com2 = secParams.pubParams.comParams.commit(&wallet2.as_fr_vec().clone(), &t);
|
||||||
|
|
||||||
let com1_proof = CommitmentProof::<Bls12>::new(rng, &pubParams.comParams,
|
let com1_proof = CommitmentProof::<Bls12>::new(rng, &secParams.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(&secParams.pubParams.comParams, &com1.c, &com1_proof, bc, bm));
|
||||||
assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof, bc2, bm));
|
assert!(!verify_opening(&secParams.pubParams.comParams, &com2.c, &com1_proof, bc2, bm));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,10 +443,10 @@ mod tests {
|
||||||
let mpk = setup(&mut rng);
|
let mpk = setup(&mut rng);
|
||||||
let blindkeypair = BlindKeyPair::<Bls12>::generate(&mut rng, &mpk, l);
|
let blindkeypair = BlindKeyPair::<Bls12>::generate(&mut rng, &mpk, l);
|
||||||
let comParams = blindkeypair.generate_cs_multi_params(&mpk);
|
let comParams = blindkeypair.generate_cs_multi_params(&mpk);
|
||||||
let rpParamsBC = ccs08::RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
let rpParamsBC = ccs08::RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||||
let rpParamsBM = ccs08::RPPublicParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
let rpParamsBM = ccs08::RPSecretParams::setup(rng, 0, std::i16::MAX as i32, comParams.clone());
|
||||||
|
|
||||||
let nizk_params = NIZKPublicParams { mpk: mpk, keypair: blindkeypair, comParams: comParams, rpParamsBC: rpParamsBC, rpParamsBM: rpParamsBM };
|
let nizk_params = NIZKPublicParams { mpk: mpk, pk: blindkeypair.public, comParams: comParams, rpParamsBC: rpParamsBC.pubParams, rpParamsBM: rpParamsBM.pubParams };
|
||||||
|
|
||||||
let is_serialized = serde_json::to_vec(&nizk_params).unwrap();
|
let is_serialized = serde_json::to_vec(&nizk_params).unwrap();
|
||||||
println!("NIZK Struct len: {}", is_serialized.len());
|
println!("NIZK Struct len: {}", is_serialized.len());
|
||||||
|
|
Loading…
Reference in New Issue