commit
4bcd94ce5a
239
go/libbolt.go
239
go/libbolt.go
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
114
src/ffishim.rs
114
src/ffishim.rs
|
@ -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);
|
||||
|
@ -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()
|
||||
}
|
||||
|
|
249
src/lib.rs
249
src/lib.rs
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue