adding payment api to customer wallet
This commit is contained in:
parent
783dcea35b
commit
1b1ba22699
|
@ -243,9 +243,6 @@ To contribute code improvements, please checkout the repository, make your chang
|
||||||
|
|
||||||
Here are some TODOs (not in any particular order):
|
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
|
* Fix warnings
|
||||||
* Add more unit tests for other dispute resolution scenarios and pay protocol (to ensure appopriate aborts), third-party test cases, etc.
|
* Add more unit tests for other dispute resolution scenarios and pay protocol (to ensure appopriate aborts), third-party test cases, etc.
|
||||||
|
|
||||||
|
|
114
src/channels.rs
114
src/channels.rs
|
@ -21,7 +21,7 @@ use std::fmt::Display;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
use serialization_wrappers::WalletCommitmentAndParamsWrapper;
|
use serialization_wrappers::WalletCommitmentAndParamsWrapper;
|
||||||
use std::ptr::hash;
|
use std::ptr::hash;
|
||||||
use nizk::NIZKPublicParams;
|
use nizk::{NIZKPublicParams, Proof};
|
||||||
use wallet::Wallet;
|
use wallet::Wallet;
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
@ -100,7 +100,7 @@ impl<E: Engine> ChannelState<E> {
|
||||||
/// setup - generate public parameters for bidirectional payment channels
|
/// setup - generate public parameters for bidirectional payment channels
|
||||||
///
|
///
|
||||||
pub fn setup<R: Rng>(&mut self, csprng: &mut R) {
|
pub fn setup<R: Rng>(&mut self, csprng: &mut R) {
|
||||||
let l = 5;
|
let l = 4;
|
||||||
let pubParams = NIZKPublicParams::<E>::setup(csprng, l);
|
let pubParams = NIZKPublicParams::<E>::setup(csprng, l);
|
||||||
let num_rand_values = 1;
|
let num_rand_values = 1;
|
||||||
|
|
||||||
|
@ -146,6 +146,9 @@ pub struct CustomerWallet<E: Engine> {
|
||||||
r: E::Fr, // randomness used to form the commitment
|
r: E::Fr, // randomness used to form the commitment
|
||||||
wallet: Wallet<E>, // vector of field elements that represent wallet
|
wallet: Wallet<E>, // vector of field elements that represent wallet
|
||||||
pub w_com: Commitment<E>, // commitment to the current state of the wallet
|
pub w_com: Commitment<E>, // commitment to the current state of the wallet
|
||||||
|
index: i32,
|
||||||
|
close_tokens: HashMap<i32, Signature<E>>,
|
||||||
|
pay_tokens: HashMap<i32, Signature<E>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> CustomerWallet<E> {
|
impl<E: Engine> CustomerWallet<E> {
|
||||||
|
@ -177,6 +180,9 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
|
|
||||||
assert!(channel_token.is_init());
|
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.");
|
println!("Customer wallet formed -> now returning the structure to the caller.");
|
||||||
return CustomerWallet {
|
return CustomerWallet {
|
||||||
pk_c: pk_c,
|
pk_c: pk_c,
|
||||||
|
@ -187,7 +193,10 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
wsk: wsk,
|
wsk: wsk,
|
||||||
r: r,
|
r: r,
|
||||||
w_com: w_com,
|
w_com: w_com,
|
||||||
wallet: wallet
|
wallet: wallet,
|
||||||
|
index: 1,
|
||||||
|
close_tokens: ct_db,
|
||||||
|
pay_tokens: pt_db
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,9 +205,9 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
return CommitmentProof::<E>::new(csprng, &channel_token.comParams, &self.w_com.c, &self.wallet.as_fr_vec(), &self.r);
|
return CommitmentProof::<E>::new(csprng, &channel_token.comParams, &self.w_com.c, &self.wallet.as_fr_vec(), &self.r);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_close_token(&self, channel: &ChannelState<E>, close_token: &Signature<E>) -> bool {
|
pub fn verify_close_token(&mut self, channel: &ChannelState<E>, close_token: &Signature<E>) -> bool {
|
||||||
// add a prefix to the wallet for close-message
|
// 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 cp = channel.cp.as_ref().unwrap();
|
||||||
let mpk = cp.pub_params.mpk.clone();
|
let mpk = cp.pub_params.mpk.clone();
|
||||||
|
|
||||||
|
@ -207,13 +216,18 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
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 pk = cp.pub_params.keypair.get_public_key(&mpk);
|
||||||
let unblind_close_token = cp.pub_params.keypair.unblind(&self.r, &close_token);
|
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!");
|
panic!("Channel establish - Verification failed for close token!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_pay_token(&self, channel: &ChannelState<E>, pay_token: &Signature<E>) -> bool {
|
pub fn verify_pay_token(&mut self, channel: &ChannelState<E>, pay_token: &Signature<E>) -> bool {
|
||||||
// unblind and verify signature
|
// unblind and verify signature
|
||||||
let cp = channel.cp.as_ref().unwrap();
|
let cp = channel.cp.as_ref().unwrap();
|
||||||
let mpk = cp.pub_params.mpk.clone();
|
let mpk = cp.pub_params.mpk.clone();
|
||||||
|
@ -224,19 +238,80 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
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.r, &pay_token);
|
let unblind_pay_token = cp.pub_params.keypair.unblind(&self.r, &pay_token);
|
||||||
let pk = cp.pub_params.keypair.get_public_key(&mpk);
|
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!") ;
|
panic!("verify_pay_token - Channel establish - Verification failed for pay token!") ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for channel pay
|
||||||
|
pub fn generate_payment<R: Rng>(&mut self, csprng: &mut R, channel: &ChannelState<E>, amount: i32) -> (Proof<E>, Commitment<E>, secp256k1::PublicKey, CustomerWallet<E>) {
|
||||||
|
// 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::<E>(&new_wpk);
|
||||||
|
|
||||||
// // for channel pay
|
// 2 - form new wallet and commitment
|
||||||
// pub fn update_wallet(&self, channel: &ChannelState<E>, pay_token: &Signature<E>, amount: i32) -> (CommitmentProof<E>, secp256k1::PublicKey) {
|
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<E: Engine> fmt::Display for CustomerWallet<E> {
|
||||||
|
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)
|
/// Merchant wallet (NEW)
|
||||||
///
|
///
|
||||||
|
@ -320,12 +395,6 @@ impl<E: Engine> MerchantWallet<E> {
|
||||||
//
|
//
|
||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//
|
|
||||||
//// customer obtains the close signature for wallet
|
|
||||||
//fn verify_proof() -> cl::Signature<E> {
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//trait MerchantEstablishChannel<E: Engine> {
|
//trait MerchantEstablishChannel<E: Engine> {
|
||||||
|
@ -380,10 +449,13 @@ mod tests {
|
||||||
|
|
||||||
println!("Done!");
|
println!("Done!");
|
||||||
|
|
||||||
// // pay protocol tests
|
// pay protocol tests
|
||||||
// let amount = 10;
|
// 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]
|
#[test]
|
||||||
|
|
|
@ -249,6 +249,7 @@ impl<E: Engine> BlindPublicKey<E> {
|
||||||
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 mut l = self.Y2.len();
|
let mut l = self.Y2.len();
|
||||||
|
println!("verify - m.len = {}, l = {}", message.len(), l);
|
||||||
assert!(message.len() <= l + 1);
|
assert!(message.len() <= l + 1);
|
||||||
let mut last_elem = l;
|
let mut last_elem = l;
|
||||||
|
|
||||||
|
|
54
src/ped92.rs
54
src/ped92.rs
|
@ -2,6 +2,7 @@
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use ff::Rand;
|
use ff::Rand;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CSParams<E: Engine> {
|
pub struct CSParams<E: Engine> {
|
||||||
|
@ -14,45 +15,32 @@ pub struct Commitment<E: Engine> {
|
||||||
pub c: E::G1,
|
pub c: E::G1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CSMultiParams<E: Engine> {
|
pub struct CSMultiParams<E: Engine> {
|
||||||
pub pub_bases: Vec<E::G1>
|
pub pub_bases: Vec<E::G1>
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl<E: Engine> fmt::Display for CSParams<E> {
|
impl<E: Engine> fmt::Display for CSMultiParams<E> {
|
||||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
// let g_vec: Vec<u8> = encode(&self.g, Infinite).unwrap();
|
|
||||||
// let h_vec: Vec<u8> = 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<E: Engine> fmt::Display for Commitment<E> {
|
let mut y_str = String::new();
|
||||||
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
let mut i = 0;
|
||||||
// let c_vec: Vec<u8> = encode(&self.c, Infinite).unwrap();
|
for y in self.pub_bases.iter() {
|
||||||
// let mut c_s = String::new();
|
y_str = format!("{}\n{} => {}", y_str, i, y);
|
||||||
// for x in c_vec.iter() {
|
i += 1;
|
||||||
// c_s = format!("{}{:x}", c_s, x);
|
}
|
||||||
// }
|
|
||||||
//
|
write!(f, "CSMultiParams : (\n{}\n)", y_str)
|
||||||
// let d_vec: Vec<u8> = encode(&self.r, Infinite).unwrap();
|
}
|
||||||
// let mut d_s = String::new();
|
}
|
||||||
// for x in d_vec.iter() {
|
|
||||||
// d_s = format!("{}{:x}", d_s, x);
|
impl<E: Engine> fmt::Display for Commitment<E> {
|
||||||
// }
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
// write!(f, "Commitment : (c=0x{}, r=0x{})", c_s, d_s)
|
write!(f, "Commitment : (c={})", &self.c)
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
|
|
||||||
impl<E: Engine> CSParams<E> {
|
impl<E: Engine> CSParams<E> {
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -4,6 +4,7 @@ use super::*;
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use ff::PrimeField;
|
use ff::PrimeField;
|
||||||
use util::hash_to_fr;
|
use util::hash_to_fr;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Wallet<E: Engine> {
|
pub struct Wallet<E: Engine> {
|
||||||
|
@ -23,10 +24,21 @@ impl<E: Engine> Wallet<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_msg(&self, msg: String) -> Vec<E::Fr> {
|
pub fn with_close(&mut self, msg: String) -> Vec<E::Fr> {
|
||||||
let m = hash_to_fr::<E>(msg.into_bytes() );
|
let m = hash_to_fr::<E>(msg.into_bytes() );
|
||||||
let mut new_vec = self.as_fr_vec();
|
self.close = Some(m.clone());
|
||||||
new_vec.push(m);
|
return self.as_fr_vec();
|
||||||
return new_vec;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> fmt::Display for Wallet<E> {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue