Add better error handling for verify_revoke_token() and more tests
This commit is contained in:
parent
a526184a74
commit
7d92625c14
|
@ -9,6 +9,7 @@ extern crate secp256k1;
|
|||
use bolt::bidirectional;
|
||||
use std::time::Instant;
|
||||
use pairing::bls12_381::{Bls12};
|
||||
use bolt::handle_bolt_result;
|
||||
|
||||
macro_rules! measure_one_arg {
|
||||
($x: expr) => {
|
||||
|
@ -96,10 +97,11 @@ fn main() {
|
|||
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_state);
|
||||
let new_pay_token_result = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state);
|
||||
let new_pay_token = handle_bolt_result!(new_pay_token_result);
|
||||
|
||||
// verify the pay token and update internal state
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token));
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token.unwrap()));
|
||||
|
||||
println!("******************************************");
|
||||
|
||||
|
@ -112,10 +114,11 @@ fn main() {
|
|||
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);
|
||||
let new_pay_token_result2 = bidirectional::verify_revoke_token(&revoke_token2, &mut merch_state);
|
||||
let new_pay_token2 = handle_bolt_result!(new_pay_token_result2);
|
||||
|
||||
// verify the pay token and update internal state
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token2));
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token2.unwrap()));
|
||||
|
||||
println!("Final Cust state: {}", cust_state);
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ class Libbolt(object):
|
|||
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'))
|
||||
return output_dictionary['payment'], output_dictionary['cust_state']
|
||||
return output_dictionary.get('payment'), output_dictionary.get('cust_state')
|
||||
|
||||
# verify payment proof
|
||||
def bidirectional_pay_verify_payment_proof(self, channel_state, pay_proof, merch_state):
|
||||
|
@ -141,20 +141,20 @@ class Libbolt(object):
|
|||
output_string = self.lib.ffishim_bidirectional_pay_generate_revoke_token(channel_state.encode(), cust_state.encode(),
|
||||
new_cust_state.encode(), close_token.encode())
|
||||
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
|
||||
return output_dictionary['revoke_token'], output_dictionary['cust_state']
|
||||
return output_dictionary.get('revoke_token'), output_dictionary.get('cust_state')
|
||||
|
||||
# verify revoke token
|
||||
def bidirectional_pay_verify_revoke_token(self, revoke_token, merch_state):
|
||||
output_string = self.lib.ffishim_bidirectional_pay_verify_revoke_token(revoke_token.encode(), merch_state.encode())
|
||||
output_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'])
|
||||
return (output_dictionary.get('pay_token'), output_dictionary.get('merch_state'))
|
||||
|
||||
# verify payment token
|
||||
def bidirectional_pay_verify_payment_token(self, channel_state, cust_state, pay_token):
|
||||
output_string = self.lib.ffishim_bidirectional_pay_verify_payment_token(channel_state.encode(), cust_state.encode(), pay_token.encode())
|
||||
output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8'))
|
||||
is_pay_valid = self._convert_boolean(output_dictionary.get('is_pay_valid'))
|
||||
return (output_dictionary['cust_state'], is_pay_valid)
|
||||
return (output_dictionary.get('cust_state'), is_pay_valid)
|
||||
|
||||
# CLOSE
|
||||
|
||||
|
|
68
py/tests.py
68
py/tests.py
|
@ -11,7 +11,10 @@ def malformed_token(token):
|
|||
token_dict = ast.literal_eval(token)
|
||||
updated_token = {}
|
||||
for k,v in token_dict.items():
|
||||
updated_token[k] = v[:-4] + rand_hex(4)
|
||||
if type(v) == str:
|
||||
updated_token[k] = v[:-4] + rand_hex(4)
|
||||
else:
|
||||
updated_token[k] = v
|
||||
return json.dumps(updated_token)
|
||||
|
||||
def malformed_proof(proof):
|
||||
|
@ -181,20 +184,71 @@ class BoltPayTests(unittest.TestCase):
|
|||
(self.cust_state, is_pay_valid) = self.bolt.bidirectional_pay_verify_payment_token(self.channel_state, self.cust_state, pay_token)
|
||||
self.assertTrue(is_pay_valid)
|
||||
|
||||
def test_pay_protocol_bad_payment_proof_fails(self):
|
||||
amount = 10
|
||||
def test_pay_protocol_bad_payment_proof_fail_handled(self):
|
||||
"""
|
||||
Payment protocol fails as expected when customer sends a bad payment proof
|
||||
:return:
|
||||
"""
|
||||
amount = 15
|
||||
(payment_proof, new_cust_state) = self.bolt.bidirectional_pay_generate_payment_proof(self.channel_state, self.cust_state, amount)
|
||||
|
||||
bad_payment_proof = malformed_proof(payment_proof)
|
||||
(new_close_token, self.merch_state) = self.bolt.bidirectional_pay_verify_payment_proof(self.channel_state, bad_payment_proof, self.merch_state)
|
||||
self.assertTrue(new_close_token is None)
|
||||
|
||||
def test_pay_protocol_bad_revoke_token_fails(self):
|
||||
pass
|
||||
def test_pay_protocol_bad_close_token_fail_handled(self):
|
||||
"""
|
||||
Payment protocol fails as expected when merchant returns a malformed/bad close token
|
||||
:return:
|
||||
"""
|
||||
amount = 10
|
||||
(payment_proof, new_cust_state) = self.bolt.bidirectional_pay_generate_payment_proof(self.channel_state, self.cust_state, amount)
|
||||
|
||||
def test_pay_protocol_bad_payment_token_fails(self):
|
||||
pass
|
||||
(new_close_token, self.merch_state) = self.bolt.bidirectional_pay_verify_payment_proof(self.channel_state, payment_proof, self.merch_state)
|
||||
bad_close_token = malformed_token(new_close_token)
|
||||
|
||||
(revoke_token, self.cust_state) = self.bolt.bidirectional_pay_generate_revoke_token(self.channel_state, self.cust_state, new_cust_state, bad_close_token)
|
||||
self.assertTrue(revoke_token is None)
|
||||
|
||||
def test_pay_protocol_bad_revoke_token_fail_handled(self):
|
||||
"""
|
||||
Payment protocol fails as expected when customer sends a bad revoke token
|
||||
:return:
|
||||
"""
|
||||
amount = 20
|
||||
(payment_proof, new_cust_state) = self.bolt.bidirectional_pay_generate_payment_proof(self.channel_state, self.cust_state, amount)
|
||||
|
||||
(new_close_token, self.merch_state) = self.bolt.bidirectional_pay_verify_payment_proof(self.channel_state, payment_proof, self.merch_state)
|
||||
|
||||
(revoke_token, self.cust_state) = self.bolt.bidirectional_pay_generate_revoke_token(self.channel_state, self.cust_state, new_cust_state, new_close_token)
|
||||
|
||||
bad_revoke_token = malformed_token(revoke_token)
|
||||
(pay_token, merch_state) = self.bolt.bidirectional_pay_verify_revoke_token(bad_revoke_token, self.merch_state)
|
||||
self.assertTrue(pay_token is None)
|
||||
|
||||
def test_pay_protocol_bad_payment_token_fail_handled(self):
|
||||
"""
|
||||
Payment protocol fails as expected when merchant returns a malformed pay token
|
||||
:return:
|
||||
"""
|
||||
amount = 25
|
||||
(payment_proof, new_cust_state) = self.bolt.bidirectional_pay_generate_payment_proof(self.channel_state, self.cust_state, amount)
|
||||
|
||||
(new_close_token, self.merch_state) = self.bolt.bidirectional_pay_verify_payment_proof(self.channel_state, payment_proof, self.merch_state)
|
||||
|
||||
(revoke_token, self.cust_state) = self.bolt.bidirectional_pay_generate_revoke_token(self.channel_state, self.cust_state, new_cust_state, new_close_token)
|
||||
|
||||
(pay_token, self.merch_state) = self.bolt.bidirectional_pay_verify_revoke_token(revoke_token, self.merch_state)
|
||||
bad_pay_token = malformed_token(pay_token)
|
||||
|
||||
(cust_state, is_pay_valid) = self.bolt.bidirectional_pay_verify_payment_token(self.channel_state, self.cust_state, bad_pay_token)
|
||||
self.assertTrue(is_pay_valid is None)
|
||||
|
||||
class BoltMultiChannelTests(unittest.TestCase):
|
||||
pass
|
||||
|
||||
class BoltIntermediaryTests(unittest.TestCase):
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
|
|
@ -343,8 +343,10 @@ pub mod ffishim {
|
|||
let mut merch_state = handle_errors!(merch_state_result);
|
||||
|
||||
// send revoke token and get pay-token in response
|
||||
let pay_token = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state);
|
||||
let ser = ["{\'pay_token\':\'", serde_json::to_string(&pay_token).unwrap().as_str(),
|
||||
let pay_token_result = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state);
|
||||
let pay_token = handle_errors!(pay_token_result);
|
||||
|
||||
let ser = ["{\'pay_token\':\'", serde_json::to_string(&pay_token.unwrap()).unwrap().as_str(),
|
||||
"\', \'merch_state\':\'", serde_json::to_string(&merch_state).unwrap().as_str() ,"\'}"].concat();
|
||||
let cser = CString::new(ser).unwrap();
|
||||
cser.into_raw()
|
||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -106,6 +106,14 @@ impl<'a> fmt::UpperHex for HexSlice<'a> {
|
|||
|
||||
pub type BoltResult<T> = Result<Option<T>, String>;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! handle_bolt_result {
|
||||
($e:expr) => (match $e {
|
||||
Ok(val) => val,
|
||||
Err(_) => None,
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////// Utilities //////////////////////////////////
|
||||
|
||||
/////////////////////////////// Bidirectional ////////////////////////////////
|
||||
|
@ -358,10 +366,14 @@ pub mod bidirectional {
|
|||
/// 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> {
|
||||
let new_pay_token = merch_state.verify_revoke_token(&rt.signature, &rt.message, &rt.message.wpk).unwrap();
|
||||
pub fn verify_revoke_token<E: Engine>(rt: &RevokeToken, merch_state: &mut MerchantState<E>) -> BoltResult<cl::Signature<E>> {
|
||||
let pay_token_result = merch_state.verify_revoke_token(&rt.signature, &rt.message, &rt.message.wpk);
|
||||
let new_pay_token = match pay_token_result {
|
||||
Ok(n) => n,
|
||||
Err(err) => return Err(String::from(err.to_string()))
|
||||
};
|
||||
update_merchant_state(&mut merch_state.keys, &rt.message.wpk, Some(rt.signature.clone()));
|
||||
return new_pay_token;
|
||||
Ok(Some(new_pay_token))
|
||||
}
|
||||
|
||||
///// end of pay protocol
|
||||
|
@ -445,10 +457,6 @@ pub mod bidirectional {
|
|||
Err(String::from("merchant_close - Customer close message not valid!"))
|
||||
}
|
||||
|
||||
// pub fn wtp_sign_merch_close_message<E: Engine>(address: &Vec<u8>, revoke_token: &Option<secp256k1::Signature>, merch_state: &MerchantState<E>) -> ChannelcloseM {
|
||||
// return merch_state.sign_revoke_message(&address, &revoke_token);
|
||||
// }
|
||||
|
||||
///
|
||||
/// Used in open-channel WTP for validating that a close_token is a valid signature under <
|
||||
///
|
||||
|
@ -583,10 +591,11 @@ mod tests {
|
|||
let revoke_token = bidirectional::generate_revoke_token(&channel_state, 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, merch_state);
|
||||
let new_pay_token_result: BoltResult<cl::Signature<Bls12>> = bidirectional::verify_revoke_token(&revoke_token, merch_state);
|
||||
let new_pay_token = handle_bolt_result!(new_pay_token_result);
|
||||
|
||||
// verify the pay token and update internal state
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token));
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token.unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -638,10 +647,11 @@ mod tests {
|
|||
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_state);
|
||||
let new_pay_token_result: BoltResult<cl::Signature<Bls12>> = bidirectional::verify_revoke_token(&revoke_token, &mut merch_state);
|
||||
let new_pay_token = handle_bolt_result!(new_pay_token_result);
|
||||
|
||||
// verify the pay token and update internal state
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token));
|
||||
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token.unwrap()));
|
||||
|
||||
println!("Successful payment!");
|
||||
|
||||
|
|
Loading…
Reference in New Issue