diff --git a/Cargo.toml b/Cargo.toml index 1d4128b..e6bd8e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,19 +10,19 @@ repository = "https://github.com/ZcashFoundation/libbolt" license = "MIT License" [dependencies] -rand = "0.6" -rand_core = "0.4.0" -ff = { git = "https://github.com/boltlabs-inc/ff", branch = "master" } -pairing = { git = "https://github.com/boltlabs-inc/pairing", branch = "master", features = ["serde"] } +rand = "0.7" +ff_bl = { git = "https://github.com/boltlabs-inc/ff", branch = "master" } +pairing_bl = { git = "https://github.com/boltlabs-inc/pairing", branch = "master", features = ["serde"] } libc = "*" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_with = "1.0" serde_bytes = "0.11.2" time = "*" -secp256k1 = { version = "0.15.0", features = ["rand", "serde"] } +secp256k1 = { version = "0.16.0", features = ["serde"] } sha2 = { version = "0.8", default-features = false } +hex = "0.3.2" [lib] -crate-type = ["lib", "cdylib"] +crate-type = ["lib", "cdylib", "staticlib"] diff --git a/Makefile b/Makefile index 9a36bf7..d2920d6 100644 --- a/Makefile +++ b/Makefile @@ -4,23 +4,25 @@ 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 test: # runs the unit test suite - cargo +nightly test --release #-- --nocapture + cargo +nightly test --release -- --nocapture update: cargo +nightly update diff --git a/README.md b/README.md index f238585..9153baa 100644 --- a/README.md +++ b/README.md @@ -40,9 +40,7 @@ We will switch to the stable release channel once libbolt (and dependencies) are # Build & Install -Please ensure you have installed the libsodium library for your platform. See install instructions [here](https://download.libsodium.org/doc/installation/index.html). - -To build the library and execute basic examples, run `make` +To build the library in debug, execute tests and basic examples, run `make` # Tests diff --git a/examples/bolt_test.rs b/examples/bolt_test_bls12.rs similarity index 97% rename from examples/bolt_test.rs rename to examples/bolt_test_bls12.rs index e61b602..bcd85ee 100644 --- a/examples/bolt_test.rs +++ b/examples/bolt_test_bls12.rs @@ -1,14 +1,13 @@ extern crate rand; -extern crate rand_core; extern crate bolt; -extern crate ff; -extern crate pairing; +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::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..6ce065c --- /dev/null +++ b/examples/bolt_test_bn256.rs @@ -0,0 +1,121 @@ +extern crate rand; +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/go/libbolt.go b/go/libbolt.go index f7d2125..8bb53f3 100644 --- a/go/libbolt.go +++ b/go/libbolt.go @@ -7,6 +7,7 @@ import "C" import ( "encoding/json" "strings" + "fmt" ) type setupResp struct { @@ -232,7 +233,7 @@ type ZkChannelParams struct { } func BidirectionalChannelSetup(name string, channelSupport bool) (ChannelState, error) { - resp := C.GoString(C.ffishim_bidirectional_channel_setup(C.CString(name), C.uint(btoi(channelSupport)))) + resp := C.GoString(C.ffishim_bls12_channel_setup(C.CString(name), C.uint(btoi(channelSupport)))) r, err := processCResponse(resp) if err != nil { return ChannelState{}, err @@ -247,7 +248,7 @@ func BidirectionalInitMerchant(channelState ChannelState, nameMerchant string) ( if err != nil { return ChannelToken{}, MerchState{}, ChannelState{}, err } - resp := C.GoString(C.ffishim_bidirectional_init_merchant(C.CString(string(serChannelState)), C.CString(nameMerchant))) + resp := C.GoString(C.ffishim_bls12_init_merchant(C.CString(string(serChannelState)), C.CString(nameMerchant))) r, err := processCResponse(resp) if err != nil { return ChannelToken{}, MerchState{}, ChannelState{}, err @@ -271,7 +272,7 @@ func BidirectionalInitCustomer(channelToken ChannelToken, balanceCustomer int, b if err != nil { return ChannelToken{}, CustState{}, err } - resp := C.GoString(C.ffishim_bidirectional_init_customer(C.CString(string(serChannelToken)), C.longlong(balanceCustomer), C.longlong(balanceMerchant), C.CString(nameCustomer))) + resp := C.GoString(C.ffishim_bls12_init_customer(C.CString(string(serChannelToken)), C.longlong(balanceCustomer), C.longlong(balanceMerchant), C.CString(nameCustomer))) r, err := processCResponse(resp) if err != nil { return ChannelToken{}, CustState{}, err @@ -294,7 +295,7 @@ func BidirectionalEstablishCustomerGenerateProof(channelToken ChannelToken, cust if err != nil { return ChannelToken{}, CustState{}, Commitment{}, CommitmentProof{}, err } - resp := C.GoString(C.ffishim_bidirectional_establish_customer_generate_proof(C.CString(string(serChannelToken)), C.CString(string(serCustState)))) + resp := C.GoString(C.ffishim_bls12_establish_customer_generate_proof(C.CString(string(serChannelToken)), C.CString(string(serCustState)))) r, err := processCResponse(resp) if err != nil { return ChannelToken{}, CustState{}, Commitment{}, CommitmentProof{}, err @@ -317,6 +318,24 @@ func BidirectionalEstablishCustomerGenerateProof(channelToken ChannelToken, cust return channelToken, custState, com, comProof, err } + + +func BidirectionalGenerateChannelID(channelToken ChannelToken) (error) { + serChannelToken, err := json.Marshal(channelToken) + if err != nil { + return err + } + resp := C.GoString(C.ffishim_bls12_generate_channel_id(C.CString(string(serChannelToken)))) + r, err := processCResponse(resp) + if err != nil { + return err + } + fmt.Println("channel id: ", r) + return err +} + + + func BidirectionalEstablishMerchantIssueCloseToken(channelState ChannelState, com Commitment, comProof CommitmentProof, channelId []string, initCustBal int, initMerchBal int, merchState MerchState) (Signature, error) { serChannelState, err := json.Marshal(channelState) if err != nil { @@ -338,7 +357,7 @@ func BidirectionalEstablishMerchantIssueCloseToken(channelState ChannelState, co if err != nil { return Signature{}, err } - resp := C.GoString(C.ffishim_bidirectional_establish_merchant_issue_close_token(C.CString(string(serChannelState)), C.CString(string(serCom)), C.CString(string(serComProof)), C.CString(string(serChannelId)), C.longlong(initCustBal), C.longlong(initMerchBal), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_establish_merchant_issue_close_token(C.CString(string(serChannelState)), C.CString(string(serCom)), C.CString(string(serComProof)), C.CString(string(serChannelId)), C.longlong(initCustBal), C.longlong(initMerchBal), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return Signature{}, err @@ -361,7 +380,7 @@ func BidirectionalEstablishMerchantIssuePayToken(channelState ChannelState, com if err != nil { return Signature{}, err } - resp := C.GoString(C.ffishim_bidirectional_establish_merchant_issue_pay_token(C.CString(string(serChannelState)), C.CString(string(serCom)), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_establish_merchant_issue_pay_token(C.CString(string(serChannelState)), C.CString(string(serCom)), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return Signature{}, err @@ -384,7 +403,7 @@ func BidirectionalVerifyCloseToken(channelState ChannelState, custState CustStat if err != nil { return false, ChannelState{}, CustState{}, err } - resp := C.GoString(C.ffishim_bidirectional_verify_close_token(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serCloseToken)))) + resp := C.GoString(C.ffishim_bls12_verify_close_token(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serCloseToken)))) r, err := processCResponse(resp) if err != nil { return false, ChannelState{}, CustState{}, err @@ -410,7 +429,7 @@ func BidirectionalEstablishCustomerFinal(channelState ChannelState, custState Cu if err != nil { return false, ChannelState{}, CustState{}, err } - resp := C.GoString(C.ffishim_bidirectional_establish_customer_final(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serPayToken)))) + resp := C.GoString(C.ffishim_bls12_establish_customer_final(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serPayToken)))) r, err := processCResponse(resp) if err != nil { return false, ChannelState{}, CustState{}, err @@ -432,7 +451,7 @@ func BidirectionalPayGeneratePaymentProof(channelState ChannelState, custState C if err != nil { return Payment{}, CustState{}, err } - resp := C.GoString(C.ffishim_bidirectional_pay_generate_payment_proof(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.longlong(amount))) + resp := C.GoString(C.ffishim_bls12_pay_generate_payment_proof(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.longlong(amount))) r, err := processCResponse(resp) if err != nil { return Payment{}, CustState{}, err @@ -459,7 +478,7 @@ func BidirectionalPayVerifyPaymentProof(channelState ChannelState, payProof Paym if err != nil { return Signature{}, MerchState{}, err } - resp := C.GoString(C.ffishim_bidirectional_pay_verify_payment_proof(C.CString(string(serChannelState)), C.CString(string(serPayProof)), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_pay_verify_payment_proof(C.CString(string(serChannelState)), C.CString(string(serPayProof)), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return Signature{}, MerchState{}, err @@ -490,7 +509,7 @@ func BidirectionalPayVerifyMultiplePaymentProofs(channelState ChannelState, send if err != nil { return Signature{}, Signature{}, MerchState{}, err } - resp := C.GoString(C.ffishim_bidirectional_pay_verify_multiple_payment_proofs(C.CString(string(serChannelState)), C.CString(string(serSenderPayProof)), C.CString(string(serReceiverPayProof)), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_pay_verify_multiple_payment_proofs(C.CString(string(serChannelState)), C.CString(string(serSenderPayProof)), C.CString(string(serReceiverPayProof)), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return Signature{}, Signature{}, MerchState{}, err @@ -526,7 +545,7 @@ func BidirectionalPayGenerateRevokeToken(channelState ChannelState, custState Cu if err != nil { return RevokeToken{}, CustState{}, err } - resp := C.GoString(C.ffishim_bidirectional_pay_generate_revoke_token(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serNewCustState)), C.CString(string(serCloseToken)))) + resp := C.GoString(C.ffishim_bls12_pay_generate_revoke_token(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serNewCustState)), C.CString(string(serCloseToken)))) r, err := processCResponse(resp) if err != nil { return RevokeToken{}, CustState{}, err @@ -549,7 +568,7 @@ func BidirectionalPayVerifyRevokeToken(revokeToken RevokeToken, merchState Merch if err != nil { return Signature{}, MerchState{}, err } - resp := C.GoString(C.ffishim_bidirectional_pay_verify_revoke_token(C.CString(string(serRevokeToken)), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_pay_verify_revoke_token(C.CString(string(serRevokeToken)), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return Signature{}, MerchState{}, err @@ -576,7 +595,7 @@ func BidirectionalPayVerifyMultipleRevokeTokens(senderRevokeToken RevokeToken, r if err != nil { return Signature{}, Signature{}, MerchState{}, err } - resp := C.GoString(C.ffishim_bidirectional_pay_verify_multiple_revoke_tokens(C.CString(string(serSenderRevokeToken)), C.CString(string(serReceiverRevokeToken)), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_pay_verify_multiple_revoke_tokens(C.CString(string(serSenderRevokeToken)), C.CString(string(serReceiverRevokeToken)), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return Signature{}, Signature{}, MerchState{}, err @@ -608,7 +627,7 @@ func BidirectionalPayVerifyPaymentToken(channelState ChannelState, custState Cus if err != nil { return CustState{}, false, err } - resp := C.GoString(C.ffishim_bidirectional_pay_verify_payment_token(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serPayToken)))) + resp := C.GoString(C.ffishim_bls12_pay_verify_payment_token(C.CString(string(serChannelState)), C.CString(string(serCustState)), C.CString(string(serPayToken)))) r, err := processCResponse(resp) if err != nil { return CustState{}, false, err @@ -626,7 +645,7 @@ func BidirectionalCustomerClose(channelState ChannelState, custState CustState) if err != nil { return CustClose{}, err } - resp := C.GoString(C.ffishim_bidirectional_customer_close(C.CString(string(serChannelState)), C.CString(string(serCustState)))) + resp := C.GoString(C.ffishim_bls12_customer_close(C.CString(string(serChannelState)), C.CString(string(serCustState)))) r, err := processCResponse(resp) if err != nil { return CustClose{}, err @@ -653,7 +672,7 @@ func BidirectionalMerchantClose(channelState ChannelState, channelToken ChannelT if err != nil { return "", "", "", err } - resp := C.GoString(C.ffishim_bidirectional_merchant_close(C.CString(string(serChannelState)), C.CString(string(serChannelToken)), C.CString(serAddress), C.CString(string(serCustClose)), C.CString(string(serMerchState)))) + resp := C.GoString(C.ffishim_bls12_merchant_close(C.CString(string(serChannelState)), C.CString(string(serChannelToken)), C.CString(serAddress), C.CString(string(serCustClose)), C.CString(string(serMerchState)))) r, err := processCResponse(resp) if err != nil { return "", "", "", err @@ -666,7 +685,7 @@ func BidirectionalWtpVerifyCustCloseMessage(channelToken ChannelToken, serWpk st if err != nil { return "", err } - resp := C.GoString(C.ffishim_bidirectional_wtp_verify_cust_close_message(C.CString(string(serChannelToken)), C.CString(serWpk), C.CString(serCloseMsg), C.CString(string(serCloseToken)))) + resp := C.GoString(C.ffishim_bls12_wtp_verify_cust_close_message(C.CString(string(serChannelToken)), C.CString(serWpk), C.CString(serCloseMsg), C.CString(string(serCloseToken)))) r, err := processCResponse(resp) if err != nil { return "", err @@ -679,7 +698,7 @@ func BidirectionalWtpVerifyMerchCloseMessage(channelToken ChannelToken, serWpk s if err != nil { return "", err } - resp := C.GoString(C.ffishim_bidirectional_wtp_verify_merch_close_message(C.CString(string(serChannelToken)), C.CString(serWpk), C.CString(serMerchClose))) + resp := C.GoString(C.ffishim_bls12_wtp_verify_merch_close_message(C.CString(string(serChannelToken)), C.CString(serWpk), C.CString(serMerchClose))) r, err := processCResponse(resp) if err != nil { return "", err diff --git a/include/libbolt.h b/include/libbolt.h index df4e45d..2bb3190 100644 --- a/include/libbolt.h +++ b/include/libbolt.h @@ -16,35 +16,36 @@ extern "C" { #endif // channel init -char* ffishim_bidirectional_channel_setup(const char *channel_name, unsigned int third_party_support); -char* ffishim_bidirectional_init_merchant(const char *ser_channel_state, const char *name_ptr); -char* ffishim_bidirectional_init_customer(const char *ser_channel_token, long long int balance_customer, long long int balance_merchant, const char *name_ptr); +char* ffishim_bls12_channel_setup(const char *channel_name, unsigned int third_party_support); +char* ffishim_bls12_init_merchant(const char *ser_channel_state, const char *name_ptr); +char* ffishim_bls12_init_customer(const char *ser_channel_token, long long int balance_customer, long long int balance_merchant, const char *name_ptr); // channel establish protocol routines -char* ffishim_bidirectional_establish_customer_generate_proof(const char *ser_channel_token, const char *ser_customer_wallet); -char* ffishim_bidirectional_establish_merchant_issue_close_token(const char *ser_channel_state, const char *ser_com, const char *ser_com_proof, const char *ser_pk_c, long long int init_cust_bal, long long int init_merch_bal, const char *ser_merch_state); -char* ffishim_bidirectional_establish_merchant_issue_pay_token(const char *ser_channel_state, const char *ser_com, const char *ser_merch_state); -char* ffishim_bidirectional_verify_close_token(const char *ser_channel_state, const char *ser_customer_wallet, const char *ser_close_token); -char* ffishim_bidirectional_establish_customer_final(const char *ser_channel_state, const char *ser_customer_wallet, const char *ser_pay_token); +char* ffishim_bls12_establish_customer_generate_proof(const char *ser_channel_token, const char *ser_customer_wallet); +char* ffishim_bls12_generate_channel_id(const char *ser_channel_token); +char* ffishim_bls12_establish_merchant_issue_close_token(const char *ser_channel_state, const char *ser_com, const char *ser_com_proof, const char *ser_pk_c, long long int init_cust_bal, long long int init_merch_bal, const char *ser_merch_state); +char* ffishim_bls12_establish_merchant_issue_pay_token(const char *ser_channel_state, const char *ser_com, const char *ser_merch_state); +char* ffishim_bls12_verify_close_token(const char *ser_channel_state, const char *ser_customer_wallet, const char *ser_close_token); +char* ffishim_bls12_establish_customer_final(const char *ser_channel_state, const char *ser_customer_wallet, const char *ser_pay_token); // channel pay protocol routines -char* ffishim_bidirectional_pay_generate_payment_proof(const char *ser_channel_state, const char *ser_customer_wallet, long long int amount); -char* ffishim_bidirectional_pay_verify_payment_proof(const char *ser_channel_state, const char *ser_pay_proof, const char *ser_merch_state); -char* ffishim_bidirectional_pay_verify_multiple_payment_proofs(const char *ser_channel_state, const char *ser_sender_pay_proof, const char *ser_receiver_pay_proof, const char *ser_merch_state); -char* ffishim_bidirectional_pay_generate_revoke_token(const char *ser_channel_state, const char *ser_cust_state, const char *ser_new_cust_state, const char *ser_close_token); -char* ffishim_bidirectional_pay_verify_revoke_token(const char *ser_revoke_token, const char *ser_merch_state); -char* ffishim_bidirectional_pay_verify_multiple_revoke_tokens(const char *ser_sender_revoke_token, const char *ser_receiver_revoke_token, const char *ser_merch_state); -char* ffishim_bidirectional_pay_verify_payment_token(const char *ser_channel_state, const char *ser_cust_state, const char *ser_pay_token); +char* ffishim_bls12_pay_generate_payment_proof(const char *ser_channel_state, const char *ser_customer_wallet, long long int amount); +char* ffishim_bls12_pay_verify_payment_proof(const char *ser_channel_state, const char *ser_pay_proof, const char *ser_merch_state); +char* ffishim_bls12_pay_verify_multiple_payment_proofs(const char *ser_channel_state, const char *ser_sender_pay_proof, const char *ser_receiver_pay_proof, const char *ser_merch_state); +char* ffishim_bls12_pay_generate_revoke_token(const char *ser_channel_state, const char *ser_cust_state, const char *ser_new_cust_state, const char *ser_close_token); +char* ffishim_bls12_pay_verify_revoke_token(const char *ser_revoke_token, const char *ser_merch_state); +char* ffishim_bls12_pay_verify_multiple_revoke_tokens(const char *ser_sender_revoke_token, const char *ser_receiver_revoke_token, const char *ser_merch_state); +char* ffishim_bls12_pay_verify_payment_token(const char *ser_channel_state, const char *ser_cust_state, const char *ser_pay_token); // closing routines for both sides -char* ffishim_bidirectional_customer_close(const char *ser_channel_state, const char *ser_cust_state); -char* ffishim_bidirectional_merchant_close(const char *ser_channel_state, const char *ser_channel_token, const char *ser_address, const char *ser_cust_close, const char *ser_merch_state); +char* ffishim_bls12_customer_close(const char *ser_channel_state, const char *ser_cust_state); +char* ffishim_bls12_merchant_close(const char *ser_channel_state, const char *ser_channel_token, const char *ser_address, const char *ser_cust_close, const char *ser_merch_state); // WTP logic for on-chain validation of closing messages -char* ffishim_bidirectional_wtp_verify_cust_close_message(const char *ser_channel_token, const char *ser_wpk, const char *ser_close_msg, const char *ser_close_token); -char* ffishim_bidirectional_wtp_verify_merch_close_message(const char *ser_channel_token, const char *ser_wpk, const char *ser_merch_close); +char* ffishim_bls12_wtp_verify_cust_close_message(const char *ser_channel_token, const char *ser_wpk, const char *ser_close_msg, const char *ser_close_token); +char* ffishim_bls12_wtp_verify_merch_close_message(const char *ser_channel_token, const char *ser_wpk, const char *ser_merch_close); -char* ffishim_bidirectional_wtp_check_wpk(const char *wpk); +char* ffishim_bls12_wtp_check_wpk(const char *wpk); #ifdef __cplusplus @@ -64,7 +65,7 @@ char* ffishim_bidirectional_wtp_check_wpk(const char *wpk); int wtp_check_wpk(const char *wpk) { - const char *ret = ffishim_bidirectional_wtp_check_wpk(wpk); + const char *ret = ffishim_bls12_wtp_check_wpk(wpk); printf("RESULT: %s\n", ret); return 0; } @@ -78,7 +79,7 @@ char* ffishim_bidirectional_wtp_check_wpk(const char *wpk); int wtp_verify_cust_close_message(const char *channel_token, const char *wpk, const char *cust_close, const char *close_token) { // Call rust - const char *return_json = ffishim_bidirectional_wtp_verify_cust_close_message(channel_token, wpk, cust_close, close_token); + const char *return_json = ffishim_bls12_wtp_verify_cust_close_message(channel_token, wpk, cust_close, close_token); Document d; d.Parse(return_json); @@ -102,7 +103,7 @@ char* ffishim_bidirectional_wtp_check_wpk(const char *wpk); int wtp_verify_merch_close_message(const char *channel_token, const char *wpk, const char *merch_close) { // Call into Rust - const char* return_json = string_replace_all(ffishim_bidirectional_wtp_verify_merch_close_message(channel_token, wpk, merch_close), '\'', '\"'); + const char* return_json = string_replace_all(ffishim_bls12_wtp_verify_merch_close_message(channel_token, wpk, merch_close), '\'', '\"'); Document d; d.Parse(return_json); diff --git a/py/libbolt.py b/py/libbolt.py index 710f26f..1f0176f 100644 --- a/py/libbolt.py +++ b/py/libbolt.py @@ -15,115 +15,123 @@ class Libbolt(object): self.load_library_params() def load_library_params(self): - self.lib.ffishim_bidirectional_channel_setup.argtypes = (c_void_p, c_uint8) - self.lib.ffishim_bidirectional_channel_setup.restype = c_void_p + self.lib.ffishim_bls12_channel_setup.argtypes = (c_void_p, c_uint8) + self.lib.ffishim_bls12_channel_setup.restype = c_void_p # ESTABLISH PROTOCOL - self.lib.ffishim_bidirectional_init_merchant.argtypes = (c_void_p, c_void_p) - self.lib.ffishim_bidirectional_init_merchant.restype = c_void_p + self.lib.ffishim_bls12_init_merchant.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bls12_init_merchant.restype = c_void_p - self.lib.ffishim_bidirectional_init_customer.argtypes = (c_void_p, ctypes.c_int32, ctypes.c_int32, c_void_p) - self.lib.ffishim_bidirectional_init_customer.restype = c_void_p + self.lib.ffishim_bls12_init_customer.argtypes = (c_void_p, ctypes.c_int32, ctypes.c_int32, c_void_p) + self.lib.ffishim_bls12_init_customer.restype = c_void_p - self.lib.ffishim_bidirectional_establish_customer_generate_proof.argtypes = (c_void_p, c_void_p) - self.lib.ffishim_bidirectional_establish_customer_generate_proof.restype = c_void_p + self.lib.ffishim_bls12_establish_customer_generate_proof.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bls12_establish_customer_generate_proof.restype = c_void_p - self.lib.ffishim_bidirectional_establish_merchant_issue_close_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_establish_merchant_issue_close_token.restype = c_void_p + self.lib.ffishim_bls12_generate_channel_id.argtypes = (c_void_p, ) + self.lib.ffishim_bls12_generate_channel_id.restype = c_void_p - self.lib.ffishim_bidirectional_establish_merchant_issue_pay_token.argtypes = (c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_establish_merchant_issue_pay_token.restype = c_void_p + self.lib.ffishim_bls12_establish_merchant_issue_close_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_establish_merchant_issue_close_token.restype = c_void_p - self.lib.ffishim_bidirectional_verify_close_token.argtypes = (c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_verify_close_token.restype = c_void_p + self.lib.ffishim_bls12_establish_merchant_issue_pay_token.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_establish_merchant_issue_pay_token.restype = c_void_p - self.lib.ffishim_bidirectional_establish_customer_final.argtypes = (c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_establish_customer_final.restype = c_void_p + self.lib.ffishim_bls12_verify_close_token.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_verify_close_token.restype = c_void_p + + self.lib.ffishim_bls12_establish_customer_final.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_establish_customer_final.restype = c_void_p # PAY PROTOCOL - self.lib.ffishim_bidirectional_pay_generate_payment_proof.argtypes = (c_void_p, c_void_p, ctypes.c_int32) - self.lib.ffishim_bidirectional_pay_generate_payment_proof.restype = c_void_p + self.lib.ffishim_bls12_pay_generate_payment_proof.argtypes = (c_void_p, c_void_p, ctypes.c_int32) + self.lib.ffishim_bls12_pay_generate_payment_proof.restype = c_void_p - self.lib.ffishim_bidirectional_pay_verify_payment_proof.argtypes = (c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_pay_verify_payment_proof.restype = c_void_p + self.lib.ffishim_bls12_pay_verify_payment_proof.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_pay_verify_payment_proof.restype = c_void_p - self.lib.ffishim_bidirectional_pay_verify_multiple_payment_proofs.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_pay_verify_multiple_payment_proofs.restype = c_void_p + self.lib.ffishim_bls12_pay_verify_multiple_payment_proofs.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_pay_verify_multiple_payment_proofs.restype = c_void_p - self.lib.ffishim_bidirectional_pay_generate_revoke_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_pay_generate_revoke_token.restype = c_void_p + self.lib.ffishim_bls12_pay_generate_revoke_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_pay_generate_revoke_token.restype = c_void_p - self.lib.ffishim_bidirectional_pay_verify_revoke_token.argtypes = (c_void_p, c_void_p) - self.lib.ffishim_bidirectional_pay_verify_revoke_token.restype = c_void_p + self.lib.ffishim_bls12_pay_verify_revoke_token.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bls12_pay_verify_revoke_token.restype = c_void_p - self.lib.ffishim_bidirectional_pay_verify_multiple_revoke_tokens.argtypes = (c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_pay_verify_multiple_revoke_tokens.restype = c_void_p + self.lib.ffishim_bls12_pay_verify_multiple_revoke_tokens.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_pay_verify_multiple_revoke_tokens.restype = c_void_p - self.lib.ffishim_bidirectional_pay_verify_payment_token.argtypes = (c_void_p, c_void_p) - self.lib.ffishim_bidirectional_pay_verify_payment_token.restype = c_void_p + self.lib.ffishim_bls12_pay_verify_payment_token.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bls12_pay_verify_payment_token.restype = c_void_p # CLOSE - self.lib.ffishim_bidirectional_customer_close.argtypes = (c_void_p, c_void_p) - self.lib.ffishim_bidirectional_customer_close.restype = c_void_p + self.lib.ffishim_bls12_customer_close.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bls12_customer_close.restype = c_void_p - self.lib.ffishim_bidirectional_merchant_close.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_merchant_close.restype = c_void_p + self.lib.ffishim_bls12_merchant_close.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_merchant_close.restype = c_void_p # ON-CHAIN BOLT LOGIC / WTPs - self.lib.ffishim_bidirectional_wtp_verify_cust_close_message.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_wtp_verify_cust_close_message.restype = c_void_p + self.lib.ffishim_bls12_wtp_verify_cust_close_message.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_wtp_verify_cust_close_message.restype = c_void_p - self.lib.ffishim_bidirectional_wtp_verify_merch_close_message.argtypes = (c_void_p, c_void_p, c_void_p) - self.lib.ffishim_bidirectional_wtp_verify_merch_close_message.restype = c_void_p + self.lib.ffishim_bls12_wtp_verify_merch_close_message.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bls12_wtp_verify_merch_close_message.restype = c_void_p self.lib.ffishim_free_string.argtypes = (c_void_p, ) def channel_setup(self, name, third_party_support=0): - output_string = self.lib.ffishim_bidirectional_channel_setup(name.encode(), third_party_support) + output_string = self.lib.ffishim_bls12_channel_setup(name.encode(), third_party_support) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('channel_state') # INIT PROTOCOL def bidirectional_init_merchant(self, channel_state, name): - output_string = self.lib.ffishim_bidirectional_init_merchant(channel_state.encode(), name.encode()) + output_string = self.lib.ffishim_bls12_init_merchant(channel_state.encode(), name.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('channel_token'), output_dictionary.get('merch_state'), output_dictionary.get('channel_state') def bidirectional_init_customer(self, channel_token, b0_cust, b0_merch, name): - output_string = self.lib.ffishim_bidirectional_init_customer(channel_token.encode(), b0_cust, b0_merch, name.encode()) + output_string = self.lib.ffishim_bls12_init_customer(channel_token.encode(), b0_cust, b0_merch, name.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return (output_dictionary.get('channel_token'), output_dictionary.get('cust_state')) # ESTABLISH PROTOCOL + def bidirectional_generate_channel_id(self, channel_token): + output_string = self.lib.ffishim_bls12_generate_channel_id(channel_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('channel_id') + def bidirectional_establish_customer_generate_proof(self, channel_token, cust_state): - output_string = self.lib.ffishim_bidirectional_establish_customer_generate_proof(channel_token.encode(), cust_state.encode()) + output_string = self.lib.ffishim_bls12_establish_customer_generate_proof(channel_token.encode(), cust_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('channel_token'), output_dictionary.get('cust_state'), output_dictionary.get('com'), output_dictionary.get('com_proof') def bidirectional_establish_merchant_issue_close_token(self, channel_state, com, com_proof, channel_id, init_cust, init_merch, merch_state): - output_string = self.lib.ffishim_bidirectional_establish_merchant_issue_close_token(channel_state.encode(), com.encode(), com_proof.encode(), json.dumps(channel_id).encode(), init_cust, init_merch, merch_state.encode()) + output_string = self.lib.ffishim_bls12_establish_merchant_issue_close_token(channel_state.encode(), com.encode(), com_proof.encode(), json.dumps(channel_id).encode(), init_cust, init_merch, merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('close_token') def bidirectional_establish_merchant_issue_pay_token(self, channel_state, com, merch_state): - output_string = self.lib.ffishim_bidirectional_establish_merchant_issue_pay_token(channel_state.encode(), com.encode(), merch_state.encode()) + output_string = self.lib.ffishim_bls12_establish_merchant_issue_pay_token(channel_state.encode(), com.encode(), merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('pay_token') def bidirectional_establish_customer_verify_close_token(self, channel_state, cust_state, close_token): - output_string = self.lib.ffishim_bidirectional_verify_close_token(channel_state.encode(), cust_state.encode(), close_token.encode()) + output_string = self.lib.ffishim_bls12_verify_close_token(channel_state.encode(), cust_state.encode(), close_token.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) is_token_valid = self._convert_boolean(output_dictionary.get('is_token_valid')) return is_token_valid, output_dictionary.get('channel_state'), output_dictionary.get('cust_state') def bidirectional_establish_customer_final(self, channel_state, cust_state, pay_token): - output_string = self.lib.ffishim_bidirectional_establish_customer_final(channel_state.encode(), cust_state.encode(), pay_token.encode()) + output_string = self.lib.ffishim_bls12_establish_customer_final(channel_state.encode(), cust_state.encode(), pay_token.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) is_established = self._convert_boolean(output_dictionary.get('is_established')) return is_established, output_dictionary.get('channel_state'), output_dictionary.get('cust_state') @@ -132,44 +140,44 @@ class Libbolt(object): # generate payment proof and new cust state def bidirectional_pay_generate_payment_proof(self, channel_state, cust_state, amount): - output_string = self.lib.ffishim_bidirectional_pay_generate_payment_proof(channel_state.encode(), cust_state.encode(), amount) + output_string = self.lib.ffishim_bls12_pay_generate_payment_proof(channel_state.encode(), cust_state.encode(), amount) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('payment'), output_dictionary.get('cust_state') # verify payment proof def bidirectional_pay_verify_payment_proof(self, channel_state, pay_proof, merch_state): - output_string = self.lib.ffishim_bidirectional_pay_verify_payment_proof(channel_state.encode(), pay_proof.encode(), merch_state.encode()) + output_string = self.lib.ffishim_bls12_pay_verify_payment_proof(channel_state.encode(), pay_proof.encode(), merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return (output_dictionary.get('close_token'), output_dictionary.get('merch_state')) # verify multiple payment proof def bidirectional_pay_verify_multiple_payment_proofs(self, channel_state, sender_pay_proof, receiver_pay_proof, merch_state): - output_string = self.lib.ffishim_bidirectional_pay_verify_multiple_payment_proofs(channel_state.encode(), sender_pay_proof.encode(), receiver_pay_proof.encode(), merch_state.encode()) + output_string = self.lib.ffishim_bls12_pay_verify_multiple_payment_proofs(channel_state.encode(), sender_pay_proof.encode(), receiver_pay_proof.encode(), merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return (output_dictionary.get('sender_close_token'), output_dictionary.get('receiver_cond_close_token'), output_dictionary.get('merch_state')) # generate revoke token def bidirectional_pay_generate_revoke_token(self, channel_state, cust_state, new_cust_state, close_token): - output_string = self.lib.ffishim_bidirectional_pay_generate_revoke_token(channel_state.encode(), cust_state.encode(), + output_string = self.lib.ffishim_bls12_pay_generate_revoke_token(channel_state.encode(), cust_state.encode(), new_cust_state.encode(), close_token.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('revoke_token'), output_dictionary.get('cust_state') # verify revoke token def bidirectional_pay_verify_revoke_token(self, revoke_token, merch_state): - output_string = self.lib.ffishim_bidirectional_pay_verify_revoke_token(revoke_token.encode(), merch_state.encode()) + output_string = self.lib.ffishim_bls12_pay_verify_revoke_token(revoke_token.encode(), merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return (output_dictionary.get('pay_token'), output_dictionary.get('merch_state')) # verify multiple revoke tokens def bidirectional_pay_verify_multiple_revoke_tokens(self, sender_revoke_token, receiver_revoke_token, merch_state): - output_string = self.lib.ffishim_bidirectional_pay_verify_multiple_revoke_tokens(sender_revoke_token.encode(), receiver_revoke_token.encode(), merch_state.encode()) + output_string = self.lib.ffishim_bls12_pay_verify_multiple_revoke_tokens(sender_revoke_token.encode(), receiver_revoke_token.encode(), merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return (output_dictionary.get('sender_pay_token'), output_dictionary.get('receiver_pay_token'), output_dictionary.get('merch_state')) # verify payment token def bidirectional_pay_verify_payment_token(self, channel_state, cust_state, pay_token): - output_string = self.lib.ffishim_bidirectional_pay_verify_payment_token(channel_state.encode(), cust_state.encode(), pay_token.encode()) + output_string = self.lib.ffishim_bls12_pay_verify_payment_token(channel_state.encode(), cust_state.encode(), pay_token.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) is_pay_valid = self._convert_boolean(output_dictionary.get('is_pay_valid')) return (output_dictionary.get('cust_state'), is_pay_valid) @@ -177,12 +185,12 @@ class Libbolt(object): # CLOSE def bidirectional_customer_close(self, channel_state, cust_state): - output_string = self.lib.ffishim_bidirectional_customer_close(channel_state.encode(), cust_state.encode()) + output_string = self.lib.ffishim_bls12_customer_close(channel_state.encode(), cust_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary.get('cust_close') def bidirectional_merchant_close(self, channel_state, channel_token, address, cust_close, merch_state): - output_string = self.lib.ffishim_bidirectional_merchant_close(channel_state.encode(), channel_token.encode(), + output_string = self.lib.ffishim_bls12_merchant_close(channel_state.encode(), channel_token.encode(), address.encode(), cust_close.encode(), merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return (output_dictionary.get('wpk'), output_dictionary.get('merch_close'), output_dictionary.get('error')) @@ -198,7 +206,7 @@ class Libbolt(object): return json.dumps(cust_close_dict.get("signature")) def wtp_verify_cust_close_message(self, channel_token, wpk, cust_close_wallet, close_token): - output_string = self.lib.ffishim_bidirectional_wtp_verify_cust_close_message(channel_token.encode(), + output_string = self.lib.ffishim_bls12_wtp_verify_cust_close_message(channel_token.encode(), wpk.encode(), cust_close_wallet.encode(), close_token.encode()) @@ -206,7 +214,7 @@ class Libbolt(object): return output_dictionary.get('result') def wtp_verify_merch_close_message(self, channel_token, wpk, merch_close): - output_string = self.lib.ffishim_bidirectional_wtp_verify_merch_close_message(channel_token.encode(), + output_string = self.lib.ffishim_bls12_wtp_verify_merch_close_message(channel_token.encode(), wpk.encode(), merch_close.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) @@ -222,6 +230,27 @@ class Libbolt(object): return False return bool_str + def get_compact_channel_token(self, channel_token_str): + ct = self._interperate_json_string_as_dictionary(channel_token_str) + + s = ct["pk_c"] + s += ct["pk_m"] + s += ct["cl_pk_m"]["X"] + s += "".join(ct["cl_pk_m"]["Y"]) + s += ct["mpk"]["g1"] + s += ct["mpk"]["g2"] + s += "".join(ct["comParams"]["pub_bases"]) + return s + + def get_compact_signing_keys(self, cust_state_str): + cust_state_str = cust_state_str.replace("null", "None") + cust_state = self._interperate_json_string_as_dictionary(cust_state_str) + + name = cust_state.get("name") + (pk, sk) = cust_state.get("pk_c"), cust_state.get("sk_c") + return name, pk, sk + + if platform == 'darwin': prefix = 'lib' ext = 'dylib' @@ -255,10 +284,20 @@ 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) + #libbolt.get_compact_channel_token(channel_token) + + print("cust state: ", cust_state) + #libbolt.get_compact_signing_keys(cust_state) + print("com: ", com) cust_state_dict = json.loads(cust_state) + channel_id = libbolt.bidirectional_generate_channel_id(channel_token) + print("channel ID: ", channel_id) + #print("wallet chan ID: ", cust_state_dict["wallet"]["channelId"]) + close_token = libbolt.bidirectional_establish_merchant_issue_close_token(channel_state, com, com_proof, cust_state_dict["wallet"]["channelId"], b0_cust, b0_merch, merch_state) print("close token: ", close_token) diff --git a/py/libbolt_bn256.py b/py/libbolt_bn256.py new file mode 100644 index 0000000..17b685d --- /dev/null +++ b/py/libbolt_bn256.py @@ -0,0 +1,369 @@ +from ctypes import cdll +from sys import platform + +import sys, ctypes +from ctypes import c_void_p, c_uint8 + +import ast +import json + +class Libbolt(object): + """Libbolt Py/C low-level API""" + + def __init__(self, path): + self.lib = cdll.LoadLibrary(path) + self.load_library_params() + + def load_library_params(self): + self.lib.ffishim_bn256_channel_setup.argtypes = (c_void_p, c_uint8) + self.lib.ffishim_bn256_channel_setup.restype = c_void_p + + # ESTABLISH PROTOCOL + + self.lib.ffishim_bn256_init_merchant.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bn256_init_merchant.restype = c_void_p + + self.lib.ffishim_bn256_init_customer.argtypes = (c_void_p, ctypes.c_int32, ctypes.c_int32, c_void_p) + self.lib.ffishim_bn256_init_customer.restype = c_void_p + + self.lib.ffishim_bn256_establish_customer_generate_proof.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bn256_establish_customer_generate_proof.restype = c_void_p + + self.lib.ffishim_bn256_generate_channel_id.argtypes = (c_void_p, ) + self.lib.ffishim_bn256_generate_channel_id.restype = c_void_p + + self.lib.ffishim_bn256_establish_merchant_issue_close_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_establish_merchant_issue_close_token.restype = c_void_p + + self.lib.ffishim_bn256_establish_merchant_issue_pay_token.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_establish_merchant_issue_pay_token.restype = c_void_p + + self.lib.ffishim_bn256_verify_close_token.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_verify_close_token.restype = c_void_p + + self.lib.ffishim_bn256_establish_customer_final.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_establish_customer_final.restype = c_void_p + + # PAY PROTOCOL + + self.lib.ffishim_bn256_pay_generate_payment_proof.argtypes = (c_void_p, c_void_p, ctypes.c_int32) + self.lib.ffishim_bn256_pay_generate_payment_proof.restype = c_void_p + + self.lib.ffishim_bn256_pay_verify_payment_proof.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_pay_verify_payment_proof.restype = c_void_p + + self.lib.ffishim_bn256_pay_verify_multiple_payment_proofs.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_pay_verify_multiple_payment_proofs.restype = c_void_p + + self.lib.ffishim_bn256_pay_generate_revoke_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_pay_generate_revoke_token.restype = c_void_p + + self.lib.ffishim_bn256_pay_verify_revoke_token.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bn256_pay_verify_revoke_token.restype = c_void_p + + self.lib.ffishim_bn256_pay_verify_multiple_revoke_tokens.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_pay_verify_multiple_revoke_tokens.restype = c_void_p + + self.lib.ffishim_bn256_pay_verify_payment_token.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bn256_pay_verify_payment_token.restype = c_void_p + + # CLOSE + + self.lib.ffishim_bn256_customer_close.argtypes = (c_void_p, c_void_p) + self.lib.ffishim_bn256_customer_close.restype = c_void_p + + self.lib.ffishim_bn256_merchant_close.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_merchant_close.restype = c_void_p + + # ON-CHAIN BOLT LOGIC / WTPs + + self.lib.ffishim_bn256_wtp_verify_cust_close_message.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_wtp_verify_cust_close_message.restype = c_void_p + + self.lib.ffishim_bn256_wtp_verify_merch_close_message.argtypes = (c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bn256_wtp_verify_merch_close_message.restype = c_void_p + + self.lib.ffishim_free_string.argtypes = (c_void_p, ) + + def channel_setup(self, name, third_party_support=0): + output_string = self.lib.ffishim_bn256_channel_setup(name.encode(), third_party_support) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('channel_state') + + # INIT PROTOCOL + + def bidirectional_init_merchant(self, channel_state, name): + output_string = self.lib.ffishim_bn256_init_merchant(channel_state.encode(), name.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('channel_token'), output_dictionary.get('merch_state'), output_dictionary.get('channel_state') + + def bidirectional_init_customer(self, channel_token, b0_cust, b0_merch, name): + output_string = self.lib.ffishim_bn256_init_customer(channel_token.encode(), b0_cust, b0_merch, name.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return (output_dictionary.get('channel_token'), output_dictionary.get('cust_state')) + + # ESTABLISH PROTOCOL + + def bidirectional_generate_channel_id(self, channel_token): + output_string = self.lib.ffishim_bn256_generate_channel_id(channel_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('channel_id') + + def bidirectional_establish_customer_generate_proof(self, channel_token, cust_state): + output_string = self.lib.ffishim_bn256_establish_customer_generate_proof(channel_token.encode(), cust_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('channel_token'), output_dictionary.get('cust_state'), output_dictionary.get('com'), output_dictionary.get('com_proof') + + def bidirectional_establish_merchant_issue_close_token(self, channel_state, com, com_proof, channel_id, init_cust, init_merch, merch_state): + output_string = self.lib.ffishim_bn256_establish_merchant_issue_close_token(channel_state.encode(), com.encode(), com_proof.encode(), json.dumps(channel_id).encode(), init_cust, init_merch, merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('close_token') + + def bidirectional_establish_merchant_issue_pay_token(self, channel_state, com, merch_state): + output_string = self.lib.ffishim_bn256_establish_merchant_issue_pay_token(channel_state.encode(), com.encode(), merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('pay_token') + + def bidirectional_establish_customer_verify_close_token(self, channel_state, cust_state, close_token): + output_string = self.lib.ffishim_bn256_verify_close_token(channel_state.encode(), cust_state.encode(), close_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + is_token_valid = self._convert_boolean(output_dictionary.get('is_token_valid')) + return is_token_valid, output_dictionary.get('channel_state'), output_dictionary.get('cust_state') + + def bidirectional_establish_customer_final(self, channel_state, cust_state, pay_token): + output_string = self.lib.ffishim_bn256_establish_customer_final(channel_state.encode(), cust_state.encode(), pay_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + is_established = self._convert_boolean(output_dictionary.get('is_established')) + return is_established, output_dictionary.get('channel_state'), output_dictionary.get('cust_state') + + # PAY PROTOCOL + + # generate payment proof and new cust state + def bidirectional_pay_generate_payment_proof(self, channel_state, cust_state, amount): + output_string = self.lib.ffishim_bn256_pay_generate_payment_proof(channel_state.encode(), cust_state.encode(), amount) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('payment'), output_dictionary.get('cust_state') + + # verify payment proof + def bidirectional_pay_verify_payment_proof(self, channel_state, pay_proof, merch_state): + output_string = self.lib.ffishim_bn256_pay_verify_payment_proof(channel_state.encode(), pay_proof.encode(), merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return (output_dictionary.get('close_token'), output_dictionary.get('merch_state')) + + # verify multiple payment proof + def bidirectional_pay_verify_multiple_payment_proofs(self, channel_state, sender_pay_proof, receiver_pay_proof, merch_state): + output_string = self.lib.ffishim_bn256_pay_verify_multiple_payment_proofs(channel_state.encode(), sender_pay_proof.encode(), receiver_pay_proof.encode(), merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return (output_dictionary.get('sender_close_token'), output_dictionary.get('receiver_cond_close_token'), output_dictionary.get('merch_state')) + + # generate revoke token + def bidirectional_pay_generate_revoke_token(self, channel_state, cust_state, new_cust_state, close_token): + output_string = self.lib.ffishim_bn256_pay_generate_revoke_token(channel_state.encode(), cust_state.encode(), + new_cust_state.encode(), close_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('revoke_token'), output_dictionary.get('cust_state') + + # verify revoke token + def bidirectional_pay_verify_revoke_token(self, revoke_token, merch_state): + output_string = self.lib.ffishim_bn256_pay_verify_revoke_token(revoke_token.encode(), merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return (output_dictionary.get('pay_token'), output_dictionary.get('merch_state')) + + # verify multiple revoke tokens + def bidirectional_pay_verify_multiple_revoke_tokens(self, sender_revoke_token, receiver_revoke_token, merch_state): + output_string = self.lib.ffishim_bn256_pay_verify_multiple_revoke_tokens(sender_revoke_token.encode(), receiver_revoke_token.encode(), merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return (output_dictionary.get('sender_pay_token'), output_dictionary.get('receiver_pay_token'), output_dictionary.get('merch_state')) + + # verify payment token + def bidirectional_pay_verify_payment_token(self, channel_state, cust_state, pay_token): + output_string = self.lib.ffishim_bn256_pay_verify_payment_token(channel_state.encode(), cust_state.encode(), pay_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + is_pay_valid = self._convert_boolean(output_dictionary.get('is_pay_valid')) + return (output_dictionary.get('cust_state'), is_pay_valid) + + # CLOSE + + def bidirectional_customer_close(self, channel_state, cust_state): + output_string = self.lib.ffishim_bn256_customer_close(channel_state.encode(), cust_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('cust_close') + + def bidirectional_merchant_close(self, channel_state, channel_token, address, cust_close, merch_state): + output_string = self.lib.ffishim_bn256_merchant_close(channel_state.encode(), channel_token.encode(), + address.encode(), cust_close.encode(), merch_state.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return (output_dictionary.get('wpk'), output_dictionary.get('merch_close'), output_dictionary.get('error')) + + # WTP logic + + def wtp_get_wallet(self, cust_state): + cust_state_dict = self._interperate_json_string_as_dictionary(cust_state) + return json.dumps(cust_state_dict.get("wpk")), json.dumps(cust_state_dict.get("wallet")) + + def wtp_get_close_token(self, cust_close): + cust_close_dict = self._interperate_json_string_as_dictionary(cust_close) + return json.dumps(cust_close_dict.get("signature")) + + def wtp_verify_cust_close_message(self, channel_token, wpk, cust_close_wallet, close_token): + output_string = self.lib.ffishim_bn256_wtp_verify_cust_close_message(channel_token.encode(), + wpk.encode(), + cust_close_wallet.encode(), + close_token.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('result') + + def wtp_verify_merch_close_message(self, channel_token, wpk, merch_close): + output_string = self.lib.ffishim_bn256_wtp_verify_merch_close_message(channel_token.encode(), + wpk.encode(), + merch_close.encode()) + output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) + return output_dictionary.get('result') + + def _interperate_json_string_as_dictionary(self, json_string): + return ast.literal_eval(json_string) + + def _convert_boolean(self, bool_str): + if bool_str == "true": + return True + if bool_str == "false": + return False + return bool_str + +if platform == 'darwin': + prefix = 'lib' + ext = 'dylib' +elif platform == 'win32': + prefix = '' + ext = 'dll' +else: + prefix = 'lib' + ext = 'so' + +DEBUG = 'debug' +RELEASE = 'release' +mode = RELEASE # debug or release + +def run_unit_test(): + libbolt = Libbolt('target/{}/{}bolt.{}'.format(mode, prefix, ext)) + + b0_cust = 100 + b0_merch = 10 + + channel_state = libbolt.channel_setup("My New Channel A") + + print("channel state new: ", len(channel_state)) + + (channel_token, merch_state, channel_state) = libbolt.bidirectional_init_merchant(channel_state, "Bob") + + print("merch_state: ", len(merch_state)) + #print("channel_token: ", type(_channel_token)) + + (channel_token, cust_state) = libbolt.bidirectional_init_customer(channel_token, b0_cust, b0_merch, "Alice") + 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) + + cust_state_dict = json.loads(cust_state) + channel_id = libbolt.bidirectional_generate_channel_id(channel_token) + print("channel ID: ", channel_id) + #print("wallet chan ID: ", cust_state_dict["wallet"]["channelId"]) + + close_token = libbolt.bidirectional_establish_merchant_issue_close_token(channel_state, com, com_proof, cust_state_dict["wallet"]["channelId"], b0_cust, b0_merch, merch_state) + print("close token: ", close_token) + + (is_token_valid, channel_state, cust_state) = libbolt.bidirectional_establish_customer_verify_close_token(channel_state, cust_state, close_token) + + pay_token = libbolt.bidirectional_establish_merchant_issue_pay_token(channel_state, com, merch_state) + print("pay token: ", pay_token) + + (is_channel_established, channel_state, cust_state) = libbolt.bidirectional_establish_customer_final(channel_state, cust_state, pay_token) + if is_channel_established: + print("updated cust_state: ", cust_state) + else: + print("channel still not established. did you verify close token?") + + # Pay protocol + print("Pay protocol...") + + # make a payment + amount = 5 + (payment_proof, new_cust_state) = libbolt.bidirectional_pay_generate_payment_proof(channel_state, cust_state, amount) + print("Pay proof: ", len(payment_proof)) + print("new cust wallet: ", new_cust_state) + print("<========================================>") + revoked_wpk, _ = libbolt.wtp_get_wallet(new_cust_state) + + (new_close_token, merch_state) = libbolt.bidirectional_pay_verify_payment_proof(channel_state, payment_proof, merch_state) + print("Close token: ", new_close_token) + print("<========================================>") + + (revoke_token, cust_state) = libbolt.bidirectional_pay_generate_revoke_token(channel_state, cust_state, new_cust_state, new_close_token) + print("Revoke token: ", revoke_token) + + (pay_token, merch_state) = libbolt.bidirectional_pay_verify_revoke_token(revoke_token, merch_state) + print("Pay token: ", pay_token) + + (cust_state, is_pay_valid) = libbolt.bidirectional_pay_verify_payment_token(channel_state, cust_state, pay_token) + print("Pay token is valid: ", is_pay_valid) + + old_cust_close = libbolt.bidirectional_customer_close(channel_state, cust_state) + + # make a payment + amount = 10 + (payment_proof2, new_cust_state2) = libbolt.bidirectional_pay_generate_payment_proof(channel_state, cust_state, amount) + print("Pay proof 2: ", len(payment_proof2)) + print("new cust wallet 2: ", new_cust_state2) + print("<========================================>") + + (new_close_token2, merch_state) = libbolt.bidirectional_pay_verify_payment_proof(channel_state, payment_proof2, merch_state) + print("Close token 2: ", new_close_token2) + print("<========================================>") + + (revoke_token2, cust_state) = libbolt.bidirectional_pay_generate_revoke_token(channel_state, cust_state, new_cust_state2, new_close_token2) + print("Revoke token 2: ", revoke_token) + + (pay_token2, merch_state) = libbolt.bidirectional_pay_verify_revoke_token(revoke_token2, merch_state) + print("Pay token 2: ", pay_token2) + + (cust_state, is_pay_valid) = libbolt.bidirectional_pay_verify_payment_token(channel_state, cust_state, pay_token2) + print("Pay token is valid: ", is_pay_valid) + + print("<========================================>") + print("<========================================>") + + cust_close = libbolt.bidirectional_customer_close(channel_state, cust_state) + print("Cust close msg: ", cust_close) + print("<========================================>") + + # normal case: no action b/c cust close is valid + address = "11" * 32 + merch_close = libbolt.bidirectional_merchant_close(channel_state, channel_token, address, cust_close, merch_state) + print("Customer initiated - Merch close msg: ", merch_close) + print("<========================================>") + + # common case: merchant catches customer double spending + address = "11" * 32 + merch_wpk, merch_close_msg, _ = libbolt.bidirectional_merchant_close(channel_state, channel_token, address, old_cust_close, merch_state) + print("Double spend - Merch close msg: ", merch_close_msg) + merch_close_valid = libbolt.wtp_verify_merch_close_message(channel_token, merch_wpk, merch_close_msg) + print("Merchant close msg valid: ", merch_close_valid) + print("<========================================>") + + print("<========================================>") + wpk, cust_close_wallet = libbolt.wtp_get_wallet(cust_state) + print("wpk = ", wpk) + print("close-msg wallet = ", cust_close_wallet) + cust_close_token = libbolt.wtp_get_close_token(cust_close) + print("close token: ", cust_close_token) + print("Valid channel opening: ", libbolt.wtp_verify_cust_close_message(channel_token, wpk, cust_close_wallet, cust_close_token)) + # TODO: merch close when cust_close represents correct channel state + + print("Invalid channel opening: ", libbolt.wtp_verify_cust_close_message(channel_token, revoked_wpk, cust_close_wallet, cust_close_token)) + print("<========================================>") + +if __name__ == "__main__": + run_unit_test() diff --git a/src/ccs08.rs b/src/ccs08.rs index 9942610..7bc6ed6 100644 --- a/src/ccs08.rs +++ b/src/ccs08.rs @@ -4,11 +4,9 @@ Efficient Protocols for Set Membership and Range Proofs Jan Camenisch, Rafik Chaabouni, and abhi shelat Asiacrypt 2008 */ -extern crate pairing; -extern crate rand; -use rand::Rng; use super::*; +use rand::Rng; use cl::{Signature, PublicParams, setup, BlindKeyPair, ProofState, SignatureProof, BlindPublicKey}; use ped92::{Commitment, CSMultiParams}; use pairing::{Engine, CurveProjective}; diff --git a/src/channels.rs b/src/channels.rs index 0ab312a..5f32a98 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -1,14 +1,3 @@ -/* - * Implement for Bolt protocols: - * - initializing channel state and generating cust/merch wallets - * - establish protocol - * - pay protocol - * - channel close algorithms (WIP) - */ - -extern crate pairing; -extern crate rand; - use super::*; use pairing::Engine; use cl::{BlindKeyPair, Signature}; @@ -134,8 +123,6 @@ impl ChannelToken { // add a method to compute hash on chain: SHA256 + RIPEMD160? } -// add methods to check if channel token is initialized -// (only if /// /// Channel state for generating/loading channel parameters and generating keypairs @@ -223,13 +210,20 @@ impl CustomerState { ::G2: serde::Serialize, ::Fr: serde::Serialize { - let mut kp = secp256k1::Secp256k1::new(); - kp.randomize(csprng); + let secp = secp256k1::Secp256k1::new(); - // generate the keypair for the channel - let (sk_c, pk_c) = kp.generate_keypair(csprng); + let mut seckey = [0u8; 32]; + csprng.fill_bytes(&mut seckey); + + // generate the signing keypair for the channel + let sk_c = secp256k1::SecretKey::from_slice(&seckey).unwrap(); + let pk_c = secp256k1::PublicKey::from_secret_key(&secp, &sk_c); + + let mut seckey1 = [0u8; 32]; + csprng.fill_bytes(&mut seckey1); // generate the keypair for the initial wallet - let (wsk, wpk) = kp.generate_keypair(csprng); + let wsk = secp256k1::SecretKey::from_slice(&seckey1).unwrap(); + let wpk = secp256k1::PublicKey::from_secret_key(&secp, &wsk); // hash the wallet pub key let wpk_h = hash_pubkey_to_fr::(&wpk); channel_token.set_customer_pk(&pk_c); @@ -346,9 +340,14 @@ impl CustomerState { // for channel pay pub fn generate_payment(&self, csprng: &mut R, channel: &ChannelState, amount: i64) -> (NIZKProof, Commitment, secp256k1::PublicKey, CustomerState) { // 1 - chooose new wpk/wsk pair - let mut kp = secp256k1::Secp256k1::new(); - kp.randomize(csprng); - let (new_wsk, new_wpk) = kp.generate_keypair(csprng); + let secp = secp256k1::Secp256k1::new(); + + let mut seckey = [0u8; 32]; + csprng.fill_bytes(&mut seckey); + + let new_wsk = secp256k1::SecretKey::from_slice(&seckey).unwrap(); + let new_wpk = secp256k1::PublicKey::from_secret_key(&secp, &new_wsk); + // compute hash of the pubkey let wpk_h = hash_pubkey_to_fr::(&new_wpk); // 2 - form new wallet and commitment @@ -489,9 +488,14 @@ impl MerchantState { pub fn new(csprng: &mut R, channel: &mut ChannelState, id: String) -> (Self, ChannelState) { let l = 5; // generate keys here - let mut tx_kp = secp256k1::Secp256k1::new(); - tx_kp.randomize(csprng); - let (wsk, wpk) = tx_kp.generate_keypair(csprng); + let secp = secp256k1::Secp256k1::new(); + // tx_kp.randomize(csprng); + // let (wsk, wpk) = tx_kp.generate_keypair(csprng); + let mut seckey = [0u8; 32]; + csprng.fill_bytes(&mut seckey); + let wsk = secp256k1::SecretKey::from_slice(&seckey).unwrap(); + let wpk = secp256k1::PublicKey::from_secret_key(&secp, &wsk); + let mut ch = channel.clone(); let nizkParams = NIZKSecretParams::::setup(csprng, l); ch.cp = Some(ChannelParams:: { pub_params: nizkParams.pubParams.clone(), l, extra_verify: true }); @@ -611,9 +615,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(); @@ -689,4 +694,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!"); + } + } diff --git a/src/cl.rs b/src/cl.rs index 2afee5d..c00d255 100644 --- a/src/cl.rs +++ b/src/cl.rs @@ -1,8 +1,5 @@ // cl.rs // CL Sigs - Pointcheval Sanders ('06) -extern crate pairing; -extern crate rand; - use super::*; use pairing::{CurveProjective, Engine}; use ff::PrimeField; @@ -12,6 +9,7 @@ use serde::{Serialize, Deserialize}; use util; #[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(bound(deserialize = "::G1: serde::Deserialize<'de>, ::G2: serde::Deserialize<'de>"))] pub struct PublicParams { pub g1: E::G1, pub g2: E::G2, @@ -23,6 +21,18 @@ impl PartialEq for PublicParams { } } +impl PublicParams { + pub fn from_slice<'de>(ser_g1: &'de [u8], ser_g2: &'de [u8]) -> Self + where ::G1: serde::Deserialize<'de>, + ::G2: serde::Deserialize<'de> + { + // TODO: handle malformed input errors + let g1: E::G1 = serde_json::from_slice(ser_g1).unwrap(); + let g2: E::G2 = serde_json::from_slice(ser_g2).unwrap(); + + PublicParams { g1, g2 } + } +} #[derive(Clone, Serialize, Deserialize, Debug)] pub struct SecretKey { @@ -51,6 +61,7 @@ impl PartialEq for SecretKey { #[derive(Clone, Serialize, Deserialize, Debug)] +#[serde(bound(deserialize = "::G2: serde::Deserialize<'de>"))] pub struct PublicKey { pub X: E::G2, pub Y: Vec, @@ -75,6 +86,23 @@ impl PartialEq for PublicKey { } } +impl PublicKey { + pub fn from_slice<'de>(ser_x: &'de [u8], ser_y: &'de [u8], y_len: usize, num_elems: usize) -> Self + where ::G2: serde::Deserialize<'de> + { + let X: E::G2 = serde_json::from_slice(ser_x).unwrap(); + let mut Y: Vec = Vec::new(); + let mut start_pos = 0; + let mut end_pos = y_len; + for _ in 0 .. num_elems { + let y = serde_json::from_slice(&ser_y[start_pos .. end_pos]).unwrap(); + start_pos = end_pos; + end_pos += y_len; + Y.push(y); + } + PublicKey { X, Y } + } +} #[derive(Clone, Serialize, Deserialize, Debug)] pub struct BlindPublicKey { @@ -120,6 +148,19 @@ impl PartialEq for Signature { } } +impl Signature { + pub fn from_slice<'de>(ser_h: &'de [u8], ser_H: &'de [u8]) -> Self + where ::G1: serde::Deserialize<'de> + { + // TODO: handle malformed input errors + let h: E::G1 = serde_json::from_slice(ser_h).unwrap(); + let H: E::G1 = serde_json::from_slice(ser_H).unwrap(); + + Signature { h, H } + } +} + + #[derive(Clone)] pub struct KeyPair { pub secret: SecretKey, @@ -682,10 +723,10 @@ mod tests { let blindkeypair = BlindKeyPair::::generate(&mut rng, &mpk, l); let serialized = serde_json::to_vec(&mpk).unwrap(); - //println!("serialized = {:?}", serialized.len()); + println!("mpk serialized len = {:?}", serialized.len()); let _mpk_des: PublicParams = serde_json::from_slice(&serialized).unwrap(); - //println!("{}", mpk_des); + //println!("{}", _mpk_des); //println!("SK => {}", &keypair.secret); let sk_serialized = serde_json::to_vec(&keypair.secret).unwrap(); @@ -697,7 +738,7 @@ mod tests { //println!("PK => {}", &keypair.public); let pk_serialized = serde_json::to_vec(&keypair.public).unwrap(); - //println!("pk_serialized = {:?}", pk_serialized.len()); + println!("cl pk_serialized len = {:?}", pk_serialized.len()); let _pk_des: PublicKey = serde_json::from_slice(&pk_serialized).unwrap(); //assert_eq!(pk_des, keypair.public); @@ -719,5 +760,58 @@ mod tests { assert_eq!(upk_des, unblind_pk); assert_ne!(upk_des, keypair.public); } + + #[test] + fn test_compact_public_params_deserialize() { + let bin_g1= vec![132, 83, 99, 124, 75, 72, 15, 109, 12, 94, 84, 103, 1, 58, 160, 232, 190, 23, 119, 195, 112, 161, 152, 141, 178, 29, 141, 61, 227, 246, 215, 157, 140, 190, 100, 18, 248, 141, 57, 222, 12, 209, 191, 158, 143, 155, 87, 255]; + let bin_g2 = vec![147, 63, 33, 190, 248, 155, 91, 211, 249, 169, 1, 147, 101, 104, 219, 88, 204, 131, 38, 167, 25, 191, 86, 67, 139, 188, 171, 101, 154, 32, 234, 92, 3, 66, 235, 159, 7, 47, 16, 83, 3, 201, 13, 227, 179, 184, 101, 102, 21, 88, 153, 208, 93, 0, 57, 108, 250, 231, 74, 192, 82, 111, 13, 211, 12, 51, 224, 198, 121, 15, 63, 129, 25, 218, 193, 47, 182, 248, 112, 185, 163, 23, 175, 169, 76, 214, 36, 184, 142, 222, 48, 212, 157, 35, 115, 181]; + + let ser_g1 = util::encode_as_hexstring(&bin_g1); + let ser_g2 = util::encode_as_hexstring(&bin_g2); + + let str_g1 = ser_g1.as_bytes(); + let str_g2 = ser_g2.as_bytes(); + + let rec_mpk = PublicParams::::from_slice(&str_g1, &str_g2); + + println!("g1: {}", rec_mpk.g1); + println!("g2: {}", rec_mpk.g2); + + let rec_g1_str = serde_json::to_string(&rec_mpk.g1).unwrap(); + assert_eq!(rec_g1_str, "\"8453637c4b480f6d0c5e5467013aa0e8be1777c370a1988db21d8d3de3f6d79d8cbe6412f88d39de0cd1bf9e8f9b57ff\""); + + let rec_g2_str = serde_json::to_string(&rec_mpk.g2).unwrap(); + assert_eq!(rec_g2_str, "\"933f21bef89b5bd3f9a901936568db58cc8326a719bf56438bbcab659a20ea5c0342eb9f072f105303c90de3b3b86566155899d05d00396cfae74ac0526f0dd30c33e0c6790f3f8119dac12fb6f870b9a317afa94cd624b88ede30d49d2373b5\""); + } + + #[test] + fn test_compact_cl_public_key_deserialize() { + let bin_g2_x = vec![147, 63, 33, 190, 248, 155, 91, 211, 249, 169, 1, 147, 101, 104, 219, 88, 204, 131, 38, 167, 25, 191, 86, 67, 139, 188, 171, 101, 154, 32, 234, 92, 3, 66, 235, 159, 7, 47, 16, 83, 3, 201, 13, 227, 179, 184, 101, 102, 21, 88, 153, 208, 93, 0, 57, 108, 250, 231, 74, 192, 82, 111, 13, 211, 12, 51, 224, 198, 121, 15, 63, 129, 25, 218, 193, 47, 182, 248, 112, 185, 163, 23, 175, 169, 76, 214, 36, 184, 142, 222, 48, 212, 157, 35, 115, 181]; + let bin_g2_y1 = vec![143, 76, 112, 7, 35, 99, 254, 7, 255, 225, 69, 13, 99, 32, 92, 186, 234, 175, 230, 0, 202, 144, 1, 216, 187, 248, 152, 76, 229, 74, 156, 94, 4, 16, 132, 119, 157, 172, 231, 164, 207, 88, 41, 6, 234, 78, 73, 58, 19, 104, 236, 127, 5, 231, 248, 150, 53, 197, 85, 194, 110, 93, 1, 73, 24, 96, 149, 133, 109, 194, 16, 190, 244, 184, 254, 192, 52, 21, 205, 109, 18, 83, 189, 175, 208, 147, 74, 32, 181, 126, 224, 136, 250, 126, 224, 186]; + let bin_g2_y2 = vec![150, 132, 45, 236, 146, 135, 127, 242, 61, 55, 73, 100, 151, 12, 51, 134, 151, 42, 138, 227, 105, 54, 121, 7, 0, 27, 205, 139, 186, 69, 139, 143, 41, 132, 35, 33, 168, 35, 31, 52, 65, 5, 73, 153, 203, 25, 178, 196, 4, 9, 218, 130, 22, 64, 98, 152, 225, 212, 27, 202, 245, 234, 138, 34, 82, 102, 40, 72, 211, 248, 16, 221, 54, 154, 186, 95, 246, 132, 54, 0, 128, 170, 111, 94, 155, 166, 27, 225, 51, 31, 107, 223, 139, 0, 209, 236]; + + let ser_g2_x = util::encode_as_hexstring(&bin_g2_x); + let ser_g2_y1 = util::encode_as_hexstring(&bin_g2_y1); + let ser_g2_y2 = util::encode_as_hexstring(&bin_g2_y2); + + let str_g2_x = ser_g2_x.as_bytes(); + let str_g2_y1 = ser_g2_y1.as_bytes(); + let str_g2_y2 = ser_g2_y2.as_bytes(); + + let mut vec = Vec::new(); + vec.extend(str_g2_y1); + vec.extend(str_g2_y2); + + let rec_cl_pk = PublicKey::::from_slice(&str_g2_x, &vec.as_slice(), ser_g2_y1.len(), 2); + + let rec_x_str = serde_json::to_string(&rec_cl_pk.X).unwrap(); + assert_eq!(rec_x_str, "\"933f21bef89b5bd3f9a901936568db58cc8326a719bf56438bbcab659a20ea5c0342eb9f072f105303c90de3b3b86566155899d05d00396cfae74ac0526f0dd30c33e0c6790f3f8119dac12fb6f870b9a317afa94cd624b88ede30d49d2373b5\""); + + let rec_y1_str = serde_json::to_string(&rec_cl_pk.Y[0]).unwrap(); + assert_eq!(rec_y1_str, "\"8f4c70072363fe07ffe1450d63205cbaeaafe600ca9001d8bbf8984ce54a9c5e041084779dace7a4cf582906ea4e493a1368ec7f05e7f89635c555c26e5d0149186095856dc210bef4b8fec03415cd6d1253bdafd0934a20b57ee088fa7ee0ba\""); + + let rec_y2_str = serde_json::to_string(&rec_cl_pk.Y[1]).unwrap(); + assert_eq!(rec_y2_str, "\"96842dec92877ff23d374964970c3386972a8ae369367907001bcd8bba458b8f29842321a8231f3441054999cb19b2c40409da8216406298e1d41bcaf5ea8a2252662848d3f810dd369aba5ff684360080aa6f5e9ba61be1331f6bdf8b00d1ec\""); + } } diff --git a/src/ffishim.rs b/src/ffishim.rs index 9be004c..a9bf19a 100644 --- a/src/ffishim.rs +++ b/src/ffishim.rs @@ -11,7 +11,6 @@ pub mod ffishim { use libc::c_char; use std::ffi::{CStr, CString}; use std::str; -// use channels::{ChannelcloseM, ResultBoltType, BoltError}; fn error_message(s: String) -> *mut c_char { let ser = ["{\'error\':\'", &s, "\'}"].concat(); @@ -34,24 +33,7 @@ pub mod ffishim { } pub type ResultSerdeType = Result; - -// fn deserialize_object<'a, T>(serialized: *mut c_char) -> T -// where -// T: Deserialize<'a>, -// { -// let bytes = unsafe { CStr::from_ptr(serialized).to_bytes() }; -// let string: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 -// serde_json::from_str(&string).unwrap() -// } -// -// fn deserialize_optional_object<'a, T>(serialized: *mut c_char) -> Option -// where -// T: Deserialize<'a>, -// { -// let bytes = unsafe { CStr::from_ptr(serialized).to_bytes() }; -// let string: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 -// Some(serde_json::from_str(&string).unwrap()) -// } + type CURVE = Bls12; fn deserialize_result_object<'a, T>(serialized: *mut c_char) -> ResultSerdeType where @@ -71,7 +53,7 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_wtp_check_wpk(ser_wpk: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_wtp_check_wpk(ser_wpk: *mut c_char) -> *mut c_char { let wpk_result: ResultSerdeType = deserialize_result_object(ser_wpk); let _wpk = handle_errors!(wpk_result); @@ -82,7 +64,7 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_channel_setup(channel_name: *const c_char, third_party_support: u32) -> *mut c_char { + pub extern fn ffishim_bls12_channel_setup(channel_name: *const c_char, third_party_support: u32) -> *mut c_char { let bytes = unsafe { CStr::from_ptr(channel_name).to_bytes() }; let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 @@ -90,7 +72,7 @@ pub mod ffishim { if third_party_support > 1 { tps = true; } - let channel_state = bidirectional::ChannelState::::new(name.to_string(), tps); + let channel_state = bidirectional::ChannelState::::new(name.to_string(), tps); let ser = ["{\'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat(); let cser = CString::new(ser).unwrap(); @@ -100,9 +82,9 @@ pub mod ffishim { // INIT #[no_mangle] - pub extern fn ffishim_bidirectional_init_merchant(ser_channel_state: *mut c_char, name_ptr: *const c_char) -> *mut c_char { + pub extern fn ffishim_bls12_init_merchant(ser_channel_state: *mut c_char, name_ptr: *const c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let mut channel_state = handle_errors!(channel_state_result); let bytes = unsafe { CStr::from_ptr(name_ptr).to_bytes() }; @@ -117,10 +99,10 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_init_customer(ser_channel_token: *mut c_char, balance_customer: i64, balance_merchant: i64, name_ptr: *const c_char) -> *mut c_char { + pub extern fn ffishim_bls12_init_customer(ser_channel_token: *mut c_char, balance_customer: i64, balance_merchant: i64, name_ptr: *const c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel token - let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); let mut channel_token = handle_errors!(channel_token_result); // Deserialize the name @@ -136,15 +118,15 @@ pub mod ffishim { // ESTABLISH - #[no_mangle] // bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state); - pub extern fn ffishim_bidirectional_establish_customer_generate_proof(ser_channel_token: *mut c_char, ser_customer_state: *mut c_char) -> *mut c_char { + #[no_mangle] + pub extern fn ffishim_bls12_establish_customer_generate_proof(ser_channel_token: *mut c_char, ser_customer_state: *mut c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel token - let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); let mut channel_token = handle_errors!(channel_token_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); let mut cust_state = handle_errors!(cust_state_result); let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state); @@ -159,26 +141,38 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_establish_merchant_issue_close_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_com_proof: *mut c_char, ser_channel_id: *mut c_char, init_cust_bal: i64, init_merch_bal: i64, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_generate_channel_id(ser_channel_token: *mut c_char) -> *mut c_char { + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token = handle_errors!(channel_token_result); + + let id = channel_token.compute_channel_id(); + let ser = ["{\'channel_id\':\'", serde_json::to_string(&id).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bls12_establish_merchant_issue_close_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_com_proof: *mut c_char, ser_channel_id: *mut c_char, init_cust_bal: i64, init_merch_bal: i64, ser_merch_state: *mut c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the com proof - let com_result: ResultSerdeType> = deserialize_result_object(ser_com); + let com_result: ResultSerdeType> = deserialize_result_object(ser_com); let com = handle_errors!(com_result); // Deserialize the com proof - let com_proof_result: ResultSerdeType> = deserialize_result_object(ser_com_proof); + let com_proof_result: ResultSerdeType> = deserialize_result_object(ser_com_proof); let com_proof = handle_errors!(com_proof_result); // Deserialize the merchant state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let merch_state = handle_errors!(merch_state_result); // Deserialize the pk_c - let channel_id_result: ResultSerdeType<::Fr> = deserialize_result_object(ser_channel_id); + let channel_id_result: ResultSerdeType<::Fr> = deserialize_result_object(ser_channel_id); let channel_id_fr = handle_errors!(channel_id_result); let close_token = bolt_try!(bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &channel_id_fr, init_cust_bal, init_merch_bal, &merch_state)); @@ -189,18 +183,18 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_establish_merchant_issue_pay_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_establish_merchant_issue_pay_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the commitment - let com_result: ResultSerdeType> = deserialize_result_object(ser_com); + let com_result: ResultSerdeType> = deserialize_result_object(ser_com); let com = handle_errors!(com_result); // Deserialize the merchant state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let merch_state = handle_errors!(merch_state_result); let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_state); @@ -211,17 +205,17 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_verify_close_token(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_verify_close_token(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let mut channel_state = handle_errors!(channel_state_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); let mut cust_state = handle_errors!(cust_state_result); // Deserialize the close token - let close_result: ResultSerdeType> = deserialize_result_object(ser_close_token); + let close_result: ResultSerdeType> = deserialize_result_object(ser_close_token); let close_token = handle_errors!(close_result); let is_close_token_valid = cust_state.verify_close_token(&mut channel_state, &close_token); @@ -235,17 +229,17 @@ pub mod ffishim { #[no_mangle] - pub extern fn ffishim_bidirectional_establish_customer_final(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, ser_pay_token: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_establish_customer_final(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, ser_pay_token: *mut c_char) -> *mut c_char { // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let mut channel_state = handle_errors!(channel_state_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); let mut cust_state = handle_errors!(cust_state_result); // Deserialize the custdata - let pay_token_result: ResultSerdeType> = deserialize_result_object(ser_pay_token); + let pay_token_result: ResultSerdeType> = deserialize_result_object(ser_pay_token); let pay_token = handle_errors!(pay_token_result); let is_channel_established = bidirectional::establish_customer_final(&mut channel_state, &mut cust_state, &pay_token); @@ -260,14 +254,14 @@ pub mod ffishim { // PAY #[no_mangle] - pub extern fn ffishim_bidirectional_pay_generate_payment_proof(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, amount: i64) -> *mut c_char { + pub extern fn ffishim_bls12_pay_generate_payment_proof(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, amount: i64) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); let cust_state = handle_errors!(cust_state_result); // Generate the payment proof @@ -280,18 +274,18 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_pay_verify_payment_proof(ser_channel_state: *mut c_char, ser_pay_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_pay_verify_payment_proof(ser_channel_state: *mut c_char, ser_pay_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the payment proof - let payment_result: ResultSerdeType> = deserialize_result_object(ser_pay_proof); + let payment_result: ResultSerdeType> = deserialize_result_object(ser_pay_proof); let payment = handle_errors!(payment_result); // Deserialize the merch state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let mut merch_state = handle_errors!(merch_state_result); let close_token = bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_state); @@ -302,21 +296,21 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_pay_verify_multiple_payment_proofs(ser_channel_state: *mut c_char, ser_sender_pay_proof: *mut c_char, ser_receiver_pay_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_pay_verify_multiple_payment_proofs(ser_channel_state: *mut c_char, ser_sender_pay_proof: *mut c_char, ser_receiver_pay_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the payment proofs - let sender_payment_result: ResultSerdeType> = deserialize_result_object(ser_sender_pay_proof); + let sender_payment_result: ResultSerdeType> = deserialize_result_object(ser_sender_pay_proof); let sender_payment = handle_errors!(sender_payment_result); - let receiver_payment_result: ResultSerdeType> = deserialize_result_object(ser_receiver_pay_proof); + let receiver_payment_result: ResultSerdeType> = deserialize_result_object(ser_receiver_pay_proof); let receiver_payment = handle_errors!(receiver_payment_result); // Deserialize the merch state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let mut merch_state = handle_errors!(merch_state_result); let close_token_result = bidirectional::verify_multiple_payment_proofs(rng, &channel_state, &sender_payment, &receiver_payment, &mut merch_state); @@ -329,21 +323,21 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_pay_generate_revoke_token(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char, ser_new_cust_state: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_pay_generate_revoke_token(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char, ser_new_cust_state: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); let mut cust_state = handle_errors!(cust_state_result); // Deserialize the cust state - let new_cust_state_result: ResultSerdeType> = deserialize_result_object(ser_new_cust_state); + let new_cust_state_result: ResultSerdeType> = deserialize_result_object(ser_new_cust_state); let new_cust_state = handle_errors!(new_cust_state_result); // Deserialize the close token - let close_token_result: ResultSerdeType> = deserialize_result_object(ser_close_token); + let close_token_result: ResultSerdeType> = deserialize_result_object(ser_close_token); let close_token = handle_errors!(close_token_result); let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state, &close_token); @@ -354,13 +348,13 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_pay_verify_revoke_token(ser_revoke_token: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_pay_verify_revoke_token(ser_revoke_token: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { // Deserialize the revoke token let revoke_token_result: ResultSerdeType = deserialize_result_object(ser_revoke_token); let revoke_token = handle_errors!(revoke_token_result); // Deserialize the cust state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let mut merch_state = handle_errors!(merch_state_result); // send revoke token and get pay-token in response @@ -374,7 +368,7 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_pay_verify_multiple_revoke_tokens(ser_sender_revoke_token: *mut c_char, ser_receiver_revoke_token: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_pay_verify_multiple_revoke_tokens(ser_sender_revoke_token: *mut c_char, ser_receiver_revoke_token: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { // Deserialize the revoke tokens let sender_revoke_token_result: ResultSerdeType = deserialize_result_object(ser_sender_revoke_token); let sender_revoke_token = handle_errors!(sender_revoke_token_result); @@ -383,7 +377,7 @@ pub mod ffishim { let receiver_revoke_token = handle_errors!(receiver_revoke_token_result); // Deserialize the cust state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let mut merch_state = handle_errors!(merch_state_result); // send revoke token and get pay-token in response @@ -399,17 +393,17 @@ pub mod ffishim { #[no_mangle] - pub extern fn ffishim_bidirectional_pay_verify_payment_token(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char, ser_pay_token: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_pay_verify_payment_token(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char, ser_pay_token: *mut c_char) -> *mut c_char { // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); let mut cust_state = handle_errors!(cust_state_result); // Deserialize the pay token - let pay_token_result: ResultSerdeType> = deserialize_result_object(ser_pay_token); + let pay_token_result: ResultSerdeType> = deserialize_result_object(ser_pay_token); let pay_token = handle_errors!(pay_token_result); // verify the pay token and update internal state @@ -423,13 +417,13 @@ pub mod ffishim { // CLOSE #[no_mangle] - pub extern fn ffishim_bidirectional_customer_close(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_customer_close(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char) -> *mut c_char { // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the cust state - let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); let cust_state = handle_errors!(cust_state_result); let cust_close = bidirectional::customer_close(&channel_state, &cust_state); @@ -439,21 +433,21 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_merchant_close(ser_channel_state: *mut c_char, ser_channel_token: *mut c_char, ser_address: *const c_char, ser_cust_close: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_merchant_close(ser_channel_state: *mut c_char, ser_channel_token: *mut c_char, ser_address: *const c_char, ser_cust_close: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { // Deserialize the channel state - let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); let channel_state = handle_errors!(channel_state_result); // Deserialize the channel token - let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); let channel_token = handle_errors!(channel_token_result); // Deserialize the customer close structure - let cust_close_result: ResultSerdeType> = deserialize_result_object(ser_cust_close); + let cust_close_result: ResultSerdeType> = deserialize_result_object(ser_cust_close); let cust_close = handle_errors!(cust_close_result); // Deserialize the merch state - let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); let merch_state = handle_errors!(merch_state_result); // Deserialize the destination address as a string @@ -475,9 +469,9 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_wtp_verify_cust_close_message(ser_channel_token: *mut c_char, ser_wpk: *mut c_char, ser_close_msg: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_wtp_verify_cust_close_message(ser_channel_token: *mut c_char, ser_wpk: *mut c_char, ser_close_msg: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { // Deserialize the channel token - let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); let channel_token = handle_errors!(channel_token_result); // Deserialize the wpk @@ -485,11 +479,11 @@ pub mod ffishim { let wpk = handle_errors!(wpk_result); // Deserialize the close wallet - let close_msg_result: ResultSerdeType> = deserialize_result_object(ser_close_msg); + let close_msg_result: ResultSerdeType> = deserialize_result_object(ser_close_msg); let close_msg = handle_errors!(close_msg_result); // Deserialize the close token - let close_token_result: ResultSerdeType> = deserialize_result_object(ser_close_token); + let close_token_result: ResultSerdeType> = deserialize_result_object(ser_close_token); let close_token = handle_errors!(close_token_result); // check the signatures @@ -500,9 +494,9 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_wtp_verify_merch_close_message(ser_channel_token: *mut c_char, ser_wpk: *mut c_char, ser_merch_close: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bls12_wtp_verify_merch_close_message(ser_channel_token: *mut c_char, ser_wpk: *mut c_char, ser_merch_close: *mut c_char) -> *mut c_char { // Deserialize the channel token - let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); let channel_token = handle_errors!(channel_token_result); // Deserialize the wpk diff --git a/src/ffishim_bn256.rs b/src/ffishim_bn256.rs new file mode 100644 index 0000000..fb969c1 --- /dev/null +++ b/src/ffishim_bn256.rs @@ -0,0 +1,511 @@ +#[no_mangle] +pub mod ffishim_bn256 { + extern crate libc; + + use bidirectional; + use ff::ScalarEngine; + use pairing::bn256::Bn256; + + use serde::Deserialize; + + use libc::c_char; + use std::ffi::{CStr, CString}; + use std::str; + + fn error_message(s: String) -> *mut c_char { + let ser = ["{\'error\':\'", &s, "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + macro_rules! bolt_try { + ($e:expr) => (match $e { + Ok(val) => val.unwrap(), + Err(err) => return error_message(err), + }); + } + + macro_rules! handle_errors { + ($e:expr) => (match $e { + Ok(val) => val, + Err(err) => return error_message(err.to_string()), + }); + } + + pub type ResultSerdeType = Result; + type CURVE = Bn256; + + fn deserialize_result_object<'a, T>(serialized: *mut c_char) -> ResultSerdeType + where + T: Deserialize<'a>, + { + let bytes = unsafe { CStr::from_ptr(serialized).to_bytes() }; + let string: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 + serde_json::from_str(&string) + } + + #[no_mangle] + pub extern fn ffishim_bn256_wtp_check_wpk(ser_wpk: *mut c_char) -> *mut c_char { + let wpk_result: ResultSerdeType = deserialize_result_object(ser_wpk); + let _wpk = handle_errors!(wpk_result); + + let res = true; + let ser = ["{\'result\':\'", serde_json::to_string(&res).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_channel_setup(channel_name: *const c_char, third_party_support: u32) -> *mut c_char { + let bytes = unsafe { CStr::from_ptr(channel_name).to_bytes() }; + let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 + + let mut tps = false; + if third_party_support > 1 { + tps = true; + } + let channel_state = bidirectional::ChannelState::::new(name.to_string(), tps); + + let ser = ["{\'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + // INIT + + #[no_mangle] + pub extern fn ffishim_bn256_init_merchant(ser_channel_state: *mut c_char, name_ptr: *const c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let mut channel_state = handle_errors!(channel_state_result); + + let bytes = unsafe { CStr::from_ptr(name_ptr).to_bytes() }; + let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 + + let (channel_token, merch_state, channel_state) = bidirectional::init_merchant(rng, &mut channel_state, name); + + let ser = ["{\'channel_token\':\'", serde_json::to_string(&channel_token).unwrap().as_str(), "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str(), "\', \'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat(); + + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_init_customer(ser_channel_token: *mut c_char, balance_customer: i64, balance_merchant: i64, name_ptr: *const c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let mut channel_token = handle_errors!(channel_token_result); + + // Deserialize the name + let bytes = unsafe { CStr::from_ptr(name_ptr).to_bytes() }; + let name: &str = str::from_utf8(bytes).unwrap(); // make sure the bytes are UTF-8 + + // We change the channel state + let cust_state = bidirectional::init_customer(rng, &mut channel_token, balance_customer, balance_merchant, name); + let ser = ["{\'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), "\', \'channel_token\':\'", serde_json::to_string(&channel_token).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + // ESTABLISH + + #[no_mangle] + pub extern fn ffishim_bn256_establish_customer_generate_proof(ser_channel_token: *mut c_char, ser_customer_state: *mut c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let mut channel_token = handle_errors!(channel_token_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let mut cust_state = handle_errors!(cust_state_result); + + let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state); + + let ser = ["{\'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), + "\', \'channel_token\':\'", serde_json::to_string(&channel_token).unwrap().as_str(), + "\', \'com\':\'", serde_json::to_string(&com).unwrap().as_str(), + "\', \'com_proof\':\'", serde_json::to_string(&com_proof).unwrap().as_str(), + "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_generate_channel_id(ser_channel_token: *mut c_char) -> *mut c_char { + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token = handle_errors!(channel_token_result); + + let id = channel_token.compute_channel_id(); + let ser = ["{\'channel_id\':\'", serde_json::to_string(&id).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_establish_merchant_issue_close_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_com_proof: *mut c_char, ser_channel_id: *mut c_char, init_cust_bal: i64, init_merch_bal: i64, ser_merch_state: *mut c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the com proof + let com_result: ResultSerdeType> = deserialize_result_object(ser_com); + let com = handle_errors!(com_result); + + // Deserialize the com proof + let com_proof_result: ResultSerdeType> = deserialize_result_object(ser_com_proof); + let com_proof = handle_errors!(com_proof_result); + + // Deserialize the merchant state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state = handle_errors!(merch_state_result); + + // Deserialize the pk_c + let channel_id_result: ResultSerdeType<::Fr> = deserialize_result_object(ser_channel_id); + let channel_id_fr = handle_errors!(channel_id_result); + + let close_token = bolt_try!(bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &channel_id_fr, init_cust_bal, init_merch_bal, &merch_state)); + + let ser = ["{\'close_token\':\'", serde_json::to_string(&close_token).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_establish_merchant_issue_pay_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the commitment + let com_result: ResultSerdeType> = deserialize_result_object(ser_com); + let com = handle_errors!(com_result); + + // Deserialize the merchant state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state = handle_errors!(merch_state_result); + + let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_state); + + let ser = ["{\'pay_token\':\'", serde_json::to_string(&pay_token).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_verify_close_token(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let mut channel_state = handle_errors!(channel_state_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let mut cust_state = handle_errors!(cust_state_result); + + // Deserialize the close token + let close_result: ResultSerdeType> = deserialize_result_object(ser_close_token); + let close_token = handle_errors!(close_result); + + let is_close_token_valid = cust_state.verify_close_token(&mut channel_state, &close_token); + + let ser = ["{\'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), + "\', \'is_token_valid\':\'", serde_json::to_string(&is_close_token_valid).unwrap().as_str(), + "\', \'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + + #[no_mangle] + pub extern fn ffishim_bn256_establish_customer_final(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, ser_pay_token: *mut c_char) -> *mut c_char { + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let mut channel_state = handle_errors!(channel_state_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let mut cust_state = handle_errors!(cust_state_result); + + // Deserialize the custdata + let pay_token_result: ResultSerdeType> = deserialize_result_object(ser_pay_token); + let pay_token = handle_errors!(pay_token_result); + + let is_channel_established = bidirectional::establish_customer_final(&mut channel_state, &mut cust_state, &pay_token); + + let ser = ["{\'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), + "\', \'is_established\':\'", serde_json::to_string(&is_channel_established).unwrap().as_str(), + "\', \'channel_state\':\'", serde_json::to_string(&channel_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + // PAY + + #[no_mangle] + pub extern fn ffishim_bn256_pay_generate_payment_proof(ser_channel_state: *mut c_char, ser_customer_state: *mut c_char, amount: i64) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_customer_state); + let cust_state = handle_errors!(cust_state_result); + + // Generate the payment proof + let (payment, new_cust_state) = bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, amount); + // Serialize the results and return to caller + let ser = ["{\'payment\':\'", serde_json::to_string(&payment).unwrap().as_str(), + "\', \'cust_state\':\'", serde_json::to_string(&new_cust_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_pay_verify_payment_proof(ser_channel_state: *mut c_char, ser_pay_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the payment proof + let payment_result: ResultSerdeType> = deserialize_result_object(ser_pay_proof); + let payment = handle_errors!(payment_result); + + // Deserialize the merch state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let mut merch_state = handle_errors!(merch_state_result); + + let close_token = bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_state); + let ser = ["{\'close_token\':\'", serde_json::to_string(&close_token).unwrap().as_str(), + "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_pay_verify_multiple_payment_proofs(ser_channel_state: *mut c_char, ser_sender_pay_proof: *mut c_char, ser_receiver_pay_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + let rng = &mut rand::thread_rng(); + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the payment proofs + let sender_payment_result: ResultSerdeType> = deserialize_result_object(ser_sender_pay_proof); + let sender_payment = handle_errors!(sender_payment_result); + + let receiver_payment_result: ResultSerdeType> = deserialize_result_object(ser_receiver_pay_proof); + let receiver_payment = handle_errors!(receiver_payment_result); + + // Deserialize the merch state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let mut merch_state = handle_errors!(merch_state_result); + + let close_token_result = bidirectional::verify_multiple_payment_proofs(rng, &channel_state, &sender_payment, &receiver_payment, &mut merch_state); + let (sender_close_token, receiver_cond_close_token) = handle_errors!(close_token_result).unwrap(); + let ser = ["{\'sender_close_token\':\'", serde_json::to_string(&sender_close_token).unwrap().as_str(), + "\', \'receiver_cond_close_token\':\'", serde_json::to_string(&receiver_cond_close_token).unwrap().as_str(), + "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_pay_generate_revoke_token(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char, ser_new_cust_state: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); + let mut cust_state = handle_errors!(cust_state_result); + + // Deserialize the cust state + let new_cust_state_result: ResultSerdeType> = deserialize_result_object(ser_new_cust_state); + let new_cust_state = handle_errors!(new_cust_state_result); + + // Deserialize the close token + let close_token_result: ResultSerdeType> = deserialize_result_object(ser_close_token); + let close_token = handle_errors!(close_token_result); + + let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state, &close_token); + let ser = ["{\'revoke_token\':\'", serde_json::to_string(&revoke_token).unwrap().as_str(), + "\', \'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_pay_verify_revoke_token(ser_revoke_token: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + // Deserialize the revoke token + let revoke_token_result: ResultSerdeType = deserialize_result_object(ser_revoke_token); + let revoke_token = handle_errors!(revoke_token_result); + + // Deserialize the cust state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let mut merch_state = handle_errors!(merch_state_result); + + // send revoke token and get pay-token in response + let pay_token_result = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state); + let pay_token = handle_errors!(pay_token_result); + + let ser = ["{\'pay_token\':\'", serde_json::to_string(&pay_token.unwrap()).unwrap().as_str(), + "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_pay_verify_multiple_revoke_tokens(ser_sender_revoke_token: *mut c_char, ser_receiver_revoke_token: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + // Deserialize the revoke tokens + let sender_revoke_token_result: ResultSerdeType = deserialize_result_object(ser_sender_revoke_token); + let sender_revoke_token = handle_errors!(sender_revoke_token_result); + + let receiver_revoke_token_result: ResultSerdeType = deserialize_result_object(ser_receiver_revoke_token); + let receiver_revoke_token = handle_errors!(receiver_revoke_token_result); + + // Deserialize the cust state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let mut merch_state = handle_errors!(merch_state_result); + + // send revoke token and get pay-token in response + let pay_token_result = bidirectional::verify_multiple_revoke_tokens(&sender_revoke_token, &receiver_revoke_token, &mut merch_state); + let (sender_pay_token, receiver_pay_token) = handle_errors!(pay_token_result).unwrap(); + + let ser = ["{\'sender_pay_token\':\'", serde_json::to_string(&sender_pay_token).unwrap().as_str(), + "\', \'receiver_pay_token\':\'", serde_json::to_string(&receiver_pay_token).unwrap().as_str(), + "\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + + #[no_mangle] + pub extern fn ffishim_bn256_pay_verify_payment_token(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char, ser_pay_token: *mut c_char) -> *mut c_char { + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); + let mut cust_state = handle_errors!(cust_state_result); + + // Deserialize the pay token + let pay_token_result: ResultSerdeType> = deserialize_result_object(ser_pay_token); + let pay_token = handle_errors!(pay_token_result); + + // verify the pay token and update internal state + let is_pay_valid = cust_state.verify_pay_token(&channel_state, &pay_token); + let ser = ["{\'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), + "\', \'is_pay_valid\':\'", serde_json::to_string(&is_pay_valid).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + // CLOSE + + #[no_mangle] + pub extern fn ffishim_bn256_customer_close(ser_channel_state: *mut c_char, ser_cust_state: *mut c_char) -> *mut c_char { + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the cust state + let cust_state_result: ResultSerdeType> = deserialize_result_object(ser_cust_state); + let cust_state = handle_errors!(cust_state_result); + + let cust_close = bidirectional::customer_close(&channel_state, &cust_state); + let ser = ["{\'cust_close\':\'", serde_json::to_string(&cust_close).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_merchant_close(ser_channel_state: *mut c_char, ser_channel_token: *mut c_char, ser_address: *const c_char, ser_cust_close: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + // Deserialize the channel state + let channel_state_result: ResultSerdeType> = deserialize_result_object(ser_channel_state); + let channel_state = handle_errors!(channel_state_result); + + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token = handle_errors!(channel_token_result); + + // Deserialize the customer close structure + let cust_close_result: ResultSerdeType> = deserialize_result_object(ser_cust_close); + let cust_close = handle_errors!(cust_close_result); + + // Deserialize the merch state + let merch_state_result: ResultSerdeType> = deserialize_result_object(ser_merch_state); + let merch_state = handle_errors!(merch_state_result); + + // Deserialize the destination address as a string + let ser_addr_bytes = unsafe { CStr::from_ptr(ser_address).to_bytes() }; + let address: &str = str::from_utf8(ser_addr_bytes).unwrap(); // make sure the bytes are UTF-8 + + let option = bidirectional::merchant_close(&channel_state, &channel_token, &cust_close, &merch_state); + let keys = match option { + Ok(n) => n.unwrap(), + Err(err) => return error_message(err), + }; + + let merch_close: bidirectional::ChannelcloseM = merch_state.sign_revoke_message(address.to_string(), &keys.revoke_token); + + let ser = ["{\'wpk\':\'", serde_json::to_string(&keys.wpk).unwrap().as_str(), + "\', \'merch_close\':\'", serde_json::to_string(&merch_close).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_wtp_verify_cust_close_message(ser_channel_token: *mut c_char, ser_wpk: *mut c_char, ser_close_msg: *mut c_char, ser_close_token: *mut c_char) -> *mut c_char { + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token = handle_errors!(channel_token_result); + + // Deserialize the wpk + let wpk_result: ResultSerdeType = deserialize_result_object(ser_wpk); + let wpk = handle_errors!(wpk_result); + + // Deserialize the close wallet + let close_msg_result: ResultSerdeType> = deserialize_result_object(ser_close_msg); + let close_msg = handle_errors!(close_msg_result); + + // Deserialize the close token + let close_token_result: ResultSerdeType> = deserialize_result_object(ser_close_token); + let close_token = handle_errors!(close_token_result); + + // check the signatures + let token_valid = bidirectional::wtp_verify_cust_close_message(&channel_token, &wpk, &close_msg, &close_token); + let ser = ["{\"result\":\"", serde_json::to_string(&token_valid).unwrap().as_str(), "\"}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } + + #[no_mangle] + pub extern fn ffishim_bn256_wtp_verify_merch_close_message(ser_channel_token: *mut c_char, ser_wpk: *mut c_char, ser_merch_close: *mut c_char) -> *mut c_char { + // Deserialize the channel token + let channel_token_result: ResultSerdeType> = deserialize_result_object(ser_channel_token); + let channel_token = handle_errors!(channel_token_result); + + // Deserialize the wpk + let wpk_result: ResultSerdeType = deserialize_result_object(ser_wpk); + let wpk = handle_errors!(wpk_result); + + // Deserialize the merch close + //let revoke_token: secp256k1::Signature = deserialize_object(ser_revoke_token); + let merch_close_result: ResultSerdeType = deserialize_result_object(ser_merch_close); + let merch_close = handle_errors!(merch_close_result); + + let revoke_token_valid = bidirectional::wtp_verify_revoke_message(&wpk, &merch_close.revoke.unwrap()); + let merch_close_valid = bidirectional::wtp_verify_merch_close_message(&channel_token, &merch_close); + let token_valid = revoke_token_valid && merch_close_valid; + + let ser = ["{\'result\':\'", serde_json::to_string(&token_valid).unwrap().as_str(), "\'}"].concat(); + let cser = CString::new(ser).unwrap(); + cser.into_raw() + } +} diff --git a/src/lib.rs b/src/lib.rs index c58820c..9532a0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,16 +13,15 @@ #![allow(non_upper_case_globals)] #![allow(unused_results)] #![allow(missing_docs)] -#![feature(exclusive_range_pattern)] #![cfg_attr(all(test, feature = "unstable"), feature(test))] #[cfg(all(test, feature = "unstable"))] extern crate test; -extern crate ff; -extern crate pairing; +extern crate ff_bl as ff; +extern crate pairing_bl as pairing; extern crate rand; -extern crate rand_core; +// extern crate rand_core; extern crate secp256k1; extern crate time; @@ -32,9 +31,11 @@ extern crate serde; extern crate serde_with; extern crate libc; +extern crate hex; #[cfg(test)] extern crate core; +extern crate serde_json; pub mod cl; pub mod ccs08; @@ -44,6 +45,7 @@ pub mod nizk; pub mod util; pub mod wallet; pub mod ffishim; +pub mod ffishim_bn256; use std::fmt; use std::str; @@ -159,10 +161,6 @@ pub mod bidirectional { pub signature: secp256k1::Signature, } - pub fn init() { - //sodiumoxide::init(); - } - /// /// init_merchant - takes as input the public params, merchant balance and keypair. /// Generates merchant data which consists of channel token and merchant state. @@ -507,6 +505,180 @@ pub mod bidirectional { } } +pub mod wtp_utils { + // Useful routines that simplify the Bolt WTP implementation for Zcash + use pairing::bls12_381::Bls12; + use ::{util, BoltResult}; + use cl; + use ped92::CSMultiParams; + pub use cl::Signature; + pub use channels::ChannelToken; + pub use wallet::Wallet; + use channels::ChannelcloseM; + + const BLS12_381_CHANNEL_TOKEN_LEN: usize = 1074; + const BLS12_381_G1_LEN: usize = 48; + const BLS12_381_G2_LEN: usize = 96; + const SECP256K1_PK_LEN: usize = 33; + const ADDRESS_LEN: usize = 33; + + pub fn reconstruct_secp_public_key(pk_bytes: &[u8; SECP256K1_PK_LEN]) -> secp256k1::PublicKey { + return secp256k1::PublicKey::from_slice(pk_bytes).unwrap(); + } + + pub fn reconstruct_secp_signature(sig_bytes: &[u8]) -> secp256k1::Signature { + return secp256k1::Signature::from_der(sig_bytes).unwrap(); + } + + pub fn reconstruct_close_wallet_bls12(channel_token: &ChannelToken, wpk: &secp256k1::PublicKey, cust_bal: u32, merch_bal: u32) -> Wallet { + let channelId = channel_token.compute_channel_id(); + let wpk_h = util::hash_pubkey_to_fr::(&wpk); + let close = util::hash_to_fr::(String::from("close").into_bytes()); + + return Wallet { + channelId, wpk: wpk_h, bc: cust_bal as i64, bm: merch_bal as i64, close: Some(close) + } + } + + pub fn reconstruct_signature_bls12(sig: &Vec) -> BoltResult> { + if (sig.len() != BLS12_381_G1_LEN * 2) { + return Err(String::from("signature has invalid length")); + } + + let mut cur_index = 0; + let mut end_index = BLS12_381_G1_LEN; + let ser_cl_h = sig[cur_index .. end_index].to_vec(); + let str_cl_h = util::encode_as_hexstring(&ser_cl_h); + let h = str_cl_h.as_bytes(); + + cur_index = end_index; + end_index += BLS12_381_G1_LEN; + let ser_cl_H = sig[cur_index .. end_index].to_vec(); + let str_cl_H = util::encode_as_hexstring(&ser_cl_H); + let H = str_cl_H.as_bytes(); + + let cl_sig = cl::Signature::::from_slice(&h, &H); + + Ok(Some(cl_sig)) + } + + pub fn reconstruct_channel_token_bls12(channel_token: &Vec) -> BoltResult> + { + // parse pkc, pkm, pkM, mpk and comParams + if channel_token.len() != BLS12_381_CHANNEL_TOKEN_LEN { + return Err(String::from("could not reconstruct the channel token!")); + } + + let num_y_elems = 5; + let num_com_params= 6; + + let mut cur_index = 0; + let mut end_index = SECP256K1_PK_LEN; + let pkc = secp256k1::PublicKey::from_slice(&channel_token[cur_index .. end_index]).unwrap(); + + cur_index = end_index; + end_index += SECP256K1_PK_LEN; + let pkm = secp256k1::PublicKey::from_slice(&channel_token[cur_index .. end_index]).unwrap(); + + cur_index = end_index; + end_index += BLS12_381_G2_LEN; // pk_M => (X, Y) + let ser_cl_x = channel_token[cur_index .. end_index].to_vec(); + let str_cl_x = util::encode_as_hexstring(&ser_cl_x); + let X = str_cl_x.as_bytes(); + + let mut Y = Vec::new(); + for _ in 0 .. num_y_elems { + cur_index = end_index; + end_index += BLS12_381_G2_LEN; + let cl_y = channel_token[cur_index .. end_index].to_vec(); + let ser_cl_y = util::encode_as_hexstring(&cl_y); + let str_cl_y = ser_cl_y.as_bytes(); + Y.extend(str_cl_y); + } + let cl_pk= cl::PublicKey::::from_slice(&X, &Y.as_slice(), str_cl_x.len(), num_y_elems); + + cur_index = end_index; + end_index += BLS12_381_G1_LEN; + let g1 = channel_token[cur_index .. end_index].to_vec(); + let ser_mpk_g1 = util::encode_as_hexstring(&g1); + + cur_index = end_index; + end_index += BLS12_381_G2_LEN; + let g2 = channel_token[cur_index .. end_index].to_vec(); + let ser_mpk_g2 = util::encode_as_hexstring(&g2); + + let ser_g1 = ser_mpk_g1.as_bytes(); + let ser_g2 = ser_mpk_g2.as_bytes(); + + let mpk = cl::PublicParams::::from_slice(&ser_g1, &ser_g2); + + let mut comparams = Vec::new(); + for _ in 0 .. num_com_params { + cur_index = end_index; + end_index += BLS12_381_G1_LEN; + let com = channel_token[cur_index .. end_index].to_vec(); + let ser_com = util::encode_as_hexstring(&com); + let str_com = ser_com.as_bytes(); + comparams.extend(str_com); + } + + let com_params = CSMultiParams::::from_slice(&comparams.as_slice(), ser_mpk_g1.len(), num_com_params); + + Ok(Some(ChannelToken { + pk_c: Some(pkc), pk_m: pkm, cl_pk_m: cl_pk, mpk: mpk, comParams: com_params + })) + } + + /// + /// Used in open-channel WTP for validating that a close_token is a valid signature + /// + pub fn wtp_verify_cust_close_message(channel_token: &ChannelToken, wpk: &secp256k1::PublicKey, + close_msg: &Wallet, close_token: &cl::Signature) -> bool { + // close_msg => || || || || CLOSE + // close_token = regular CL signature on close_msg + // channel_token => + + // (1) check that channel token and close msg are consistent (e.g., close_msg.channelId == H(channel_token.pk_c) && + let chan_token_cid = channel_token.compute_channel_id(); // util::hash_pubkey_to_fr::(&pk_c); + let chan_token_wpk = util::hash_pubkey_to_fr::(&wpk); + + let cid_thesame = (close_msg.channelId == chan_token_cid); + // (2) check that wpk matches what's in the close msg + let wpk_thesame = (close_msg.wpk == chan_token_wpk); + return cid_thesame && wpk_thesame && channel_token.cl_pk_m.verify(&channel_token.mpk, &close_msg.as_fr_vec(), &close_token); + } + + pub fn wtp_generate_secp_signature(seckey: &[u8; 32], msg: &[u8; 32]) -> Vec { + let secp = secp256k1::Secp256k1::signing_only(); + + let msg = secp256k1::Message::from_slice(msg).unwrap(); + let seckey = secp256k1::SecretKey::from_slice(seckey).unwrap(); + let sig = secp.sign(&msg, &seckey); + + // get serialized signature + let ser_sig = sig.serialize_der(); + + return ser_sig.to_vec(); + } + + pub fn wtp_verify_secp_signature(pubkey: &secp256k1::PublicKey, hash: &Vec, sig: &secp256k1::Signature) -> bool { + let secp = secp256k1::Secp256k1::verification_only(); + let msg = secp256k1::Message::from_slice(hash.as_slice()).unwrap(); + + return secp.verify(&msg, &sig, &pubkey).is_ok() + } + + pub fn reconstruct_secp_channel_close_m(address: &[u8; ADDRESS_LEN], ser_revoke_token: &Vec, ser_sig: &Vec) -> ChannelcloseM { + let revoke_token = secp256k1::Signature::from_der(&ser_revoke_token.as_slice()).unwrap(); + let sig = secp256k1::Signature::from_der(&ser_sig.as_slice()).unwrap(); + ChannelcloseM { + address: hex::encode(&address.to_vec()), + revoke: Some(revoke_token), + signature: sig, + } + } +} + #[cfg(all(test, feature = "unstable"))] mod benches { use rand::{Rng, thread_rng}; @@ -523,6 +695,7 @@ mod tests { use super::*; use pairing::bls12_381::Bls12; use rand::Rng; + use sha2::Digest; fn setup_new_channel_helper(channel_state: &mut bidirectional::ChannelState, init_cust_bal: i64, init_merch_bal: i64) @@ -899,4 +1072,91 @@ mod tests { let _des_cw: bidirectional::CustomerState = serde_json::from_str(&serialized_cw).unwrap(); } + + #[test] + fn test_reconstruct_channel_token() { + let _ser_channel_token = "024c252c7e36d0c30ae7c67dabea2168f41b36b85c14d3e180b423fa1a5df0e7ac027df0457901953b9b776f4999d5a1e78\ + 049c0afa4f741d0d3bb7d9711a0f8c0038f4c70072363fe07ffe1450d63205cbaeaafe600ca9001d8bbf8984ce54a9c5e041084779dace7a4cf582906ea4e\ + 493a1368ec7f05e7f89635c555c26e5d0149186095856dc210bef4b8fec03415cd6d1253bdafd0934a20b57ee088fa7ee0bab0668b1aa84c30e856dd685ce\ + e2a95844cb68504e82fd9dd874cbf6f7ee58155245e97c52625b53f4ca969f48b33c59f0009adc70d1472a303a35ace0d96149c8cdb96f29b6f476b8f4a10\ + bd430c4658d4e0b5873fcb946a76aa861c6c4c601ab8fb0b9c88d2e8861de2f0dae2bb2a8492db2978ce8f2e509328efbf12384ae2db5c17021d222724a3b\ + c4b621bf4f32601d555ff2cfc2171adeb2f1bd42c484c1c0a1e5d7d2853c102080680cefc925808b6e3d71b29a93f7e8f5c2eeeeef944b3740feddb24ec2c\ + 17e3db22ee6a7af77e32a9d186bdcc150dd59b0cd92b92b6656cb588dec9d1d07be5e2a319bf37f1120b7c656f78dc6c4064f8d63f590f70cdc0c1746fde6\ + 035eeb9aa90b69ea666ad71b27078ab61573aec60bab80a4e6a8e4d8ce02204f5b7e0131bf24d5df1428e9e571891c6feb1c0a52ba789136b244f13f510c4\ + f1f0eb4b0a7e675f105f8102c672461da340ebcae1eddd49a009bcf3b199eb2006fab6cf0ccf102b5c6dd45722dc0c27d4b9697f627f1bcbe44f6d96842de\ + c92877ff23d374964970c3386972a8ae369367907001bcd8bba458b8f29842321a8231f3441054999cb19b2c40409da8216406298e1d41bcaf5ea8a225266\ + 2848d3f810dd369aba5ff684360080aa6f5e9ba61be1331f6bdf8b00d1ec8453637c4b480f6d0c5e5467013aa0e8be1777c370a1988db21d8d3de3f6d79d8\ + cbe6412f88d39de0cd1bf9e8f9b57ff933f21bef89b5bd3f9a901936568db58cc8326a719bf56438bbcab659a20ea5c0342eb9f072f105303c90de3b3b865\ + 66155899d05d00396cfae74ac0526f0dd30c33e0c6790f3f8119dac12fb6f870b9a317afa94cd624b88ede30d49d2373b58453637c4b480f6d0c5e5467013\ + aa0e8be1777c370a1988db21d8d3de3f6d79d8cbe6412f88d39de0cd1bf9e8f9b57ffa397625c859a63e2c6e42486c4f76f306d484cce151f8614f87506e9\ + 9c871521dd244bfeb380481aed8df823a507c7a3ad367c1797fc6efa089f929729e7d48bfa9c60860fbb212918bb91d8c6aa523046bdf208c95fa5a0fb86a\ + 1e46f92e0e5893e136b74d38e106fa990590598932a4e2458034cea22337c6f365bcb5cab59ceea03d7a9f7821ea432e262877ef0128cb73d8733c3961762\ + 26acb6b3de132c803be39a4e803cbc5a4670cb6169583fa899146fab0227dc2ae167393f96f3b8b31e015af1c305de3a07f52408e9c52495c2458ea05c7a3\ + 71dc14f3b1d6a646ed7cc0ca9417d8bde6efc1ac300d8e28f"; + let ser_channel_token = hex::decode(_ser_channel_token).unwrap(); + + let option_ct = wtp_utils::reconstruct_channel_token_bls12(&ser_channel_token); + let channel_token = match option_ct { + Ok(n) => n.unwrap(), + Err(e) => panic!("Error reconstructing compact rep of channel token: {}", e) + }; + + let channelId = channel_token.compute_channel_id(); + + let original_channelId = "[\"0744645c9cbbf4e47f456fa05e2c6888a59f688641d25b2607610ce03b4ae20c\"]"; + let computed_channelId = serde_json::to_string(&channelId).unwrap(); + + println!("channel ID: {}", channelId); + println!("pkc: {:?}", channel_token.pk_c.unwrap()); + println!("pkm: {:?}", channel_token.pk_m); + + assert_eq!(original_channelId, computed_channelId); + + // reconstruct signature + let _ser_signature = "93f26490b4576c38dfb8dceae547f4b49aeb945ecc9cccc528c39068c78177bda68aaf45743f09c48ad99b6007fe415b\ + aee9eafd51cfdb0dc567a5d152bc37861727e85088b417cf3ff57c108d0156eee56aff810f1e5f9e76cd6a3590d6db5e"; + let ser_signature = hex::decode(_ser_signature).unwrap(); + + let option_sig = wtp_utils::reconstruct_signature_bls12(&ser_signature); + + let sig = match option_sig { + Ok(n) => n.unwrap(), + Err(e) => panic!("Error reconstructing compact rep of signature: {}", e) + }; + } + + #[test] + fn test_reconstruct_secp_sig() { + let _ser_sig = "3044022064650285b55624f1f64b2c75e76589fa4b1033dabaa7ff50ff026e1dc038279202204ca696e0a829687c87171e8e5dab17069be248ff2595fd9607f3346dadcb579f"; + let ser_sig = hex::decode(_ser_sig).unwrap(); + + let signature = wtp_utils::reconstruct_secp_signature(ser_sig.as_slice()); + assert_eq!(format!("{:?}", signature), _ser_sig); + + let sk = hex::decode("81361b9bc2f67524dcc59b980dc8b06aadb77db54f6968d2af76ecdb612e07e4").unwrap(); + let msg = "hello world!"; + let mut sha256 = sha2::Sha256::new(); + sha256.input(msg); + let mut hash = [0u8; 32]; + hash.copy_from_slice(&sha256.result()); + + let mut seckey = [0u8; 32]; + seckey.copy_from_slice(sk.as_slice()); + let sig = wtp_utils::wtp_generate_secp_signature(&seckey, &hash); + } + + #[test] + fn test_reconstruct_channel_close_m() { + let mut address = [0u8; 33]; + let address_slice = hex::decode("0a1111111111111111111111111111111111111111111111111111111111111111").unwrap(); + address.copy_from_slice(address_slice.as_slice()); + + let channelClose = wtp_utils::reconstruct_secp_channel_close_m(&address, + &hex::decode("3044022041932b376fe2c5e9e9ad0a3804e2290c3bc40617ea4f7b913be858dbcc3760b50220429d6eb1aabbd4135db4e0776c0b768af844b0af44f2f8f9da5a65e8541b4e9f").unwrap(), + &hex::decode("3045022100e76653c5f8cb4c2f39efc7c5450d4f68ef3d84d482305534f5dfc310095a3124022003c4651ce1305cffe5e483ab99925cc4c9c5df2b5449bb18a51d52b21d789716").unwrap()); + + assert_eq!(channelClose.address, "0a1111111111111111111111111111111111111111111111111111111111111111"); + assert_eq!(format!("{:?}", channelClose.revoke.unwrap()), "3044022041932b376fe2c5e9e9ad0a3804e2290c3bc40617ea4f7b913be858dbcc3760b50220429d6eb1aabbd4135db4e0776c0b768af844b0af44f2f8f9da5a65e8541b4e9f"); + assert_eq!(format!("{:?}", channelClose.signature), "3045022100e76653c5f8cb4c2f39efc7c5450d4f68ef3d84d482305534f5dfc310095a3124022003c4651ce1305cffe5e483ab99925cc4c9c5df2b5449bb18a51d52b21d789716"); + } } diff --git a/src/nizk.rs b/src/nizk.rs index ec9729d..a95ac40 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -1,6 +1,3 @@ -extern crate pairing; -extern crate rand; - use super::*; use rand::Rng; use cl::{Signature, PublicParams, setup, BlindKeyPair, SignatureProof, BlindPublicKey}; diff --git a/src/ped92.rs b/src/ped92.rs index 53d59bc..35223e4 100644 --- a/src/ped92.rs +++ b/src/ped92.rs @@ -1,5 +1,5 @@ // ped92.rs -use rand::Rng; +use rand::{Rng, AsByteSliceMut}; use pairing::{Engine, CurveProjective}; use ff::{Rand, Field, PrimeField}; use std::fmt; @@ -40,6 +40,24 @@ impl PartialEq for CSMultiParams { } } +impl CSMultiParams { + pub fn from_slice<'de>(ser_gs: &'de [u8], g_len: usize, num_elems: usize) -> Self + where ::G1: serde::Deserialize<'de> + { + let mut pub_bases: Vec = Vec::new(); + let mut start_pos = 0; + let mut end_pos = g_len; + for _ in 0 .. num_elems { + let g: E::G1 = serde_json::from_slice(&ser_gs[start_pos .. end_pos]).unwrap(); + start_pos = end_pos; + end_pos += g_len; + pub_bases.push(g); + } + + return CSMultiParams { pub_bases}; + } +} + impl fmt::Display for CSMultiParams { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -369,5 +387,39 @@ mod tests { assert_eq!(proof.verify_proof(&comParams, &com.c, &challenge, None), true); } - // add tests for extend/remove commits dynamically + #[test] + fn test_cs_multiparam_serialization() { + + let mut vec: Vec = Vec::new(); + let bin_g1= vec![132, 83, 99, 124, 75, 72, 15, 109, 12, 94, 84, 103, 1, 58, 160, 232, 190, 23, 119, 195, 112, 161, 152, 141, 178, 29, 141, 61, 227, 246, 215, 157, 140, 190, 100, 18, 248, 141, 57, 222, 12, 209, 191, 158, 143, 155, 87, 255]; + let bin_g2 = vec![140, 16, 244, 244, 135, 28, 18, 94, 46, 64, 233, 195, 218, 147, 238, 170, 46, 164, 50, 92, 234, 117, 61, 158, 64, 226, 153, 38, 127, 168, 49, 125, 177, 183, 74, 164, 138, 128, 168, 84, 137, 67, 21, 179, 124, 88, 194, 239]; + let bin_g3 = vec![147, 174, 242, 238, 231, 127, 9, 120, 16, 9, 191, 238, 60, 57, 106, 34, 198, 62, 28, 183, 77, 170, 27, 116, 36, 75, 242, 26, 242, 23, 213, 31, 186, 21, 141, 219, 59, 104, 247, 118, 56, 95, 183, 124, 103, 83, 93, 154]; + + let ser_g1 = util::encode_as_hexstring(&bin_g1); + let ser_g2 = util::encode_as_hexstring(&bin_g2); + let ser_g3 = util::encode_as_hexstring(&bin_g3); + + let str_g1 = ser_g1.as_bytes(); + let str_g2 = ser_g2.as_bytes(); + let str_g3 = ser_g3.as_bytes(); + + vec.extend(str_g1); + vec.extend(str_g2); + vec.extend(str_g3); + + let rec_csparams = CSMultiParams::::from_slice(&vec.as_slice(), str_g1.len(), 3); + println!("CS params: {:?}", rec_csparams.pub_bases); + + let ser_cs = serde_json::to_string(&rec_csparams).unwrap(); + + println!("Serialized: {:}", ser_cs); + let rec_g1_str = serde_json::to_string(&rec_csparams.pub_bases[0]).unwrap(); + assert_eq!(rec_g1_str, "\"8453637c4b480f6d0c5e5467013aa0e8be1777c370a1988db21d8d3de3f6d79d8cbe6412f88d39de0cd1bf9e8f9b57ff\""); + + let rec_g2_str = serde_json::to_string(&rec_csparams.pub_bases[1]).unwrap(); + assert_eq!(rec_g2_str, "\"8c10f4f4871c125e2e40e9c3da93eeaa2ea4325cea753d9e40e299267fa8317db1b74aa48a80a854894315b37c58c2ef\""); + + let rec_g3_str = serde_json::to_string(&rec_csparams.pub_bases[2]).unwrap(); + assert_eq!(rec_g3_str, "\"93aef2eee77f09781009bfee3c396a22c63e1cb74daa1b74244bf21af217d51fba158ddb3b68f776385fb77c67535d9a\""); + } } diff --git a/src/util.rs b/src/util.rs index c15cfa1..fcfa4e2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -24,6 +24,12 @@ pub fn is_vec_g2_equal(a: &Vec, b: &Vec) -> bool { .all(|(a, b)| a == b) } +pub fn encode_as_hexstring(bytes: &Vec) -> String { + let mut ser_hex = hex::encode(bytes); + ser_hex.insert(0, '"'); + ser_hex.push('"'); + return ser_hex; +} pub fn hash_g1_to_fr(x: &Vec) -> E::Fr { let mut x_vec: Vec = Vec::new(); @@ -39,7 +45,7 @@ pub fn hash_g2_to_fr(x: &E::G2) -> E::Fr { hash_to_fr::(x_vec) } -pub fn fmt_bytes_to_int(bytearray: [u8; 64]) -> String { +pub fn fmt_bytes_to_int(bytearray: [u8; 32]) -> String { let mut result: String = "".to_string(); for byte in bytearray.iter() { // Decide if you want upper- or lowercase results, @@ -55,12 +61,13 @@ pub fn fmt_bytes_to_int(bytearray: [u8; 64]) -> String { return s; } + pub fn compute_the_hash(bytes: &Vec) -> E::Fr { - let mut hasher = sha2::Sha512::new(); + let mut hasher = sha2::Sha256::new(); hasher.input(&bytes.as_slice()); let sha2_digest = hasher.result(); - let mut hash_buf: [u8; 64] = [0; 64]; - hash_buf.copy_from_slice(&sha2_digest[0..64]); + let mut hash_buf: [u8; 32] = [0; 32]; + hash_buf.copy_from_slice(&sha2_digest); let hexresult = fmt_bytes_to_int(hash_buf); return E::Fr::from_str(&hexresult).unwrap(); } @@ -89,10 +96,9 @@ pub fn convert_int_to_fr(value: i64) -> E::Fr { pub fn compute_pub_key_fingerprint(wpk: &secp256k1::PublicKey) -> String { let x_slice = wpk.serialize(); - let mut hasher = sha2::Sha512::new(); + let mut hasher = sha2::Sha256::new(); hasher.input(&x_slice.to_vec()); let sha2_digest = hasher.result(); - // let sha2_digest = sha512::hash(&x_slice); let h = format!("{:x}", HexSlice::new(&sha2_digest[0..16])); return h; } @@ -105,12 +111,12 @@ pub fn hash_buffer_to_fr<'a, E: Engine>(prefix: &'a str, buf: &[u8; 64]) -> E::F } pub fn hash_to_slice(input_buf: &Vec) -> [u8; 32] { - let mut hasher = sha2::Sha512::new(); + let mut hasher = sha2::Sha256::new(); hasher.input(&input_buf.as_slice()); let sha2_digest = hasher.result(); let mut hash_buf: [u8; 32] = [0; 32]; - hash_buf.copy_from_slice(&sha2_digest[0..32]); + hash_buf.copy_from_slice(&sha2_digest); return hash_buf; } @@ -158,7 +164,7 @@ mod tests { let mut two = G2::one(); two.double(); assert_eq!(format!("{}", hash_g2_to_fr::(&two).into_repr()), - "0x27cd26f702a777dbf782534ae6bf2ec4aa6cb4617c8366f10f59bef13beb8c56"); + "0x6550a1431236024424ac8e7f65781f244b70a38e5b3c275000a2b91089706868"); } #[test] @@ -168,13 +174,13 @@ mod tests { let mut x_vec: Vec = Vec::new(); x_vec.extend(format!("{}", two).bytes()); assert_eq!(format!("{}", hash_to_fr::(x_vec).into_repr()), - "0x27cd26f702a777dbf782534ae6bf2ec4aa6cb4617c8366f10f59bef13beb8c56"); + "0x6550a1431236024424ac8e7f65781f244b70a38e5b3c275000a2b91089706868"); } #[test] fn fmt_byte_to_int_works() { - assert_eq!(fmt_bytes_to_int([12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123]), - "122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123134312235231231343122352312313431223523123"); + assert_eq!(fmt_bytes_to_int([12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235]), // , 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123, 13, 43, 12, 235, 23, 123]), + "122352312313431223523123134312235231231343122352312313431223523123134312235"); } #[test] diff --git a/src/wallet.rs b/src/wallet.rs index 67228b4..1f881cc 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -1,5 +1,3 @@ -extern crate pairing; - use super::*; use pairing::Engine; use ff::PrimeField;