diff --git a/README.md b/README.md index 731091c..fdfa01c 100644 --- a/README.md +++ b/README.md @@ -243,9 +243,6 @@ To contribute code improvements, please checkout the repository, make your chang Here are some TODOs (not in any particular order): -* Serialization support for libbolt structures such as `CustomerWallet`, `PaymentProof`, and so on. -* Support for other curves (e.g., pairing library from Zcash) -* Finish unidirectional channel construction * Fix warnings * Add more unit tests for other dispute resolution scenarios and pay protocol (to ensure appopriate aborts), third-party test cases, etc. diff --git a/src/channels.rs b/src/channels.rs index 963d0b3..3309138 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -21,7 +21,7 @@ use std::fmt::Display; use serde::{Serialize, Deserialize}; use serialization_wrappers::WalletCommitmentAndParamsWrapper; use std::ptr::hash; -use nizk::NIZKPublicParams; +use nizk::{NIZKPublicParams, Proof}; use wallet::Wallet; #[derive(Clone, Serialize, Deserialize)] @@ -100,7 +100,7 @@ impl ChannelState { /// setup - generate public parameters for bidirectional payment channels /// pub fn setup(&mut self, csprng: &mut R) { - let l = 5; + let l = 4; let pubParams = NIZKPublicParams::::setup(csprng, l); let num_rand_values = 1; @@ -146,6 +146,9 @@ pub struct CustomerWallet { r: E::Fr, // randomness used to form the commitment wallet: Wallet, // vector of field elements that represent wallet pub w_com: Commitment, // commitment to the current state of the wallet + index: i32, + close_tokens: HashMap>, + pay_tokens: HashMap> } impl CustomerWallet { @@ -177,6 +180,9 @@ impl CustomerWallet { assert!(channel_token.is_init()); + let mut ct_db= HashMap::new(); + let mut pt_db= HashMap::new(); + println!("Customer wallet formed -> now returning the structure to the caller."); return CustomerWallet { pk_c: pk_c, @@ -187,7 +193,10 @@ impl CustomerWallet { wsk: wsk, r: r, w_com: w_com, - wallet: wallet + wallet: wallet, + index: 1, + close_tokens: ct_db, + pay_tokens: pt_db } } @@ -196,9 +205,9 @@ impl CustomerWallet { return CommitmentProof::::new(csprng, &channel_token.comParams, &self.w_com.c, &self.wallet.as_fr_vec(), &self.r); } - pub fn verify_close_token(&self, channel: &ChannelState, close_token: &Signature) -> bool { + pub fn verify_close_token(&mut self, channel: &ChannelState, close_token: &Signature) -> bool { // add a prefix to the wallet for close-message - let close_wallet = self.wallet.with_msg(String::from("close")); + let close_wallet = self.wallet.with_close(String::from("close")); let cp = channel.cp.as_ref().unwrap(); let mpk = cp.pub_params.mpk.clone(); @@ -207,13 +216,18 @@ impl CustomerWallet { 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.keypair.unblind(&self.r, &close_token); - return pk.verify(&mpk, &close_wallet, &unblind_close_token); + let is_valid = pk.verify(&mpk, &close_wallet, &unblind_close_token); + if is_valid { + // record the unblinded close token + self.close_tokens.insert( self.index - 1, unblind_close_token); + } + return is_valid; } panic!("Channel establish - Verification failed for close token!"); } - pub fn verify_pay_token(&self, channel: &ChannelState, pay_token: &Signature) -> bool { + pub fn verify_pay_token(&mut self, channel: &ChannelState, pay_token: &Signature) -> bool { // unblind and verify signature let cp = channel.cp.as_ref().unwrap(); let mpk = cp.pub_params.mpk.clone(); @@ -224,19 +238,80 @@ impl CustomerWallet { println!("verify_pay_token - Blinded pay token is valid!!"); let unblind_pay_token = cp.pub_params.keypair.unblind(&self.r, &pay_token); let pk = cp.pub_params.keypair.get_public_key(&mpk); - return pk.verify(&mpk, &wallet, &unblind_pay_token); + let is_valid = pk.verify(&mpk, &wallet, &unblind_pay_token); + if is_valid { + self.pay_tokens.insert(self.index - 1, unblind_pay_token); + } + return is_valid; } panic!("verify_pay_token - Channel establish - Verification failed for pay token!") ; } + // for channel pay + pub fn generate_payment(&mut self, csprng: &mut R, channel: &ChannelState, amount: i32) -> (Proof, Commitment, secp256k1::PublicKey, CustomerWallet) { + // 1 - chooose new wpk/wsk pair + let mut kp = secp256k1::Secp256k1::new(); + kp.randomize(csprng); + let (new_wsk, new_wpk) = kp.generate_keypair(csprng); + let wpk_h = hash_pubkey_to_fr::(&new_wpk); -// // for channel pay -// pub fn update_wallet(&self, channel: &ChannelState, pay_token: &Signature, amount: i32) -> (CommitmentProof, secp256k1::PublicKey) { -// -// } + // 2 - form new wallet and commitment + let new_cust_bal= self.cust_balance - amount; + let new_merch_bal = self.merch_balance + amount; + let new_r = E::Fr::rand(csprng); + + let cp = channel.cp.as_ref().unwrap(); + let new_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: wpk_h, bc: new_cust_bal, bm: new_merch_bal, close: None }; + let new_wcom = cp.pub_params.comParams.commit(&new_wallet.as_fr_vec(), &new_r); + + // 3 - generate new blinded and randomized pay token + let i = self.index - 1; + let mut prev_pay_token = self.pay_tokens.get(&i).unwrap(); + + println!("generate_payment - before generating proof!"); + println!("OLD {}", &self.wallet); + println!("NEW {}", &new_wallet); + println!("{}", &prev_pay_token); + + let pay_proof = cp.pub_params.prove(csprng, self.r.clone(), self.wallet.clone(), new_wallet.clone(), + new_wcom.clone(), new_r, &prev_pay_token); + println!("generate_payment - after generating proof!"); + + // TODO: update internal state accordingly + let new_cw = CustomerWallet { + pk_c: self.pk_c.clone(), + sk_c: self.sk_c.clone(), + cust_balance: new_cust_bal, + merch_balance: new_merch_bal, + wpk: new_wpk, + wsk: new_wsk, + r: new_r, + w_com: new_wcom.clone(), + wallet: new_wallet.clone(), + index: self.index + 1, // increment index here + close_tokens: self.close_tokens.clone(), + pay_tokens: self.pay_tokens.clone() + }; + + println!("returning results..."); + // return new_wcom, + return (pay_proof, new_wcom, self.wpk, new_cw); + } } +impl fmt::Display for CustomerWallet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut content = String::new(); + content = format!("pk = {}\n", &self.pk_c); + content = format!("{}sk = {}\n", content, &self.sk_c); + content = format!("{}cust-bal = {}\n", content, &self.cust_balance); + content = format!("{}merch-bal = {}\n", content, &self.merch_balance); + write!(f, "CustomerWallet : (\n{}\n)", &content) + } +} + + /// /// Merchant wallet (NEW) /// @@ -320,12 +395,6 @@ impl MerchantWallet { // // } //} -// -//// customer obtains the close signature for wallet -//fn verify_proof() -> cl::Signature { -// -//} - //trait MerchantEstablishChannel { @@ -380,10 +449,13 @@ mod tests { println!("Done!"); -// // pay protocol tests + // pay protocol tests // let amount = 10; -// let (new_cust_com_proof, wpk) = cust_wallet.update_wallet(&channel, amount); - +// let (pay_proof, new_com, old_wpk, new_cw) = cust_wallet.generate_payment(rng, &channel, amount); +// +// println!("{}", new_com); +// println!("wpk => {}", old_wpk); +// println!("{}", new_cw); } #[test] diff --git a/src/cl.rs b/src/cl.rs index 04bd557..2c240d0 100644 --- a/src/cl.rs +++ b/src/cl.rs @@ -249,6 +249,7 @@ impl BlindPublicKey { pub fn verify(&self, mpk: &PublicParams, message: &Vec, signature: &Signature) -> bool { let mut L = E::G2::zero(); let mut l = self.Y2.len(); + println!("verify - m.len = {}, l = {}", message.len(), l); assert!(message.len() <= l + 1); let mut last_elem = l; diff --git a/src/ped92.rs b/src/ped92.rs index eb02459..fd19541 100644 --- a/src/ped92.rs +++ b/src/ped92.rs @@ -2,6 +2,7 @@ use rand::{thread_rng, Rng}; use pairing::{Engine, CurveProjective}; use ff::Rand; +use std::fmt; #[derive(Clone)] pub struct CSParams { @@ -14,45 +15,32 @@ pub struct Commitment { pub c: E::G1, } + + #[derive(Clone)] pub struct CSMultiParams { pub pub_bases: Vec } -//impl fmt::Display for CSParams { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// let g_vec: Vec = encode(&self.g, Infinite).unwrap(); -// let h_vec: Vec = encode(&self.h, Infinite).unwrap(); -// let mut g_s = String::new(); -// for x in g_vec.iter() { -// g_s = format!("{}{:x}", g_s, x); -// } -// -// let mut h_s = String::new(); -// for y in h_vec.iter() { -// h_s = format!("{}{:x}", h_s, y); -// } -// -// write!(f, "CSP : (g=0x{}, h=0x{})", g_s, h_s) -// } -//} +impl fmt::Display for CSMultiParams { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//impl fmt::Display for Commitment { -// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -// let c_vec: Vec = encode(&self.c, Infinite).unwrap(); -// let mut c_s = String::new(); -// for x in c_vec.iter() { -// c_s = format!("{}{:x}", c_s, x); -// } -// -// let d_vec: Vec = encode(&self.r, Infinite).unwrap(); -// let mut d_s = String::new(); -// for x in d_vec.iter() { -// d_s = format!("{}{:x}", d_s, x); -// } -// write!(f, "Commitment : (c=0x{}, r=0x{})", c_s, d_s) -// } -//} + let mut y_str = String::new(); + let mut i = 0; + for y in self.pub_bases.iter() { + y_str = format!("{}\n{} => {}", y_str, i, y); + i += 1; + } + + write!(f, "CSMultiParams : (\n{}\n)", y_str) + } +} + +impl fmt::Display for Commitment { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Commitment : (c={})", &self.c) + } +} impl CSParams { /* diff --git a/src/wallet.rs b/src/wallet.rs index 75d2fb3..44465db 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -4,6 +4,7 @@ use super::*; use pairing::{Engine, CurveProjective}; use ff::PrimeField; use util::hash_to_fr; +use std::fmt; #[derive(Clone)] pub struct Wallet { @@ -23,10 +24,21 @@ impl Wallet { } } - pub fn with_msg(&self, msg: String) -> Vec { + pub fn with_close(&mut self, msg: String) -> Vec { let m = hash_to_fr::(msg.into_bytes() ); - let mut new_vec = self.as_fr_vec(); - new_vec.push(m); - return new_vec; + self.close = Some(m.clone()); + return self.as_fr_vec(); } } + +impl fmt::Display for Wallet { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.close.is_some() { + let close_str = self.close.unwrap(); + write!(f, "Wallet : (\npkc={}\nwpk={}\nbc={}\nbm={}\nclose={}\n)", &self.pkc, &self.wpk, &self.bc, &self.bm, close_str) + } else { + write!(f, "Wallet : (\npkc={}\nwpk={}\nbc={}\nbm={}\nclose=None\n)", &self.pkc, &self.wpk, &self.bc, &self.bm) + } + } +} +