From 0b58e0ae24829affe90fa691f09f4235ec076bfb Mon Sep 17 00:00:00 2001 From: aniampio Date: Wed, 20 Jul 2022 12:19:19 +0100 Subject: [PATCH] Small updates and code cleaning --- Cargo.lock | 6 +- common/nym_offline_compact_ecash/Cargo.toml | 7 +- .../src/scheme/identify.rs | 55 +++++++----- .../src/scheme/keygen.rs | 2 +- common/nym_offline_compact_ecash/src/utils.rs | 12 +-- .../benches/benchmarks.rs | 7 +- .../src/scheme/identification.rs | 85 +++++++++---------- 7 files changed, 92 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d8bb1d707..3cf9af3333 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3136,12 +3136,12 @@ dependencies = [ name = "nym_compact_ecash" version = "0.1.0" dependencies = [ - "bls12_381 0.5.0", + "bls12_381 0.6.0", "bs58", "criterion", "digest 0.9.0", - "ff 0.10.1", - "group 0.10.0", + "ff 0.11.0", + "group 0.11.0", "itertools", "rand 0.8.5", "sha2", diff --git a/common/nym_offline_compact_ecash/Cargo.toml b/common/nym_offline_compact_ecash/Cargo.toml index 0d73627ca0..6b5b9944c6 100644 --- a/common/nym_offline_compact_ecash/Cargo.toml +++ b/common/nym_offline_compact_ecash/Cargo.toml @@ -7,7 +7,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] } +#bls12_381 = { version = "0.5", default-features = false, features = ["pairings", "alloc", "experimental"] } +bls12_381 = { path = "/Users/ania/Documents/Git/andrew_bls12_381", default-features = false, features = ["alloc", "pairings", "experimental", "zeroize"] } itertools = "0.10" digest = "0.9" rand = "0.8" @@ -19,11 +20,11 @@ bs58 = "0.4.0" criterion = { version = "0.3", features = ["html_reports"] } [dependencies.ff] -version = "0.10" +version = "0.11" default-features = false [dependencies.group] -version = "0.10" +version = "0.11" default-features = false [[bench]] diff --git a/common/nym_offline_compact_ecash/src/scheme/identify.rs b/common/nym_offline_compact_ecash/src/scheme/identify.rs index 9f01a7b2be..8d9cd9280e 100644 --- a/common/nym_offline_compact_ecash/src/scheme/identify.rs +++ b/common/nym_offline_compact_ecash/src/scheme/identify.rs @@ -1,3 +1,8 @@ +use std::collections::HashSet; + +use bls12_381::G1Projective; +use group::Curve; + use crate::{PayInfo, VerificationKeyAuth}; use crate::error::{CompactEcashError, Result}; use crate::scheme::keygen::PublicKeyUser; @@ -11,6 +16,7 @@ pub enum IdentifyResult { DoubleSpendingPublicKeys(PublicKeyUser), } + pub fn identify(params: &Parameters, public_keys_u: &[PublicKeyUser], verification_key: &VerificationKeyAuth, payment1: Payment, payment2: Payment, pay_info1: PayInfo, pay_info2: PayInfo) -> Result { // verify first the validity of both payments assert!(payment1.spend_verify(¶ms, &verification_key, &pay_info1).unwrap()); @@ -45,6 +51,9 @@ pub fn identify(params: &Parameters, public_keys_u: &[PublicKeyUser], verificati #[cfg(test)] mod tests { + use std::collections::HashSet; + + use group::Curve; use itertools::izip; use crate::{aggregate_verification_keys, aggregate_wallets, generate_keypair_user, issue_verify, issue_wallet, PartialWallet, PayInfo, ttp_keygen, VerificationKeyAuth, withdrawal_request}; @@ -210,6 +219,17 @@ mod tests { let grp = params.grp(); let user_keypair = generate_keypair_user(&grp); + // GENERATE KEYS FOR OTHER USERS + let mut public_keys: Vec = Default::default(); + for i in 0..50 { + let sk = grp.random_scalar(); + let sk_user = SecretKeyUser { sk }; + let pk_user = sk_user.public_key(&grp); + public_keys.push(pk_user.clone()); + } + public_keys.push(user_keypair.public_key().clone()); + + let (req, req_info) = withdrawal_request(grp, &user_keypair.secret_key()).unwrap(); let authorities_keypairs = ttp_keygen(&grp, 2, 3).unwrap(); @@ -251,7 +271,7 @@ mod tests { let pay_info1 = PayInfo { info: [6u8; 32] }; let spend_vv = 1; - let (payment1, upd_wallet) = aggr_wallet.spend( + let (payment1, _) = aggr_wallet.spend( ¶ms, &verification_key, &user_keypair.secret_key(), @@ -269,7 +289,6 @@ mod tests { aggr_wallet.l.set(current_l - 1); let pay_info2 = PayInfo { info: [7u8; 32] }; - let spend_vv = 1; let (payment2, _) = aggr_wallet.spend( ¶ms, @@ -284,17 +303,6 @@ mod tests { .spend_verify(¶ms, &verification_key, &pay_info2) .unwrap()); - // GENERATE KEYS FOR OTHER USERS - let mut public_keys: Vec = Default::default(); - for i in 0..50 { - let sk = grp.random_scalar(); - let sk_user = SecretKeyUser { sk }; - let pk_user = sk_user.public_key(&grp); - public_keys.push(pk_user); - } - public_keys.push(user_keypair.public_key()); - - let identify_result = identify(¶ms, &public_keys, &verification_key, payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap(); assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key())); } @@ -306,6 +314,16 @@ mod tests { let grp = params.grp(); let user_keypair = generate_keypair_user(&grp); + // GENERATE KEYS FOR OTHER USERS + let mut public_keys: Vec = Default::default(); + for i in 0..50 { + let sk = grp.random_scalar(); + let sk_user = SecretKeyUser { sk }; + let pk_user = sk_user.public_key(&grp); + public_keys.push(pk_user.clone()); + } + public_keys.push(user_keypair.public_key().clone()); + let (req, req_info) = withdrawal_request(grp, &user_keypair.secret_key()).unwrap(); let authorities_keypairs = ttp_keygen(&grp, 2, 3).unwrap(); @@ -347,7 +365,7 @@ mod tests { let pay_info1 = PayInfo { info: [6u8; 32] }; let spend_vv = 10; - let (payment1, upd_wallet) = aggr_wallet.spend( + let (payment1, _) = aggr_wallet.spend( ¶ms, &verification_key, &user_keypair.secret_key(), @@ -374,15 +392,6 @@ mod tests { spend_vv, ).unwrap(); - // GENERATE KEYS FOR OTHER USERS - let mut public_keys: Vec = Default::default(); - for i in 0..50 { - let sk = grp.random_scalar(); - let sk_user = SecretKeyUser { sk }; - let pk_user = sk_user.public_key(&grp); - public_keys.push(pk_user); - } - public_keys.push(user_keypair.public_key()); let identify_result = identify(¶ms, &public_keys, &verification_key, payment1, payment2, pay_info1.clone(), pay_info2.clone()).unwrap(); assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key())); diff --git a/common/nym_offline_compact_ecash/src/scheme/keygen.rs b/common/nym_offline_compact_ecash/src/scheme/keygen.rs index 9e58ccb358..92f47557f0 100644 --- a/common/nym_offline_compact_ecash/src/scheme/keygen.rs +++ b/common/nym_offline_compact_ecash/src/scheme/keygen.rs @@ -332,7 +332,7 @@ impl SecretKeyUser { } } -#[derive(Debug, Eq, PartialEq, Clone)] +#[derive(Debug, Eq, PartialEq, Clone, Hash)] pub struct PublicKeyUser { pub(crate) pk: G1Projective, } diff --git a/common/nym_offline_compact_ecash/src/utils.rs b/common/nym_offline_compact_ecash/src/utils.rs index 42c2303aa7..c8bfa95eff 100644 --- a/common/nym_offline_compact_ecash/src/utils.rs +++ b/common/nym_offline_compact_ecash/src/utils.rs @@ -6,10 +6,10 @@ use core::ops::Mul; use std::convert::{TryFrom, TryInto}; use std::ops::Neg; -use bls12_381::hash_to_curve::{ExpandMsgXmd, HashToCurve, HashToField}; use bls12_381::{ - multi_miller_loop, G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, Scalar, + G1Affine, G1Projective, G2Affine, G2Prepared, G2Projective, multi_miller_loop, Scalar, }; +use bls12_381::hash_to_curve::{ExpandMsgXmd, HashToCurve, HashToField}; use ff::Field; use group::{Curve, Group}; @@ -36,7 +36,7 @@ impl Polynomial { Scalar::zero() // if x is zero then we can ignore most of the expensive computation and // just return the last term of the polynomial - } else if x.is_zero() { + } else if x.is_zero().unwrap_u8() == 1 { // we checked that coefficients are not empty so unwrap here is fine *self.coefficients.first().unwrap() } else { @@ -85,9 +85,9 @@ pub(crate) fn perform_lagrangian_interpolation_at_origin( points: &[SignerIndex], values: &[T], ) -> Result -where - T: Sum, - for<'a> &'a T: Mul, + where + T: Sum, + for<'a> &'a T: Mul, { if points.is_empty() || values.is_empty() { return Err(CompactEcashError::Interpolation( diff --git a/common/nym_offline_divisible_ecash/benches/benchmarks.rs b/common/nym_offline_divisible_ecash/benches/benchmarks.rs index 11e6433e34..18960cd434 100644 --- a/common/nym_offline_divisible_ecash/benches/benchmarks.rs +++ b/common/nym_offline_divisible_ecash/benches/benchmarks.rs @@ -1,3 +1,4 @@ +use std::collections::HashSet; use std::ops::Neg; use std::time::Duration; @@ -134,14 +135,14 @@ fn bench_divisible_ecash(c: &mut Criterion) { let pk_user = SecretKeyUser::public_key(&sk_user, &grp); // GENERATE KEYS FOR OTHER USERS - let mut pk_all_users: Vec = Default::default(); + let mut pk_all_users = HashSet::new(); for i in 0..50 { let sk = grp.random_scalar(); let sk_user = SecretKeyUser { sk }; let pk_user = sk_user.public_key(&grp); - pk_all_users.push(pk_user); + pk_all_users.insert(pk_user); } - pk_all_users.push(pk_user.clone()); + pk_all_users.insert(pk_user.clone()); // WITHDRAWAL REQUEST let (withdrawal_req, req_info) = withdrawal_request(¶ms, &sk_user).unwrap(); diff --git a/common/nym_offline_divisible_ecash/src/scheme/identification.rs b/common/nym_offline_divisible_ecash/src/scheme/identification.rs index d74ab23aa6..237971a095 100644 --- a/common/nym_offline_divisible_ecash/src/scheme/identification.rs +++ b/common/nym_offline_divisible_ecash/src/scheme/identification.rs @@ -22,7 +22,7 @@ pub enum IdentifyResult { pub fn identify( params: &Parameters, verification_key: &VerificationKeyAuth, - public_keys_u: &[PublicKeyUser], + public_keys_u: &HashSet, payment1: Payment, payment2: Payment, pay_info1: PayInfo, @@ -32,56 +32,53 @@ pub fn identify( assert!(payment2.spend_verify(¶ms, &verification_key, &pay_info2).unwrap()); let params_a = params.get_params_a(); + // compute the serial numbers for k1 in [0, V1-1] let mut serial_numbers = HashMap::new(); - for k1 in 0..payment1.vv { - let sn = pairing(&payment1.phi.1.to_affine(), ¶ms_a.get_ith_delta(k1 as usize).to_affine()) - + pairing(&payment1.phi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment1.vv as usize, k1 as usize).to_affine()); - serial_numbers.insert(sn, k1); + for k in 0..payment1.vv { + let sn = pairing(&payment1.phi.1.to_affine(), ¶ms_a.get_ith_delta(k as usize).to_affine()) + + pairing(&payment1.phi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment1.vv as usize, k as usize).to_affine()); + serial_numbers.insert(sn, k); } // compute the serial numbers fo k2 in [0, V2-1] + let mut k1 = 0; + let mut k2 = 0; let mut duplicate_serial_numbers: Vec<(Gt, u64, u64)> = Default::default(); - for k2 in 0..payment2.vv { - let sn = pairing(&payment2.phi.1.to_affine(), ¶ms_a.get_ith_delta(k2 as usize).to_affine()) - + pairing(&payment2.phi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment2.vv as usize, k2 as usize).to_affine()); + for j in 0..payment2.vv { + let sn = pairing(&payment2.phi.1.to_affine(), ¶ms_a.get_ith_delta(j as usize).to_affine()) + + pairing(&payment2.phi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment2.vv as usize, j as usize).to_affine()); if !serial_numbers.contains_key(&sn) { - serial_numbers.insert(sn, k2); + serial_numbers.insert(sn, j); } else { - let k1 = *serial_numbers.get(&sn).unwrap() as u64; - duplicate_serial_numbers.push((sn, k1, k2)); + k1 = *serial_numbers.get(&sn).unwrap() as u64; + k2 = j.clone(); + break; } + return Ok(IdentifyResult::NotADuplicatePayment); } - if duplicate_serial_numbers.is_empty() { - Ok(IdentifyResult::NotADuplicatePayment) + if pay_info1 == pay_info2 { + Ok(IdentifyResult::DuplicatePayInfo(pay_info1)) } else { - if pay_info1.info == pay_info2.info { - Ok(IdentifyResult::DuplicatePayInfo(pay_info1)) - } else { - for elem in duplicate_serial_numbers.iter() { - let k1 = elem.1; - let k2 = elem.2; - let delta_k1 = params_a.get_ith_delta(k1 as usize); - let delta_k2 = params_a.get_ith_delta(k2 as usize); - let tt1 = pairing(&payment1.varphi.1.to_affine(), &delta_k1.to_affine()) - + pairing(&payment1.varphi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment1.vv as usize, k1 as usize).to_affine()); - let tt2 = pairing(&payment2.varphi.1.to_affine(), &delta_k2.to_affine()) - + pairing(&payment2.varphi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment2.vv as usize, k2 as usize).to_affine()); + let delta_k1 = params_a.get_ith_delta(k1 as usize); + let delta_k2 = params_a.get_ith_delta(k2 as usize); + let tt1 = pairing(&payment1.varphi.1.to_affine(), &delta_k1.to_affine()) + + pairing(&payment1.varphi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment1.vv as usize, k1 as usize).to_affine()); + let tt2 = pairing(&payment2.varphi.1.to_affine(), &delta_k2.to_affine()) + + pairing(&payment2.varphi.0.to_affine(), ¶ms_a.get_etas_ith_jth_elem(payment2.vv as usize, k2 as usize).to_affine()); - for pk_u in public_keys_u.iter() { - let pg_pku_deltas = pairing(&pk_u.pk.to_affine(), &(delta_k1 * payment1.rr + delta_k2 * payment2.rr.neg()).to_affine()); - if tt1 - tt2 == pg_pku_deltas { - return Ok(IdentifyResult::DoubleSpendingPublicKeys(pk_u.clone())); - } - } + for pk_u in public_keys_u.iter() { + let pg_pku_deltas = pairing(&pk_u.pk.to_affine(), &(delta_k1 * payment1.rr + delta_k2 * payment2.rr.neg()).to_affine()); + if tt1 - tt2 == pg_pku_deltas { + return Ok(IdentifyResult::DoubleSpendingPublicKeys(pk_u.clone())); } - return Err(DivisibleEcashError::Identify( - "A duplicate serial number was detected, the payinfo1 and payinfo2 are different, but we failed to identify the double-spending public key".to_string(), - )); } + return Err(DivisibleEcashError::Identify( + "A duplicate serial number was detected, the payinfo1 and payinfo2 are different, but we failed to identify the double-spending public key".to_string(), + )); } } @@ -160,7 +157,8 @@ mod tests { let pay_info2 = pay_info1.clone(); - let identify_result = identify(¶ms, &verification_key, &[pk_user1, pk_user2], payment1, payment2, pay_info1, pay_info2).unwrap(); + let public_keys = HashSet::from([pk_user1, pk_user2]); + let identify_result = identify(¶ms, &verification_key, &public_keys, payment1, payment2, pay_info1, pay_info2).unwrap(); assert_eq!(identify_result, IdentifyResult::DuplicatePayInfo(pay_info1)); } @@ -189,14 +187,14 @@ mod tests { // GENERATE KEYS FOR OTHER USERS - let mut pk_all_users: Vec = Default::default(); + let mut pk_all_users = HashSet::new(); for i in 0..50 { let sk = grp.random_scalar(); let sk_user = SecretKeyUser { sk }; let pk_user = sk_user.public_key(&grp); - pk_all_users.push(pk_user); + pk_all_users.insert(pk_user); } - pk_all_users.push(pk_user1.clone()); + pk_all_users.insert(pk_user1.clone()); // WITHDRAWAL REQUEST FOR USER1 let (withdrawal_req1, req_info1) = withdrawal_request(¶ms, &sk_user1).unwrap(); @@ -257,14 +255,14 @@ mod tests { let pk_user1 = SecretKeyUser::public_key(&sk_user1, &grp); // GENERATE KEYS FOR OTHER USERS - let mut pk_all_users: Vec = Default::default(); + let mut public_keys = HashSet::new(); for i in 0..50 { let sk = grp.random_scalar(); let sk_user = SecretKeyUser { sk }; let pk_user = sk_user.public_key(&grp); - pk_all_users.push(pk_user); + public_keys.insert(pk_user); } - pk_all_users.push(pk_user1.clone()); + public_keys.insert(pk_user1.clone()); // WITHDRAWAL REQUEST FOR USER1 let (withdrawal_req1, req_info1) = withdrawal_request(¶ms, &sk_user1).unwrap(); @@ -296,7 +294,7 @@ mod tests { let (payment2, wallet1) = wallet1.spend(¶ms, &verification_key, &sk_user1, &pay_info2, 10, false).unwrap(); - let identify_result = identify(¶ms, &verification_key, &pk_all_users, payment1, payment2, pay_info1, pay_info2).unwrap(); + let identify_result = identify(¶ms, &verification_key, &public_keys, payment1, payment2, pay_info1, pay_info2).unwrap(); assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(pk_user1)); } @@ -380,7 +378,8 @@ mod tests { // SPEND VERIFICATION for USER2 assert!(payment2.spend_verify(¶ms, &verification_key, &pay_info2).unwrap()); - let identify_result = identify(¶ms, &verification_key, &[pk_user1, pk_user2], payment1, payment2, pay_info1, pay_info2).unwrap(); + let public_keys = HashSet::from([pk_user1, pk_user2]); + let identify_result = identify(¶ms, &verification_key, &public_keys, payment1, payment2, pay_info1, pay_info2).unwrap(); assert_eq!(identify_result, IdentifyResult::NotADuplicatePayment); } } \ No newline at end of file