Extend bolt interface with beginnings of wtp logic for on-chain tx

validation
This commit is contained in:
J. Ayo Akinyele 2019-08-22 20:52:18 -04:00
parent 68ed3a0711
commit 523121fcdc
6 changed files with 228 additions and 129 deletions

View File

@ -54,50 +54,68 @@ fn main() {
let b0_customer = 150;
let b0_merchant = 10;
let pay_inc = 20;
let pay_inc2 = 10;
let (mut channel_token, mut merch_wallet) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
// initialize the balance for merch_wallet
merch_wallet.init_balance(b0_merchant);
let (mut channel_token, mut merch_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
// initialize the balance for merch_state
merch_state.init_balance(b0_merchant);
let mut cust_wallet = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice");
let mut cust_state = bidirectional::init_customer(rng, &mut channel_state, &mut channel_token, b0_customer, b0_merchant, "Alice");
println!("{}", cust_wallet);
println!("{}", cust_state);
// lets establish the channel
let (com, com_proof, est_time) = measure_two_arg!(bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_wallet));
let (com, com_proof, est_time) = measure_two_arg!(bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state));
println!(">> Time to generate proof for establish: {} ms", est_time);
// obtain close token for closing out channel
let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_wallet);
let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_state);
let close_token= match option {
Ok(n) => n.unwrap(),
Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e)
};
assert!(cust_wallet.verify_close_token(&channel_state, &close_token));
assert!(cust_state.verify_close_token(&channel_state, &close_token));
// wait for funding tx to be confirmed, etc
// obtain payment token for pay protocol
let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_wallet);
//assert!(cust_wallet.verify_pay_token(&channel_state, &pay_token));
let pay_token = bidirectional::establish_merchant_issue_pay_token(rng, &channel_state, &com, &merch_state);
//assert!(cust_state.verify_pay_token(&channel_state, &pay_token));
assert!(bidirectional::establish_customer_final(&mut channel_state, &mut cust_wallet, &pay_token));
assert!(bidirectional::establish_customer_final(&mut channel_state, &mut cust_state, &pay_token));
println!("Channel established!");
let (payment, new_cust_wallet, pay_time) = measure_two_arg!(bidirectional::generate_payment_proof(rng, &channel_state, &cust_wallet, pay_inc));
let (payment, new_cust_state, pay_time) = measure_two_arg!(bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, pay_inc));
println!(">> Time to generate payment proof: {} ms", pay_time);
let (new_close_token, verify_time) = measure_one_arg!(bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_wallet));
let (new_close_token, verify_time) = measure_one_arg!(bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_state));
println!(">> Time to verify payment proof: {} ms", verify_time);
let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_wallet, new_cust_wallet, &new_close_token);
let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state, &new_close_token);
// send revoke token and get pay-token in response
let new_pay_token = bidirectional::verify_revoke_token(&revoke_token, &mut merch_wallet);
let new_pay_token = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state);
// verify the pay token and update internal state
assert!(cust_wallet.verify_pay_token(&channel_state, &new_pay_token));
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token));
println!("******************************************");
let (payment2, new_cust_state2, pay_time2) = measure_two_arg!(bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, pay_inc2));
println!(">> Time to generate payment proof 2: {} ms", pay_time2);
let (new_close_token2, verify_time2) = measure_one_arg!(bidirectional::verify_payment_proof(rng, &channel_state, &payment2, &mut merch_state));
println!(">> Time to verify payment proof 2: {} ms", verify_time2);
let revoke_token2 = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state2, &new_close_token2);
// send revoke token and get pay-token in response
let new_pay_token2 = bidirectional::verify_revoke_token(&revoke_token2, &mut merch_state);
// verify the pay token and update internal state
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token2));
println!("Final Cust state: {}", cust_state);
}

View File

@ -58,12 +58,22 @@ class Libbolt(object):
self.lib.ffishim_bidirectional_pay_verify_payment_token.argtypes = (c_void_p, c_void_p)
self.lib.ffishim_bidirectional_pay_verify_payment_token.restype = c_void_p
# CLOSE
self.lib.ffishim_bidirectional_customer_close.argtypes = (c_void_p, c_void_p)
self.lib.ffishim_bidirectional_customer_close.restype = c_void_p
self.lib.ffishim_bidirectional_merchant_close.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p)
self.lib.ffishim_bidirectional_merchant_close.restype = c_void_p
# ON-CHAIN BOLT LOGIC / WTPs
self.lib.ffishim_bidirectional_verify_open_channel.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p)
self.lib.ffishim_bidirectional_verify_open_channel.restype = c_void_p
#self.lib.ffishim_bidirectional_verify_close_channel.argtypes = (c_void_p, c_void_p)
#self.lib.ffishim_bidirectional_verify_close_channel.restype = c_void_p
# self.lib.ffishim_bidirectional_resolve.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p)
# self.lib.ffishim_bidirectional_resolve.restype = c_void_p
@ -115,7 +125,7 @@ class Libbolt(object):
# PAY PROTOCOL
# generate payment proof
# generate payment proof and new cust state
def bidirectional_pay_generate_payment_proof(self, channel_state, cust_state, amount):
output_string = self.lib.ffishim_bidirectional_pay_generate_payment_proof(channel_state.encode(), cust_state.encode(), amount)
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
@ -140,6 +150,12 @@ class Libbolt(object):
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
return (output_dictionary['pay_token'], output_dictionary['merch_state'])
# verify payment token
def bidirectional_pay_verify_payment_token(self, channel_state, cust_state, pay_token):
output_string = self.lib.ffishim_bidirectional_pay_verify_payment_token(channel_state.encode(), cust_state.encode(), pay_token.encode())
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
return (output_dictionary['cust_state'], output_dictionary['is_pay_valid'])
# CLOSE
def bidirectional_customer_close(self, channel_state, cust_state):
@ -153,7 +169,21 @@ class Libbolt(object):
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
return (output_dictionary.get('wpk'), output_dictionary.get('revoke_token'), output_dictionary.get('error'))
#
# WTP logic
def wtp_get_wallet(self, cust_state):
cust_state_dict = self.interperate_json_string_as_dictionary(cust_state)
return json.dumps(cust_state_dict.get("wpk")), json.dumps(cust_state_dict.get("wallet"))
def wtp_get_close_token(self, cust_close):
cust_close_dict = self.interperate_json_string_as_dictionary(cust_close)
return json.dumps(cust_close_dict.get("signature"))
def wtp_verify_open_channel(self, channel_token, wpk, cust_close_wallet, close_token):
output_string = self.lib.ffishim_bidirectional_verify_open_channel(channel_token.encode(), wpk.encode(), cust_close_wallet.encode(), close_token.encode())
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
return output_dictionary.get('result')
# def bidirectional_resolve(self, pp, cust_data, merch_data, cust_closure, merch_closure):
# output_string = self.lib.ffishim_bidirectional_resolve( pp.encode(), cust_data.encode(), merch_data.encode(), cust_closure.encode(), merch_closure.encode())
# output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
@ -196,62 +226,104 @@ DEBUG = 'debug'
RELEASE = 'release'
mode = RELEASE # debug or release
libbolt = Libbolt('target/{}/{}bolt.{}'.format(mode, prefix, ext))
def run_unit_test():
libbolt = Libbolt('target/{}/{}bolt.{}'.format(mode, prefix, ext))
b0_cust = 100
b0_merch = 10
b0_cust = 100
b0_merch = 10
channel_state = libbolt.channel_setup("My New Channel A")
channel_state = libbolt.channel_setup("My New Channel A")
print("channel state new: ", channel_state)
print("channel state new: ", len(channel_state))
(channel_token, merch_state) = libbolt.bidirectional_init_merchant(channel_state, b0_merch, "Bob")
(channel_token, merch_state) = libbolt.bidirectional_init_merchant(channel_state, b0_merch, "Bob")
print("merch_state: ", len(merch_state))
#print("channel_token: ", type(_channel_token))
print("merch_state: ", len(merch_state))
#print("channel_token: ", type(_channel_token))
(channel_token, cust_state) = libbolt.bidirectional_init_customer(channel_state, channel_token, b0_cust, b0_merch, "Alice")
print("cust_state: ", len(cust_state))
(channel_token, cust_state) = libbolt.bidirectional_init_customer(channel_state, channel_token, b0_cust, b0_merch, "Alice")
print("cust_state: ", len(cust_state))
(channel_token, cust_state, com, com_proof) = libbolt.bidirectional_establish_customer_generate_proof(channel_token, cust_state)
print("com: ", com)
(channel_token, cust_state, com, com_proof) = libbolt.bidirectional_establish_customer_generate_proof(channel_token, cust_state)
print("com: ", com)
close_token = libbolt.bidirectional_establish_merchant_issue_close_token(channel_state, com, com_proof, merch_state)
print("close token: ", close_token)
close_token = libbolt.bidirectional_establish_merchant_issue_close_token(channel_state, com, com_proof, merch_state)
print("close token: ", close_token)
(is_token_valid, channel_state, cust_state) = libbolt.bidirectional_establish_customer_verify_close_token(channel_state, cust_state, close_token)
(is_token_valid, channel_state, cust_state) = libbolt.bidirectional_establish_customer_verify_close_token(channel_state, cust_state, close_token)
pay_token = libbolt.bidirectional_establish_merchant_issue_pay_token(channel_state, com, merch_state)
print("pay token: ", pay_token)
pay_token = libbolt.bidirectional_establish_merchant_issue_pay_token(channel_state, com, merch_state)
print("pay token: ", pay_token)
(is_channel_established, channel_state, cust_state) = libbolt.bidirectional_establish_customer_final(channel_state, cust_state, pay_token)
if is_channel_established:
print("updated cust_state: ", cust_state)
else:
print("channel still not established. did you verify close token?")
(is_channel_established, channel_state, cust_state) = libbolt.bidirectional_establish_customer_final(channel_state, cust_state, pay_token)
if is_channel_established:
print("updated cust_state: ", cust_state)
else:
print("channel still not established. did you verify close token?")
# Pay protocol
print("Pay protocol...")
# Pay protocol
print("Pay protocol...")
amount = 5
(payment_proof, new_cust_state) = libbolt.bidirectional_pay_generate_payment_proof(channel_state, cust_state, amount)
print("Pay proof: ", len(payment_proof))
print("new cust wallet: ", new_cust_state)
print("<========================================>")
# make a payment
amount = 5
(payment_proof, new_cust_state) = libbolt.bidirectional_pay_generate_payment_proof(channel_state, cust_state, amount)
print("Pay proof: ", len(payment_proof))
print("new cust wallet: ", new_cust_state)
print("<========================================>")
revoked_wpk, _ = libbolt.wtp_get_wallet(new_cust_state)
(new_close_token, merch_state) = libbolt.bidirectional_pay_verify_payment_proof(channel_state, payment_proof, merch_state)
print("Close token: ", new_close_token)
print("<========================================>")
(new_close_token, merch_state) = libbolt.bidirectional_pay_verify_payment_proof(channel_state, payment_proof, merch_state)
print("Close token: ", new_close_token)
print("<========================================>")
(revoke_token, cust_state) = libbolt.bidirectional_pay_generate_revoke_token(channel_state, cust_state, new_cust_state, new_close_token)
print("Revoke token: ", revoke_token)
(revoke_token, cust_state) = libbolt.bidirectional_pay_generate_revoke_token(channel_state, cust_state, new_cust_state, new_close_token)
print("Revoke token: ", revoke_token)
(pay_token, merch_state) = libbolt.bidirectional_pay_verify_revoke_token(revoke_token, merch_state)
print("Pay token: ", pay_token)
(pay_token, merch_state) = libbolt.bidirectional_pay_verify_revoke_token(revoke_token, merch_state)
print("Pay token: ", pay_token)
cust_close = libbolt.bidirectional_customer_close(channel_state, cust_state)
print("Cust close msg: ", cust_close)
print("<========================================>")
(cust_state, is_pay_valid) = libbolt.bidirectional_pay_verify_payment_token(channel_state, cust_state, pay_token)
print("Pay token is valid: ", is_pay_valid)
merch_close_tokens = libbolt.bidirectional_merchant_close(channel_state, channel_token, cust_close, merch_state)
print("Merch close tokens: ", merch_close_tokens)
# make a payment
amount = 10
(payment_proof2, new_cust_state2) = libbolt.bidirectional_pay_generate_payment_proof(channel_state, cust_state, amount)
print("Pay proof 2: ", len(payment_proof2))
print("new cust wallet 2: ", new_cust_state2)
print("<========================================>")
(new_close_token2, merch_state) = libbolt.bidirectional_pay_verify_payment_proof(channel_state, payment_proof2, merch_state)
print("Close token 2: ", new_close_token2)
print("<========================================>")
(revoke_token2, cust_state) = libbolt.bidirectional_pay_generate_revoke_token(channel_state, cust_state, new_cust_state2, new_close_token2)
print("Revoke token 2: ", revoke_token)
(pay_token2, merch_state) = libbolt.bidirectional_pay_verify_revoke_token(revoke_token2, merch_state)
print("Pay token 2: ", pay_token2)
(cust_state, is_pay_valid) = libbolt.bidirectional_pay_verify_payment_token(channel_state, cust_state, pay_token2)
print("Pay token is valid: ", is_pay_valid)
print("<========================================>")
print("<========================================>")
cust_close = libbolt.bidirectional_customer_close(channel_state, cust_state)
print("Cust close msg: ", cust_close)
print("<========================================>")
merch_close_tokens = libbolt.bidirectional_merchant_close(channel_state, channel_token, cust_close, merch_state)
print("Merch close tokens: ", merch_close_tokens)
print("<========================================>")
wpk, cust_close_wallet = libbolt.wtp_get_wallet(cust_state)
print("wpk = ", wpk)
print("close-msg wallet = ", cust_close_wallet)
cust_close_token = libbolt.wtp_get_close_token(cust_close)
print("close token: ", cust_close_token)
print("Valid channel opening: ", libbolt.wtp_verify_open_channel(channel_token, wpk, cust_close_wallet, cust_close_token))
print("Invalid channel opening: ", libbolt.wtp_verify_open_channel(channel_token, revoked_wpk, cust_close_wallet, cust_close_token))
if __name__ == "__main__":
run_unit_test()

View File

@ -103,8 +103,9 @@ pub struct ChannelState<E: Engine> {
))]
pub struct ChannelToken<E: Engine> {
pub pk_c: Option<secp256k1::PublicKey>, // pk_c
pub blind_pk_m: cl::BlindPublicKey<E>, // PK_m
pub pk_m: secp256k1::PublicKey, // pk_m
pub cl_pk_m: cl::PublicKey<E>, // PK_m
pub mpk: cl::PublicParams<E>, // mpk for PK_m
pub comParams: CSMultiParams<E>,
}
@ -243,7 +244,7 @@ impl<E: Engine> CustomerState<E> {
let mut ct_db= HashMap::new();
let mut pt_db= HashMap::new();
println!("Customer wallet formed -> now returning the structure to the caller.");
//println!("Customer wallet formed -> now returning the structure to the caller.");
return CustomerState {
name: name,
pk_c: pk_c,
@ -256,7 +257,7 @@ impl<E: Engine> CustomerState<E> {
t: t,
w_com: w_com,
wallet: wallet,
index: 1,
index: 0,
close_tokens: ct_db,
pay_tokens: pt_db
}
@ -267,7 +268,7 @@ impl<E: Engine> CustomerState<E> {
}
pub fn get_close_token(&self) -> cl::Signature<E> {
let index = self.index - 1;
let index = self.index;
let close_token = self.close_tokens.get(&index).unwrap();
// rerandomize first
return close_token.clone();
@ -288,19 +289,19 @@ impl<E: Engine> CustomerState<E> {
let is_close_valid = cp.pub_params.keypair.verify(&mpk, &close_wallet, &self.t, &close_token);
if is_close_valid {
println!("verify_close_token - Blinded close token is valid!!");
//println!("verify_close_token - Blinded close token is valid!!");
let pk = cp.pub_params.keypair.get_public_key(&mpk);
let unblind_close_token = cp.pub_params.keypair.unblind(&self.t, &close_token);
let is_valid = pk.verify(&mpk, &close_wallet, &unblind_close_token);
if is_valid {
// record the unblinded close token
//cp.pub_params.keypair
self.close_tokens.insert( self.index - 1, unblind_close_token);
self.close_tokens.insert( self.index, unblind_close_token);
}
return is_valid;
}
println!("Customer - Verification failed for close token!");
//println!("Customer - Verification failed for close token!");
return false;
}
@ -314,22 +315,22 @@ impl<E: Engine> CustomerState<E> {
let is_pay_valid = cp.pub_params.keypair.verify(&mpk, &wallet, &self.t, &pay_token);
if is_pay_valid {
println!("verify_pay_token - Blinded pay token is valid!!");
//println!("verify_pay_token - Blinded pay token is valid!!");
let unblind_pay_token = cp.pub_params.keypair.unblind(&self.t, &pay_token);
let pk = cp.pub_params.keypair.get_public_key(&mpk);
let is_valid = pk.verify(&mpk, &wallet, &unblind_pay_token);
if is_valid {
self.pay_tokens.insert(self.index - 1, unblind_pay_token);
self.pay_tokens.insert(self.index, unblind_pay_token);
}
return is_valid;
}
println!("Customer - Verification failed for pay token!");
//println!("Customer - Verification failed for pay token!");
return false;
}
pub fn has_tokens(&self) -> bool {
let index = self.index - 1;
let index = self.index;
let is_ct = self.close_tokens.get(&index).is_some();
let is_pt = self.pay_tokens.get(&index).is_some();
return is_ct && is_pt;
@ -356,8 +357,9 @@ impl<E: Engine> CustomerState<E> {
let new_wcom = cp.pub_params.comParams.commit(&new_wallet.as_fr_vec(), &new_t);
// 3 - generate new blinded and randomized pay token
let i = self.index - 1;
let i = self.index;
let mut prev_pay_token = self.pay_tokens.get(&i).unwrap();
//println!("Found prev pay token: {}", prev_pay_token);
let pay_proof = cp.pub_params.prove(csprng, self.t.clone(), old_wallet, new_wallet.clone(),
new_wcom.clone(), new_t, &prev_pay_token);
@ -375,7 +377,7 @@ impl<E: Engine> CustomerState<E> {
t: new_t,
w_com: new_wcom.clone(),
wallet: new_wallet.clone(),
index: self.index + 1, // increment index here
index: self.index, // increment index here
close_tokens: self.close_tokens.clone(),
pay_tokens: self.pay_tokens.clone()
};
@ -474,10 +476,15 @@ impl<E: Engine> MerchantState<E> {
}
pub fn init<R: Rng>(&mut self, csprng: &mut R, channel: &mut ChannelState<E>) -> ChannelToken<E> {
let cp = channel.cp.as_ref().unwrap(); // if not set, then panic!
let mpk = cp.pub_params.mpk.clone();
let cl_pk = cp.pub_params.keypair.get_public_key(&mpk);
return ChannelToken {
pk_c: None,
blind_pk_m: self.keypair.public.clone(),
cl_pk_m: cl_pk.clone(), // extract the regular public key
pk_m: self.pk.clone(),
mpk: mpk,
comParams: self.comParams.clone()
}
}
@ -488,7 +495,7 @@ impl<E: Engine> MerchantState<E> {
}
pub fn issue_close_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, extend_close: bool) -> Signature<E> {
println!("issue_close_token => generating token");
//println!("issue_close_token => generating token");
let x = hash_to_fr::<E>(String::from("close").into_bytes() );
let close_com = match extend_close {
true => self.comParams.extend_commit(com, &x),
@ -499,7 +506,7 @@ impl<E: Engine> MerchantState<E> {
}
pub fn issue_pay_token<R: Rng>(&self, csprng: &mut R, cp: &ChannelParams<E>, com: &Commitment<E>, remove_close: bool) -> Signature<E> {
println!("issue_pay_token => generating token");
//println!("issue_pay_token => generating token");
let x = hash_to_fr::<E>(String::from("close").into_bytes() );
let pay_com = match remove_close {
true => self.comParams.remove_commit(com, &x),
@ -513,7 +520,7 @@ impl<E: Engine> MerchantState<E> {
let is_valid = nizk::verify_opening(&self.comParams, &com.c, &com_proof);
let cp = channel.cp.as_ref().unwrap();
if is_valid {
println!("Commitment PoK is valid!");
// println!("Commitment PoK is valid!");
let close_token = self.issue_close_token(csprng, cp, com, true);
let pay_token = self.issue_pay_token(csprng, cp, com, false);
return Ok((close_token, pay_token));

View File

@ -133,23 +133,6 @@ pub struct KeyPair<E: Engine> {
pub public: PublicKey<E>,
}
//#[derive(Clone, Serialize, Deserialize)]
//#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
//<E as pairing::Engine>::G1: serde::Serialize, \
//<E as pairing::Engine>::G2: serde::Serialize"
//))]
//#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
//<E as pairing::Engine>::G1: serde::Deserialize<'de>, \
//<E as pairing::Engine>::G2: serde::Deserialize<'de>"
//))]
//pub struct TestStruct<E: Engine> {
// pub mpk: PublicParams<E>,
// pub keypair: BlindKeyPair<E>,
// pub comParams: CSMultiParams<E>,
// pub rpParamsBC: ccs08::RPPublicParams<E>,
// pub rpParamsBM: ccs08::RPPublicParams<E>
//}
#[derive(Clone, Serialize, Deserialize)]
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
<E as pairing::Engine>::G1: serde::Serialize, \

View File

@ -223,11 +223,11 @@ pub mod ffishim {
let mut rng = &mut rand::thread_rng();
// Deserialize the channel state
let channel_state: bidirectional::ChannelState<Bls12> = deserialize_object(ser_channel_state);
// Deserialize the cust wallet
let cust_state: bidirectional::CustomerState<Bls12> = deserialize_object(ser_customer_wallet);
// Generate the payment proof
let (payment, new_cust_state) = bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, amount);
// Serialize the results and return to caller
let ser = ["{\'payment\':\'", serde_json::to_string(&payment).unwrap().as_str(),
"\', \'cust_state\':\'", serde_json::to_string(&new_cust_state).unwrap().as_str() ,"\'}"].concat();
let cser = CString::new(ser).unwrap();
@ -349,6 +349,26 @@ pub mod ffishim {
cser.into_raw()
}
#[no_mangle]
pub extern fn ffishim_bidirectional_verify_open_channel(ser_channel_token: *mut c_char,
ser_wpk: *mut c_char,
ser_close_msg: *mut c_char,
ser_close_token: *mut c_char) -> *mut c_char {
// Deserialize the channel token
let channel_token: bidirectional::ChannelToken<Bls12> = deserialize_object(ser_channel_token);
// Deserialize the wpk
let wpk: secp256k1::PublicKey = deserialize_object(ser_wpk);
// Deserialize the close wallet
let close_msg: bidirectional::Wallet<Bls12> = deserialize_object(ser_close_msg);
// Deserialize the close token
let close_token: bidirectional::Signature<Bls12> = deserialize_object(ser_close_token);
// check the signatures
let token_valid = bidirectional::verify_open_channel(&channel_token, &wpk, &close_msg, &close_token);
let ser = ["{\'result\':\'", serde_json::to_string(&token_valid).unwrap().as_str(), "\'}"].concat();
let cser = CString::new(ser).unwrap();
cser.into_raw()
}
}
// #[no_mangle]

View File

@ -133,6 +133,8 @@ pub mod bidirectional {
pub use BoltResult;
pub use channels::{ChannelState, ChannelToken, CustomerState, MerchantState, PubKeyMap, ChannelParams, BoltError, ResultBoltSig};
pub use nizk::{CommitmentProof, Proof};
pub use wallet::Wallet;
pub use cl::PublicParams;
#[derive(Clone, Serialize, Deserialize)]
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
@ -175,13 +177,13 @@ pub mod bidirectional {
///
/// init_merchant - takes as input the public params, merchant balance and keypair.
/// Generates merchant data which consists of channel token and merchant wallet.
/// Generates merchant data which consists of channel token and merchant state.
///
pub fn init_merchant<'a, R: Rng, E: Engine>(csprng: &mut R, channel_state: &mut ChannelState<E>, name: &'a str) -> (ChannelToken<E>, MerchantState<E>) {
// create new merchant wallet
// create new merchant state
let merch_name = String::from(name);
let mut merch_state = MerchantState::<E>::new(csprng, channel_state, merch_name);
// initialize the merchant wallet
// initialize the merchant state
let mut channel_token = merch_state.init(csprng, channel_state);
return (channel_token, merch_state);
@ -203,7 +205,7 @@ pub mod bidirectional {
}
///
/// establish_customer_generate_proof (Phase 1) - takes as input the public params, customer wallet and
/// establish_customer_generate_proof (Phase 1) - takes as input the public params, customer state and
/// common public bases from merchant. Generates a PoK of the committed values in the
/// new wallet.
///
@ -239,8 +241,8 @@ pub mod bidirectional {
}
///
/// establish_customer_final - takes as input the channel state, customer wallet,
/// customer wallet and pay token (blinded sig) obtained from merchant. Add the returned
/// establish_customer_final - takes as input the channel state, customer state,
/// and pay token (blinded sig) obtained from merchant. Add the returned
/// blinded signature to the wallet.
///
pub fn establish_customer_final<E: Engine>(channel_state: &mut ChannelState<E>, cust_state: &mut CustomerState<E>, pay_token: &cl::Signature<E>) -> bool {
@ -352,7 +354,7 @@ pub mod bidirectional {
///
/// verify_revoke_token (phase 2) - takes as input revoke message and signature,
/// merchant wallet, from the customer. If the revocation token is valid,
/// merchant state, 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).
///
pub fn verify_revoke_token<E: Engine>(rt: &RevokeToken, merch_state: &mut MerchantState<E>) -> cl::Signature<E> {
@ -366,7 +368,7 @@ pub mod bidirectional {
// for customer => on input a wallet w, it outputs a customer channel closure message
///
/// customer_close - takes as input the channel state, merchant's verification
/// key, and customer wallet. Generates a channel closure message for customer.
/// key, and customer state. Generates a channel closure message for customer.
///
pub fn customer_close<E: Engine>(channel_state: &ChannelState<E>, cust_state: &CustomerState<E>) -> ChannelcloseC<E> {
if !channel_state.channel_established {
@ -384,30 +386,6 @@ pub mod bidirectional {
ChannelcloseC { wpk: cust_state.wpk, message: wallet, signature: close_token }
}
// fn exist_in_merchant_state<E: Engine>(db: &HashMap<String, PubKeyMap>, wpk: &secp256k1::PublicKey, rev: Option<secp256k1::Signature>) -> (bool, Option<PubKeyMap>) {
// if db.is_empty() {
// return (false, None);
// }
//
// let fingerprint = util::compute_pub_key_fingerprint(wpk);
// if db.contains_key(&fingerprint) {
// let revoked_state = db.get(&fingerprint).unwrap();
//
//
//
// if revoked_state.revoke_token.is_none() {
// // let's just check the public key
// return (revoked_state.wpk == *wpk, None);
// }
// if !rev.is_none() {
// return (revoked_state.wpk == *wpk && pub_key.revoke_token.unwrap() == rev.unwrap(), None);
// }
// return (pub_key.wpk == *wpk, Some(pub_key));
// }
//
// return false;
// }
fn update_merchant_state(db: &mut HashMap<String, PubKeyMap>, wpk: &secp256k1::PublicKey, rev: Option<secp256k1::Signature>) {
let fingerprint = util::compute_pub_key_fingerprint(wpk);
//println!("Print fingerprint: {}", fingerprint);
@ -434,12 +412,12 @@ pub mod bidirectional {
}
let cp = channel_state.cp.as_ref().unwrap();
let pk = cp.pub_params.keypair.get_public_key(&cp.pub_params.mpk);
let pk = cp.pub_params.keypair.get_public_key(&channel_token.mpk);
let mut wallet = cust_close.message.clone();
let close_wallet = wallet.with_close(String::from("close")).clone();
let close_token = cust_close.signature.clone();
let is_valid = pk.verify(&cp.pub_params.mpk, &close_wallet, &close_token);
let is_valid = pk.verify(&channel_token.mpk, &close_wallet, &close_token);
if is_valid {
let wpk = cust_close.wpk;
@ -464,6 +442,27 @@ pub mod bidirectional {
}
Err(String::from("merchant_close - Customer close message not valid!"))
}
///
/// WTP for validating that a close_token was well-formed
///
pub fn verify_open_channel<E: Engine>(channel_token: &ChannelToken<E>, wpk: &secp256k1::PublicKey, close_msg: &wallet::Wallet<E>, close_token: &Signature<E>) -> bool {
// close_msg => <pkc> || <wpk> || <balance-cust> || <balance-merch> || CLOSE
// close_token = regular CL signature on close_msg
// channel_token => <pk_c, CL_PK_m, pk_m, mpk, comParams>
// (1) check that channel token and close msg are consistent (e.g., close_msg.pk_c == H(channel_token.pk_c) &&
let pk_c = channel_token.pk_c.unwrap();
let chan_token_pk_c = util::hash_pubkey_to_fr::<E>(&pk_c);
let chan_token_wpk = util::hash_pubkey_to_fr::<E>(&wpk);
let pkc_thesame = (close_msg.pkc == chan_token_pk_c);
// (2) check that wpk matches what's in the close msg
let wpk_thesame = (close_msg.wpk == chan_token_wpk);
return pkc_thesame && wpk_thesame && channel_token.cl_pk_m.verify(&channel_token.mpk, &close_msg.as_fr_vec(), &close_token);
}
}
#[cfg(all(test, feature = "unstable"))]