Merge pull request #24 from boltlabs-inc/intermediary

Intermediary
This commit is contained in:
J. Ayo Akinyele 2019-10-14 10:28:53 -04:00 committed by GitHub
commit 4bcd94ce5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 463 additions and 214 deletions

View File

@ -10,53 +10,95 @@ import (
)
type setupResp struct {
ChannelState string `json:"channel_state"`
ChannelToken string `json:"channel_token"`
CustState string `json:"cust_state"`
MerchState string `json:"merch_state"`
Com string `json:"com"`
ComProof string `json:"com_proof"`
IsTokenValid bool `json:"is_token_valid,string"`
IsEstablished bool `json:"is_established,string"`
IsPayValid bool `json:"is_pay_valid,string"`
Payment string `json:"payment"`
CloseToken string `json:"close_token"`
RevokeToken string `json:"revoke_token"`
PayToken string `json:"pay_token"`
CustClose string `json:"cust_close"`
MerchClose string `json:"merch_close"`
Wpk string `json:"wpk"`
Error string `json:"error"`
Result string `json:"result"`
ChannelState string `json:"channel_state"`
ChannelToken string `json:"channel_token"`
CustState string `json:"cust_state"`
MerchState string `json:"merch_state"`
Com string `json:"com"`
ComProof string `json:"com_proof"`
IsTokenValid bool `json:"is_token_valid,string"`
IsEstablished bool `json:"is_established,string"`
IsPayValid bool `json:"is_pay_valid,string"`
Payment string `json:"payment"`
CloseToken string `json:"close_token"`
SenderCloseToken string `json:"sender_close_token"`
ReceiverCondCloseToken string `json:"receiver_cond_close_token"`
RevokeToken string `json:"revoke_token"`
PayToken string `json:"pay_token"`
SenderPayToken string `json:"sender_pay_token"`
ReceiverPayToken string `json:"receiver_pay_token"`
CustClose string `json:"cust_close"`
MerchClose string `json:"merch_close"`
Wpk string `json:"wpk"`
Error string `json:"error"`
Result string `json:"result"`
}
type ChannelState struct {
R int `json:"R"`
TxFee int64 `json:"tx_fee"`
Cp interface{} `json:"cp"`
Name string `json:"name"`
PayInit bool `json:"pay_init"`
ChannelEstablished bool `json:"channel_established"`
ThirdParty bool `json:"third_party"`
R int `json:"R"`
TxFee int64 `json:"tx_fee"`
Cp *ChannelParams `json:"cp"`
Name string `json:"name"`
PayInit bool `json:"pay_init"`
ChannelEstablished bool `json:"channel_established"`
ThirdParty bool `json:"third_party"`
}
type ChannelParams struct {
ExtraVerify bool `json:"extra_verify"`
L int64 `json:"l"`
PubParams PubParams `json:"pub_params"`
}
type PubParams struct {
ComParams ComParams `json:"comParams"`
Mpk MPK `json:"mpk"`
Pk PublicKey `json:"pk"`
RpParams RpPubParams `json:"rpParams"`
}
type RpPubParams struct {
ComParams ComParams `json:"csParams"`
L int64 `json:"l"`
U int64 `json:"u"`
Mpk MPK `json:"mpk"`
Pk PublicKey `json:"pk"`
Signatures map[string]Signature `json:"signatures"`
}
type MerchState struct {
Id string `json:"id"`
KeyPair KeyPair `json:"keypair"`
NizkParams interface{} `json:"nizkParams"`
Pk string `json:"pk"`
Sk string `json:"sk"`
ComParams ComParams `json:"comParams"`
Keys interface{} `json:"keys"`
PayTokens interface{} `json:"pay_tokens"`
Id string `json:"id"`
KeyPair KeyPair `json:"keypair"`
NizkParams NIZKParams `json:"nizkParams"`
Pk string `json:"pk"`
Sk string `json:"sk"`
ComParams ComParams `json:"comParams"`
Keys map[string]RevokedKey `json:"keys"`
PayTokens map[string]Signature `json:"pay_tokens"`
}
type RevokedKey struct {
Wpk string `json:"wpk"`
RevokeToken *string `json:"revoke_token"`
}
type NIZKParams struct {
PubParams PubParams `json:"pubParams"`
KeyPair KeyPair `json:"keypair"`
RpParams RpParams `json:"rpParams"`
}
type RpParams struct {
PubParams RpPubParams `json:"pubParams"`
KeyPair KeyPair `json:"kp"`
}
type CustState struct {
Name string `json:"name"`
PkC string `json:"pk_c"`
SkC string `json:"sk_c"`
CustBalance int64 `json:"cust_balance"`
MerchBalance int64 `json:"merch_balance"`
CustBalance int64 `json:"cust_balance"`
MerchBalance int64 `json:"merch_balance"`
Wpk string `json:"wpk"`
Wsk string `json:"wsk"`
OldKP *KP `json:"old_kp,omitempty"`
@ -80,8 +122,8 @@ type Commitment struct {
type Wallet struct {
Pkc []string `json:"pkc"`
Wpk []string `json:"wpk"`
Bc int64 `json:"bc"`
Bm int64 `json:"bm"`
Bc int64 `json:"bc"`
Bm int64 `json:"bm"`
Close []string `json:"close"`
}
@ -95,6 +137,36 @@ type SecretKey struct {
Y [][]string `json:"y"`
}
type Payment struct {
Proof Proof `json:"proof"`
Com Commitment `json:"com"`
Wpk string `json:"wpk"`
Amount int64 `json:"amount"`
}
type Proof struct {
Sig Signature `json:"sig"`
SigProof SigProof `json:"sigProof"`
ComProof CommitmentProof `json:"comProof"`
RangeProofBC RangeProof `json:"rpBC"`
RangeProofBM RangeProof `json:"rpBM"`
}
type SigProof struct {
Zsig [][]string `json:"zsig"`
Zv []string `json:"zv"`
A interface{} `json:"a"`
}
type RangeProof struct {
V []Signature `json:"V"`
D string `json:"D"`
Com Commitment `json:"comm"`
SigProofs []SigProof `json:"sigProofs"`
Zr []string `json:"zr"`
Zs [][]string `json:"zs"`
}
type PublicKey struct {
X1 string `json:"X1"`
X2 string `json:"X2"`
@ -331,7 +403,7 @@ func BidirectionalEstablishCustomerFinal(channelState ChannelState, custState Cu
resp := C.GoString(C.ffishim_bidirectional_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
return false, ChannelState{}, CustState{}, err
}
err = json.Unmarshal([]byte(r.ChannelState), &channelState)
if err != nil {
@ -341,34 +413,43 @@ func BidirectionalEstablishCustomerFinal(channelState ChannelState, custState Cu
return r.IsEstablished, channelState, custState, err
}
func BidirectionalPayGeneratePaymentProof(channelState ChannelState, custState CustState, amount int) (string, CustState, error) {
func BidirectionalPayGeneratePaymentProof(channelState ChannelState, custState CustState, amount int) (Payment, CustState, error) {
serChannelState, err := json.Marshal(channelState)
if err != nil {
return "", CustState{}, err
return Payment{}, CustState{}, err
}
serCustState, err := json.Marshal(custState)
if err != nil {
return "", CustState{}, err
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)))
r, err := processCResponse(resp)
if err != nil {
return "", CustState{}, err
return Payment{}, CustState{}, err
}
payProof := Payment{}
err = json.Unmarshal([]byte(r.Payment), &payProof)
if err != nil {
return Payment{}, CustState{}, err
}
err = json.Unmarshal([]byte(r.CustState), &custState)
return r.Payment, custState, err
return payProof, custState, err
}
func BidirectionalPayVerifyPaymentProof(channelState ChannelState, serPayProof string, merchState MerchState) (Signature, MerchState, error) {
func BidirectionalPayVerifyPaymentProof(channelState ChannelState, payProof Payment, merchState MerchState) (Signature, MerchState, error) {
serChannelState, err := json.Marshal(channelState)
if err != nil {
return Signature{}, MerchState{}, err
}
serPayProof, err := json.Marshal(payProof)
if err != nil {
return Signature{}, MerchState{}, err
}
serMerchState, err := json.Marshal(merchState)
if err != nil {
return Signature{}, MerchState{}, err
}
resp := C.GoString(C.ffishim_bidirectional_pay_verify_payment_proof(C.CString(string(serChannelState)), C.CString(serPayProof), C.CString(string(serMerchState))))
resp := C.GoString(C.ffishim_bidirectional_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
@ -382,6 +463,42 @@ func BidirectionalPayVerifyPaymentProof(channelState ChannelState, serPayProof s
return *closeToken, merchState, err
}
func BidirectionalPayVerifyMultiplePaymentProofs(channelState ChannelState, senderPayProof Payment, receiverPayProof Payment, merchState MerchState) (Signature, Signature, MerchState, error) {
serChannelState, err := json.Marshal(channelState)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
serSenderPayProof, err := json.Marshal(senderPayProof)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
serReceiverPayProof, err := json.Marshal(receiverPayProof)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
serMerchState, err := json.Marshal(merchState)
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))))
r, err := processCResponse(resp)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
err = json.Unmarshal([]byte(r.MerchState), &merchState)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
senderCloseToken := &Signature{}
err = json.Unmarshal([]byte(r.SenderCloseToken), senderCloseToken)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
receiverCondCloseToken := &Signature{}
err = json.Unmarshal([]byte(r.ReceiverCondCloseToken), receiverCondCloseToken)
return *senderCloseToken, *receiverCondCloseToken, merchState, err
}
func BidirectionalPayGenerateRevokeToken(channelState ChannelState, custState CustState, newCustState CustState, closeToken Signature) (RevokeToken, CustState, error) {
serChannelState, err := json.Marshal(channelState)
if err != nil {
@ -436,6 +553,38 @@ func BidirectionalPayVerifyRevokeToken(revokeToken RevokeToken, merchState Merch
return *payToken, merchState, err
}
func BidirectionalPayVerifyMultipleRevokeTokens(senderRevokeToken RevokeToken, receiverRevokeToken RevokeToken, merchState MerchState) (Signature, Signature, MerchState, error) {
serMerchState, err := json.Marshal(merchState)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
serSenderRevokeToken, err := json.Marshal(senderRevokeToken)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
serReceiverRevokeToken, err := json.Marshal(receiverRevokeToken)
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))))
r, err := processCResponse(resp)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
err = json.Unmarshal([]byte(r.MerchState), &merchState)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
senderPayToken := &Signature{}
err = json.Unmarshal([]byte(r.SenderPayToken), senderPayToken)
if err != nil {
return Signature{}, Signature{}, MerchState{}, err
}
receiverPayToken := &Signature{}
err = json.Unmarshal([]byte(r.ReceiverPayToken), receiverPayToken)
return *senderPayToken, *receiverPayToken, merchState, err
}
func BidirectionalPayVerifyPaymentToken(channelState ChannelState, custState CustState, payToken Signature) (CustState, bool, error) {
serChannelState, err := json.Marshal(channelState)
if err != nil {

View File

@ -83,6 +83,59 @@ func Test_Pay(t *testing.T) {
assert.True(t, isTokenValid)
}
func Test_IntermediaryPay(t *testing.T) {
b0Alice := 1000
b0Bob := 100
b0Intermediary := 100
channelState, err := BidirectionalChannelSetup("Test Channel", false)
assert.Nil(t, err)
channelToken, merchState, channelState, err := BidirectionalInitMerchant(channelState, "Hub")
assert.Nil(t, err)
channelToken, custStateAlice, err := BidirectionalInitCustomer(channelToken, b0Alice, b0Intermediary, "Alice")
assert.Nil(t, err)
channelToken, custStateAlice, com, comProof, err := BidirectionalEstablishCustomerGenerateProof(channelToken, custStateAlice)
assert.Nil(t, err)
closeToken, err := BidirectionalEstablishMerchantIssueCloseToken(channelState, com, comProof, custStateAlice.PkC, b0Alice, b0Intermediary, merchState)
assert.Nil(t, err)
_, channelState, custStateAlice, err = BidirectionalVerifyCloseToken(channelState, custStateAlice, closeToken)
assert.Nil(t, err)
payToken, err := BidirectionalEstablishMerchantIssuePayToken(channelState, com, merchState)
assert.Nil(t, err)
_, channelState, custStateAlice, err = BidirectionalEstablishCustomerFinal(channelState, custStateAlice, payToken)
assert.Nil(t, err)
channelToken, custStateBob, err := BidirectionalInitCustomer(channelToken, b0Bob, b0Intermediary, "Bob")
assert.Nil(t, err)
channelToken, custStateBob, com, comProof, err = BidirectionalEstablishCustomerGenerateProof(channelToken, custStateBob)
assert.Nil(t, err)
closeToken, err = BidirectionalEstablishMerchantIssueCloseToken(channelState, com, comProof, custStateBob.PkC, b0Bob, b0Intermediary, merchState)
assert.Nil(t, err)
_, channelState, custStateBob, err = BidirectionalVerifyCloseToken(channelState, custStateBob, closeToken)
assert.Nil(t, err)
payToken, err = BidirectionalEstablishMerchantIssuePayToken(channelState, com, merchState)
assert.Nil(t, err)
_, channelState, custStateBob, err = BidirectionalEstablishCustomerFinal(channelState, custStateBob, payToken)
assert.Nil(t, err)
paymentA, newCustStateAlice, err := BidirectionalPayGeneratePaymentProof(channelState, custStateAlice, 10)
assert.Nil(t, err)
paymentB, newCustStateBob, err := BidirectionalPayGeneratePaymentProof(channelState, custStateBob, -10)
assert.Nil(t, err)
closeTokenA, closeTokenB, merchState, err := BidirectionalPayVerifyMultiplePaymentProofs(channelState, paymentA, paymentB, merchState)
assert.Nil(t, err)
revokeTokenA, custStateAlice, err := BidirectionalPayGenerateRevokeToken(channelState, custStateAlice, newCustStateAlice, closeTokenA)
assert.Nil(t, err)
revokeTokenB, custStateBob, err := BidirectionalPayGenerateRevokeToken(channelState, custStateBob, newCustStateBob, closeTokenB)
assert.Nil(t, err)
payTokenA, payTokenB, merchState, err := BidirectionalPayVerifyMultipleRevokeTokens(revokeTokenA, revokeTokenB, merchState)
assert.Nil(t, err)
custStateAlice, isTokenValid, err := BidirectionalPayVerifyPaymentToken(channelState, custStateAlice, payTokenA)
assert.Nil(t, err)
assert.True(t, isTokenValid)
custStateBob, isTokenValid, err = BidirectionalPayVerifyPaymentToken(channelState, custStateBob, payTokenB)
assert.Nil(t, err)
assert.True(t, isTokenValid)
}
func Test_Close(t *testing.T) {
b0Cust := 1000
b0Merch := 100

View File

@ -30,8 +30,10 @@ char* ffishim_bidirectional_establish_customer_final(const char *ser_channel_sta
// 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);
// closing routines for both sides

View File

@ -49,12 +49,18 @@ class Libbolt(object):
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_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_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_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_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_bidirectional_pay_verify_payment_token.argtypes = (c_void_p, c_void_p)
self.lib.ffishim_bidirectional_pay_verify_payment_token.restype = c_void_p
@ -136,6 +142,12 @@ class Libbolt(object):
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_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(),
@ -149,6 +161,12 @@ class Libbolt(object):
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_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())

View File

@ -4,7 +4,7 @@ pub mod ffishim {
use bidirectional;
use ff::Rand;
use pairing::bls12_381::{Bls12};
use pairing::bls12_381::Bls12;
use serde::Deserialize;
@ -56,8 +56,8 @@ pub mod ffishim {
// }
fn deserialize_result_object<'a, T>(serialized: *mut c_char) -> ResultSerdeType<T>
where
T: Deserialize<'a>,
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
@ -66,8 +66,8 @@ pub mod ffishim {
#[no_mangle]
pub extern fn ffishim_free_string(pointer: *mut c_char) {
unsafe{
if pointer.is_null() { return }
unsafe {
if pointer.is_null() { return; }
CString::from_raw(pointer)
};
}
@ -81,7 +81,6 @@ pub mod ffishim {
let ser = ["{\'result\':\'", serde_json::to_string(&res).unwrap().as_str(), "\'}"].concat();
let cser = CString::new(ser).unwrap();
cser.into_raw()
}
#[no_mangle]
@ -108,31 +107,31 @@ pub mod ffishim {
let channel_state_result: ResultSerdeType<bidirectional::ChannelState<Bls12>> = 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 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 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_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_bidirectional_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<bidirectional::ChannelToken<Bls12>> = 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
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 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()
}
@ -142,21 +141,21 @@ pub mod ffishim {
#[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 {
let rng = &mut rand::thread_rng();
// Deserialize the channel token
// Deserialize the channel token
let channel_token_result: ResultSerdeType<bidirectional::ChannelToken<Bls12>> = deserialize_result_object(ser_channel_token);
let mut channel_token = handle_errors!(channel_token_result);
// Deserialize the cust state
let cust_state_result: ResultSerdeType<bidirectional::CustomerState<Bls12>> = deserialize_result_object(ser_customer_state);
let mut cust_state= handle_errors!(cust_state_result);
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();
"\', \'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()
}
@ -203,7 +202,7 @@ pub mod ffishim {
// Deserialize the commitment
let com_result: ResultSerdeType<bidirectional::Commitment<Bls12>> = deserialize_result_object(ser_com);
let com= handle_errors!(com_result);
let com = handle_errors!(com_result);
// Deserialize the merchant state
let merch_state_result: ResultSerdeType<bidirectional::MerchantState<Bls12>> = deserialize_result_object(ser_merch_state);
@ -221,7 +220,7 @@ pub mod ffishim {
// Deserialize the channel state
let channel_state_result: ResultSerdeType<bidirectional::ChannelState<Bls12>> = deserialize_result_object(ser_channel_state);
let mut channel_state = handle_errors!(channel_state_result);
// Deserialize the cust state
let cust_state_result: ResultSerdeType<bidirectional::CustomerState<Bls12>> = deserialize_result_object(ser_customer_state);
let mut cust_state = handle_errors!(cust_state_result);
@ -233,8 +232,8 @@ pub mod ffishim {
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();
"\', \'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()
}
@ -257,8 +256,8 @@ pub mod ffishim {
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();
"\', \'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()
}
@ -281,7 +280,7 @@ pub mod ffishim {
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();
"\', \'cust_state\':\'", serde_json::to_string(&new_cust_state).unwrap().as_str(), "\'}"].concat();
let cser = CString::new(ser).unwrap();
cser.into_raw()
}
@ -303,7 +302,34 @@ pub mod ffishim {
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();
"\', \'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_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 {
let rng = &mut rand::thread_rng();
// Deserialize the channel state
let channel_state_result: ResultSerdeType<bidirectional::ChannelState<Bls12>> = deserialize_result_object(ser_channel_state);
let channel_state = handle_errors!(channel_state_result);
// Deserialize the payment proofs
let sender_payment_result: ResultSerdeType<bidirectional::Payment<Bls12>> = deserialize_result_object(ser_sender_pay_proof);
let sender_payment = handle_errors!(sender_payment_result);
let receiver_payment_result: ResultSerdeType<bidirectional::Payment<Bls12>> = deserialize_result_object(ser_receiver_pay_proof);
let receiver_payment = handle_errors!(receiver_payment_result);
// Deserialize the merch state
let merch_state_result: ResultSerdeType<bidirectional::MerchantState<Bls12>> = 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()
}
@ -328,7 +354,7 @@ pub mod ffishim {
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();
"\', \'cust_state\':\'", serde_json::to_string(&cust_state).unwrap().as_str(), "\'}"].concat();
let cser = CString::new(ser).unwrap();
cser.into_raw()
}
@ -337,7 +363,7 @@ pub mod ffishim {
pub extern fn ffishim_bidirectional_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<bidirectional::RevokeToken> = deserialize_result_object(ser_revoke_token);
let revoke_token= handle_errors!(revoke_token_result);
let revoke_token = handle_errors!(revoke_token_result);
// Deserialize the cust state
let merch_state_result: ResultSerdeType<bidirectional::MerchantState<Bls12>> = deserialize_result_object(ser_merch_state);
@ -348,7 +374,31 @@ pub mod ffishim {
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();
"\', \'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_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 {
// Deserialize the revoke tokens
let sender_revoke_token_result: ResultSerdeType<bidirectional::RevokeToken> = deserialize_result_object(ser_sender_revoke_token);
let sender_revoke_token = handle_errors!(sender_revoke_token_result);
let receiver_revoke_token_result: ResultSerdeType<bidirectional::RevokeToken> = 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<bidirectional::MerchantState<Bls12>> = 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()
}
@ -371,7 +421,7 @@ pub mod ffishim {
// 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();
"\', \'is_pay_valid\':\'", serde_json::to_string(&is_pay_valid).unwrap().as_str(), "\'}"].concat();
let cser = CString::new(ser).unwrap();
cser.into_raw()
}
@ -400,7 +450,7 @@ pub mod ffishim {
let channel_state_result: ResultSerdeType<bidirectional::ChannelState<Bls12>> = deserialize_result_object(ser_channel_state);
let channel_state = handle_errors!(channel_state_result);
// Deserialize the channel token
// Deserialize the channel token
let channel_token_result: ResultSerdeType<bidirectional::ChannelToken<Bls12>> = deserialize_result_object(ser_channel_token);
let channel_token = handle_errors!(channel_token_result);
@ -425,7 +475,7 @@ pub mod ffishim {
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();
"\', \'merch_close\':\'", serde_json::to_string(&merch_close).unwrap().as_str(), "\'}"].concat();
let cser = CString::new(ser).unwrap();
cser.into_raw()
}

View File

@ -303,47 +303,32 @@ pub mod bidirectional {
}
///
/// Verify third party payment proof from two bi-directional channel payments with intermediary
/// Verify third party payment proof from two bi-directional channel payments with intermediary (payment amount
///
// pub fn verify_third_party_payment(pp: &PublicParams, fee: i64, proof1: &BalanceProof, proof2: &BalanceProof) -> bool {
// if proof1.third_party && proof2.third_party {
// let vcom1 = &proof1.proof_vcom.as_ref().unwrap();
// let vcom2 = &proof2.proof_vcom.as_ref().unwrap();
// let rproof1 = &proof1.proof_vrange.as_ref().unwrap();
// let rproof2 = &proof2.proof_vrange.as_ref().unwrap();
// let pc_gens1 = PedersenGens::default();
// let pc_gens2 = PedersenGens::default();
// let mut transcript1 = Transcript::new(b"Range Proof for Balance Increment");
// let range_proof1_valid = rproof1.range_proof.0.verify_single(&pp.bp_gens, &pc_gens1,
// &mut transcript1,
// &rproof1.range_proof.1,
// pp.range_proof_bits).is_ok();
//
// let mut transcript2 = Transcript::new(b"Range Proof for Balance Increment");
// let range_proof2_valid = rproof2.range_proof.0.verify_single(&pp.bp_gens, &pc_gens2,
// &mut transcript2,
// &rproof2.range_proof.1,
// pp.range_proof_bits).is_ok();
//
// let len = vcom1.pub_bases.len();
// assert!(len >= 2 && vcom1.pub_bases.len() == vcom2.pub_bases.len());
//
// // g^(e1 + -e2 + fee) * h^(r1 + r2) ==> should be equal to g^(fee) * h^(r1 + r2)
// // lets add commitments for vcom1 and vcom2 to check
// let added_commits = vcom1.C + vcom2.C;
// let tx_fee = vcom1.pub_bases[1] * -convert_int_to_fr(fee);
// // compute h^r1 + r2
// let h_r1_r2 = (vcom1.pub_bases[0] * proof1.vcom.unwrap().r) +
// (vcom2.pub_bases[0] * proof2.vcom.unwrap().r) + tx_fee;
//
// let is_pay_plus_fee = added_commits == h_r1_r2;
// return clproto::bs_verify_nizk_proof(&vcom1) &&
// clproto::bs_verify_nizk_proof(&vcom2) &&
// range_proof1_valid && range_proof2_valid &&
// is_pay_plus_fee;
// }
// panic!("verify_third_party_payment - third-party payment not enabled for both proofs");
// }
pub fn verify_multiple_payment_proofs<R: Rng, E: Engine>(csprng: &mut R,
channel_state: &ChannelState<E>,
sender_payment: &Payment<E>,
receiver_payment: &Payment<E>,
merch_state: &mut MerchantState<E>)
-> BoltResult<(cl::Signature<E>, cl::Signature<E>)> {
let tx_fee = channel_state.get_channel_fee();
let amount = sender_payment.amount + receiver_payment.amount;
if amount != 0 { // we want to check this relation in ZK without knowing the amount
return Err(String::from("payments do not offset"));
}
let new_close_token = merch_state.verify_payment(csprng, &channel_state,
&sender_payment.proof, &sender_payment.com, &sender_payment.wpk, sender_payment.amount + tx_fee).unwrap();
let cond_close_token = merch_state.verify_payment(csprng, &channel_state,
&receiver_payment.proof, &receiver_payment.com, &receiver_payment.wpk, receiver_payment.amount + tx_fee).unwrap();
// store the wpk since it has been revealed
update_merchant_state(&mut merch_state.keys, &sender_payment.wpk, None);
update_merchant_state(&mut merch_state.keys, &receiver_payment.wpk, None);
return Ok(Some((new_close_token, cond_close_token)));
}
///
@ -364,8 +349,8 @@ pub mod bidirectional {
}
///
/// verify_revoke_token (phase 2) - takes as input revoke message and signature,
/// merchant state, from the customer. If the revocation token is valid,
/// verify_revoke_token (phase 2) - takes as input revoke message and signature
/// from the customer and the merchant state. If the revocation token is valid,
/// generate a new signature for the new wallet (from the PoK of committed values in new wallet).
///
pub fn verify_revoke_token<E: Engine>(rt: &RevokeToken, merch_state: &mut MerchantState<E>) -> BoltResult<cl::Signature<E>> {
@ -378,6 +363,30 @@ pub mod bidirectional {
Ok(Some(new_pay_token))
}
///
/// verify_multiple_revoke_tokens (phase 2) - takes as input revoke messages and signatures
/// from the sender and receiver and the merchant state of the intermediary.
/// If the revocation tokens are valid, generate new signatures for the new wallets of both
/// sender and receiver (from the PoK of committed values in new wallet).
///
pub fn verify_multiple_revoke_tokens<E: Engine>(rt_sender: &RevokeToken, rt_receiver: &RevokeToken, merch_state: &mut MerchantState<E>) -> BoltResult<(cl::Signature<E>, cl::Signature<E>)> {
let pay_token_sender_result = merch_state.verify_revoke_token(&rt_sender.signature, &rt_sender.message, &rt_sender.message.wpk);
let pay_token_receiver_result = merch_state.verify_revoke_token(&rt_receiver.signature, &rt_receiver.message, &rt_receiver.message.wpk);
let new_pay_token_sender = match pay_token_sender_result {
Ok(n) => n,
Err(err) => return Err(String::from(err.to_string()))
};
let new_pay_token_receiver = match pay_token_receiver_result {
Ok(n) => n,
Err(err) => return Err(String::from(err.to_string()))
};
update_merchant_state(&mut merch_state.keys, &rt_sender.message.wpk, Some(rt_sender.signature.clone()));
update_merchant_state(&mut merch_state.keys, &rt_receiver.message.wpk, Some(rt_receiver.signature.clone()));
Ok(Some((new_pay_token_sender, new_pay_token_receiver)))
}
///// end of pay protocol
// for customer => on input a wallet w, it outputs a customer channel closure message
@ -563,7 +572,7 @@ mod tests {
//let pk_h = hash_pubkey_to_fr::<Bls12>(&cust_state.pk_c.clone());
let pk_c = cust_state.get_public_key();
let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &pk_c,
cust_balance, merch_balance, &merch_state);
cust_balance, merch_balance, &merch_state);
let close_token = match option {
Ok(n) => n.unwrap(),
Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e)
@ -817,99 +826,67 @@ mod tests {
}
// fn execute_third_party_pay_protocol_helper(pp: &bidirectional::PublicParams,
// channel1: &mut bidirectional::ChannelState, channel2: &mut bidirectional::ChannelState,
// merch_keys: &cl::KeyPairD, merch1_data: &mut bidirectional::InitMerchantData,
// merch2_data: &mut bidirectional::InitMerchantData,
// cust1_keys: &cl::KeyPairD, cust1_data: &mut bidirectional::InitCustomerData,
// cust2_keys: &cl::KeyPairD, cust2_data: &mut bidirectional::InitCustomerData,
// payment_increment: i64) {
// // let's test the pay protocol
// bidirectional::pay_by_customer_phase1_precompute(&pp, &cust1_data.channel_token, &merch_keys.pk, &mut cust1_data.csk);
// bidirectional::pay_by_customer_phase1_precompute(&pp, &cust2_data.channel_token, &merch_keys.pk, &mut cust2_data.csk);
//
// println!("Channel 1 fee: {}", channel1.get_channel_fee());
// let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel1,
// &cust1_data.channel_token, // channel token
// &merch_keys.pk, // merchant pub key
// &cust1_data.csk, // wallet
// payment_increment); // balance increment
// println!("Channel 2 fee: {}", channel2.get_channel_fee());
// let (t_c2, new_wallet2, pay_proof2) = bidirectional::pay_by_customer_phase1(&pp, &channel2,
// &cust2_data.channel_token, // channel token
// &merch_keys.pk, // merchant pub key
// &cust2_data.csk, // wallet
// -payment_increment); // balance decrement
//
// // validate pay_proof1 and pay_proof2 (and the channel state for the fee paying channel, if fee > 0)
// let tx_fee = channel1.get_channel_fee() + channel2.get_channel_fee();
// assert!(bidirectional::verify_third_party_payment(&pp, tx_fee, &pay_proof1.bal_proof, &pay_proof2.bal_proof));
//
// // get the refund token (rt_w)
// let rt_w1 = bidirectional::pay_by_merchant_phase1(&pp, channel1, &pay_proof1, &merch1_data);
//
// // get the refund token (rt_w)
// let rt_w2 = bidirectional::pay_by_merchant_phase1(&pp, channel2, &pay_proof2, &merch2_data);
//
// // get the revocation token (rv_w) on the old public key (wpk)
// let rv_w1 = bidirectional::pay_by_customer_phase2(&pp, &cust1_data.csk, &new_wallet1, &merch_keys.pk, &rt_w1);
//
// // get the revocation token (rv_w) on the old public key (wpk)
// let rv_w2 = bidirectional::pay_by_customer_phase2(&pp, &cust2_data.csk, &new_wallet2, &merch_keys.pk, &rt_w2);
//
// // get the new wallet sig (new_wallet_sig) on the new wallet
// let new_wallet_sig1 = bidirectional::pay_by_merchant_phase2(&pp, channel1, &pay_proof1, merch1_data, &rv_w1);
//
// // get the new wallet sig (new_wallet_sig) on the new wallet
// let new_wallet_sig2 = bidirectional::pay_by_merchant_phase2(&pp, channel2, &pay_proof2, merch2_data, &rv_w2);
//
// assert!(bidirectional::pay_by_customer_final(&pp, &merch_keys.pk, cust1_data, t_c1, new_wallet1, rt_w1, new_wallet_sig1));
//
// assert!(bidirectional::pay_by_customer_final(&pp, &merch_keys.pk, cust2_data, t_c2, new_wallet2, rt_w2, new_wallet_sig2));
// }
//
// #[test]
// #[ignore]
// fn third_party_payment_basics_work() {
// let pp = bidirectional::setup(true);
//
// // third party -- so indicate so in the channel state
// let mut channel_a = bidirectional::ChannelState::new(String::from("Channel A <-> I"), true);
// let mut channel_b = bidirectional::ChannelState::new(String::from("Channel B <-> I"), true);
//
// let fee = 2;
// channel_a.set_channel_fee(fee);
//
// let total_payment = 20;
// let b0_alice = 30;
// let b0_bob = 30;
// let b0_merchant_a = 40;
// let b0_merchant_b = 40;
//
// let (merch_keys, mut merch_data_a, alice_keys, mut alice_data) = setup_new_channel_helper(&pp, &mut channel_a, b0_alice, b0_merchant_a);
//
// let (mut merch_data_b, bob_keys, mut bob_data) =
// setup_new_channel_existing_merchant_helper(&pp, &mut channel_b, b0_bob, b0_merchant_b, &merch_keys);
//
// // run establish protocol for alice and merchant channel
// execute_establish_protocol_helper(&pp, &mut channel_a, &merch_keys, &mut merch_data_a, &alice_keys, &mut alice_data);
//
// // run establish protocol for bob and merchant channel
// execute_establish_protocol_helper(&pp, &mut channel_b, &merch_keys, &mut merch_data_b, &bob_keys, &mut bob_data);
//
// assert!(channel_a.channel_established);
// assert!(channel_b.channel_established);
//
// // alice can pay bob through the merchant
// execute_third_party_pay_protocol_helper(&pp, &mut channel_a, &mut channel_b,
// &merch_keys, &mut merch_data_a, &mut merch_data_b,
// &alice_keys, &mut alice_data, &bob_keys, &mut bob_data, total_payment);
//
// println!("Customer alice balance: {}", alice_data.csk.balance);
// println!("Merchant channel balance with alice: {}", merch_data_a.csk.balance);
// println!("Customer bob balance: {}", bob_data.csk.balance);
// println!("Merchant channel balance with bob: {}", merch_data_b.csk.balance);
// }
#[test]
fn intermediary_payment_basics_works() {
println!("Intermediary test...");
let mut rng = &mut rand::thread_rng();
let b0_alice = rng.gen_range(100, 1000);
let b0_bob = rng.gen_range(100, 1000);
let b0_merch_a = rng.gen_range(100, 1000);
let b0_merch_b = rng.gen_range(100, 1000);
let tx_fee = rng.gen_range(1, 5);
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("New Channel State"), true);
channel_state.set_channel_fee(tx_fee);
let merch_name = "Hub";
// 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 channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, merch_name);
// initialize on the customer side with balance: b0_cust
let mut alice_cust_state = bidirectional::init_customer(rng, &mut channel_token, b0_alice, b0_merch_a, "Alice");
let mut bob_cust_state = bidirectional::init_customer(rng, &mut channel_token, b0_bob, b0_merch_b, "Bob");
// run establish protocol for customer and merchant channel
//let mut channel_state_alice = channel_state.clone();
//let mut channel_state_bob = channel_state.clone();
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_alice, b0_merch_a, &mut merch_state, &mut alice_cust_state);
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_bob, b0_merch_b, &mut merch_state, &mut bob_cust_state);
assert!(channel_state.channel_established);
//assert!(channel_state_bob.channel_established);
// run pay protocol - flow for third-party
let amount = rng.gen_range(5, 100);
let (sender_payment, new_alice_cust_state) = bidirectional::generate_payment_proof(rng, &channel_state, &alice_cust_state, amount);
let (receiver_payment, new_bob_cust_state) = bidirectional::generate_payment_proof(rng, &channel_state, &bob_cust_state, -amount);
// TODO: figure out how to attach conditions on payment recipients close token that they must (1) produce revocation token for sender's old wallet and (2) must have channel open
// intermediary executes the following on the two payment proofs
let close_token_result = bidirectional::verify_multiple_payment_proofs(rng, &channel_state, &sender_payment, &receiver_payment, &mut merch_state);
let (alice_close_token, bob_cond_close_token) = handle_bolt_result!(close_token_result).unwrap();
// both alice and bob generate a revoke token
let revoke_token_alice = bidirectional::generate_revoke_token(&channel_state, &mut alice_cust_state, new_alice_cust_state, &alice_close_token);
let revoke_token_bob = bidirectional::generate_revoke_token(&channel_state, &mut bob_cust_state, new_bob_cust_state, &bob_cond_close_token);
// send both revoke tokens to intermediary and get pay-tokens in response
let new_pay_token_result: BoltResult<(cl::Signature<Bls12>,cl::Signature<Bls12>)> = bidirectional::verify_multiple_revoke_tokens(&revoke_token_alice, &revoke_token_bob, &mut merch_state);
let (new_pay_token_alice, new_pay_token_bob) = handle_bolt_result!(new_pay_token_result).unwrap();
// verify the pay tokens and update internal state
assert!(alice_cust_state.verify_pay_token(&channel_state, &new_pay_token_alice));
assert!(bob_cust_state.verify_pay_token(&channel_state, &new_pay_token_bob));
println!("Successful payment with intermediary!");
}
#[test]
fn serialization_tests() {