add third-party payment option

This commit is contained in:
J. Ayo Akinyele 2018-08-13 18:16:02 -04:00
parent ca4f790cee
commit fb261a917b
5 changed files with 174 additions and 48 deletions

View File

@ -102,7 +102,7 @@ fn main() {
// let's test the pay protocol // let's test the pay protocol
assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &init_cust_data.T, &merch_keypair.pk, &mut init_cust_data.csk)); assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &init_cust_data.T, &merch_keypair.pk, &mut init_cust_data.csk));
let s = PreciseTime::now(); let s = PreciseTime::now();
let (t_c, new_wallet, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &init_cust_data.T, // channel token let (t_c, new_wallet, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &channel, &init_cust_data.T, // channel token
&merch_keypair.pk, // merchant pub key &merch_keypair.pk, // merchant pub key
&init_cust_data.csk, // wallet &init_cust_data.csk, // wallet
5); // balance increment 5); // balance increment
@ -132,7 +132,7 @@ fn main() {
} }
assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &init_cust_data.T, &merch_keypair.pk, &mut init_cust_data.csk)); assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &init_cust_data.T, &merch_keypair.pk, &mut init_cust_data.csk));
let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &init_cust_data.T, // channel token let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel, &init_cust_data.T, // channel token
&merch_keypair.pk, // merchant pub key &merch_keypair.pk, // merchant pub key
&init_cust_data.csk, // wallet &init_cust_data.csk, // wallet
-10); // balance increment -10); // balance increment

View File

@ -332,7 +332,7 @@ mod tests {
let cm_csp = commit_scheme::setup(b, m_keypair.pk.Z2.clone(), mpk.g2.clone()); let cm_csp = commit_scheme::setup(b, m_keypair.pk.Z2.clone(), mpk.g2.clone());
let r = m1[0]; let r = m1[0];
let (w_com, _) = commit_scheme::commit(&cm_csp, &m1, r); let w_com = commit_scheme::commit(&cm_csp, &m1, r);
assert!(commit_scheme::decommit(&cm_csp, &w_com, &m1)); assert!(commit_scheme::decommit(&cm_csp, &w_com, &m1));

View File

@ -155,27 +155,23 @@ pub fn setup_gen_params(len: usize) -> CSParams {
return CSParams { pub_bases: p }; return CSParams { pub_bases: p };
} }
pub fn commit(csp: &CSParams, x: &Vec<Fr>, r: Fr) -> (Commitment, Vec<G2>) { pub fn commit(csp: &CSParams, x: &Vec<Fr>, r: Fr) -> Commitment {
let rng = &mut thread_rng(); let rng = &mut thread_rng();
//let r = R.unwrap_or(Fr::random(rng)); //let r = R.unwrap_or(Fr::random(rng));
let mut c_vec: Vec<G2> = Vec::new();
// c = g1^m1 * ... * gn^mn * h^r // c = g1^m1 * ... * gn^mn * h^r
//println!("(commit) index: 0"); //println!("(commit) index: 0");
let mut c = (csp.pub_bases[0] * r); let mut c = (csp.pub_bases[0] * r);
c_vec.push(c);
for i in 1 .. x.len() { for i in 1 .. x.len() {
//println!("(commit) index: {}", i); //println!("(commit) index: {}", i);
let tmp = (csp.pub_bases[i] * x[i]); c = c + (csp.pub_bases[i] * x[i]);
c_vec.push(tmp);
c = c + tmp;
} }
// return (c, r) <- r // return (c, r) <- r
let commitment = Commitment { c: c, r: r }; let commitment = Commitment { c: c, r: r };
// debugging // debugging
//println!("{}", commitment); //println!("{}", commitment);
return (commitment, c_vec); return commitment;
} }
pub fn decommit(csp: &CSParams, cm: &Commitment, x: &Vec<Fr>) -> bool { pub fn decommit(csp: &CSParams, cm: &Commitment, x: &Vec<Fr>) -> bool {
@ -222,7 +218,7 @@ mod tests {
m.push(Fr::random(rng)); m.push(Fr::random(rng));
} }
let r = m[0]; let r = m[0];
let (c, _) = commit(&csp, &m, r); let c = commit(&csp, &m, r);
assert!(decommit(&csp, &c, &m) == true); assert!(decommit(&csp, &c, &m) == true);
} }

View File

@ -468,7 +468,7 @@ pub mod unidirectional {
ck_vec.push(ck); ck_vec.push(ck);
} }
let (w_com, _) = commit_scheme::commit(&cm_pk, &msg.hash(), r); let w_com = commit_scheme::commit(&cm_pk, &msg.hash(), r);
let t_c = ChannelToken { w_com: w_com, pk: keypair.pk }; let t_c = ChannelToken { w_com: w_com, pk: keypair.pk };
let csk_c = CustSecretKey { sk: keypair.sk, k1: k1, k2: k2, r: r, balance: b0_customer, ck_vec: ck_vec }; let csk_c = CustSecretKey { sk: keypair.sk, k1: k1, k2: k2, r: r, balance: b0_customer, ck_vec: ck_vec };
return InitCustomerData { T: t_c, csk: csk_c }; return InitCustomerData { T: t_c, csk: csk_c };
@ -514,6 +514,7 @@ pub mod bidirectional {
use hash_pub_key_to_fr; use hash_pub_key_to_fr;
use hash_buffer_to_fr; use hash_buffer_to_fr;
use debug_elem_in_hex; use debug_elem_in_hex;
use debug_g2_in_hex;
use debug_gt_in_hex; use debug_gt_in_hex;
use convert_to_fr; use convert_to_fr;
use convert_str_to_fr; use convert_str_to_fr;
@ -611,6 +612,7 @@ pub mod bidirectional {
pub struct ChannelState { pub struct ChannelState {
keys: HashMap<String, PubKeyMap>, keys: HashMap<String, PubKeyMap>,
R: i32, R: i32,
tx_fee: i32,
pub name: String, pub name: String,
pub cid: Fr, pub cid: Fr,
pub pay_init: bool, pub pay_init: bool,
@ -623,6 +625,7 @@ pub mod bidirectional {
ChannelState { ChannelState {
keys: HashMap::new(), // store wpks/revoke_tokens keys: HashMap::new(), // store wpks/revoke_tokens
R: 0, R: 0,
tx_fee: 0,
name: name.to_string(), name: name.to_string(),
cid: generate_channel_id(), cid: generate_channel_id(),
pay_init: false, pay_init: false,
@ -630,6 +633,14 @@ pub mod bidirectional {
third_party: third_party_support third_party: third_party_support
} }
} }
pub fn set_channel_fee(&mut self, fee: i32) {
self.tx_fee = fee;
}
pub fn get_channel_fee(&self) -> i32 {
return self.tx_fee as i32;
}
} }
pub struct ChannelclosureC { pub struct ChannelclosureC {
@ -643,22 +654,33 @@ pub mod bidirectional {
} }
// proof of valid balance // proof of valid balance
#[derive(Clone)]
pub struct ProofVB { pub struct ProofVB {
range_proof: bulletproofs::RangeProof, range_proof: bulletproofs::RangeProof,
value_commitment: RistrettoPoint value_commitment: RistrettoPoint
} }
#[derive(Clone)]
pub struct BalanceProof {
third_party: bool,
balance_increment: i32,
w_com_pr_pr: G2,
old_bal_com: G2,
vcom: Option<commit_scheme::Commitment>,
proof_vcom: Option<clproto::ProofCV>,
proof_vrange: Option<ProofVB>
}
#[derive(Clone)]
pub struct PaymentProof { pub struct PaymentProof {
proof2a: clproto::ProofCV, // PoK of committed values in new wallet proof2a: clproto::ProofCV, // PoK of committed values in new wallet
proof2b: clproto::ProofCV, // PoK of committed values in old wallet (minus wpk) proof2b: clproto::ProofCV, // PoK of committed values in old wallet (minus wpk)
proof2c: clproto::ProofVS, // PoK of old wallet signature (that includes wpk) proof2c: clproto::ProofVS, // PoK of old wallet signature (that includes wpk)
proof3: ProofVB, // range proof that balance - balance_inc is between (0, val_max) proof3: ProofVB, // range proof that balance - balance_inc is between (0, val_max)
w_com_pr_pr: G2,
balance_inc: i32, // balance increment
old_bal_com: G2,
old_com_base: G2, old_com_base: G2,
wpk: secp256k1::PublicKey, // verification key for old wallet wpk: secp256k1::PublicKey, // verification key for old wallet
wallet_sig: clsigs::SignatureD // blinded signature for old wallet wallet_sig: clsigs::SignatureD, // blinded signature for old wallet
pub bal_proof: BalanceProof
} }
pub struct RevokeToken { pub struct RevokeToken {
@ -718,7 +740,7 @@ pub mod bidirectional {
// commitment, channel id, customer balance, hash of wpk (wallet ver/pub key) // commitment, channel id, customer balance, hash of wpk (wallet ver/pub key)
let mut x: Vec<Fr> = vec![r, cid, b0, h_wpk]; let mut x: Vec<Fr> = vec![r, cid, b0, h_wpk];
// commitment of wallet values // commitment of wallet values
let (w_com, _) = commit_scheme::commit(&cm_csp, &x, r); let w_com = commit_scheme::commit(&cm_csp, &x, r);
// construct channel token // construct channel token
let t_c = ChannelToken { w_com: w_com, pk: keypair.pk.clone(), third_party_pay: channel.third_party }; let t_c = ChannelToken { w_com: w_com, pk: keypair.pk.clone(), third_party_pay: channel.third_party };
// construct customer wallet secret key plus other components // construct customer wallet secret key plus other components
@ -827,7 +849,7 @@ pub mod bidirectional {
return true; return true;
} }
pub fn pay_by_customer_phase1(pp: &PublicParams, T: &ChannelToken, pk_m: &clsigs::PublicKeyD, pub fn pay_by_customer_phase1(pp: &PublicParams, channel: &ChannelState, T: &ChannelToken, pk_m: &clsigs::PublicKeyD,
old_w: &CustomerWallet, balance_increment: i32) -> (ChannelToken, CustomerWallet, PaymentProof) { old_w: &CustomerWallet, balance_increment: i32) -> (ChannelToken, CustomerWallet, PaymentProof) {
//println!("pay_by_customer_phase1 - generate new wallet commit, PoK of commit values, and PoK of old wallet."); //println!("pay_by_customer_phase1 - generate new wallet commit, PoK of commit values, and PoK of old wallet.");
// get balance, keypair, commitment randomness and wallet sig // get balance, keypair, commitment randomness and wallet sig
@ -852,18 +874,18 @@ pub mod bidirectional {
// retrieve the current payment channel id // retrieve the current payment channel id
let cid = old_w.cid.clone(); let cid = old_w.cid.clone();
// convert balance into Fr (B - e) // convert balance into Fr (B - e)
let updated_balance = bal - balance_increment; let updated_balance = bal - balance_increment - channel.tx_fee;
if updated_balance < 0 { if updated_balance < 0 {
panic!("pay_by_customer_phase1 - insufficient funds to make payment!"); panic!("pay_by_customer_phase1 - insufficient funds to make payment!");
} }
// record the potential to payment // record the potential to payment
let merchant_balance = old_w.merchant_balance + balance_increment; let merchant_balance = old_w.merchant_balance + (balance_increment + channel.tx_fee);
let updated_balance_pr = convert_int_to_fr(updated_balance); let updated_balance_pr = convert_int_to_fr(updated_balance);
let mut new_wallet_sec: Vec<Fr> = vec![r_pr, cid, updated_balance_pr, h_wpk]; let mut new_wallet_sec: Vec<Fr> = vec![r_pr, cid, updated_balance_pr, h_wpk];
// commitment of new wallet values // commitment of new wallet values
let (w_com, com_vec) = commit_scheme::commit(&cm_csp, &new_wallet_sec, r_pr); let w_com = commit_scheme::commit(&cm_csp, &new_wallet_sec, r_pr);
let w_com_bytes: Vec<u8> = encode(&w_com.c, Infinite).unwrap(); let w_com_bytes: Vec<u8> = encode(&w_com.c, Infinite).unwrap();
// generate proof of knowledge for committed values in new wallet // generate proof of knowledge for committed values in new wallet
@ -887,8 +909,52 @@ pub mod bidirectional {
let proof_rp = ProofVB { range_proof: range_proof, value_commitment: value_cm }; let proof_rp = ProofVB { range_proof: range_proof, value_commitment: value_cm };
let mut bal_proof;
if T.third_party_pay { if T.third_party_pay {
// TODO: add check for third-party payment support let r_inc = Fr::random(rng);
let bal_inc_fr = -convert_int_to_fr(balance_increment + channel.tx_fee);
let inc_vec: Vec<Fr> = vec![r_inc, bal_inc_fr];
let mut v_com = commit_scheme::commit(&cm_csp, &inc_vec, r_inc);
//let tx_fee = cm_csp.pub_bases[1] * -convert_int_to_fr(channel.tx_fee);
//v_com.c = v_com.c + tx_fee;
let proof_vcom = clproto::bs_gen_nizk_proof(&inc_vec, &cm_csp.pub_bases, v_com.c);
// range proof that pay increment < payment max
let v_com_bytes: Vec<u8> = encode(&proof_vcom.C, Infinite).unwrap();
let mut inc_bal;
let final_balance_increment = balance_increment + channel.tx_fee;
if final_balance_increment < 0 {
// negative value => convert to positive value
assert!(final_balance_increment >= -E_MAX);
inc_bal = -final_balance_increment as u64
} else {
// positive value
inc_bal = final_balance_increment as u64;
}
let inc_blinding = Scalar::hash_from_bytes::<Sha512>(&v_com_bytes);
let mut osrng1 = OsRng::new().unwrap();
let mut transcript1 = ProofTranscript::new(b"Range Proof for Balance Increment");
let inc_range_proof = RangeProof::prove_single(&pp.range_proof_gens, &mut transcript1,
&mut osrng1, inc_bal, &inc_blinding,
pp.range_proof_bits).unwrap();
let inc_pg = &pp.range_proof_gens.pedersen_gens;
let inc_cm = inc_pg.commit(Scalar::from(inc_bal), inc_blinding);
let proof_vrange = ProofVB { range_proof: inc_range_proof, value_commitment: inc_cm };
bal_proof = BalanceProof { third_party: true, vcom: Some(v_com),
proof_vcom: Some(proof_vcom), proof_vrange: Some(proof_vrange),
w_com_pr_pr: w_com_pr_pr, balance_increment: 0,
old_bal_com: wallet_proof.bal_com,
};
} else {
// balance_increment => // epsilon - payment increment/decrement
// wallet_proof.bal_com => // old balance commitment
bal_proof = BalanceProof { third_party: false, vcom: None,
proof_vcom: None, proof_vrange: None,
w_com_pr_pr: w_com_pr_pr, balance_increment: balance_increment,
old_bal_com: wallet_proof.bal_com,
};
} }
// create payment proof which includes params to reveal wpk from old wallet // create payment proof which includes params to reveal wpk from old wallet
@ -897,10 +963,7 @@ pub mod bidirectional {
proof2b: wallet_proof.proof_cv, // PoK of committed values (minus h(wpk)) proof2b: wallet_proof.proof_cv, // PoK of committed values (minus h(wpk))
proof2c: wallet_proof.proof_vs, // PoK of signature on old wallet proof2c: wallet_proof.proof_vs, // PoK of signature on old wallet
proof3: proof_rp, // range proof that the updated_balance is within a public range proof3: proof_rp, // range proof that the updated_balance is within a public range
// TODO: clean up: balance_inc, old_bal_com, old_com_base, wpk (should be a separate structure?) bal_proof: bal_proof,
w_com_pr_pr: w_com_pr_pr,
balance_inc: balance_increment, // epsilon - payment increment/decrement
old_bal_com: wallet_proof.bal_com, // old balance commitment
old_com_base: cm_csp.pub_bases[wpk_index], // base Z old_com_base: cm_csp.pub_bases[wpk_index], // base Z
wpk: old_w.wpk.clone(), // showing public key for old wallet wpk: old_w.wpk.clone(), // showing public key for old wallet
wallet_sig: wallet_proof.blind_sig // blinded signature for old wallet wallet_sig: wallet_proof.blind_sig // blinded signature for old wallet
@ -922,6 +985,7 @@ pub mod bidirectional {
let proof_cv = &proof.proof2a; let proof_cv = &proof.proof2a;
let proof_old_cv = &proof.proof2b; let proof_old_cv = &proof.proof2b;
let proof_vs = &proof.proof2c; let proof_vs = &proof.proof2c;
let bal_proof = &proof.bal_proof;
// get merchant keypair // get merchant keypair
let pk_m = &m_data.T; let pk_m = &m_data.T;
let sk_m = &m_data.csk.sk; let sk_m = &m_data.csk.sk;
@ -932,7 +996,7 @@ pub mod bidirectional {
// add specified wpk to make the proof valid // add specified wpk to make the proof valid
// NOTE: if valid, then wpk is indeed the wallet public key for the wallet // NOTE: if valid, then wpk is indeed the wallet public key for the wallet
let new_C = proof_old_cv.C + proof.old_bal_com + (proof.old_com_base * hash_pub_key_to_fr(&proof.wpk)); let new_C = proof_old_cv.C + bal_proof.old_bal_com + (proof.old_com_base * hash_pub_key_to_fr(&proof.wpk));
let new_proof_old_cv = clproto::ProofCV { T: proof_old_cv.T, let new_proof_old_cv = clproto::ProofCV { T: proof_old_cv.T,
C: new_C, C: new_C,
s: proof_old_cv.s.clone(), s: proof_old_cv.s.clone(),
@ -944,7 +1008,7 @@ pub mod bidirectional {
} }
let is_existing_wpk = exist_in_merchant_state(&state, &proof.wpk, None); let is_existing_wpk = exist_in_merchant_state(&state, &proof.wpk, None);
let bal_inc_within_range = proof.balance_inc >= -E_MAX && proof.balance_inc <= E_MAX; let bal_inc_within_range = bal_proof.balance_increment >= -E_MAX && bal_proof.balance_increment <= E_MAX;
// check the range proof of the updated balance // check the range proof of the updated balance
let mut osrng = OsRng::new().unwrap(); let mut osrng = OsRng::new().unwrap();
let mut transcript = ProofTranscript::new(b"BOLT Range Proof"); let mut transcript = ProofTranscript::new(b"BOLT Range Proof");
@ -958,7 +1022,7 @@ pub mod bidirectional {
// check that the proof of valid signature and then // check that the proof of valid signature and then
if proof_vs_old_wallet && !is_existing_wpk && bal_inc_within_range && is_range_proof_valid { if proof_vs_old_wallet && !is_existing_wpk && bal_inc_within_range && is_range_proof_valid {
println!("Proof of knowledge of signature is valid!"); println!("Proof of knowledge of signature is valid!");
if proof.balance_inc < 0 { if bal_proof.balance_increment < 0 {
// negative increment // negative increment
state.R = 1; state.R = 1;
} else { } else {
@ -970,14 +1034,25 @@ pub mod bidirectional {
} }
// now we can verify the proof of knowledge for committed values in new wallet // now we can verify the proof of knowledge for committed values in new wallet
let bal_index = 2; if !proof.bal_proof.third_party {
let mut bal_inc_fr; let bal_inc_fr = -convert_int_to_fr(bal_proof.balance_increment);
bal_inc_fr = -convert_int_to_fr(proof.balance_inc); // check that the PoK on new wallet commitment is valid and
// check that the PoK on new wallet commitment is valid and // the updated balance differs by the balance increment from the balance
// the updated balance differs by the balance increment from the balance // in previous wallet
// in previous wallet let bal_index = 2;
let w_com_pr = proof.w_com_pr_pr + proof.old_bal_com + (proof_old_cv.pub_bases[bal_index] * bal_inc_fr); let w_com_pr = bal_proof.w_com_pr_pr + bal_proof.old_bal_com + (proof_old_cv.pub_bases[bal_index] * bal_inc_fr);
if clproto::bs_verify_nizk_proof(&proof_cv) && (proof_cv.C == w_com_pr) { if proof_cv.C != w_com_pr {
panic!("pay_by_merchant_phase1 - Old and new balance does not differ by payment amount!");
}
} else {
// in third party case, what we do a PoK for committed payment increment
let proof_vcom = proof.bal_proof.proof_vcom.as_ref().unwrap();
if !clproto::bs_verify_nizk_proof(&proof_vcom) {
panic!("pay_by_merchant_phase1 - Could not verify the NIZK PoK of payment amount");
}
}
if clproto::bs_verify_nizk_proof(&proof_cv) {
// generate refund token on new wallet // generate refund token on new wallet
let i = pk_m.Z2.len()-1; let i = pk_m.Z2.len()-1;
let c_refund = proof_cv.C + (pk_m.Z2[i] * convert_str_to_fr("refund")); let c_refund = proof_cv.C + (pk_m.Z2[i] * convert_str_to_fr("refund"));
@ -993,6 +1068,52 @@ pub mod bidirectional {
panic!("pay_by_merchant_phase1 - NIZK verification failed for new wallet commitment!"); panic!("pay_by_merchant_phase1 - NIZK verification failed for new wallet commitment!");
} }
///
/// Verify third party payment proof from two bi-directional channel payments with intermediary
///
pub fn verify_third_party_payment(pp: &PublicParams, fee: i32, proof1: &BalanceProof, proof2: &BalanceProof) -> bool {
if proof1.third_party && proof2.third_party {
let vcom1 = &proof1.proof_vcom.as_ref().unwrap();
let vcom2 = &proof2.proof_vcom.as_ref().unwrap();
let rproof1 = &proof1.proof_vrange.as_ref().unwrap();
let rproof2 = &proof2.proof_vrange.as_ref().unwrap();
let mut osrng1 = OsRng::new().unwrap();
let mut transcript1 = ProofTranscript::new(b"Range Proof for Balance Increment");
let range_proof1_valid = rproof1.range_proof.verify(&[rproof1.value_commitment],
&pp.range_proof_gens,
&mut transcript1,
&mut osrng1,
pp.range_proof_bits).is_ok();
let mut osrng2 = OsRng::new().unwrap();
let mut transcript2 = ProofTranscript::new(b"Range Proof for Balance Increment");
let range_proof2_valid = rproof2.range_proof.verify(&[rproof2.value_commitment],
&pp.range_proof_gens,
&mut transcript2,
&mut osrng2,
pp.range_proof_bits).is_ok();
let len = vcom1.pub_bases.len();
assert!(len >= 2 && vcom1.pub_bases.len() == vcom2.pub_bases.len());
// g^(e1 + -e2 + fee) * h^(r1 + r2) ==> should be equal to g^(fee) * h^(r1 + r2)
// lets add commitments for vcom1 and vcom2 to check
let added_commits = vcom1.C + vcom2.C;
let tx_fee = vcom1.pub_bases[1] * -convert_int_to_fr(fee);
// compute h^r1 + r2
let h_r1_r2 = (vcom1.pub_bases[0] * proof1.vcom.unwrap().r) +
(vcom2.pub_bases[0] * proof2.vcom.unwrap().r) + tx_fee;
let is_pay_plus_fee = added_commits == h_r1_r2;
return clproto::bs_verify_nizk_proof(&vcom1) &&
clproto::bs_verify_nizk_proof(&vcom2) &&
range_proof1_valid && range_proof2_valid &&
is_pay_plus_fee;
}
panic!("verify_third_party_payment - third-party payment not enabled for both proofs");
}
pub fn pay_by_customer_phase2(pp: &PublicParams, old_w: &CustomerWallet, new_w: &CustomerWallet, pub fn pay_by_customer_phase2(pp: &PublicParams, old_w: &CustomerWallet, new_w: &CustomerWallet,
pk_m: &clsigs::PublicKeyD, rt_w: &clsigs::SignatureD) -> RevokeToken { pk_m: &clsigs::PublicKeyD, rt_w: &clsigs::SignatureD) -> RevokeToken {
// (1) verify the refund token (rt_w) against the new wallet contents // (1) verify the refund token (rt_w) against the new wallet contents
@ -1030,7 +1151,7 @@ pub mod bidirectional {
// update merchant state with (wpk, sigma_rev) // update merchant state with (wpk, sigma_rev)
update_merchant_state(&mut state, &proof.wpk, Some(rv.signature)); update_merchant_state(&mut state, &proof.wpk, Some(rv.signature));
let new_wallet_sig = clproto::bs_compute_blind_signature(&pp.cl_mpk, &sk_m, proof_cv.C, proof_cv.num_secrets); let new_wallet_sig = clproto::bs_compute_blind_signature(&pp.cl_mpk, &sk_m, proof_cv.C, proof_cv.num_secrets);
m_data.csk.balance += proof.balance_inc; m_data.csk.balance += proof.bal_proof.balance_increment + state.tx_fee;
state.R = 2; state.R = 2;
return new_wallet_sig; return new_wallet_sig;
} }
@ -1225,6 +1346,7 @@ mod tests {
use super::*; use super::*;
#[test] #[test]
#[ignore] // JAA: REMOVE
fn unidirectional_payment_basics_work() { fn unidirectional_payment_basics_work() {
// TODO: finish me // TODO: finish me
assert!(true == true); assert!(true == true);
@ -1305,7 +1427,7 @@ mod tests {
// let's test the pay protocol // let's test the pay protocol
assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &cust_data.T, &merch_keys.pk, &mut cust_data.csk)); assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &cust_data.T, &merch_keys.pk, &mut cust_data.csk));
let (t_c, new_wallet, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &cust_data.T, // channel token let (t_c, new_wallet, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &channel, &cust_data.T, // channel token
&merch_keys.pk, // merchant pub key &merch_keys.pk, // merchant pub key
&cust_data.csk, // wallet &cust_data.csk, // wallet
payment_increment); // balance increment (FUNC INPUT) payment_increment); // balance increment (FUNC INPUT)
@ -1416,15 +1538,22 @@ mod tests {
assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &cust1_data.T, &merch_keys.pk, &mut cust1_data.csk)); assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &cust1_data.T, &merch_keys.pk, &mut cust1_data.csk));
assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &cust2_data.T, &merch_keys.pk, &mut cust2_data.csk)); assert!(bidirectional::pay_by_customer_phase1_precompute(&pp, &cust2_data.T, &merch_keys.pk, &mut cust2_data.csk));
let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &cust1_data.T, // channel token println!("Channel 1 fee: {}", channel1.get_channel_fee());
let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel1,
&cust1_data.T, // channel token
&merch_keys.pk, // merchant pub key &merch_keys.pk, // merchant pub key
&cust1_data.csk, // wallet &cust1_data.csk, // wallet
payment_increment); // balance increment (FUNC INPUT) payment_increment); // balance increment
println!("Channel 2 fee: {}", channel2.get_channel_fee());
let (t_c2, new_wallet2, pay_proof2) = bidirectional::pay_by_customer_phase1(&pp, &cust2_data.T, // channel token let (t_c2, new_wallet2, pay_proof2) = bidirectional::pay_by_customer_phase1(&pp, &channel2,
&cust2_data.T, // channel token
&merch_keys.pk, // merchant pub key &merch_keys.pk, // merchant pub key
&cust2_data.csk, // wallet &cust2_data.csk, // wallet
-payment_increment); // balance increment (FUNC INPUT) -payment_increment); // balance decrement
// validate pay_proof1 and pay_proof2 (and the channel state for the fee paying channel, if fee > 0)
let tx_fee = channel1.get_channel_fee() + channel2.get_channel_fee();
assert!(bidirectional::verify_third_party_payment(&pp, tx_fee, &pay_proof1.bal_proof, &pay_proof2.bal_proof));
// get the refund token (rt_w) // get the refund token (rt_w)
let rt_w1 = bidirectional::pay_by_merchant_phase1(&pp, channel1, &pay_proof1, &merch1_data); let rt_w1 = bidirectional::pay_by_merchant_phase1(&pp, channel1, &pay_proof1, &merch1_data);
@ -1458,10 +1587,12 @@ mod tests {
let mut channelA = bidirectional::ChannelState::new(String::from("Channel A -> I"), true); let mut channelA = bidirectional::ChannelState::new(String::from("Channel A -> I"), true);
let mut channelB = bidirectional::ChannelState::new(String::from("Channel B -> I"), true); let mut channelB = bidirectional::ChannelState::new(String::from("Channel B -> I"), true);
// let fee = 2;
channelA.set_channel_fee(fee);
let total_payment = 20; let total_payment = 20;
let b0_alice = 20; let b0_alice = 30;
let b0_bob = 20; let b0_bob = 30;
let b0_merchantA = 40; let b0_merchantA = 40;
let b0_merchantB = 40; let b0_merchantB = 40;

View File

@ -48,7 +48,6 @@ pub fn encrypt(key: &SymKey, plaintext: &String) -> SymCT {
pub fn decrypt(key: &SymKey, ciphertext: &SymCT) -> String { pub fn decrypt(key: &SymKey, ciphertext: &SymCT) -> String {
let nonce = ciphertext.nonce; let nonce = ciphertext.nonce;
let pt = secretbox::open(&ciphertext.ciphertext, &nonce, &key.key).unwrap(); let pt = secretbox::open(&ciphertext.ciphertext, &nonce, &key.key).unwrap();
// TODO: investigate better error handling here
let plaintext = String::from_utf8(pt).expect("Found invalid UTF-8"); let plaintext = String::from_utf8(pt).expect("Found invalid UTF-8");
return plaintext; return plaintext;
} }