2018-06-24 22:06:36 -07:00
//! This crate is an experimental implementation of Blind Off-chain
//! lightweight transactions (BOLT).
//!
//! It builds on academic work done by Ian Miers and Matthew Green -
//! https://eprint.iacr.org/2016/701.
//!
//! Libbolt relies on BN curves at 128-bit security, as implemented in
//! [`bn module`](https://github.com/zcash-hackworks/bn).
//!
2018-07-21 21:22:21 -07:00
#![ feature(extern_prelude) ]
2018-06-24 22:06:36 -07:00
2018-07-24 18:42:07 -07:00
#![ cfg_attr(all(test, feature = " unstable " ), feature(test)) ]
#[ cfg(all(test, feature = " unstable " )) ] extern crate test ;
2018-02-24 00:12:58 -08:00
extern crate bn ;
2018-02-24 23:46:52 -08:00
extern crate rand ;
2018-07-21 21:22:21 -07:00
extern crate rand_core ;
2018-02-24 23:46:52 -08:00
extern crate bincode ;
extern crate sodiumoxide ;
2018-06-07 23:57:46 -07:00
extern crate rustc_serialize ;
2018-06-08 18:20:15 -07:00
extern crate secp256k1 ;
2018-07-14 18:17:00 -07:00
extern crate time ;
2018-10-04 11:38:10 -07:00
extern crate merlin ;
2018-07-21 21:22:21 -07:00
extern crate bulletproofs ;
extern crate curve25519_dalek ;
2018-08-10 00:01:50 -07:00
extern crate sha2 ;
2018-03-24 06:44:45 -07:00
2019-02-19 09:01:51 -08:00
extern crate serde ;
extern crate serde_with ;
extern crate libc ;
2018-02-24 23:46:52 -08:00
use std ::fmt ;
2018-03-24 06:44:45 -07:00
use std ::str ;
2018-07-21 21:22:21 -07:00
use bn ::{ Group , Fr , G1 , G2 , Gt } ;
2018-02-24 23:46:52 -08:00
use bincode ::SizeLimit ::Infinite ;
use bincode ::rustc_serialize ::{ encode , decode } ;
2018-04-08 00:46:17 -07:00
use sodiumoxide ::randombytes ;
2018-03-24 06:44:45 -07:00
use sodiumoxide ::crypto ::hash ::sha512 ;
2018-12-22 12:35:13 -08:00
use sha2 ::Sha512 ;
2018-06-09 23:00:01 -07:00
use std ::collections ::HashMap ;
2018-12-22 12:35:13 -08:00
use curve25519_dalek ::digest ::* ;
2018-07-21 21:22:21 -07:00
use curve25519_dalek ::scalar ::Scalar ;
2018-10-04 11:38:10 -07:00
use merlin ::Transcript ;
use bulletproofs ::{ BulletproofGens , PedersenGens , RangeProof } ;
2018-02-24 00:12:58 -08:00
2019-02-19 09:01:51 -08:00
use serde ::{ Serialize , Deserialize } ;
2018-04-07 12:01:27 -07:00
pub mod prf ;
2018-04-02 07:47:19 -07:00
pub mod sym ;
2018-04-07 12:01:27 -07:00
pub mod ote ;
2018-04-02 07:47:19 -07:00
pub mod clsigs ;
pub mod commit_scheme ;
2018-07-24 21:56:41 -07:00
pub mod clproto ;
2019-02-19 09:01:51 -08:00
pub mod serialization_wrappers ;
2018-04-02 07:47:19 -07:00
2018-06-14 20:50:00 -07:00
const E_MIN : i32 = 1 ;
2018-07-25 19:59:47 -07:00
const E_MAX : i32 = 255 ; // TODO: should be 2^32 - 1
2018-02-24 23:46:52 -08:00
2018-03-24 06:44:45 -07:00
pub fn debug_elem_in_hex ( prefix : & str , r : & Fr ) {
let encoded : Vec < u8 > = encode ( & r , Infinite ) . unwrap ( ) ;
print! ( " {} (hex) = 0x " , prefix ) ;
for e in encoded . iter ( ) {
print! ( " {:x} " , e ) ;
}
print! ( " \n " ) ;
2018-02-24 00:12:58 -08:00
}
2018-06-05 19:57:44 -07:00
pub fn debug_g1_in_hex ( prefix : & str , g : & G1 ) {
let encoded : Vec < u8 > = encode ( & g , Infinite ) . unwrap ( ) ;
print! ( " {} (hex) = 0x " , prefix ) ;
for e in encoded . iter ( ) {
print! ( " {:x} " , e ) ;
}
print! ( " \n " ) ;
}
pub fn debug_g2_in_hex ( prefix : & str , g : & G2 ) {
let encoded : Vec < u8 > = encode ( & g , Infinite ) . unwrap ( ) ;
print! ( " {} (hex) = 0x " , prefix ) ;
for e in encoded . iter ( ) {
print! ( " {:x} " , e ) ;
}
print! ( " \n " ) ;
}
2018-06-07 23:57:46 -07:00
pub fn debug_gt_in_hex ( prefix : & str , g : & Gt ) {
let encoded : Vec < u8 > = encode ( & g , Infinite ) . unwrap ( ) ;
print! ( " {} (hex) = 0x " , prefix ) ;
for e in encoded . iter ( ) {
print! ( " {:x} " , e ) ;
}
print! ( " \n " ) ;
}
2018-03-24 06:44:45 -07:00
struct HexSlice < ' a > ( & ' a [ u8 ] ) ;
impl < ' a > HexSlice < ' a > {
fn new < T > ( data : & ' a T ) -> HexSlice < ' a >
where T : ? Sized + AsRef < [ u8 ] > + ' a
{
HexSlice ( data . as_ref ( ) )
2018-02-24 23:46:52 -08:00
}
}
2018-02-24 00:12:58 -08:00
2018-03-24 06:44:45 -07:00
impl < ' a > fmt ::LowerHex for HexSlice < ' a > {
2018-02-24 23:46:52 -08:00
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
2018-03-24 06:44:45 -07:00
for byte in self . 0 {
// Decide if you want upper- or lowercase results,
// padding the values to two characters, spaces
// between bytes, etc.
write! ( f , " {:x} " , byte ) ? ;
2018-02-24 23:46:52 -08:00
}
2018-03-24 06:44:45 -07:00
Ok ( ( ) )
2018-02-24 23:46:52 -08:00
}
2018-02-24 00:12:58 -08:00
}
2018-03-24 06:44:45 -07:00
impl < ' a > fmt ::UpperHex for HexSlice < ' a > {
2018-02-24 23:46:52 -08:00
fn fmt ( & self , f : & mut fmt ::Formatter ) -> fmt ::Result {
2018-03-24 06:44:45 -07:00
for byte in self . 0 {
// Decide if you want upper- or lowercase results,
// padding the values to two characters, spaces
// between bytes, etc.
write! ( f , " {:X} " , byte ) ? ;
2018-02-24 23:46:52 -08:00
}
2018-03-24 06:44:45 -07:00
Ok ( ( ) )
2018-02-24 23:46:52 -08:00
}
2018-02-24 00:12:58 -08:00
}
2018-02-24 23:46:52 -08:00
2018-04-07 12:01:27 -07:00
pub fn print ( g : & G1 ) -> String {
let c_vec : Vec < u8 > = encode ( g , Infinite ) . unwrap ( ) ;
let mut c_s = String ::new ( ) ;
for x in c_vec . iter ( ) {
c_s = format! ( " {} {:x} " , c_s , x ) ;
}
return c_s ;
}
2018-06-09 23:00:01 -07:00
// OLD RefundMessage
//impl<'a> RefundMessage<'a> {
// pub fn new(_c_id: Fr, _index: i32) -> RefundMessage<'a> {
// RefundMessage {
// prefix: "refund", c_id: _c_id, index: _index,
2018-03-24 21:03:59 -07:00
// }
2018-06-09 23:00:01 -07:00
// }
//
// pub fn hash(&self) -> Fr {
// let mut input_buf = Vec::new();
// input_buf.extend_from_slice(self.prefix.as_bytes());
// let c_id_vec: Vec<u8> = encode(&self.c_id, Infinite).unwrap();
// // encode cId in the vector
// input_buf.extend(c_id_vec);
2018-08-15 00:47:02 -07:00
// // encode the balance as a hex string
2018-06-09 23:00:01 -07:00
// let b = format!("{:x}", self.index);
// input_buf.extend_from_slice(b.as_bytes());
// // TODO: add the ck vector (l-bit key)
//// let mut in_str = String::new();
//// for y in input_buf.iter() {
//// in_str = format!("{}{:x}", in_str, y);
//// }
//// println!("input_buf: {}", in_str);
//
// // hash the inputs via SHA256
// let sha2_digest = sha512::hash(input_buf.as_slice());
// // println!("hash: {:?}", sha2_digest);
// // let h = format!("{:x}", HexSlice::new(&sha2_digest));
// let mut hash_buf: [u8; 64] = [0; 64];
// hash_buf.copy_from_slice(&sha2_digest[0..64]);
// return Fr::interpret(&hash_buf);
// }
//}
2018-03-24 06:44:45 -07:00
2018-06-09 23:00:01 -07:00
// spend message (for unidirectional scheme)
2018-05-06 18:50:37 -07:00
#[ derive(Clone) ]
pub struct SpendMessage < ' a > {
prefix : & ' a str ,
j : i32 ,
s : G1 ,
u : G1 ,
pi : Proof ,
2018-06-05 10:26:16 -07:00
ck : sym ::SymKey
2018-05-06 18:50:37 -07:00
}
impl < ' a > SpendMessage < ' a > {
2018-06-05 10:26:16 -07:00
pub fn new ( _j : i32 , _s : G1 , _u : G1 , _pi : Proof , _ck : sym ::SymKey ) -> SpendMessage < ' a > {
2018-05-06 18:50:37 -07:00
SpendMessage {
prefix : " spend " , j : _j , s : _s , u : _u , pi : _pi , ck : _ck ,
}
}
pub fn hash ( & self ) -> Fr {
// hash into a Fr element
2018-06-05 10:26:16 -07:00
let rng = & mut rand ::thread_rng ( ) ;
return Fr ::random ( rng ) ;
2018-05-06 18:50:37 -07:00
}
}
2018-03-24 21:03:59 -07:00
#[ derive(Copy, Clone) ]
pub struct Message {
sk : clsigs ::SecretKey , // the secret key for the signature scheme (Is it possible to make this a generic field?)
k1 : Fr , // seed 1 for PRF
k2 : Fr , // seed 2 for PRF
balance : i32 // the balance for the user
}
2018-03-24 06:44:45 -07:00
2018-03-24 21:03:59 -07:00
impl Message {
pub fn new ( _sk : clsigs ::SecretKey , _k1 : Fr , _k2 : Fr , _balance : i32 ) -> Message {
Message {
sk : _sk , k1 : _k1 , k2 : _k2 , balance : _balance ,
2018-03-24 06:44:45 -07:00
}
}
2018-06-24 22:06:36 -07:00
pub fn hash ( & self ) -> Vec < Fr > {
2018-07-25 19:19:03 -07:00
let input_buf = self . sk . encode ( ) ;
2018-06-24 22:06:36 -07:00
let mut v : Vec < Fr > = Vec ::new ( ) ;
2018-07-25 12:17:51 -07:00
v . push ( convert_to_fr ( & input_buf ) ) ;
2018-03-24 21:03:59 -07:00
// encode k1 in the vector
2018-06-24 22:06:36 -07:00
v . push ( self . k1 . clone ( ) ) ;
v . push ( self . k2 . clone ( ) ) ;
// convert the balance into a Fr
let bal = Fr ::from_str ( self . balance . to_string ( ) . as_str ( ) ) . unwrap ( ) ;
v . push ( bal ) ;
2018-03-24 21:03:59 -07:00
2018-06-24 22:06:36 -07:00
return v ;
2018-03-24 06:44:45 -07:00
}
2018-03-24 21:03:59 -07:00
}
2018-03-24 06:44:45 -07:00
2018-06-24 20:14:02 -07:00
////////////////////////////////// Utilities //////////////////////////////////
2018-05-06 18:50:37 -07:00
2018-06-11 00:31:27 -07:00
pub fn concat_to_vector ( output : & mut Vec < u8 > , t : & G2 ) {
let t_vec : Vec < u8 > = encode ( t , Infinite ) . unwrap ( ) ;
output . extend ( t_vec ) ;
}
2018-05-06 18:50:37 -07:00
#[ derive(Copy, Clone) ]
pub struct Proof {
T : G1 ,
c : Fr ,
s1 : Fr ,
s2 : Fr
}
2018-07-25 12:17:51 -07:00
pub fn hash_g1_to_fr ( x : & G1 ) -> Fr {
2018-06-05 10:26:16 -07:00
let x_vec : Vec < u8 > = encode ( & x , Infinite ) . unwrap ( ) ;
let sha2_digest = sha512 ::hash ( x_vec . as_slice ( ) ) ;
2018-05-06 18:50:37 -07:00
2018-06-05 10:26:16 -07:00
let mut hash_buf : [ u8 ; 64 ] = [ 0 ; 64 ] ;
hash_buf . copy_from_slice ( & sha2_digest [ 0 .. 64 ] ) ;
return Fr ::interpret ( & hash_buf ) ;
}
2018-05-06 18:50:37 -07:00
2018-07-25 12:17:51 -07:00
pub fn hash_pub_key_to_fr ( wpk : & secp256k1 ::PublicKey ) -> Fr {
2018-06-08 18:20:15 -07:00
let x_slice = wpk . serialize_uncompressed ( ) ;
let sha2_digest = sha512 ::hash ( & x_slice ) ;
let mut hash_buf : [ u8 ; 64 ] = [ 0 ; 64 ] ;
hash_buf . copy_from_slice ( & sha2_digest [ 0 .. 64 ] ) ;
return Fr ::interpret ( & hash_buf ) ;
}
2018-07-25 12:17:51 -07:00
pub fn compute_pub_key_fingerprint ( wpk : & secp256k1 ::PublicKey ) -> String {
2018-06-14 18:07:18 -07:00
let x_slice = wpk . serialize ( ) ;
let sha2_digest = sha512 ::hash ( & x_slice ) ;
let h = format! ( " {:x} " , HexSlice ::new ( & sha2_digest [ 0 .. 16 ] ) ) ;
return h ;
}
2018-07-25 12:17:51 -07:00
pub fn hash_buffer_to_fr < ' a > ( prefix : & ' a str , buf : & [ u8 ; 64 ] ) -> Fr {
2018-06-13 17:28:37 -07:00
let mut input_buf = Vec ::new ( ) ;
input_buf . extend_from_slice ( prefix . as_bytes ( ) ) ;
input_buf . extend_from_slice ( buf ) ;
let sha2_digest = sha512 ::hash ( & input_buf . as_slice ( ) ) ;
let mut hash_buf : [ u8 ; 64 ] = [ 0 ; 64 ] ;
hash_buf . copy_from_slice ( & sha2_digest [ 0 .. 64 ] ) ;
return Fr ::interpret ( & hash_buf ) ;
}
2018-07-25 12:17:51 -07:00
fn convert_to_fr ( input_buf : & Vec < u8 > ) -> Fr {
2018-06-09 23:00:01 -07:00
// hash the inputs via SHA256
let sha2_digest = sha512 ::hash ( input_buf . as_slice ( ) ) ;
// println!("hash: {:?}", sha2_digest);
// let h = format!("{:x}", HexSlice::new(&sha2_digest));
let mut hash_buf : [ u8 ; 64 ] = [ 0 ; 64 ] ;
hash_buf . copy_from_slice ( & sha2_digest [ 0 .. 64 ] ) ;
return Fr ::interpret ( & hash_buf ) ;
}
2018-07-25 12:17:51 -07:00
fn convert_str_to_fr < ' a > ( input : & ' a str ) -> Fr {
2018-06-13 17:28:37 -07:00
let mut input_buf = Vec ::new ( ) ;
input_buf . extend_from_slice ( input . as_bytes ( ) ) ;
2018-07-25 12:17:51 -07:00
return convert_to_fr ( & input_buf ) ;
2018-06-13 17:28:37 -07:00
}
2018-08-10 00:01:50 -07:00
fn convert_int_to_fr ( value : i32 ) -> Fr {
if value > 0 {
return Fr ::from_str ( value . to_string ( ) . as_str ( ) ) . unwrap ( ) ;
} else {
// negative value
let value2 = value * - 1 ;
return - Fr ::from_str ( value2 . to_string ( ) . as_str ( ) ) . unwrap ( ) ;
}
}
2018-06-09 23:00:01 -07:00
// refund message
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-06-14 20:50:00 -07:00
pub struct RefundMessage {
pub msgtype : String , // purpose type of message
2018-06-11 00:31:27 -07:00
pub wpk : secp256k1 ::PublicKey ,
pub balance : usize , // the balance
2019-02-26 11:52:47 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable_option " , deserialize_with = " serialization_wrappers::deserialize_optional_fr " ) ]
2018-06-14 20:50:00 -07:00
pub r : Option < Fr > , // randomness from customer wallet
pub rt : Option < clsigs ::SignatureD > // refund token
2018-06-09 23:00:01 -07:00
}
2018-06-14 20:50:00 -07:00
impl RefundMessage {
2018-06-14 22:18:20 -07:00
pub fn new ( _msgtype : String , _wpk : secp256k1 ::PublicKey ,
2018-06-14 20:50:00 -07:00
_balance : usize , _r : Option < Fr > , _rt : Option < clsigs ::SignatureD > ) -> RefundMessage {
2018-06-09 23:00:01 -07:00
RefundMessage {
2018-06-14 22:18:20 -07:00
msgtype : _msgtype , wpk : _wpk , balance : _balance , r : _r , rt : _rt
2018-06-09 23:00:01 -07:00
}
}
pub fn hash ( & self ) -> Vec < Fr > {
let mut v : Vec < Fr > = Vec ::new ( ) ;
let mut input_buf = Vec ::new ( ) ;
2018-06-11 00:31:27 -07:00
input_buf . extend_from_slice ( self . msgtype . as_bytes ( ) ) ;
2018-07-25 12:17:51 -07:00
v . push ( convert_to_fr ( & input_buf ) ) ;
2018-06-09 23:00:01 -07:00
2018-07-25 12:17:51 -07:00
v . push ( hash_pub_key_to_fr ( & self . wpk ) ) ;
2018-06-09 23:00:01 -07:00
// encoee the balance as a hex string
let b = format! ( " {:x} " , self . balance ) ;
let mut b_buf = Vec ::new ( ) ;
b_buf . extend_from_slice ( b . as_bytes ( ) ) ;
2018-07-25 12:17:51 -07:00
v . push ( convert_to_fr ( & b_buf ) ) ;
2018-06-09 23:00:01 -07:00
//let r_vec: Vec<u8> = encode(&self.r, Infinite).unwrap();
2018-06-24 22:06:36 -07:00
if ! self . r . is_none ( ) {
2018-06-09 23:00:01 -07:00
v . push ( self . r . unwrap ( ) . clone ( ) ) ;
}
2018-06-24 22:06:36 -07:00
if ! self . rt . is_none ( ) {
2018-06-14 20:50:00 -07:00
let rt = {
& self . rt . clone ( )
} ;
let rt_ref = rt . as_ref ( ) ;
v . push ( rt_ref . unwrap ( ) . hash ( & self . msgtype ) ) ;
2018-06-09 23:00:01 -07:00
}
return v ;
}
}
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-06-14 18:07:18 -07:00
pub struct RevokedMessage {
pub msgtype : String ,
2018-06-11 00:31:27 -07:00
pub wpk : secp256k1 ::PublicKey ,
2019-02-26 11:52:47 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_fixed_byte_array_option " , deserialize_with = " serialization_wrappers::deserialize_optional_fixed_64_byte_array " ) ]
2018-06-14 22:18:20 -07:00
pub sig : Option < [ u8 ; 64 ] > // represents revocation token serialized compact bytes
2018-06-09 23:00:01 -07:00
}
2018-06-14 18:07:18 -07:00
impl RevokedMessage {
2018-06-14 22:18:20 -07:00
pub fn new ( _msgtype : String , _wpk : secp256k1 ::PublicKey , _sig : Option < [ u8 ; 64 ] > ) -> RevokedMessage {
2018-06-09 23:00:01 -07:00
RevokedMessage {
2018-06-11 00:31:27 -07:00
msgtype : _msgtype , wpk : _wpk , sig : _sig
2018-06-09 23:00:01 -07:00
}
}
pub fn hash ( & self ) -> Vec < Fr > {
let mut v : Vec < Fr > = Vec ::new ( ) ;
let mut input_buf = Vec ::new ( ) ;
2018-06-11 00:31:27 -07:00
input_buf . extend_from_slice ( self . msgtype . as_bytes ( ) ) ;
2018-07-25 12:17:51 -07:00
v . push ( convert_to_fr ( & input_buf ) ) ;
2018-06-09 23:00:01 -07:00
2018-07-25 12:17:51 -07:00
v . push ( hash_pub_key_to_fr ( & self . wpk ) ) ;
2018-06-11 00:31:27 -07:00
2018-06-24 22:06:36 -07:00
if ! self . sig . is_none ( ) {
2018-07-25 12:17:51 -07:00
v . push ( hash_buffer_to_fr ( & self . msgtype , & self . sig . unwrap ( ) ) ) ;
2018-06-13 17:28:37 -07:00
}
2018-06-09 23:00:01 -07:00
return v ;
}
2018-05-06 18:50:37 -07:00
2018-06-13 17:28:37 -07:00
// return a message digest (32-bytes)
pub fn hash_to_slice ( & self ) -> [ u8 ; 32 ] {
let mut input_buf = Vec ::new ( ) ;
input_buf . extend_from_slice ( self . msgtype . as_bytes ( ) ) ;
input_buf . extend_from_slice ( & self . wpk . serialize_uncompressed ( ) ) ;
let sha2_digest = sha512 ::hash ( input_buf . as_slice ( ) ) ;
// println!("hash: {:?}", sha2_digest);
// let h = format!("{:x}", HexSlice::new(&sha2_digest));
let mut hash_buf : [ u8 ; 32 ] = [ 0 ; 32 ] ;
hash_buf . copy_from_slice ( & sha2_digest [ 0 .. 32 ] ) ;
return hash_buf ;
}
}
2018-05-06 18:50:37 -07:00
2018-06-24 22:06:36 -07:00
////////////////////////////////// Utilities //////////////////////////////////
/////////////////////////////// Unidirectional ////////////////////////////////
pub mod unidirectional {
use std ::fmt ;
2018-08-24 00:18:36 -07:00
use std ::collections ::HashMap ;
2018-07-21 21:22:21 -07:00
use rand ::{ Rng , thread_rng } ;
use rand_core ::RngCore ;
2018-08-24 00:18:36 -07:00
use bn ::{ Group , Fr , G2 } ;
2018-06-24 22:06:36 -07:00
use sym ;
use commit_scheme ;
use clsigs ;
2018-08-24 00:18:36 -07:00
use clproto ;
2018-06-24 22:06:36 -07:00
use Message ;
use sodiumoxide ::randombytes ;
2018-08-24 00:18:36 -07:00
#[ derive(Clone) ]
pub struct CustomerWallet {
sk : clsigs ::SecretKeyD , // the secret key for the signature scheme (Is it possible to make this a generic field?)
cid : Fr , // channel Id
wpk : secp256k1 ::PublicKey , // signature verification key
wsk : secp256k1 ::SecretKey // signature signing key
}
2018-06-24 22:06:36 -07:00
pub struct PublicParams {
cl_mpk : clsigs ::PublicParams ,
l : usize
}
pub struct ChannelToken {
w_com : commit_scheme ::Commitment ,
pk : clsigs ::PublicKey
}
pub struct CustSecretKey {
2018-08-10 00:01:50 -07:00
sk : clsigs ::SecretKey , // the secret key for the signature scheme
2018-06-24 22:06:36 -07:00
k1 : Fr , // seed 1 for PRF
k2 : Fr , // seed 2 for PRF
r : Fr , // random coins for commitment scheme
balance : i32 , // the balance for the user
ck_vec : Vec < sym ::SymKey >
}
pub struct MerchSecretKey {
sk : clsigs ::SecretKey ,
balance : i32
}
pub struct InitCustomerData {
2018-08-16 15:05:01 -07:00
channel_token : ChannelToken ,
2018-06-24 22:06:36 -07:00
csk : CustSecretKey
}
pub struct InitMerchantData {
2018-08-16 15:05:01 -07:00
channel_token : clsigs ::PublicKey ,
2018-06-24 22:06:36 -07:00
csk : MerchSecretKey
}
2018-08-24 00:18:36 -07:00
pub struct PubKeyMap {
wpk : secp256k1 ::PublicKey ,
revoke_token : Option < secp256k1 ::Signature >
}
pub struct ChannelState {
keys : HashMap < String , PubKeyMap > ,
R : i32 ,
tx_fee : i32 ,
pub name : String ,
pub cid : Fr ,
pub pay_init : bool ,
pub channel_established : bool ,
pub third_party : bool
}
2018-06-24 22:06:36 -07:00
pub fn setup ( ) -> PublicParams {
2018-07-25 19:19:03 -07:00
let cl_mpk = clsigs ::setup_d ( ) ;
2018-06-24 22:06:36 -07:00
let l = 4 ;
let pp = PublicParams { cl_mpk : cl_mpk , l : l } ;
return pp ;
}
pub fn keygen ( pp : & PublicParams ) -> clsigs ::KeyPairD {
2018-07-25 19:19:03 -07:00
let keypair = clsigs ::keygen_d ( & pp . cl_mpk , pp . l ) ;
2018-06-24 22:06:36 -07:00
return keypair ;
}
2018-08-24 00:18:36 -07:00
///
/// init_customer - takes as input the public params, channel state, commitment params, keypair,
/// and initial balance for customer and merchant. Generate initial customer channel token,
/// and wallet commitment.
///
2018-06-24 22:06:36 -07:00
pub fn init_customer ( pp : & PublicParams , cm_pk : commit_scheme ::CSParams ,
b0_customer : i32 , b0_merchant : i32 ,
keypair : & clsigs ::KeyPair ) -> InitCustomerData {
2018-07-21 21:22:21 -07:00
sym ::init_mod ( ) ;
2018-06-24 22:06:36 -07:00
let rng = & mut rand ::thread_rng ( ) ;
// pick two distinct seeds
let l = 256 ;
let k1 = Fr ::random ( rng ) ;
let k2 = Fr ::random ( rng ) ;
let r = Fr ::random ( rng ) ;
let msg = Message ::new ( keypair . sk , k1 , k2 , b0_customer ) ;
let mut ck_vec : Vec < sym ::SymKey > = Vec ::new ( ) ;
// generate the vector ck of sym keys
for i in 1 .. b0_customer {
let ck = sym ::keygen ( l ) ;
ck_vec . push ( ck ) ;
}
2018-08-13 15:16:02 -07:00
let w_com = commit_scheme ::commit ( & cm_pk , & msg . hash ( ) , r ) ;
2018-06-24 22:06:36 -07:00
let t_c = ChannelToken { w_com : w_com , pk : keypair . pk } ;
let csk_c = CustSecretKey { sk : keypair . sk , k1 : k1 , k2 : k2 , r : r , balance : b0_customer , ck_vec : ck_vec } ;
2018-08-16 15:05:01 -07:00
return InitCustomerData { channel_token : t_c , csk : csk_c } ;
2018-06-24 22:06:36 -07:00
}
2018-08-24 00:18:36 -07:00
///
/// init_merchant - takes as input the public params, merchant balance and keypair.
/// Generates merchant data which consists of channel token and merchant wallet.
///
2018-06-24 22:06:36 -07:00
pub fn init_merchant ( pp : & PublicParams , b0_merchant : i32 , keypair : & clsigs ::KeyPair ) -> InitMerchantData {
let csk_m = MerchSecretKey { sk : keypair . sk , balance : b0_merchant } ;
2018-08-16 15:05:01 -07:00
return InitMerchantData { channel_token : keypair . pk , csk : csk_m } ;
2018-06-24 22:06:36 -07:00
}
2018-05-06 18:50:37 -07:00
2018-08-24 00:18:36 -07:00
///
/// establish_customer_phase1 - takes as input the public params, customer wallet and
/// common public bases from merchant. Generates a PoK of the committed values in the
/// new wallet.
///
pub fn establish_customer_phase1 ( pp : & PublicParams , c_data : & InitCustomerData ,
pub_bases : & Vec < G2 > ) -> clproto ::ProofCV {
unimplemented! ( ) ;
2018-05-10 14:08:42 -07:00
// // set sk_0 to random bytes of length l
// // let sk_0 = random_bytes(pp.l);
// let buf_len: usize = pp.l_bits as usize;
// let mut sk0 = vec![0; buf_len];
// randombytes::randombytes_into(&mut sk0);
//
// let pi1 = create_nizk_proof_one(csk_c.sk, csk_c.k1, csk_c.k2, );
2018-08-24 00:18:36 -07:00
}
///
/// establish_merchant_phase2 - takes as input the public params, channel state, initial
/// merchant wallet and PoK of committed values from the customer. Generates a blinded
/// signature over the contents of the customer's wallet.
///
pub fn establish_merchant_phase2 ( pp : & PublicParams , state : & mut ChannelState , m_data : & InitMerchantData ,
proof : & clproto ::ProofCV ) -> clsigs ::SignatureD {
unimplemented! ( ) ;
}
///
/// establish_customer_final - takes as input the public params, merchant's verification key,
/// customer wallet and blinded signature obtained from merchant. Add the returned
/// blinded signature to the wallet.
///
pub fn establish_customer_final ( pp : & PublicParams , pk_m : & clsigs ::PublicKeyD ,
w : & mut CustomerWallet , sig : clsigs ::SignatureD ) -> bool {
unimplemented! ( ) ;
}
2018-08-24 00:31:46 -07:00
// TODO: add pay protocol api, channel disput algs, etc
2018-06-24 22:06:36 -07:00
}
/////////////////////////////// Unidirectional ////////////////////////////////
2018-05-10 14:08:42 -07:00
2018-06-24 22:06:36 -07:00
/////////////////////////////// Bidirectional ////////////////////////////////
2018-05-10 14:08:42 -07:00
pub mod bidirectional {
2018-03-25 20:20:05 -07:00
use std ::fmt ;
2018-07-21 21:22:21 -07:00
use rand ::{ rngs ::OsRng , Rng } ;
use rand_core ::RngCore ;
2018-06-12 11:30:24 -07:00
use bn ::{ Group , Fr , G1 , G2 , Gt } ;
2018-03-25 20:20:05 -07:00
use commit_scheme ;
use clsigs ;
2018-07-24 21:56:41 -07:00
use clproto ;
2018-06-18 20:19:53 -07:00
use sodiumoxide ;
2018-06-24 22:06:36 -07:00
use secp256k1 ;
2018-06-09 23:00:01 -07:00
use RefundMessage ;
use RevokedMessage ;
2018-06-14 18:07:18 -07:00
use HashMap ;
2018-07-25 12:17:51 -07:00
use hash_pub_key_to_fr ;
2018-06-11 11:05:24 -07:00
use debug_elem_in_hex ;
2018-06-12 11:30:24 -07:00
use debug_gt_in_hex ;
2018-07-25 12:17:51 -07:00
use convert_str_to_fr ;
2018-08-10 00:01:50 -07:00
use convert_int_to_fr ;
2018-07-25 12:17:51 -07:00
use compute_pub_key_fingerprint ;
2018-06-14 20:50:00 -07:00
use E_MIN ;
use E_MAX ;
2018-12-22 12:35:13 -08:00
//use hash_buffer_to_fr;
//use debug_g2_in_hex;
//use convert_to_fr;
2018-07-21 21:22:21 -07:00
use bulletproofs ;
2019-02-13 06:30:18 -08:00
use sodiumoxide ::crypto ::hash ::sha512 ;
2018-08-10 00:01:50 -07:00
use sha2 ::Sha512 ;
2018-07-21 21:22:21 -07:00
use curve25519_dalek ::scalar ::Scalar ;
use curve25519_dalek ::ristretto ::RistrettoPoint ;
2018-10-04 11:38:10 -07:00
use merlin ::Transcript ;
use bulletproofs ::{ BulletproofGens , PedersenGens , RangeProof } ;
2018-08-10 00:01:50 -07:00
use bincode ::rustc_serialize ::encode ;
use bincode ::SizeLimit ::Infinite ;
2018-06-12 11:30:24 -07:00
2019-02-19 09:01:51 -08:00
use serialization_wrappers ;
use serde ::{ Serialize , Deserialize } ;
2018-06-12 11:30:24 -07:00
fn print_secret_vector ( x : & Vec < Fr > ) {
for i in 0 .. x . len ( ) {
let msg = format! ( " x[ {} ] => " , i ) ;
debug_elem_in_hex ( & msg , & x [ i ] ) ;
}
}
fn print_public_bases_vector ( g : & Vec < Gt > ) {
for i in 0 .. g . len ( ) {
let msg = format! ( " g[ {} ] => " , i ) ;
debug_gt_in_hex ( & msg , & g [ i ] ) ;
}
}
2018-03-25 20:20:05 -07:00
2019-02-26 11:52:47 -08:00
// TODO DELETE THHIS TEST STRUCT
2019-02-19 09:01:51 -08:00
#[ derive(Serialize, Deserialize) ]
pub struct TestPublicParams {
pub cl_mpk : clsigs ::PublicParams ,
pub range_proof_bits : usize
}
#[ derive(Serialize, Deserialize) ]
2018-03-25 20:20:05 -07:00
pub struct PublicParams {
2018-04-05 23:44:31 -07:00
cl_mpk : clsigs ::PublicParams ,
2018-08-15 00:47:02 -07:00
l : usize , // messages for commitment
2019-02-19 09:01:51 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_bullet_proof " , deserialize_with = " serialization_wrappers::deserialize_bullet_proof " ) ]
2018-10-04 11:38:10 -07:00
bp_gens : bulletproofs ::BulletproofGens ,
2018-07-21 21:22:21 -07:00
range_proof_bits : usize ,
2018-06-19 22:14:56 -07:00
extra_verify : bool // extra verification for certain points in the establish/pay protocol
2018-03-25 20:20:05 -07:00
}
2019-02-19 15:02:53 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-04-05 23:44:31 -07:00
pub struct ChannelToken {
2018-03-25 20:20:05 -07:00
w_com : commit_scheme ::Commitment ,
2018-08-10 00:01:50 -07:00
pk : clsigs ::PublicKeyD ,
third_party_pay : bool
2018-03-25 20:20:05 -07:00
}
2018-07-14 18:17:00 -07:00
// proof of wallet signature, blind signature on wallet and common params for NIZK
2019-02-19 15:02:53 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-07-14 18:17:00 -07:00
pub struct CustomerWalletProof {
2018-07-24 21:56:41 -07:00
proof_cv : clproto ::ProofCV , // proof of knowledge of committed values
proof_vs : clproto ::ProofVS , // proof of knowledge of valid signature
2019-02-19 09:01:51 -08:00
2019-02-19 15:02:53 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_g_two " ) ]
2018-08-10 00:01:50 -07:00
bal_com : G2 , // old balance commitment
2018-07-14 18:17:00 -07:00
blind_sig : clsigs ::SignatureD , // a blind signature
2018-07-24 21:56:41 -07:00
common_params : clproto ::CommonParams , // common params for NIZK
2018-07-14 18:17:00 -07:00
}
2019-02-19 15:02:53 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-06-09 00:14:50 -07:00
pub struct CustomerWallet {
2018-06-05 10:26:16 -07:00
sk : clsigs ::SecretKeyD , // the secret key for the signature scheme (Is it possible to make this a generic field?)
2019-02-19 15:02:53 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_fr " ) ]
2018-05-11 13:21:35 -07:00
cid : Fr , // channel Id
2018-06-08 18:20:15 -07:00
wpk : secp256k1 ::PublicKey , // signature verification key
wsk : secp256k1 ::SecretKey , // signature signing key
2019-02-19 15:02:53 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_fr " ) ]
2018-07-14 18:17:00 -07:00
h_wpk : Fr ,
2019-02-19 15:02:53 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_fr " ) ]
2018-03-25 20:20:05 -07:00
r : Fr , // random coins for commitment scheme
2018-06-13 17:28:37 -07:00
pub balance : i32 , // the balance for the user
2018-06-19 22:14:56 -07:00
merchant_balance : i32 ,
2018-06-13 17:28:37 -07:00
signature : Option < clsigs ::SignatureD > ,
2018-08-14 05:28:01 -07:00
// proof of signature on wallet contents in zero-knowledge
proof : Option < CustomerWalletProof > ,
2018-06-13 17:28:37 -07:00
refund_token : Option < clsigs ::SignatureD >
2018-03-25 20:20:05 -07:00
}
2019-02-19 15:02:53 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-03-25 20:20:05 -07:00
pub struct MerchSecretKey {
2018-06-09 23:00:01 -07:00
sk : clsigs ::SecretKeyD , // merchant signing key
2018-06-13 17:28:37 -07:00
pub balance : i32
2018-03-25 20:20:05 -07:00
}
2019-02-19 15:02:53 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-03-25 20:20:05 -07:00
pub struct InitCustomerData {
2018-08-16 15:05:01 -07:00
pub channel_token : ChannelToken ,
2018-06-09 00:14:50 -07:00
pub csk : CustomerWallet ,
2019-02-19 15:02:53 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable_vec " , deserialize_with = " serialization_wrappers::deserialize_g_two_vec " ) ]
2018-06-13 17:28:37 -07:00
pub bases : Vec < G2 > ,
2018-03-25 20:20:05 -07:00
}
2019-02-19 15:02:53 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-03-25 20:20:05 -07:00
pub struct InitMerchantData {
2018-08-16 15:05:01 -07:00
pub channel_token : clsigs ::PublicKeyD ,
2018-06-11 11:05:24 -07:00
pub csk : MerchSecretKey ,
2019-02-19 15:02:53 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable_vec " , deserialize_with = " serialization_wrappers::deserialize_g_two_vec " ) ]
2018-06-11 11:05:24 -07:00
pub bases : Vec < G2 >
2018-03-25 20:20:05 -07:00
}
2018-07-29 17:44:08 -07:00
// part of channel state
2019-02-19 12:27:39 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-06-14 18:07:18 -07:00
pub struct PubKeyMap {
wpk : secp256k1 ::PublicKey ,
revoke_token : Option < secp256k1 ::Signature >
}
2019-02-19 09:01:51 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-06-14 18:07:18 -07:00
pub struct ChannelState {
keys : HashMap < String , PubKeyMap > ,
R : i32 ,
2018-08-13 15:16:02 -07:00
tx_fee : i32 ,
2018-06-14 18:07:18 -07:00
pub name : String ,
2019-02-19 09:01:51 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_fr " ) ]
2018-06-09 23:00:01 -07:00
pub cid : Fr ,
2018-06-11 00:31:27 -07:00
pub pay_init : bool ,
2018-07-30 00:06:06 -07:00
pub channel_established : bool ,
pub third_party : bool
}
impl ChannelState {
pub fn new ( name : String , third_party_support : bool ) -> ChannelState {
ChannelState {
keys : HashMap ::new ( ) , // store wpks/revoke_tokens
R : 0 ,
2018-08-13 15:16:02 -07:00
tx_fee : 0 ,
2018-07-30 00:06:06 -07:00
name : name . to_string ( ) ,
2019-02-13 06:30:18 -08:00
cid : Fr ::from_str ( " 0 " ) . unwrap ( ) ,
2018-07-30 00:06:06 -07:00
pay_init : false ,
channel_established : false ,
third_party : third_party_support
}
}
2018-08-13 15:16:02 -07:00
2019-02-13 06:30:18 -08:00
pub fn generate_channel_id ( & mut self , pk : & clsigs ::PublicKeyD ) {
let pk_bytes = pk . encode ( ) ;
let sha2_digest = sha512 ::hash ( & pk_bytes . as_slice ( ) ) ;
let mut hash_buf : [ u8 ; 64 ] = [ 0 ; 64 ] ;
hash_buf . copy_from_slice ( & sha2_digest [ 0 .. 64 ] ) ;
self . cid = Fr ::interpret ( & hash_buf ) ;
}
2018-08-13 15:16:02 -07:00
pub fn set_channel_fee ( & mut self , fee : i32 ) {
self . tx_fee = fee ;
}
pub fn get_channel_fee ( & self ) -> i32 {
return self . tx_fee as i32 ;
}
2018-06-09 23:00:01 -07:00
}
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-07-25 12:17:51 -07:00
pub struct ChannelclosureC {
2018-06-14 22:18:20 -07:00
pub message : RefundMessage ,
2018-06-09 23:00:01 -07:00
signature : clsigs ::SignatureD
}
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-07-25 12:17:51 -07:00
pub struct ChannelclosureM {
2018-06-14 18:07:18 -07:00
message : RevokedMessage ,
2018-06-09 23:00:01 -07:00
signature : clsigs ::SignatureD
}
2018-07-21 21:22:21 -07:00
// proof of valid balance
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-07-21 21:22:21 -07:00
pub struct ProofVB {
2018-10-04 11:38:10 -07:00
range_proof : ( bulletproofs ::RangeProof , curve25519_dalek ::ristretto ::CompressedRistretto ) ,
2018-07-21 21:22:21 -07:00
value_commitment : RistrettoPoint
}
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-08-13 15:16:02 -07:00
pub struct BalanceProof {
third_party : bool ,
balance_increment : i32 ,
2019-02-26 11:52:47 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_g_two " ) ]
2018-08-13 15:16:02 -07:00
w_com_pr_pr : G2 ,
2019-02-26 11:52:47 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_g_two " ) ]
2018-08-13 15:16:02 -07:00
old_bal_com : G2 ,
vcom : Option < commit_scheme ::Commitment > ,
proof_vcom : Option < clproto ::ProofCV > ,
proof_vrange : Option < ProofVB >
}
2019-02-26 11:52:47 -08:00
#[ derive(Clone, Serialize, Deserialize) ]
2018-06-11 00:31:27 -07:00
pub struct PaymentProof {
2018-07-24 21:56:41 -07:00
proof2a : clproto ::ProofCV , // PoK of committed values in new wallet
2019-02-14 08:55:23 -08:00
//proof2b: clproto::ProofCV, // PoK of committed values in old wallet (minus wpk)
2018-07-24 21:56:41 -07:00
proof2c : clproto ::ProofVS , // PoK of old wallet signature (that includes wpk)
2018-07-21 21:22:21 -07:00
proof3 : ProofVB , // range proof that balance - balance_inc is between (0, val_max)
2019-02-26 11:52:47 -08:00
#[ serde(serialize_with = " serialization_wrappers::serialize_generic_encodable " , deserialize_with = " serialization_wrappers::deserialize_g_two " ) ]
2018-06-18 11:07:19 -07:00
old_com_base : G2 ,
2018-06-23 10:54:01 -07:00
wpk : secp256k1 ::PublicKey , // verification key for old wallet
2018-08-13 15:16:02 -07:00
wallet_sig : clsigs ::SignatureD , // blinded signature for old wallet
pub bal_proof : BalanceProof
2018-06-11 00:31:27 -07:00
}
2019-02-26 11:52:47 -08:00
#[ derive(Serialize, Deserialize) ]
2018-06-14 18:07:18 -07:00
pub struct RevokeToken {
message : RevokedMessage ,
pub signature : secp256k1 ::Signature
2018-06-13 17:28:37 -07:00
}
2018-06-18 20:19:53 -07:00
pub fn init ( ) {
sodiumoxide ::init ( ) ;
}
2018-08-24 00:18:36 -07:00
///
/// setup - generate public parameters for bidirectional payment channels
///
2018-06-19 22:14:56 -07:00
pub fn setup ( _extra_verify : bool ) -> PublicParams {
2018-07-25 19:19:03 -07:00
let cl_mpk = clsigs ::setup_d ( ) ;
2018-06-13 17:28:37 -07:00
let l = 4 ;
2018-07-21 21:22:21 -07:00
let n = 32 ; // bitsize: 32-bit (0, 2^32-1)
let num_rand_values = 1 ;
2018-12-22 12:35:13 -08:00
let generators = BulletproofGens ::new ( 64 , num_rand_values ) ; // bitsize
2018-07-21 21:22:21 -07:00
2018-10-04 11:38:10 -07:00
let pp = PublicParams { cl_mpk : cl_mpk , l : l , bp_gens : generators , range_proof_bits : n , extra_verify : _extra_verify } ;
2018-03-25 20:20:05 -07:00
return pp ;
}
2018-08-24 00:18:36 -07:00
///
/// keygen - takes as input public parameters and generates a digital signature keypair
///
2018-06-05 10:26:16 -07:00
pub fn keygen ( pp : & PublicParams ) -> clsigs ::KeyPairD {
2018-07-25 19:19:03 -07:00
let keypair = clsigs ::keygen_d ( & pp . cl_mpk , pp . l ) ;
2018-03-25 20:20:05 -07:00
return keypair ;
}
2018-06-11 11:05:24 -07:00
pub fn generate_commit_setup ( pp : & PublicParams , pk : & clsigs ::PublicKeyD ) -> commit_scheme ::CSParams {
let g2 = pp . cl_mpk . g2 . clone ( ) ;
let bases = pk . Z2 . clone ( ) ;
let cm_csp = commit_scheme ::setup ( pp . l , bases , g2 ) ;
return cm_csp ;
}
2018-08-15 07:28:46 -07:00
///
/// init_customer - takes as input the public params, channel state, commitment params, keypair,
/// and initial balance for customer and merchant. Generate initial customer channel token,
/// and wallet commitment.
///
2019-02-13 06:30:18 -08:00
pub fn init_customer ( pp : & PublicParams , channel : & mut ChannelState , b0_customer : i32 , b0_merchant : i32 ,
2018-06-13 17:28:37 -07:00
cm_csp : & commit_scheme ::CSParams , keypair : & clsigs ::KeyPairD ) -> InitCustomerData {
2018-08-10 00:01:50 -07:00
assert! ( b0_customer > = 0 ) ;
assert! ( b0_merchant > = 0 ) ;
2018-03-25 20:20:05 -07:00
let rng = & mut rand ::thread_rng ( ) ;
2018-06-08 18:20:15 -07:00
// generate verification key and signing key (for wallet)
let mut schnorr = secp256k1 ::Secp256k1 ::new ( ) ;
schnorr . randomize ( rng ) ;
2018-07-21 21:22:21 -07:00
let ( wsk , wpk ) = schnorr . generate_keypair ( rng ) ;
2018-07-25 12:17:51 -07:00
let h_wpk = hash_pub_key_to_fr ( & wpk ) ;
2018-06-08 18:20:15 -07:00
// convert balance into Fr
2018-08-10 00:01:50 -07:00
let b0 = convert_int_to_fr ( b0_customer ) ;
2018-06-08 18:20:15 -07:00
// randomness for commitment
2018-03-25 20:20:05 -07:00
let r = Fr ::random ( rng ) ;
2018-08-15 00:47:02 -07:00
// retrieve the channel id
2019-02-13 06:30:18 -08:00
channel . generate_channel_id ( & keypair . pk ) ;
2018-08-13 20:57:23 -07:00
let cid = channel . cid ;
2018-07-29 17:44:08 -07:00
// initial contents of wallet:
// commitment, channel id, customer balance, hash of wpk (wallet ver/pub key)
let mut x : Vec < Fr > = vec! [ r , cid , b0 , h_wpk ] ;
// commitment of wallet values
2018-08-13 15:16:02 -07:00
let w_com = commit_scheme ::commit ( & cm_csp , & x , r ) ;
2018-07-29 17:44:08 -07:00
// construct channel token
2018-08-10 00:01:50 -07:00
let t_c = ChannelToken { w_com : w_com , pk : keypair . pk . clone ( ) , third_party_pay : channel . third_party } ;
2018-07-29 17:44:08 -07:00
// construct customer wallet secret key plus other components
2018-07-14 18:17:00 -07:00
let csk_c = CustomerWallet { sk : keypair . sk . clone ( ) , cid : cid , wpk : wpk , wsk : wsk , h_wpk : h_wpk ,
2018-06-19 22:14:56 -07:00
r : r , balance : b0_customer , merchant_balance : b0_merchant ,
2018-07-14 18:17:00 -07:00
proof : None , signature : None , refund_token : None } ;
2018-07-29 17:44:08 -07:00
2018-08-16 15:05:01 -07:00
return InitCustomerData { channel_token : t_c , csk : csk_c , bases : cm_csp . pub_bases . clone ( ) } ;
2018-03-25 20:20:05 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// init_merchant - takes as input the public params, merchant balance and keypair.
/// Generates merchant data which consists of channel token and merchant wallet.
///
2018-06-05 10:26:16 -07:00
pub fn init_merchant ( pp : & PublicParams , b0_merchant : i32 , keypair : & clsigs ::KeyPairD ) -> InitMerchantData {
2018-08-10 00:01:50 -07:00
assert! ( b0_merchant > = 0 ) ;
2018-06-11 11:05:24 -07:00
let cm_csp = generate_commit_setup ( & pp , & keypair . pk ) ;
2018-06-05 10:26:16 -07:00
let csk_m = MerchSecretKey { sk : keypair . sk . clone ( ) , balance : b0_merchant } ;
2018-08-16 15:05:01 -07:00
return InitMerchantData { channel_token : keypair . pk . clone ( ) , csk : csk_m , bases : cm_csp . pub_bases } ;
2018-03-25 20:20:05 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// establish_customer_phase1 - takes as input the public params, customer wallet and
/// common public bases from merchant. Generates a PoK of the committed values in the
/// new wallet.
///
2018-06-14 18:07:18 -07:00
pub fn establish_customer_phase1 ( pp : & PublicParams , c_data : & InitCustomerData ,
2018-08-15 07:28:46 -07:00
pub_bases : & Vec < G2 > ) -> clproto ::ProofCV {
2018-06-08 18:20:15 -07:00
// obtain customer init data
2018-08-16 15:05:01 -07:00
let t_c = & c_data . channel_token ;
2018-06-08 18:20:15 -07:00
let csk_c = & c_data . csk ;
2018-07-14 18:17:00 -07:00
let h_wpk = csk_c . h_wpk ;
2018-08-10 00:01:50 -07:00
let b0 = convert_int_to_fr ( csk_c . balance ) ;
2018-06-08 18:20:15 -07:00
// collect secrets
2018-07-29 17:44:08 -07:00
let mut x : Vec < Fr > = vec! [ t_c . w_com . r , csk_c . cid , b0 , h_wpk ] ;
2018-06-11 00:31:27 -07:00
// generate proof of knowledge for committed values
2018-07-24 21:56:41 -07:00
let proof_1 = clproto ::bs_gen_nizk_proof ( & x , & pub_bases , t_c . w_com . c ) ;
2018-06-08 18:20:15 -07:00
return proof_1 ;
2018-04-08 00:46:17 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// establish_merchant_phase2 - takes as input the public params, channel state, initial
/// merchant wallet and PoK of committed values from the customer. Generates a blinded
/// signature over the contents of the customer's wallet.
///
2018-06-11 00:31:27 -07:00
pub fn establish_merchant_phase2 ( pp : & PublicParams , state : & mut ChannelState , m_data : & InitMerchantData ,
2018-07-24 21:56:41 -07:00
proof : & clproto ::ProofCV ) -> clsigs ::SignatureD {
2019-02-13 19:18:54 -08:00
// verifies proof (\pi_1) and produces signature on the committed values in the initial wallet
2018-07-24 21:56:41 -07:00
let wallet_sig = clproto ::bs_check_proof_and_gen_signature ( & pp . cl_mpk , & m_data . csk . sk , & proof ) ;
2018-06-11 00:31:27 -07:00
state . channel_established = true ;
2018-06-09 00:14:50 -07:00
return wallet_sig ;
}
2018-03-25 20:20:05 -07:00
2018-08-15 07:28:46 -07:00
///
/// establish_customer_final - takes as input the public params, merchant's verification key,
/// customer wallet and blinded signature obtained from merchant. Add the returned
/// blinded signature to the wallet.
///
2018-06-14 18:07:18 -07:00
pub fn establish_customer_final ( pp : & PublicParams , pk_m : & clsigs ::PublicKeyD ,
w : & mut CustomerWallet , sig : clsigs ::SignatureD ) -> bool {
2018-06-09 23:00:01 -07:00
if w . signature . is_none ( ) {
2018-06-24 22:06:36 -07:00
if pp . extra_verify {
2019-02-13 19:18:54 -08:00
// customer can verify that merchant generated a correct signature on
// the expected committed values
2018-08-10 00:01:50 -07:00
let bal = convert_int_to_fr ( w . balance ) ;
2018-07-29 17:44:08 -07:00
let mut x : Vec < Fr > = vec! [ w . r . clone ( ) , w . cid . clone ( ) , bal , w . h_wpk . clone ( ) ] ;
2018-07-25 19:19:03 -07:00
assert! ( clsigs ::verify_d ( & pp . cl_mpk , & pk_m , & x , & sig ) ) ;
2018-06-23 10:54:01 -07:00
}
2018-06-09 23:00:01 -07:00
w . signature = Some ( sig ) ;
2018-08-15 07:28:46 -07:00
//println!("establish_customer_final - verified merchant signature on initial wallet with {}", w.balance);
2018-06-09 00:14:50 -07:00
return true ;
}
2018-06-11 00:31:27 -07:00
// must be an old wallet
2018-06-09 00:14:50 -07:00
return false ;
2018-03-25 20:20:05 -07:00
}
2018-06-11 00:31:27 -07:00
///// end of establish channel protocol
2018-03-25 20:20:05 -07:00
2018-08-15 07:28:46 -07:00
///
/// pay_by_customer_phase1_precompute - takes as input the public params, channel token,
/// merchant verification key, old customer wallet. Generates PoK of signature on previous wallet.
///
2018-08-16 15:05:01 -07:00
pub fn pay_by_customer_phase1_precompute ( pp : & PublicParams , t : & ChannelToken , pk_m : & clsigs ::PublicKeyD , old_w : & mut CustomerWallet ) {
2018-08-15 07:28:46 -07:00
// generate proof of knowledge of valid signature on previous wallet
2018-08-24 00:31:46 -07:00
// get channel id, balance, commitment randomness and wallet sig
2018-07-14 18:17:00 -07:00
let cid = old_w . cid . clone ( ) ;
let old_r = & old_w . r ;
let old_wallet_sig = & old_w . signature ;
let wallet_sig = old_wallet_sig . clone ( ) . unwrap ( ) ;
// retrieve old balance
2018-08-10 00:01:50 -07:00
let old_balance = convert_int_to_fr ( old_w . balance ) ;
2018-07-14 18:17:00 -07:00
2018-07-24 18:42:07 -07:00
let old_h_wpk = old_w . h_wpk ;
2018-07-29 17:44:08 -07:00
let mut old_x : Vec < Fr > = vec! [ old_w . r . clone ( ) , cid , old_balance , old_h_wpk ] ;
2018-07-14 18:17:00 -07:00
// retrieve the commitment scheme parameters based on merchant's PK
let cm_csp = generate_commit_setup ( & pp , & pk_m ) ;
2018-08-10 00:01:50 -07:00
// extract the portion of the commitment to the balance of the wallet
let bal_index = 2 ;
let old_w_bal_com = cm_csp . pub_bases [ bal_index ] * old_balance ;
2018-07-14 18:17:00 -07:00
// proof of committed values not including the old wpk since we are revealing it
// to the merchant
let index = 3 ;
2018-08-16 15:05:01 -07:00
let old_w_com_pr = t . w_com . c - old_w_bal_com - ( cm_csp . pub_bases [ index ] * old_h_wpk ) ;
2018-08-10 00:01:50 -07:00
// NOTE: the third argument represents the challenge that is included in the final proof structure
2018-07-24 21:56:41 -07:00
let proof_old_cv = clproto ::bs_gen_nizk_proof ( & old_x , & cm_csp . pub_bases , old_w_com_pr ) ;
2018-07-14 18:17:00 -07:00
2018-08-15 00:47:02 -07:00
// generate the blind signature for the old wallet signature (we do not want to reveal this
2018-08-10 00:01:50 -07:00
// to the merchant)
2018-07-24 21:56:41 -07:00
let blind_sig = clproto ::prover_generate_blinded_sig ( & wallet_sig ) ;
2018-08-10 00:01:50 -07:00
// generate the common params necessary to execute the two party NIZK protocol
// for verifying the signature
2018-07-24 21:56:41 -07:00
let common_params = clproto ::gen_common_params ( & pp . cl_mpk , & pk_m , & wallet_sig ) ;
2018-08-10 00:01:50 -07:00
// generate the NIZK proof of valid signature based on the old wallet
2018-07-24 21:56:41 -07:00
let proof_vs = clproto ::vs_gen_nizk_proof ( & old_x , & common_params , common_params . vs ) ;
2018-07-14 18:17:00 -07:00
2018-08-10 00:01:50 -07:00
// return the payment proof for the old wallet
2018-08-14 05:28:01 -07:00
let old_iou_proof = CustomerWalletProof { proof_cv : proof_old_cv , proof_vs : proof_vs ,
bal_com : old_w_bal_com , blind_sig : blind_sig , common_params : common_params } ;
old_w . proof = Some ( old_iou_proof ) ;
2018-07-14 18:17:00 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// pay_by_customer_phase1 - takes as input the public params, channel state, channel token,
/// merchant public keys, old wallet and balance increment. Generate a new wallet commitment
/// PoK of the committed values in new wallet and PoK of old wallet. Return new channel token,
/// new wallet (minus blind signature and refund token) and payment proof.
///
2018-08-16 15:05:01 -07:00
pub fn pay_by_customer_phase1 ( pp : & PublicParams , channel : & ChannelState , t : & ChannelToken , pk_m : & clsigs ::PublicKeyD ,
2018-06-18 11:07:19 -07:00
old_w : & CustomerWallet , balance_increment : i32 ) -> ( ChannelToken , CustomerWallet , PaymentProof ) {
2018-07-21 21:22:21 -07:00
let mut rng = & mut rand ::thread_rng ( ) ;
2018-06-11 00:31:27 -07:00
2018-07-14 18:17:00 -07:00
if old_w . proof . is_none ( ) {
panic! ( " You have not executed the pay_by_customer_phase1_precompute! " ) ;
}
let wallet_proof = old_w . proof . clone ( ) . unwrap ( ) ;
2018-06-13 19:24:18 -07:00
let bal = old_w . balance ;
2018-06-11 00:31:27 -07:00
// generate new keypair
let mut schnorr = secp256k1 ::Secp256k1 ::new ( ) ;
schnorr . randomize ( rng ) ;
2018-07-21 21:22:21 -07:00
let ( wsk , wpk ) = schnorr . generate_keypair ( rng ) ;
2018-07-25 12:17:51 -07:00
let h_wpk = hash_pub_key_to_fr ( & wpk ) ;
2018-06-11 00:31:27 -07:00
// new sample randomness r'
2018-06-13 17:28:37 -07:00
let r_pr = Fr ::random ( rng ) ;
2018-06-12 11:30:24 -07:00
// retrieve the commitment scheme parameters based on merchant's PK
let cm_csp = generate_commit_setup ( & pp , & pk_m ) ;
2018-06-23 10:54:01 -07:00
// retrieve the current payment channel id
2018-06-11 00:31:27 -07:00
let cid = old_w . cid . clone ( ) ;
2018-06-11 11:05:24 -07:00
// convert balance into Fr (B - e)
2018-08-13 15:16:02 -07:00
let updated_balance = bal - balance_increment - channel . tx_fee ;
2018-06-24 22:06:36 -07:00
if updated_balance < 0 {
2018-06-14 18:07:18 -07:00
panic! ( " pay_by_customer_phase1 - insufficient funds to make payment! " ) ;
}
2018-06-23 10:54:01 -07:00
// record the potential to payment
2018-08-13 15:16:02 -07:00
let merchant_balance = old_w . merchant_balance + ( balance_increment + channel . tx_fee ) ;
2018-06-14 18:07:18 -07:00
2018-08-10 00:01:50 -07:00
let updated_balance_pr = convert_int_to_fr ( updated_balance ) ;
2018-06-11 00:31:27 -07:00
2018-07-29 17:44:08 -07:00
let mut new_wallet_sec : Vec < Fr > = vec! [ r_pr , cid , updated_balance_pr , h_wpk ] ;
// commitment of new wallet values
2018-08-13 15:16:02 -07:00
let w_com = commit_scheme ::commit ( & cm_csp , & new_wallet_sec , r_pr ) ;
2018-08-10 00:01:50 -07:00
let w_com_bytes : Vec < u8 > = encode ( & w_com . c , Infinite ) . unwrap ( ) ;
// generate proof of knowledge for committed values in new wallet
let mut proof_cv = clproto ::bs_gen_nizk_proof ( & new_wallet_sec , & cm_csp . pub_bases , w_com . c ) ;
let bal_index = 2 ; // index of balance
// sending partial commitment that does not include the balance
let w_com_pr_pr = proof_cv . C - ( cm_csp . pub_bases [ bal_index ] * updated_balance_pr ) ;
let wpk_index = new_wallet_sec . len ( ) - 1 ;
2018-06-11 00:31:27 -07:00
2018-07-21 21:22:21 -07:00
// bullet proof integration here to generate the range proof
2018-09-08 10:59:50 -07:00
let mut transcript = Transcript ::new ( b " BOLT Range Proof " ) ;
2018-07-21 21:22:21 -07:00
let value = updated_balance as u64 ;
2018-08-10 00:01:50 -07:00
let val_blinding = Scalar ::hash_from_bytes ::< Sha512 > ( & w_com_bytes ) ;
2018-10-04 11:38:10 -07:00
let pc_gens = PedersenGens ::default ( ) ;
let range_proof = RangeProof ::prove_single ( & pp . bp_gens , & pc_gens , & mut transcript ,
value , & val_blinding ,
2018-07-21 21:22:21 -07:00
pp . range_proof_bits ) . unwrap ( ) ;
2018-10-04 11:38:10 -07:00
//let pg = &pp.range_proof_gens.pedersen_gens;
let value_cm = pc_gens . commit ( Scalar ::from ( value ) , val_blinding ) ;
2018-07-21 21:22:21 -07:00
let proof_rp = ProofVB { range_proof : range_proof , value_commitment : value_cm } ;
2018-06-12 11:30:24 -07:00
2018-08-13 15:16:02 -07:00
let mut bal_proof ;
2018-08-16 15:05:01 -07:00
if t . third_party_pay {
2018-08-13 15:16:02 -07:00
let r_inc = Fr ::random ( rng ) ;
let bal_inc_fr = - convert_int_to_fr ( balance_increment + channel . tx_fee ) ;
let inc_vec : Vec < Fr > = vec! [ r_inc , bal_inc_fr ] ;
let mut v_com = commit_scheme ::commit ( & cm_csp , & inc_vec , r_inc ) ;
let proof_vcom = clproto ::bs_gen_nizk_proof ( & inc_vec , & cm_csp . pub_bases , v_com . c ) ;
// range proof that pay increment < payment max
let v_com_bytes : Vec < u8 > = encode ( & proof_vcom . C , Infinite ) . unwrap ( ) ;
let mut inc_bal ;
let final_balance_increment = balance_increment + channel . tx_fee ;
if final_balance_increment < 0 {
// negative value => convert to positive value
assert! ( final_balance_increment > = - E_MAX ) ;
inc_bal = - final_balance_increment as u64
} else {
// positive value
inc_bal = final_balance_increment as u64 ;
}
let inc_blinding = Scalar ::hash_from_bytes ::< Sha512 > ( & v_com_bytes ) ;
2018-09-08 10:59:50 -07:00
let mut transcript1 = Transcript ::new ( b " Range Proof for Balance Increment " ) ;
2018-10-04 11:38:10 -07:00
let pc_gens = PedersenGens ::default ( ) ;
let inc_range_proof = RangeProof ::prove_single ( & pp . bp_gens , & pc_gens , & mut transcript1 ,
inc_bal , & inc_blinding ,
2018-08-13 15:16:02 -07:00
pp . range_proof_bits ) . unwrap ( ) ;
2018-10-04 11:38:10 -07:00
//let inc_pg = &pp.range_proof_gens.pedersen_gens;
let inc_cm = pc_gens . commit ( Scalar ::from ( inc_bal ) , inc_blinding ) ;
2018-08-13 15:16:02 -07:00
let proof_vrange = ProofVB { range_proof : inc_range_proof , value_commitment : inc_cm } ;
bal_proof = BalanceProof { third_party : true , vcom : Some ( v_com ) ,
proof_vcom : Some ( proof_vcom ) , proof_vrange : Some ( proof_vrange ) ,
w_com_pr_pr : w_com_pr_pr , balance_increment : 0 ,
old_bal_com : wallet_proof . bal_com ,
} ;
} else {
2018-08-15 07:28:46 -07:00
// balance_increment => // epsilon - payment increment/decrement
// wallet_proof.bal_com => // old balance commitment
2018-08-13 15:16:02 -07:00
bal_proof = BalanceProof { third_party : false , vcom : None ,
proof_vcom : None , proof_vrange : None ,
w_com_pr_pr : w_com_pr_pr , balance_increment : balance_increment ,
old_bal_com : wallet_proof . bal_com ,
} ;
2018-08-10 00:01:50 -07:00
}
2018-06-13 19:24:18 -07:00
// create payment proof which includes params to reveal wpk from old wallet
2018-06-13 17:28:37 -07:00
let payment_proof = PaymentProof {
2018-08-10 00:01:50 -07:00
proof2a : proof_cv , // (1) PoK for committed values, wCom' (in new wallet)
2019-02-14 08:55:23 -08:00
//proof2b: wallet_proof.proof_cv, // PoK of committed values (minus h(wpk))
2018-07-14 18:17:00 -07:00
proof2c : wallet_proof . proof_vs , // PoK of signature on old wallet
2018-07-21 21:22:21 -07:00
proof3 : proof_rp , // range proof that the updated_balance is within a public range
2018-08-13 15:16:02 -07:00
bal_proof : bal_proof ,
2018-08-10 00:01:50 -07:00
old_com_base : cm_csp . pub_bases [ wpk_index ] , // base Z
2018-07-14 18:17:00 -07:00
wpk : old_w . wpk . clone ( ) , // showing public key for old wallet
wallet_sig : wallet_proof . blind_sig // blinded signature for old wallet
2018-06-12 11:30:24 -07:00
} ;
2018-06-13 19:24:18 -07:00
// create new wallet structure (w/o signature or refund token)
2018-08-16 15:05:01 -07:00
let t_c = ChannelToken { w_com : w_com , pk : t . pk . clone ( ) , third_party_pay : t . third_party_pay } ;
2018-07-14 18:17:00 -07:00
let csk_c = CustomerWallet { sk : old_w . sk . clone ( ) , cid : cid , wpk : wpk , wsk : wsk , h_wpk : h_wpk ,
2018-06-19 22:14:56 -07:00
r : r_pr , balance : updated_balance , merchant_balance : merchant_balance ,
2018-07-14 18:17:00 -07:00
proof : None , signature : None , refund_token : None } ;
2018-06-18 11:07:19 -07:00
return ( t_c , csk_c , payment_proof ) ;
2018-06-05 10:26:16 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// pay_by_merchant_phase1 - takes as input the public params, channel state, payment proof
/// and merchant keys. If proof is valid, then merchant returns the refund token
/// (i.e., partially blind signature on IOU with updated balance)
///
2018-06-14 18:07:18 -07:00
pub fn pay_by_merchant_phase1 ( pp : & PublicParams , mut state : & mut ChannelState , proof : & PaymentProof ,
m_data : & InitMerchantData ) -> clsigs ::SignatureD {
2018-06-12 11:30:24 -07:00
let proof_cv = & proof . proof2a ;
2019-02-14 08:55:23 -08:00
//let proof_old_cv = &proof.proof2b;
2018-06-23 10:54:01 -07:00
let proof_vs = & proof . proof2c ;
2018-08-13 15:16:02 -07:00
let bal_proof = & proof . bal_proof ;
2018-08-15 07:28:46 -07:00
let blinded_sig = & proof . wallet_sig ;
2018-06-13 17:28:37 -07:00
// get merchant keypair
2018-08-16 15:05:01 -07:00
let pk_m = & m_data . channel_token ;
2018-06-13 17:28:37 -07:00
let sk_m = & m_data . csk . sk ;
// let's first confirm that proof of knowledge of signature on old wallet is valid
2018-08-15 07:28:46 -07:00
let proof_vs_old_wallet = clproto ::vs_verify_blind_sig ( & pp . cl_mpk , & pk_m , & proof_vs , & blinded_sig ) ;
2018-06-23 10:54:01 -07:00
2019-02-14 08:55:23 -08:00
// // add specified wpk to make the proof valid
// // NOTE: if valid, then wpk is indeed the wallet public key for the wallet
// let new_c = proof_old_cv.C + bal_proof.old_bal_com + (proof.old_com_base * hash_pub_key_to_fr(&proof.wpk));
// let new_proof_old_cv = clproto::ProofCV { T: proof_old_cv.T,
// C: new_c,
// s: proof_old_cv.s.clone(),
// pub_bases: proof_old_cv.pub_bases.clone(),
// num_secrets: proof_old_cv.num_secrets };
// let is_wpk_valid_reveal = clproto::bs_verify_nizk_proof(&new_proof_old_cv);
// if !is_wpk_valid_reveal {
// panic!("pay_by_merchant_phase1 - failed to verify NIZK PoK of committed values that reveals wpk!");
// }
2018-06-23 10:54:01 -07:00
2018-06-14 18:07:18 -07:00
let is_existing_wpk = exist_in_merchant_state ( & state , & proof . wpk , None ) ;
2018-08-13 15:16:02 -07:00
let bal_inc_within_range = bal_proof . balance_increment > = - E_MAX & & bal_proof . balance_increment < = E_MAX ;
2018-07-21 21:22:21 -07:00
// check the range proof of the updated balance
2018-09-08 10:59:50 -07:00
let mut transcript = Transcript ::new ( b " BOLT Range Proof " ) ;
2018-10-04 11:38:10 -07:00
let pc_gens = PedersenGens ::default ( ) ;
let is_range_proof_valid = proof . proof3 . range_proof . 0. verify_single ( & pp . bp_gens , & pc_gens ,
& mut transcript , & proof . proof3 . range_proof . 1 ,
2018-07-21 21:22:21 -07:00
pp . range_proof_bits ) . is_ok ( ) ;
2018-06-23 10:54:01 -07:00
// if above is is_wpk_valid_reveal => true, then we can proceed to
// check that the proof of valid signature and then
2018-08-10 00:01:50 -07:00
if proof_vs_old_wallet & & ! is_existing_wpk & & bal_inc_within_range & & is_range_proof_valid {
2018-06-14 18:07:18 -07:00
println! ( " Proof of knowledge of signature is valid! " ) ;
2018-08-13 15:16:02 -07:00
if bal_proof . balance_increment < 0 {
2018-06-14 18:07:18 -07:00
// negative increment
state . R = 1 ;
} else {
// postiive increment
state . R = - 1 ; // -1 denotes \bot here
}
2018-06-11 00:31:27 -07:00
} else {
2018-06-23 10:54:01 -07:00
panic! ( " pay_by_merchant_phase1 - Verification failure for old wallet signature contents! " ) ;
2018-06-11 00:31:27 -07:00
}
2018-06-12 11:30:24 -07:00
2018-06-23 10:54:01 -07:00
// now we can verify the proof of knowledge for committed values in new wallet
2018-08-13 15:16:02 -07:00
if ! proof . bal_proof . third_party {
let bal_inc_fr = - convert_int_to_fr ( bal_proof . balance_increment ) ;
// check that the PoK on new wallet commitment is valid and
// the updated balance differs by the balance increment from the balance
// in previous wallet
let bal_index = 2 ;
2019-02-14 08:55:23 -08:00
let w_com_pr = bal_proof . w_com_pr_pr + bal_proof . old_bal_com + ( proof_cv . pub_bases [ bal_index ] * bal_inc_fr ) ;
2018-08-13 15:16:02 -07:00
if proof_cv . C ! = w_com_pr {
panic! ( " pay_by_merchant_phase1 - Old and new balance does not differ by payment amount! " ) ;
}
} else {
// in third party case, what we do a PoK for committed payment increment
let proof_vcom = proof . bal_proof . proof_vcom . as_ref ( ) . unwrap ( ) ;
if ! clproto ::bs_verify_nizk_proof ( & proof_vcom ) {
panic! ( " pay_by_merchant_phase1 - Could not verify the NIZK PoK of payment amount " ) ;
}
}
if clproto ::bs_verify_nizk_proof ( & proof_cv ) {
2018-06-13 17:28:37 -07:00
// generate refund token on new wallet
let i = pk_m . Z2 . len ( ) - 1 ;
2018-07-25 12:17:51 -07:00
let c_refund = proof_cv . C + ( pk_m . Z2 [ i ] * convert_str_to_fr ( " refund " ) ) ;
2018-06-13 17:28:37 -07:00
// generating partially blind signature on refund || wpk' || B - e
2018-08-15 07:28:46 -07:00
let rt_w = clproto ::bs_compute_blind_signature ( & pp . cl_mpk , & sk_m , c_refund , proof_cv . num_secrets + 1 ) ;
2018-06-14 18:07:18 -07:00
println! ( " pay_by_merchant_phase1 - Proof of knowledge of commitment on new wallet is valid " ) ;
update_merchant_state ( & mut state , & proof . wpk , None ) ;
2018-06-14 22:18:20 -07:00
state . pay_init = true ;
2018-06-13 17:28:37 -07:00
return rt_w ;
2018-06-12 11:30:24 -07:00
}
2018-06-14 18:07:18 -07:00
panic! ( " pay_by_merchant_phase1 - NIZK verification failed for new wallet commitment! " ) ;
2018-06-13 17:28:37 -07:00
}
2018-08-13 15:16:02 -07:00
///
/// Verify third party payment proof from two bi-directional channel payments with intermediary
///
pub fn verify_third_party_payment ( pp : & PublicParams , fee : i32 , 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 ( ) ;
2018-10-04 11:38:10 -07:00
let pc_gens1 = PedersenGens ::default ( ) ;
let pc_gens2 = PedersenGens ::default ( ) ;
2018-09-08 10:59:50 -07:00
let mut transcript1 = Transcript ::new ( b " Range Proof for Balance Increment " ) ;
2018-10-04 11:38:10 -07:00
let range_proof1_valid = rproof1 . range_proof . 0. verify_single ( & pp . bp_gens , & pc_gens1 ,
2018-08-13 15:16:02 -07:00
& mut transcript1 ,
2018-10-04 11:38:10 -07:00
& rproof1 . range_proof . 1 ,
2018-08-13 15:16:02 -07:00
pp . range_proof_bits ) . is_ok ( ) ;
2018-09-08 10:59:50 -07:00
let mut transcript2 = Transcript ::new ( b " Range Proof for Balance Increment " ) ;
2018-10-04 11:38:10 -07:00
let range_proof2_valid = rproof2 . range_proof . 0. verify_single ( & pp . bp_gens , & pc_gens2 ,
2018-08-13 15:16:02 -07:00
& mut transcript2 ,
2018-10-04 11:38:10 -07:00
& rproof2 . range_proof . 1 ,
2018-08-13 15:16:02 -07:00
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 ;
2018-08-13 15:18:14 -07:00
2018-08-13 15:16:02 -07:00
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 " ) ;
}
2018-08-15 07:28:46 -07:00
///
/// pay_by_customer_phase2 - takes as input the public params, old wallet, new wallet,
/// merchant's verification key and refund token. If the refund token is valid, generate
/// a revocation token for the old wallet public key.
///
2018-06-14 18:07:18 -07:00
pub fn pay_by_customer_phase2 ( pp : & PublicParams , old_w : & CustomerWallet , new_w : & CustomerWallet ,
pk_m : & clsigs ::PublicKeyD , rt_w : & clsigs ::SignatureD ) -> RevokeToken {
2018-06-13 19:24:18 -07:00
// (1) verify the refund token (rt_w) against the new wallet contents
2018-08-10 00:01:50 -07:00
let bal = convert_int_to_fr ( new_w . balance ) ;
2018-07-29 17:44:08 -07:00
let h_wpk = hash_pub_key_to_fr ( & new_w . wpk ) ;
let refund = convert_str_to_fr ( " refund " ) ;
let mut x : Vec < Fr > = vec! [ new_w . r . clone ( ) , new_w . cid . clone ( ) , bal , h_wpk , refund ] ;
2018-06-13 17:28:37 -07:00
2018-07-25 19:19:03 -07:00
let is_rt_w_valid = clsigs ::verify_d ( & pp . cl_mpk , & pk_m , & x , & rt_w ) ;
2018-06-24 22:06:36 -07:00
if is_rt_w_valid {
2018-06-13 17:28:37 -07:00
println! ( " Refund token is valid against the new wallet! " ) ;
2018-06-14 20:50:00 -07:00
let schnorr = secp256k1 ::Secp256k1 ::new ( ) ;
2018-06-14 18:07:18 -07:00
let rm = RevokedMessage ::new ( String ::from ( " revoked " ) , old_w . wpk , None ) ;
2018-06-13 17:28:37 -07:00
let msg = secp256k1 ::Message ::from_slice ( & rm . hash_to_slice ( ) ) . unwrap ( ) ;
// msg = "revoked"|| old_wpk (for old wallet)
let rv_w = schnorr . sign ( & msg , & old_w . wsk ) ;
// return the revocation token
2018-07-21 21:22:21 -07:00
return RevokeToken { message : rm , signature : rv_w } ;
2018-06-13 17:28:37 -07:00
}
2018-06-14 18:07:18 -07:00
panic! ( " pay_by_customer_phase2 - Merchant did not provide a valid refund token! " ) ;
2018-06-13 17:28:37 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// pay_by_merchant_phase2 - takes as input the public params, channel state, proof of payment,
/// merchant wallet, and revocation token from the customer. If the revocation token is valid,
/// generate a new signature for the new wallet (from the PoK of committed values in new wallet).
///
2018-06-14 18:07:18 -07:00
pub fn pay_by_merchant_phase2 ( pp : & PublicParams , mut state : & mut ChannelState ,
proof : & PaymentProof , m_data : & mut InitMerchantData ,
rv : & RevokeToken ) -> clsigs ::SignatureD {
2018-06-13 17:28:37 -07:00
let proof_cv = & proof . proof2a ;
let sk_m = & m_data . csk . sk ;
let schnorr = secp256k1 ::Secp256k1 ::new ( ) ;
let msg = secp256k1 ::Message ::from_slice ( & rv . message . hash_to_slice ( ) ) . unwrap ( ) ;
// verify that the revocation token is valid
let is_rv_valid = schnorr . verify ( & msg , & rv . signature , & proof . wpk ) . is_ok ( ) ;
2018-06-14 18:07:18 -07:00
2018-07-24 21:56:41 -07:00
if clproto ::bs_verify_nizk_proof ( & proof_cv ) & & is_rv_valid {
2018-06-14 18:07:18 -07:00
// update merchant state with (wpk, sigma_rev)
update_merchant_state ( & mut state , & proof . wpk , Some ( rv . signature ) ) ;
2018-07-24 21:56:41 -07:00
let new_wallet_sig = clproto ::bs_compute_blind_signature ( & pp . cl_mpk , & sk_m , proof_cv . C , proof_cv . num_secrets ) ;
2018-08-13 15:16:02 -07:00
m_data . csk . balance + = proof . bal_proof . balance_increment + state . tx_fee ;
2018-06-14 18:07:18 -07:00
state . R = 2 ;
2018-06-13 17:28:37 -07:00
return new_wallet_sig ;
}
2018-06-14 18:07:18 -07:00
panic! ( " pay_by_merchant_phase2 - Customer did not provide valid revocation token! " ) ;
2018-06-13 17:28:37 -07:00
}
2018-08-15 07:28:46 -07:00
///
/// pay_by_customer_final - takes as input the public params, merchant's verification key,
/// customer's old wallet, new channel token, new wallet and wallet signature (from merchant).
/// Update the new wallet accordingly and checks if the signature from merchant is valid.
///
2018-06-13 19:24:18 -07:00
pub fn pay_by_customer_final ( pp : & PublicParams , pk_m : & clsigs ::PublicKeyD ,
2018-06-18 11:07:19 -07:00
c_data : & mut InitCustomerData , mut new_t : ChannelToken ,
2018-06-13 17:28:37 -07:00
mut new_w : CustomerWallet , sig : clsigs ::SignatureD ) -> bool {
if new_w . signature . is_none ( ) {
2018-06-24 22:06:36 -07:00
if pp . extra_verify {
2018-08-10 00:01:50 -07:00
let bal = convert_int_to_fr ( new_w . balance ) ;
2018-07-29 17:44:08 -07:00
let h_wpk = hash_pub_key_to_fr ( & new_w . wpk ) ;
let mut x : Vec < Fr > = vec! [ new_w . r . clone ( ) , new_w . cid . clone ( ) , bal , h_wpk ] ;
2018-07-25 19:19:03 -07:00
assert! ( clsigs ::verify_d ( & pp . cl_mpk , & pk_m , & x , & sig ) ) ;
2018-06-23 10:54:01 -07:00
}
// update signature in new wallet
2018-06-13 17:28:37 -07:00
new_w . signature = Some ( sig ) ;
2018-06-23 10:54:01 -07:00
// update csk in new wallet
2018-06-13 17:28:37 -07:00
c_data . csk = new_w ;
2018-06-23 10:54:01 -07:00
// update the channel token
2018-08-16 15:05:01 -07:00
c_data . channel_token = new_t ;
2018-06-13 17:28:37 -07:00
return true ;
}
// must be an old wallet
return false ;
2018-03-25 20:20:05 -07:00
}
2018-06-13 17:28:37 -07:00
2018-06-11 00:31:27 -07:00
///// end of pay protocol
2018-03-25 20:20:05 -07:00
2018-06-09 23:00:01 -07:00
// for customer => on input a wallet w, it outputs a customer channel closure message rc_c
2018-08-15 07:28:46 -07:00
///
/// customer_refund - takes as input the public params, channel state, merchant's verification
/// key, and customer wallet. Generates a channel closure message for customer.
///
2018-06-14 22:18:20 -07:00
pub fn customer_refund ( pp : & PublicParams , state : & ChannelState , pk_m : & clsigs ::PublicKeyD ,
2018-07-25 12:17:51 -07:00
w : & CustomerWallet ) -> ChannelclosureC {
2018-06-11 00:31:27 -07:00
let m ;
2018-06-09 23:00:01 -07:00
let balance = w . balance as usize ;
2018-06-11 00:31:27 -07:00
if ! state . pay_init {
2018-06-23 10:54:01 -07:00
// pay protocol not invoked so take the balance
2018-06-14 22:18:20 -07:00
m = RefundMessage ::new ( String ::from ( " refundUnsigned " ) , w . wpk , balance , Some ( w . r ) , None ) ;
2018-06-11 00:31:27 -07:00
} else {
// if channel has already been activated, then take unspent funds
2018-06-14 22:18:20 -07:00
m = RefundMessage ::new ( String ::from ( " refundToken " ) , w . wpk , balance , None , w . refund_token . clone ( ) ) ;
2018-06-09 23:00:01 -07:00
}
// generate signature on the balance/channel id, etc to obtain funds back
let m_vec = m . hash ( ) ;
2018-07-25 19:19:03 -07:00
let sigma = clsigs ::sign_d ( & pp . cl_mpk , & w . sk , & m_vec ) ;
2018-07-25 12:17:51 -07:00
return ChannelclosureC { message : m , signature : sigma } ;
2018-06-09 23:00:01 -07:00
}
2018-06-14 18:07:18 -07:00
fn exist_in_merchant_state ( state : & ChannelState , wpk : & secp256k1 ::PublicKey , rev : Option < secp256k1 ::Signature > ) -> bool {
2018-06-24 22:06:36 -07:00
if state . keys . is_empty ( ) {
2018-06-14 18:07:18 -07:00
return false ;
}
2018-07-25 12:17:51 -07:00
let fingerprint = compute_pub_key_fingerprint ( wpk ) ;
2018-06-24 22:06:36 -07:00
if state . keys . contains_key ( & fingerprint ) {
2018-06-14 18:07:18 -07:00
let pub_key = state . keys . get ( & fingerprint ) . unwrap ( ) ;
if pub_key . revoke_token . is_none ( ) {
// let's just check the public key
2018-07-21 21:22:21 -07:00
return pub_key . wpk = = * wpk ;
2018-06-14 18:07:18 -07:00
}
2018-06-24 22:06:36 -07:00
if ! rev . is_none ( ) {
2018-07-21 21:22:21 -07:00
return pub_key . wpk = = * wpk & & pub_key . revoke_token . unwrap ( ) = = rev . unwrap ( ) ;
2018-06-14 18:07:18 -07:00
}
2018-07-21 21:22:21 -07:00
return pub_key . wpk = = * wpk ;
2018-06-14 18:07:18 -07:00
}
return false ;
2018-06-09 23:00:01 -07:00
}
2018-06-14 18:07:18 -07:00
fn update_merchant_state ( state : & mut ChannelState , wpk : & secp256k1 ::PublicKey , rev : Option < secp256k1 ::Signature > ) -> bool {
2018-07-25 12:17:51 -07:00
let fingerprint = compute_pub_key_fingerprint ( wpk ) ;
2018-06-14 18:07:18 -07:00
//println!("Print fingerprint: {}", fingerprint);
if ! rev . is_none ( ) {
let cust_pub_key = PubKeyMap { wpk : wpk . clone ( ) , revoke_token : Some ( rev . unwrap ( ) . clone ( ) ) } ;
state . keys . insert ( fingerprint , cust_pub_key ) ;
} else {
let cust_pub_key = PubKeyMap { wpk : wpk . clone ( ) , revoke_token : None } ;
state . keys . insert ( fingerprint , cust_pub_key ) ;
}
2018-06-09 23:00:01 -07:00
return true ;
}
2018-08-15 07:28:46 -07:00
///
/// merchant_refute - takes as input the public params, channel token, merchant's wallet,
/// channels tate, channel closure from customer, and revocation token.
/// Generates a channel closure message for merchant and updated merchant internal state.
///
2018-08-16 15:05:01 -07:00
pub fn merchant_refute ( pp : & PublicParams , state : & mut ChannelState , t_c : & ChannelToken , m_data : & InitMerchantData ,
rc_c : & ChannelclosureC , rv_token : & secp256k1 ::Signature ) -> ChannelclosureM {
2018-08-15 07:28:46 -07:00
// for merchant => on input the merchant's current state S_old and a customer channel closure message,
// outputs a merchant channel closure message rc_m and updated merchant state S_new
2018-08-16 15:05:01 -07:00
let is_valid = clsigs ::verify_d ( & pp . cl_mpk , & t_c . pk , & rc_c . message . hash ( ) , & rc_c . signature ) ;
2018-06-09 23:00:01 -07:00
if is_valid {
let wpk = rc_c . message . wpk ;
let balance = rc_c . message . balance ;
2018-08-14 10:00:44 -07:00
if ! exist_in_merchant_state ( & state , & wpk , Some ( * rv_token ) ) {
2018-06-09 23:00:01 -07:00
// update state to include the user's wallet key
2018-06-14 18:07:18 -07:00
assert! ( update_merchant_state ( state , & wpk , Some ( * rv_token ) ) ) ;
2018-06-09 23:00:01 -07:00
}
2019-02-19 09:01:51 -08:00
let ser_rv_token = rv_token . serialize_compact ( ) ;
2018-08-14 10:00:44 -07:00
let rm = RevokedMessage ::new ( String ::from ( " revoked " ) , wpk , Some ( ser_rv_token ) ) ;
// sign the revoked message
let signature = clsigs ::sign_d ( & pp . cl_mpk , & m_data . csk . sk , & rm . hash ( ) ) ;
return ChannelclosureM { message : rm , signature : signature } ;
2018-06-09 23:00:01 -07:00
} else {
panic! ( " Signature on customer closure message is invalid! " ) ;
}
}
2018-08-15 07:28:46 -07:00
///
/// resolve - on input the customer and merchant channel tokens T_c, T_m, along with
/// closure messages rc_c, rc_m.
/// this will be executed by the network to make sure the right balance is returned
/// to each party based on provided inputs.
///
2018-08-14 05:28:01 -07:00
pub fn resolve ( pp : & PublicParams , c : & InitCustomerData , m : & InitMerchantData ,
2018-07-25 12:17:51 -07:00
rc_c : Option < ChannelclosureC > , rc_m : Option < ChannelclosureM > ,
2018-06-14 22:18:20 -07:00
rt_w : Option < clsigs ::SignatureD > ) -> ( i32 , i32 ) {
2018-06-11 00:31:27 -07:00
let total_balance = c . csk . balance + m . csk . balance ;
2018-06-24 22:06:36 -07:00
if rc_c . is_none ( ) & & rc_m . is_none ( ) {
2018-08-14 10:00:44 -07:00
panic! ( " resolve1 - Did not specify channel closure messages for either customer or merchant! " ) ;
2018-06-09 23:00:01 -07:00
}
if rc_c . is_none ( ) {
2018-08-14 05:28:01 -07:00
// could not find customer's channel closure message.
// judgement: give merchant everything
2018-06-11 00:31:27 -07:00
return ( 0 , total_balance ) ;
2018-06-09 23:00:01 -07:00
}
2018-08-16 15:05:01 -07:00
let pk_c = & c . channel_token . pk ; // get public key for customer
let pk_m = & m . channel_token ; // get public key for merchant
2018-06-09 23:00:01 -07:00
let rc_cust = rc_c . unwrap ( ) ;
2018-07-25 19:19:03 -07:00
let rcc_valid = clsigs ::verify_d ( & pp . cl_mpk , & pk_c , & rc_cust . message . hash ( ) , & rc_cust . signature ) ;
2018-06-11 00:31:27 -07:00
if ! rcc_valid {
2018-08-14 10:00:44 -07:00
panic! ( " resolve2 - rc_c signature is invalid! " ) ;
2018-06-11 00:31:27 -07:00
}
2018-08-15 07:28:46 -07:00
let msg = & rc_cust . message ;
2018-08-16 15:05:01 -07:00
let w_com = & c . channel_token . w_com ;
2018-06-11 00:31:27 -07:00
if msg . msgtype = = " refundUnsigned " {
// assert the validity of the w_com
2018-06-14 22:18:20 -07:00
let cm_csp = generate_commit_setup ( & pp , & pk_m ) ;
2018-07-25 12:17:51 -07:00
let h_wpk = hash_pub_key_to_fr ( & c . csk . wpk ) ;
2018-06-11 00:31:27 -07:00
// convert balance into Fr
2018-08-10 00:01:50 -07:00
let balance = convert_int_to_fr ( c . csk . balance ) ;
2018-07-29 17:44:08 -07:00
let mut x : Vec < Fr > = vec! [ w_com . r , c . csk . cid , h_wpk , balance ] ;
2018-06-11 00:31:27 -07:00
// check that w_com is a valid commitment
if ! commit_scheme ::decommit ( & cm_csp , & w_com , & x ) {
// if this fails, then customer gets 0 and merchant gets full channel balance
2018-08-14 10:00:44 -07:00
println! ( " resolve3 - failed verify commitment on wallet " ) ;
2018-06-11 00:31:27 -07:00
return ( 0 , total_balance ) ;
}
} else if msg . msgtype = = " refundToken " {
2018-06-14 22:18:20 -07:00
// check that the refund token for specified wallet is valid
2018-08-14 10:00:44 -07:00
let bal = convert_int_to_fr ( msg . balance as i32 ) ;
let h_wpk = hash_pub_key_to_fr ( & msg . wpk ) ;
let refund = convert_str_to_fr ( " refund " ) ;
let mut x : Vec < Fr > = vec! [ c . csk . r . clone ( ) , c . csk . cid . clone ( ) , bal , h_wpk , refund ] ;
let is_rt_valid = clsigs ::verify_d ( & pp . cl_mpk , & pk_m , & x , & rt_w . unwrap ( ) ) ;
if ! is_rt_valid {
2018-06-11 00:31:27 -07:00
// refund token signature not valid, so pay full channel balance to merchant
return ( 0 , total_balance )
}
}
2018-08-14 10:00:44 -07:00
2018-06-11 00:31:27 -07:00
if ! rc_m . is_none ( ) {
let rc_merch = rc_m . unwrap ( ) ;
2018-07-25 19:19:03 -07:00
let refute_valid = clsigs ::verify_d ( & pp . cl_mpk , & pk_m , & rc_merch . message . hash ( ) , & rc_merch . signature ) ;
2018-06-11 00:31:27 -07:00
if ! refute_valid {
2018-08-14 05:28:01 -07:00
// refute token is invalid, so return customer balance and merchant balance
return ( c . csk . balance , m . csk . balance ) ;
2018-06-11 00:31:27 -07:00
} else {
// if refutation is valid
return ( 0 , total_balance ) ;
}
}
2018-06-09 23:00:01 -07:00
2018-08-14 10:00:44 -07:00
panic! ( " resolve4 - Did not specify channel closure messages for either customer or merchant! " ) ;
2018-06-09 23:00:01 -07:00
}
2018-03-25 20:20:05 -07:00
}
2018-07-24 18:42:07 -07:00
2019-02-19 09:01:51 -08:00
#[ no_mangle ]
pub mod ffishim {
extern crate libc ;
use bidirectional ;
use clsigs ;
2019-02-19 12:27:39 -08:00
use commit_scheme ;
2019-02-19 15:02:53 -08:00
use clproto ;
2019-02-19 12:27:39 -08:00
2019-02-19 09:01:51 -08:00
use serde ::{ Serialize } ;
use libc ::{ c_char } ;
use std ::ffi ::{ CStr , CString } ;
use std ::str ;
use std ::mem ;
2019-02-26 11:52:47 -08:00
#[ no_mangle ]
pub extern fn ffishim_free_string ( pointer : * mut c_char ) {
unsafe {
if pointer . is_null ( ) { return }
CString ::from_raw ( pointer )
} ;
}
2019-02-19 09:01:51 -08:00
#[ no_mangle ]
pub extern fn ffishim_bidirectional_setup ( extra_verify : u32 ) -> * mut c_char {
let mut ev = false ;
if extra_verify > 1 {
ev = true ;
}
let pp = bidirectional ::setup ( ev ) ;
2019-02-26 17:10:40 -08:00
let ser = [ " { \' pp \' : \' " , serde_json ::to_string ( & pp ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
2019-02-19 15:02:53 -08:00
pub extern fn ffishim_bidirectional_channelstate_new ( channel_name : * const c_char , third_party_support : u32 ) -> * mut c_char {
2019-02-19 09:01:51 -08:00
2019-02-19 15:02:53 -08:00
let bytes = unsafe { CStr ::from_ptr ( channel_name ) . to_bytes ( ) } ;
let name : & str = str ::from_utf8 ( bytes ) . unwrap ( ) ; // make sure the bytes are UTF-8
2019-02-26 11:52:47 -08:00
2019-02-19 09:01:51 -08:00
let mut tps = false ;
if third_party_support > 1 {
tps = true ;
}
2019-02-19 15:02:53 -08:00
let channel = bidirectional ::ChannelState ::new ( name . to_string ( ) , tps ) ;
2019-02-26 17:10:40 -08:00
let ser = [ " { \' state \' : \' " , serde_json ::to_string ( & channel ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ; ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
2019-02-26 11:52:47 -08:00
// TODO GET RID OF THESE TEST THINGS
2019-02-19 09:01:51 -08:00
#[ no_mangle ]
pub extern fn ffishim_bidirectional_teststruct ( ) -> * mut c_char {
let cl_mpk_instance = clsigs ::setup_d ( ) ;
let test = bidirectional ::TestPublicParams {
cl_mpk : cl_mpk_instance ,
range_proof_bits : 52
} ;
2019-02-26 17:10:40 -08:00
let cl_mpk_instance_two = clsigs ::setup_d ( ) ;
let test_two = bidirectional ::TestPublicParams {
cl_mpk : cl_mpk_instance_two ,
range_proof_bits : 21
} ;
// let ser = ["{\'a\' : \'" , "serde_jsonto_string(test).unwrap().as_str()", "\' ,\'b\' : \'", "serde_jsonto_string(test_two).unwrap().as_str()", "\'}"].concat();
let ser = [ " { \' a \' : \' " , serde_json ::to_string ( & test ) . unwrap ( ) . as_str ( ) , " \' , \' b \' : \' " , serde_json ::to_string ( & test_two ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
2019-02-26 11:52:47 -08:00
2019-02-19 09:01:51 -08:00
cser . into_raw ( )
}
#[ no_mangle ]
2019-02-26 11:52:47 -08:00
pub extern fn ffishim_bidirectional_teststruct_in ( mut serialized_pp : * mut c_char ) -> usize {
2019-02-19 09:01:51 -08:00
let bytes = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name : & str = str ::from_utf8 ( bytes ) . unwrap ( ) ; // make sure the bytes are UTF-8
2019-02-26 11:52:47 -08:00
let mut object : bidirectional ::TestPublicParams = serde_json ::from_str ( & name ) . unwrap ( ) ;
let test = bidirectional ::TestPublicParams {
cl_mpk : clsigs ::setup_d ( ) ,
range_proof_bits : 3
} ;
let ser = serde_json ::to_string ( & test ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
unsafe { serialized_pp = cser . into_raw ( ) ; }
2019-02-26 17:10:40 -08:00
object . range_proof_bits
2019-02-19 09:01:51 -08:00
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_keygen ( serialized_pp : * mut c_char ) -> * mut c_char {
let bytes = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name : & str = str ::from_utf8 ( bytes ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name ) . unwrap ( ) ;
let keypair = bidirectional ::keygen ( & deserialized_pp ) ;
2019-02-26 17:10:40 -08:00
let ser = [ " { \' keypair \' : \' " , serde_json ::to_string ( & keypair ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_init_merchant ( serialized_pp : * mut c_char , balance_merchant : i32 , serialized_merchant_keypair : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
let init_merchant_data = bidirectional ::init_merchant ( & deserialized_pp , balance_merchant , & deserialized_merchant_keypair ) ;
2019-02-26 17:10:40 -08:00
let ser = [ " { \' merchant_data \' : \' " , serde_json ::to_string ( & init_merchant_data ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
2019-02-26 17:10:40 -08:00
pub extern fn ffishim_bidirectional_generate_commit_setup ( serialized_pp : * mut c_char , serialized_merchant_public_key : * mut c_char ) -> * mut c_char {
2019-02-19 09:01:51 -08:00
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the merchant keypair
2019-02-26 17:10:40 -08:00
let bytes_pk = unsafe { CStr ::from_ptr ( serialized_merchant_public_key ) . to_bytes ( ) } ;
let name_pk : & str = str ::from_utf8 ( bytes_pk ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_public_key : clsigs ::PublicKeyD = serde_json ::from_str ( & name_pk ) . unwrap ( ) ;
2019-02-19 09:01:51 -08:00
2019-02-26 17:10:40 -08:00
let cm_csp = bidirectional ::generate_commit_setup ( & deserialized_pp , & deserialized_merchant_public_key ) ;
let ser = [ " { \' commit_setup \' : \' " , serde_json ::to_string ( & cm_csp ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
2019-02-26 11:52:47 -08:00
pub extern fn ffishim_bidirectional_init_customer ( serialized_pp : * mut c_char , serialized_channel : * mut c_char , balance_customer : i32 , balance_merchant : i32 , serialized_commitment_setup : * mut c_char , serialized_customer_keypair : * mut c_char ) -> * mut c_char {
2019-02-19 09:01:51 -08:00
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
2019-02-26 11:52:47 -08:00
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
2019-02-19 09:01:51 -08:00
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
2019-02-19 15:10:23 -08:00
let mut deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
2019-02-19 09:01:51 -08:00
// Deserialize the commitment setup
let bytes_commitment_setup = unsafe { CStr ::from_ptr ( serialized_commitment_setup ) . to_bytes ( ) } ;
let name_commitment_setup : & str = str ::from_utf8 ( bytes_commitment_setup ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_ccommitment_setup : commit_scheme ::CSParams = serde_json ::from_str ( & name_commitment_setup ) . unwrap ( ) ;
// Deserialize the client keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_customer_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_customer_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
2019-02-26 17:10:40 -08:00
// We change the channel state
2019-02-19 15:10:23 -08:00
let cust_data = bidirectional ::init_customer ( & deserialized_pp , & mut deserialized_channel_state , balance_customer , balance_merchant , & deserialized_ccommitment_setup , & deserialized_customer_keypair ) ;
2019-02-26 17:10:40 -08:00
let ser = [ " { \' customer_data \' : \' " , serde_json ::to_string ( & cust_data ) . unwrap ( ) . as_str ( ) , " \' , \' state \' : \' " , serde_json ::to_string ( & deserialized_channel_state ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ;
2019-02-19 09:01:51 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
2019-02-19 15:02:53 -08:00
#[ no_mangle ]
pub extern fn ffishim_bidirectional_establish_customer_phase1 ( serialized_pp : * mut c_char , serialized_customer_data : * mut c_char , serialized_merchant_data : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
2019-02-19 09:01:51 -08:00
2019-02-19 15:02:53 -08:00
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
2019-02-19 09:01:51 -08:00
2019-02-19 15:02:53 -08:00
// Deserialize the merchant data
let bytes_merchant_data = unsafe { CStr ::from_ptr ( serialized_merchant_data ) . to_bytes ( ) } ;
let name_merchant_data : & str = str ::from_utf8 ( bytes_merchant_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_data : bidirectional ::InitMerchantData = serde_json ::from_str ( & name_merchant_data ) . unwrap ( ) ;
2019-02-19 09:01:51 -08:00
2019-02-19 15:02:53 -08:00
let proof1 = bidirectional ::establish_customer_phase1 ( & deserialized_pp , & deserialized_customer_data , & deserialized_merchant_data . bases ) ;
2019-02-26 17:10:40 -08:00
let ser = [ " { \' proof \' : \' " , serde_json ::to_string ( & proof1 ) . unwrap ( ) . as_str ( ) , " \' } " ] . concat ( ) ; ;
2019-02-19 15:02:53 -08:00
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
2019-02-19 09:01:51 -08:00
2019-02-19 15:02:53 -08:00
#[ no_mangle ]
2019-02-26 11:52:47 -08:00
pub extern fn ffishim_bidirectional_establish_merchant_phase2 ( serialized_pp : * mut c_char , serialized_channel : * mut c_char , serialized_merchant_data : * mut c_char , serialized_proof1 : * mut c_char ) -> * mut c_char {
2019-02-19 15:02:53 -08:00
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
2019-02-26 11:52:47 -08:00
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
2019-02-19 15:02:53 -08:00
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
// Deserialize the merchant data
let bytes_merchant_data = unsafe { CStr ::from_ptr ( serialized_merchant_data ) . to_bytes ( ) } ;
let name_merchant_data : & str = str ::from_utf8 ( bytes_merchant_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_data : bidirectional ::InitMerchantData = serde_json ::from_str ( & name_merchant_data ) . unwrap ( ) ;
// Deserialize the first proof
let bytes_proof_1 = unsafe { CStr ::from_ptr ( serialized_proof1 ) . to_bytes ( ) } ;
let name_proof_1 : & str = str ::from_utf8 ( bytes_proof_1 ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_proof_1 : clproto ::ProofCV = serde_json ::from_str ( & name_proof_1 ) . unwrap ( ) ;
let wallet_sig = bidirectional ::establish_merchant_phase2 ( & deserialized_pp , & mut deserialized_channel_state , & deserialized_merchant_data , & deserialized_proof_1 ) ;
let ser = serde_json ::to_string ( & wallet_sig ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_establish_customer_final ( serialized_pp : * mut c_char , serialized_merchant_keypair : * mut c_char , serialized_customer_data : * mut c_char , serialized_wallet_sig : * mut c_char ) -> bool {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
// Deserialize the wallet_sig
let bytes_wallet_sig = unsafe { CStr ::from_ptr ( serialized_wallet_sig ) . to_bytes ( ) } ;
let name_wallet_sig : & str = str ::from_utf8 ( bytes_wallet_sig ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_wallet_sig : clsigs ::SignatureD = serde_json ::from_str ( & name_wallet_sig ) . unwrap ( ) ;
bidirectional ::establish_customer_final ( & deserialized_pp , & deserialized_merchant_keypair . pk , & mut deserialized_customer_data . csk , deserialized_wallet_sig )
}
2019-02-26 11:52:47 -08:00
#[ no_mangle ]
pub extern fn ffishim_bidirectional_pay_by_customer_phase1_precompute ( serialized_pp : * mut c_char , serialized_customer_data : /* Needs to be mut */ * mut c_char , serialized_merchant_keypair : * mut c_char ) -> bool {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
// TODO this is going to do literally nothing...
bidirectional ::pay_by_customer_phase1_precompute ( & deserialized_pp , & deserialized_customer_data . channel_token , & deserialized_merchant_keypair . pk , & mut deserialized_customer_data . csk ) ;
true
}
//TODO Two return values
#[ no_mangle ]
pub extern fn ffishim_bidirectional_pay_by_customer_phase1 ( serialized_pp : * mut c_char , serialized_channel : * mut c_char , serialized_customer_data : * mut c_char , serialized_merchant_keypair : * mut c_char , balance_increment : i32 ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
// TODO: Dictionary these bad boys: ChannelToken, CustomerWallet, PaymentProof
let ( t_c , new_wallet , pay_proof ) = bidirectional ::pay_by_customer_phase1 ( & deserialized_pp , & deserialized_channel_state , & deserialized_customer_data . channel_token , & deserialized_merchant_keypair . pk , & deserialized_customer_data . csk , balance_increment ) ;
let ser = serde_json ::to_string ( & pay_proof ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_pay_by_merchant_phase1 ( serialized_pp : * mut c_char , serialized_channel : /* make mut */ * mut c_char , serialized_pay_proof : * mut c_char , serialized_merchant_data : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
// Deserialize the pay proof
let bytes_pay_proof = unsafe { CStr ::from_ptr ( serialized_pay_proof ) . to_bytes ( ) } ;
let name_pay_proof : & str = str ::from_utf8 ( bytes_pay_proof ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pay_proof : bidirectional ::PaymentProof = serde_json ::from_str ( & name_pay_proof ) . unwrap ( ) ;
// Deserialize the merchant data
let bytes_merchant_data = unsafe { CStr ::from_ptr ( serialized_merchant_data ) . to_bytes ( ) } ;
let name_merchant_data : & str = str ::from_utf8 ( bytes_merchant_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_data : bidirectional ::InitMerchantData = serde_json ::from_str ( & name_merchant_data ) . unwrap ( ) ;
let rt_w = bidirectional ::pay_by_merchant_phase1 ( & deserialized_pp , & mut deserialized_channel_state , & deserialized_pay_proof , & deserialized_merchant_data ) ;
let ser = serde_json ::to_string ( & rt_w ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_pay_by_customer_phase2 ( serialized_pp : * mut c_char , serialized_customer_data : * mut c_char , serialized_new_wallet : * mut c_char , serialized_merchant_keypair : * mut c_char , serialized_rt_w : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
// Deserialize the new wallet
let bytes_new_wallet = unsafe { CStr ::from_ptr ( serialized_new_wallet ) . to_bytes ( ) } ;
let name_new_wallet : & str = str ::from_utf8 ( bytes_new_wallet ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_new_wallet : bidirectional ::CustomerWallet = serde_json ::from_str ( & name_new_wallet ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
// Deserialize the rt_w
let bytes_rt_w = unsafe { CStr ::from_ptr ( serialized_rt_w ) . to_bytes ( ) } ;
let name_rt_w : & str = str ::from_utf8 ( bytes_rt_w ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_rt_w : clsigs ::SignatureD = serde_json ::from_str ( & name_rt_w ) . unwrap ( ) ;
// RevokeToken
let rv_w = bidirectional ::pay_by_customer_phase2 ( & deserialized_pp , & deserialized_customer_data . csk , & deserialized_new_wallet , & deserialized_merchant_keypair . pk , & deserialized_rt_w ) ;
let ser = serde_json ::to_string ( & rv_w ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_pay_by_merchant_phase2 ( serialized_pp : * mut c_char , serialized_channel : /* make mut */ * mut c_char , serialized_pay_proof : * mut c_char , serialized_merchant_data : /* make mut */ * mut c_char , serialized_revoke_token : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
// Deserialize the pay proof
let bytes_pay_proof = unsafe { CStr ::from_ptr ( serialized_pay_proof ) . to_bytes ( ) } ;
let name_pay_proof : & str = str ::from_utf8 ( bytes_pay_proof ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pay_proof : bidirectional ::PaymentProof = serde_json ::from_str ( & name_pay_proof ) . unwrap ( ) ;
// Deserialize the merchant data
let bytes_merchant_data = unsafe { CStr ::from_ptr ( serialized_merchant_data ) . to_bytes ( ) } ;
let name_merchant_data : & str = str ::from_utf8 ( bytes_merchant_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_merchant_data : bidirectional ::InitMerchantData = serde_json ::from_str ( & name_merchant_data ) . unwrap ( ) ;
// Deserialize the merchant revoke token
let bytes_revoke_token = unsafe { CStr ::from_ptr ( serialized_revoke_token ) . to_bytes ( ) } ;
let name_revoke_token : & str = str ::from_utf8 ( bytes_revoke_token ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_revoke_token : bidirectional ::RevokeToken = serde_json ::from_str ( & name_revoke_token ) . unwrap ( ) ;
let new_wallet_sig = bidirectional ::pay_by_merchant_phase2 ( & deserialized_pp , & mut deserialized_channel_state , & deserialized_pay_proof , & mut deserialized_merchant_data , & deserialized_revoke_token ) ;
let ser = serde_json ::to_string ( & new_wallet_sig ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_pay_by_customer_final ( serialized_pp : * mut c_char , serialized_merchant_keypair : * mut c_char , serialized_customer_data : /* make mut */ * mut c_char , serialized_channel_token : * mut c_char , serialized_new_wallet : * mut c_char , serialized_new_wallet_sig : * mut c_char ) -> bool {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
// Deserialize the channel token
let bytes_channel_token = unsafe { CStr ::from_ptr ( serialized_channel_token ) . to_bytes ( ) } ;
let name_channel_token : & str = str ::from_utf8 ( bytes_channel_token ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_channel_token : bidirectional ::ChannelToken = serde_json ::from_str ( & name_channel_token ) . unwrap ( ) ;
// Deserialize the new wallet
let bytes_new_wallet = unsafe { CStr ::from_ptr ( serialized_new_wallet ) . to_bytes ( ) } ;
let name_new_wallet : & str = str ::from_utf8 ( bytes_new_wallet ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_new_wallet : bidirectional ::CustomerWallet = serde_json ::from_str ( & name_new_wallet ) . unwrap ( ) ;
// Deserialize the new wallet sig
let bytes_new_wallet_sig = unsafe { CStr ::from_ptr ( serialized_new_wallet_sig ) . to_bytes ( ) } ;
let name_new_wallet_sig : & str = str ::from_utf8 ( bytes_new_wallet_sig ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_new_wallet_sig : clsigs ::SignatureD = serde_json ::from_str ( & name_new_wallet_sig ) . unwrap ( ) ;
bidirectional ::pay_by_customer_final ( & deserialized_pp , & deserialized_merchant_keypair . pk , & mut deserialized_customer_data , deserialized_channel_token , deserialized_new_wallet , deserialized_new_wallet_sig ) ;
true
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_customer_refund ( serialized_pp : * mut c_char , serialized_channel : * mut c_char , serialized_merchant_keypair : * mut c_char , serialized_wallet : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
// Deserialize the merchant keypair
let bytes_kp = unsafe { CStr ::from_ptr ( serialized_merchant_keypair ) . to_bytes ( ) } ;
let name_kp : & str = str ::from_utf8 ( bytes_kp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_keypair : clsigs ::KeyPairD = serde_json ::from_str ( & name_kp ) . unwrap ( ) ;
// Deserialize the new wallet
let bytes_wallet = unsafe { CStr ::from_ptr ( serialized_wallet ) . to_bytes ( ) } ;
let name_wallet : & str = str ::from_utf8 ( bytes_wallet ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_wallet : bidirectional ::CustomerWallet = serde_json ::from_str ( & name_wallet ) . unwrap ( ) ;
let rc_c = bidirectional ::customer_refund ( & deserialized_pp , & deserialized_channel_state , & deserialized_merchant_keypair . pk , & deserialized_wallet ) ;
let ser = serde_json ::to_string ( & rc_c ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_merchant_refund ( serialized_pp : * mut c_char , serialized_channel : * mut c_char , serialized_channel_token : * mut c_char , serialized_merchant_data : * mut c_char , serialized_channel_closure : * mut c_char , serialized_revoke_token : * mut c_char ) -> * mut c_char {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the channel state
let bytes_channel = unsafe { CStr ::from_ptr ( serialized_channel ) . to_bytes ( ) } ;
let name_channel : & str = str ::from_utf8 ( bytes_channel ) . unwrap ( ) ; // make sure the bytes are UTF-8
let mut deserialized_channel_state : bidirectional ::ChannelState = serde_json ::from_str ( & name_channel ) . unwrap ( ) ;
// Deserialize the channel token
let bytes_channel_token = unsafe { CStr ::from_ptr ( serialized_channel_token ) . to_bytes ( ) } ;
let name_channel_token : & str = str ::from_utf8 ( bytes_channel_token ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_channel_token : bidirectional ::ChannelToken = serde_json ::from_str ( & name_channel_token ) . unwrap ( ) ;
// Deserialize the merchant data
let bytes_merchant_data = unsafe { CStr ::from_ptr ( serialized_merchant_data ) . to_bytes ( ) } ;
let name_merchant_data : & str = str ::from_utf8 ( bytes_merchant_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_data : bidirectional ::InitMerchantData = serde_json ::from_str ( & name_merchant_data ) . unwrap ( ) ;
// Deserialize the closure
let bytes_channel_closure = unsafe { CStr ::from_ptr ( serialized_channel_closure ) . to_bytes ( ) } ;
let name_channel_closure : & str = str ::from_utf8 ( bytes_channel_closure ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_channel_closure : bidirectional ::ChannelclosureC = serde_json ::from_str ( & name_channel_closure ) . unwrap ( ) ;
// Deserialize the revoke_token
let bytes_revoke_token = unsafe { CStr ::from_ptr ( serialized_revoke_token ) . to_bytes ( ) } ;
let name_revoke_token : & str = str ::from_utf8 ( bytes_revoke_token ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_revoke_token : secp256k1 ::Signature = serde_json ::from_str ( & name_revoke_token ) . unwrap ( ) ;
let rc_m = bidirectional ::merchant_refute ( & deserialized_pp , & mut deserialized_channel_state , & deserialized_channel_token , & deserialized_merchant_data , & deserialized_channel_closure , & deserialized_revoke_token ) ;
let ser = serde_json ::to_string ( & rc_m ) . unwrap ( ) ;
let cser = CString ::new ( ser ) . unwrap ( ) ;
cser . into_raw ( )
}
#[ no_mangle ]
pub extern fn ffishim_bidirectional_resolve ( serialized_pp : * mut c_char , serialized_customer_data : * mut c_char , serialized_merchant_data : * mut c_char , serialized_closure_customer : * mut c_char , serialized_closure_merchant : * mut c_char , serialized_revoke_token : * mut c_char ) -> i32 {
// Deserialize the pp
let bytes_pp = unsafe { CStr ::from_ptr ( serialized_pp ) . to_bytes ( ) } ;
let name_pp : & str = str ::from_utf8 ( bytes_pp ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_pp : bidirectional ::PublicParams = serde_json ::from_str ( & name_pp ) . unwrap ( ) ;
// Deserialize the custdata
let bytes_customer_data = unsafe { CStr ::from_ptr ( serialized_customer_data ) . to_bytes ( ) } ;
let name_customer_data : & str = str ::from_utf8 ( bytes_customer_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_customer_data : bidirectional ::InitCustomerData = serde_json ::from_str ( & name_customer_data ) . unwrap ( ) ;
// Deserialize the merchant data
let bytes_merchant_data = unsafe { CStr ::from_ptr ( serialized_merchant_data ) . to_bytes ( ) } ;
let name_merchant_data : & str = str ::from_utf8 ( bytes_merchant_data ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_merchant_data : bidirectional ::InitMerchantData = serde_json ::from_str ( & name_merchant_data ) . unwrap ( ) ;
//TODO handle none()
// Deserialize the client closure
let bytes_closure_customer = unsafe { CStr ::from_ptr ( serialized_closure_customer ) . to_bytes ( ) } ;
let name_closure_customer : & str = str ::from_utf8 ( bytes_closure_customer ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_closure_customer : bidirectional ::ChannelclosureC = serde_json ::from_str ( & name_closure_customer ) . unwrap ( ) ;
// Deserialize the merchant closure
let bytes_closure_merchant = unsafe { CStr ::from_ptr ( serialized_closure_merchant ) . to_bytes ( ) } ;
let name_closure_merchant : & str = str ::from_utf8 ( bytes_closure_merchant ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_closure_merchant : bidirectional ::ChannelclosureM = serde_json ::from_str ( & name_closure_merchant ) . unwrap ( ) ;
// Deserialize the revoke_token
let bytes_revoke_token = unsafe { CStr ::from_ptr ( serialized_revoke_token ) . to_bytes ( ) } ;
let name_revoke_token : & str = str ::from_utf8 ( bytes_revoke_token ) . unwrap ( ) ; // make sure the bytes are UTF-8
let deserialized_revoke_token : clsigs ::SignatureD = serde_json ::from_str ( & name_revoke_token ) . unwrap ( ) ;
// TODO multiple returns
let ( new_b0_cust , new_b0_merch ) = bidirectional ::resolve ( & deserialized_pp , & deserialized_customer_data , & deserialized_merchant_data , Some ( deserialized_closure_customer ) , Some ( deserialized_closure_merchant ) , Some ( deserialized_revoke_token ) ) ;
new_b0_cust
}
2019-02-19 09:01:51 -08:00
}
2018-07-24 18:42:07 -07:00
#[ cfg(all(test, feature = " unstable " )) ]
mod benches {
use rand ::{ Rng , thread_rng } ;
use test ::{ Bencher , black_box } ;
#[ bench ]
pub fn bench_one ( bh : & mut Bencher ) {
2018-07-24 21:56:41 -07:00
println! ( " Run benchmark tests here! " ) ;
2018-07-24 18:42:07 -07:00
}
}
2018-07-25 19:19:03 -07:00
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ test ]
2018-08-14 10:00:44 -07:00
#[ ignore ]
2018-07-25 19:19:03 -07:00
fn unidirectional_payment_basics_work ( ) {
// TODO: finish me
2018-08-14 10:00:44 -07:00
assert! ( true ) ;
2018-07-25 19:19:03 -07:00
}
fn setup_new_channel_helper ( pp : & bidirectional ::PublicParams , channel : & mut bidirectional ::ChannelState ,
init_cust_bal : i32 , init_merch_bal : i32 )
-> ( clsigs ::KeyPairD , bidirectional ::InitMerchantData ,
clsigs ::KeyPairD , bidirectional ::InitCustomerData ) {
let b0_cust = init_cust_bal ;
let b0_merch = init_merch_bal ;
// generate long-lived keypair for merchant -- used to identify
2018-08-24 00:31:46 -07:00
// merchant to all customers
2018-07-25 19:19:03 -07:00
let merch_keys = bidirectional ::keygen ( & pp ) ;
2018-08-15 00:47:02 -07:00
// customer generates an ephemeral keypair for use on a single channel
2018-07-25 19:19:03 -07:00
let cust_keys = bidirectional ::keygen ( & pp ) ;
// 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 merch_data = bidirectional ::init_merchant ( & pp , b0_merch , & merch_keys ) ;
// retrieve commitment setup params (using merchant long lived pk params)
let cm_csp = bidirectional ::generate_commit_setup ( & pp , & merch_keys . pk ) ;
// initialize on the customer side with balance: b0_cust
2019-02-13 06:39:22 -08:00
let cust_data = bidirectional ::init_customer ( & pp , channel ,
2018-07-25 19:19:03 -07:00
b0_cust , b0_merch ,
& cm_csp , & cust_keys ) ;
return ( merch_keys , merch_data , cust_keys , cust_data ) ;
}
2018-07-30 00:06:06 -07:00
fn setup_new_channel_existing_merchant_helper ( pp : & bidirectional ::PublicParams , channel : & mut bidirectional ::ChannelState ,
init_cust_bal : i32 , init_merch_bal : i32 , merch_keys : & clsigs ::KeyPairD )
-> ( bidirectional ::InitMerchantData , clsigs ::KeyPairD , bidirectional ::InitCustomerData ) {
let b0_cust = init_cust_bal ;
let b0_merch = init_merch_bal ;
2018-08-15 00:47:02 -07:00
// customer generates an ephemeral keypair for use on a single channel
2018-07-30 00:06:06 -07:00
let cust_keys = bidirectional ::keygen ( & pp ) ;
// 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 merch_data = bidirectional ::init_merchant ( & pp , b0_merch , & merch_keys ) ;
// retrieve commitment setup params (using merchant long lived pk params)
let cm_csp = bidirectional ::generate_commit_setup ( & pp , & merch_keys . pk ) ;
// initialize on the customer side with balance: b0_cust
2019-02-13 06:39:22 -08:00
let cust_data = bidirectional ::init_customer ( & pp , channel ,
2018-07-30 00:06:06 -07:00
b0_cust , b0_merch ,
& cm_csp , & cust_keys ) ;
return ( merch_data , cust_keys , cust_data ) ;
}
fn execute_establish_protocol_helper ( pp : & bidirectional ::PublicParams , channel : & mut bidirectional ::ChannelState ,
merch_keys : & clsigs ::KeyPairD , merch_data : & mut bidirectional ::InitMerchantData ,
cust_keys : & clsigs ::KeyPairD , cust_data : & mut bidirectional ::InitCustomerData ) {
// entering the establish protocol for the channel
2018-08-15 07:28:46 -07:00
let proof = bidirectional ::establish_customer_phase1 ( & pp , & cust_data , & merch_data . bases ) ;
2018-07-30 00:06:06 -07:00
// obtain the wallet signature from the merchant
let wallet_sig = bidirectional ::establish_merchant_phase2 ( & pp , channel , & merch_data , & proof ) ;
// complete channel establishment
assert! ( bidirectional ::establish_customer_final ( & pp , & merch_keys . pk , & mut cust_data . csk , wallet_sig ) ) ;
}
2018-07-25 19:19:03 -07:00
// pp, channel, merch_keys, merch_data, cust_keys, cust_data, pay_increment
fn execute_pay_protocol_helper ( pp : & bidirectional ::PublicParams , channel : & mut bidirectional ::ChannelState ,
merch_keys : & clsigs ::KeyPairD , merch_data : & mut bidirectional ::InitMerchantData ,
cust_keys : & clsigs ::KeyPairD , cust_data : & mut bidirectional ::InitCustomerData ,
payment_increment : i32 ) {
// let's test the pay protocol
2018-08-16 15:05:01 -07:00
bidirectional ::pay_by_customer_phase1_precompute ( & pp , & cust_data . channel_token , & merch_keys . pk , & mut cust_data . csk ) ;
2018-07-25 19:59:47 -07:00
2018-08-16 15:05:01 -07:00
let ( t_c , new_wallet , pay_proof ) = bidirectional ::pay_by_customer_phase1 ( & pp , & channel , & cust_data . channel_token , // channel token
2018-07-25 19:19:03 -07:00
& merch_keys . pk , // merchant pub key
& cust_data . csk , // wallet
payment_increment ) ; // balance increment (FUNC INPUT)
// get the refund token (rt_w)
let rt_w = bidirectional ::pay_by_merchant_phase1 ( & pp , channel , & pay_proof , & merch_data ) ;
// get the revocation token (rv_w) on the old public key (wpk)
let rv_w = bidirectional ::pay_by_customer_phase2 ( & pp , & cust_data . csk , & new_wallet , & merch_keys . pk , & rt_w ) ;
// get the new wallet sig (new_wallet_sig) on the new wallet
let new_wallet_sig = bidirectional ::pay_by_merchant_phase2 ( & pp , channel , & pay_proof , merch_data , & rv_w ) ;
assert! ( bidirectional ::pay_by_customer_final ( & pp , & merch_keys . pk , cust_data , t_c , new_wallet , new_wallet_sig ) ) ;
}
#[ test ]
fn bidirectional_payment_basics_work ( ) {
2018-07-29 17:44:08 -07:00
let pp = bidirectional ::setup ( true ) ;
2018-07-25 19:19:03 -07:00
2018-07-30 00:06:06 -07:00
// just bidirectional case (w/o third party)
let mut channel = bidirectional ::ChannelState ::new ( String ::from ( " Channel A -> B " ) , false ) ;
2018-07-25 19:19:03 -07:00
let total_owed = 40 ;
let b0_customer = 90 ;
let b0_merchant = 20 ;
let payment_increment = 20 ;
//let msg = "Open Channel ID: ";
//libbolt::debug_elem_in_hex(msg, &channel.cid);
let ( merch_keys , mut merch_data , cust_keys , mut cust_data ) = setup_new_channel_helper ( & pp , & mut channel , b0_customer , b0_merchant ) ;
2018-07-30 00:06:06 -07:00
// run establish protocol for customer and merchant channel
execute_establish_protocol_helper ( & pp , & mut channel , & merch_keys , & mut merch_data , & cust_keys , & mut cust_data ) ;
2018-07-25 19:19:03 -07:00
assert! ( channel . channel_established ) ;
{
// make multiple payments in a loop
let num_payments = total_owed / payment_increment ;
for i in 0 .. num_payments {
execute_pay_protocol_helper ( & pp , & mut channel , & merch_keys , & mut merch_data , & cust_keys , & mut cust_data , payment_increment ) ;
}
{
// scope localizes the immutable borrow here (for debug purposes only)
let cust_wallet = & cust_data . csk ;
let merch_wallet = & merch_data . csk ;
println! ( " Customer balance: {} " , cust_wallet . balance ) ;
println! ( " Merchant balance: {} " , merch_wallet . balance ) ;
assert! ( cust_wallet . balance = = ( b0_customer - total_owed ) & & merch_wallet . balance = = total_owed + b0_merchant ) ;
}
let cust_wallet = & cust_data . csk ;
// get channel closure message
let rc_c = bidirectional ::customer_refund ( & pp , & channel , & merch_keys . pk , & cust_wallet ) ;
println! ( " Obtained the channel closure message: {} " , rc_c . message . msgtype ) ;
}
2018-07-30 00:06:06 -07:00
}
#[ test ]
fn bidirectional_payment_negative_payment_works ( ) {
let pp = bidirectional ::setup ( true ) ;
// just bidirectional case (w/o third party)
2018-08-24 00:31:46 -07:00
let mut channel = bidirectional ::ChannelState ::new ( String ::from ( " Channel A <-> B " ) , false ) ;
2018-07-30 00:06:06 -07:00
let total_owed = - 20 ;
let b0_customer = 90 ;
let b0_merchant = 30 ;
let payment_increment = - 20 ;
//let msg = "Open Channel ID: ";
//libbolt::debug_elem_in_hex(msg, &channel.cid);
let ( merch_keys , mut merch_data , cust_keys , mut cust_data ) = setup_new_channel_helper ( & pp , & mut channel , b0_customer , b0_merchant ) ;
// run establish protocol for customer and merchant channel
execute_establish_protocol_helper ( & pp , & mut channel , & merch_keys , & mut merch_data , & cust_keys , & mut cust_data ) ;
println! ( " Initial Customer balance: {} " , cust_data . csk . balance ) ;
println! ( " Initial Merchant balance: {} " , merch_data . csk . balance ) ;
assert! ( channel . channel_established ) ;
{
// make multiple payments in a loop
execute_pay_protocol_helper ( & pp , & mut channel , & merch_keys , & mut merch_data , & cust_keys , & mut cust_data , payment_increment ) ;
{
// scope localizes the immutable borrow here (for debug purposes only)
let cust_wallet = & cust_data . csk ;
let merch_wallet = & merch_data . csk ;
println! ( " Customer balance: {} " , cust_wallet . balance ) ;
println! ( " Merchant balance: {} " , merch_wallet . balance ) ;
assert! ( cust_wallet . balance = = ( b0_customer - total_owed ) & & merch_wallet . balance = = total_owed + b0_merchant ) ;
}
}
}
fn execute_third_party_pay_protocol_helper ( pp : & bidirectional ::PublicParams ,
channel1 : & mut bidirectional ::ChannelState , channel2 : & mut bidirectional ::ChannelState ,
merch_keys : & clsigs ::KeyPairD , merch1_data : & mut bidirectional ::InitMerchantData ,
merch2_data : & mut bidirectional ::InitMerchantData ,
cust1_keys : & clsigs ::KeyPairD , cust1_data : & mut bidirectional ::InitCustomerData ,
cust2_keys : & clsigs ::KeyPairD , cust2_data : & mut bidirectional ::InitCustomerData ,
payment_increment : i32 ) {
// let's test the pay protocol
2018-08-16 15:05:01 -07:00
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 ) ;
2018-07-30 00:06:06 -07:00
2018-08-13 15:16:02 -07:00
println! ( " Channel 1 fee: {} " , channel1 . get_channel_fee ( ) ) ;
let ( t_c1 , new_wallet1 , pay_proof1 ) = bidirectional ::pay_by_customer_phase1 ( & pp , & channel1 ,
2018-08-16 15:05:01 -07:00
& cust1_data . channel_token , // channel token
2018-07-30 00:06:06 -07:00
& merch_keys . pk , // merchant pub key
& cust1_data . csk , // wallet
2018-08-13 15:16:02 -07:00
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 ,
2018-08-16 15:05:01 -07:00
& cust2_data . channel_token , // channel token
2018-07-30 00:06:06 -07:00
& merch_keys . pk , // merchant pub key
& cust2_data . csk , // wallet
2018-08-13 15:16:02 -07:00
- 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 ) ) ;
2018-07-25 19:19:03 -07:00
2018-07-30 00:06:06 -07:00
// 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 , new_wallet_sig1 ) ) ;
assert! ( bidirectional ::pay_by_customer_final ( & pp , & merch_keys . pk , cust2_data , t_c2 , new_wallet2 , new_wallet_sig2 ) ) ;
2018-07-25 19:19:03 -07:00
}
#[ test ]
fn third_party_payment_basics_work ( ) {
2018-07-30 00:06:06 -07:00
let pp = bidirectional ::setup ( true ) ;
// third party -- so indicate so in the channel state
2018-08-24 00:31:46 -07:00
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 ) ;
2018-07-30 00:06:06 -07:00
2018-08-13 15:16:02 -07:00
let fee = 2 ;
2018-08-16 23:00:02 -07:00
channel_a . set_channel_fee ( fee ) ;
2018-08-13 15:16:02 -07:00
2018-07-30 00:06:06 -07:00
let total_payment = 20 ;
2018-08-13 15:16:02 -07:00
let b0_alice = 30 ;
let b0_bob = 30 ;
2018-08-16 23:00:02 -07:00
let b0_merchant_a = 40 ;
let b0_merchant_b = 40 ;
2018-07-30 00:06:06 -07:00
2018-08-16 23:00:02 -07:00
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 ) ;
2018-07-30 00:06:06 -07:00
2018-08-16 23:00:02 -07:00
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 ) ;
2018-07-30 00:06:06 -07:00
// run establish protocol for alice and merchant channel
2018-08-16 23:00:02 -07:00
execute_establish_protocol_helper ( & pp , & mut channel_a , & merch_keys , & mut merch_data_a , & alice_keys , & mut alice_data ) ;
2018-07-30 00:06:06 -07:00
// run establish protocol for bob and merchant channel
2018-08-16 23:00:02 -07:00
execute_establish_protocol_helper ( & pp , & mut channel_b , & merch_keys , & mut merch_data_b , & bob_keys , & mut bob_data ) ;
2018-07-30 00:06:06 -07:00
2018-08-16 23:00:02 -07:00
assert! ( channel_a . channel_established ) ;
assert! ( channel_b . channel_established ) ;
2018-07-30 00:06:06 -07:00
// alice can pay bob through the merchant
2018-08-16 23:00:02 -07:00
execute_third_party_pay_protocol_helper ( & pp , & mut channel_a , & mut channel_b ,
& merch_keys , & mut merch_data_a , & mut merch_data_b ,
2018-07-30 00:06:06 -07:00
& alice_keys , & mut alice_data , & bob_keys , & mut bob_data , total_payment ) ;
println! ( " Customer alice balance: {} " , alice_data . csk . balance ) ;
2018-08-16 23:00:02 -07:00
println! ( " Merchant channel balance with alice: {} " , merch_data_a . csk . balance ) ;
2018-07-30 00:06:06 -07:00
println! ( " Customer bob balance: {} " , bob_data . csk . balance ) ;
2018-08-16 23:00:02 -07:00
println! ( " Merchant channel balance with bob: {} " , merch_data_b . csk . balance ) ;
2018-07-25 19:19:03 -07:00
}
2018-08-10 00:01:50 -07:00
}