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.
|
|
|
|
//!
|
2019-08-12 20:45:57 -07:00
|
|
|
//! Libbolt relies on BLS12-381 curves at 128-bit security, as implemented in a fork of
|
|
|
|
//! [`pairing module`](https://github.com/boltlabs-inc/pairing).
|
2018-06-24 22:06:36 -07:00
|
|
|
//!
|
2019-03-05 19:58:40 -08:00
|
|
|
#![allow(non_snake_case)]
|
2019-06-08 11:22:20 -07:00
|
|
|
#![allow(non_camel_case_types)]
|
|
|
|
#![allow(unused_parens)]
|
|
|
|
#![allow(non_upper_case_globals)]
|
|
|
|
#![allow(unused_results)]
|
|
|
|
#![allow(missing_docs)]
|
2019-07-27 12:09:03 -07:00
|
|
|
#![feature(exclusive_range_pattern)]
|
2018-06-24 22:06:36 -07:00
|
|
|
|
2018-07-24 18:42:07 -07:00
|
|
|
#![cfg_attr(all(test, feature = "unstable"), feature(test))]
|
2019-09-13 13:16:35 -07:00
|
|
|
#[cfg(all(test, feature = "unstable"))]
|
|
|
|
extern crate test;
|
2018-07-24 18:42:07 -07:00
|
|
|
|
2019-06-12 23:52:20 -07:00
|
|
|
extern crate ff;
|
|
|
|
extern crate pairing;
|
2018-02-24 23:46:52 -08:00
|
|
|
extern crate rand;
|
2018-07-21 21:22:21 -07:00
|
|
|
extern crate rand_core;
|
2019-06-12 23:52:20 -07:00
|
|
|
|
2018-02-24 23:46:52 -08:00
|
|
|
extern crate bincode;
|
|
|
|
extern crate sodiumoxide;
|
2018-06-08 18:20:15 -07:00
|
|
|
extern crate secp256k1;
|
2018-07-14 18:17:00 -07:00
|
|
|
extern crate time;
|
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;
|
|
|
|
|
2019-06-12 23:52:20 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
extern crate rand_xorshift;
|
2019-06-28 14:44:14 -07:00
|
|
|
extern crate core;
|
2019-02-19 09:01:51 -08:00
|
|
|
|
2019-09-27 10:02:31 -07:00
|
|
|
pub mod sym;
|
|
|
|
pub mod cl;
|
|
|
|
pub mod ccs08;
|
|
|
|
pub mod ped92;
|
|
|
|
pub mod channels;
|
|
|
|
pub mod nizk;
|
|
|
|
pub mod util;
|
|
|
|
pub mod wallet;
|
|
|
|
pub mod ffishim;
|
|
|
|
|
2018-02-24 23:46:52 -08:00
|
|
|
use std::fmt;
|
2018-03-24 06:44:45 -07:00
|
|
|
use std::str;
|
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;
|
2019-06-12 23:52:20 -07:00
|
|
|
use ff::{Rand, Field};
|
2018-02-24 00:12:58 -08:00
|
|
|
|
2019-02-19 09:01:51 -08:00
|
|
|
use serde::{Serialize, Deserialize};
|
2019-07-31 19:06:57 -07:00
|
|
|
use serde::de::{Deserializer, Unexpected, Error};
|
2019-02-19 09:01:51 -08:00
|
|
|
|
2019-08-12 20:45:57 -07:00
|
|
|
////////////////////////////////// Utilities //////////////////////////////////
|
2018-06-07 23:57:46 -07:00
|
|
|
|
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
|
|
|
|
2019-08-11 02:48:46 -07:00
|
|
|
pub type BoltResult<T> = Result<Option<T>, String>;
|
|
|
|
|
2019-09-05 19:45:47 -07:00
|
|
|
#[macro_export]
|
|
|
|
macro_rules! handle_bolt_result {
|
|
|
|
($e:expr) => (match $e {
|
|
|
|
Ok(val) => val,
|
|
|
|
Err(_) => None,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-06-24 22:06:36 -07:00
|
|
|
////////////////////////////////// Utilities //////////////////////////////////
|
|
|
|
|
|
|
|
/////////////////////////////// Bidirectional ////////////////////////////////
|
2018-05-10 14:08:42 -07:00
|
|
|
pub mod bidirectional {
|
2019-08-22 21:50:41 -07:00
|
|
|
use rand::Rng;
|
2019-07-28 22:18:40 -07:00
|
|
|
use util;
|
|
|
|
use wallet;
|
2019-08-22 21:50:41 -07:00
|
|
|
use pairing::Engine;
|
2018-06-18 20:19:53 -07:00
|
|
|
use sodiumoxide;
|
2019-09-13 13:16:35 -07:00
|
|
|
use cl;
|
|
|
|
// for blind signature
|
|
|
|
use secp256k1;
|
|
|
|
// for on-chain keys
|
2018-06-14 18:07:18 -07:00
|
|
|
use HashMap;
|
2019-02-13 06:30:18 -08:00
|
|
|
use sodiumoxide::crypto::hash::sha512;
|
2018-08-10 00:01:50 -07:00
|
|
|
use sha2::Sha512;
|
2019-07-28 22:18:40 -07:00
|
|
|
|
2019-02-19 09:01:51 -08:00
|
|
|
use serde::{Serialize, Deserialize};
|
2019-08-26 08:08:49 -07:00
|
|
|
use util::{RevokedMessage, hash_to_slice};
|
2019-07-31 19:06:57 -07:00
|
|
|
pub use ped92::Commitment;
|
|
|
|
pub use cl::{PublicKey, Signature};
|
2019-08-11 02:48:46 -07:00
|
|
|
pub use BoltResult;
|
2019-08-26 08:08:49 -07:00
|
|
|
pub use channels::{ChannelState, ChannelToken, CustomerState, MerchantState, ChannelcloseM,
|
2019-09-02 03:00:00 -07:00
|
|
|
PubKeyMap, ChannelParams, BoltError, ResultBoltType};
|
2019-08-27 13:58:30 -07:00
|
|
|
pub use nizk::NIZKProof;
|
2019-08-22 17:52:18 -07:00
|
|
|
pub use wallet::Wallet;
|
|
|
|
pub use cl::PublicParams;
|
2019-08-27 13:58:30 -07:00
|
|
|
pub use ped92::CommitmentProof;
|
2019-07-28 22:18:40 -07:00
|
|
|
|
2019-07-31 19:06:57 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
|
|
|
#[serde(bound(serialize = "<E as ff::ScalarEngine>::Fr: serde::Serialize, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Serialize"))]
|
|
|
|
#[serde(bound(deserialize = "<E as ff::ScalarEngine>::Fr: serde::Deserialize<'de>, \
|
|
|
|
<E as pairing::Engine>::G1: serde::Deserialize<'de>"))]
|
2019-07-30 14:25:27 -07:00
|
|
|
pub struct ChannelcloseC<E: Engine> {
|
2019-08-20 16:09:01 -07:00
|
|
|
pub wpk: secp256k1::PublicKey,
|
2019-07-28 22:18:40 -07:00
|
|
|
pub message: wallet::Wallet<E>,
|
2019-09-13 13:16:35 -07:00
|
|
|
pub signature: cl::Signature<E>,
|
2018-03-25 20:20:05 -07:00
|
|
|
}
|
|
|
|
|
2019-07-31 19:06:57 -07:00
|
|
|
#[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, \
|
|
|
|
<E as pairing::Engine>::Fqk: 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>,\
|
|
|
|
<E as pairing::Engine>::Fqk: serde::Deserialize<'de>"
|
|
|
|
))]
|
2019-07-28 22:18:40 -07:00
|
|
|
pub struct Payment<E: Engine> {
|
2019-08-27 13:58:30 -07:00
|
|
|
proof: NIZKProof<E>,
|
2019-07-28 22:18:40 -07:00
|
|
|
com: Commitment<E>,
|
2018-06-14 18:07:18 -07:00
|
|
|
wpk: secp256k1::PublicKey,
|
2019-09-27 10:02:31 -07:00
|
|
|
amount: i64,
|
2018-06-11 00:31:27 -07:00
|
|
|
}
|
|
|
|
|
2019-07-31 19:06:57 -07:00
|
|
|
#[derive(Clone, Serialize, Deserialize)]
|
2018-06-14 18:07:18 -07:00
|
|
|
pub struct RevokeToken {
|
2019-07-28 22:18:40 -07:00
|
|
|
message: util::RevokedMessage,
|
2019-09-13 13:16:35 -07:00
|
|
|
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
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
/// init_merchant - takes as input the public params, merchant balance and keypair.
|
2019-08-22 17:52:18 -07:00
|
|
|
/// Generates merchant data which consists of channel token and merchant state.
|
2018-08-24 00:18:36 -07:00
|
|
|
///
|
2019-09-10 19:21:09 -07:00
|
|
|
pub fn init_merchant<'a, R: Rng, E: Engine>(csprng: &mut R, channel_state: &mut ChannelState<E>, name: &'a str) -> (ChannelToken<E>, MerchantState<E>, ChannelState<E>) {
|
2019-08-22 17:52:18 -07:00
|
|
|
// create new merchant state
|
2019-07-28 22:18:40 -07:00
|
|
|
let merch_name = String::from(name);
|
2019-09-10 19:21:09 -07:00
|
|
|
let (mut merch_state, mut channel_state) = MerchantState::<E>::new(csprng, channel_state, merch_name);
|
2019-08-22 17:52:18 -07:00
|
|
|
// initialize the merchant state
|
2019-09-10 19:21:09 -07:00
|
|
|
let channel_token = merch_state.init(csprng, &mut channel_state);
|
2018-03-25 20:20:05 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
return (channel_token, merch_state, channel_state.clone());
|
2018-06-11 11:05:24 -07:00
|
|
|
}
|
|
|
|
|
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-09-16 08:58:10 -07:00
|
|
|
pub fn init_customer<'a, R: Rng, E: Engine>(csprng: &mut R, channel_token: &mut ChannelToken<E>,
|
2019-09-27 10:02:31 -07:00
|
|
|
b0_cust: i64, b0_merch: i64, name: &'a str) -> CustomerState<E> {
|
2019-07-28 22:18:40 -07:00
|
|
|
assert!(b0_cust >= 0);
|
|
|
|
assert!(b0_merch >= 0);
|
2018-03-25 20:20:05 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
let cust_name = String::from(name);
|
2019-09-16 08:58:10 -07:00
|
|
|
return CustomerState::<E>::new(csprng, channel_token, b0_cust, b0_merch, cust_name);
|
2018-03-25 20:20:05 -07:00
|
|
|
}
|
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-08-22 17:52:18 -07:00
|
|
|
/// establish_customer_generate_proof (Phase 1) - takes as input the public params, customer state and
|
2018-08-15 07:28:46 -07:00
|
|
|
/// common public bases from merchant. Generates a PoK of the committed values in the
|
|
|
|
/// new wallet.
|
|
|
|
///
|
2019-08-16 09:29:01 -07:00
|
|
|
pub fn establish_customer_generate_proof<R: Rng, E: Engine>(csprng: &mut R, channel_token: &ChannelToken<E>, cust_state: &CustomerState<E>) -> (Commitment<E>, CommitmentProof<E>) {
|
|
|
|
let cust_com_proof = cust_state.generate_proof(csprng, channel_token);
|
|
|
|
return (cust_state.w_com.clone(), cust_com_proof);
|
2018-04-08 00:46:17 -07:00
|
|
|
}
|
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-07-30 14:25:27 -07:00
|
|
|
/// establish_merchant_issue_close_token (Phase 1) - takes as input the channel state,
|
|
|
|
/// PoK of committed values from the customer. Generates close token (a blinded
|
|
|
|
/// signature) over the contents of the customer's wallet.
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
pub fn establish_merchant_issue_close_token<R: Rng, E: Engine>(csprng: &mut R, channel_state: &ChannelState<E>,
|
2019-08-27 06:56:02 -07:00
|
|
|
com: &Commitment<E>, com_proof: &CommitmentProof<E>,
|
2019-09-27 10:02:31 -07:00
|
|
|
pkc: &E::Fr, init_cust_balance: i64, init_merch_balance: i64,
|
2019-08-27 06:56:02 -07:00
|
|
|
merch_state: &MerchantState<E>) -> BoltResult<cl::Signature<E>> {
|
2019-07-30 14:25:27 -07:00
|
|
|
// verifies proof of committed values and derives blind signature on the committed values to the customer's initial wallet
|
2019-09-13 13:16:35 -07:00
|
|
|
match merch_state.verify_proof(csprng, channel_state, com, com_proof, pkc, init_cust_balance, init_merch_balance) {
|
2019-08-11 02:48:46 -07:00
|
|
|
Ok(n) => Ok(Some(n.0)), // just close token
|
|
|
|
Err(err) => Err(String::from(err.to_string()))
|
|
|
|
}
|
2019-07-28 22:18:40 -07:00
|
|
|
}
|
|
|
|
|
2019-07-30 14:25:27 -07:00
|
|
|
///
|
|
|
|
/// establish_merchant_issue_pay_token (Phase 1) - takes as input the channel state,
|
|
|
|
/// the commitment from the customer. Generates close token (a blinded
|
|
|
|
/// signature) over the contents of the customer's wallet.
|
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
pub fn establish_merchant_issue_pay_token<R: Rng, E: Engine>(csprng: &mut R, channel_state: &ChannelState<E>,
|
2019-09-13 13:16:35 -07:00
|
|
|
com: &Commitment<E>, merch_state: &MerchantState<E>) -> cl::Signature<E> {
|
2019-07-28 22:18:40 -07:00
|
|
|
let cp = channel_state.cp.as_ref().unwrap();
|
2019-08-16 09:29:01 -07:00
|
|
|
let pay_token = merch_state.issue_pay_token(csprng, cp, com, false);
|
2019-07-28 22:18:40 -07:00
|
|
|
return pay_token;
|
2018-06-09 00:14:50 -07:00
|
|
|
}
|
2018-03-25 20:20:05 -07:00
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-08-22 17:52:18 -07:00
|
|
|
/// establish_customer_final - takes as input the channel state, customer state,
|
|
|
|
/// and pay token (blinded sig) obtained from merchant. Add the returned
|
2018-08-15 07:28:46 -07:00
|
|
|
/// blinded signature to the wallet.
|
|
|
|
///
|
2019-08-16 09:29:01 -07:00
|
|
|
pub fn establish_customer_final<E: Engine>(channel_state: &mut ChannelState<E>, cust_state: &mut CustomerState<E>, pay_token: &cl::Signature<E>) -> bool {
|
2019-07-28 22:18:40 -07:00
|
|
|
// verify the pay-token first
|
2019-08-16 09:29:01 -07:00
|
|
|
if !cust_state.verify_pay_token(&channel_state, pay_token) {
|
2019-07-31 19:06:57 -07:00
|
|
|
println!("establish_customer_final - Failed to verify the pay-token");
|
2019-07-28 22:18:40 -07:00
|
|
|
return false;
|
2018-06-09 00:14:50 -07:00
|
|
|
}
|
2018-08-15 07:28:46 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// only if both tokens have been stored
|
2019-08-16 09:29:01 -07:00
|
|
|
if (cust_state.has_tokens()) {
|
2019-07-28 22:18:40 -07:00
|
|
|
// must be an old wallet
|
|
|
|
channel_state.channel_established = true;
|
|
|
|
}
|
|
|
|
return channel_state.channel_established;
|
2018-07-14 18:17:00 -07:00
|
|
|
}
|
2019-07-28 22:18:40 -07:00
|
|
|
///// end of establish channel protocol
|
2018-07-14 18:17:00 -07:00
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
|
|
|
|
///
|
2019-07-31 19:06:57 -07:00
|
|
|
/// generate_payment_proof (phase 1) - takes as input the public params, channel state, channel token,
|
2018-08-15 07:28:46 -07:00
|
|
|
/// 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.
|
|
|
|
///
|
2019-09-27 10:02:31 -07:00
|
|
|
pub fn generate_payment_proof<R: Rng, E: Engine>(csprng: &mut R, channel_state: &ChannelState<E>, cust_state: &CustomerState<E>, amount: i64) -> (Payment<E>, CustomerState<E>) {
|
2019-09-10 10:11:31 -07:00
|
|
|
let tx_fee = channel_state.get_channel_fee();
|
|
|
|
let payment_amount = match tx_fee > 0 {
|
|
|
|
true => amount + tx_fee,
|
|
|
|
false => amount
|
|
|
|
};
|
|
|
|
let (proof, com, wpk, new_cust_state) = cust_state.generate_payment(csprng, &channel_state, payment_amount);
|
2019-07-28 22:18:40 -07:00
|
|
|
let payment = Payment { proof, com, wpk, amount };
|
2019-08-16 09:29:01 -07:00
|
|
|
return (payment, new_cust_state);
|
2018-06-05 10:26:16 -07:00
|
|
|
}
|
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
/// verify_payment (phase 1) - takes as input the public params, channel state, payment proof
|
2018-08-15 07:28:46 -07:00
|
|
|
/// and merchant keys. If proof is valid, then merchant returns the refund token
|
|
|
|
/// (i.e., partially blind signature on IOU with updated balance)
|
|
|
|
///
|
2019-07-31 19:06:57 -07:00
|
|
|
pub fn verify_payment_proof<R: Rng, E: Engine>(csprng: &mut R, channel_state: &ChannelState<E>,
|
2019-09-13 13:16:35 -07:00
|
|
|
payment: &Payment<E>, merch_state: &mut MerchantState<E>) -> cl::Signature<E> {
|
2019-07-28 22:18:40 -07:00
|
|
|
// if payment proof verifies, then returns close-token and records wpk => pay-token
|
|
|
|
// if valid revoke_token is provided later for wpk, then release pay-token
|
2019-09-10 10:11:31 -07:00
|
|
|
let tx_fee = channel_state.get_channel_fee();
|
|
|
|
let payment_amount = match tx_fee > 0 {
|
|
|
|
true => payment.amount + tx_fee,
|
|
|
|
false => payment.amount
|
|
|
|
};
|
2019-08-16 09:29:01 -07:00
|
|
|
let new_close_token = merch_state.verify_payment(csprng, &channel_state,
|
2019-09-13 13:16:35 -07:00
|
|
|
&payment.proof, &payment.com, &payment.wpk, payment_amount).unwrap();
|
2019-08-20 16:09:01 -07:00
|
|
|
// store the wpk since it has been revealed
|
|
|
|
update_merchant_state(&mut merch_state.keys, &payment.wpk, None);
|
2019-07-28 22:18:40 -07:00
|
|
|
return new_close_token;
|
|
|
|
}
|
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
|
|
|
|
///
|
2019-09-27 10:02:31 -07:00
|
|
|
// pub fn verify_third_party_payment(pp: &PublicParams, fee: i64, proof1: &BalanceProof, proof2: &BalanceProof) -> bool {
|
2019-07-28 22:18:40 -07:00
|
|
|
// if proof1.third_party && proof2.third_party {
|
|
|
|
// let vcom1 = &proof1.proof_vcom.as_ref().unwrap();
|
|
|
|
// let vcom2 = &proof2.proof_vcom.as_ref().unwrap();
|
|
|
|
// let rproof1 = &proof1.proof_vrange.as_ref().unwrap();
|
|
|
|
// let rproof2 = &proof2.proof_vrange.as_ref().unwrap();
|
|
|
|
// let pc_gens1 = PedersenGens::default();
|
|
|
|
// let pc_gens2 = PedersenGens::default();
|
|
|
|
// let mut transcript1 = Transcript::new(b"Range Proof for Balance Increment");
|
|
|
|
// let range_proof1_valid = rproof1.range_proof.0.verify_single(&pp.bp_gens, &pc_gens1,
|
|
|
|
// &mut transcript1,
|
|
|
|
// &rproof1.range_proof.1,
|
|
|
|
// pp.range_proof_bits).is_ok();
|
|
|
|
//
|
|
|
|
// let mut transcript2 = Transcript::new(b"Range Proof for Balance Increment");
|
|
|
|
// let range_proof2_valid = rproof2.range_proof.0.verify_single(&pp.bp_gens, &pc_gens2,
|
|
|
|
// &mut transcript2,
|
|
|
|
// &rproof2.range_proof.1,
|
|
|
|
// pp.range_proof_bits).is_ok();
|
|
|
|
//
|
|
|
|
// let len = vcom1.pub_bases.len();
|
|
|
|
// assert!(len >= 2 && vcom1.pub_bases.len() == vcom2.pub_bases.len());
|
|
|
|
//
|
|
|
|
// // g^(e1 + -e2 + fee) * h^(r1 + r2) ==> should be equal to g^(fee) * h^(r1 + r2)
|
|
|
|
// // lets add commitments for vcom1 and vcom2 to check
|
|
|
|
// let added_commits = vcom1.C + vcom2.C;
|
|
|
|
// let tx_fee = vcom1.pub_bases[1] * -convert_int_to_fr(fee);
|
|
|
|
// // compute h^r1 + r2
|
|
|
|
// let h_r1_r2 = (vcom1.pub_bases[0] * proof1.vcom.unwrap().r) +
|
|
|
|
// (vcom2.pub_bases[0] * proof2.vcom.unwrap().r) + tx_fee;
|
|
|
|
//
|
|
|
|
// let is_pay_plus_fee = added_commits == h_r1_r2;
|
|
|
|
// return clproto::bs_verify_nizk_proof(&vcom1) &&
|
|
|
|
// clproto::bs_verify_nizk_proof(&vcom2) &&
|
|
|
|
// range_proof1_valid && range_proof2_valid &&
|
|
|
|
// is_pay_plus_fee;
|
|
|
|
// }
|
|
|
|
// panic!("verify_third_party_payment - third-party payment not enabled for both proofs");
|
|
|
|
// }
|
2018-08-13 15:16:02 -07:00
|
|
|
|
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
/// generate_revoke_token (phase 2) - takes as input the public params, old wallet, new wallet,
|
2018-08-15 07:28:46 -07:00
|
|
|
/// merchant's verification key and refund token. If the refund token is valid, generate
|
|
|
|
/// a revocation token for the old wallet public key.
|
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
pub fn generate_revoke_token<E: Engine>(channel_state: &ChannelState<E>,
|
2019-09-13 13:16:35 -07:00
|
|
|
old_cust_state: &mut CustomerState<E>,
|
|
|
|
new_cust_state: CustomerState<E>,
|
|
|
|
new_close_token: &cl::Signature<E>) -> RevokeToken {
|
2019-07-28 22:18:40 -07:00
|
|
|
// let's update the old wallet
|
2019-08-16 09:29:01 -07:00
|
|
|
assert!(old_cust_state.update(new_cust_state));
|
2019-07-31 19:31:10 -07:00
|
|
|
// generate the token after verifying that the close token is valid
|
2019-08-16 09:29:01 -07:00
|
|
|
let (message, signature) = old_cust_state.generate_revoke_token(channel_state, new_close_token).unwrap();
|
2019-07-31 19:31:10 -07:00
|
|
|
// return the revoke token (msg + sig pair)
|
2019-07-28 22:18:40 -07:00
|
|
|
return RevokeToken { message, signature };
|
2018-06-13 17:28:37 -07:00
|
|
|
}
|
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-07-28 22:18:40 -07:00
|
|
|
/// verify_revoke_token (phase 2) - takes as input revoke message and signature,
|
2019-08-22 17:52:18 -07:00
|
|
|
/// merchant state, from the customer. If the revocation token is valid,
|
2019-07-28 22:18:40 -07:00
|
|
|
/// generate a new signature for the new wallet (from the PoK of committed values in new wallet).
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-09-05 19:45:47 -07:00
|
|
|
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()))
|
|
|
|
};
|
2019-08-16 09:29:01 -07:00
|
|
|
update_merchant_state(&mut merch_state.keys, &rt.message.wpk, Some(rt.signature.clone()));
|
2019-09-05 19:45:47 -07:00
|
|
|
Ok(Some(new_pay_token))
|
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
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// for customer => on input a wallet w, it outputs a customer channel closure message
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-08-12 10:30:42 -07:00
|
|
|
/// customer_close - takes as input the channel state, merchant's verification
|
2019-08-22 17:52:18 -07:00
|
|
|
/// key, and customer state. Generates a channel closure message for customer.
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-08-16 09:29:01 -07:00
|
|
|
pub fn customer_close<E: Engine>(channel_state: &ChannelState<E>, cust_state: &CustomerState<E>) -> ChannelcloseC<E> {
|
2019-07-30 14:25:27 -07:00
|
|
|
if !channel_state.channel_established {
|
|
|
|
panic!("Cannot close a channel that has not been established!");
|
|
|
|
}
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
let mut wallet = cust_state.get_wallet();
|
2019-08-16 09:29:01 -07:00
|
|
|
let close_token = cust_state.get_close_token();
|
2019-07-31 19:06:57 -07:00
|
|
|
|
|
|
|
let cp = channel_state.cp.as_ref().unwrap();
|
2019-09-10 19:21:09 -07:00
|
|
|
let pk = cp.pub_params.pk.get_pub_key();
|
2019-07-31 19:06:57 -07:00
|
|
|
let close_wallet = wallet.with_close(String::from("close"));
|
|
|
|
|
|
|
|
assert!(pk.verify(&cp.pub_params.mpk, &close_wallet, &close_token));
|
2019-08-20 16:09:01 -07:00
|
|
|
ChannelcloseC { wpk: cust_state.wpk, message: wallet, signature: close_token }
|
2018-06-09 23:00:01 -07:00
|
|
|
}
|
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
fn update_merchant_state(db: &mut HashMap<String, PubKeyMap>, wpk: &secp256k1::PublicKey, rev: Option<secp256k1::Signature>) {
|
|
|
|
let fingerprint = util::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()) };
|
2019-07-28 22:18:40 -07:00
|
|
|
db.insert(fingerprint, cust_pub_key);
|
2018-06-14 18:07:18 -07:00
|
|
|
} else {
|
|
|
|
let cust_pub_key = PubKeyMap { wpk: wpk.clone(), revoke_token: None };
|
2019-07-28 22:18:40 -07:00
|
|
|
db.insert(fingerprint, cust_pub_key);
|
2018-06-14 18:07:18 -07:00
|
|
|
}
|
2018-06-09 23:00:01 -07:00
|
|
|
}
|
|
|
|
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-08-20 16:09:01 -07:00
|
|
|
/// merchant_close - takes as input the channel state, channel token, customer close msg/sig,
|
|
|
|
/// Returns tokens for merchant close transaction (only if customer close message is found to be a
|
|
|
|
/// double spend). If not, then None is returned.
|
2018-08-15 07:28:46 -07:00
|
|
|
///
|
2019-08-20 16:09:01 -07:00
|
|
|
pub fn merchant_close<E: Engine>(channel_state: &ChannelState<E>,
|
|
|
|
channel_token: &ChannelToken<E>,
|
|
|
|
cust_close: &ChannelcloseC<E>,
|
|
|
|
merch_state: &MerchantState<E>) -> BoltResult<PubKeyMap> {
|
|
|
|
if (!channel_state.channel_established) {
|
|
|
|
return Err(String::from("merchant_close - Channel not established! Cannot generate channel closure message."));
|
|
|
|
}
|
|
|
|
|
|
|
|
let cp = channel_state.cp.as_ref().unwrap();
|
2019-09-10 19:21:09 -07:00
|
|
|
let pk = cp.pub_params.pk.get_pub_key();
|
2019-08-20 16:09:01 -07:00
|
|
|
let mut wallet = cust_close.message.clone();
|
|
|
|
let close_wallet = wallet.with_close(String::from("close")).clone();
|
|
|
|
let close_token = cust_close.signature.clone();
|
|
|
|
|
2019-08-22 17:52:18 -07:00
|
|
|
let is_valid = pk.verify(&channel_token.mpk, &close_wallet, &close_token);
|
2019-08-20 16:09:01 -07:00
|
|
|
|
|
|
|
if is_valid {
|
|
|
|
let wpk = cust_close.wpk;
|
|
|
|
// found the wpk, which means old close token
|
|
|
|
let fingerprint = util::compute_pub_key_fingerprint(&wpk);
|
|
|
|
if merch_state.keys.contains_key(&fingerprint) {
|
|
|
|
let revoked_state = merch_state.keys.get(&fingerprint).unwrap();
|
|
|
|
if !revoked_state.revoke_token.is_none() {
|
|
|
|
let revoke_token = revoked_state.revoke_token.unwrap().clone();
|
|
|
|
// verify the revoked state first before returning
|
|
|
|
let secp = secp256k1::Secp256k1::new();
|
|
|
|
let revoke_msg = RevokedMessage::new(String::from("revoked"), wpk.clone());
|
|
|
|
let msg = secp256k1::Message::from_slice(&revoke_msg.hash_to_slice()).unwrap();
|
|
|
|
// verify that the revocation token is valid
|
|
|
|
if secp.verify(&msg, &revoke_token, &wpk).is_ok() {
|
2019-08-26 08:08:49 -07:00
|
|
|
// compute signature on
|
2019-08-20 16:09:01 -07:00
|
|
|
return Ok(Some(revoked_state.clone()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Err(String::from("merchant_close - Found wpk but could not find the revoke token. Merchant abort detected."));
|
|
|
|
}
|
|
|
|
return Err(String::from("merchant_close - Could not find entry for wpk & revoke token pair. Valid close!"));
|
|
|
|
}
|
|
|
|
Err(String::from("merchant_close - Customer close message not valid!"))
|
2018-06-09 23:00:01 -07:00
|
|
|
}
|
2019-08-22 17:52:18 -07:00
|
|
|
|
|
|
|
///
|
2019-08-26 08:08:49 -07:00
|
|
|
/// Used in open-channel WTP for validating that a close_token is a valid signature under <
|
2019-08-22 17:52:18 -07:00
|
|
|
///
|
2019-08-26 08:08:49 -07:00
|
|
|
pub fn wtp_verify_cust_close_message<E: Engine>(channel_token: &ChannelToken<E>, wpk: &secp256k1::PublicKey, close_msg: &wallet::Wallet<E>, close_token: &Signature<E>) -> bool {
|
2019-08-22 17:52:18 -07:00
|
|
|
// 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);
|
|
|
|
}
|
|
|
|
|
2019-08-26 08:08:49 -07:00
|
|
|
///
|
|
|
|
/// Used in merch-close WTP for validating that revoke_token is a valid signature under <wpk> and the <revoked || wpk> message
|
|
|
|
///
|
2019-09-02 13:44:17 -07:00
|
|
|
pub fn wtp_verify_revoke_message(wpk: &secp256k1::PublicKey, revoke_token: &secp256k1::Signature) -> bool {
|
2019-08-26 08:08:49 -07:00
|
|
|
let secp = secp256k1::Secp256k1::verification_only();
|
|
|
|
let revoke_msg = RevokedMessage::new(String::from("revoked"), wpk.clone());
|
|
|
|
let msg = secp256k1::Message::from_slice(&revoke_msg.hash_to_slice()).unwrap();
|
|
|
|
// verify that the revocation token is valid with respect to revoked || wpk
|
|
|
|
return secp.verify(&msg, &revoke_token, &wpk).is_ok();
|
|
|
|
}
|
2019-08-22 17:52:18 -07:00
|
|
|
|
2019-08-26 08:08:49 -07:00
|
|
|
///
|
|
|
|
/// Used in merch-close WTP for validating that merch_sig is a valid signature under <merch_pk> on <dest_addr || revoke-token> message
|
|
|
|
///
|
|
|
|
pub fn wtp_verify_merch_close_message<E: Engine>(channel_token: &ChannelToken<E>, merch_close: &ChannelcloseM) -> bool {
|
|
|
|
let secp = secp256k1::Secp256k1::verification_only();
|
|
|
|
let mut msg = Vec::new();
|
|
|
|
msg.extend(merch_close.address.as_bytes());
|
|
|
|
if !merch_close.revoke.is_none() {
|
|
|
|
// serialize signature in DER format
|
|
|
|
let r = merch_close.revoke.unwrap().serialize_der().to_vec();
|
|
|
|
msg.extend(r);
|
|
|
|
}
|
|
|
|
let msg2 = secp256k1::Message::from_slice(&hash_to_slice(&msg)).unwrap();
|
|
|
|
// verify that merch sig is valid with respect to dest_address
|
|
|
|
return secp.verify(&msg2, &merch_close.signature, &channel_token.pk_m).is_ok();
|
|
|
|
}
|
2018-03-25 20:20:05 -07: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::*;
|
2019-07-28 22:18:40 -07:00
|
|
|
use ff::Rand;
|
2019-09-13 13:16:35 -07:00
|
|
|
use pairing::bls12_381::Bls12;
|
2019-08-20 16:09:01 -07:00
|
|
|
use rand::Rng;
|
2019-09-10 19:21:09 -07:00
|
|
|
use channels::ChannelState;
|
2019-09-13 13:16:35 -07:00
|
|
|
use util::hash_pubkey_to_fr;
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-07-29 21:53:58 -07:00
|
|
|
fn setup_new_channel_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
2019-09-27 10:02:31 -07:00
|
|
|
init_cust_bal: i64, init_merch_bal: i64)
|
2019-09-13 13:16:35 -07:00
|
|
|
-> (bidirectional::ChannelToken<Bls12>, bidirectional::MerchantState<Bls12>, bidirectional::CustomerState<Bls12>, bidirectional::ChannelState<Bls12>) {
|
2019-07-29 21:53:58 -07:00
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
let merch_name = "Bob";
|
|
|
|
let cust_name = "Alice";
|
|
|
|
|
|
|
|
let b0_cust = init_cust_bal;
|
|
|
|
let b0_merch = init_merch_bal;
|
|
|
|
|
|
|
|
// 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
|
2019-09-10 19:21:09 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, channel_state, merch_name);
|
2019-07-29 21:53:58 -07:00
|
|
|
|
|
|
|
// initialize on the customer side with balance: b0_cust
|
2019-09-16 08:58:10 -07:00
|
|
|
let cust_state = bidirectional::init_customer(rng, &mut channel_token, b0_cust, b0_merch, cust_name);
|
2019-07-29 21:53:58 -07:00
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
return (channel_token, merch_state, cust_state, channel_state);
|
2019-07-29 21:53:58 -07:00
|
|
|
}
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-07-29 22:37:32 -07:00
|
|
|
fn execute_establish_protocol_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
2019-09-13 13:16:35 -07:00
|
|
|
channel_token: &mut bidirectional::ChannelToken<Bls12>,
|
2019-09-27 10:02:31 -07:00
|
|
|
cust_balance: i64,
|
|
|
|
merch_balance: i64,
|
2019-09-13 13:16:35 -07:00
|
|
|
merch_state: &mut bidirectional::MerchantState<Bls12>,
|
|
|
|
cust_state: &mut bidirectional::CustomerState<Bls12>) {
|
2019-07-29 22:37:32 -07:00
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
|
|
|
// lets establish the channel
|
2019-08-16 09:29:01 -07:00
|
|
|
let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, channel_token, cust_state);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
|
|
|
// obtain close token for closing out channel
|
2019-09-16 12:27:17 -07:00
|
|
|
//let pk_h = hash_pubkey_to_fr::<Bls12>(&cust_state.pk_c.clone());
|
|
|
|
let pk_c = cust_state.get_public_key();
|
|
|
|
let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &pk_c,
|
|
|
|
cust_balance, merch_balance, &merch_state);
|
2019-09-13 13:16:35 -07:00
|
|
|
let close_token = match option {
|
2019-08-11 02:48:46 -07:00
|
|
|
Ok(n) => n.unwrap(),
|
|
|
|
Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e)
|
|
|
|
};
|
2019-08-16 09:29:01 -07:00
|
|
|
assert!(cust_state.verify_close_token(&channel_state, &close_token));
|
2019-07-29 22:37:32 -07:00
|
|
|
|
|
|
|
// wait for funding tx to be confirmed, etc
|
|
|
|
|
|
|
|
// obtain payment token for pay protocol
|
2019-08-16 09:29:01 -07:00
|
|
|
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));
|
2019-07-29 22:37:32 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
assert!(bidirectional::establish_customer_final(channel_state, cust_state, &pay_token));
|
2019-07-29 22:37:32 -07:00
|
|
|
println!("Channel established!");
|
|
|
|
}
|
|
|
|
|
|
|
|
fn execute_payment_protocol_helper(channel_state: &mut bidirectional::ChannelState<Bls12>,
|
2019-09-13 13:16:35 -07:00
|
|
|
channel_token: &mut bidirectional::ChannelToken<Bls12>,
|
|
|
|
merch_state: &mut bidirectional::MerchantState<Bls12>,
|
|
|
|
cust_state: &mut bidirectional::CustomerState<Bls12>,
|
2019-09-27 10:02:31 -07:00
|
|
|
payment_increment: i64) {
|
2019-07-29 22:37:32 -07:00
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let (payment, new_cust_state) = bidirectional::generate_payment_proof(rng, channel_state, &cust_state, payment_increment);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let new_close_token = bidirectional::verify_payment_proof(rng, &channel_state, &payment, merch_state);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let revoke_token = bidirectional::generate_revoke_token(&channel_state, cust_state, new_cust_state, &new_close_token);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
|
|
|
// send revoke token and get pay-token in response
|
2019-09-05 19:45:47 -07:00
|
|
|
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);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
|
|
|
// verify the pay token and update internal state
|
2019-09-05 19:45:47 -07:00
|
|
|
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token.unwrap()));
|
2019-09-13 13:16:35 -07:00
|
|
|
}
|
2018-07-25 19:19:03 -07:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn bidirectional_payment_basics_work() {
|
2018-07-30 00:06:06 -07:00
|
|
|
// just bidirectional case (w/o third party)
|
2019-07-28 22:18:40 -07:00
|
|
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
2018-07-25 19:19:03 -07:00
|
|
|
let total_owed = 40;
|
|
|
|
let b0_customer = 90;
|
|
|
|
let b0_merchant = 20;
|
|
|
|
let payment_increment = 20;
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant Bob");
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-09-16 08:58:10 -07:00
|
|
|
let mut cust_state = bidirectional::init_customer(rng, &mut channel_token, b0_customer, b0_merchant, "Alice");
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
println!("{}", cust_state);
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// lets establish the channel
|
2019-08-16 09:29:01 -07:00
|
|
|
let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state);
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// obtain close token for closing out channel
|
2019-09-13 13:16:35 -07:00
|
|
|
let pk_h = hash_pubkey_to_fr::<Bls12>(&cust_state.pk_c.clone());
|
|
|
|
let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &pk_h,
|
|
|
|
b0_customer, b0_merchant, &merch_state);
|
|
|
|
let close_token = match option {
|
2019-08-11 02:48:46 -07:00
|
|
|
Ok(n) => n.unwrap(),
|
|
|
|
Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e)
|
|
|
|
};
|
2019-08-16 09:29:01 -07:00
|
|
|
assert!(cust_state.verify_close_token(&channel_state, &close_token));
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// wait for funding tx to be confirmed, etc
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// obtain payment token for pay protocol
|
2019-08-16 09:29:01 -07:00
|
|
|
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));
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
assert!(bidirectional::establish_customer_final(&mut channel_state, &mut cust_state, &pay_token));
|
2019-07-28 22:18:40 -07:00
|
|
|
println!("Channel established!");
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let (payment, new_cust_state) = bidirectional::generate_payment_proof(rng, &channel_state, &cust_state, 10);
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let new_close_token = bidirectional::verify_payment_proof(rng, &channel_state, &payment, &mut merch_state);
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let revoke_token = bidirectional::generate_revoke_token(&channel_state, &mut cust_state, new_cust_state, &new_close_token);
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// send revoke token and get pay-token in response
|
2019-09-05 19:45:47 -07:00
|
|
|
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);
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// verify the pay token and update internal state
|
2019-09-05 19:45:47 -07:00
|
|
|
assert!(cust_state.verify_pay_token(&channel_state, &new_pay_token.unwrap()));
|
2018-07-30 00:06:06 -07:00
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
println!("Successful payment!");
|
2019-07-31 19:06:57 -07:00
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let cust_close = bidirectional::customer_close(&channel_state, &cust_state);
|
2019-07-31 19:06:57 -07:00
|
|
|
println!("Obtained the channel close message");
|
|
|
|
println!("{}", cust_close.message);
|
|
|
|
println!("{}", cust_close.signature);
|
2018-07-25 19:19:03 -07:00
|
|
|
}
|
|
|
|
|
2019-07-29 22:37:32 -07:00
|
|
|
#[test]
|
|
|
|
fn bidirectional_multiple_payments_work() {
|
|
|
|
let total_owed = 40;
|
|
|
|
let b0_customer = 380;
|
|
|
|
let b0_merchant = 20;
|
|
|
|
let payment_increment = 20;
|
|
|
|
|
|
|
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
2019-09-10 10:11:31 -07:00
|
|
|
// set fee for channel
|
|
|
|
let fee = 5;
|
|
|
|
channel_state.set_channel_fee(fee);
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper(&mut channel_state, b0_customer, b0_merchant);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
|
|
|
// run establish protocol for customer and merchant channel
|
2019-08-27 06:56:02 -07:00
|
|
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
2019-07-29 22:37:32 -07:00
|
|
|
|
|
|
|
assert!(channel_state.channel_established);
|
|
|
|
|
|
|
|
{
|
|
|
|
// make multiple payments in a loop
|
|
|
|
let num_payments = total_owed / payment_increment;
|
2019-09-13 13:16:35 -07:00
|
|
|
for i in 0..num_payments {
|
2019-08-16 09:29:01 -07:00
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, payment_increment);
|
2019-07-29 22:37:32 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// scope localizes the immutable borrow here (for debug purposes only)
|
2019-08-16 09:29:01 -07:00
|
|
|
println!("Customer balance: {:?}", &cust_state.cust_balance);
|
|
|
|
println!("Merchant balance: {:?}", &cust_state.merch_balance);
|
2019-09-10 10:11:31 -07:00
|
|
|
let total_owed_with_fees = (fee * num_payments) + total_owed;
|
|
|
|
assert!(cust_state.cust_balance == (b0_customer - total_owed_with_fees) && cust_state.merch_balance == total_owed_with_fees + b0_merchant);
|
2019-07-29 22:37:32 -07:00
|
|
|
}
|
|
|
|
|
2019-08-20 16:09:01 -07:00
|
|
|
let cust_close_msg = bidirectional::customer_close(&channel_state, &cust_state);
|
2019-07-31 19:06:57 -07:00
|
|
|
println!("Obtained the channel close message");
|
2019-08-20 16:09:01 -07:00
|
|
|
println!("{}", cust_close_msg.message);
|
|
|
|
println!("{}", cust_close_msg.signature);
|
2019-07-29 22:37:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-30 14:25:27 -07:00
|
|
|
#[test]
|
|
|
|
fn bidirectional_payment_negative_payment_works() {
|
|
|
|
// just bidirectional case (w/o third party)
|
|
|
|
let total_owed = -20;
|
|
|
|
let b0_customer = 90;
|
|
|
|
let b0_merchant = 30;
|
|
|
|
let payment_increment = -20;
|
|
|
|
|
|
|
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper(&mut channel_state, b0_customer, b0_merchant);
|
2019-07-30 14:25:27 -07:00
|
|
|
|
|
|
|
// run establish protocol for customer and merchant channel
|
2019-08-27 06:56:02 -07:00
|
|
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
2019-07-30 14:25:27 -07:00
|
|
|
assert!(channel_state.channel_established);
|
|
|
|
|
|
|
|
{
|
2019-08-16 09:29:01 -07:00
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, payment_increment);
|
2019-07-30 14:25:27 -07:00
|
|
|
|
|
|
|
{
|
|
|
|
// scope localizes the immutable borrow here (for debug purposes only)
|
2019-08-16 09:29:01 -07:00
|
|
|
println!("Customer balance: {:?}", &cust_state.cust_balance);
|
|
|
|
println!("Merchant balance: {:?}", &cust_state.merch_balance);
|
|
|
|
assert!(cust_state.cust_balance == (b0_customer - total_owed) && cust_state.merch_balance == total_owed + b0_merchant);
|
2019-07-30 14:25:27 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-20 16:09:01 -07:00
|
|
|
#[test]
|
|
|
|
fn bidirectional_merchant_close_detects_double_spends() {
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
|
|
|
let b0_customer = rng.gen_range(100, 1000);
|
|
|
|
let b0_merchant = 10;
|
|
|
|
let pay_increment = 20;
|
|
|
|
|
|
|
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper(&mut channel_state, b0_customer, b0_merchant);
|
2019-08-20 16:09:01 -07:00
|
|
|
|
|
|
|
// run establish protocol for customer and merchant channel
|
2019-08-27 06:56:02 -07:00
|
|
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
2019-08-20 16:09:01 -07:00
|
|
|
|
|
|
|
assert!(channel_state.channel_established);
|
|
|
|
|
|
|
|
// let's make a few payments then exit channel (will post an old channel state
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
// let's close then move state forward
|
|
|
|
let old_cust_close_msg = bidirectional::customer_close(&channel_state, &cust_state);
|
|
|
|
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
let cur_cust_close_msg = bidirectional::customer_close(&channel_state, &cust_state);
|
|
|
|
|
|
|
|
let merch_close_result = bidirectional::merchant_close(&channel_state,
|
2019-09-13 13:16:35 -07:00
|
|
|
&channel_token,
|
|
|
|
&old_cust_close_msg,
|
|
|
|
&merch_state);
|
2019-08-20 16:09:01 -07:00
|
|
|
let merch_close_msg = match merch_close_result {
|
|
|
|
Ok(n) => n.unwrap(),
|
|
|
|
Err(err) => panic!("Merchant close msg: {}", err)
|
|
|
|
};
|
|
|
|
|
|
|
|
println!("Double spend attempt by customer! Evidence below...");
|
|
|
|
println!("Merchant close: wpk = {}", merch_close_msg.wpk);
|
|
|
|
println!("Merchant close: revoke_token = {}", merch_close_msg.revoke_token.unwrap());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_panic]
|
|
|
|
fn bidirectional_merchant_close_works() {
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
|
|
|
let b0_customer = rng.gen_range(100, 1000);
|
|
|
|
let b0_merchant = 10;
|
|
|
|
let pay_increment = 20;
|
|
|
|
|
|
|
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
|
|
|
|
2019-09-13 13:16:35 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut cust_state, mut channel_state) = setup_new_channel_helper(&mut channel_state, b0_customer, b0_merchant);
|
2019-08-20 16:09:01 -07:00
|
|
|
|
|
|
|
// run establish protocol for customer and merchant channel
|
2019-08-27 06:56:02 -07:00
|
|
|
execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state);
|
2019-08-20 16:09:01 -07:00
|
|
|
|
|
|
|
assert!(channel_state.channel_established);
|
|
|
|
|
|
|
|
// let's make a few payments then exit channel (will post an old channel state
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
execute_payment_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state, pay_increment);
|
|
|
|
|
|
|
|
let cust_close_msg = bidirectional::customer_close(&channel_state, &cust_state);
|
|
|
|
|
|
|
|
let merch_close_result = bidirectional::merchant_close(&channel_state,
|
2019-09-13 13:16:35 -07:00
|
|
|
&channel_token,
|
|
|
|
&cust_close_msg,
|
|
|
|
&merch_state);
|
2019-08-20 16:09:01 -07:00
|
|
|
let merch_close_msg = match merch_close_result {
|
|
|
|
Ok(n) => n.unwrap(),
|
|
|
|
Err(err) => panic!("Merchant close msg: {}", err)
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-07-28 22:18:40 -07:00
|
|
|
// fn execute_third_party_pay_protocol_helper(pp: &bidirectional::PublicParams,
|
|
|
|
// channel1: &mut bidirectional::ChannelState, channel2: &mut bidirectional::ChannelState,
|
|
|
|
// merch_keys: &cl::KeyPairD, merch1_data: &mut bidirectional::InitMerchantData,
|
|
|
|
// merch2_data: &mut bidirectional::InitMerchantData,
|
|
|
|
// cust1_keys: &cl::KeyPairD, cust1_data: &mut bidirectional::InitCustomerData,
|
|
|
|
// cust2_keys: &cl::KeyPairD, cust2_data: &mut bidirectional::InitCustomerData,
|
2019-09-27 10:02:31 -07:00
|
|
|
// payment_increment: i64) {
|
2019-07-28 22:18:40 -07:00
|
|
|
// // let's test the pay protocol
|
|
|
|
// bidirectional::pay_by_customer_phase1_precompute(&pp, &cust1_data.channel_token, &merch_keys.pk, &mut cust1_data.csk);
|
|
|
|
// bidirectional::pay_by_customer_phase1_precompute(&pp, &cust2_data.channel_token, &merch_keys.pk, &mut cust2_data.csk);
|
|
|
|
//
|
|
|
|
// println!("Channel 1 fee: {}", channel1.get_channel_fee());
|
|
|
|
// let (t_c1, new_wallet1, pay_proof1) = bidirectional::pay_by_customer_phase1(&pp, &channel1,
|
|
|
|
// &cust1_data.channel_token, // channel token
|
|
|
|
// &merch_keys.pk, // merchant pub key
|
|
|
|
// &cust1_data.csk, // wallet
|
|
|
|
// payment_increment); // balance increment
|
|
|
|
// println!("Channel 2 fee: {}", channel2.get_channel_fee());
|
|
|
|
// let (t_c2, new_wallet2, pay_proof2) = bidirectional::pay_by_customer_phase1(&pp, &channel2,
|
|
|
|
// &cust2_data.channel_token, // channel token
|
|
|
|
// &merch_keys.pk, // merchant pub key
|
|
|
|
// &cust2_data.csk, // wallet
|
|
|
|
// -payment_increment); // balance decrement
|
|
|
|
//
|
|
|
|
// // validate pay_proof1 and pay_proof2 (and the channel state for the fee paying channel, if fee > 0)
|
|
|
|
// let tx_fee = channel1.get_channel_fee() + channel2.get_channel_fee();
|
|
|
|
// assert!(bidirectional::verify_third_party_payment(&pp, tx_fee, &pay_proof1.bal_proof, &pay_proof2.bal_proof));
|
|
|
|
//
|
|
|
|
// // get the refund token (rt_w)
|
|
|
|
// let rt_w1 = bidirectional::pay_by_merchant_phase1(&pp, channel1, &pay_proof1, &merch1_data);
|
|
|
|
//
|
|
|
|
// // get the refund token (rt_w)
|
|
|
|
// let rt_w2 = bidirectional::pay_by_merchant_phase1(&pp, channel2, &pay_proof2, &merch2_data);
|
|
|
|
//
|
|
|
|
// // get the revocation token (rv_w) on the old public key (wpk)
|
|
|
|
// let rv_w1 = bidirectional::pay_by_customer_phase2(&pp, &cust1_data.csk, &new_wallet1, &merch_keys.pk, &rt_w1);
|
|
|
|
//
|
|
|
|
// // get the revocation token (rv_w) on the old public key (wpk)
|
|
|
|
// let rv_w2 = bidirectional::pay_by_customer_phase2(&pp, &cust2_data.csk, &new_wallet2, &merch_keys.pk, &rt_w2);
|
|
|
|
//
|
|
|
|
// // get the new wallet sig (new_wallet_sig) on the new wallet
|
|
|
|
// let new_wallet_sig1 = bidirectional::pay_by_merchant_phase2(&pp, channel1, &pay_proof1, merch1_data, &rv_w1);
|
|
|
|
//
|
|
|
|
// // get the new wallet sig (new_wallet_sig) on the new wallet
|
|
|
|
// let new_wallet_sig2 = bidirectional::pay_by_merchant_phase2(&pp, channel2, &pay_proof2, merch2_data, &rv_w2);
|
|
|
|
//
|
|
|
|
// assert!(bidirectional::pay_by_customer_final(&pp, &merch_keys.pk, cust1_data, t_c1, new_wallet1, rt_w1, new_wallet_sig1));
|
|
|
|
//
|
|
|
|
// assert!(bidirectional::pay_by_customer_final(&pp, &merch_keys.pk, cust2_data, t_c2, new_wallet2, rt_w2, new_wallet_sig2));
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// #[test]
|
|
|
|
// #[ignore]
|
|
|
|
// fn third_party_payment_basics_work() {
|
|
|
|
// let pp = bidirectional::setup(true);
|
|
|
|
//
|
|
|
|
// // third party -- so indicate so in the channel state
|
|
|
|
// let mut channel_a = bidirectional::ChannelState::new(String::from("Channel A <-> I"), true);
|
|
|
|
// let mut channel_b = bidirectional::ChannelState::new(String::from("Channel B <-> I"), true);
|
|
|
|
//
|
|
|
|
// let fee = 2;
|
|
|
|
// channel_a.set_channel_fee(fee);
|
|
|
|
//
|
|
|
|
// let total_payment = 20;
|
|
|
|
// let b0_alice = 30;
|
|
|
|
// let b0_bob = 30;
|
|
|
|
// let b0_merchant_a = 40;
|
|
|
|
// let b0_merchant_b = 40;
|
|
|
|
//
|
|
|
|
// let (merch_keys, mut merch_data_a, alice_keys, mut alice_data) = setup_new_channel_helper(&pp, &mut channel_a, b0_alice, b0_merchant_a);
|
|
|
|
//
|
|
|
|
// let (mut merch_data_b, bob_keys, mut bob_data) =
|
|
|
|
// setup_new_channel_existing_merchant_helper(&pp, &mut channel_b, b0_bob, b0_merchant_b, &merch_keys);
|
|
|
|
//
|
|
|
|
// // run establish protocol for alice and merchant channel
|
|
|
|
// execute_establish_protocol_helper(&pp, &mut channel_a, &merch_keys, &mut merch_data_a, &alice_keys, &mut alice_data);
|
|
|
|
//
|
|
|
|
// // run establish protocol for bob and merchant channel
|
|
|
|
// execute_establish_protocol_helper(&pp, &mut channel_b, &merch_keys, &mut merch_data_b, &bob_keys, &mut bob_data);
|
|
|
|
//
|
|
|
|
// assert!(channel_a.channel_established);
|
|
|
|
// assert!(channel_b.channel_established);
|
|
|
|
//
|
|
|
|
// // alice can pay bob through the merchant
|
|
|
|
// execute_third_party_pay_protocol_helper(&pp, &mut channel_a, &mut channel_b,
|
|
|
|
// &merch_keys, &mut merch_data_a, &mut merch_data_b,
|
|
|
|
// &alice_keys, &mut alice_data, &bob_keys, &mut bob_data, total_payment);
|
|
|
|
//
|
|
|
|
// println!("Customer alice balance: {}", alice_data.csk.balance);
|
|
|
|
// println!("Merchant channel balance with alice: {}", merch_data_a.csk.balance);
|
|
|
|
// println!("Customer bob balance: {}", bob_data.csk.balance);
|
|
|
|
// println!("Merchant channel balance with bob: {}", merch_data_b.csk.balance);
|
|
|
|
// }
|
2018-07-25 19:19:03 -07:00
|
|
|
|
2019-03-05 17:05:05 -08:00
|
|
|
#[test]
|
|
|
|
fn serialization_tests() {
|
2019-07-29 21:53:58 -07:00
|
|
|
let mut channel_state = bidirectional::ChannelState::<Bls12>::new(String::from("Channel A -> B"), false);
|
|
|
|
let mut rng = &mut rand::thread_rng();
|
|
|
|
|
|
|
|
let serialized = serde_json::to_string(&channel_state).unwrap();
|
|
|
|
println!("new channel state len: {}", &serialized.len());
|
|
|
|
|
|
|
|
let chan_state: bidirectional::ChannelState<Bls12> = serde_json::from_str(&serialized).unwrap();
|
|
|
|
|
2019-09-10 19:21:09 -07:00
|
|
|
let (mut channel_token, mut merch_state, mut channel_state) = bidirectional::init_merchant(rng, &mut channel_state, "Merchant A");
|
2019-07-31 19:06:57 -07:00
|
|
|
|
|
|
|
let b0_cust = 100;
|
|
|
|
let b0_merch = 10;
|
2019-09-16 08:58:10 -07:00
|
|
|
let cust_state = bidirectional::init_customer(rng, &mut channel_token, b0_cust, b0_merch, "Customer A");
|
2019-07-31 19:06:57 -07:00
|
|
|
|
|
|
|
let serlalized_ct = serde_json::to_string(&channel_token).unwrap();
|
|
|
|
|
|
|
|
println!("serialized ct: {:?}", &serlalized_ct);
|
|
|
|
|
|
|
|
let des_ct: bidirectional::ChannelToken<Bls12> = serde_json::from_str(&serlalized_ct).unwrap();
|
|
|
|
|
|
|
|
//println!("des_ct: {}", &des_ct);
|
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let serlalized_cw = serde_json::to_string(&cust_state).unwrap();
|
2019-07-31 19:06:57 -07:00
|
|
|
|
|
|
|
println!("serialized cw: {:?}", &serlalized_cw);
|
|
|
|
|
2019-08-16 09:29:01 -07:00
|
|
|
let des_cw: bidirectional::CustomerState<Bls12> = serde_json::from_str(&serlalized_cw).unwrap();
|
2019-03-05 17:05:05 -08:00
|
|
|
}
|
2018-08-10 00:01:50 -07:00
|
|
|
}
|