From f2e7c83dbf5eaa39ab4f60e3c4d93c6db710c38d Mon Sep 17 00:00:00 2001 From: "J. Ayo Akinyele" Date: Fri, 22 Nov 2019 10:06:13 -0500 Subject: [PATCH] can now instantiate zkchannels on BLS12-381 or BN256 --- Makefile | 8 +- examples/{bolt_test.rs => bolt_test_bls12.rs} | 2 +- examples/bolt_test_bn256.rs | 122 ++++++++++++++++++ py/libbolt.py | 1 + src/channels.rs | 65 +++++++++- 5 files changed, 193 insertions(+), 5 deletions(-) rename examples/{bolt_test.rs => bolt_test_bls12.rs} (99%) create mode 100644 examples/bolt_test_bn256.rs diff --git a/Makefile b/Makefile index 9a36bf7..a50649f 100644 --- a/Makefile +++ b/Makefile @@ -4,16 +4,18 @@ all: export RUSTFLAGS=-Awarnings cargo +nightly build cargo +nightly test - cargo +nightly run --example bolt_test + cargo +nightly run --example bolt_test_bls12 + cargo +nightly run --example bolt_test_bn256 debug: export RUST_BACKTRACE=1 cargo +nightly build - cargo +nightly run --example bolt_test + cargo +nightly run --example bolt_test_bls12 release: cargo +nightly build --release - cargo +nightly run --release --example bolt_test + cargo +nightly run --release --example bolt_test_bls12 + cargo +nightly run --release --example bolt_test_bn256 bench: cargo +nightly bench diff --git a/examples/bolt_test.rs b/examples/bolt_test_bls12.rs similarity index 99% rename from examples/bolt_test.rs rename to examples/bolt_test_bls12.rs index acf99f4..409e5c2 100644 --- a/examples/bolt_test.rs +++ b/examples/bolt_test_bls12.rs @@ -8,7 +8,7 @@ extern crate secp256k1; use bolt::bidirectional; use std::time::Instant; -use pairing::bls12_381::{Bls12}; +use pairing::bls12_381::Bls12; use bolt::handle_bolt_result; macro_rules! measure_one_arg { diff --git a/examples/bolt_test_bn256.rs b/examples/bolt_test_bn256.rs new file mode 100644 index 0000000..8658d1b --- /dev/null +++ b/examples/bolt_test_bn256.rs @@ -0,0 +1,122 @@ +extern crate rand; +extern crate rand_core; +extern crate bolt; +extern crate ff_bl as ff; +extern crate pairing_bl as pairing; +extern crate time; +extern crate secp256k1; + +use bolt::bidirectional; +use std::time::Instant; +use pairing::bn256::Bn256; +use bolt::handle_bolt_result; + +macro_rules! measure_one_arg { + ($x: expr) => { + { + let s = Instant::now(); + let res = $x; + let e = s.elapsed(); + (res, e.as_millis()) + }; + } +} + +macro_rules! measure_two_arg { + ($x: expr) => { + { + let s = Instant::now(); + let (res1, res2) = $x; + let e = s.elapsed(); + (res1, res2, e.as_millis()) + }; + } +} + + +//macro_rules! measure_ret_mut { +// ($x: expr) => { +// { +// let s = Instant::now(); +// let mut handle = $x; +// let e = s.elapsed(); +// (handle, s.as_millis()) +// }; +// } +//} + +fn main() { + println!("******************************************"); + let mut channel_state = bidirectional::ChannelState::::new(String::from("Channel A -> B"), false); + let rng = &mut rand::thread_rng(); + + let b0_customer = 150; + let b0_merchant = 10; + let pay_inc = 20; + let pay_inc2 = 10; + + let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob"); + + let mut cust_state = bidirectional::init_customer(rng, &mut channel_token, b0_customer, b0_merchant, "Alice"); + + println!("{}", cust_state); + + // lets establish the channel + let (com, com_proof, est_time) = measure_two_arg!(bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state)); + println!(">> Time to generate proof for establish: {} ms", est_time); + + // obtain close token for closing out channel + let channel_id = channel_token.compute_channel_id(); + let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, + &channel_id, b0_customer, b0_merchant, &merch_state); + let close_token= match option { + Ok(n) => n.unwrap(), + Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e) + }; + + assert!(cust_state.verify_close_token(&channel_state, &close_token)); + + // wait for funding tx to be confirmed, etc + + // obtain payment token for pay protocol + let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_state); + //assert!(cust_state.verify_pay_token(&channel_state, &pay_token)); + + assert!(bidirectional::establish_customer_final(&mut channel_state, &mut cust_state, &pay_token)); + println!("Channel established!"); + + let (payment, new_cust_state, pay_time) = measure_two_arg!(bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, pay_inc)); + println!(">> Time to generate payment proof: {} ms", pay_time); + + let (new_close_token, verify_time) = measure_one_arg!(bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_state)); + println!(">> Time to verify payment proof: {} ms", verify_time); + + let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state, &new_close_token); + + // send revoke token and get pay-token in response + let new_pay_token_result = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state); + let new_pay_token = handle_bolt_result!(new_pay_token_result); + + // verify the pay token and update internal state + assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token.unwrap())); + + println!("******************************************"); + + let (payment2, new_cust_state2, pay_time2) = measure_two_arg!(bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, pay_inc2)); + println!(">> Time to generate payment proof 2: {} ms", pay_time2); + + let (new_close_token2, verify_time2) = measure_one_arg!(bidirectional::verify_payment_proof(rng, &channel_state, &payment2, &mut merch_state)); + println!(">> Time to verify payment proof 2: {} ms", verify_time2); + + let revoke_token2 = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state2, &new_close_token2); + + // send revoke token and get pay-token in response + let new_pay_token_result2 = bidirectional::verify_revoke_token(&revoke_token2, &mut merch_state); + let new_pay_token2 = handle_bolt_result!(new_pay_token_result2); + + // verify the pay token and update internal state + assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token2.unwrap())); + + println!("Final Cust state: {}", cust_state); + +} diff --git a/py/libbolt.py b/py/libbolt.py index 137e5c6..54aed1a 100644 --- a/py/libbolt.py +++ b/py/libbolt.py @@ -263,6 +263,7 @@ def run_unit_test(): print("cust_state: ", len(cust_state)) (channel_token, cust_state, com, com_proof) = libbolt.bidirectional_establish_customer_generate_proof(channel_token, cust_state) + print("channel token len: => ", len(channel_token)) print("channel token: => ", channel_token) print("com: ", com) diff --git a/src/channels.rs b/src/channels.rs index e3f3352..83107a1 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -598,9 +598,10 @@ impl MerchantState { mod tests { use super::*; use pairing::bls12_381::Bls12; + use pairing::bn256::Bn256; #[test] - fn channel_util_works() { + fn channel_util_works_with_Bls12() { let mut channel = ChannelState::::new(String::from("Channel A <-> B"), false); let rng = &mut rand::thread_rng(); @@ -676,4 +677,66 @@ mod tests { let _channelId = channel_token.compute_channel_id(); } + + #[test] + fn channel_util_works_with_Bn256() { + let mut channel = ChannelState::::new(String::from("Channel A <-> B"), false); + let rng = &mut rand::thread_rng(); + + let b0_cust = 100; + let b0_merch = 20; + // each party executes the init algorithm on the agreed initial challenge balance + // in order to derive the channel tokens + // initialize on the merchant side with balance: b0_merch + let (mut merch_state, mut channel) = MerchantState::::new(rng, &mut channel, String::from("Merchant B")); + + // initialize the merchant wallet with the balance + let mut channel_token = merch_state.init(&mut channel); + + // retrieve commitment setup params (using merchant long lived pk params) + // initialize on the customer side with balance: b0_cust + let mut cust_state = CustomerState::::new(rng, &mut channel_token, b0_cust, b0_merch, String::from("Alice")); + + // lets establish the channel + let cust_com_proof = cust_state.generate_proof(rng, &mut channel_token); + + // first return the close token, then wait for escrow-tx confirmation + // then send the pay-token after confirmation + let channelId = channel_token.compute_channel_id(); + assert_eq!(channelId, cust_state.get_wallet().channelId); + let (close_token, pay_token) = merch_state.verify_proof(rng, &channel, &cust_state.w_com, &cust_com_proof, &channelId, b0_cust, b0_merch).unwrap(); + // unblind tokens and verify signatures + assert!(cust_state.verify_close_token(&channel, &close_token)); + + assert!(cust_state.verify_pay_token(&channel, &pay_token)); + + // pay protocol tests + let amount = 10; + let (pay_proof, new_com, old_wpk, new_cw) = cust_state.generate_payment(rng, &channel, amount); + + // new pay_token is not sent until revoke_token is obtained from the customer + let new_close_token = merch_state.verify_payment(rng, &channel, &pay_proof, &new_com, &old_wpk, amount).unwrap(); + + //println!("1 - Updated close Token : {}", new_close_token); + // unblind tokens and verify signatures + + // assuming the pay_proof checks out, can go ahead and update internal state of cust_state + assert!(cust_state.update(new_cw)); + //println!("2 - updated customer wallet!"); + + assert!(cust_state.verify_close_token(&channel, &new_close_token)); + //println!("3 - verified the close token!"); + + // invalidate the previous state only if close token checks out + let (revoke_msg, revoke_sig) = cust_state.generate_revoke_token(&channel, &new_close_token).unwrap(); + //println!("4 - Generated revoke token successfully."); + + //println!("5 - Revoke token => {}", revoke_token); + + let new_pay_token = merch_state.verify_revoke_token(&revoke_sig, &revoke_msg, &old_wpk).unwrap(); + assert!(cust_state.verify_pay_token(&channel, &new_pay_token)); + + //println!("Validated revoke token!"); + } + }