new libbolt interface with fixes and improvements to internal state management
This commit is contained in:
parent
2cd297ce00
commit
1c91cf03fe
140
README.md
140
README.md
|
@ -80,121 +80,111 @@ A bidirectional payment channel enables two parties to exchange arbitrary positi
|
||||||
|
|
||||||
### Channel Setup and Key Generation
|
### Channel Setup and Key Generation
|
||||||
|
|
||||||
The first part of setting up bi-directional payment channels involve generating initial setup parameters, channel state and key generation for both parties.
|
The first part of setting up bi-directional payment channels involve generating initial setup parameters using curve BLS12-381 with channel state.
|
||||||
|
|
||||||
use bolt::bidirectional;
|
use bolt::bidirectional;
|
||||||
|
|
||||||
// setup bidirectional scheme params
|
|
||||||
let pp = bidirectional::setup(true);
|
|
||||||
|
|
||||||
// generate the initial channel state
|
// generate the initial channel state
|
||||||
// second argument represents third-party mode
|
// second argument represents third-party mode
|
||||||
let mut channel = bidirectional::ChannelState::new(String::from("My New 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();
|
||||||
To generate keys for both parties, call the `bidirectional::keygen()` routine with the public parameters as input.
|
|
||||||
|
// generate fresh public parameters
|
||||||
// merchant generates a long-lived key pair
|
channel_state.setup(&mut rng);
|
||||||
let m_keypair = bidirectional::keygen(&pp);
|
|
||||||
|
|
||||||
// customer generates an ephemeral keypair for use on a single channel
|
|
||||||
let c_keypair = bidirectional::keygen(&pp);
|
|
||||||
|
|
||||||
### Initialization
|
### Initialization
|
||||||
|
|
||||||
To initialize the channel for both parties, do the following:
|
To initialize wallet/keys for both parties, call the ``bidirectional::init_merchant()`` and ``bidirectional::init_customer()``:
|
||||||
|
|
||||||
let b0_merch = 10;
|
let b0_merch = 10;
|
||||||
let b0_cust = 100;
|
let b0_cust = 100;
|
||||||
// initialize on the merchant side with balance, b0_merch
|
|
||||||
let mut m_data = bidirectional::init_merchant(&pp, b0_merch, &m_keypair));
|
// initialize the merchant wallet and initialize with balance
|
||||||
|
let (mut channel_token, mut merch_wallet) = bidirectional::init_merchant(rng, &mut channel_state, "Bob");
|
||||||
// generate the public params for the commitment scheme
|
|
||||||
let cm_csp = bidirectional::generate_commit_setup(&pp, &m_keypair.pk);
|
// initialize the balance for merch_wallet
|
||||||
|
merch_wallet.init_balance(b0_merch);
|
||||||
// initialize on the customer side with balance, b0_cust
|
|
||||||
let mut c_data = bidirectional::init_customer(&pp, // public params
|
// generate the customer wallet using the channel token from the merchant
|
||||||
&channel, // channel state
|
let mut cust_wallet = bidirectional::init_customer(rng, // rng
|
||||||
|
&mut channel_state, // channel state
|
||||||
|
&mut channel_token, // channel token
|
||||||
b0_cust, // init customer balance
|
b0_cust, // init customer balance
|
||||||
b0_merch, // init merchant balance
|
b0_merch, // init merchant balance
|
||||||
&cm_csp, // commitment pub params
|
"Alice")); // channel name/purpose
|
||||||
&c_keypair)); // customer keypair
|
|
||||||
|
|
||||||
|
|
||||||
### Establish Protocol
|
### Establish Protocol
|
||||||
|
|
||||||
When opening a payment channel, execute the establishment protocol API to escrow funds privately as follows:
|
When opening a payment channel, execute the establishment protocol API to escrow funds privately as follows:
|
||||||
|
|
||||||
// entering the establish protocol for the channel
|
// establish the channel by generating initial wallet commitment proof
|
||||||
let proof1 = bidirectional::establish_customer_phase1(&pp, &c_data, &m_data.bases);
|
let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_wallet);
|
||||||
|
|
||||||
// obtain the wallet signature from the merchant
|
// obtain close token for closing out channel
|
||||||
let w_sig = bidirectional::establish_merchant_phase2(&pp, &mut channel, &m_data, &proof1));
|
let close_token = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_wallet);
|
||||||
|
|
||||||
// complete channel establishment");
|
// customer verifies that close-token
|
||||||
assert!(bidirectional::establish_customer_final(&pp, &m_keypair.pk, &mut c_data.csk, w_sig));
|
assert!(cust_wallet.verify_close_token(&channel_state, &close_token));
|
||||||
|
|
||||||
|
// form funding tx and wait for network confirmation
|
||||||
|
|
||||||
|
// obtain payment token after confirming funding tx
|
||||||
|
let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_wallet);
|
||||||
|
|
||||||
|
// customer
|
||||||
|
assert!(bidirectional::establish_final(&mut channel_state, &mut cust_wallet, &pay_token));
|
||||||
|
|
||||||
// confirm that the channel state is now established
|
// confirm that the channel state is now established
|
||||||
assert!(channel.channel_established);
|
assert!(channel_state.channel_established);
|
||||||
|
|
||||||
### Pay protocol
|
### Pay protocol
|
||||||
|
|
||||||
To spend on the channel, execute the pay protocol API (can be executed as many times as necessary):
|
To spend on the channel, execute the pay protocol API (can be executed as many times as necessary):
|
||||||
|
|
||||||
// precomputation phase that customer does offline prior to a spend
|
|
||||||
bidirectional::pay_by_customer_phase1_precompute(&pp, &c_data.channel_token, &m_keypair.pk, &mut c_data.csk);
|
|
||||||
|
|
||||||
// generate new channel token, new wallet and payment proof
|
|
||||||
// send the payment proof to the merchant
|
|
||||||
let (t_c, new_w, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &channel,
|
|
||||||
&c_data.channel_token, // channel token
|
|
||||||
&m_keypair.pk, // merchant verification key
|
|
||||||
&c_data.csk, // current wallet
|
|
||||||
5); // balance increment
|
|
||||||
|
|
||||||
// get the refund token (rt_w) from the merchant
|
|
||||||
let rt_w = bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof, &m_data));
|
|
||||||
|
|
||||||
// generate the revocation token (rv_w) on the old public key (wpk)
|
|
||||||
let rv_w = bidirectional::pay_by_customer_phase2(&pp, &c_data.csk, &new_w, &m_keypair.pk, &rt_w));
|
|
||||||
|
|
||||||
// get the signature on the new wallet from merchant
|
|
||||||
let new_w_sig = bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof, &mut m_data, &rv_w));
|
|
||||||
|
|
||||||
// complete the final step of pay protocol - verify merchant signature on wallet
|
|
||||||
assert!(bidirectional::pay_by_customer_final(&pp, &m_keypair.pk, &mut c_data, t_c, new_w, new_w_sig));
|
|
||||||
|
|
||||||
### Channel Closure Algorithms
|
// phase 1 - payment proof and new cust wallet
|
||||||
|
let (payment, new_cust_wallet) = bidirectional::generate_payment(rng, &channel_state, &cust_wallet, 10);
|
||||||
|
|
||||||
|
// phase 1 - merchant verifies the payment proof and returns a close-token
|
||||||
|
let new_close_token = bidirectional::verify_payment(rng, &channel_state, &payment, &mut merch_wallet);
|
||||||
|
|
||||||
|
// phase 2 - verify the close-token, update cust wallet and generate a revoke token for previous cust wallet state
|
||||||
|
let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_wallet, new_cust_wallet, &new_close_token);
|
||||||
|
|
||||||
|
// phase 2 - merchant verifies the revoke token and sends back the pay-token in response
|
||||||
|
let new_pay_token = bidirectional::verify_revoke_token(&revoke_token, &mut merch_wallet);
|
||||||
|
|
||||||
|
// final - customer verifies the pay token and updates internal state
|
||||||
|
assert!(cust_wallet.verify_pay_token(&channel_state, &new_pay_token));
|
||||||
|
|
||||||
|
|
||||||
|
### Channel Closure Algorithms (TODO)
|
||||||
|
|
||||||
To close a channel, the customer must execute the `bidirectional::customer_refund()` routine as follows:
|
To close a channel, the customer must execute the `bidirectional::customer_refund()` routine as follows:
|
||||||
|
|
||||||
let cust_wallet = &c_data.csk;
|
let cust_close = bidirectional::customer_refund(&channel_state, &cust_wallet);
|
||||||
let rc_c = bidirectional::customer_refund(&pp, &channel, &m_keypair.pk, &cust_wallet);
|
|
||||||
|
|
||||||
The merchant can dispute a customer's claim by executing the `bidirectional::merchant_retute()` routine as follows:
|
The merchant can dispute a customer's claim by executing the `bidirectional::merchant_retute()` routine as follows:
|
||||||
|
|
||||||
let channel_token = &c_data.channel_token;
|
let merch_close = bidirectional::merchant_refute(&mut channel_state, &channel_token, &cust_close, &rv_w.signature);
|
||||||
let rc_m = bidirectional::merchant_refute(&pp, &mut channel, &channel_token, &m_data, &rc_c, &rv_w.signature);
|
|
||||||
|
|
||||||
|
|
||||||
To resolve a dispute between a customer and a merchant, the following routine is executed by the network:
|
To resolve a dispute between a customer and a merchant, the following routine is executed by the network:
|
||||||
|
|
||||||
let (new_b0_cust, new_b0_merch) = bidirectional::resolve(&pp, &c_data, &m_data,
|
let (new_b0_cust, new_b0_merch) = bidirectional::resolve(&c_data, &m_data,
|
||||||
Some(rc_c), Some(rc_m), Some(rt_w));
|
Some(rc_c), Some(rc_m), Some(rt_w));
|
||||||
|
|
||||||
`new_b0_cust` and `new_b0_merch` represent the new balances for the customer and merchant (respectively).
|
`new_b0_cust` and `new_b0_merch` represent the new balances for the customer and merchant (respectively).
|
||||||
|
|
||||||
## Third-party Payments
|
## Third-party Payments (TODO)
|
||||||
|
|
||||||
The bidirectional payment channels can be used to construct third-party payments in which a party **A** pays a second party **B** through an untrusted intermediary (**I**) to which both **A** and **B** have already established a channel. With BOLT, the intermediary learns nothing about the payment from **A** to **B** and cannot link transactions to individual users.
|
The bidirectional payment channels can be used to construct third-party payments in which a party **A** pays a second party **B** through an untrusted intermediary (**I**) to which both **A** and **B** have already established a channel. With BOLT, the intermediary learns nothing about the payment from **A** to **B** and cannot link transactions to individual users.
|
||||||
|
|
||||||
To enable third-party payment support, initialize each payment channel as follows:
|
To enable third-party payment support, initialize each payment channel as follows:
|
||||||
|
|
||||||
|
|
||||||
let pp = bidirectional::setup(true);
|
|
||||||
|
|
||||||
// create the channel state for each channel and indicate third-party support
|
// create the channel state for each channel and indicate third-party support
|
||||||
let mut channel_a = bidirectional::ChannelState::new(String::from("Channel A <-> I"), true);
|
let mut channel_a = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A <-> I"), true);
|
||||||
let mut channel_b = bidirectional::ChannelState::new(String::from("Channel B <-> I"), true);
|
let mut channel_b = bidirectional::ChannelState::<Bls12>::new(String::from("Channel B <-> I"), true);
|
||||||
|
|
||||||
Moreover, the intermediary can set a channel fee as follows:
|
Moreover, the intermediary can set a channel fee as follows:
|
||||||
|
|
||||||
|
@ -207,13 +197,13 @@ The channel establishment still works as described before and the pay protocol i
|
||||||
|
|
||||||
let payment_amount = 20;
|
let payment_amount = 20;
|
||||||
// get payment proof on first channel with party A (and I)
|
// get payment proof on first channel with party A (and I)
|
||||||
let (t_c1, new_w1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel_a,
|
let (t_c1, new_w1, pay_proof1) = bidirectional::pay_by_customer_phase1(&channel_a,
|
||||||
&c1_data.channel_token, // channel token
|
&c1_data.channel_token, // channel token
|
||||||
&merch_keys.pk, // merchant pub key
|
&merch_keys.pk, // merchant pub key
|
||||||
&c1_data.csk, // wallet
|
&c1_data.csk, // wallet
|
||||||
payment_amount); // bal inc
|
payment_amount); // bal inc
|
||||||
// get payment proof on second channel with party B (and I)
|
// get payment proof on second channel with party B (and I)
|
||||||
let (t_c2, new_w2, pay_proof2) = bidirectional::pay_by_customer_phase1(&pp, &channel2,
|
let (t_c2, new_w2, pay_proof2) = bidirectional::pay_by_customer_phase1(&channel2,
|
||||||
&c2_data.channel_token, // channel token
|
&c2_data.channel_token, // channel token
|
||||||
&m_keys.pk, // merchant pub key
|
&m_keys.pk, // merchant pub key
|
||||||
&c2_data.csk, // wallet
|
&c2_data.csk, // wallet
|
||||||
|
@ -227,7 +217,7 @@ The channel establishment still works as described before and the pay protocol i
|
||||||
|
|
||||||
See the `third_party_payment_basics_work()` unit test in `src/lib.rs` for more details.
|
See the `third_party_payment_basics_work()` unit test in `src/lib.rs` for more details.
|
||||||
|
|
||||||
# Documentation
|
# Documentation (TODO)
|
||||||
|
|
||||||
Build the api documentation by simply running `make doc`. Documentation will be generated in your local `target/doc` directory.
|
Build the api documentation by simply running `make doc`. Documentation will be generated in your local `target/doc` directory.
|
||||||
|
|
||||||
|
|
|
@ -36,144 +36,148 @@ macro_rules! measure_ret_mut {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("******************************************");
|
println!("Hello world!");
|
||||||
// libbolt tests below
|
|
||||||
println!("Testing the channel setup...");
|
|
||||||
|
|
||||||
//println!("[1a] libbolt - setup bidirectional scheme params");
|
|
||||||
let (pp, setup_time1) = measure!(bidirectional::setup(false));
|
|
||||||
|
|
||||||
//println!("[1b] libbolt - generate the initial channel state");
|
|
||||||
let mut channel = bidirectional::ChannelState::new(String::from("My New Channel A"), false);
|
|
||||||
|
|
||||||
println!("Setup time: {}", setup_time1);
|
|
||||||
|
|
||||||
//let msg = "Open Channel ID: ";
|
|
||||||
//libbolt::debug_elem_in_hex(msg, &channel.cid);
|
|
||||||
|
|
||||||
let b0_cust = 50;
|
|
||||||
let b0_merch = 50;
|
|
||||||
|
|
||||||
// generate long-lived keypair for merchant -- used to identify
|
|
||||||
// it to all customers
|
|
||||||
//println!("[2] libbolt - generate long-lived key pair for merchant");
|
|
||||||
let (merch_keypair, _) = measure!(bidirectional::keygen(&pp));
|
|
||||||
|
|
||||||
// customer generates an ephemeral keypair for use on a single channel
|
|
||||||
println!("[3] libbolt - generate ephemeral key pair for customer (use with one channel)");
|
|
||||||
let (cust_keypair, _) = measure!(bidirectional::keygen(&pp));
|
|
||||||
|
|
||||||
// each party executes the init algorithm on the agreed initial challenge balance
|
|
||||||
// in order to derive the channel tokens
|
|
||||||
println!("[5a] libbolt - initialize on the merchant side with balance {}", b0_merch);
|
|
||||||
let (mut merch_data, initm_time) = measure_ret_mut!(bidirectional::init_merchant(&pp, b0_merch, &merch_keypair));
|
|
||||||
println!(">> TIME for init_merchant: {}", initm_time);
|
|
||||||
|
|
||||||
println!("[5b] libbolt - initialize on the customer side with balance {}", b0_cust);
|
|
||||||
let cm_csp = bidirectional::generate_commit_setup(&pp, &merch_keypair.pk);
|
|
||||||
let (mut cust_data, initc_time) = measure_ret_mut!(bidirectional::init_customer(&pp, &mut channel, b0_cust, b0_merch, &cm_csp, &cust_keypair));
|
|
||||||
println!(">> TIME for init_customer: {}", initc_time);
|
|
||||||
println!("******************************************");
|
|
||||||
// libbolt tests below
|
|
||||||
println!("Testing the establish protocol...");
|
|
||||||
|
|
||||||
println!("[6a] libbolt - entering the establish protocol for the channel");
|
|
||||||
let (proof1, est_cust_time1) = measure!(bidirectional::establish_customer_phase1(&pp, &cust_data, &merch_data.bases));
|
|
||||||
println!(">> TIME for establish_customer_phase1: {}", est_cust_time1);
|
|
||||||
|
|
||||||
println!("[6b] libbolt - obtain the wallet signature from the merchant");
|
|
||||||
let (wallet_sig, est_merch_time2) = measure!(bidirectional::establish_merchant_phase2(&pp, &mut channel, &merch_data, &proof1));
|
|
||||||
println!(">> TIME for establish_merchant_phase2: {}", est_merch_time2);
|
|
||||||
|
|
||||||
println!("[6c] libbolt - complete channel establishment");
|
|
||||||
assert!(bidirectional::establish_customer_final(&pp, &merch_keypair.pk, &mut cust_data.csk, wallet_sig));
|
|
||||||
|
|
||||||
assert!(channel.channel_established);
|
|
||||||
|
|
||||||
println!("Channel has been established!");
|
|
||||||
println!("******************************************");
|
|
||||||
|
|
||||||
println!("Testing the pay protocol...");
|
|
||||||
// let's test the pay protocol
|
|
||||||
bidirectional::pay_by_customer_phase1_precompute(&pp, &cust_data.channel_token, &merch_keypair.pk, &mut cust_data.csk);
|
|
||||||
let s = PreciseTime::now();
|
|
||||||
let (t_c, new_wallet, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &channel, &cust_data.channel_token, // channel token
|
|
||||||
&merch_keypair.pk, // merchant pub key
|
|
||||||
&cust_data.csk, // wallet
|
|
||||||
5); // balance increment
|
|
||||||
let e = PreciseTime::now();
|
|
||||||
println!(">> TIME for pay_by_customer_phase1: {}", s.to(e));
|
|
||||||
|
|
||||||
// get the refund token (rt_w)
|
|
||||||
let (rt_w, pay_merch_time1) = measure!(bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof, &merch_data));
|
|
||||||
println!(">> TIME for pay_by_merchant_phase1: {}", pay_merch_time1);
|
|
||||||
|
|
||||||
// get the revocation token (rv_w) on the old public key (wpk)
|
|
||||||
let (rv_w, pay_cust_time2) = measure!(bidirectional::pay_by_customer_phase2(&pp, &cust_data.csk, &new_wallet, &merch_keypair.pk, &rt_w));
|
|
||||||
println!(">> TIME for pay_by_customer_phase2: {}", pay_cust_time2);
|
|
||||||
|
|
||||||
// get the new wallet sig (new_wallet_sig) on the new wallet
|
|
||||||
let (new_wallet_sig, pay_merch_time2) = measure!(bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof, &mut merch_data, &rv_w));
|
|
||||||
println!(">> TIME for pay_by_merchant_phase2: {}", pay_merch_time2);
|
|
||||||
|
|
||||||
assert!(bidirectional::pay_by_customer_final(&pp, &merch_keypair.pk, &mut cust_data, t_c, new_wallet, rt_w, new_wallet_sig));
|
|
||||||
|
|
||||||
{
|
|
||||||
// scope localizes the immutable borrow here (for debug purposes only)
|
|
||||||
let cust_wallet = &cust_data.csk;
|
|
||||||
let merch_wallet = &merch_data.csk;
|
|
||||||
println!("Customer balance: {}", cust_wallet.balance);
|
|
||||||
println!("Merchant balance: {}", merch_wallet.balance);
|
|
||||||
}
|
|
||||||
|
|
||||||
bidirectional::pay_by_customer_phase1_precompute(&pp, &cust_data.channel_token, &merch_keypair.pk, &mut cust_data.csk);
|
|
||||||
let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel, &cust_data.channel_token, // channel token
|
|
||||||
&merch_keypair.pk, // merchant pub key
|
|
||||||
&cust_data.csk, // wallet
|
|
||||||
-10); // balance increment
|
|
||||||
|
|
||||||
// get the refund token (rt_w)
|
|
||||||
let rt_w1 = bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof1, &merch_data);
|
|
||||||
|
|
||||||
// get the revocation token (rv_w) on the old public key (wpk)
|
|
||||||
let rv_w1 = bidirectional::pay_by_customer_phase2(&pp, &cust_data.csk, &new_wallet1, &merch_keypair.pk, &rt_w1);
|
|
||||||
|
|
||||||
// get the new wallet sig (new_wallet_sig) on the new wallet
|
|
||||||
let new_wallet_sig1 = bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof1, &mut merch_data, &rv_w1);
|
|
||||||
|
|
||||||
assert!(bidirectional::pay_by_customer_final(&pp, &merch_keypair.pk, &mut cust_data, t_c1, new_wallet1, rt_w1, new_wallet_sig1));
|
|
||||||
|
|
||||||
{
|
|
||||||
let cust_wallet = &cust_data.csk;
|
|
||||||
let merch_wallet = &merch_data.csk;
|
|
||||||
println!("Updated balances...");
|
|
||||||
println!("Customer balance: {}", cust_wallet.balance);
|
|
||||||
println!("Merchant balance: {}", merch_wallet.balance);
|
|
||||||
let updated_cust_bal = b0_cust + 5;
|
|
||||||
let updated_merch_bal = b0_merch - 5;
|
|
||||||
assert_eq!(updated_cust_bal, cust_wallet.balance);
|
|
||||||
assert_eq!(updated_merch_bal, merch_wallet.balance);
|
|
||||||
}
|
|
||||||
println!("Pay protocol complete!");
|
|
||||||
|
|
||||||
println!("******************************************");
|
|
||||||
println!("Testing the dispute algorithms...");
|
|
||||||
|
|
||||||
{
|
|
||||||
let cust_wallet = &cust_data.csk;
|
|
||||||
// get channel closure message
|
|
||||||
let rc_c = bidirectional::customer_refund(&pp, &channel, &merch_keypair.pk, &cust_wallet);
|
|
||||||
println!("Obtained the channel closure message: {}", rc_c.message.msgtype);
|
|
||||||
|
|
||||||
let channel_token = &cust_data.channel_token;
|
|
||||||
let rc_m = bidirectional::merchant_refute(&pp, &mut channel, &channel_token, &merch_data, &rc_c, &rv_w1.signature);
|
|
||||||
println!("Merchant has refuted the refund request!");
|
|
||||||
|
|
||||||
let (new_b0_cust, new_b0_merch) = bidirectional::resolve(&pp, &cust_data, &merch_data,
|
|
||||||
Some(rc_c), Some(rc_m));
|
|
||||||
println!("Resolved! Customer = {}, Merchant = {}", new_b0_cust, new_b0_merch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: add tests for customer/merchant cheating scenarios
|
|
||||||
println!("******************************************");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//fn main() {
|
||||||
|
// println!("******************************************");
|
||||||
|
// // libbolt tests below
|
||||||
|
// println!("Testing the channel setup...");
|
||||||
|
//
|
||||||
|
// //println!("[1a] libbolt - setup bidirectional scheme params");
|
||||||
|
// let (pp, setup_time1) = measure!(bidirectional::setup(false));
|
||||||
|
//
|
||||||
|
// //println!("[1b] libbolt - generate the initial channel state");
|
||||||
|
// let mut channel = bidirectional::ChannelState::new(String::from("My New Channel A"), false);
|
||||||
|
//
|
||||||
|
// println!("Setup time: {}", setup_time1);
|
||||||
|
//
|
||||||
|
// //let msg = "Open Channel ID: ";
|
||||||
|
// //libbolt::debug_elem_in_hex(msg, &channel.cid);
|
||||||
|
//
|
||||||
|
// let b0_cust = 50;
|
||||||
|
// let b0_merch = 50;
|
||||||
|
//
|
||||||
|
// // generate long-lived keypair for merchant -- used to identify
|
||||||
|
// // it to all customers
|
||||||
|
// //println!("[2] libbolt - generate long-lived key pair for merchant");
|
||||||
|
// let (merch_keypair, _) = measure!(bidirectional::keygen(&pp));
|
||||||
|
//
|
||||||
|
// // customer generates an ephemeral keypair for use on a single channel
|
||||||
|
// println!("[3] libbolt - generate ephemeral key pair for customer (use with one channel)");
|
||||||
|
// let (cust_keypair, _) = measure!(bidirectional::keygen(&pp));
|
||||||
|
//
|
||||||
|
// // each party executes the init algorithm on the agreed initial challenge balance
|
||||||
|
// // in order to derive the channel tokens
|
||||||
|
// println!("[5a] libbolt - initialize on the merchant side with balance {}", b0_merch);
|
||||||
|
// let (mut merch_data, initm_time) = measure_ret_mut!(bidirectional::init_merchant(&pp, b0_merch, &merch_keypair));
|
||||||
|
// println!(">> TIME for init_merchant: {}", initm_time);
|
||||||
|
//
|
||||||
|
// println!("[5b] libbolt - initialize on the customer side with balance {}", b0_cust);
|
||||||
|
// let cm_csp = bidirectional::generate_commit_setup(&pp, &merch_keypair.pk);
|
||||||
|
// let (mut cust_data, initc_time) = measure_ret_mut!(bidirectional::init_customer(&pp, &mut channel, b0_cust, b0_merch, &cm_csp, &cust_keypair));
|
||||||
|
// println!(">> TIME for init_customer: {}", initc_time);
|
||||||
|
// println!("******************************************");
|
||||||
|
// // libbolt tests below
|
||||||
|
// println!("Testing the establish protocol...");
|
||||||
|
//
|
||||||
|
// println!("[6a] libbolt - entering the establish protocol for the channel");
|
||||||
|
// let (proof1, est_cust_time1) = measure!(bidirectional::establish_customer_phase1(&pp, &cust_data, &merch_data.bases));
|
||||||
|
// println!(">> TIME for establish_customer_phase1: {}", est_cust_time1);
|
||||||
|
//
|
||||||
|
// println!("[6b] libbolt - obtain the wallet signature from the merchant");
|
||||||
|
// let (wallet_sig, est_merch_time2) = measure!(bidirectional::establish_merchant_phase2(&pp, &mut channel, &merch_data, &proof1));
|
||||||
|
// println!(">> TIME for establish_merchant_phase2: {}", est_merch_time2);
|
||||||
|
//
|
||||||
|
// println!("[6c] libbolt - complete channel establishment");
|
||||||
|
// assert!(bidirectional::establish_customer_final(&pp, &merch_keypair.pk, &mut cust_data.csk, wallet_sig));
|
||||||
|
//
|
||||||
|
// assert!(channel.channel_established);
|
||||||
|
//
|
||||||
|
// println!("Channel has been established!");
|
||||||
|
// println!("******************************************");
|
||||||
|
//
|
||||||
|
// println!("Testing the pay protocol...");
|
||||||
|
// // let's test the pay protocol
|
||||||
|
// bidirectional::pay_by_customer_phase1_precompute(&pp, &cust_data.channel_token, &merch_keypair.pk, &mut cust_data.csk);
|
||||||
|
// let s = PreciseTime::now();
|
||||||
|
// let (t_c, new_wallet, pay_proof) = bidirectional::pay_by_customer_phase1(&pp, &channel, &cust_data.channel_token, // channel token
|
||||||
|
// &merch_keypair.pk, // merchant pub key
|
||||||
|
// &cust_data.csk, // wallet
|
||||||
|
// 5); // balance increment
|
||||||
|
// let e = PreciseTime::now();
|
||||||
|
// println!(">> TIME for pay_by_customer_phase1: {}", s.to(e));
|
||||||
|
//
|
||||||
|
// // get the refund token (rt_w)
|
||||||
|
// let (rt_w, pay_merch_time1) = measure!(bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof, &merch_data));
|
||||||
|
// println!(">> TIME for pay_by_merchant_phase1: {}", pay_merch_time1);
|
||||||
|
//
|
||||||
|
// // get the revocation token (rv_w) on the old public key (wpk)
|
||||||
|
// let (rv_w, pay_cust_time2) = measure!(bidirectional::pay_by_customer_phase2(&pp, &cust_data.csk, &new_wallet, &merch_keypair.pk, &rt_w));
|
||||||
|
// println!(">> TIME for pay_by_customer_phase2: {}", pay_cust_time2);
|
||||||
|
//
|
||||||
|
// // get the new wallet sig (new_wallet_sig) on the new wallet
|
||||||
|
// let (new_wallet_sig, pay_merch_time2) = measure!(bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof, &mut merch_data, &rv_w));
|
||||||
|
// println!(">> TIME for pay_by_merchant_phase2: {}", pay_merch_time2);
|
||||||
|
//
|
||||||
|
// assert!(bidirectional::pay_by_customer_final(&pp, &merch_keypair.pk, &mut cust_data, t_c, new_wallet, rt_w, new_wallet_sig));
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// // scope localizes the immutable borrow here (for debug purposes only)
|
||||||
|
// let cust_wallet = &cust_data.csk;
|
||||||
|
// let merch_wallet = &merch_data.csk;
|
||||||
|
// println!("Customer balance: {}", cust_wallet.balance);
|
||||||
|
// println!("Merchant balance: {}", merch_wallet.balance);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// bidirectional::pay_by_customer_phase1_precompute(&pp, &cust_data.channel_token, &merch_keypair.pk, &mut cust_data.csk);
|
||||||
|
// let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel, &cust_data.channel_token, // channel token
|
||||||
|
// &merch_keypair.pk, // merchant pub key
|
||||||
|
// &cust_data.csk, // wallet
|
||||||
|
// -10); // balance increment
|
||||||
|
//
|
||||||
|
// // get the refund token (rt_w)
|
||||||
|
// let rt_w1 = bidirectional::pay_by_merchant_phase1(&pp, &mut channel, &pay_proof1, &merch_data);
|
||||||
|
//
|
||||||
|
// // get the revocation token (rv_w) on the old public key (wpk)
|
||||||
|
// let rv_w1 = bidirectional::pay_by_customer_phase2(&pp, &cust_data.csk, &new_wallet1, &merch_keypair.pk, &rt_w1);
|
||||||
|
//
|
||||||
|
// // get the new wallet sig (new_wallet_sig) on the new wallet
|
||||||
|
// let new_wallet_sig1 = bidirectional::pay_by_merchant_phase2(&pp, &mut channel, &pay_proof1, &mut merch_data, &rv_w1);
|
||||||
|
//
|
||||||
|
// assert!(bidirectional::pay_by_customer_final(&pp, &merch_keypair.pk, &mut cust_data, t_c1, new_wallet1, rt_w1, new_wallet_sig1));
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let cust_wallet = &cust_data.csk;
|
||||||
|
// let merch_wallet = &merch_data.csk;
|
||||||
|
// println!("Updated balances...");
|
||||||
|
// println!("Customer balance: {}", cust_wallet.balance);
|
||||||
|
// println!("Merchant balance: {}", merch_wallet.balance);
|
||||||
|
// let updated_cust_bal = b0_cust + 5;
|
||||||
|
// let updated_merch_bal = b0_merch - 5;
|
||||||
|
// assert_eq!(updated_cust_bal, cust_wallet.balance);
|
||||||
|
// assert_eq!(updated_merch_bal, merch_wallet.balance);
|
||||||
|
// }
|
||||||
|
// println!("Pay protocol complete!");
|
||||||
|
//
|
||||||
|
// println!("******************************************");
|
||||||
|
// println!("Testing the dispute algorithms...");
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// let cust_wallet = &cust_data.csk;
|
||||||
|
// // get channel closure message
|
||||||
|
// let rc_c = bidirectional::customer_refund(&pp, &channel, &merch_keypair.pk, &cust_wallet);
|
||||||
|
// println!("Obtained the channel closure message: {}", rc_c.message.msgtype);
|
||||||
|
//
|
||||||
|
// let channel_token = &cust_data.channel_token;
|
||||||
|
// let rc_m = bidirectional::merchant_refute(&pp, &mut channel, &channel_token, &merch_data, &rc_c, &rv_w1.signature);
|
||||||
|
// println!("Merchant has refuted the refund request!");
|
||||||
|
//
|
||||||
|
// let (new_b0_cust, new_b0_merch) = bidirectional::resolve(&pp, &cust_data, &merch_data,
|
||||||
|
// Some(rc_c), Some(rc_m));
|
||||||
|
// println!("Resolved! Customer = {}, Merchant = {}", new_b0_cust, new_b0_merch);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // TODO: add tests for customer/merchant cheating scenarios
|
||||||
|
// println!("******************************************");
|
||||||
|
//}
|
||||||
|
|
|
@ -15,7 +15,7 @@ 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};
|
use ped92::{CSParams, Commitment, CSMultiParams};
|
||||||
use util::{hash_pubkey_to_fr, convert_int_to_fr, hash_to_fr, CommitmentProof};
|
use util::{hash_pubkey_to_fr, convert_int_to_fr, hash_to_fr, CommitmentProof, RevokedMessage};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
@ -26,9 +26,9 @@ use nizk::{NIZKPublicParams, Proof};
|
||||||
use wallet::Wallet;
|
use wallet::Wallet;
|
||||||
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
#[derive(Clone, Serialize, Deserialize)]
|
||||||
struct PubKeyMap {
|
pub struct PubKeyMap {
|
||||||
wpk: secp256k1::PublicKey,
|
pub wpk: secp256k1::PublicKey,
|
||||||
revoke_token: Option<secp256k1::Signature>
|
pub revoke_token: Option<secp256k1::Signature>
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[derive(Clone, Serialize, Deserialize)]
|
//#[derive(Clone, Serialize, Deserialize)]
|
||||||
|
@ -43,7 +43,6 @@ pub struct ChannelParams<E: Engine> {
|
||||||
//#[derive(Clone, Serialize, Deserialize)]
|
//#[derive(Clone, Serialize, Deserialize)]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ChannelState<E: Engine> {
|
pub struct ChannelState<E: Engine> {
|
||||||
keys: HashMap<String, PubKeyMap>,
|
|
||||||
R: i32,
|
R: i32,
|
||||||
tx_fee: i32,
|
tx_fee: i32,
|
||||||
pub cp: Option<ChannelParams<E>>,
|
pub cp: Option<ChannelParams<E>>,
|
||||||
|
@ -82,7 +81,6 @@ 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 {
|
||||||
keys: HashMap::new(), // store wpks/revoke_tokens
|
|
||||||
R: 0,
|
R: 0,
|
||||||
tx_fee: 0,
|
tx_fee: 0,
|
||||||
cp: None,
|
cp: None,
|
||||||
|
@ -143,6 +141,7 @@ struct WalletKeyPair {
|
||||||
/// Customer wallet consists of a keypair (NEW)
|
/// Customer wallet consists of a keypair (NEW)
|
||||||
///
|
///
|
||||||
pub struct CustomerWallet<E: Engine> {
|
pub struct CustomerWallet<E: Engine> {
|
||||||
|
pub name: String,
|
||||||
pub pk_c: secp256k1::PublicKey,
|
pub pk_c: secp256k1::PublicKey,
|
||||||
sk_c: secp256k1::SecretKey,
|
sk_c: secp256k1::SecretKey,
|
||||||
cust_balance: i32, //
|
cust_balance: i32, //
|
||||||
|
@ -159,7 +158,7 @@ pub struct CustomerWallet<E: Engine> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> CustomerWallet<E> {
|
impl<E: Engine> CustomerWallet<E> {
|
||||||
pub fn new<R: Rng>(csprng: &mut R, channel: &mut ChannelState<E>, channel_token: &mut ChannelToken<E>, cust_bal: i32, merch_bal: i32) -> Self {
|
pub fn new<R: Rng>(csprng: &mut R, channel: &mut ChannelState<E>, channel_token: &mut ChannelToken<E>, cust_bal: i32, merch_bal: i32, name: String) -> Self {
|
||||||
assert!(!channel_token.is_init());
|
assert!(!channel_token.is_init());
|
||||||
let mut kp = secp256k1::Secp256k1::new();
|
let mut kp = secp256k1::Secp256k1::new();
|
||||||
kp.randomize(csprng);
|
kp.randomize(csprng);
|
||||||
|
@ -192,6 +191,7 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
|
|
||||||
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 {
|
||||||
|
name: name,
|
||||||
pk_c: pk_c,
|
pk_c: pk_c,
|
||||||
sk_c: sk_c,
|
sk_c: sk_c,
|
||||||
cust_balance: cust_bal,
|
cust_balance: cust_bal,
|
||||||
|
@ -209,7 +209,7 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate nizk proof of knowledge of commitment opening
|
// generate nizk proof of knowledge of commitment opening
|
||||||
pub fn generate_proof<R: Rng>(&mut self, csprng: &mut R, channel_token: &ChannelToken<E>) -> CommitmentProof<E> {
|
pub fn generate_proof<R: Rng>(&self, csprng: &mut R, channel_token: &ChannelToken<E>) -> CommitmentProof<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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,6 +218,7 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
let close_wallet = self.wallet.with_close(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();
|
||||||
|
//println!("verify_close_token - Wallet: {}", &self.wallet);
|
||||||
|
|
||||||
let is_close_valid = cp.pub_params.keypair.verify(&mpk, &close_wallet, &self.r, &close_token);
|
let is_close_valid = cp.pub_params.keypair.verify(&mpk, &close_wallet, &self.r, &close_token);
|
||||||
if is_close_valid {
|
if is_close_valid {
|
||||||
|
@ -232,14 +233,16 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("Channel establish - Verification failed for close token!");
|
panic!("Customer - Verification failed for close token!");
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
// 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();
|
||||||
let wallet = self.wallet.as_fr_vec();
|
// we don't want to include "close" prefix here (even if it is set)
|
||||||
|
let wallet = self.wallet.without_close();
|
||||||
|
//println!("verify_pay_token - Wallet: {}", &self.wallet);
|
||||||
|
|
||||||
let is_pay_valid = cp.pub_params.keypair.verify(&mpk, &wallet, &self.r, &pay_token);
|
let is_pay_valid = cp.pub_params.keypair.verify(&mpk, &wallet, &self.r, &pay_token);
|
||||||
if is_pay_valid {
|
if is_pay_valid {
|
||||||
|
@ -253,11 +256,18 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
return is_valid;
|
return is_valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("verify_pay_token - Channel establish - Verification failed for pay token!") ;
|
panic!("Customer - Verification failed for pay token!");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_tokens(&self) -> bool {
|
||||||
|
let index = self.index - 1;
|
||||||
|
let is_ct = self.close_tokens.get(&index).is_some();
|
||||||
|
let is_pt = self.pay_tokens.get(&index).is_some();
|
||||||
|
return is_ct && is_pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for channel pay
|
// 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>) {
|
pub fn generate_payment<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, amount: i32) -> (Proof<E>, Commitment<E>, secp256k1::PublicKey, CustomerWallet<E>) {
|
||||||
// 1 - chooose new wpk/wsk pair
|
// 1 - chooose new wpk/wsk pair
|
||||||
let mut kp = secp256k1::Secp256k1::new();
|
let mut kp = secp256k1::Secp256k1::new();
|
||||||
kp.randomize(csprng);
|
kp.randomize(csprng);
|
||||||
|
@ -269,26 +279,47 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
let new_merch_bal = self.merch_balance + amount;
|
let new_merch_bal = self.merch_balance + amount;
|
||||||
let new_r = E::Fr::rand(csprng);
|
let new_r = E::Fr::rand(csprng);
|
||||||
|
|
||||||
println!("old wallet close => {}", self.wallet.close.unwrap());
|
//println!("old wallet close => {}", self.wallet.close.unwrap());
|
||||||
|
|
||||||
let cp = channel.cp.as_ref().unwrap();
|
let cp = channel.cp.as_ref().unwrap();
|
||||||
let old_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: self.wallet.wpk.clone(), bc: self.cust_balance, bm: self.merch_balance, close: None };
|
let old_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: self.wallet.wpk.clone(), bc: self.cust_balance, bm: self.merch_balance, close: None };
|
||||||
let new_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: wpk_h, bc: new_cust_bal, bm: new_merch_bal, close: Some(self.wallet.close.unwrap()) };
|
let new_wallet = Wallet { pkc: self.wallet.pkc.clone(), wpk: wpk_h, bc: new_cust_bal, bm: new_merch_bal, close: Some(self.wallet.close.unwrap()) };
|
||||||
let new_wcom = cp.pub_params.comParams.commit(&new_wallet.as_fr_vec(), &new_r);
|
let new_wcom = cp.pub_params.comParams.commit(&new_wallet.as_fr_vec(), &new_r);
|
||||||
|
|
||||||
|
// turn this into a isolated test to make sure we are handling transition between close/pay tokens
|
||||||
|
// println!("<==============================>");
|
||||||
|
// println!("new wcom: {}", new_wcom);
|
||||||
|
//
|
||||||
|
// let new_wcom_pay= cp.pub_params.comParams.commit(&new_wallet.without_close(), &new_r);
|
||||||
|
// println!("new pay com: {}", new_wcom_pay);
|
||||||
|
// println!("<==============================>");
|
||||||
|
//
|
||||||
|
// let x = hash_to_fr::<E>(String::from("close").into_bytes() );
|
||||||
|
// let ext_new_wcom = cp.pub_params.comParams.extend_commit(&new_wcom_pay, &x);
|
||||||
|
// assert!( ext_new_wcom.c == new_wcom.c );
|
||||||
|
//
|
||||||
|
// // remove
|
||||||
|
// let rm_close_new_wcom = cp.pub_params.comParams.remove_commit(&ext_new_wcom, &x);
|
||||||
|
// println!("removed close from ext new wcom: {}", rm_close_new_wcom);
|
||||||
|
// assert!( rm_close_new_wcom.c == new_wcom_pay.c );
|
||||||
|
//
|
||||||
|
// panic!("they are all equal!");
|
||||||
|
|
||||||
|
|
||||||
// 3 - generate new blinded and randomized pay token
|
// 3 - generate new blinded and randomized pay token
|
||||||
let i = self.index - 1;
|
let i = self.index - 1;
|
||||||
let mut prev_pay_token = self.pay_tokens.get(&i).unwrap();
|
let mut prev_pay_token = self.pay_tokens.get(&i).unwrap();
|
||||||
|
|
||||||
println!("OLD {}", &self.wallet);
|
// println!("OLD {}", &self.wallet);
|
||||||
println!("NEW {}", &new_wallet);
|
// println!("NEW {}", &new_wallet);
|
||||||
println!("{}", &prev_pay_token);
|
// println!("{}", &prev_pay_token);
|
||||||
|
|
||||||
let pay_proof = cp.pub_params.prove(csprng, self.r.clone(), old_wallet, new_wallet.clone(),
|
let pay_proof = cp.pub_params.prove(csprng, self.r.clone(), old_wallet, new_wallet.clone(),
|
||||||
new_wcom.clone(), new_r, &prev_pay_token);
|
new_wcom.clone(), new_r, &prev_pay_token);
|
||||||
|
|
||||||
// update internal state after proof has been verified by remote
|
// update internal state after proof has been verified by remote
|
||||||
let new_cw = CustomerWallet {
|
let new_cw = CustomerWallet {
|
||||||
|
name: self.name.clone(),
|
||||||
pk_c: self.pk_c.clone(),
|
pk_c: self.pk_c.clone(),
|
||||||
sk_c: self.sk_c.clone(),
|
sk_c: self.sk_c.clone(),
|
||||||
cust_balance: new_cust_bal,
|
cust_balance: new_cust_bal,
|
||||||
|
@ -310,6 +341,7 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
// update the internal state of the customer wallet
|
// update the internal state of the customer wallet
|
||||||
pub fn update(&mut self, new_wallet: CustomerWallet<E>) -> bool {
|
pub fn update(&mut self, new_wallet: CustomerWallet<E>) -> bool {
|
||||||
// update everything except for the wpk/wsk pair
|
// update everything except for the wpk/wsk pair
|
||||||
|
assert!(self.name == new_wallet.name);
|
||||||
self.cust_balance = new_wallet.cust_balance;
|
self.cust_balance = new_wallet.cust_balance;
|
||||||
self.merch_balance = new_wallet.merch_balance;
|
self.merch_balance = new_wallet.merch_balance;
|
||||||
self.r = new_wallet.r;
|
self.r = new_wallet.r;
|
||||||
|
@ -330,7 +362,7 @@ impl<E: Engine> CustomerWallet<E> {
|
||||||
let old_wallet = self.old_kp.unwrap();
|
let old_wallet = self.old_kp.unwrap();
|
||||||
// proceed with generating the close token
|
// proceed with generating the close token
|
||||||
let secp = secp256k1::Secp256k1::new();
|
let secp = secp256k1::Secp256k1::new();
|
||||||
let rm = RevokedMessage::new(String::from("revoked"), old_wallet.wpk, None);
|
let mut rm = RevokedMessage::new(String::from("revoked"), old_wallet.wpk, None);
|
||||||
let revoke_msg = secp256k1::Message::from_slice(&rm.hash_to_slice()).unwrap();
|
let revoke_msg = secp256k1::Message::from_slice(&rm.hash_to_slice()).unwrap();
|
||||||
// msg = "revoked"|| old wsk (for old wallet)
|
// msg = "revoked"|| old wsk (for old wallet)
|
||||||
let revoke_token = secp.sign(&revoke_msg, &old_wallet.wsk);
|
let revoke_token = secp.sign(&revoke_msg, &old_wallet.wsk);
|
||||||
|
@ -363,7 +395,9 @@ pub struct MerchantWallet<E: Engine> {
|
||||||
balance: i32,
|
balance: i32,
|
||||||
pk: secp256k1::PublicKey, // pk_m
|
pk: secp256k1::PublicKey, // pk_m
|
||||||
sk: secp256k1::SecretKey, // sk_m
|
sk: secp256k1::SecretKey, // sk_m
|
||||||
comParams: CSMultiParams<E>
|
comParams: CSMultiParams<E>,
|
||||||
|
pub keys: HashMap<String, PubKeyMap>,
|
||||||
|
pub pay_tokens: HashMap<String, cl::Signature<E>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: Engine> MerchantWallet<E> {
|
impl<E: Engine> MerchantWallet<E> {
|
||||||
|
@ -379,7 +413,9 @@ impl<E: Engine> MerchantWallet<E> {
|
||||||
balance: 0,
|
balance: 0,
|
||||||
pk: wpk,
|
pk: wpk,
|
||||||
sk: wsk,
|
sk: wsk,
|
||||||
comParams: cp.pub_params.comParams.clone()
|
comParams: cp.pub_params.comParams.clone(),
|
||||||
|
keys: HashMap::new(), // store wpks/revoke_tokens
|
||||||
|
pay_tokens: HashMap::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,19 +429,31 @@ impl<E: Engine> MerchantWallet<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn issue_close_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, extend: bool) -> Signature<E> {
|
pub fn init_balance(&mut self, balance: i32) {
|
||||||
|
// set by the escrow/funding transactionf for the channel
|
||||||
|
self.balance = balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
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()
|
||||||
};
|
};
|
||||||
|
//println!("com for close-token: {}", &close_com);
|
||||||
return self.keypair.sign_blind(csprng, &cp.pub_params.mpk, close_com);
|
return self.keypair.sign_blind(csprng, &cp.pub_params.mpk, close_com);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn issue_pay_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>) -> 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");
|
||||||
return self.keypair.sign_blind(csprng, &cp.pub_params.mpk, com.clone());
|
let x = hash_to_fr::<E>(String::from("close").into_bytes() );
|
||||||
|
let pay_com = match remove_close {
|
||||||
|
true => self.comParams.remove_commit(com, &x),
|
||||||
|
false => com.clone()
|
||||||
|
};
|
||||||
|
//println!("com for pay-token: {}", &pay_com);
|
||||||
|
return self.keypair.sign_blind(csprng, &cp.pub_params.mpk, pay_com);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_proof<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, com: &Commitment<E>, com_proof: &CommitmentProof<E>) -> (Signature<E>, Signature<E>) {
|
pub fn verify_proof<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, com: &Commitment<E>, com_proof: &CommitmentProof<E>) -> (Signature<E>, Signature<E>) {
|
||||||
|
@ -414,35 +462,50 @@ impl<E: Engine> MerchantWallet<E> {
|
||||||
if is_valid {
|
if is_valid {
|
||||||
println!("Commitment PoK is valid!");
|
println!("Commitment PoK is valid!");
|
||||||
let close_token = self.issue_close_token(csprng, cp, com, true);
|
let close_token = self.issue_close_token(csprng, cp, com, true);
|
||||||
let pay_token = self.issue_pay_token(csprng, cp, com);
|
let pay_token = self.issue_pay_token(csprng, cp, com, false);
|
||||||
return (close_token, pay_token);
|
return (close_token, pay_token);
|
||||||
}
|
}
|
||||||
panic!("verify_proof - Failed to verify PoK of commitment opening");
|
panic!("verify_proof - Failed to verify PoK of commitment opening");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_payment<R: Rng>(&self, csprng: &mut R, channel: &ChannelState<E>, proof: &Proof<E>, com: &Commitment<E>, wpk: &secp256k1::PublicKey, amount: i32) -> (Signature<E>, Signature<E>) {
|
fn store_wpk_with_token(&mut self, wpk: &secp256k1::PublicKey, pay_token: Signature<E>) {
|
||||||
|
// compute fingerprint on wpk
|
||||||
|
let wpk_str = util::compute_pub_key_fingerprint(&wpk);
|
||||||
|
self.pay_tokens.insert(wpk_str, pay_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_pay_token(&self, wpk: &secp256k1::PublicKey) -> Signature<E> {
|
||||||
|
let wpk_str = util::compute_pub_key_fingerprint(&wpk);
|
||||||
|
return self.pay_tokens.get(&wpk_str).unwrap().clone();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify_payment<R: Rng>(&mut self, csprng: &mut R, channel: &ChannelState<E>, proof: &Proof<E>, com: &Commitment<E>, wpk: &secp256k1::PublicKey, amount: i32) -> Signature<E> {
|
||||||
let cp = channel.cp.as_ref().unwrap();
|
let cp = channel.cp.as_ref().unwrap();
|
||||||
let pay_proof = proof.clone();
|
let pay_proof = proof.clone();
|
||||||
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
let prev_wpk = hash_pubkey_to_fr::<E>(&wpk);
|
||||||
let epsilon = E::Fr::from_str(&amount.to_string()).unwrap();
|
let epsilon = E::Fr::from_str(&amount.to_string()).unwrap();
|
||||||
|
|
||||||
if cp.pub_params.verify(pay_proof, epsilon, com, prev_wpk) {
|
if cp.pub_params.verify(pay_proof, epsilon, com, prev_wpk) {
|
||||||
|
// 1 - proceed with generating close and pay token
|
||||||
// 1 - proceed with generating close 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);
|
let pay_token = self.issue_pay_token(csprng, cp, com, true);
|
||||||
return (close_token, pay_token);
|
// let's store the pay token with the wpk for now
|
||||||
|
self.store_wpk_with_token(wpk, pay_token);
|
||||||
|
return close_token;
|
||||||
}
|
}
|
||||||
|
|
||||||
panic!("verify_payment - Failed to validate NIZK PoK for payment.");
|
panic!("verify_payment - Failed to validate NIZK PoK for payment.");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_revoke_token(&self, revoke_token: &secp256k1::Signature, revoke_msg: &RevokedMessage, wpk: &secp256k1::PublicKey) -> bool {
|
pub fn verify_revoke_token(&self, revoke_token: &secp256k1::Signature, revoke_msg: &RevokedMessage, wpk: &secp256k1::PublicKey) -> Signature<E> {
|
||||||
let secp = secp256k1::Secp256k1::new();
|
let secp = secp256k1::Secp256k1::new();
|
||||||
let msg = secp256k1::Message::from_slice(&revoke_msg.hash_to_slice()).unwrap();
|
let msg = secp256k1::Message::from_slice(&revoke_msg.hash_to_slice()).unwrap();
|
||||||
// verify that the revocation token is valid
|
// verify that the revocation token is valid
|
||||||
return secp.verify(&msg, revoke_token, wpk).is_ok();
|
if secp.verify(&msg, revoke_token, wpk).is_ok() {
|
||||||
|
return self.get_pay_token(wpk);
|
||||||
|
}
|
||||||
|
panic!("verify_revoke_token - Failed to verify the revoke token for wpk!");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -456,7 +519,6 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn channel_util_works() {
|
fn channel_util_works() {
|
||||||
println!("Initializing channels...");
|
|
||||||
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();
|
||||||
|
|
||||||
|
@ -475,7 +537,7 @@ mod tests {
|
||||||
|
|
||||||
// retrieve commitment setup params (using merchant long lived pk params)
|
// retrieve commitment setup params (using merchant long lived pk params)
|
||||||
// initialize on the customer side with balance: b0_cust
|
// initialize on the customer side with balance: b0_cust
|
||||||
let mut cust_wallet = CustomerWallet::<Bls12>::new(rng, &mut channel, &mut channel_token, b0_cust, b0_merch);
|
let mut cust_wallet = CustomerWallet::<Bls12>::new(rng, &mut channel, &mut channel_token, b0_cust, b0_merch, String::from("Alice"));
|
||||||
|
|
||||||
// lets establish the channel
|
// lets establish the channel
|
||||||
let cust_com_proof = cust_wallet.generate_proof(rng, &mut channel_token);
|
let cust_com_proof = cust_wallet.generate_proof(rng, &mut channel_token);
|
||||||
|
@ -483,40 +545,43 @@ mod tests {
|
||||||
// first return the close token, then wait for escrow-tx confirmation
|
// first return the close token, then wait for escrow-tx confirmation
|
||||||
// then send the pay-token after confirmation
|
// then send the pay-token after confirmation
|
||||||
let (close_token, pay_token) = merch_wallet.verify_proof(rng, &channel, &cust_wallet.w_com, &cust_com_proof);
|
let (close_token, pay_token) = merch_wallet.verify_proof(rng, &channel, &cust_wallet.w_com, &cust_com_proof);
|
||||||
|
|
||||||
// unblind tokens and verify signatures
|
// unblind tokens and verify signatures
|
||||||
assert!(cust_wallet.verify_pay_token(&channel, &pay_token));
|
|
||||||
|
|
||||||
assert!(cust_wallet.verify_close_token(&channel, &close_token));
|
assert!(cust_wallet.verify_close_token(&channel, &close_token));
|
||||||
|
|
||||||
|
assert!(cust_wallet.verify_pay_token(&channel, &pay_token));
|
||||||
|
|
||||||
println!("Done!");
|
println!("Done!");
|
||||||
|
|
||||||
// pay protocol tests
|
// pay protocol tests
|
||||||
let amount = 10;
|
let amount = 10;
|
||||||
let (pay_proof, new_com, old_wpk, new_cw) = cust_wallet.generate_payment(rng, &channel, amount);
|
let (pay_proof, new_com, old_wpk, new_cw) = cust_wallet.generate_payment(rng, &channel, amount);
|
||||||
|
|
||||||
println!("{}", new_com);
|
// println!("{}", new_com);
|
||||||
println!("wpk => {}", old_wpk);
|
// println!("wpk => {}", old_wpk);
|
||||||
println!("{}", new_cw);
|
// println!("{}", new_cw);
|
||||||
|
|
||||||
// new pay_token is not sent until revoke_token is obtained from the customer
|
// new pay_token is not sent until revoke_token is obtained from the customer
|
||||||
let (new_close_token, new_pay_token) = merch_wallet.verify_payment(rng, &channel, &pay_proof, &new_com, &old_wpk, amount);
|
let new_close_token = merch_wallet.verify_payment(rng, &channel, &pay_proof, &new_com, &old_wpk, amount);
|
||||||
|
|
||||||
println!("Close Token : {}", new_close_token);
|
//println!("1 - Updated close Token : {}", new_close_token);
|
||||||
// unblind tokens and verify signatures
|
// unblind tokens and verify signatures
|
||||||
|
|
||||||
// assuming the pay_proof checks out, can go ahead and update internal state of cust_wallet
|
// assuming the pay_proof checks out, can go ahead and update internal state of cust_wallet
|
||||||
assert!(cust_wallet.update(new_cw));
|
assert!(cust_wallet.update(new_cw));
|
||||||
|
//println!("2 - updated customer wallet!");
|
||||||
|
|
||||||
|
assert!(cust_wallet.verify_close_token(&channel, &new_close_token));
|
||||||
|
//println!("3 - verified the close token!");
|
||||||
|
|
||||||
// invalidate the previous state only if close token checks out
|
// invalidate the previous state only if close token checks out
|
||||||
let (revoke_msg, revoke_token) = cust_wallet.generate_revoke_token(&channel, &new_close_token);
|
let (revoke_msg, revoke_sig) = cust_wallet.generate_revoke_token(&channel, &new_close_token);
|
||||||
|
//println!("4 - Generated revoke token successfully.");
|
||||||
|
|
||||||
|
//println!("5 - Revoke token => {}", revoke_token);
|
||||||
|
|
||||||
|
let new_pay_token = merch_wallet.verify_revoke_token(&revoke_sig, &revoke_msg, &old_wpk);
|
||||||
assert!(cust_wallet.verify_pay_token(&channel, &new_pay_token));
|
assert!(cust_wallet.verify_pay_token(&channel, &new_pay_token));
|
||||||
|
|
||||||
println!("Revoke token => {}", revoke_token);
|
//println!("Validated revoke token!");
|
||||||
|
|
||||||
assert!(merch_wallet.verify_revoke_token(&revoke_token, &revoke_msg, &old_wpk));
|
|
||||||
|
|
||||||
println!("Validated revoke token!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -90,6 +90,12 @@ pub struct Signature<E: Engine> {
|
||||||
pub H: E::G1,
|
pub H: E::G1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: Engine> PartialEq for Signature<E> {
|
||||||
|
fn eq(&self, other: &Signature<E>) -> bool {
|
||||||
|
self.h == other.h && self.H == other.H
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct KeyPair<E: Engine> {
|
pub struct KeyPair<E: Engine> {
|
||||||
pub secret: SecretKey<E>,
|
pub secret: SecretKey<E>,
|
||||||
|
|
3043
src/lib.rs
3043
src/lib.rs
File diff suppressed because it is too large
Load Diff
17
src/ped92.rs
17
src/ped92.rs
|
@ -1,7 +1,7 @@
|
||||||
// ped92.rs
|
// ped92.rs
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use pairing::{Engine, CurveProjective};
|
use pairing::{Engine, CurveProjective};
|
||||||
use ff::Rand;
|
use ff::{Rand, Field};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -128,6 +128,19 @@ impl<E: Engine> CSMultiParams<E> {
|
||||||
return Commitment { c };
|
return Commitment { c };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_commit(&self, com: &Commitment<E>, x: &E::Fr) -> Commitment<E> {
|
||||||
|
// c = com * gn+1 ^ x
|
||||||
|
let len = self.pub_bases.len();
|
||||||
|
let mut c = self.pub_bases[len-1].clone();
|
||||||
|
let xx = x.clone();
|
||||||
|
c.mul_assign(xx);
|
||||||
|
c.negate();
|
||||||
|
c.add_assign(&com.c);
|
||||||
|
|
||||||
|
return Commitment { c };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn decommit(&self, cm: &Commitment<E>, x: &Vec<E::Fr>, r: &E::Fr) -> bool {
|
pub fn decommit(&self, cm: &Commitment<E>, x: &Vec<E::Fr>, r: &E::Fr) -> bool {
|
||||||
let l = x.len();
|
let l = x.len();
|
||||||
// pub_base[0] => h, x[0] => r
|
// pub_base[0] => h, x[0] => r
|
||||||
|
@ -208,4 +221,6 @@ mod tests {
|
||||||
let c2 = csp.commit(&m2, &r);
|
let c2 = csp.commit(&m2, &r);
|
||||||
assert_eq!(csp.decommit(&c2, &m2, &r), true);
|
assert_eq!(csp.decommit(&c2, &m2, &r), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add tests for extend/remove commits dynamically
|
||||||
}
|
}
|
||||||
|
|
57
src/util.rs
57
src/util.rs
|
@ -5,6 +5,7 @@ use ff::PrimeField;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use ped92::CSMultiParams;
|
use ped92::CSMultiParams;
|
||||||
use secp256k1::{Signature, PublicKey};
|
use secp256k1::{Signature, PublicKey};
|
||||||
|
use cl::Signature as clSignature;
|
||||||
|
|
||||||
pub fn hash_g1_to_fr<E: Engine>(x: &Vec<E::G1>) -> E::Fr {
|
pub fn hash_g1_to_fr<E: Engine>(x: &Vec<E::G1>) -> E::Fr {
|
||||||
let mut x_vec: Vec<u8> = Vec::new();
|
let mut x_vec: Vec<u8> = Vec::new();
|
||||||
|
@ -63,6 +64,14 @@ pub fn convert_int_to_fr<E: Engine>(value: i32) -> E::Fr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compute_pub_key_fingerprint(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 struct CommitmentProof<E: Engine> {
|
pub struct CommitmentProof<E: Engine> {
|
||||||
pub T: E::G1,
|
pub T: E::G1,
|
||||||
pub z: Vec<E::Fr>
|
pub z: Vec<E::Fr>
|
||||||
|
@ -187,54 +196,6 @@ impl RevokedMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// refund message
|
|
||||||
#[derive(Clone, Serialize, Deserialize)]
|
|
||||||
pub struct CloseMessage<E: Engine> {
|
|
||||||
pub msgtype: String, // purpose type of message
|
|
||||||
pub wpk: secp256k1::PublicKey,
|
|
||||||
pub balance: usize, // the balance
|
|
||||||
pub r: Option<E::Fr>, // randomness from customer wallet
|
|
||||||
pub rt: Option<cl::Signature<E>> // refund token
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<E: Engine> CloseMessage<E> {
|
|
||||||
pub fn new(_msgtype: String, _wpk: secp256k1::PublicKey,
|
|
||||||
_balance: usize, _r: Option<E::Fr>, _rt: Option<cl::Signature<E>>) -> CloseMessage<E> {
|
|
||||||
RefundMessage {
|
|
||||||
msgtype: _msgtype, wpk: _wpk, balance: _balance, r: _r, rt: _rt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub fn hash(&self) -> Vec<E::Fr> {
|
|
||||||
// let mut v: Vec<Fr> = Vec::new();
|
|
||||||
// let mut input_buf = Vec::new();
|
|
||||||
// input_buf.extend_from_slice(self.msgtype.as_bytes());
|
|
||||||
// v.push(convert_to_fr::<E>(&input_buf));
|
|
||||||
//
|
|
||||||
// v.push(hash_pubkey_to_fr::<E>(&self.wpk));
|
|
||||||
//
|
|
||||||
// // encoee the balance as a hex string
|
|
||||||
// let b = format!("{:x}", self.balance);
|
|
||||||
// let mut b_buf = Vec::new();
|
|
||||||
// b_buf.extend_from_slice(b.as_bytes());
|
|
||||||
// v.push(convert_to_fr(&b_buf));
|
|
||||||
//
|
|
||||||
// //let r_vec: Vec<u8> = encode(&self.r, Infinite).unwrap();
|
|
||||||
// if !self.r.is_none() {
|
|
||||||
// v.push(self.r.unwrap().clone());
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if !self.rt.is_none() {
|
|
||||||
// let rt = {
|
|
||||||
// &self.rt.clone()
|
|
||||||
// };
|
|
||||||
// let rt_ref = rt.as_ref();
|
|
||||||
// v.push(rt_ref.unwrap().hash(&self.msgtype));
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return v;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
|
@ -24,6 +24,10 @@ impl<E: Engine> Wallet<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn without_close(&self) -> Vec<E::Fr> {
|
||||||
|
vec!(self.pkc, self.wpk, E::Fr::from_str(&self.bc.to_string()).unwrap(), E::Fr::from_str(&self.bm.to_string()).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn with_close(&mut 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() );
|
||||||
self.close = Some(m.clone());
|
self.close = Some(m.clone());
|
||||||
|
|
Loading…
Reference in New Issue