diff --git a/examples/bolt_test.rs b/examples/bolt_test.rs index 0850161..c505336 100644 --- a/examples/bolt_test.rs +++ b/examples/bolt_test.rs @@ -69,7 +69,8 @@ fn main() { 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_state); + let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, + b0_customer, b0_merchant, &merch_state); let close_token= match option { Ok(n) => n.unwrap(), Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e) diff --git a/py/libbolt.py b/py/libbolt.py index 4c2b8f1..976bdfa 100644 --- a/py/libbolt.py +++ b/py/libbolt.py @@ -29,7 +29,7 @@ class Libbolt(object): self.lib.ffishim_bidirectional_establish_customer_generate_proof.argtypes = (c_void_p, c_void_p) self.lib.ffishim_bidirectional_establish_customer_generate_proof.restype = c_void_p - self.lib.ffishim_bidirectional_establish_merchant_issue_close_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p) + self.lib.ffishim_bidirectional_establish_merchant_issue_close_token.argtypes = (c_void_p, c_void_p, c_void_p, c_void_p, c_void_p, c_void_p) self.lib.ffishim_bidirectional_establish_merchant_issue_close_token.restype = c_void_p self.lib.ffishim_bidirectional_establish_merchant_issue_pay_token.argtypes = (c_void_p, c_void_p, c_void_p) @@ -100,8 +100,8 @@ class Libbolt(object): output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary['channel_token'], output_dictionary['cust_state'], output_dictionary['com'], output_dictionary['com_proof'] - def bidirectional_establish_merchant_issue_close_token(self, channel_state, com, com_proof, merch_state): - output_string = self.lib.ffishim_bidirectional_establish_merchant_issue_close_token(channel_state.encode(), com.encode(), com_proof.encode(), merch_state.encode()) + def bidirectional_establish_merchant_issue_close_token(self, channel_state, com, com_proof, init_cust, init_merch, merch_state): + output_string = self.lib.ffishim_bidirectional_establish_merchant_issue_close_token(channel_state.encode(), com.encode(), com_proof.encode(), init_cust, init_merch, merch_state.encode()) output_dictionary = ast.literal_eval(ctypes.cast(output_string, ctypes.c_char_p).value.decode('utf-8')) return output_dictionary['close_token'] @@ -229,7 +229,7 @@ def run_unit_test(): (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) + close_token = libbolt.bidirectional_establish_merchant_issue_close_token(channel_state, com, com_proof, b0_cust, b0_merch, 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) diff --git a/src/channels.rs b/src/channels.rs index 6b54a6a..910247d 100644 --- a/src/channels.rs +++ b/src/channels.rs @@ -415,22 +415,6 @@ impl CustomerState { } -// pub name: String, -// pub pk_c: secp256k1::PublicKey, -// sk_c: secp256k1::SecretKey, -// pub cust_balance: i32, // -// pub merch_balance: i32, -// pub wpk: secp256k1::PublicKey, // keypair bound to the wallet -// wsk: secp256k1::SecretKey, -// old_kp: Option, // old wallet key pair -// t: E::Fr, // randomness used to form the commitment -// wallet: Wallet, // vector of field elements that represent wallet -// pub w_com: Commitment, // commitment to the current state of the wallet -// index: i32, -// close_tokens: HashMap>, -// pay_tokens: HashMap> - - impl fmt::Display for CustomerState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut content = String::new(); @@ -445,7 +429,16 @@ impl fmt::Display for CustomerState { content = format!("{}revoked: wpk = {}\nrevoked: wsk = {}\n", content, &old_kp.wpk, &old_kp.wsk); } content = format!("{}t = {}\n", content, &self.t); - + content = format!("{}wallet = {}\n", content, &self.wallet); + content = format!("{}w_com = {}\n", content, &self.w_com); + let close_token = self.close_tokens.get(&self.index); + let pay_token = self.pay_tokens.get(&self.index); + if (!close_token.is_none()) { + content = format!("{}close_token = {}\n", content, &self.close_tokens.get(&self.index).unwrap()); + } + if (!pay_token.is_none()) { + content = format!("{}pay_token = {}\n", content, &self.pay_tokens.get(&self.index).unwrap()); + } write!(f, "CustomerState : (\n{}\n)", &content) } } @@ -471,7 +464,7 @@ pub struct ChannelcloseM { ))] pub struct MerchantState { keypair: cl::BlindKeyPair, - pub balance: i32, + pub init_balance: i32, pk: secp256k1::PublicKey, // pk_m sk: secp256k1::SecretKey, // sk_m comParams: CSMultiParams, @@ -489,7 +482,7 @@ impl MerchantState { MerchantState { keypair: cp.pub_params.keypair.clone(), - balance: 0, + init_balance: 0, pk: wpk, sk: wsk, comParams: cp.pub_params.comParams.clone(), @@ -514,7 +507,7 @@ impl MerchantState { pub fn init_balance(&mut self, balance: i32) { // set by the escrow/funding transactionf for the channel - self.balance = balance; + self.init_balance = balance; } pub fn issue_close_token(&self, csprng: &mut R, cp: &ChannelParams, com: &Commitment, extend_close: bool) -> Signature { @@ -539,11 +532,13 @@ impl MerchantState { return self.keypair.sign_blind(csprng, &cp.pub_params.mpk, pay_com); } - pub fn verify_proof(&self, csprng: &mut R, channel: &ChannelState, com: &Commitment, com_proof: &CommitmentProof) -> ResultBoltSig<(Signature, Signature)> { - let is_valid = nizk::verify_opening(&self.comParams, &com.c, &com_proof); + pub fn verify_proof(&self, csprng: &mut R, channel: &ChannelState, com: &Commitment, com_proof: &CommitmentProof, cust_balance: i32, merch_balance: i32) -> ResultBoltSig<(Signature, Signature)> { + if (merch_balance != self.init_balance) { + return Err(BoltError::new("verify_proof - initial balance of merchant inconsistent with specified balance")); + } + let is_valid = nizk::verify_opening(&self.comParams, &com.c, &com_proof, cust_balance, merch_balance); let cp = channel.cp.as_ref().unwrap(); if 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)); @@ -566,7 +561,7 @@ impl MerchantState { let cp = channel.cp.as_ref().unwrap(); let pay_proof = proof.clone(); let prev_wpk = hash_pubkey_to_fr::(&wpk); - let epsilon = util::convert_int_to_fr::(amount); // E::Fr::from_str(&amount.to_string()).unwrap(); + let epsilon = util::convert_int_to_fr::(amount); if cp.pub_params.verify(pay_proof, epsilon, com, prev_wpk) { // 1 - proceed with generating close and pay token @@ -627,6 +622,7 @@ mod tests { // in order to derive the channel tokens // initialize on the merchant side with balance: b0_merch let mut merch_state = MerchantState::::new(rng, &mut channel, String::from("Merchant B")); + merch_state.init_balance(b0_merch); // initialize the merchant wallet with the balance let mut channel_token = merch_state.init(rng, &mut channel); @@ -640,7 +636,7 @@ mod tests { // first return the close token, then wait for escrow-tx confirmation // then send the pay-token after confirmation - let (close_token, pay_token) = merch_state.verify_proof(rng, &channel, &cust_state.w_com, &cust_com_proof).unwrap(); + let (close_token, pay_token) = merch_state.verify_proof(rng, &channel, &cust_state.w_com, &cust_com_proof, b0_cust, b0_merch).unwrap(); // unblind tokens and verify signatures assert!(cust_state.verify_close_token(&channel, &close_token)); diff --git a/src/ffishim.rs b/src/ffishim.rs index e63151a..97de458 100644 --- a/src/ffishim.rs +++ b/src/ffishim.rs @@ -132,7 +132,8 @@ pub mod ffishim { } #[no_mangle] - pub extern fn ffishim_bidirectional_establish_merchant_issue_close_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_com_proof: *mut c_char, ser_merch_state: *mut c_char) -> *mut c_char { + pub extern fn ffishim_bidirectional_establish_merchant_issue_close_token(ser_channel_state: *mut c_char, ser_com: *mut c_char, ser_com_proof: *mut c_char, + init_cust_bal: i32, init_merch_bal: i32, ser_merch_state: *mut c_char) -> *mut c_char { let rng = &mut rand::thread_rng(); // Deserialize the channel state let channel_state: bidirectional::ChannelState = deserialize_object(ser_channel_state); @@ -146,7 +147,7 @@ pub mod ffishim { // Deserialize the merchant wallet let merch_state: bidirectional::MerchantState = deserialize_object(ser_merch_state); - let close_token = bolt_try!(bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_state)); + let close_token = bolt_try!(bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, init_cust_bal, init_merch_bal, &merch_state)); let ser = ["{\'close_token\':\'", serde_json::to_string(&close_token).unwrap().as_str(), "\'}"].concat(); let cser = CString::new(ser).unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 3992bb3..ee09afe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -218,9 +218,11 @@ pub mod bidirectional { /// signature) over the contents of the customer's wallet. /// pub fn establish_merchant_issue_close_token(csprng: &mut R, channel_state: &ChannelState, - com: &Commitment, com_proof: &CommitmentProof, merch_state: &MerchantState) -> BoltResult> { + com: &Commitment, com_proof: &CommitmentProof, + init_cust_balance: i32, init_merch_balance: i32, + merch_state: &MerchantState) -> BoltResult> { // verifies proof of committed values and derives blind signature on the committed values to the customer's initial wallet - match merch_state.verify_proof(csprng, channel_state, com, com_proof) { + match merch_state.verify_proof(csprng, channel_state, com, com_proof, init_cust_balance, merch_state.init_balance) { Ok(n) => Ok(Some(n.0)), // just close token Err(err) => Err(String::from(err.to_string())) } @@ -537,6 +539,8 @@ mod tests { fn execute_establish_protocol_helper(channel_state: &mut bidirectional::ChannelState, channel_token: &mut bidirectional::ChannelToken, + cust_balance: i32, + merch_balance: i32, merch_state: &mut bidirectional::MerchantState, cust_state: &mut bidirectional::CustomerState) { @@ -546,7 +550,7 @@ mod tests { let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, channel_token, cust_state); // obtain close token for closing out channel - let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_state); + let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, cust_balance, merch_balance, &merch_state); let close_token= match option { Ok(n) => n.unwrap(), Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e) @@ -609,7 +613,8 @@ mod tests { let (com, com_proof) = bidirectional::establish_customer_generate_proof(rng, &mut channel_token, &mut cust_state); // obtain close token for closing out channel - let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, &merch_state); + let option = bidirectional::establish_merchant_issue_close_token(rng, &channel_state, &com, &com_proof, + b0_customer, b0_merchant, &merch_state); let close_token= match option { Ok(n) => n.unwrap(), Err(e) => panic!("Failed - bidirectional::establish_merchant_issue_close_token(): {}", e) @@ -661,7 +666,7 @@ mod tests { let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel - execute_establish_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state); + execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); assert!(channel_state.channel_established); @@ -703,7 +708,7 @@ mod tests { let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel - execute_establish_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state); + execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); assert!(channel_state.channel_established); { @@ -733,7 +738,7 @@ mod tests { let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel - execute_establish_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state); + execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); assert!(channel_state.channel_established); @@ -780,7 +785,7 @@ mod tests { let (mut channel_token, mut merch_state, mut cust_state) = setup_new_channel_helper( &mut channel_state, b0_customer, b0_merchant); // run establish protocol for customer and merchant channel - execute_establish_protocol_helper(&mut channel_state, &mut channel_token, &mut merch_state, &mut cust_state); + execute_establish_protocol_helper(&mut channel_state, &mut channel_token, b0_customer, b0_merchant, &mut merch_state, &mut cust_state); assert!(channel_state.channel_established); diff --git a/src/nizk.rs b/src/nizk.rs index 645b3ca..4488de9 100644 --- a/src/nizk.rs +++ b/src/nizk.rs @@ -264,7 +264,7 @@ impl CommitmentProof { /// /// Verify PoK for the opening of a commitment /// -pub fn verify_opening(com_params: &CSMultiParams, com: &E::G1, proof: &CommitmentProof) -> bool { +pub fn verify_opening(com_params: &CSMultiParams, com: &E::G1, proof: &CommitmentProof, init_cust: i32, init_merch: i32) -> bool { let mut comc = com.clone(); let T = proof.T.clone(); @@ -299,13 +299,15 @@ pub fn verify_opening(com_params: &CSMultiParams, com: &E::G1, pro let mut s3 = proof.reveal[3].clone(); s3.mul_assign(&challenge); s3.add_assign(&proof.t[3]); - let bc_equal = (s3 == proof.z[3]); + let init_c = util::convert_int_to_fr::(init_cust); + let bc_equal = (s3 == proof.z[3]) && (proof.reveal[3] == init_c); // merch init balances: index = 4 let mut s4 = proof.reveal[4].clone(); s4.mul_assign(&challenge); s4.add_assign(&proof.t[4]); - let bm_equal = (s4 == proof.z[4]); + let init_m = util::convert_int_to_fr::(init_merch); + let bm_equal = (s4 == proof.z[4]) && (proof.reveal[4] == init_m); return comc == x && pkc_equal && bc_equal && bm_equal; } @@ -476,7 +478,7 @@ mod tests { let com_proof = CommitmentProof::::new(rng, &pubParams.comParams, &com.c, &wallet.as_fr_vec(), &t, &vec![1, 3, 4]); - assert!(verify_opening(&pubParams.comParams, &com.c, &com_proof)); + assert!(verify_opening(&pubParams.comParams, &com.c, &com_proof, bc, bm)); } #[test] @@ -499,8 +501,8 @@ mod tests { let com1_proof = CommitmentProof::::new(rng, &pubParams.comParams, &com1.c, &wallet1.as_fr_vec(), &t, &vec![1, 3, 4]); - assert!(verify_opening(&pubParams.comParams, &com1.c, &com1_proof)); - assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof)); + assert!(verify_opening(&pubParams.comParams, &com1.c, &com1_proof, bc, bm)); + assert!(!verify_opening(&pubParams.comParams, &com2.c, &com1_proof, bc2, bm)); }