Speed up the verification function and add benchmarks

This commit is contained in:
aniampio
2023-11-22 14:38:43 +00:00
parent 76055c295b
commit e5d783c6c4
3 changed files with 165 additions and 115 deletions
@@ -18,6 +18,7 @@ use nym_compact_ecash::{
};
use nym_compact_ecash::identify::{identify, IdentifyResult};
use nym_compact_ecash::setup::setup;
use nym_compact_ecash::scheme::expiration_date_signatures::{sign_expiration_date, verify_valid_dates_signatures};
#[allow(unused)]
fn double_pairing(g11: &G1Affine, g21: &G2Affine, g12: &G1Affine, g22: &G2Affine) {
@@ -181,31 +182,31 @@ fn bench_compact_ecash(c: &mut Criterion) {
let (req, req_info) = withdrawal_request(grp, &user_keypair.secret_key()).unwrap();
// CLIENT BENCHMARK: prepare a single withdrawal request
// group.bench_function(
// &format!(
// "[Client] withdrawal_request_{}_authorities_{}_L_{}_threshold",
// case.num_authorities, case.L, case.threshold_p,
// ),
// |b| b.iter(|| withdrawal_request(grp, &user_keypair.secret_key()).unwrap()),
// );
group.bench_function(
&format!(
"[Client] withdrawal_request_{}_authorities_{}_L_{}_threshold",
case.num_authorities, case.L, case.threshold_p,
),
|b| b.iter(|| withdrawal_request(grp, &user_keypair.secret_key()).unwrap()),
);
// ISSUING AUTHRORITY BENCHMARK: Benchmark the issue_wallet function
// called by an authority to issue a blind signature on a partial wallet
let mut rng = rand::thread_rng();
let keypair = authorities_keypairs.choose(&mut rng).unwrap();
// group.bench_function(
// &format!("[Issuing Authority] issue_partial_wallet_with_L_{}", case.L, ),
// |b| {
// b.iter(|| {
// issue_wallet(
// &grp,
// keypair.secret_key(),
// user_keypair.public_key(),
// &req,
// ).unwrap()
// })
// },
// );
group.bench_function(
&format!("[Issuing Authority] issue_partial_wallet_with_L_{}", case.L, ),
|b| {
b.iter(|| {
issue_wallet(
&grp,
keypair.secret_key(),
user_keypair.public_key(),
&req,
).unwrap()
})
},
);
let mut wallet_blinded_signatures = Vec::new();
for auth_keypair in authorities_keypairs {
@@ -221,10 +222,10 @@ fn bench_compact_ecash(c: &mut Criterion) {
// CLIENT BENCHMARK: verify the issued partial wallet
let w = wallet_blinded_signatures.get(0).clone().unwrap();
let vk = verification_keys_auth.get(0).clone().unwrap();
// group.bench_function(
// &format!("[Client] issue_verify_a_partial_wallet_with_L_{}", case.L, ),
// |b| b.iter(|| issue_verify(&grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap()),
// );
group.bench_function(
&format!("[Client] issue_verify_a_partial_wallet_with_L_{}", case.L, ),
|b| b.iter(|| issue_verify(&grp, vk, &user_keypair.secret_key(), w, &req_info).unwrap()),
);
let unblinded_wallet_shares: Vec<PartialWallet> = izip!(
wallet_blinded_signatures.iter(),
@@ -234,24 +235,24 @@ fn bench_compact_ecash(c: &mut Criterion) {
.collect();
// CLIENT BENCHMARK: aggregating all partial wallets
// group.bench_function(
// &format!(
// "[Client] aggregate_wallets_with_L_{}_threshold_{}",
// case.L, case.threshold_p,
// ),
// |b| {
// b.iter(|| {
// aggregate_wallets(
// &grp,
// &verification_key,
// &user_keypair.secret_key(),
// &unblinded_wallet_shares,
// &req_info,
// )
// .unwrap()
// })
// },
// );
group.bench_function(
&format!(
"[Client] aggregate_wallets_with_L_{}_threshold_{}",
case.L, case.threshold_p,
),
|b| {
b.iter(|| {
aggregate_wallets(
&grp,
&verification_key,
&user_keypair.secret_key(),
&unblinded_wallet_shares,
&req_info,
)
.unwrap()
})
},
);
// Aggregate partial wallets
let aggr_wallet = aggregate_wallets(
@@ -264,28 +265,28 @@ fn bench_compact_ecash(c: &mut Criterion) {
.unwrap();
// SPENDING PHASE
let pay_info = PayInfo { info: [6u8; 32] };
let pay_info = PayInfo { payinfo: [6u8; 88] };
// CLIENT BENCHMARK: spend a single coin from the wallet
// group.bench_function(
// &format!(
// "[Client] spend_a_single_coin_L_{}_threshold_{}",
// case.L, case.threshold_p,
// ),
// |b| {
// b.iter(|| {
// aggr_wallet
// .spend(
// &params,
// &verification_key,
// &user_keypair.secret_key(),
// &pay_info,
// true,
// case.spend_vv,
// )
// .unwrap()
// })
// },
// );
group.bench_function(
&format!(
"[Client] spend_a_single_coin_L_{}_threshold_{}",
case.L, case.threshold_p,
),
|b| {
b.iter(|| {
aggr_wallet
.spend(
&params,
&verification_key,
&user_keypair.secret_key(),
&pay_info,
true,
case.spend_vv,
)
.unwrap()
})
},
);
let (payment, upd_wallet) = aggr_wallet
.spend(
@@ -299,19 +300,19 @@ fn bench_compact_ecash(c: &mut Criterion) {
.unwrap();
// MERCHANT BENCHMARK: verify whether the submitted payment is legit
// group.bench_function(
// &format!(
// "[Merchant] spend_verify_of_a_single_payment_L_{}_threshold_{}",
// case.L, case.threshold_p,
// ),
// |b| {
// b.iter(|| {
// payment
// .spend_verify(&params, &verification_key, &pay_info)
// .unwrap()
// })
// },
// );
group.bench_function(
&format!(
"[Merchant] spend_verify_of_a_single_payment_L_{}_threshold_{}",
case.L, case.threshold_p,
),
|b| {
b.iter(|| {
payment
.spend_verify(&params, &verification_key, &pay_info)
.unwrap()
})
},
);
// BENCHMARK IDENTIFICATION
// Let's generate a double spending payment
@@ -320,7 +321,7 @@ fn bench_compact_ecash(c: &mut Criterion) {
let current_l = aggr_wallet.l.get();
aggr_wallet.l.set(current_l - case.spend_vv);
let pay_info2 = PayInfo { info: [7u8; 32] };
let pay_info2 = PayInfo { payinfo: [7u8; 88] };
let (payment2, _) = aggr_wallet.spend(
&params,
&verification_key,
@@ -356,5 +357,45 @@ fn bench_compact_ecash(c: &mut Criterion) {
assert_eq!(identify_result, IdentifyResult::DoubleSpendingPublicKeys(user_keypair.public_key()));
}
criterion_group!(benches, bench_compact_ecash);
fn bench_partial_sign_expiration_date(c: &mut Criterion){
let mut group = c.benchmark_group("benchmark-expiration-date");
let L = 32;
let params = setup(L);
let expiration_date = 1703183958;
let authorities_keys = ttp_keygen(&params.grp(), 2, 3).unwrap();
let sk_i_auth = authorities_keys[0].secret_key();
let vk_i_auth = authorities_keys[0].verification_key();
let partial_exp_sig = sign_expiration_date(&params, &sk_i_auth, expiration_date);
// ISSUING AUTHORITY BENCHMARK: issue a set of (partial) signatures for a given expiration date
group.bench_function(
&format!(
"[IssuingAuthority] sign_expiration_date",
),
|b| {
b.iter(|| {
sign_expiration_date(&params, &sk_i_auth, expiration_date)
})
},
);
// CLIENT: verify the correctness of the set of (partial) signatures for a given expiration date
assert!(verify_valid_dates_signatures(&params, &vk_i_auth, &partial_exp_sig, expiration_date).is_ok());
group.bench_function(
&format!(
"[Client] verify_valid_dates_signatures",
),
|b| {
b.iter(|| {
verify_valid_dates_signatures(&params, &vk_i_auth, &partial_exp_sig, expiration_date)
})
},
);
}
criterion_group!(benches, bench_partial_sign_expiration_date);
criterion_main!(benches);
+1 -1
View File
@@ -21,7 +21,7 @@ use crate::traits::Bytable;
mod error;
mod proofs;
mod scheme;
pub mod scheme;
#[cfg(test)]
mod tests;
mod traits;
@@ -92,36 +92,39 @@ pub fn verify_valid_dates_signatures(
signatures: &[ExpirationDateSignature],
expiration_date: u64,
) -> Result<()>{
for (l , sig) in signatures.iter().enumerate() {
let m0: Scalar = Scalar::from(expiration_date);
let m1: Scalar = Scalar::from(expiration_date - constants::VALIDITY_PERIOD + l as u64);
let m2: Scalar = Scalar::from_bytes(&constants::TYPE_EXP).unwrap();
// Compute the hash
let h = hash_g1([m0.to_bytes(), m1.to_bytes(), m2.to_bytes()].concat());
// Verify the signature correctness
if sig.h != h {
return Err(CompactEcashError::ExpirationDate(
"Failed to verify the commitment hash".to_string(),
));
}
let partially_signed_attributes = [m0, m1, m2]
.iter()
.zip(vkey.beta_g2.iter())
.map(|(m, beta_i)| beta_i * Scalar::from(*m))
.sum::<G2Projective>();
signatures
.par_iter()
.enumerate()
.try_for_each(|(l, sig)| {
let m0: Scalar = Scalar::from(expiration_date);
let m1: Scalar = Scalar::from(expiration_date - constants::VALIDITY_PERIOD + l as u64);
let m2: Scalar = Scalar::from_bytes(&constants::TYPE_EXP).unwrap();
// Compute the hash
let h = hash_g1([m0.to_bytes(), m1.to_bytes(), m2.to_bytes()].concat());
// Verify the signature correctness
if sig.h != h {
return Err(CompactEcashError::ExpirationDate(
"Failed to verify the commitment hash".to_string(),
));
}
let partially_signed_attributes = [m0, m1, m2]
.iter()
.zip(vkey.beta_g2.iter())
.map(|(m, beta_i)| beta_i * Scalar::from(*m))
.sum::<G2Projective>();
if !check_bilinear_pairing(
&sig.h.to_affine(),
&G2Prepared::from((vkey.alpha + partially_signed_attributes).to_affine()),
&sig.s.to_affine(),
params.grp().prepared_miller_g2(),
) {
return Err(CompactEcashError::ExpirationDate(
"Verification of the date signature failed".to_string(),
));
}
}
Ok(())
if !check_bilinear_pairing(
&sig.h.to_affine(),
&G2Prepared::from((vkey.alpha + partially_signed_attributes).to_affine()),
&sig.s.to_affine(),
params.grp().prepared_miller_g2(),
) {
return Err(CompactEcashError::ExpirationDate(
"Verification of the date signature failed".to_string(),
));
}
Ok(())
})
}
/// Aggregates partial expiration date signatures into a list of aggregated expiration date signatures.
@@ -131,9 +134,7 @@ pub fn verify_valid_dates_signatures(
/// * `params` - The cryptographic parameters used in the signing process.
/// * `vk_auth` - The global verification key.
/// * `expiration_date` - The expiration date for which the signatures are being aggregated (as unix timestamp).
/// * `indices` - A list of unique indices corresponding to the signing authorities.
/// * `vkeys` - A list of verification keys associated with the signing authorities.
/// * `signatures` - A list of partial expiration date signatures to be aggregated.
/// * `signatures` - A list of tuples containing unique indices, verification keys, and partial expiration date signatures corresponding to the signing authorities.
///
/// # Returns
///
@@ -142,16 +143,23 @@ pub fn verify_valid_dates_signatures(
///
/// # Errors
///
/// This function returns an error if there is a mismatch in the lengths of `vkeys` and `signatures`,
/// or if there are not enough unique indices. It also returns an error the verification of
/// the partial or aggregated signatures fails.
/// This function returns an error if there is a mismatch in the lengths of `signatures`. This occurs
/// when the number of tuples in `signatures` is not equal to the expected number of signing authorities.
/// Each tuple should contain a unique index, a verification key, and a list of partial signatures.
///
/// It also returns an error if there are not enough unique indices. This happens when the number
/// of unique indices in the tuples is less than the total number of signing authorities.
///
/// Additionally, an error is returned if the verification of the partial or aggregated signatures fails.
/// This can occur if the cryptographic verification process fails for any of the provided signatures.
///
pub fn aggregate_expiration_signatures(
params: &Parameters,
vk_auth: &VerificationKeyAuth,
expiration_date: u64,
signatures: &[(u64, VerificationKeyAuth, Vec<PartialExpirationDateSignature>)],
) -> Result<Vec<ExpirationDateSignature>>{
// Check if we have enough unique partial signatures to meet the required threshold
// Check if all indices are unique
if signatures.iter().map(|(index, _, _)| index).unique().count() != signatures.len() {
return Err(CompactEcashError::ExpirationDate(
"Not enough unique indices shares".to_string(),
@@ -180,6 +188,7 @@ pub fn aggregate_expiration_signatures(
verify_valid_dates_signatures(params, vkey, partial_signatures, expiration_date)
})?;
// Collect the partial signatures for the same valid date
let collected_at_l: Vec<_> = signatures
.iter()