clean up
This commit is contained in:
parent
3933f4468d
commit
375baafd1b
15
bin/bolt.rs
15
bin/bolt.rs
|
@ -423,7 +423,7 @@ fn main() {
|
|||
//let mut m: Vec<Fr> = Vec::new();
|
||||
let mut C = mpk.g2 * m1[0];
|
||||
for i in 0 .. b {
|
||||
println!("index: {}", i);
|
||||
//println!("index: {}", i);
|
||||
C = C + (m_keypair.pk.Z2[i] * m1[i+1]);
|
||||
}
|
||||
let msg = "Sample Commit output:";
|
||||
|
@ -485,7 +485,7 @@ fn main() {
|
|||
println!("[4] libbolt - generate the initial channel state");
|
||||
let b0_cust = 50;
|
||||
let b0_merch = 50;
|
||||
let mut channel = bidirectional::init_channel("A -> B");
|
||||
let mut channel = bidirectional::init_channel(String::from("A -> B"));
|
||||
let msg = "Open Channel ID: ";
|
||||
libbolt::debug_elem_in_hex(msg, &channel.cid);
|
||||
|
||||
|
@ -522,15 +522,14 @@ fn main() {
|
|||
&init_cust_data.csk, // wallet
|
||||
5); // balance increment
|
||||
|
||||
// TODO: add merchant state (1 -> 2 -> 3, etc) to keep track of where customer is in the pay protocol
|
||||
// get the refund token (rt_w)
|
||||
let rt_w = bidirectional::pay_by_merchant_phase1(&pp, &pay_proof, &init_merch_data);
|
||||
let rt_w = bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof, &init_merch_data);
|
||||
|
||||
// get the revocation token (rv_w) on the old public key (wpk)
|
||||
let rv_w = bidirectional::pay_by_customer_phase2(&pp, &init_cust_data.csk, &new_wallet, &merch_keypair.pk, &rt_w);
|
||||
|
||||
// get the new wallet sig (new_wallet_sig) on the new wallet
|
||||
let new_wallet_sig = bidirectional::pay_by_merchant_phase2(&pp, &pay_proof, &mut init_merch_data, &rv_w);
|
||||
let new_wallet_sig = bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof, &mut init_merch_data, &rv_w);
|
||||
|
||||
assert!(bidirectional::pay_by_customer_final(&pp, &merch_keypair.pk, &mut init_cust_data, new_wallet, new_wallet_sig));
|
||||
|
||||
|
@ -538,5 +537,11 @@ fn main() {
|
|||
let merch_wallet = &init_merch_data.csk;
|
||||
println!("Customer balance: {}", cust_wallet.balance);
|
||||
println!("Merchant balance: {}", merch_wallet.balance);
|
||||
|
||||
println!("Pay protocol complete!");
|
||||
|
||||
|
||||
// bidirectional::update_merchant_state(&mut channel, &pay_proof.wpk, Some(rv_w.signature));
|
||||
// assert!(bidirectional::exist_in_merchant_state(&channel, &pay_proof.wpk, Some(rv_w.signature)));
|
||||
// println!("Stored the pub key and rev token!");
|
||||
}
|
||||
|
|
|
@ -135,7 +135,7 @@ The BOLT privacy guarantees can be summarized as follows:
|
|||
\item The sole exception to rule (3) is when a payment interaction fails or is disputed. In this case, the Merchant learns which channel is associated with the final (failed) payment, but cannot link this channel to any previous payments.
|
||||
\end{itemize}
|
||||
|
||||
In practice this guarantee is sufficient to protect customer identities. Channels are not linked to customer identities (due to the anonymous payment network), and the merchant cannot link any pervious payments to the failed payment or channel.
|
||||
In practice this guarantee is sufficient to protect customer identities. Channels are not linked to customer identities (due to the anonymous payment network), and the merchant cannot link any previous payments to the failed payment or channel.
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% BOLT Design
|
||||
|
@ -697,21 +697,21 @@ BOLT is a payment channel protocol. In order to use BOLT, a Customer and Merchan
|
|||
\paragraph{Pairwise channels.} A standard pairwise BOLT interaction consists of five phases. At a high level they are as follows:
|
||||
|
||||
\begin{enumerate}
|
||||
\item {\bf Channel negotiation.} To initiate an interaction, Customer and Merchant agree on the initial balances of the channel, which we denote by A (customer initial balance) and B (merchant initial balance) respectively. The Merchant provides a public key and signed channel opening transaction to Customer.
|
||||
\item {\bf Channel negotiation.} To initiate an interaction, Customer and Merchant agree on the initial balances of the channel, which we denote by A (customer initial balance) and B (merchant initial balance) respectively. The Merchant provides a public key and signed channel opening transaction to the Customer.
|
||||
|
||||
{\bf Note}: this may or may not be a formal BOLT protocol step, and can be done in various ways. One approach is to have both parties sign a transaction for the underlying currency network. The other is to have both parties do separate transactions on the currency network. We need to figure this out BUT it will be currency specific, so it is the hardest part.
|
||||
%{\bf Note}: this may or may not be a formal BOLT protocol step, and can be done in various ways. One approach is to have both parties sign a transaction for the underlying currency network. The other is to have both parties do separate transactions on the currency network. We need to figure this out BUT it will be currency specific, so it is the hardest part.
|
||||
|
||||
\item {\bf Channel funding.} Customer transmits the channel opening transaction to the currency network, which causes the Customer and Merchant to fund the channel with ({\bf A}, {\bf B}) units of currency respectively. This funding is conducted {\em on-chain}, and should be conducted using a privacy-preserving currency so as to protect the customer's identity.
|
||||
\item {\bf Channel funding.} Customer transmits the channel opening transaction to the currency network, which causes the Customer and Merchant to fund the channel with ({\bf A}, {\bf B}) units of currency respectively. This funding is conducted {\em on-chain}, and should be conducted using a privacy-preserving currency like Zcash so as to protect the customer's identity.
|
||||
|
||||
\item {\bf Channel activation.} Once the channel has been funded and the transaction confirmed on the network, the parties now interact directly to activate the channel and prepare it for online payments.
|
||||
|
||||
\item {\bf Payment.} This step may occur many times. To initiate a payment, the customer initiates an off-chain payment of D units of currency (of positive or negative value) to the merchant. This payment maintains the total channel balance, but updates the Customer and Merchant's ownership of the balances. The merchant does not learn which Customer or Channel was involved in the payment. This produces updated state at each party.
|
||||
\item {\bf Payment.} This step may occur many times. To initiate a payment, the customer initiates an off-chain payment of {\bf D} units of currency (of positive or negative value) to the merchant. This payment maintains the total channel balance, but updates the Customer and Merchant's ownership of the balances. The merchant does not learn which Customer or Channel was involved in the payment. This produces updated state at each party.
|
||||
|
||||
\item {\bf Channel closure.} At the conclusion of a channel interaction, the customer or merchant may initiate the closure of the channel. If the parties dispute the balance of the channel, each party transmits a ``closure token'' to the currency network. The payment network must include logic to evaluate the tokens to determine the correct balances {\bf (A, B)} to pay out to the Customer and Merchant respectively. The parties may now withdraw their shares of the resulting channel.
|
||||
|
||||
\end{enumerate}
|
||||
|
||||
A key design consideration of BOLT is that no party should ever be at risk of losing their funds because the other party has become unresponsive or has submitted invalid information. At each of the above steps, either party may abort and close the channel using the most recent balance information. The cryptocurrency network must enforce a time-delay before releasing funds, in order to ensure that both parties have the opportunity to dispute closure.
|
||||
A key design consideration of BOLT is that no party should ever be at risk of losing their funds because the other party has become unresponsive or has submitted invalid information. At each of the above steps, either party may abort and close the channel using the most recent balance information. The cryptocurrency network must enforce a {\em time-delay before releasing funds}, in order to ensure that both parties have the opportunity to dispute closure.
|
||||
|
||||
We include a discussion of the precise requirements for the cryptocurrency network further below.
|
||||
|
||||
|
|
167
src/lib.rs
167
src/lib.rs
|
@ -623,6 +623,13 @@ pub fn hashPubKeyToFr(wpk: &secp256k1::PublicKey) -> Fr {
|
|||
return Fr::interpret(&hash_buf);
|
||||
}
|
||||
|
||||
pub fn computePubKeyFingerprint(wpk: &secp256k1::PublicKey) -> String {
|
||||
let x_slice = wpk.serialize();
|
||||
let sha2_digest = sha512::hash(&x_slice);
|
||||
let h = format!("{:x}", HexSlice::new(&sha2_digest[0..16]));
|
||||
return h;
|
||||
}
|
||||
|
||||
pub fn hashBufferToFr<'a>(prefix: &'a str, buf: &[u8; 64]) -> Fr {
|
||||
let mut input_buf = Vec::new();
|
||||
input_buf.extend_from_slice(prefix.as_bytes());
|
||||
|
@ -635,15 +642,6 @@ pub fn hashBufferToFr<'a>(prefix: &'a str, buf: &[u8; 64]) -> Fr {
|
|||
return Fr::interpret(&hash_buf);
|
||||
}
|
||||
|
||||
//pub fn hashStrToFr(x: &str) -> Fr {
|
||||
// // TODO: change to serde (instead of rustc_serialize)
|
||||
// let sha2_digest = sha512::hash(x.as_slice());
|
||||
//
|
||||
// let mut hash_buf: [u8; 64] = [0; 64];
|
||||
// hash_buf.copy_from_slice(&sha2_digest[0..64]);
|
||||
// return Fr::interpret(&hash_buf);
|
||||
//}
|
||||
|
||||
fn convertToFr(input_buf: &Vec<u8>) -> Fr {
|
||||
// hash the inputs via SHA256
|
||||
let sha2_digest = sha512::hash(input_buf.as_slice());
|
||||
|
@ -710,14 +708,14 @@ impl<'a> RefundMessage<'a> {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RevokedMessage<'a> {
|
||||
pub msgtype: &'a str,
|
||||
pub struct RevokedMessage {
|
||||
pub msgtype: String,
|
||||
pub wpk: secp256k1::PublicKey,
|
||||
pub sig: Option<Vec<u8>> // represents revocation token serialized compact bytes
|
||||
}
|
||||
|
||||
impl<'a> RevokedMessage<'a> {
|
||||
pub fn new(_msgtype: &'a str, _wpk: secp256k1::PublicKey, _sig: Option<Vec<u8>>) -> RevokedMessage<'a> {
|
||||
impl RevokedMessage {
|
||||
pub fn new(_msgtype: String, _wpk: secp256k1::PublicKey, _sig: Option<Vec<u8>>) -> RevokedMessage {
|
||||
RevokedMessage {
|
||||
msgtype: _msgtype, wpk: _wpk, sig: _sig
|
||||
}
|
||||
|
@ -871,12 +869,14 @@ pub mod bidirectional {
|
|||
use secp256k1; // ::{Secp256k1, PublicKey, SecretKey};
|
||||
use RefundMessage;
|
||||
use RevokedMessage;
|
||||
use HashMap;
|
||||
use hashPubKeyToFr;
|
||||
use hashBufferToFr;
|
||||
use debug_elem_in_hex;
|
||||
use debug_gt_in_hex;
|
||||
use convertToFr;
|
||||
use convertStrToFr;
|
||||
use computePubKeyFingerprint;
|
||||
|
||||
fn print_secret_vector(x: &Vec<Fr>) {
|
||||
for i in 0 .. x.len() {
|
||||
|
@ -934,9 +934,15 @@ pub mod bidirectional {
|
|||
|
||||
// TODO: add method to display contents of the channel state
|
||||
// should include contents of the channel state
|
||||
pub struct ChannelState<'a> {
|
||||
//pub pub_keys: HashMap,
|
||||
pub name: &'a str,
|
||||
pub struct PubKeyMap {
|
||||
wpk: secp256k1::PublicKey,
|
||||
revoke_token: Option<secp256k1::Signature>
|
||||
}
|
||||
|
||||
pub struct ChannelState {
|
||||
keys: HashMap<String, PubKeyMap>,
|
||||
R: i32,
|
||||
pub name: String,
|
||||
pub cid: Fr,
|
||||
pub pay_init: bool,
|
||||
pub channel_established: bool
|
||||
|
@ -947,8 +953,8 @@ pub mod bidirectional {
|
|||
signature: clsigs::SignatureD
|
||||
}
|
||||
|
||||
pub struct ChannelClosure_M<'a> {
|
||||
message: RevokedMessage<'a>,
|
||||
pub struct ChannelClosure_M {
|
||||
message: RevokedMessage,
|
||||
signature: clsigs::SignatureD
|
||||
}
|
||||
|
||||
|
@ -956,15 +962,15 @@ pub mod bidirectional {
|
|||
proof2a: clsigs::ProofCV, // proof of committed values in new wallet
|
||||
proof2b: clsigs::ProofVS, // proof of knowledge of wallet signature
|
||||
// TODO: add proof2c: range proof that balance - balance_inc is between (0, val_max)
|
||||
balance: i32, // balance increment
|
||||
balance_inc: i32, // balance increment
|
||||
w_com: commit_scheme::Commitment, // commitment for new wallet
|
||||
wpk: secp256k1::PublicKey, // verification key for old wallet
|
||||
pub wpk: secp256k1::PublicKey, // verification key for old wallet (TODO:: remove pub)
|
||||
wallet_sig: clsigs::SignatureD // blinded signature for old wallet
|
||||
}
|
||||
|
||||
pub struct RevokeToken<'a> {
|
||||
message: RevokedMessage<'a>,
|
||||
signature: secp256k1::Signature
|
||||
pub struct RevokeToken {
|
||||
message: RevokedMessage,
|
||||
pub signature: secp256k1::Signature
|
||||
}
|
||||
|
||||
pub fn setup() -> PublicParams {
|
||||
|
@ -995,7 +1001,7 @@ pub mod bidirectional {
|
|||
return cm_csp;
|
||||
}
|
||||
|
||||
pub fn init_customer<'a>(pp: &PublicParams, channel: &ChannelState, b0_customer: i32,
|
||||
pub fn init_customer(pp: &PublicParams, channel: &ChannelState, b0_customer: i32,
|
||||
cm_csp: &commit_scheme::CSParams, keypair: &clsigs::KeyPairD) -> InitCustomerData {
|
||||
println!("Run Init customer...");
|
||||
let rng = &mut rand::thread_rng();
|
||||
|
@ -1032,14 +1038,15 @@ pub mod bidirectional {
|
|||
return InitMerchantData { T: keypair.pk.clone(), csk: csk_m, bases: cm_csp.pub_bases };
|
||||
}
|
||||
|
||||
pub fn init_channel<'a>(name: &'a str) -> ChannelState<'a> {
|
||||
pub fn init_channel(name: String) -> ChannelState {
|
||||
let cid = generate_channel_id();
|
||||
// TODO: add hashmap definition to store wpks and optionally store rev tokens?
|
||||
return ChannelState { name: name, cid: cid, channel_established: false, pay_init: false }
|
||||
let keys = HashMap::new(); // will store wpks/revoke_tokens
|
||||
return ChannelState { keys: keys, R: 0, name: name, cid: cid, channel_established: false, pay_init: false }
|
||||
}
|
||||
|
||||
//// begin of establish channel protocol
|
||||
pub fn establish_customer_phase1(pp: &PublicParams, c_data: &InitCustomerData, m_data: &InitMerchantData) -> clsigs::ProofCV {
|
||||
pub fn establish_customer_phase1(pp: &PublicParams, c_data: &InitCustomerData,
|
||||
m_data: &InitMerchantData) -> clsigs::ProofCV {
|
||||
println!("Run establish_customer algorithm...");
|
||||
// obtain customer init data
|
||||
let t_c = &c_data.T;
|
||||
|
@ -1071,7 +1078,8 @@ pub mod bidirectional {
|
|||
return wallet_sig;
|
||||
}
|
||||
|
||||
pub fn establish_customer_final(pp: &PublicParams, pk_m: &clsigs::PublicKeyD, w: &mut CustomerWallet, sig: clsigs::SignatureD) -> bool {
|
||||
pub fn establish_customer_final(pp: &PublicParams, pk_m: &clsigs::PublicKeyD,
|
||||
w: &mut CustomerWallet, sig: clsigs::SignatureD) -> bool {
|
||||
if w.signature.is_none() {
|
||||
let mut x: Vec<Fr> = Vec::new();
|
||||
x.push(w.r.clone());
|
||||
|
@ -1094,7 +1102,7 @@ pub mod bidirectional {
|
|||
|
||||
///// begin of pay protocol
|
||||
pub fn pay_by_customer_phase1(pp: &PublicParams, T: &ChannelToken, pk_m: &clsigs::PublicKeyD,
|
||||
old_w: &CustomerWallet, balance_increment: i32) -> (CustomerWallet, PaymentProof) {
|
||||
old_w: &CustomerWallet, balance_increment: i32) -> (CustomerWallet, PaymentProof) {
|
||||
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
|
||||
let rng = &mut rand::thread_rng();
|
||||
|
@ -1122,6 +1130,10 @@ pub mod bidirectional {
|
|||
let old_balance = Fr::from_str(bal.to_string().as_str()).unwrap();
|
||||
// convert balance into Fr (B - e)
|
||||
let updated_balance = bal - balance_increment;
|
||||
if (updated_balance < 0) {
|
||||
panic!("pay_by_customer_phase1 - insufficient funds to make payment!");
|
||||
}
|
||||
|
||||
let updated_balance_pr = Fr::from_str(updated_balance.to_string().as_str()).unwrap();
|
||||
|
||||
let mut new_wallet_sec: Vec<Fr> = Vec::new();
|
||||
|
@ -1159,7 +1171,7 @@ pub mod bidirectional {
|
|||
proof2a: proof_cv, // proof of knowledge for committed values
|
||||
proof2b: proof_vs, // proof of knowledge of signature on old wallet
|
||||
w_com: w_com,
|
||||
balance: balance_increment, // epsilon - increment/decrement
|
||||
balance_inc: balance_increment, // epsilon - increment/decrement
|
||||
//w_com_pr: w_com_pr, // old commitment minus wpk
|
||||
wpk: old_wpk.clone(), // showing public key for old wallet
|
||||
wallet_sig: blind_sigs // blinded signature for old wallet
|
||||
|
@ -1174,7 +1186,8 @@ pub mod bidirectional {
|
|||
// NOTE regarding balance increments
|
||||
// a positive increment => increment merchant balance, and decrement customer balance
|
||||
// a negative increment => decrement merchant balance, and increment customer balance
|
||||
pub fn pay_by_merchant_phase1(pp: &PublicParams, proof: &PaymentProof, m_data: &InitMerchantData) -> clsigs::SignatureD {
|
||||
pub fn pay_by_merchant_phase1(pp: &PublicParams, mut state: &mut ChannelState, proof: &PaymentProof,
|
||||
m_data: &InitMerchantData) -> clsigs::SignatureD {
|
||||
println!("Run pay algorithm by Merchant - phase 2");
|
||||
let blind_sigs = &proof.wallet_sig;
|
||||
let proof_cv = &proof.proof2a;
|
||||
|
@ -1185,11 +1198,18 @@ pub mod bidirectional {
|
|||
|
||||
// let's first confirm that proof of knowledge of signature on old wallet is valid
|
||||
let proof_vs_old_wallet = clsigs::vs_verify_blind_sig(&pp.cl_mpk, &pk_m, &proof_vs, &blind_sigs);
|
||||
if proof_vs_old_wallet {
|
||||
println!("Yay! Proof of knowledge of signature is valid!");
|
||||
|
||||
let is_existing_wpk = exist_in_merchant_state(&state, &proof.wpk, None);
|
||||
if proof_vs_old_wallet && !is_existing_wpk {
|
||||
println!("Proof of knowledge of signature is valid!");
|
||||
if (proof.balance_inc < 0) {
|
||||
// negative increment
|
||||
state.R = 1;
|
||||
} else {
|
||||
// postiive increment
|
||||
state.R = -1; // -1 denotes \bot here
|
||||
}
|
||||
} else {
|
||||
panic!("FAILURE! Verification failure for old wallet signature !");
|
||||
panic!("pay_by_merchant_phase1 - Verification failure for old wallet signature !");
|
||||
}
|
||||
|
||||
// verify the proof of knowledge for committed values in new wallet
|
||||
|
@ -1199,19 +1219,17 @@ pub mod bidirectional {
|
|||
let c_refund = proof_cv.C + (pk_m.Z2[i] * convertStrToFr("refund"));
|
||||
// generating partially blind signature on refund || wpk' || B - e
|
||||
let rt_w = clsigs::bs_compute_blind_signature(&pp.cl_mpk, &sk_m, c_refund, proof_cv.num_secrets + 1); // proof_cv.C
|
||||
println!("Yay! Proof of knowledge of commitment on new wallet is valid");
|
||||
println!("pay_by_merchant_phase1 - Proof of knowledge of commitment on new wallet is valid");
|
||||
update_merchant_state(&mut state, &proof.wpk, None);
|
||||
return rt_w;
|
||||
}
|
||||
|
||||
// generate signature for new wallet with updated balance
|
||||
|
||||
// let's update the merchant's wallet balance now
|
||||
panic!("Failed verification!");
|
||||
panic!("pay_by_merchant_phase1 - NIZK verification failed for new wallet commitment!");
|
||||
}
|
||||
|
||||
pub fn pay_by_customer_phase2<'a>(pp: &PublicParams, old_w: &CustomerWallet, new_w: &CustomerWallet,
|
||||
pk_m: &clsigs::PublicKeyD, rt_w: &clsigs::SignatureD) -> RevokeToken<'a> {
|
||||
|
||||
pub fn pay_by_customer_phase2(pp: &PublicParams, old_w: &CustomerWallet, new_w: &CustomerWallet,
|
||||
pk_m: &clsigs::PublicKeyD, rt_w: &clsigs::SignatureD) -> RevokeToken {
|
||||
// (1) verify the refund token (rt_w) against the new wallet contents
|
||||
let mut x: Vec<Fr> = Vec::new();
|
||||
x.push(new_w.r.clone());
|
||||
|
@ -1225,32 +1243,36 @@ pub mod bidirectional {
|
|||
if (is_rt_w_valid) {
|
||||
println!("Refund token is valid against the new wallet!");
|
||||
let mut schnorr = secp256k1::Secp256k1::new();
|
||||
let rm = RevokedMessage::new("revoked", old_w.wpk, None);
|
||||
let rm = RevokedMessage::new(String::from("revoked"), old_w.wpk, None);
|
||||
let msg = secp256k1::Message::from_slice(&rm.hash_to_slice()).unwrap();
|
||||
// msg = "revoked"|| old_wpk (for old wallet)
|
||||
let rv_w = schnorr.sign(&msg, &old_w.wsk);
|
||||
|
||||
// return the revocation token
|
||||
return RevokeToken { message: rm, signature: rv_w.unwrap() };
|
||||
}
|
||||
panic!("FAIL: Merchant did not provide a valid refund token!");
|
||||
panic!("pay_by_customer_phase2 - Merchant did not provide a valid refund token!");
|
||||
}
|
||||
|
||||
pub fn pay_by_merchant_phase2(pp: &PublicParams, proof: &PaymentProof, m_data: &mut InitMerchantData, rv: &RevokeToken) -> clsigs::SignatureD {
|
||||
pub fn pay_by_merchant_phase2(pp: &PublicParams, mut state: &mut ChannelState,
|
||||
proof: &PaymentProof, m_data: &mut InitMerchantData,
|
||||
rv: &RevokeToken) -> clsigs::SignatureD {
|
||||
let proof_cv = &proof.proof2a;
|
||||
let sk_m = &m_data.csk.sk;
|
||||
let schnorr = secp256k1::Secp256k1::new();
|
||||
let msg = secp256k1::Message::from_slice(&rv.message.hash_to_slice()).unwrap();
|
||||
// verify that the revocation token is valid
|
||||
let is_rv_valid = schnorr.verify(&msg, &rv.signature, &proof.wpk).is_ok();
|
||||
// TODO: check that we are in the proper state
|
||||
|
||||
if clsigs::bs_verify_nizk_proof(&proof_cv) && is_rv_valid {
|
||||
// update merchant state with (wpk, sigma_rev)
|
||||
update_merchant_state(&mut state, &proof.wpk, Some(rv.signature));
|
||||
let new_wallet_sig = clsigs::bs_compute_blind_signature(&pp.cl_mpk, &sk_m, proof_cv.C, proof_cv.num_secrets);
|
||||
m_data.csk.balance += proof.balance;
|
||||
m_data.csk.balance += proof.balance_inc;
|
||||
state.R = 2;
|
||||
return new_wallet_sig;
|
||||
}
|
||||
|
||||
panic!("FAIL: Customer did not provide valid revocation token!");
|
||||
panic!("pay_by_merchant_phase2 - Customer did not provide valid revocation token!");
|
||||
}
|
||||
|
||||
pub fn pay_by_customer_final(pp: &PublicParams, pk_m: &clsigs::PublicKeyD,
|
||||
|
@ -1298,38 +1320,61 @@ pub mod bidirectional {
|
|||
return ChannelClosure_C { message: m, signature: sigma };
|
||||
}
|
||||
|
||||
fn exist_in_merchant_state(s: &ChannelState, wpk: &secp256k1::PublicKey, sig_rev: &clsigs::SignatureD) -> bool {
|
||||
// TODO: check the database for the fingerprint for the wpk + sig?
|
||||
return true;
|
||||
fn exist_in_merchant_state(state: &ChannelState, wpk: &secp256k1::PublicKey, rev: Option<secp256k1::Signature>) -> bool {
|
||||
if (state.keys.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let fingerprint = computePubKeyFingerprint(wpk);
|
||||
if (state.keys.contains_key(&fingerprint)) {
|
||||
let pub_key = state.keys.get(&fingerprint).unwrap();
|
||||
if pub_key.revoke_token.is_none() {
|
||||
// let's just check the public key
|
||||
return (pub_key.wpk == *wpk);
|
||||
}
|
||||
if (!rev.is_none()) {
|
||||
return (pub_key.wpk == *wpk && pub_key.revoke_token.unwrap() == rev.unwrap());
|
||||
}
|
||||
return (pub_key.wpk == *wpk);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
fn update_merchant_state(s: &mut ChannelState, wpk: &secp256k1::PublicKey) -> bool {
|
||||
// TODO: implement this method to update channel state db with current public key hash?
|
||||
fn update_merchant_state(state: &mut ChannelState, wpk: &secp256k1::PublicKey, rev: Option<secp256k1::Signature>) -> bool {
|
||||
let fingerprint = computePubKeyFingerprint(wpk);
|
||||
//println!("Print fingerprint: {}", fingerprint);
|
||||
if !rev.is_none() {
|
||||
let cust_pub_key = PubKeyMap { wpk: wpk.clone(), revoke_token: Some(rev.unwrap().clone()) };
|
||||
state.keys.insert(fingerprint, cust_pub_key);
|
||||
} else {
|
||||
let cust_pub_key = PubKeyMap { wpk: wpk.clone(), revoke_token: None };
|
||||
state.keys.insert(fingerprint, cust_pub_key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// for merchant => on input the merchant's current state S_old and a customer channel closure message,
|
||||
// outputs a merchant channel closure message rc_m and updated merchant state S_new
|
||||
pub fn merchant_refute<'a>(pp: &PublicParams, T_c: &ChannelToken, m_data: &InitMerchantData,
|
||||
state: &mut ChannelState, rc_c: ChannelClosure_C<'a>) -> Option<ChannelClosure_M<'a>> {
|
||||
state: &mut ChannelState, rc_c: ChannelClosure_C<'a>, rv_token: &secp256k1::Signature) -> Option<ChannelClosure_M> {
|
||||
println!("Run Refute...");
|
||||
|
||||
let is_valid = clsigs::verifyD(&pp.cl_mpk, &T_c.pk, &rc_c.message.hash(), &rc_c.signature);
|
||||
if is_valid {
|
||||
let wpk = rc_c.message.wpk;
|
||||
let rv_token = rc_c.signature; // TODO: change to \sigma_rev
|
||||
let balance = rc_c.message.balance;
|
||||
if exist_in_merchant_state(&state, &wpk, &rv_token) {
|
||||
if exist_in_merchant_state(&state, &wpk, Some(*rv_token)) {
|
||||
// let mut s = Secp256k1::new();
|
||||
// let sig = rv_token.serialize_compact(&s);
|
||||
// TODO: convert rv_w into a slice
|
||||
let rm = RevokedMessage::new("revoked", wpk, None);
|
||||
let rm = RevokedMessage::new(String::from("revoked"), wpk, None);
|
||||
// sign the revoked message
|
||||
let signature = clsigs::signD(&pp.cl_mpk, &m_data.csk.sk, &rm.hash());
|
||||
return Some(ChannelClosure_M { message: rm, signature: signature });
|
||||
} else {
|
||||
// update state to include the user's wallet key
|
||||
assert!(update_merchant_state(state, &wpk));
|
||||
assert!(update_merchant_state(state, &wpk, Some(*rv_token)));
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
|
@ -1340,7 +1385,7 @@ pub mod bidirectional {
|
|||
// on input th ecustmomer and merchant channel tokens T_c, T_m
|
||||
// along with closure messages rc_c, rc_m
|
||||
pub fn resolve<'a>(pp: &PublicParams, c: &InitCustomerData, m: &InitMerchantData, // cust and merch
|
||||
rc_c: Option<ChannelClosure_C<'a>>, rc_m: Option<ChannelClosure_M<'a>>) -> (i32, i32) {
|
||||
rc_c: Option<ChannelClosure_C<'a>>, rc_m: Option<ChannelClosure_M>) -> (i32, i32) {
|
||||
println!("Run Resolve...");
|
||||
let total_balance = c.csk.balance + m.csk.balance;
|
||||
if (rc_c.is_none() && rc_m.is_none()) {
|
||||
|
|
Loading…
Reference in New Issue